@skyfox2000/webui 0.1.0

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 (213) hide show
  1. package/.eslintrc.js +23 -0
  2. package/.prettierrc +11 -0
  3. package/.vscode/settings.json +25 -0
  4. package/README.md +104 -0
  5. package/env.d.ts +11 -0
  6. package/index.html +19 -0
  7. package/lib/AceEditor.d.ts +4 -0
  8. package/lib/BasicLayout.d.ts +4 -0
  9. package/lib/Error403.d.ts +4 -0
  10. package/lib/Error404.d.ts +4 -0
  11. package/lib/ExcelForm.d.ts +4 -0
  12. package/lib/UploadForm.d.ts +4 -0
  13. package/lib/assets/modules/basicLayout-YP_-EySb.js +726 -0
  14. package/lib/assets/modules/error403-Bi0E2twj.js +33 -0
  15. package/lib/assets/modules/error404-BF7vasR_.js +33 -0
  16. package/lib/assets/modules/excelForm-Dzndz-SG.js +109 -0
  17. package/lib/assets/modules/excelForm-WJVQmaDT.js +317 -0
  18. package/lib/assets/modules/index-FzWSvscZ.js +107 -0
  19. package/lib/assets/modules/index-ekkaExvB.js +49 -0
  20. package/lib/assets/modules/uploadForm-BahGnrAq.js +415 -0
  21. package/lib/assets/modules/uploadForm-DEnOjhwc.js +308 -0
  22. package/lib/components/common/button/index.vue.d.ts +42 -0
  23. package/lib/components/common/button/index.vue.d.ts.map +1 -0
  24. package/lib/components/common/icon/appicon.vue.d.ts +12 -0
  25. package/lib/components/common/icon/appicon.vue.d.ts.map +1 -0
  26. package/lib/components/common/icon/fullscreen.vue.d.ts +4 -0
  27. package/lib/components/common/icon/fullscreen.vue.d.ts.map +1 -0
  28. package/lib/components/common/icon/helper.vue.d.ts +23 -0
  29. package/lib/components/common/icon/helper.vue.d.ts.map +1 -0
  30. package/lib/components/common/icon/index.vue.d.ts +244 -0
  31. package/lib/components/common/icon/index.vue.d.ts.map +1 -0
  32. package/lib/components/common/icon/layoutIcon.vue.d.ts +44 -0
  33. package/lib/components/common/icon/layoutIcon.vue.d.ts.map +1 -0
  34. package/lib/components/common/icon/projectIcon.vue.d.ts +60 -0
  35. package/lib/components/common/icon/projectIcon.vue.d.ts.map +1 -0
  36. package/lib/components/common/icon/toolIcon.vue.d.ts +44 -0
  37. package/lib/components/common/icon/toolIcon.vue.d.ts.map +1 -0
  38. package/lib/components/common/index.d.ts +19 -0
  39. package/lib/components/common/index.d.ts.map +1 -0
  40. package/lib/components/common/tooltip/index.vue.d.ts +22 -0
  41. package/lib/components/common/tooltip/index.vue.d.ts.map +1 -0
  42. package/lib/components/content/dialog/excelForm.vue.d.ts +31 -0
  43. package/lib/components/content/dialog/excelForm.vue.d.ts.map +1 -0
  44. package/lib/components/content/dialog/index.vue.d.ts +35 -0
  45. package/lib/components/content/dialog/index.vue.d.ts.map +1 -0
  46. package/lib/components/content/dialog/uploadForm.vue.d.ts +25 -0
  47. package/lib/components/content/dialog/uploadForm.vue.d.ts.map +1 -0
  48. package/lib/components/content/drawer/index.vue.d.ts +27 -0
  49. package/lib/components/content/drawer/index.vue.d.ts.map +1 -0
  50. package/lib/components/content/form/formItem.vue.d.ts +26 -0
  51. package/lib/components/content/form/formItem.vue.d.ts.map +1 -0
  52. package/lib/components/content/form/index.vue.d.ts +26 -0
  53. package/lib/components/content/form/index.vue.d.ts.map +1 -0
  54. package/lib/components/content/index.d.ts +27 -0
  55. package/lib/components/content/index.d.ts.map +1 -0
  56. package/lib/components/content/search/index.vue.d.ts +30 -0
  57. package/lib/components/content/search/index.vue.d.ts.map +1 -0
  58. package/lib/components/content/search/searchItem.vue.d.ts +24 -0
  59. package/lib/components/content/search/searchItem.vue.d.ts.map +1 -0
  60. package/lib/components/content/table/index.vue.d.ts +37 -0
  61. package/lib/components/content/table/index.vue.d.ts.map +1 -0
  62. package/lib/components/content/table/tableOperate.vue.d.ts +19 -0
  63. package/lib/components/content/table/tableOperate.vue.d.ts.map +1 -0
  64. package/lib/components/content/toolbar/icontool.vue.d.ts +8 -0
  65. package/lib/components/content/toolbar/icontool.vue.d.ts.map +1 -0
  66. package/lib/components/content/toolbar/index.vue.d.ts +19 -0
  67. package/lib/components/content/toolbar/index.vue.d.ts.map +1 -0
  68. package/lib/components/content/tree/index.vue.d.ts +47 -0
  69. package/lib/components/content/tree/index.vue.d.ts.map +1 -0
  70. package/lib/components/error/error403.vue.d.ts +4 -0
  71. package/lib/components/error/error403.vue.d.ts.map +1 -0
  72. package/lib/components/error/error404.vue.d.ts +4 -0
  73. package/lib/components/error/error404.vue.d.ts.map +1 -0
  74. package/lib/components/form/aceEditor/aceConfig.d.ts +9 -0
  75. package/lib/components/form/aceEditor/aceConfig.d.ts.map +1 -0
  76. package/lib/components/form/aceEditor/index.vue.d.ts +13 -0
  77. package/lib/components/form/aceEditor/index.vue.d.ts.map +1 -0
  78. package/lib/components/form/autoComplete/index.vue.d.ts +140 -0
  79. package/lib/components/form/autoComplete/index.vue.d.ts.map +1 -0
  80. package/lib/components/form/cascader/index.vue.d.ts +110 -0
  81. package/lib/components/form/cascader/index.vue.d.ts.map +1 -0
  82. package/lib/components/form/checkbox/index.vue.d.ts +129 -0
  83. package/lib/components/form/checkbox/index.vue.d.ts.map +1 -0
  84. package/lib/components/form/datePicker/index.vue.d.ts +7 -0
  85. package/lib/components/form/datePicker/index.vue.d.ts.map +1 -0
  86. package/lib/components/form/index.d.ts +41 -0
  87. package/lib/components/form/index.d.ts.map +1 -0
  88. package/lib/components/form/input/index.vue.d.ts +27 -0
  89. package/lib/components/form/input/index.vue.d.ts.map +1 -0
  90. package/lib/components/form/input/inputIcon.vue.d.ts +11 -0
  91. package/lib/components/form/input/inputIcon.vue.d.ts.map +1 -0
  92. package/lib/components/form/input/inputNumber.vue.d.ts +4 -0
  93. package/lib/components/form/input/inputNumber.vue.d.ts.map +1 -0
  94. package/lib/components/form/input/inputPassword.vue.d.ts +4 -0
  95. package/lib/components/form/input/inputPassword.vue.d.ts.map +1 -0
  96. package/lib/components/form/propEditor/index.vue.d.ts +13 -0
  97. package/lib/components/form/propEditor/index.vue.d.ts.map +1 -0
  98. package/lib/components/form/radio/index.vue.d.ts +134 -0
  99. package/lib/components/form/radio/index.vue.d.ts.map +1 -0
  100. package/lib/components/form/radio/radioStatus.vue.d.ts +32 -0
  101. package/lib/components/form/radio/radioStatus.vue.d.ts.map +1 -0
  102. package/lib/components/form/rangePicker/index.vue.d.ts +17 -0
  103. package/lib/components/form/rangePicker/index.vue.d.ts.map +1 -0
  104. package/lib/components/form/select/index.vue.d.ts +143 -0
  105. package/lib/components/form/select/index.vue.d.ts.map +1 -0
  106. package/lib/components/form/switch/index.vue.d.ts +44 -0
  107. package/lib/components/form/switch/index.vue.d.ts.map +1 -0
  108. package/lib/components/form/textarea/index.vue.d.ts +4 -0
  109. package/lib/components/form/textarea/index.vue.d.ts.map +1 -0
  110. package/lib/components/form/transfer/index.vue.d.ts +39 -0
  111. package/lib/components/form/transfer/index.vue.d.ts.map +1 -0
  112. package/lib/components/form/transfer/transferTable.vue.d.ts +39 -0
  113. package/lib/components/form/transfer/transferTable.vue.d.ts.map +1 -0
  114. package/lib/components/form/treeSelect/index.vue.d.ts +39 -0
  115. package/lib/components/form/treeSelect/index.vue.d.ts.map +1 -0
  116. package/lib/components/form/upload/uploadList.vue.d.ts +477 -0
  117. package/lib/components/form/upload/uploadList.vue.d.ts.map +1 -0
  118. package/lib/components/index.d.ts +9 -0
  119. package/lib/components/index.d.ts.map +1 -0
  120. package/lib/components/layout/breadcrumb/index.vue.d.ts +4 -0
  121. package/lib/components/layout/breadcrumb/index.vue.d.ts.map +1 -0
  122. package/lib/components/layout/content/index.vue.d.ts +23 -0
  123. package/lib/components/layout/content/index.vue.d.ts.map +1 -0
  124. package/lib/components/layout/datetime/index.vue.d.ts +4 -0
  125. package/lib/components/layout/datetime/index.vue.d.ts.map +1 -0
  126. package/lib/components/layout/header/headerExits.vue.d.ts +4 -0
  127. package/lib/components/layout/header/headerExits.vue.d.ts.map +1 -0
  128. package/lib/components/layout/header/index.vue.d.ts +4 -0
  129. package/lib/components/layout/header/index.vue.d.ts.map +1 -0
  130. package/lib/components/layout/index.d.ts +17 -0
  131. package/lib/components/layout/index.d.ts.map +1 -0
  132. package/lib/components/layout/menu/index.vue.d.ts +7 -0
  133. package/lib/components/layout/menu/index.vue.d.ts.map +1 -0
  134. package/lib/components/layout/menu/menuTabs.vue.d.ts +4 -0
  135. package/lib/components/layout/menu/menuTabs.vue.d.ts.map +1 -0
  136. package/lib/components/layout/page/basicLayout.vue.d.ts +7 -0
  137. package/lib/components/layout/page/basicLayout.vue.d.ts.map +1 -0
  138. package/lib/es/AceEditor/index.js +168 -0
  139. package/lib/es/BasicLayout/index.js +4 -0
  140. package/lib/es/Error403/index.js +4 -0
  141. package/lib/es/Error404/index.js +4 -0
  142. package/lib/es/ExcelForm/index.js +5 -0
  143. package/lib/es/UploadForm/index.js +5 -0
  144. package/lib/index.d.ts +2 -0
  145. package/lib/webui.css +1 -0
  146. package/lib/webui.es.js +3349 -0
  147. package/package.json +66 -0
  148. package/plugins/vite-plugin-auto-generate-vue.ts +105 -0
  149. package/postcss.config.ts +6 -0
  150. package/src/assets/global.css +9 -0
  151. package/src/components/common/button/index.vue +126 -0
  152. package/src/components/common/icon/appicon.vue +28 -0
  153. package/src/components/common/icon/fullscreen.vue +13 -0
  154. package/src/components/common/icon/helper.vue +30 -0
  155. package/src/components/common/icon/index.vue +426 -0
  156. package/src/components/common/icon/layoutIcon.vue +33 -0
  157. package/src/components/common/icon/projectIcon.vue +41 -0
  158. package/src/components/common/icon/toolIcon.vue +33 -0
  159. package/src/components/common/index.ts +19 -0
  160. package/src/components/common/tooltip/index.vue +25 -0
  161. package/src/components/content/dialog/excelForm.vue +479 -0
  162. package/src/components/content/dialog/index.vue +149 -0
  163. package/src/components/content/dialog/uploadForm.vue +228 -0
  164. package/src/components/content/drawer/index.vue +93 -0
  165. package/src/components/content/form/formItem.vue +76 -0
  166. package/src/components/content/form/index.vue +48 -0
  167. package/src/components/content/index.ts +32 -0
  168. package/src/components/content/search/index.vue +135 -0
  169. package/src/components/content/search/searchItem.vue +52 -0
  170. package/src/components/content/table/index.vue +215 -0
  171. package/src/components/content/table/tableOperate.vue +131 -0
  172. package/src/components/content/toolbar/icontool.vue +151 -0
  173. package/src/components/content/toolbar/index.vue +107 -0
  174. package/src/components/content/tree/index.vue +140 -0
  175. package/src/components/error/error403.vue +14 -0
  176. package/src/components/error/error404.vue +14 -0
  177. package/src/components/form/aceEditor/aceConfig.ts +90 -0
  178. package/src/components/form/aceEditor/index.vue +175 -0
  179. package/src/components/form/autoComplete/index.vue +171 -0
  180. package/src/components/form/cascader/index.vue +110 -0
  181. package/src/components/form/checkbox/index.vue +108 -0
  182. package/src/components/form/datePicker/index.vue +29 -0
  183. package/src/components/form/index.ts +54 -0
  184. package/src/components/form/input/index.vue +70 -0
  185. package/src/components/form/input/inputIcon.vue +39 -0
  186. package/src/components/form/input/inputNumber.vue +23 -0
  187. package/src/components/form/input/inputPassword.vue +22 -0
  188. package/src/components/form/propEditor/index.vue +81 -0
  189. package/src/components/form/radio/index.vue +132 -0
  190. package/src/components/form/radio/radioStatus.vue +42 -0
  191. package/src/components/form/rangePicker/index.vue +64 -0
  192. package/src/components/form/select/index.vue +186 -0
  193. package/src/components/form/switch/index.vue +58 -0
  194. package/src/components/form/textarea/index.vue +23 -0
  195. package/src/components/form/transfer/index.vue +95 -0
  196. package/src/components/form/transfer/transferTable.vue +124 -0
  197. package/src/components/form/treeSelect/index.vue +108 -0
  198. package/src/components/form/upload/uploadList.vue +235 -0
  199. package/src/components/index.ts +97 -0
  200. package/src/components/layout/breadcrumb/index.vue +38 -0
  201. package/src/components/layout/content/index.vue +28 -0
  202. package/src/components/layout/datetime/index.vue +16 -0
  203. package/src/components/layout/header/headerExits.vue +28 -0
  204. package/src/components/layout/header/index.vue +43 -0
  205. package/src/components/layout/index.ts +16 -0
  206. package/src/components/layout/menu/index.vue +64 -0
  207. package/src/components/layout/menu/menuTabs.vue +56 -0
  208. package/src/components/layout/page/basicLayout.vue +67 -0
  209. package/src/vite-env.d.ts +8 -0
  210. package/tailwind.config.ts +11 -0
  211. package/tsconfig.json +53 -0
  212. package/vite.config.ts +117 -0
  213. package//344/273/243/347/240/201/350/247/204/350/214/203/345/217/212/351/243/216/346/240/274/346/214/207/345/215/227.md +116 -0
@@ -0,0 +1,228 @@
1
+ <script setup lang="ts">
2
+ import { watch, ref, onMounted } from 'vue';
3
+ import { Button } from '../../common';
4
+ import { Modal, Space } from 'ant-design-vue';
5
+ import { AsyncUploader, EditorControl, GridControl, gridRowUpdate } from '@skyfox2000/webbase';
6
+ import { AnyData, ApiResponse, IUrlInfo, ResStatus } from '@skyfox2000/fapi';
7
+ import { UploadList } from '../../form';
8
+ import { UploadFile } from '@skyfox2000/webbase';
9
+ import message from 'vue-m-message';
10
+ import { UploadStatus } from '@skyfox2000/webbase';
11
+
12
+ const props = defineProps<{
13
+ /**
14
+ * #### 使用模式
15
+ * - Row 数据行
16
+ * - Page 页面
17
+ */
18
+ mode: 'Row' | 'Page';
19
+ /**
20
+ * 文件后缀限制
21
+ */
22
+ fileExt?: string[];
23
+ /**
24
+ * 表格控制器
25
+ */
26
+ gridCtrl: GridControl<AnyData>;
27
+ /**
28
+ * 最大文件数
29
+ * 默认1个
30
+ */
31
+ maxCount?: number;
32
+ /**
33
+ * 并发上传文件数
34
+ * 默认3个
35
+ */
36
+ maxConcurrent?: number;
37
+ /**
38
+ * 弹窗控制器
39
+ */
40
+ uploadForm: EditorControl<AnyData>;
41
+ /**
42
+ * 上传地址和参数
43
+ */
44
+ uploadUrl?: IUrlInfo;
45
+ /**
46
+ * 下载地址和参数
47
+ */
48
+ downloadUrl?: IUrlInfo;
49
+ /**
50
+ * 部分错误上传是否继续保存
51
+ */
52
+ continueOnError?: boolean;
53
+ }>();
54
+
55
+ const uploadFormCtrl = props.uploadForm;
56
+ const open = ref<boolean>(false);
57
+
58
+ const maxCount = props.maxCount ?? 1;
59
+ const maxConcurrent = props.maxConcurrent ?? 3;
60
+
61
+ const fileList = ref<UploadFile[]>([]);
62
+ const emit = defineEmits<{
63
+ /**
64
+ * 显示预处理
65
+ */
66
+ 'before:file-list': [EditorControl<AnyData>, UploadFile[]];
67
+ /**
68
+ * 上传前预处理
69
+ */
70
+ 'before:upload': [UploadFile[]];
71
+ /**
72
+ * 上传结束,处理上传后的文件
73
+ */
74
+ 'after:upload': [UploadFile[]];
75
+ }>();
76
+
77
+ watch(
78
+ () => uploadFormCtrl.visible.value,
79
+ () => {
80
+ open.value = uploadFormCtrl.visible.value;
81
+ },
82
+ );
83
+ const uploadUrl = ref(props.uploadUrl);
84
+ const downloadUrl = ref(props.downloadUrl);
85
+
86
+ const dialogUpload = async () => {
87
+ const url = uploadUrl.value;
88
+ if (!url) {
89
+ message.error('未配置文件上传地址!');
90
+ return;
91
+ }
92
+
93
+ emit('before:upload', fileList.value);
94
+ const uploader = new AsyncUploader(url, maxConcurrent);
95
+
96
+ uploadFormCtrl.isFormLoading.value = true;
97
+ try {
98
+ if (fileList.value.length === 0) {
99
+ message.warning('请选择上传的文件!');
100
+ return;
101
+ }
102
+
103
+ // 开始上传文件
104
+ await uploader.uploadFiles(
105
+ fileList.value,
106
+ (_) => { },
107
+ (files) => {
108
+ uploadFormCtrl.isFormLoading.value = false;
109
+ let err_count = 0;
110
+ for (const file of files) {
111
+ if (file.status === UploadStatus.Error) {
112
+ err_count++;
113
+ }
114
+ }
115
+ if (!err_count) {
116
+ message.success('全部文件上传成功!');
117
+ emit('after:upload', files);
118
+ dialogSave();
119
+ } else if (err_count < files.length) {
120
+ if (props.continueOnError) {
121
+ message.error('上传结束,部分文件上传失败!');
122
+ message.warning('保存上传成功的文件!');
123
+ emit('after:upload', files);
124
+ dialogSave();
125
+ } else {
126
+ message.error('上传结束,部分文件上传失败,取消保存!');
127
+ }
128
+ } else message.error('上传结束,所有文件上传失败!');
129
+ },
130
+ );
131
+ } catch (error) {
132
+ uploadFormCtrl.isFormLoading.value = false;
133
+ console.error('上传错误:', error);
134
+ message.error('上传错误,请稍后再试!');
135
+ emit('after:upload', fileList.value);
136
+ }
137
+ };
138
+
139
+ const dialogSave = async () => {
140
+ switch (props.mode) {
141
+ case 'Row':
142
+ if (uploadFormCtrl.formData.value) {
143
+ // 仅修改上传相关字段
144
+ const result: ApiResponse<any> = await gridRowUpdate(props.gridCtrl, uploadFormCtrl.formData.value);
145
+ if (result.status === ResStatus.SUCCESS) {
146
+ uploadFormCtrl.visible.value = false;
147
+ }
148
+ }
149
+ break;
150
+ case 'Page':
151
+ break;
152
+ }
153
+ };
154
+
155
+ onMounted(() => {
156
+ const pageCtrl = props.gridCtrl.page;
157
+ uploadUrl.value = uploadUrl.value ?? pageCtrl.urls.upload;
158
+ downloadUrl.value = downloadUrl.value ?? pageCtrl.urls.download;
159
+ if (!uploadUrl.value) {
160
+ message.error('未配置文件上传地址!');
161
+ return;
162
+ }
163
+ if (!uploadUrl.value.api) uploadUrl.value.api = pageCtrl.api;
164
+ if (uploadUrl.value.authorize === undefined) uploadUrl.value.authorize = pageCtrl.authorize;
165
+
166
+ if (!downloadUrl.value) {
167
+ message.error('未配置文件下载地址!');
168
+ return;
169
+ }
170
+ if (!downloadUrl.value.api) downloadUrl.value.api = pageCtrl.api;
171
+ if (downloadUrl.value.authorize === undefined) downloadUrl.value.authorize = pageCtrl.authorize;
172
+
173
+ for (const key in uploadFormCtrl.formData.value) {
174
+ if (props.gridCtrl.rowData.value) uploadFormCtrl.formData.value[key] = props.gridCtrl.rowData.value[key];
175
+ }
176
+
177
+ const list: UploadFile[] = [];
178
+ emit('before:file-list', uploadFormCtrl, list);
179
+ fileList.value.push(...list);
180
+ open.value = uploadFormCtrl.visible.value;
181
+ });
182
+
183
+ const dialogClose = () => {
184
+ uploadFormCtrl.visible.value = false;
185
+ };
186
+ </script>
187
+ <template>
188
+ <Modal title="文件上传" v-model:open="open"
189
+ :wrapClassName="'modal mx-auto ' + ($attrs.width ? 'w-[' + $attrs.width + ']' : 'w-[430px]')"
190
+ @close="dialogClose">
191
+ <UploadList v-model:file-list="fileList" :download-url="downloadUrl!" :max-count="maxCount" :file-ext="fileExt" />
192
+ <template #footer>
193
+ <Space>
194
+ <Button @click="dialogClose">取消</Button>
195
+ <Button @click="dialogUpload" type="primary" :loading="uploadFormCtrl.isFormSaving.value">
196
+ 上传文件并保存
197
+ </Button>
198
+ </Space>
199
+ </template>
200
+ </Modal>
201
+ </template>
202
+ <style>
203
+ .modal {
204
+ .ant-modal-content {
205
+ padding: 16px;
206
+ }
207
+ }
208
+
209
+ .full-modal {
210
+ .ant-modal {
211
+ width: 100% !important;
212
+ max-width: 100%;
213
+ top: 0;
214
+ padding-bottom: 0;
215
+ margin: 0;
216
+ }
217
+
218
+ .ant-modal-content {
219
+ display: flex;
220
+ flex-direction: column;
221
+ height: calc(100vh);
222
+ }
223
+
224
+ .ant-modal-body {
225
+ flex: 1;
226
+ }
227
+ }
228
+ </style>
@@ -0,0 +1,93 @@
1
+ <script setup lang="ts">
2
+ import { ref, watch, onMounted, provide } from 'vue';
3
+ import { Button } from '../../common';
4
+ import { Drawer, Space, theme } from 'ant-design-vue';
5
+ const { useToken } = theme;
6
+ const { token } = useToken();
7
+ import { EditorControl, onFormSave, onFormSaveAs, onFormClose, ProviderKeys } from '@skyfox2000/webbase';
8
+ import { AnyData } from '@skyfox2000/fapi';
9
+ import { ToolIcon } from '../../common';
10
+
11
+ const open = ref<boolean>(false);
12
+
13
+ // interface RuleItem {
14
+ // key: string[]; // 使用字符串数组来表示嵌套属性的路径
15
+ // validate: (value: any) => boolean; //
16
+ // message: string
17
+ // }
18
+
19
+ const props = defineProps<{
20
+ /**
21
+ * 确认按钮文字,空字符串则不显示
22
+ */
23
+ saveText?: string;
24
+ /**
25
+ * 另存为按钮文字,空字符串则不显示
26
+ */
27
+ saveAsText?: string;
28
+ /**
29
+ * 取消按钮文字,空字符则不显示
30
+ */
31
+ cancelText?: string;
32
+ /**
33
+ * 保存数据请求配置
34
+ */
35
+ editorCtrl: EditorControl<AnyData>;
36
+ }>();
37
+
38
+ const editorCtrl = props.editorCtrl;
39
+ provide(ProviderKeys.EditorControl, editorCtrl);
40
+
41
+ watch(
42
+ () => editorCtrl.visible.value,
43
+ (newVal) => {
44
+ open.value = newVal ?? false;
45
+ },
46
+ );
47
+
48
+ onMounted(() => {
49
+ open.value = editorCtrl.visible.value ?? false;
50
+ });
51
+
52
+ const drawerClose = () => {
53
+ onFormClose(editorCtrl);
54
+ };
55
+ </script>
56
+ <template>
57
+ <Drawer v-model:open="open" :get-container="false" :closable="false" :header-style="{
58
+ height: '40px',
59
+ padding: '10px 6px 10px 16px',
60
+ backgroundColor: token.colorBgLayout,
61
+ }" :body-style="{
62
+ padding: '10px 16px',
63
+ }" :footer-style="{
64
+ textAlign: 'right',
65
+ }" :style="{
66
+ position: 'absolute',
67
+ boxShadow: 'rgba(0, 0, 0, 0.3) -2px 0px 8px',
68
+ }" width="420px" @close="drawerClose">
69
+ <template #extra>
70
+ <div class="hover:bg-gray-200 w-[24px] h-[24px] rounded-md">
71
+ <ToolIcon class="top-[-2px] left-[2px] w-6 h-6" icon="icon-new" :angle="45" fontsize="24px" clickable
72
+ color="#666" :position="[0, 0]" @click="() => onFormClose(editorCtrl)" />
73
+ </div>
74
+ </template>
75
+ <template #default>
76
+ <slot></slot>
77
+ </template>
78
+ <template #footer>
79
+ <Space>
80
+ <Button @click="() => onFormClose(editorCtrl)" v-if="cancelText !== ''">{{ cancelText ?? '取消' }}</Button>
81
+ <Button @click="() => onFormSaveAs(editorCtrl)"
82
+ v-if="saveAsText !== '' && editorCtrl.saveAsBtnVisible !== false" type="primary"
83
+ :loading="editorCtrl.isFormSaving.value">
84
+ {{ saveAsText ?? '另存为' }}
85
+ </Button>
86
+ <Button @click="() => onFormSave(editorCtrl)" v-if="saveText !== '' && editorCtrl.saveBtnVisible !== false"
87
+ type="primary" :loading="editorCtrl.isFormSaving.value">
88
+ {{ saveText ?? '保存' }}
89
+ </Button>
90
+ </Space>
91
+ </template>
92
+ </Drawer>
93
+ </template>
@@ -0,0 +1,76 @@
1
+ <script setup lang="ts">
2
+ import { EditorControl, ProviderKeys, useFormItemFactory } from '@skyfox2000/webbase';
3
+ import { FormItem } from 'ant-design-vue';
4
+ import { Helper } from '../../common';
5
+ import { inject, ref, useAttrs } from 'vue';
6
+ import { AnyData } from '@skyfox2000/fapi';
7
+
8
+ const props = defineProps<{
9
+ /**
10
+ * 标签文字
11
+ */
12
+ label?: string;
13
+ /**
14
+ * 验证规则
15
+ */
16
+ rule?: string;
17
+ /**
18
+ * 帮助文字
19
+ */
20
+ helper?: string;
21
+ /**
22
+ * 宽度
23
+ */
24
+ width?: string;
25
+ }>();
26
+
27
+ // 关闭自动继承属性到根元素
28
+ defineOptions({
29
+ inheritAttrs: false,
30
+ });
31
+ const attrs = useAttrs(); // 手动获取 $attrs
32
+
33
+ const editorCtrl = inject(ProviderKeys.EditorControl, undefined) as EditorControl<AnyData> | undefined;
34
+ const errInfo = useFormItemFactory(props, editorCtrl);
35
+
36
+ const visible = ref(false);
37
+ setTimeout(() => {
38
+ // 延迟显示,提高性能
39
+ visible.value = true;
40
+ }, 30);
41
+
42
+ // 参考代码
43
+ // this.$parent.$el.scrollIntoView({
44
+ // //滚动到指定节点
45
+ // block: "center", //值有start,center,end,nearest,当前显示在视图区域中间
46
+ // behavior: "smooth" //值有auto、instant,smooth,缓动动画(当前是慢速的)
47
+ // });
48
+ </script>
49
+ <template>
50
+ <div :class="['w-full relative mb-1', width]">
51
+ <FormItem
52
+ v-if="visible"
53
+ :required="!!rule && editorCtrl?.formRules?.value?.[rule]?.required"
54
+ class="!w-[95%] relative"
55
+ v-bind="attrs"
56
+ :class="[rule ? '' : 'mb-3']"
57
+ >
58
+ <template #label>
59
+ <span :class="[errInfo.errClass ? 'text-[#ff4d4f]' : '', 'w-full']"> {{ label }}</span>
60
+ </template>
61
+ <div class="w-full flex items-center">
62
+ <div class="flex-grow">
63
+ <slot></slot>
64
+ </div>
65
+ <div class="w-8 mt-[-2px]">
66
+ <slot name="helper">
67
+ <Helper v-if="helper" :text="helper" />
68
+ </slot>
69
+ </div>
70
+ </div>
71
+ </FormItem>
72
+ <span class="absolute bottom-[3px] left-[85px] text-[12px] text-[#ff4d4fcc] block" v-if="errInfo.errClass">
73
+ {{ errInfo.msg }}
74
+ </span>
75
+ </div>
76
+ </template>
@@ -0,0 +1,48 @@
1
+ <script lang="ts" setup>
2
+ import { EditorControl, ProviderKeys, onFormSave } from '@skyfox2000/webbase';
3
+ import { AnyData } from '@skyfox2000/fapi';
4
+ import { Form } from 'ant-design-vue';
5
+ import { inject } from 'vue';
6
+ // 使用以下统一控制表单显示
7
+ // :label-col="{ flex: '60px' }"
8
+ // :wrapper-col="{ flex: '200px' }"
9
+ // 单独项使用FormItem控制
10
+ const props = defineProps<{
11
+ /**
12
+ * 快速配置表单标签宽度
13
+ */
14
+ labelWidth?: string;
15
+ /**
16
+ * 快速配置表单项宽度
17
+ */
18
+ wrapperWidth?: string;
19
+ /**
20
+ * 表单配置信息
21
+ */
22
+ editorCtrl?: EditorControl<AnyData>;
23
+ }>();
24
+
25
+ const editorCtrl =
26
+ props.editorCtrl ?? (inject(ProviderKeys.EditorControl, undefined) as EditorControl<AnyData> | undefined);
27
+ </script>
28
+ <template>
29
+ <Form
30
+ :label-col="{ flex: props.labelWidth ?? '85px' }"
31
+ :wrapper-col="{
32
+ flex: props.wrapperWidth ?? '1',
33
+ }"
34
+ :style="{
35
+ display: 'flex',
36
+ flexWrap: 'wrap',
37
+ }"
38
+ v-submit="
39
+ () => {
40
+ if (editorCtrl) {
41
+ onFormSave(editorCtrl);
42
+ }
43
+ }
44
+ "
45
+ >
46
+ <slot></slot>
47
+ </Form>
48
+ </template>
@@ -0,0 +1,32 @@
1
+ import Dialog from './dialog/index.vue';
2
+ export { Dialog };
3
+ import UploadForm from './dialog/uploadForm.vue';
4
+ export { UploadForm };
5
+ import ExcelForm from './dialog/excelForm.vue';
6
+ export { ExcelForm };
7
+
8
+ import Drawer from './drawer/index.vue';
9
+ export { Drawer };
10
+
11
+ import Form from './form/index.vue';
12
+ export { Form };
13
+ import FormItem from './form/formItem.vue';
14
+ export { FormItem };
15
+
16
+ import Search from './search/index.vue';
17
+ export { Search };
18
+ import SearchItem from './search/searchItem.vue';
19
+ export { SearchItem };
20
+
21
+ import Table from './table/index.vue';
22
+ export { Table };
23
+ import TableOperate from './table/tableOperate.vue';
24
+ export { TableOperate };
25
+
26
+ import Toolbar from './toolbar/index.vue';
27
+ export { Toolbar };
28
+ import Icontool from './toolbar/icontool.vue';
29
+ export { Icontool };
30
+
31
+ import Tree from './tree/index.vue';
32
+ export { Tree };
@@ -0,0 +1,135 @@
1
+ <script lang="ts" setup>
2
+ import { onMounted, ref, watch, useSlots, VNode } from 'vue';
3
+ import { Form, Space } from 'ant-design-vue';
4
+ import SearchItem from './searchItem.vue';
5
+ import { Button } from '../../common';
6
+ import { GridControl } from '@skyfox2000/webbase';
7
+ import { AnyData } from '@skyfox2000/fapi';
8
+
9
+ /**
10
+ * 搜索表单BUG
11
+ * 添加ref="searchForm" 后打包报错
12
+ */
13
+ // ref="searchForm"
14
+ // The inferred type of '__VLS_template' cannot be named without a reference to '.pnpm/vue-types@3.0.2_vue@3.5.16_typescript@5.8.3_/node_modules/vue-types'. This is likely not portable. A type annotation is necessary.
15
+ // 225 function __VLS_template() {
16
+ //
17
+ //
18
+
19
+ // 使用以下统一控制表单显示
20
+ // :label-col="{ flex: '60px' }"
21
+ // :wrapper-col="{ flex: '200px' }"
22
+ // 单独项使用FormItem控制
23
+ const props = defineProps<{
24
+ /**
25
+ * 搜索条件
26
+ */
27
+ search: Record<string, any>;
28
+ /**
29
+ * 表格控制对象
30
+ */
31
+ gridCtrl: GridControl<AnyData>;
32
+ }>();
33
+
34
+ // const pageData = props.gridData.page;
35
+
36
+ const emits = defineEmits<{
37
+ (e: 'update:search', val: Record<string, any>): void;
38
+ }>();
39
+
40
+ /**
41
+ * 搜索按钮前的占位数量,1或者2
42
+ */
43
+ const holderSize = ref(0);
44
+ const defaultSlots = ref(0);
45
+ const controlSlots = ref(0);
46
+ const getSlotLen = (items: VNode[]): number => {
47
+ let count = 0;
48
+ for (let i = 0; i < items.length; i++) {
49
+ if (typeof items[i].type === 'object') count++;
50
+ }
51
+ return count;
52
+ };
53
+ const slots = useSlots();
54
+ const updateHolderSize = () => {
55
+ defaultSlots.value = 0;
56
+ controlSlots.value = 0;
57
+ if (slots.default) defaultSlots.value = getSlotLen(slots.default({}));
58
+ if (props.gridCtrl.searchBar && slots.control) controlSlots.value = getSlotLen(slots.control({}));
59
+
60
+ holderSize.value = 2 - ((defaultSlots.value + controlSlots.value) % 3);
61
+ };
62
+
63
+ watch(
64
+ () => props.gridCtrl.searchBar,
65
+ () => {
66
+ updateHolderSize();
67
+ },
68
+ );
69
+
70
+ const defaultData: Record<string, any> = JSON.parse(JSON.stringify(props.search));
71
+
72
+ onMounted(() => {
73
+ updateHolderSize();
74
+ let search = { ...props.search };
75
+ props.gridCtrl.gridQuery = {
76
+ ...props.gridCtrl.gridQuery,
77
+ Query: {
78
+ ...props.gridCtrl.gridQuery?.Query,
79
+ ...search,
80
+ },
81
+ };
82
+ });
83
+
84
+ const onSearch = () => {
85
+ let search = { ...props.search };
86
+ props.gridCtrl.gridQuery = {
87
+ ...props.gridCtrl.gridQuery,
88
+ Query: {
89
+ ...props.gridCtrl.gridQuery?.Query,
90
+ ...search,
91
+ },
92
+ };
93
+ props.gridCtrl.reload.value = true;
94
+ };
95
+
96
+ const onReset = () => {
97
+ const data = JSON.parse(JSON.stringify(defaultData));
98
+ for (const key in props.search) {
99
+ if (data[key] === undefined) {
100
+ data[key] = undefined;
101
+ }
102
+ }
103
+ emits('update:search', data);
104
+ };
105
+ </script>
106
+ <template>
107
+ <Form
108
+ v-if="defaultSlots + controlSlots > 0"
109
+ :label-col="{ flex: '60px' }"
110
+ :style="{
111
+ flexWrap: 'wrap',
112
+ borderBottom: '1px solid #e9e9e9',
113
+ }"
114
+ class="flex mb-[10px]"
115
+ v-submit="onSearch"
116
+ >
117
+ <!-- 默认插槽 -->
118
+ <slot></slot>
119
+ <!-- 受控插槽 -->
120
+ <slot name="control" v-if="gridCtrl.searchBar"></slot>
121
+ <!-- 表单操作按钮 占位数量 -->
122
+ <SearchItem class="w-1/3" v-if="holderSize >= 1"> </SearchItem>
123
+ <SearchItem class="w-1/3" v-if="holderSize >= 2"> </SearchItem>
124
+ <SearchItem
125
+ v-if="defaultSlots || gridCtrl.searchBar"
126
+ class="w-1/3 flex justify-end text-right pr-5"
127
+ :wrapper-col="{ flex: 'auto' }"
128
+ >
129
+ <Space>
130
+ <Button type="primary" @click="onSearch" icon="icon-search">搜索</Button>
131
+ <Button @click="onReset" icon="icon-reset">重置</Button>
132
+ </Space>
133
+ </SearchItem>
134
+ </Form>
135
+ </template>
@@ -0,0 +1,52 @@
1
+ <script setup lang="ts">
2
+ import { inject, useAttrs } from 'vue';
3
+ import { ProviderKeys, EditorControl, useFormItemFactory } from '@skyfox2000/webbase';
4
+ import { FormItem } from 'ant-design-vue';
5
+ import { AnyData } from '@skyfox2000/fapi';
6
+
7
+ const props = defineProps<{
8
+ /**
9
+ * 标签文字
10
+ */
11
+ label?: string;
12
+ /**
13
+ * 宽度
14
+ */
15
+ width?: string;
16
+ /**
17
+ * 验证规则
18
+ */
19
+ rule?: string;
20
+ }>();
21
+ // 关闭自动继承属性到根元素
22
+ defineOptions({
23
+ inheritAttrs: false,
24
+ });
25
+ const attrs = useAttrs(); // 手动获取 $attrs
26
+
27
+ const editorCtrl = inject(ProviderKeys.EditorControl, undefined) as EditorControl<AnyData> | undefined;
28
+ const errInfo = useFormItemFactory(props, editorCtrl);
29
+ </script>
30
+ <template>
31
+ <div class="w-1/3 relative mb-1">
32
+ <FormItem
33
+ :required="rule !== undefined"
34
+ class="w-[90%] relative"
35
+ v-bind="attrs"
36
+ :class="[rule ? '' : 'mb-3', width]"
37
+ :labelCol="{ span: 6 }"
38
+ >
39
+ <template #label v-if="label">
40
+ <span :class="[errInfo.errClass ? 'text-[#ff4d4f]' : '', 'w-full']"> {{ label }}</span>
41
+ </template>
42
+ <div class="flex items-center">
43
+ <div class="flex-grow pl-1">
44
+ <slot></slot>
45
+ </div>
46
+ </div>
47
+ </FormItem>
48
+ <span class="absolute bottom-[3px] left-[85px] text-[12px] text-[#ff4d4fcc] block" v-if="errInfo.msg">
49
+ {{ errInfo.msg }}
50
+ </span>
51
+ </div>
52
+ </template>