vue2-client 1.8.310 → 1.8.312

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 (222) hide show
  1. package/.env +19 -19
  2. package/.eslintrc.js +90 -90
  3. package/CHANGELOG.md +824 -824
  4. package/Components.md +60 -60
  5. package/babel.config.js +21 -21
  6. package/docs/LowCode/lowcode.md +155 -155
  7. package/docs/LowCode/lowcodeForDeveloper.md +230 -230
  8. package/docs/index.md +30 -30
  9. package/index.js +31 -31
  10. package/jest-transform-stub.js +8 -8
  11. package/jest.config.js +21 -21
  12. package/jest.setup.js +7 -7
  13. package/package.json +97 -97
  14. package/public/index.html +27 -27
  15. package/src/App.vue +188 -188
  16. package/src/ReportView.js +19 -19
  17. package/src/assets/img/querySlotDemo.svg +15 -15
  18. package/src/assets/svg/badtwo.svg +1 -1
  19. package/src/assets/svg/goodtwo.svg +1 -1
  20. package/src/base-client/components/common/AMisRender/index.js +3 -3
  21. package/src/base-client/components/common/AMisRender/index.vue +263 -263
  22. package/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox.vue +438 -416
  23. package/src/base-client/components/common/AddressSearchCombobox/demo.vue +36 -36
  24. package/src/base-client/components/common/AddressSearchCombobox/ic_map.svg +6 -6
  25. package/src/base-client/components/common/AmapMarker/AmapPointRendering.vue +120 -120
  26. package/src/base-client/components/common/CitySelect/CitySelect.vue +342 -342
  27. package/src/base-client/components/common/CitySelect/index.js +3 -3
  28. package/src/base-client/components/common/CitySelect/index.md +109 -109
  29. package/src/base-client/components/common/CreateQuery/CreateQuery.vue +669 -669
  30. package/src/base-client/components/common/CreateQuery/CreateQueryItem.vue +1014 -1014
  31. package/src/base-client/components/common/CreateQuery/index.js +3 -3
  32. package/src/base-client/components/common/CreateQuery/index.md +42 -42
  33. package/src/base-client/components/common/CreateSimpleFormQuery/CreateSimpleFormQuery.vue +452 -452
  34. package/src/base-client/components/common/CreateSimpleFormQuery/CreateSimpleFormQueryItem.vue +511 -511
  35. package/src/base-client/components/common/CreateSimpleFormQuery/index.js +3 -3
  36. package/src/base-client/components/common/CreateSimpleFormQuery/index.md +42 -42
  37. package/src/base-client/components/common/FormGroupEdit/FormGroupEdit.vue +149 -149
  38. package/src/base-client/components/common/FormGroupEdit/index.js +3 -3
  39. package/src/base-client/components/common/FormGroupEdit/index.md +43 -43
  40. package/src/base-client/components/common/FormGroupQuery/FormGroupQuery.vue +166 -166
  41. package/src/base-client/components/common/FormGroupQuery/index.js +3 -3
  42. package/src/base-client/components/common/FormGroupQuery/index.md +43 -43
  43. package/src/base-client/components/common/JSONToTree/jsontotree.vue +271 -271
  44. package/src/base-client/components/common/LowCodeComponent/LowCodeEditorPanel.vue +413 -350
  45. package/src/base-client/components/common/LowCodeComponent/LowCodePageOrganization.vue +502 -502
  46. package/src/base-client/components/common/LowCodeComponent/LowCodeRender.vue +728 -699
  47. package/src/base-client/components/common/LowCodeComponent/LowCodeRenderEnter.vue +29 -29
  48. package/src/base-client/components/common/LowCodeComponent/LowCodeUIStore.vue +219 -162
  49. package/src/base-client/components/common/PersonSetting/PersonSetting.vue +208 -208
  50. package/src/base-client/components/common/PersonSetting/index.js +3 -3
  51. package/src/base-client/components/common/Tree/Tree.vue +149 -149
  52. package/src/base-client/components/common/Tree/index.js +2 -2
  53. package/src/base-client/components/common/Upload/Upload.vue +239 -239
  54. package/src/base-client/components/common/Upload/index.js +3 -3
  55. package/src/base-client/components/common/XAddForm/XAddForm.vue +105 -105
  56. package/src/base-client/components/common/XAddNativeForm/XAddNativeForm.vue +807 -807
  57. package/src/base-client/components/common/XAddNativeForm/index.md +146 -146
  58. package/src/base-client/components/common/XAddNativeForm/lowcodeEditorRegister.js +16 -16
  59. package/src/base-client/components/common/XAddNativeFormOA/XAddNativeFormOA.vue +303 -303
  60. package/src/base-client/components/common/XAddNativeFormOA/index.js +3 -3
  61. package/src/base-client/components/common/XAddNativeFormOA/index.md +146 -146
  62. package/src/base-client/components/common/XBadge/XBadge.vue +78 -78
  63. package/src/base-client/components/common/XCard/XCard.vue +64 -64
  64. package/src/base-client/components/common/XDataCard/XDataCard.vue +355 -0
  65. package/src/base-client/components/common/XDataCard/index.js +3 -0
  66. package/src/base-client/components/common/XDataCard/index.md +1 -0
  67. package/src/base-client/components/common/XDataDrawer/XDataDrawer.vue +180 -180
  68. package/src/base-client/components/common/XDataDrawer/index.js +3 -3
  69. package/src/base-client/components/common/XDataDrawer/index.md +41 -41
  70. package/src/base-client/components/common/XDescriptions/XDescriptions.vue +188 -187
  71. package/src/base-client/components/common/XDescriptions/XDescriptionsGroup.vue +306 -306
  72. package/src/base-client/components/common/XDescriptions/demo.vue +50 -50
  73. package/src/base-client/components/common/XDescriptions/index.js +3 -3
  74. package/src/base-client/components/common/XDescriptions/index.md +83 -83
  75. package/src/base-client/components/common/XDetailsView/XDetailsView.vue +214 -214
  76. package/src/base-client/components/common/XDetailsView/index.js +3 -3
  77. package/src/base-client/components/common/XForm/XForm.vue +294 -294
  78. package/src/base-client/components/common/XForm/XFormItem.vue +911 -911
  79. package/src/base-client/components/common/XForm/XTreeSelect.vue +207 -207
  80. package/src/base-client/components/common/XForm/index.md +178 -178
  81. package/src/base-client/components/common/XFormCol/XFormCol.vue +36 -36
  82. package/src/base-client/components/common/XFormGroup/XFormGroup.vue +241 -241
  83. package/src/base-client/components/common/XFormGroup/demo.vue +40 -40
  84. package/src/base-client/components/common/XFormGroup/index.js +3 -3
  85. package/src/base-client/components/common/XFormGroup/index.md +38 -38
  86. package/src/base-client/components/common/XFormGroupDetails/XFormGroupDetails.vue +72 -72
  87. package/src/base-client/components/common/XFormGroupDetails/index.js +3 -3
  88. package/src/base-client/components/common/XFormTable/XFormTable.vue +545 -539
  89. package/src/base-client/components/common/XFormTable/demo.vue +72 -72
  90. package/src/base-client/components/common/XFormTable/index.md +98 -98
  91. package/src/base-client/components/common/XFormTable/lowcodeEditorRegister.js +30 -30
  92. package/src/base-client/components/common/XImportExcel/XImportExcel.vue +147 -147
  93. package/src/base-client/components/common/XReport/XReport.vue +858 -858
  94. package/src/base-client/components/common/XReport/XReportDemo.vue +266 -266
  95. package/src/base-client/components/common/XReport/XReportDesign.vue +509 -509
  96. package/src/base-client/components/common/XReport/XReportJsonRender.vue +295 -295
  97. package/src/base-client/components/common/XReport/XReportTrGroup.vue +801 -801
  98. package/src/base-client/components/common/XReport/index.js +3 -3
  99. package/src/base-client/components/common/XReport/index.md +44 -44
  100. package/src/base-client/components/common/XReportSlot/XReportSlot.vue +110 -110
  101. package/src/base-client/components/common/XReportSlot/index.js +3 -3
  102. package/src/base-client/components/common/XSimpleDescriptions/XSimpleDescriptions.vue +137 -0
  103. package/src/base-client/components/common/XSimpleDescriptions/index.js +3 -0
  104. package/src/base-client/components/common/XSimpleDescriptions/index.md +7 -0
  105. package/src/base-client/components/common/XStepView/XStepView.vue +252 -252
  106. package/src/base-client/components/common/XStepView/index.js +3 -3
  107. package/src/base-client/components/common/XStepView/index.md +31 -31
  108. package/src/base-client/components/common/XTable/XTable.vue +715 -676
  109. package/src/base-client/components/common/XTable/index.md +255 -255
  110. package/src/base-client/components/common/XTree/XTree.vue +423 -423
  111. package/src/base-client/components/common/XTree/index.js +3 -3
  112. package/src/base-client/components/common/XTree/index.md +36 -36
  113. package/src/base-client/components/common/XTreeOne/XTreeOne.vue +114 -114
  114. package/src/base-client/components/common/XTreeOne/lowcodeEditorRegister.js +11 -11
  115. package/src/base-client/components/index.js +51 -51
  116. package/src/base-client/components/system/DictionaryDetailsView/DictionaryDetailsView.vue +232 -232
  117. package/src/base-client/components/system/QueryParamsDetailsView/QueryParamsDetailsView.vue +281 -281
  118. package/src/base-client/plugins/AppData.js +121 -121
  119. package/src/base-client/plugins/Config.js +19 -19
  120. package/src/base-client/plugins/GetLoginInfoService.js +183 -183
  121. package/src/base-client/plugins/tabs-page-plugin.js +39 -39
  122. package/src/bootstrap.js +39 -39
  123. package/src/components/CodeMirror/inedx.vue +118 -118
  124. package/src/components/CodeMirror/setting.js +40 -40
  125. package/src/components/FilePreview/FilePreview.vue +166 -166
  126. package/src/components/NumberInfo/NumberInfo.vue +54 -54
  127. package/src/components/STable/index.js +361 -361
  128. package/src/components/checkbox/ColorCheckbox.vue +157 -157
  129. package/src/components/checkbox/ImgCheckbox.vue +163 -163
  130. package/src/components/menu/SideMenu.vue +75 -75
  131. package/src/components/menu/menu.js +273 -273
  132. package/src/components/tool/AStepItem.vue +60 -60
  133. package/src/config/CreateQueryConfig.js +322 -322
  134. package/src/config/default/antd.config.js +89 -89
  135. package/src/config/default/setting.config.js +55 -55
  136. package/src/font-style/font.css +4 -4
  137. package/src/layouts/CommonLayout.vue +56 -56
  138. package/src/layouts/PageLayout.vue +151 -151
  139. package/src/layouts/SinglePageView.vue +138 -138
  140. package/src/layouts/header/AdminHeader.vue +132 -132
  141. package/src/layouts/header/HeaderNotice.vue +177 -177
  142. package/src/layouts/tabs/TabsHead.vue +189 -189
  143. package/src/layouts/tabs/TabsView.vue +387 -387
  144. package/src/lib.js +1 -1
  145. package/src/main.js +26 -26
  146. package/src/mock/extend/index.js +84 -84
  147. package/src/mock/goods/index.js +108 -108
  148. package/src/pages/AMisDemo/AMisDemo.vue +325 -325
  149. package/src/pages/AMisDemo/AMisDemo2.vue +74 -74
  150. package/src/pages/DynamicStatistics/ChartSelector.vue +331 -331
  151. package/src/pages/DynamicStatistics/DataTabs.vue +83 -83
  152. package/src/pages/DynamicStatistics/DynamicTable.vue +128 -128
  153. package/src/pages/DynamicStatistics/EvaluationArea.vue +69 -69
  154. package/src/pages/DynamicStatistics/FavoriteList.vue +51 -51
  155. package/src/pages/DynamicStatistics/QuestionHistoryAndFavorites.vue +591 -591
  156. package/src/pages/DynamicStatistics/SearchBar.vue +192 -192
  157. package/src/pages/DynamicStatistics/index.vue +282 -282
  158. package/src/pages/Example/index.vue +193 -33
  159. package/src/pages/NewDynamicStatistics/ChartSelector.vue +331 -331
  160. package/src/pages/NewDynamicStatistics/DataTabs.vue +122 -122
  161. package/src/pages/NewDynamicStatistics/DynamicTable.vue +128 -128
  162. package/src/pages/NewDynamicStatistics/EvaluationArea.vue +69 -69
  163. package/src/pages/NewDynamicStatistics/FavoriteList.vue +51 -51
  164. package/src/pages/NewDynamicStatistics/QuestionHistoryAndFavorites.vue +289 -289
  165. package/src/pages/NewDynamicStatistics/SearchBar.vue +193 -193
  166. package/src/pages/NewDynamicStatistics/index.vue +258 -258
  167. package/src/pages/ServiceReview/index.vue +284 -284
  168. package/src/pages/XReportView/index.vue +62 -62
  169. package/src/pages/login/Login.vue +378 -378
  170. package/src/pages/login/LoginV3.vue +389 -389
  171. package/src/pages/lowCode/lowCodeEditor.vue +1219 -1030
  172. package/src/pages/lowCode/lowCodeRenderPage.vue +43 -43
  173. package/src/pages/resourceManage/orgListManage.vue +98 -98
  174. package/src/pages/system/dictionary/index.vue +44 -44
  175. package/src/pages/system/monitor/loginInfor/index.vue +37 -37
  176. package/src/pages/system/monitor/operLog/index.vue +37 -37
  177. package/src/pages/system/settings/modifyPassword.vue +117 -117
  178. package/src/pages/system/ticket/index.vue +480 -480
  179. package/src/pages/system/ticket/submitTicketSuccess.vue +484 -484
  180. package/src/router/async/config.async.js +34 -34
  181. package/src/router/async/router.map.js +104 -104
  182. package/src/router/guards.js +223 -223
  183. package/src/router/index.js +27 -27
  184. package/src/router.js +19 -19
  185. package/src/services/api/TicketDetailsViewApi.js +46 -46
  186. package/src/services/api/cas.js +79 -79
  187. package/src/services/api/common.js +307 -307
  188. package/src/services/api/entity.js +18 -18
  189. package/src/services/api/index.js +17 -17
  190. package/src/services/api/restTools.js +46 -46
  191. package/src/services/apiService.js +14 -14
  192. package/src/services/user.js +71 -71
  193. package/src/services/v3Api.js +81 -81
  194. package/src/store/modules/index.js +5 -5
  195. package/src/store/modules/lowCode.js +33 -33
  196. package/src/store/modules/setting.js +119 -119
  197. package/src/theme/default/style.less +58 -58
  198. package/src/theme/global.less +139 -139
  199. package/src/utils/authority-utils.js +85 -85
  200. package/src/utils/errorCode.js +6 -6
  201. package/src/utils/formatter.js +80 -80
  202. package/src/utils/htmlToPDF.js +108 -108
  203. package/src/utils/htmlToPDFApi.js +5 -5
  204. package/src/utils/indexedDB.js +258 -258
  205. package/src/utils/login.js +188 -188
  206. package/src/utils/lowcode/lowcodeComponentMixin.js +120 -120
  207. package/src/utils/lowcode/lowcodeLog.js +29 -29
  208. package/src/utils/lowcode/lowcodeUtils.js +373 -373
  209. package/src/utils/lowcode/registerComponentForEditor.js +11 -11
  210. package/src/utils/lowcode/registerComponentForRender.js +11 -11
  211. package/src/utils/map-utils.js +47 -47
  212. package/src/utils/reg.js +95 -95
  213. package/src/utils/request.js +347 -347
  214. package/src/utils/routerUtil.js +435 -435
  215. package/src/utils/runEvalFunction.js +6 -6
  216. package/src/utils/util.js +241 -241
  217. package/src/utils/waterMark.js +31 -31
  218. package/test/Amis.spec.js +163 -163
  219. package/test/Tree.spec.js +167 -167
  220. package/test/myDialog.spec.js +46 -46
  221. package/vue.config.js +181 -181
  222. package//350/277/201/347/247/273/346/227/245/345/277/227.md +15 -15
@@ -1,911 +1,911 @@
1
- <template>
2
- <!-- 输入框 -->
3
- <x-form-col
4
- v-if="attr.type === 'input' && show"
5
- :flex="attr.flex">
6
- <a-form-model-item
7
- :ref="attr.model"
8
- :label="attr.name"
9
- :labelCol="layout === 'inline' && attr.occupyCol ? labelAndWrapperCol[attr.occupyCol].labelCol:undefined"
10
- :wrapperCol="layout === 'inline'&& attr.occupyCol ? labelAndWrapperCol[attr.occupyCol].wrapperCol:undefined"
11
- :style="layout === 'inline'&& attr.occupyCol && attr.occupyCol > 1? {width:`calc(100% - ${attr.occupyCol * 1.533}rem)`}:{}"
12
- :prop="attr.prop ? attr.prop : attr.model">
13
- <!-- 如果配置了后置按钮插槽 -->
14
- <a-input-group
15
- v-if="(attr.inputOnAfterName && attr.inputOnAfterFunc) || (attr.inputOnAfterIcon && attr.inputOnAfterIconFunc)"
16
- style="display: flex; width: 100%;"
17
- compact>
18
- <a-input
19
- v-model="form[attr.model]"
20
- :read-only="readOnly"
21
- :disabled="disabled && !readOnly"
22
- :whitespace="true"
23
- style="flex: 1; width: auto; min-width: 0;"
24
- @blur="attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
25
- :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
26
- :ref="`${attr.model}input`"/>
27
- <a-button
28
- v-if="attr.inputOnAfterName && attr.inputOnAfterFunc"
29
- style="flex: 1; width: auto; min-width: 4rem;max-width: 6rem"
30
- type="primary"
31
- @click="emitFunc(attr.inputOnAfterFunc,form[attr.model])">
32
- {{ attr.inputOnAfterName }}
33
- </a-button>
34
- <!-- 仅可以配置 一个按钮 以及 一个图标插槽 -->
35
- <a-button
36
- style="width: 2rem; flex-shrink: 0;"
37
- v-if="attr.inputOnAfterIcon"
38
- :type="attr.inputOnAfterIcon && attr.inputOnAfterName ? 'primary' :''"
39
- :icon="attr.inputOnAfterIcon || 'question'"
40
- @click="emitFunc(attr.inputOnAfterIconFunc,form[attr.model])">
41
- </a-button>
42
- </a-input-group>
43
- <a-input-number
44
- v-else-if="attr.numberInput && !readOnly"
45
- v-model="form[attr.model]"
46
- :whitespace="true"
47
- :disabled="disabled && !readOnly"
48
- style="width:100%"
49
- @blur="attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
50
- :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
51
- :ref="`${attr.model}input`"/>
52
- <a-input
53
- v-else
54
- v-model="form[attr.model]"
55
- :whitespace="true"
56
- :read-only="readOnly"
57
- :disabled="disabled && !readOnly"
58
- style="width:100%"
59
- @blur="attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
60
- :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
61
- :ref="`${attr.model}input`"/>
62
-
63
- </a-form-model-item>
64
- </x-form-col>
65
- <!-- 下拉框 -->
66
- <x-form-col
67
- v-else-if="(attr.type === 'select' || (attr.type === 'rate' && mode==='查询')) && show"
68
- :flex="attr.flex">
69
- <a-form-model-item
70
- :ref="attr.model"
71
- :label="attr.name"
72
- :prop="attr.prop ? attr.prop : attr.model">
73
- <a-select
74
- v-if="!attr.lazyLoad || attr.lazyLoad === 'false'"
75
- v-model="form[attr.model]"
76
- :disabled="disabled"
77
- :filter-option="filterOption"
78
- :getPopupContainer=" triggerNode => { return triggerNode.parentNode } "
79
- :placeholder="attr.placeholder ? attr.placeholder : '请选择'"
80
- show-search
81
- >
82
- <a-select-option
83
- v-if="mode === '查询'"
84
- key="999999"
85
- value="全部">全部
86
- </a-select-option>
87
- <template v-if="attr.keys">
88
- <a-select-option
89
- v-for="(item,index) in attr.keys"
90
- :key="index.value"
91
- :value="item.value">
92
- {{ item.label }}
93
- </a-select-option>
94
- </template>
95
- <template v-else>
96
- <template
97
- v-if="attr.keyName.indexOf('logic@') !== -1 || attr.keyName.indexOf('config@') !== -1
98
- ||attr.keyName.indexOf('search@') !== -1 || attr.keyName.indexOf('search@') !== -1">
99
- <a-select-option
100
- v-for="(item,index) in option"
101
- :key="index.value"
102
- :value="item.value">
103
- <template v-if="attr.keyName.indexOf('config@') !== -1 && item.status">
104
- <!-- 徽标(badge) -->
105
- <a-badge v-if="item.status !== 'gary'" :color="item.status" :text="item.label"/>
106
- <a-badge v-else color="#D9D9D9" :text="item.label"/>
107
- </template>
108
- <template v-else>
109
- {{ item.label }}
110
- </template>
111
- </a-select-option>
112
- </template>
113
- <template
114
- v-else-if="attr.keyName.indexOf('async ') !== -1 || attr.keyName.indexOf('function ') !== -1">
115
- <a-select-option
116
- v-for="(item,index) in optionForFunc"
117
- :key="index.value"
118
- :value="item.value">
119
- <template>
120
- {{ item.label }}
121
- </template>
122
- </a-select-option>
123
- </template>
124
- <template v-else>
125
- <a-select-option
126
- v-for="item in $appdata.getDictionaryList(attr.keyName)"
127
- :key="item.value"
128
- :value="item.value">
129
- <!-- 徽标(badge) -->
130
- <x-badge :badge-key="attr.keyName" :replaceText="item.text" :value="item.value"/>
131
- </a-select-option>
132
- </template>
133
- </template>
134
- </a-select>
135
- <a-select
136
- v-else
137
- v-model="form[attr.model]"
138
- :disabled="disabled"
139
- :filter-option="filterOption"
140
- :getPopupContainer=" triggerNode => { return triggerNode.parentNode } "
141
- :placeholder="attr.placeholder ? attr.placeholder : '搜索' + attr.name"
142
- show-search
143
- @search="fetchFunction"
144
- >
145
- <a-spin v-if="searching" slot="notFoundContent" size="small"/>
146
- <a-select-option
147
- v-if="mode === '查询'"
148
- key="999999"
149
- value="全部">全部
150
- </a-select-option>
151
- <a-select-option
152
- v-for="(item,index) in option"
153
- :key="index"
154
- :value="item.value">{{ item.label }}
155
- </a-select-option>
156
- </a-select>
157
- </a-form-model-item>
158
- </x-form-col>
159
- <!-- 多选框 -->
160
- <x-form-col
161
- v-else-if="attr.type === 'checkbox' && show"
162
- :flex="attr.flex">
163
- <a-form-model-item
164
- :ref="attr.model"
165
- :label="attr.name"
166
- :prop="attr.prop ? attr.prop : attr.model">
167
- <a-select
168
- v-if="!attr.lazyLoad || attr.lazyLoad === 'false'"
169
- v-model="form[attr.model]"
170
- :disabled="disabled"
171
- :filter-option="filterOption"
172
- :getPopupContainer=" triggerNode => { return triggerNode.parentNode } "
173
- :placeholder="attr.placeholder ? attr.placeholder : '请选择'"
174
- mode="multiple"
175
- show-search
176
- allowClear
177
- >
178
- <template v-if="attr.keys">
179
- <a-select-option
180
- v-for="(item,index) in attr.keys"
181
- :key="index"
182
- :value="item.value">
183
- {{ item.label }}
184
- </a-select-option>
185
- </template>
186
- <template v-else>
187
- <template
188
- v-if="attr.keyName.indexOf('logic@') !== -1 || attr.keyName.indexOf('config@') !== -1
189
- ||attr.keyName.indexOf('search@') !== -1 || attr.keyName.indexOf('search@') !== -1">
190
- <a-select-option
191
- v-for="(item,index) in option"
192
- :key="index"
193
- :value="item.value">{{ item.label }}
194
- </a-select-option>
195
- </template>
196
- <template v-else>
197
- <a-select-option
198
- v-for="item in $appdata.getDictionaryList(attr.keyName)"
199
- :key="item.value"
200
- :value="item.value">{{ item.text }}
201
- </a-select-option>
202
- </template>
203
- </template>
204
- </a-select>
205
- <a-select
206
- v-else
207
- v-model="form[attr.model]"
208
- :disabled="disabled"
209
- :filter-option="filterOption"
210
- :getPopupContainer=" triggerNode => { return triggerNode.parentNode } "
211
- :placeholder="attr.placeholder ? attr.placeholder : '搜索' + attr.name"
212
- mode="multiple"
213
- show-search
214
- allowClear
215
- @search="fetchFunction"
216
- >
217
- <a-spin v-if="searching" slot="notFoundContent" size="small"/>
218
- <a-select-option
219
- v-for="(item,index) in option"
220
- :key="index"
221
- :value="item.value">{{ item.label }}
222
- </a-select-option>
223
- </a-select>
224
- </a-form-model-item>
225
- </x-form-col>
226
- <!-- 单选框 -->
227
- <x-form-col
228
- v-else-if="attr.type === 'radio' && show"
229
- :flex="attr.flex">
230
- <a-form-model-item
231
- :ref="attr.model"
232
- :label="attr.name"
233
- :prop="attr.prop ? attr.prop : attr.model">
234
- <a-radio-group v-model="form[attr.model]">
235
- <template v-if="attr.keys">
236
- <a-radio v-for="(item,index) in attr.keys" :key="index" :value="item.value">
237
- {{ item.label }}
238
- </a-radio>
239
- </template>
240
- <template v-else>
241
- <template
242
- v-if="attr.keyName.indexOf('logic@') !== -1 || attr.keyName.indexOf('config@') !== -1
243
- ||attr.keyName.indexOf('search@') !== -1 || attr.keyName.indexOf('search@') !== -1">
244
- <a-radio v-for="(item,index) in option" :key="index" :value="item.value">
245
- {{ item.label }}
246
- </a-radio>
247
- </template>
248
- <template v-else>
249
- <a-radio v-for="(item,index) in $appdata.getDictionaryList(attr.keyName)" :key="index" :value="item.value">
250
- {{ item.text }}
251
- </a-radio>
252
- </template>
253
- </template>
254
- </a-radio-group>
255
- </a-form-model-item>
256
- </x-form-col>
257
- <!-- 日期范围选择器 -->
258
- <x-form-col
259
- v-else-if="attr.type === 'rangePicker' && show"
260
- :flex="attr.flex">
261
- <a-form-model-item :ref="attr.model" :label="attr.name" :prop="attr.prop ? attr.prop : attr.model">
262
- <a-date-picker
263
- v-if="mode === '新增/修改'"
264
- v-model="form[attr.model]"
265
- :disabled="disabled"
266
- :show-time="true"
267
- style="width: 100%;"
268
- valueFormat="YYYY-MM-DD HH:mm:ss"/>
269
- <a-range-picker
270
- v-else
271
- v-model="form[attr.model]"
272
- :disabled="disabled"
273
- :show-time="true"
274
- valueFormat="YYYY-MM-DD HH:mm:ss"
275
- style="width: 100%;"
276
- />
277
- </a-form-model-item>
278
- </x-form-col>
279
- <!-- 月份选择器 -->
280
- <x-form-col
281
- v-else-if="attr.type === 'monthPicker' && show"
282
- :flex="attr.flex">
283
- <a-form-model-item :ref="attr.model" :label="attr.name" :prop="attr.prop ? attr.prop : attr.model">
284
- <a-month-picker
285
- v-model="form[attr.model]"
286
- :disabled="disabled"
287
- :show-time="true"
288
- valueFormat="YYYY-MM"
289
- style="width: 100%;"
290
- />
291
- </a-form-model-item>
292
- </x-form-col>
293
- <!-- 年份选择器 -->
294
- <x-form-col
295
- v-else-if="attr.type === 'yearPicker' && show"
296
- :flex="attr.flex">
297
- <a-form-model-item :ref="attr.model" :label="attr.name" :prop="attr.prop ? attr.prop : attr.model">
298
- <a-date-picker
299
- v-model="form[attr.model]"
300
- :disabled="disabled"
301
- format="YYYY"
302
- mode="year"
303
- v-decorator="['year']"
304
- placeholder="请选择年份"
305
- :open="yearShowOne"
306
- style="width: 100%;"
307
- @openChange="openChangeOne"
308
- @panelChange="panelChangeOne"/>
309
- </a-form-model-item>
310
- </x-form-col>
311
- <!-- 单日选择器 -->
312
- <x-form-col
313
- v-else-if="attr.type === 'datePicker' && show"
314
- :flex="attr.flex">
315
- <a-form-model-item :ref="attr.model" :label="attr.name" :prop="attr.prop ? attr.prop : attr.model">
316
- <a-range-picker
317
- v-if="mode === '查询'"
318
- v-model="form[attr.model]"
319
- :disabled="disabled"
320
- :show-time="true"
321
- style="width: 100%;"
322
- format="YYYY-MM-DD"
323
- valueFormat="YYYY-MM-DD HH:mm:ss"/>
324
- <a-date-picker
325
- v-else
326
- v-model="form[attr.model]"
327
- :disabled="disabled"
328
- style="width: 100%;"
329
- :show-time="{ defaultValue: moment('00:00:00', 'HH:mm:ss') }"
330
- valueFormat="YYYY-MM-DD HH:mm:ss"/>
331
- </a-form-model-item>
332
- </x-form-col>
333
- <!-- 文本域 -->
334
- <a-col
335
- v-else-if="attr.type === 'textarea' && show"
336
- :style="layout === 'inline'?{width:'calc(100% - 60px)'}:{}"
337
- :xs="24"
338
- :sm="24"
339
- :md="24"
340
- :lg="24"
341
- :xl="24"
342
- :xxl="24">
343
- <a-form-model-item
344
- :labelCol="layout === 'inline'?{span:2}:undefined"
345
- :wrapperCol="layout === 'inline'?{span:22}:undefined"
346
- :ref="attr.model"
347
- :label="attr.name"
348
- :prop="attr.prop ? attr.prop : attr.model">
349
- <a-textarea
350
- v-model="form[attr.model]"
351
- style="width: 100%;"
352
- :disabled="disabled"
353
- :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
354
- :rows="4"/>
355
- </a-form-model-item>
356
- </a-col>
357
- <!-- 文件上传 -->
358
- <a-col
359
- v-else-if="(attr.type === 'file' || attr.type === 'image') && show"
360
- :style="layout === 'inline'?{width:'calc(100% - 60px)'}:{}"
361
- :xs="24"
362
- :sm="24"
363
- :md="24"
364
- :lg="24"
365
- :xl="24"
366
- :xxl="24">
367
- <a-form-model-item
368
- :labelCol="layout === 'inline'?{span:2}:undefined"
369
- :wrapperCol="layout === 'inline'?{span:22}:undefined"
370
- :ref="attr.model"
371
- :label="attr.name"
372
- :prop="attr.prop ? attr.prop : attr.model">
373
- <upload
374
- :files="files"
375
- :images="images"
376
- :model="attr"
377
- :uploadStyle="attr.uploadStyle"
378
- :service-name="serviceName"
379
- @setFiles="setFiles"></upload>
380
- </a-form-model-item>
381
- </a-col>
382
- <!-- 省市区选择框 -->
383
- <x-form-col
384
- v-else-if="attr.type === 'citySelect' && show"
385
- :flex="attr.flex">
386
- <a-form-model-item :ref="attr.model" :label="attr.name" :prop="attr.prop ? attr.prop : attr.model">
387
- <citySelect
388
- ref="citySelect"
389
- v-model="form[attr.model]"
390
- :contexts="attr.contexts"
391
- :value-type="attr.valueType"
392
- :default-value="form[attr.model]"></citySelect>
393
- </a-form-model-item>
394
- </x-form-col>
395
- <!-- 地点搜索框 -->
396
- <x-form-col
397
- v-else-if="attr.type === 'addressSearch' && show"
398
- :flex="attr.flex">
399
- <a-form-model-item
400
- :ref="attr.model"
401
- :label="attr.name"
402
- :prop="attr.prop ? attr.prop : attr.model"
403
- :labelCol="layout === 'inline' && attr.occupyCol ? labelAndWrapperCol[attr.occupyCol].labelCol:undefined"
404
- :wrapperCol="layout === 'inline'&& attr.occupyCol ? labelAndWrapperCol[attr.occupyCol].wrapperCol:undefined"
405
- :style="layout === 'inline'&& attr.occupyCol && attr.occupyCol > 1? {width:`calc(100% - ${attr.occupyCol * 1.533}rem)`}:{}">
406
- <address-search-combobox
407
- :emitFunc="emitFunc"
408
- :attr="attr"
409
- :read-only="readOnly"
410
- v-model="searchResult"
411
- :resultKeys="{ address: attr.model, coords: `${attr.model}_lng_lat` }"
412
- ref="addressSearchCombobox"
413
- searchResultType="Object"
414
- @onSelect="addressSearchComboboxSelect"
415
- @onDivisionsChange="onDivisionsChange"
416
- ></address-search-combobox>
417
- </a-form-model-item>
418
- </x-form-col>
419
- <!-- 人员选择框 -->
420
- <x-form-col
421
- v-else-if="attr.type === 'personSetting' && show"
422
- :flex="attr.flex">
423
- <a-form-model-item :ref="attr.model" :label="attr.name" :prop="attr.prop ? attr.prop : attr.model">
424
- <PersonSetting v-model="form[attr.model]"></PersonSetting>
425
- </a-form-model-item>
426
- </x-form-col>
427
- <!-- 树形选择框 -->
428
- <x-form-col
429
- v-else-if="attr.type === 'treeSelect' && show"
430
- :flex="attr.flex">
431
- <x-tree-select
432
- v-model="form[attr.model]"
433
- :attr="attr"
434
- ref="xTreeSelect">
435
- </x-tree-select>
436
- </x-form-col>
437
- <!-- 评分框 -->
438
- <x-form-col
439
- v-else-if="attr.type === 'rate' && show"
440
- :flex="attr.flex">
441
- <a-form-model-item
442
- :ref="attr.model"
443
- :label="attr.name"
444
- :prop="attr.prop ? attr.prop : attr.model">
445
- <a-rate v-model="form[attr.model]"/>
446
- </a-form-model-item>
447
- </x-form-col>
448
- </template>
449
- <script>
450
-
451
- import { debounce } from 'ant-design-vue/lib/vc-table/src/utils'
452
- import XFormCol from '@vue2-client/base-client/components/common/XFormCol'
453
- import XBadge from '@vue2-client/base-client/components/common/XBadge'
454
- import CitySelect from '@vue2-client/base-client/components/common/CitySelect'
455
- import PersonSetting from '@vue2-client/base-client/components/common/PersonSetting'
456
- import AddressSearchCombobox from '@vue2-client/base-client/components/common/AddressSearchCombobox'
457
- import Upload from '@vue2-client/base-client/components/common/Upload'
458
- import moment from 'moment'
459
- import util from '.././../../../utils/util'
460
- import XTreeSelect from '@vue2-client/base-client/components/common/XForm/XTreeSelect'
461
- import { getConfigByName, runLogic } from '@vue2-client/services/api/common'
462
- import { searchToListOption, searchToOption } from '@vue2-client/services/v3Api'
463
- import { mapState } from 'vuex'
464
- import executeStrFunction from '@vue2-client/utils/runEvalFunction'
465
-
466
- export default {
467
- name: 'XFormItem',
468
- components: {
469
- XTreeSelect,
470
- XFormCol,
471
- XBadge,
472
- CitySelect,
473
- PersonSetting,
474
- AddressSearchCombobox,
475
- Upload
476
- },
477
- data () {
478
- // 检索去抖
479
- this.fetchFunction = debounce(this.fetchFunction, 800)
480
- return {
481
- option: [],
482
- // 最后检索版本
483
- lastFetchId: 0,
484
- // 检索中
485
- searching: false,
486
- searchResult: '',
487
- yearShowOne: false,
488
- optionForFunc: [],
489
- // 控制当前表单项是否展示
490
- show: true,
491
- labelAndWrapperCol: [{
492
- labelCol: undefined,
493
- wrapperCol: undefined
494
- },
495
- {
496
- labelCol: undefined,
497
- wrapperCol: undefined
498
- },
499
- {
500
- labelCol: { span: 3 },
501
- wrapperCol: { span: 21 }
502
- },
503
- {
504
- labelCol: { span: 2 },
505
- wrapperCol: { span: 22 }
506
- }],
507
- // moment
508
- moment
509
- }
510
- },
511
- props: {
512
- attr: {
513
- type: Object,
514
- default:
515
- () => {
516
- return {}
517
- }
518
- },
519
- form: {
520
- type: Object,
521
- required:
522
- true
523
- },
524
- disabled: {
525
- type: Boolean,
526
- default:
527
- () => {
528
- return false
529
- }
530
- },
531
- readOnly: {
532
- type: Boolean,
533
- default:
534
- () => {
535
- return false
536
- }
537
- },
538
- mode: {
539
- type: String,
540
- default:
541
- () => {
542
- return '查询'
543
- }
544
- },
545
- files: {
546
- type: Array,
547
- default:
548
- () => {
549
- return []
550
- }
551
- },
552
- images: {
553
- type: Array,
554
- default:
555
- () => {
556
- return []
557
- }
558
- },
559
- serviceName: {
560
- type: String,
561
- default:
562
- undefined
563
- },
564
- // 调用logic获取数据源的追加参数
565
- getDataParams: {
566
- type: Object,
567
- default:
568
- undefined
569
- },
570
- // 布局
571
- layout: {
572
- type: String,
573
- default:
574
- 'horizontal'
575
- },
576
- // 环境
577
- env: {
578
- type: String,
579
- default:
580
- () => {
581
- return 'prod'
582
- }
583
- },
584
- // 设置表单值
585
- setForm: {
586
- type: Function,
587
- default: (val) => {
588
- console.log(val)
589
- }
590
- },
591
- },
592
- created () {
593
- this.init()
594
- if (this.attr.keyName && (this.attr?.keyName?.toString().indexOf('async ') !== -1 || this.attr?.keyName?.toString()?.indexOf('function') !== -1)) {
595
- this.debouncedUpdateOptions = debounce(this.updateOptions, 200)
596
- }
597
- if (this.attr.dataChangeFunc) {
598
- this.debouncedDataChangeFunc = debounce(this.dataChangeFunc, 200)
599
- }
600
- if (this.attr.showFormItemFunc) {
601
- this.debouncedShowFormItemFunc = debounce(this.showFormItemFunc, 100)
602
- // 执行一次
603
- debounce(this.showFormItemFunc, 100)()
604
- }
605
- // 人员联动框增加监听
606
- if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动人员')) {
607
- this.debouncedUserLinkFunc = debounce(this.updateUserOptions, 200)
608
- }
609
- },
610
- computed: {
611
- ...mapState('account', { currUser: 'user' })
612
- },
613
- watch: {
614
- attr: {
615
- handler () {
616
- this.init()
617
- },
618
- deep: true
619
- },
620
- form: {
621
- handler (newVal) {
622
- // 如果是从函数获取 options
623
- if (this.attr.keyName && (this.attr.keyName.toString().indexOf('async ') !== -1 || this.attr.keyName.toString().indexOf('function') !== -1)) {
624
- this.debouncedUpdateOptions()
625
- }
626
- // 如果有自定义函数变更函数
627
- if (this.attr.dataChangeFunc) {
628
- this.debouncedDataChangeFunc()
629
- }
630
- // 如果有自定义是否展示表单项函数
631
- if (this.attr.showFormItemFunc) {
632
- this.debouncedShowFormItemFunc()
633
- }
634
- // 地址搜索框赋值
635
- if (this.attr.type === 'addressSearch') {
636
- this.$refs.addressSearchCombobox.addressInput = this.form[this.attr.model]
637
- }
638
- // 数据源来自人员联动时更新数据
639
- if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动人员')) {
640
- this.debouncedUserLinkFunc()
641
- }
642
- },
643
- deep: true
644
- }
645
- },
646
- methods: {
647
- focusInput () {
648
- if (this.attr.defaultFocus) {
649
- this.$nextTick(h => {
650
- const el = this.$refs[`${this.attr.model}input`]?.$el
651
- let inputEl
652
- if (el) {
653
- if (el.tagName.toLowerCase() === 'input') {
654
- inputEl = el
655
- } else {
656
- inputEl = el.querySelector('input')
657
- }
658
- }
659
- if (inputEl) {
660
- inputEl.focus()
661
- if (inputEl.type === 'number') {
662
- if (inputEl.valueAsNumber) {
663
- inputEl.setSelectionRange(0, inputEl.valueAsNumber.toString().length)
664
- }
665
- } else {
666
- if (inputEl.value) {
667
- inputEl.setSelectionRange(0, inputEl.value.length)
668
- }
669
- }
670
- }
671
- })
672
- }
673
- },
674
- // 更新人员下拉框数据
675
- async updateUserOptions () {
676
- if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString()?.endsWith(']联动人员')) {
677
- const searchData = { source: '获取人员', userid: this.currUser.id }
678
- const startIndex = this.attr.keyName.indexOf('[') + 1
679
- const endIndex = this.attr.keyName.indexOf(']', startIndex)
680
- const fromModel = this.attr.keyName.substring(startIndex, endIndex).replace('.', '_')
681
- const formModelData = this.form[fromModel]
682
- await searchToListOption(searchData, res => {
683
- this.getDataCallback(
684
- res.filter(h => {
685
- if (fromModel && fromModel.length) {
686
- if (fromModel.indexOf('org') > -1) {
687
- return formModelData?.includes(h.orgid || h.f_organization_id)
688
- } else {
689
- return formModelData?.includes(h?.parentid)
690
- }
691
- } else {
692
- return false
693
- }
694
- }
695
- )
696
- )
697
- })
698
- }
699
- },
700
- // js 函数作为数据源
701
- async updateOptions () {
702
- if (this.attr.keyName && (this.attr.keyName.indexOf('async ') !== -1 || this.attr.keyName.indexOf('function ') !== -1)) {
703
- this.optionForFunc = await executeStrFunction(this.attr.keyName, [this.form, runLogic])
704
- }
705
- },
706
- async dataChangeFunc () {
707
- if (this.attr.dataChangeFunc) {
708
- await executeStrFunction(this.attr.dataChangeFunc, [this.form, this.setForm, this.attr, util])
709
- }
710
- },
711
- async showFormItemFunc () {
712
- if (this.attr.showFormItemFunc) {
713
- this.show = executeStrFunction(this.attr.showFormItemFunc, [this.form, this.setForm, this.attr, util])
714
- } else {
715
- this.show = true
716
- }
717
- },
718
- init () {
719
- if (this.mode === '新增/修改' && !this.attr.flex) {
720
- if (['horizontal', 'vertical'].includes(this.layout)) {
721
- // 新增修改表单 horizontal 模式下默认为一行
722
- this.attr.flex = {
723
- xs: 24,
724
- sm: 24,
725
- md: 24,
726
- lg: 24,
727
- xl: 24,
728
- xxl: 24
729
- }
730
- } else {
731
- if (['input', 'addressSearch'] && this.attr.occupyCol) {
732
- // 如果是 input 看是否配置了 占用列配置
733
- this.attr.flex = {
734
- xs: 8 * this.attr.occupyCol,
735
- sm: 8 * this.attr.occupyCol,
736
- md: 8 * this.attr.occupyCol,
737
- lg: 8 * this.attr.occupyCol,
738
- xl: 8 * this.attr.occupyCol,
739
- xxl: 8 * this.attr.occupyCol
740
- }
741
- } else {
742
- // 新增修改表单 vertical 模式下默认为1列
743
- this.attr.flex = {
744
- xs: 24,
745
- sm: 24,
746
- md: 24,
747
- lg: 12,
748
- xl: 8,
749
- xxl: 8
750
- }
751
- }
752
- }
753
- } else {
754
- this.attr.flex = {
755
- xs: 24,
756
- sm: 24,
757
- md: 24,
758
- lg: 8,
759
- xl: 6,
760
- xxl: 6
761
- }
762
- }
763
- if (this.attr.keyName && this.attr.keyName.indexOf('logic@') !== -1) {
764
- this.getData({}, res => this.getDataCallback(res))
765
- }
766
- if (this.attr.keyName && this.attr.keyName.indexOf('search@') !== -1) {
767
- // `tool.getFullTree(this.getRights().where(row.getType()==$organization$))`
768
- // 判断是否根据角色查询
769
- let source = this.attr.keyName.substring(7)
770
- const userid = this.currUser.id
771
- let roleName = 'roleName'
772
- if (source.startsWith('根据角色[') && source.endsWith(']获取人员')) {
773
- const startIndex = source.indexOf('[') + 1
774
- const endIndex = source.indexOf(']', startIndex)
775
- roleName = source.substring(startIndex, endIndex)
776
- source = '根据角色获取人员'
777
- }
778
- const searchData = { source, userid, roleName }
779
- // 判断是否根据某个表单项联动 仅返回列表结构并筛选
780
- if (source.startsWith('根据表单项[') && source.endsWith(']联动人员')) {
781
- this.updateUserOptions()
782
- } else if (this.attr.type === 'select' || this.attr.type === 'checkbox') {
783
- // 仅获取最内层数据
784
- searchToListOption(searchData, res => this.getDataCallback(res))
785
- } else {
786
- searchToOption(searchData, res => this.getDataCallback(res))
787
- }
788
- } else if (this.attr.keyName && this.attr.keyName.indexOf('config@') !== -1) {
789
- const configName = this.attr.keyName.substring(7)
790
- getConfigByName(configName, this.serviceName, res => {
791
- this.getDataCallback(res.value)
792
- }, this.env === 'dev')
793
- } else if (this.attr.keyName && (this.attr.keyName.indexOf('async ') !== -1 || this.attr.keyName.indexOf('function ') !== -1)) {
794
- this.updateOptions()
795
- } else {
796
- this.initRadioValue()
797
- }
798
- this.focusInput()
799
- },
800
- addressSearchComboboxSelect (data) {
801
- this.form = Object.assign(this.form, JSON.parse(data))
802
- },
803
- onDivisionsChange (data) {
804
- this.emitFunc('addressSearchComboboxSelect', {
805
- key: this.attr.model,
806
- value: data
807
- })
808
- },
809
- getDataCallback (res) {
810
- this.option = res
811
- if (this.attr.type === 'treeSelect') {
812
- this.$refs.xTreeSelect.init({
813
- option: this.option,
814
- form: this.form,
815
- queryType: this.attr.queryType,
816
- name: this.attr.name,
817
- model: this.attr.model,
818
- mode: this.mode,
819
- disabled: this.disabled
820
- })
821
- } else if (this.attr.type === 'radio') {
822
- this.initRadioValue()
823
- }
824
- },
825
- initRadioValue () {
826
- const model = this.attr.model
827
- if (this.mode === '新增/修改' && this.attr.type === 'radio' && !this.form[model]) {
828
- if (this.attr.keys && this.attr.keys.length > 0) {
829
- this.form[model] = this.attr.keys[0].value
830
- } else if (this.option && this.option.length > 0) {
831
- this.form[model] = this.option[0].value
832
- } else if (this.attr.keyName) {
833
- const list = this.$appdata.getDictionaryList(this.attr.keyName)
834
- if (list.length > 0) {
835
- this.form[model] = list[0].value
836
- }
837
- }
838
- }
839
- },
840
- openChangeOne (status) {
841
- if (status) {
842
- this.yearShowOne = true
843
- }
844
- },
845
- // 得到年份选择器的值
846
- panelChangeOne (value) {
847
- this.yearShowOne = false
848
- this.form[this.attr.model] = value.format('YYYY')
849
- },
850
- // 文件框时设置上传组件的值
851
- setFiles (fileIds) {
852
- if (!this.form[this.attr.model]) {
853
- this.form[this.attr.model] = []
854
- }
855
- this.form[this.attr.model] = [...fileIds]
856
- },
857
- // 懒加载检索方法
858
- fetchFunction (value) {
859
- this.lastFetchId += 1
860
- const fetchId = this.lastFetchId
861
- this.option = []
862
- this.searching = true
863
- this.getData({
864
- word: value
865
- }, res => {
866
- if (fetchId !== this.lastFetchId) {
867
- return
868
- }
869
- this.option = res
870
- this.searching = false
871
- })
872
- },
873
- // 获取数据
874
- getData (value, callbackFun) {
875
- if (value !== '') {
876
- const logicName = this.attr.keyName
877
- const logic = logicName.substring(6)
878
- // 调用logic前设置参数
879
- if (this.getDataParams && this.getDataParams[this.attr.model]) {
880
- Object.assign(value, this.getDataParams[this.attr.model])
881
- }
882
- runLogic(logic, Object.assign(value, {
883
- orgId: this.currUser.orgid,
884
- userId: this.currUser.id
885
- }), this.serviceName, this.env === 'dev').then(res => {
886
- callbackFun(res)
887
- }).catch(e => {
888
- callbackFun([])
889
- console.error('获取数据失败:' + e)
890
- })
891
- }
892
- },
893
- filterOption (input, option) {
894
- const child = option.componentOptions.children[0]
895
- if (child.text) {
896
- return child.text.toLowerCase().indexOf(input.toLowerCase()) >= 0
897
- } else if (child.elm.innerText) {
898
- return child.elm.innerText.toLowerCase().indexOf(input.toLowerCase()) >= 0
899
- } else {
900
- return child.child.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
901
- }
902
- },
903
- emitFunc (func, data) {
904
- this.$emit('x-form-item-emit-func', func, data)
905
- }
906
- }
907
- }
908
- </script>
909
-
910
- <style lang="less" scoped>
911
- </style>
1
+ <template>
2
+ <!-- 输入框 -->
3
+ <x-form-col
4
+ v-if="attr.type === 'input' && show"
5
+ :flex="attr.flex">
6
+ <a-form-model-item
7
+ :ref="attr.model"
8
+ :label="attr.name"
9
+ :labelCol="layout === 'inline' && attr.occupyCol ? labelAndWrapperCol[attr.occupyCol].labelCol:undefined"
10
+ :wrapperCol="layout === 'inline'&& attr.occupyCol ? labelAndWrapperCol[attr.occupyCol].wrapperCol:undefined"
11
+ :style="layout === 'inline'&& attr.occupyCol && attr.occupyCol > 1? {width:`calc(100% - ${attr.occupyCol * 1.533}rem)`}:{}"
12
+ :prop="attr.prop ? attr.prop : attr.model">
13
+ <!-- 如果配置了后置按钮插槽 -->
14
+ <a-input-group
15
+ v-if="(attr.inputOnAfterName && attr.inputOnAfterFunc) || (attr.inputOnAfterIcon && attr.inputOnAfterIconFunc)"
16
+ style="display: flex; width: 100%;"
17
+ compact>
18
+ <a-input
19
+ v-model="form[attr.model]"
20
+ :read-only="readOnly"
21
+ :disabled="disabled && !readOnly"
22
+ :whitespace="true"
23
+ style="flex: 1; width: auto; min-width: 0;"
24
+ @blur="attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
25
+ :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
26
+ :ref="`${attr.model}input`"/>
27
+ <a-button
28
+ v-if="attr.inputOnAfterName && attr.inputOnAfterFunc"
29
+ style="flex: 1; width: auto; min-width: 4rem;max-width: 6rem"
30
+ type="primary"
31
+ @click="emitFunc(attr.inputOnAfterFunc,form[attr.model])">
32
+ {{ attr.inputOnAfterName }}
33
+ </a-button>
34
+ <!-- 仅可以配置 一个按钮 以及 一个图标插槽 -->
35
+ <a-button
36
+ style="width: 2rem; flex-shrink: 0;"
37
+ v-if="attr.inputOnAfterIcon"
38
+ :type="attr.inputOnAfterIcon && attr.inputOnAfterName ? 'primary' :''"
39
+ :icon="attr.inputOnAfterIcon || 'question'"
40
+ @click="emitFunc(attr.inputOnAfterIconFunc,form[attr.model])">
41
+ </a-button>
42
+ </a-input-group>
43
+ <a-input-number
44
+ v-else-if="attr.numberInput && !readOnly"
45
+ v-model="form[attr.model]"
46
+ :whitespace="true"
47
+ :disabled="disabled && !readOnly"
48
+ style="width:100%"
49
+ @blur="attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
50
+ :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
51
+ :ref="`${attr.model}input`"/>
52
+ <a-input
53
+ v-else
54
+ v-model="form[attr.model]"
55
+ :whitespace="true"
56
+ :read-only="readOnly"
57
+ :disabled="disabled && !readOnly"
58
+ style="width:100%"
59
+ @blur="attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
60
+ :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
61
+ :ref="`${attr.model}input`"/>
62
+
63
+ </a-form-model-item>
64
+ </x-form-col>
65
+ <!-- 下拉框 -->
66
+ <x-form-col
67
+ v-else-if="(attr.type === 'select' || (attr.type === 'rate' && mode==='查询')) && show"
68
+ :flex="attr.flex">
69
+ <a-form-model-item
70
+ :ref="attr.model"
71
+ :label="attr.name"
72
+ :prop="attr.prop ? attr.prop : attr.model">
73
+ <a-select
74
+ v-if="!attr.lazyLoad || attr.lazyLoad === 'false'"
75
+ v-model="form[attr.model]"
76
+ :disabled="disabled"
77
+ :filter-option="filterOption"
78
+ :getPopupContainer=" triggerNode => { return triggerNode.parentNode } "
79
+ :placeholder="attr.placeholder ? attr.placeholder : '请选择'"
80
+ show-search
81
+ >
82
+ <a-select-option
83
+ v-if="mode === '查询'"
84
+ key="999999"
85
+ value="全部">全部
86
+ </a-select-option>
87
+ <template v-if="attr.keys">
88
+ <a-select-option
89
+ v-for="(item,index) in attr.keys"
90
+ :key="index.value"
91
+ :value="item.value">
92
+ {{ item.label }}
93
+ </a-select-option>
94
+ </template>
95
+ <template v-else>
96
+ <template
97
+ v-if="attr.keyName.indexOf('logic@') !== -1 || attr.keyName.indexOf('config@') !== -1
98
+ ||attr.keyName.indexOf('search@') !== -1 || attr.keyName.indexOf('search@') !== -1">
99
+ <a-select-option
100
+ v-for="(item,index) in option"
101
+ :key="index.value"
102
+ :value="item.value">
103
+ <template v-if="attr.keyName.indexOf('config@') !== -1 && item.status">
104
+ <!-- 徽标(badge) -->
105
+ <a-badge v-if="item.status !== 'gary'" :color="item.status" :text="item.label"/>
106
+ <a-badge v-else color="#D9D9D9" :text="item.label"/>
107
+ </template>
108
+ <template v-else>
109
+ {{ item.label }}
110
+ </template>
111
+ </a-select-option>
112
+ </template>
113
+ <template
114
+ v-else-if="attr.keyName.indexOf('async ') !== -1 || attr.keyName.indexOf('function ') !== -1">
115
+ <a-select-option
116
+ v-for="(item,index) in optionForFunc"
117
+ :key="index.value"
118
+ :value="item.value">
119
+ <template>
120
+ {{ item.label }}
121
+ </template>
122
+ </a-select-option>
123
+ </template>
124
+ <template v-else>
125
+ <a-select-option
126
+ v-for="item in $appdata.getDictionaryList(attr.keyName)"
127
+ :key="item.value"
128
+ :value="item.value">
129
+ <!-- 徽标(badge) -->
130
+ <x-badge :badge-key="attr.keyName" :replaceText="item.text" :value="item.value"/>
131
+ </a-select-option>
132
+ </template>
133
+ </template>
134
+ </a-select>
135
+ <a-select
136
+ v-else
137
+ v-model="form[attr.model]"
138
+ :disabled="disabled"
139
+ :filter-option="filterOption"
140
+ :getPopupContainer=" triggerNode => { return triggerNode.parentNode } "
141
+ :placeholder="attr.placeholder ? attr.placeholder : '搜索' + attr.name"
142
+ show-search
143
+ @search="fetchFunction"
144
+ >
145
+ <a-spin v-if="searching" slot="notFoundContent" size="small"/>
146
+ <a-select-option
147
+ v-if="mode === '查询'"
148
+ key="999999"
149
+ value="全部">全部
150
+ </a-select-option>
151
+ <a-select-option
152
+ v-for="(item,index) in option"
153
+ :key="index"
154
+ :value="item.value">{{ item.label }}
155
+ </a-select-option>
156
+ </a-select>
157
+ </a-form-model-item>
158
+ </x-form-col>
159
+ <!-- 多选框 -->
160
+ <x-form-col
161
+ v-else-if="attr.type === 'checkbox' && show"
162
+ :flex="attr.flex">
163
+ <a-form-model-item
164
+ :ref="attr.model"
165
+ :label="attr.name"
166
+ :prop="attr.prop ? attr.prop : attr.model">
167
+ <a-select
168
+ v-if="!attr.lazyLoad || attr.lazyLoad === 'false'"
169
+ v-model="form[attr.model]"
170
+ :disabled="disabled"
171
+ :filter-option="filterOption"
172
+ :getPopupContainer=" triggerNode => { return triggerNode.parentNode } "
173
+ :placeholder="attr.placeholder ? attr.placeholder : '请选择'"
174
+ mode="multiple"
175
+ show-search
176
+ allowClear
177
+ >
178
+ <template v-if="attr.keys">
179
+ <a-select-option
180
+ v-for="(item,index) in attr.keys"
181
+ :key="index"
182
+ :value="item.value">
183
+ {{ item.label }}
184
+ </a-select-option>
185
+ </template>
186
+ <template v-else>
187
+ <template
188
+ v-if="attr.keyName.indexOf('logic@') !== -1 || attr.keyName.indexOf('config@') !== -1
189
+ ||attr.keyName.indexOf('search@') !== -1 || attr.keyName.indexOf('search@') !== -1">
190
+ <a-select-option
191
+ v-for="(item,index) in option"
192
+ :key="index"
193
+ :value="item.value">{{ item.label }}
194
+ </a-select-option>
195
+ </template>
196
+ <template v-else>
197
+ <a-select-option
198
+ v-for="item in $appdata.getDictionaryList(attr.keyName)"
199
+ :key="item.value"
200
+ :value="item.value">{{ item.text }}
201
+ </a-select-option>
202
+ </template>
203
+ </template>
204
+ </a-select>
205
+ <a-select
206
+ v-else
207
+ v-model="form[attr.model]"
208
+ :disabled="disabled"
209
+ :filter-option="filterOption"
210
+ :getPopupContainer=" triggerNode => { return triggerNode.parentNode } "
211
+ :placeholder="attr.placeholder ? attr.placeholder : '搜索' + attr.name"
212
+ mode="multiple"
213
+ show-search
214
+ allowClear
215
+ @search="fetchFunction"
216
+ >
217
+ <a-spin v-if="searching" slot="notFoundContent" size="small"/>
218
+ <a-select-option
219
+ v-for="(item,index) in option"
220
+ :key="index"
221
+ :value="item.value">{{ item.label }}
222
+ </a-select-option>
223
+ </a-select>
224
+ </a-form-model-item>
225
+ </x-form-col>
226
+ <!-- 单选框 -->
227
+ <x-form-col
228
+ v-else-if="attr.type === 'radio' && show"
229
+ :flex="attr.flex">
230
+ <a-form-model-item
231
+ :ref="attr.model"
232
+ :label="attr.name"
233
+ :prop="attr.prop ? attr.prop : attr.model">
234
+ <a-radio-group v-model="form[attr.model]">
235
+ <template v-if="attr.keys">
236
+ <a-radio v-for="(item,index) in attr.keys" :key="index" :value="item.value">
237
+ {{ item.label }}
238
+ </a-radio>
239
+ </template>
240
+ <template v-else>
241
+ <template
242
+ v-if="attr.keyName.indexOf('logic@') !== -1 || attr.keyName.indexOf('config@') !== -1
243
+ ||attr.keyName.indexOf('search@') !== -1 || attr.keyName.indexOf('search@') !== -1">
244
+ <a-radio v-for="(item,index) in option" :key="index" :value="item.value">
245
+ {{ item.label }}
246
+ </a-radio>
247
+ </template>
248
+ <template v-else>
249
+ <a-radio v-for="(item,index) in $appdata.getDictionaryList(attr.keyName)" :key="index" :value="item.value">
250
+ {{ item.text }}
251
+ </a-radio>
252
+ </template>
253
+ </template>
254
+ </a-radio-group>
255
+ </a-form-model-item>
256
+ </x-form-col>
257
+ <!-- 日期范围选择器 -->
258
+ <x-form-col
259
+ v-else-if="attr.type === 'rangePicker' && show"
260
+ :flex="attr.flex">
261
+ <a-form-model-item :ref="attr.model" :label="attr.name" :prop="attr.prop ? attr.prop : attr.model">
262
+ <a-date-picker
263
+ v-if="mode === '新增/修改'"
264
+ v-model="form[attr.model]"
265
+ :disabled="disabled"
266
+ :show-time="true"
267
+ style="width: 100%;"
268
+ valueFormat="YYYY-MM-DD HH:mm:ss"/>
269
+ <a-range-picker
270
+ v-else
271
+ v-model="form[attr.model]"
272
+ :disabled="disabled"
273
+ :show-time="true"
274
+ valueFormat="YYYY-MM-DD HH:mm:ss"
275
+ style="width: 100%;"
276
+ />
277
+ </a-form-model-item>
278
+ </x-form-col>
279
+ <!-- 月份选择器 -->
280
+ <x-form-col
281
+ v-else-if="attr.type === 'monthPicker' && show"
282
+ :flex="attr.flex">
283
+ <a-form-model-item :ref="attr.model" :label="attr.name" :prop="attr.prop ? attr.prop : attr.model">
284
+ <a-month-picker
285
+ v-model="form[attr.model]"
286
+ :disabled="disabled"
287
+ :show-time="true"
288
+ valueFormat="YYYY-MM"
289
+ style="width: 100%;"
290
+ />
291
+ </a-form-model-item>
292
+ </x-form-col>
293
+ <!-- 年份选择器 -->
294
+ <x-form-col
295
+ v-else-if="attr.type === 'yearPicker' && show"
296
+ :flex="attr.flex">
297
+ <a-form-model-item :ref="attr.model" :label="attr.name" :prop="attr.prop ? attr.prop : attr.model">
298
+ <a-date-picker
299
+ v-model="form[attr.model]"
300
+ :disabled="disabled"
301
+ format="YYYY"
302
+ mode="year"
303
+ v-decorator="['year']"
304
+ placeholder="请选择年份"
305
+ :open="yearShowOne"
306
+ style="width: 100%;"
307
+ @openChange="openChangeOne"
308
+ @panelChange="panelChangeOne"/>
309
+ </a-form-model-item>
310
+ </x-form-col>
311
+ <!-- 单日选择器 -->
312
+ <x-form-col
313
+ v-else-if="attr.type === 'datePicker' && show"
314
+ :flex="attr.flex">
315
+ <a-form-model-item :ref="attr.model" :label="attr.name" :prop="attr.prop ? attr.prop : attr.model">
316
+ <a-range-picker
317
+ v-if="mode === '查询'"
318
+ v-model="form[attr.model]"
319
+ :disabled="disabled"
320
+ :show-time="true"
321
+ style="width: 100%;"
322
+ format="YYYY-MM-DD"
323
+ valueFormat="YYYY-MM-DD HH:mm:ss"/>
324
+ <a-date-picker
325
+ v-else
326
+ v-model="form[attr.model]"
327
+ :disabled="disabled"
328
+ style="width: 100%;"
329
+ :show-time="{ defaultValue: moment('00:00:00', 'HH:mm:ss') }"
330
+ valueFormat="YYYY-MM-DD HH:mm:ss"/>
331
+ </a-form-model-item>
332
+ </x-form-col>
333
+ <!-- 文本域 -->
334
+ <a-col
335
+ v-else-if="attr.type === 'textarea' && show"
336
+ :style="layout === 'inline'?{width:'calc(100% - 60px)'}:{}"
337
+ :xs="24"
338
+ :sm="24"
339
+ :md="24"
340
+ :lg="24"
341
+ :xl="24"
342
+ :xxl="24">
343
+ <a-form-model-item
344
+ :labelCol="layout === 'inline'?{span:2}:undefined"
345
+ :wrapperCol="layout === 'inline'?{span:22}:undefined"
346
+ :ref="attr.model"
347
+ :label="attr.name"
348
+ :prop="attr.prop ? attr.prop : attr.model">
349
+ <a-textarea
350
+ v-model="form[attr.model]"
351
+ style="width: 100%;"
352
+ :disabled="disabled"
353
+ :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
354
+ :rows="4"/>
355
+ </a-form-model-item>
356
+ </a-col>
357
+ <!-- 文件上传 -->
358
+ <a-col
359
+ v-else-if="(attr.type === 'file' || attr.type === 'image') && show"
360
+ :style="layout === 'inline'?{width:'calc(100% - 60px)'}:{}"
361
+ :xs="24"
362
+ :sm="24"
363
+ :md="24"
364
+ :lg="24"
365
+ :xl="24"
366
+ :xxl="24">
367
+ <a-form-model-item
368
+ :labelCol="layout === 'inline'?{span:2}:undefined"
369
+ :wrapperCol="layout === 'inline'?{span:22}:undefined"
370
+ :ref="attr.model"
371
+ :label="attr.name"
372
+ :prop="attr.prop ? attr.prop : attr.model">
373
+ <upload
374
+ :files="files"
375
+ :images="images"
376
+ :model="attr"
377
+ :uploadStyle="attr.uploadStyle"
378
+ :service-name="serviceName"
379
+ @setFiles="setFiles"></upload>
380
+ </a-form-model-item>
381
+ </a-col>
382
+ <!-- 省市区选择框 -->
383
+ <x-form-col
384
+ v-else-if="attr.type === 'citySelect' && show"
385
+ :flex="attr.flex">
386
+ <a-form-model-item :ref="attr.model" :label="attr.name" :prop="attr.prop ? attr.prop : attr.model">
387
+ <citySelect
388
+ ref="citySelect"
389
+ v-model="form[attr.model]"
390
+ :contexts="attr.contexts"
391
+ :value-type="attr.valueType"
392
+ :default-value="form[attr.model]"></citySelect>
393
+ </a-form-model-item>
394
+ </x-form-col>
395
+ <!-- 地点搜索框 -->
396
+ <x-form-col
397
+ v-else-if="attr.type === 'addressSearch' && show"
398
+ :flex="attr.flex">
399
+ <a-form-model-item
400
+ :ref="attr.model"
401
+ :label="attr.name"
402
+ :prop="attr.prop ? attr.prop : attr.model"
403
+ :labelCol="layout === 'inline' && attr.occupyCol ? labelAndWrapperCol[attr.occupyCol].labelCol:undefined"
404
+ :wrapperCol="layout === 'inline'&& attr.occupyCol ? labelAndWrapperCol[attr.occupyCol].wrapperCol:undefined"
405
+ :style="layout === 'inline'&& attr.occupyCol && attr.occupyCol > 1? {width:`calc(100% - ${attr.occupyCol * 1.533}rem)`}:{}">
406
+ <address-search-combobox
407
+ :emitFunc="emitFunc"
408
+ :attr="attr"
409
+ :read-only="readOnly"
410
+ v-model="searchResult"
411
+ :resultKeys="{ address: attr.model, coords: `${attr.model}_lng_lat` }"
412
+ ref="addressSearchCombobox"
413
+ searchResultType="Object"
414
+ @onSelect="addressSearchComboboxSelect"
415
+ @onDivisionsChange="onDivisionsChange"
416
+ ></address-search-combobox>
417
+ </a-form-model-item>
418
+ </x-form-col>
419
+ <!-- 人员选择框 -->
420
+ <x-form-col
421
+ v-else-if="attr.type === 'personSetting' && show"
422
+ :flex="attr.flex">
423
+ <a-form-model-item :ref="attr.model" :label="attr.name" :prop="attr.prop ? attr.prop : attr.model">
424
+ <PersonSetting v-model="form[attr.model]"></PersonSetting>
425
+ </a-form-model-item>
426
+ </x-form-col>
427
+ <!-- 树形选择框 -->
428
+ <x-form-col
429
+ v-else-if="attr.type === 'treeSelect' && show"
430
+ :flex="attr.flex">
431
+ <x-tree-select
432
+ v-model="form[attr.model]"
433
+ :attr="attr"
434
+ ref="xTreeSelect">
435
+ </x-tree-select>
436
+ </x-form-col>
437
+ <!-- 评分框 -->
438
+ <x-form-col
439
+ v-else-if="attr.type === 'rate' && show"
440
+ :flex="attr.flex">
441
+ <a-form-model-item
442
+ :ref="attr.model"
443
+ :label="attr.name"
444
+ :prop="attr.prop ? attr.prop : attr.model">
445
+ <a-rate v-model="form[attr.model]"/>
446
+ </a-form-model-item>
447
+ </x-form-col>
448
+ </template>
449
+ <script>
450
+
451
+ import { debounce } from 'ant-design-vue/lib/vc-table/src/utils'
452
+ import XFormCol from '@vue2-client/base-client/components/common/XFormCol'
453
+ import XBadge from '@vue2-client/base-client/components/common/XBadge'
454
+ import CitySelect from '@vue2-client/base-client/components/common/CitySelect'
455
+ import PersonSetting from '@vue2-client/base-client/components/common/PersonSetting'
456
+ import AddressSearchCombobox from '@vue2-client/base-client/components/common/AddressSearchCombobox'
457
+ import Upload from '@vue2-client/base-client/components/common/Upload'
458
+ import moment from 'moment'
459
+ import util from '.././../../../utils/util'
460
+ import XTreeSelect from '@vue2-client/base-client/components/common/XForm/XTreeSelect'
461
+ import { getConfigByName, runLogic } from '@vue2-client/services/api/common'
462
+ import { searchToListOption, searchToOption } from '@vue2-client/services/v3Api'
463
+ import { mapState } from 'vuex'
464
+ import executeStrFunction from '@vue2-client/utils/runEvalFunction'
465
+
466
+ export default {
467
+ name: 'XFormItem',
468
+ components: {
469
+ XTreeSelect,
470
+ XFormCol,
471
+ XBadge,
472
+ CitySelect,
473
+ PersonSetting,
474
+ AddressSearchCombobox,
475
+ Upload
476
+ },
477
+ data () {
478
+ // 检索去抖
479
+ this.fetchFunction = debounce(this.fetchFunction, 800)
480
+ return {
481
+ option: [],
482
+ // 最后检索版本
483
+ lastFetchId: 0,
484
+ // 检索中
485
+ searching: false,
486
+ searchResult: '',
487
+ yearShowOne: false,
488
+ optionForFunc: [],
489
+ // 控制当前表单项是否展示
490
+ show: true,
491
+ labelAndWrapperCol: [{
492
+ labelCol: undefined,
493
+ wrapperCol: undefined
494
+ },
495
+ {
496
+ labelCol: undefined,
497
+ wrapperCol: undefined
498
+ },
499
+ {
500
+ labelCol: { span: 3 },
501
+ wrapperCol: { span: 21 }
502
+ },
503
+ {
504
+ labelCol: { span: 2 },
505
+ wrapperCol: { span: 22 }
506
+ }],
507
+ // moment
508
+ moment
509
+ }
510
+ },
511
+ props: {
512
+ attr: {
513
+ type: Object,
514
+ default:
515
+ () => {
516
+ return {}
517
+ }
518
+ },
519
+ form: {
520
+ type: Object,
521
+ required:
522
+ true
523
+ },
524
+ disabled: {
525
+ type: Boolean,
526
+ default:
527
+ () => {
528
+ return false
529
+ }
530
+ },
531
+ readOnly: {
532
+ type: Boolean,
533
+ default:
534
+ () => {
535
+ return false
536
+ }
537
+ },
538
+ mode: {
539
+ type: String,
540
+ default:
541
+ () => {
542
+ return '查询'
543
+ }
544
+ },
545
+ files: {
546
+ type: Array,
547
+ default:
548
+ () => {
549
+ return []
550
+ }
551
+ },
552
+ images: {
553
+ type: Array,
554
+ default:
555
+ () => {
556
+ return []
557
+ }
558
+ },
559
+ serviceName: {
560
+ type: String,
561
+ default:
562
+ undefined
563
+ },
564
+ // 调用logic获取数据源的追加参数
565
+ getDataParams: {
566
+ type: Object,
567
+ default:
568
+ undefined
569
+ },
570
+ // 布局
571
+ layout: {
572
+ type: String,
573
+ default:
574
+ 'horizontal'
575
+ },
576
+ // 环境
577
+ env: {
578
+ type: String,
579
+ default:
580
+ () => {
581
+ return 'prod'
582
+ }
583
+ },
584
+ // 设置表单值
585
+ setForm: {
586
+ type: Function,
587
+ default: (val) => {
588
+ console.log(val)
589
+ }
590
+ },
591
+ },
592
+ created () {
593
+ this.init()
594
+ if (this.attr.keyName && (this.attr?.keyName?.toString().indexOf('async ') !== -1 || this.attr?.keyName?.toString()?.indexOf('function') !== -1)) {
595
+ this.debouncedUpdateOptions = debounce(this.updateOptions, 200)
596
+ }
597
+ if (this.attr.dataChangeFunc) {
598
+ this.debouncedDataChangeFunc = debounce(this.dataChangeFunc, 200)
599
+ }
600
+ if (this.attr.showFormItemFunc) {
601
+ this.debouncedShowFormItemFunc = debounce(this.showFormItemFunc, 100)
602
+ // 执行一次
603
+ debounce(this.showFormItemFunc, 100)()
604
+ }
605
+ // 人员联动框增加监听
606
+ if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动人员')) {
607
+ this.debouncedUserLinkFunc = debounce(this.updateUserOptions, 200)
608
+ }
609
+ },
610
+ computed: {
611
+ ...mapState('account', { currUser: 'user' })
612
+ },
613
+ watch: {
614
+ attr: {
615
+ handler () {
616
+ this.init()
617
+ },
618
+ deep: true
619
+ },
620
+ form: {
621
+ handler (newVal) {
622
+ // 如果是从函数获取 options
623
+ if (this.attr.keyName && (this.attr.keyName.toString().indexOf('async ') !== -1 || this.attr.keyName.toString().indexOf('function') !== -1)) {
624
+ this.debouncedUpdateOptions()
625
+ }
626
+ // 如果有自定义函数变更函数
627
+ if (this.attr.dataChangeFunc) {
628
+ this.debouncedDataChangeFunc()
629
+ }
630
+ // 如果有自定义是否展示表单项函数
631
+ if (this.attr.showFormItemFunc) {
632
+ this.debouncedShowFormItemFunc()
633
+ }
634
+ // 地址搜索框赋值
635
+ if (this.attr.type === 'addressSearch') {
636
+ this.$refs.addressSearchCombobox.addressInput = this.form[this.attr.model]
637
+ }
638
+ // 数据源来自人员联动时更新数据
639
+ if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动人员')) {
640
+ this.debouncedUserLinkFunc()
641
+ }
642
+ },
643
+ deep: true
644
+ }
645
+ },
646
+ methods: {
647
+ focusInput () {
648
+ if (this.attr.defaultFocus) {
649
+ this.$nextTick(h => {
650
+ const el = this.$refs[`${this.attr.model}input`]?.$el
651
+ let inputEl
652
+ if (el) {
653
+ if (el.tagName.toLowerCase() === 'input') {
654
+ inputEl = el
655
+ } else {
656
+ inputEl = el.querySelector('input')
657
+ }
658
+ }
659
+ if (inputEl) {
660
+ inputEl.focus()
661
+ if (inputEl.type === 'number') {
662
+ if (inputEl.valueAsNumber) {
663
+ inputEl.setSelectionRange(0, inputEl.valueAsNumber.toString().length)
664
+ }
665
+ } else {
666
+ if (inputEl.value) {
667
+ inputEl.setSelectionRange(0, inputEl.value.length)
668
+ }
669
+ }
670
+ }
671
+ })
672
+ }
673
+ },
674
+ // 更新人员下拉框数据
675
+ async updateUserOptions () {
676
+ if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString()?.endsWith(']联动人员')) {
677
+ const searchData = { source: '获取人员', userid: this.currUser.id }
678
+ const startIndex = this.attr.keyName.indexOf('[') + 1
679
+ const endIndex = this.attr.keyName.indexOf(']', startIndex)
680
+ const fromModel = this.attr.keyName.substring(startIndex, endIndex).replace('.', '_')
681
+ const formModelData = this.form[fromModel]
682
+ await searchToListOption(searchData, res => {
683
+ this.getDataCallback(
684
+ res.filter(h => {
685
+ if (fromModel && fromModel.length) {
686
+ if (fromModel.indexOf('org') > -1) {
687
+ return formModelData?.includes(h.orgid || h.f_organization_id)
688
+ } else {
689
+ return formModelData?.includes(h?.parentid)
690
+ }
691
+ } else {
692
+ return false
693
+ }
694
+ }
695
+ )
696
+ )
697
+ })
698
+ }
699
+ },
700
+ // js 函数作为数据源
701
+ async updateOptions () {
702
+ if (this.attr.keyName && (this.attr.keyName.indexOf('async ') !== -1 || this.attr.keyName.indexOf('function ') !== -1)) {
703
+ this.optionForFunc = await executeStrFunction(this.attr.keyName, [this.form, runLogic])
704
+ }
705
+ },
706
+ async dataChangeFunc () {
707
+ if (this.attr.dataChangeFunc) {
708
+ await executeStrFunction(this.attr.dataChangeFunc, [this.form, this.setForm, this.attr, util])
709
+ }
710
+ },
711
+ async showFormItemFunc () {
712
+ if (this.attr.showFormItemFunc) {
713
+ this.show = executeStrFunction(this.attr.showFormItemFunc, [this.form, this.setForm, this.attr, util])
714
+ } else {
715
+ this.show = true
716
+ }
717
+ },
718
+ init () {
719
+ if (this.mode === '新增/修改' && !this.attr.flex) {
720
+ if (['horizontal', 'vertical'].includes(this.layout)) {
721
+ // 新增修改表单 horizontal 模式下默认为一行
722
+ this.attr.flex = {
723
+ xs: 24,
724
+ sm: 24,
725
+ md: 24,
726
+ lg: 24,
727
+ xl: 24,
728
+ xxl: 24
729
+ }
730
+ } else {
731
+ if (['input', 'addressSearch'] && this.attr.occupyCol) {
732
+ // 如果是 input 看是否配置了 占用列配置
733
+ this.attr.flex = {
734
+ xs: 8 * this.attr.occupyCol,
735
+ sm: 8 * this.attr.occupyCol,
736
+ md: 8 * this.attr.occupyCol,
737
+ lg: 8 * this.attr.occupyCol,
738
+ xl: 8 * this.attr.occupyCol,
739
+ xxl: 8 * this.attr.occupyCol
740
+ }
741
+ } else {
742
+ // 新增修改表单 vertical 模式下默认为1列
743
+ this.attr.flex = {
744
+ xs: 24,
745
+ sm: 24,
746
+ md: 24,
747
+ lg: 12,
748
+ xl: 8,
749
+ xxl: 8
750
+ }
751
+ }
752
+ }
753
+ } else {
754
+ this.attr.flex = {
755
+ xs: 24,
756
+ sm: 24,
757
+ md: 24,
758
+ lg: 8,
759
+ xl: 6,
760
+ xxl: 6
761
+ }
762
+ }
763
+ if (this.attr.keyName && this.attr.keyName.indexOf('logic@') !== -1) {
764
+ this.getData({}, res => this.getDataCallback(res))
765
+ }
766
+ if (this.attr.keyName && this.attr.keyName.indexOf('search@') !== -1) {
767
+ // `tool.getFullTree(this.getRights().where(row.getType()==$organization$))`
768
+ // 判断是否根据角色查询
769
+ let source = this.attr.keyName.substring(7)
770
+ const userid = this.currUser.id
771
+ let roleName = 'roleName'
772
+ if (source.startsWith('根据角色[') && source.endsWith(']获取人员')) {
773
+ const startIndex = source.indexOf('[') + 1
774
+ const endIndex = source.indexOf(']', startIndex)
775
+ roleName = source.substring(startIndex, endIndex)
776
+ source = '根据角色获取人员'
777
+ }
778
+ const searchData = { source, userid, roleName }
779
+ // 判断是否根据某个表单项联动 仅返回列表结构并筛选
780
+ if (source.startsWith('根据表单项[') && source.endsWith(']联动人员')) {
781
+ this.updateUserOptions()
782
+ } else if (this.attr.type === 'select' || this.attr.type === 'checkbox') {
783
+ // 仅获取最内层数据
784
+ searchToListOption(searchData, res => this.getDataCallback(res))
785
+ } else {
786
+ searchToOption(searchData, res => this.getDataCallback(res))
787
+ }
788
+ } else if (this.attr.keyName && this.attr.keyName.indexOf('config@') !== -1) {
789
+ const configName = this.attr.keyName.substring(7)
790
+ getConfigByName(configName, this.serviceName, res => {
791
+ this.getDataCallback(res.value)
792
+ }, this.env === 'dev')
793
+ } else if (this.attr.keyName && (this.attr.keyName.indexOf('async ') !== -1 || this.attr.keyName.indexOf('function ') !== -1)) {
794
+ this.updateOptions()
795
+ } else {
796
+ this.initRadioValue()
797
+ }
798
+ this.focusInput()
799
+ },
800
+ addressSearchComboboxSelect (data) {
801
+ this.form = Object.assign(this.form, JSON.parse(data))
802
+ },
803
+ onDivisionsChange (data) {
804
+ this.emitFunc('addressSearchComboboxSelect', {
805
+ key: this.attr.model,
806
+ value: data
807
+ })
808
+ },
809
+ getDataCallback (res) {
810
+ this.option = res
811
+ if (this.attr.type === 'treeSelect') {
812
+ this.$refs.xTreeSelect.init({
813
+ option: this.option,
814
+ form: this.form,
815
+ queryType: this.attr.queryType,
816
+ name: this.attr.name,
817
+ model: this.attr.model,
818
+ mode: this.mode,
819
+ disabled: this.disabled
820
+ })
821
+ } else if (this.attr.type === 'radio') {
822
+ this.initRadioValue()
823
+ }
824
+ },
825
+ initRadioValue () {
826
+ const model = this.attr.model
827
+ if (this.mode === '新增/修改' && this.attr.type === 'radio' && !this.form[model]) {
828
+ if (this.attr.keys && this.attr.keys.length > 0) {
829
+ this.form[model] = this.attr.keys[0].value
830
+ } else if (this.option && this.option.length > 0) {
831
+ this.form[model] = this.option[0].value
832
+ } else if (this.attr.keyName) {
833
+ const list = this.$appdata.getDictionaryList(this.attr.keyName)
834
+ if (list.length > 0) {
835
+ this.form[model] = list[0].value
836
+ }
837
+ }
838
+ }
839
+ },
840
+ openChangeOne (status) {
841
+ if (status) {
842
+ this.yearShowOne = true
843
+ }
844
+ },
845
+ // 得到年份选择器的值
846
+ panelChangeOne (value) {
847
+ this.yearShowOne = false
848
+ this.form[this.attr.model] = value.format('YYYY')
849
+ },
850
+ // 文件框时设置上传组件的值
851
+ setFiles (fileIds) {
852
+ if (!this.form[this.attr.model]) {
853
+ this.form[this.attr.model] = []
854
+ }
855
+ this.form[this.attr.model] = [...fileIds]
856
+ },
857
+ // 懒加载检索方法
858
+ fetchFunction (value) {
859
+ this.lastFetchId += 1
860
+ const fetchId = this.lastFetchId
861
+ this.option = []
862
+ this.searching = true
863
+ this.getData({
864
+ word: value
865
+ }, res => {
866
+ if (fetchId !== this.lastFetchId) {
867
+ return
868
+ }
869
+ this.option = res
870
+ this.searching = false
871
+ })
872
+ },
873
+ // 获取数据
874
+ getData (value, callbackFun) {
875
+ if (value !== '') {
876
+ const logicName = this.attr.keyName
877
+ const logic = logicName.substring(6)
878
+ // 调用logic前设置参数
879
+ if (this.getDataParams && this.getDataParams[this.attr.model]) {
880
+ Object.assign(value, this.getDataParams[this.attr.model])
881
+ }
882
+ runLogic(logic, Object.assign(value, {
883
+ orgId: this.currUser.orgid,
884
+ userId: this.currUser.id
885
+ }), this.serviceName, this.env === 'dev').then(res => {
886
+ callbackFun(res)
887
+ }).catch(e => {
888
+ callbackFun([])
889
+ console.error('获取数据失败:' + e)
890
+ })
891
+ }
892
+ },
893
+ filterOption (input, option) {
894
+ const child = option.componentOptions.children[0]
895
+ if (child.text) {
896
+ return child.text.toLowerCase().indexOf(input.toLowerCase()) >= 0
897
+ } else if (child.elm.innerText) {
898
+ return child.elm.innerText.toLowerCase().indexOf(input.toLowerCase()) >= 0
899
+ } else {
900
+ return child.child.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
901
+ }
902
+ },
903
+ emitFunc (func, data) {
904
+ this.$emit('x-form-item-emit-func', func, data)
905
+ }
906
+ }
907
+ }
908
+ </script>
909
+
910
+ <style lang="less" scoped>
911
+ </style>