@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,42 @@
1
+ <script setup lang="ts">
2
+ import { ref, PropType } from 'vue';
3
+ import Radio from './index.vue';
4
+ import { OPTIONS } from '@skyfox2000/webbase';
5
+
6
+ const props = defineProps({
7
+ /**
8
+ * 数据源OPTIONS的key
9
+ */
10
+ dataKey: {
11
+ type: String as PropType<string>,
12
+ default: 'EnableDisable',
13
+ },
14
+ /**
15
+ * 是否显示全部选项
16
+ */
17
+ all: {
18
+ type: Boolean as PropType<boolean>,
19
+ required: false,
20
+ },
21
+ /**
22
+ * 自定义全部选项的值
23
+ * 如果all为true,则显示全部选项
24
+ * 未设置allValue,则默认[0, 1]
25
+ */
26
+ allValue: {
27
+ type: [String, Number, Array] as PropType<string | number | string[] | number[]>,
28
+ required: false,
29
+ },
30
+ });
31
+ const options = ref(JSON.parse(JSON.stringify(OPTIONS.getOptions(props.dataKey))));
32
+ if (props.all === true) {
33
+ options.value.unshift({
34
+ label: '全部',
35
+ value: props.allValue || [0, 1],
36
+ });
37
+ }
38
+ </script>
39
+
40
+ <template>
41
+ <Radio :data="options"></Radio>
42
+ </template>
@@ -0,0 +1,64 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue';
3
+ import { RangePicker } from 'ant-design-vue';
4
+ import locale from 'ant-design-vue/es/date-picker/locale/zh_CN';
5
+ import { useInputFactory } from '@skyfox2000/webbase';
6
+ import dayjs, { Dayjs } from 'dayjs';
7
+
8
+ const props = withDefaults(
9
+ defineProps<{
10
+ startDate?: string | null;
11
+ endDate?: string | null;
12
+ valueFormat?: string;
13
+ }>(),
14
+ {
15
+ valueFormat: 'YYYY-MM-DD',
16
+ },
17
+ );
18
+
19
+ const emit = defineEmits<{
20
+ (e: 'update:startDate', value: string | null): void;
21
+ (e: 'update:endDate', value: string | null): void;
22
+ }>();
23
+
24
+ const inputFactory = useInputFactory();
25
+ const { errInfo } = inputFactory;
26
+
27
+ const dateFormat = computed(() => props.valueFormat);
28
+ const rangeValue = computed((): [Dayjs, Dayjs] | [string, string] | undefined => {
29
+ const start = props.startDate;
30
+ const end = props.endDate;
31
+ if (!start || !end) return undefined;
32
+
33
+ try {
34
+ const startDayjs = dayjs(start);
35
+ const endDayjs = dayjs(end);
36
+ if (!startDayjs.isValid() || !endDayjs.isValid()) return undefined;
37
+ return [startDayjs, endDayjs];
38
+ } catch {
39
+ return undefined;
40
+ }
41
+ });
42
+
43
+ const handleChange = (dates: [Dayjs, Dayjs] | [string, string] | null, dateStrings: [string, string]) => {
44
+ if (!dates || !dateStrings || dateStrings.length !== 2) {
45
+ emit('update:startDate', null);
46
+ emit('update:endDate', null);
47
+ return;
48
+ }
49
+
50
+ emit('update:startDate', dateStrings[0] || null);
51
+ emit('update:endDate', dateStrings[1] || null);
52
+ };
53
+ </script>
54
+
55
+ <template>
56
+ <RangePicker
57
+ :class="errInfo?.errClass === 'error' ? ['error', '!border-red-300', 'shadow-[0_0_3px_0px_#ff4d4f]'] : ''"
58
+ class="w-full"
59
+ :locale="locale"
60
+ :value-format="dateFormat"
61
+ :value="rangeValue"
62
+ @change="handleChange"
63
+ />
64
+ </template>
@@ -0,0 +1,186 @@
1
+ <script setup lang="ts">
2
+ import { ref, onMounted, onUnmounted, watch, PropType, useAttrs } from 'vue';
3
+ import { Select, SelectOption } from 'ant-design-vue';
4
+ import {
5
+ circleLoading,
6
+ useInputFactory,
7
+ OptionCommProps,
8
+ OptionItemProps,
9
+ onOptionChanged,
10
+ loadOption,
11
+ unloadOption,
12
+ getSelectedLabels,
13
+ SelectValue,
14
+ formValidate,
15
+ OPTIONS,
16
+ isEmpty,
17
+ } from '@skyfox2000/webbase';
18
+ import { IUrlInfo } from '@skyfox2000/fapi';
19
+
20
+ type SelectValueType = string | number | string[] | number[] | null;
21
+ const props = defineProps({
22
+ ...OptionCommProps,
23
+ value: {
24
+ type: [String, Number, Array, null] as PropType<SelectValueType>,
25
+ default: undefined,
26
+ },
27
+ /**
28
+ * 自动选择第一个选项
29
+ */
30
+ selectFirst: {
31
+ type: Boolean,
32
+ default: false,
33
+ },
34
+ /**
35
+ * 数据源OPTIONS的key
36
+ */
37
+ dataKey: {
38
+ type: String as PropType<string>,
39
+ required: false,
40
+ },
41
+ /**
42
+ * 是否显示全部选项
43
+ */
44
+ all: {
45
+ type: Boolean as PropType<boolean>,
46
+ default: false,
47
+ },
48
+ /**
49
+ * 自定义全部选项的值
50
+ * 如果all为true,则显示全部选项
51
+ * 未设置allValue,则默认[0, 1]
52
+ */
53
+ allValue: {
54
+ type: [String, Number, Array] as PropType<string | number | string[] | number[]>,
55
+ required: false,
56
+ },
57
+ });
58
+
59
+ // 关闭自动继承属性到根元素
60
+ defineOptions({
61
+ inheritAttrs: false,
62
+ });
63
+ const attrs = useAttrs(); // 手动获取 $attrs
64
+
65
+ const url = ref<IUrlInfo>({
66
+ ...props.url,
67
+ url: props.url?.url || '',
68
+ fieldMap: props.fieldMap || props.url?.fieldMap,
69
+ params: props.params || props.url?.params,
70
+ loadingText: false,
71
+ });
72
+
73
+ const inputFactory = useInputFactory();
74
+ const { editorCtrl, errInfo, labelText } = inputFactory;
75
+
76
+ /// 避免类型错误
77
+ const innerValue = ref<string | number | string[] | number[] | undefined>(undefined);
78
+ const emit = defineEmits(['change', 'update:value', 'update:labels']);
79
+ inputFactory.inputEmit = emit;
80
+ /**
81
+ * 实际的选择项
82
+ */
83
+ const selectOptions = ref<OptionItemProps[]>([]);
84
+ watch(
85
+ () => selectOptions.value,
86
+ (newVal) => {
87
+ if (newVal.length > 0 && isEmpty(props.value) && props.selectFirst) {
88
+ innerValue.value = newVal[0].value;
89
+ onChanged(newVal[0].value);
90
+ } else {
91
+ // 当选项加载完成后,设置实际的 value 值
92
+ innerValue.value = props.value === null ? undefined : props.value;
93
+ }
94
+ },
95
+ );
96
+
97
+ const placeholder = ref(attrs.placeholder);
98
+ watch(
99
+ () => url.value.loading,
100
+ (newVal) => {
101
+ if (newVal) placeholder.value = '';
102
+ else if (!placeholder.value) placeholder.value = '请选择' + labelText.value;
103
+ },
104
+ { immediate: true },
105
+ );
106
+
107
+ const defaultVal = ref(props.value);
108
+ watch(
109
+ () => innerValue.value,
110
+ (newVal) => {
111
+ if (attrs.mode === 'multiple') {
112
+ if (isEmpty(newVal) && isEmpty(defaultVal.value)) {
113
+ emit('update:value', defaultVal.value);
114
+ return;
115
+ }
116
+ }
117
+ emit('update:value', newVal);
118
+ },
119
+ );
120
+
121
+ const onChanged = (value: any) => {
122
+ const selectedOptions = onOptionChanged(props, value as SelectValue, selectOptions, inputFactory);
123
+ const labels: string[] = getSelectedLabels(selectedOptions);
124
+
125
+ innerValue.value = value;
126
+ emit('update:labels', labels);
127
+ emit('change', value);
128
+
129
+ if (errInfo?.value.errClass && editorCtrl) {
130
+ /// 重新开始验证
131
+ formValidate(editorCtrl);
132
+ }
133
+ };
134
+
135
+ onMounted(() => {
136
+ if (url.value && !url.value.fieldMap) {
137
+ url.value.fieldMap = {
138
+ label: 'Name',
139
+ value: 'Id',
140
+ key: 'Id',
141
+ };
142
+ }
143
+ if (props.dataKey) {
144
+ const options = JSON.parse(JSON.stringify(OPTIONS.getOptions(props.dataKey)));
145
+ selectOptions.value = options;
146
+ } else loadOption(props.autoload, props, selectOptions, inputFactory, url.value, url.value?.params);
147
+ });
148
+
149
+ onUnmounted(() => {
150
+ unloadOption(props, inputFactory);
151
+ });
152
+ </script>
153
+
154
+ <template>
155
+ <div>
156
+ <div
157
+ v-if="props.url && props.url.loading === true"
158
+ class="absolute z-10 mt-[5px] mr-[10px] text-[#999] flex items-center"
159
+ >
160
+ <circleLoading class="text-[#555] mx-[5px] !ml-[10px] !w-4 !h-4" />
161
+ <span>数据加载中...</span>
162
+ </div>
163
+ <Select
164
+ :class="[errInfo?.errClass, 'w-full']"
165
+ v-model:value="innerValue"
166
+ :allow-clear="true"
167
+ @change="onChanged"
168
+ :placeholder="placeholder"
169
+ :label-in-value="false"
170
+ v-bind="attrs"
171
+ >
172
+ <template v-for="item in selectOptions" :key="item.value">
173
+ <SelectOption :value="item.value" v-if="item.visible !== false">
174
+ {{ item.label }}
175
+ </SelectOption>
176
+ </template>
177
+ </Select>
178
+ </div>
179
+ </template>
180
+
181
+ <style scoped>
182
+ .error :deep(.ant-select-selector) {
183
+ border-color: #ff4d4f80;
184
+ box-shadow: 0 0 3px 0 #ff4d4f;
185
+ }
186
+ </style>
@@ -0,0 +1,58 @@
1
+ <script setup lang="ts">
2
+ import { ref, onMounted, onUnmounted } from 'vue';
3
+ import { formValidate, useInputFactory, OptionItemProps, loadOption, unloadOption } from '@skyfox2000/webbase';
4
+ import { Switch } from 'ant-design-vue';
5
+ import message from 'vue-m-message';
6
+
7
+ const props = defineProps({
8
+ /**
9
+ * 选择项数据
10
+ */
11
+ data: {
12
+ type: Array<Record<string, any>>,
13
+ required: true,
14
+ },
15
+ });
16
+
17
+ /**
18
+ * 实际的选择项
19
+ */
20
+ const switchOptions = ref<OptionItemProps[]>([]);
21
+
22
+ const emit = defineEmits<{
23
+ (e: 'change', checked: boolean | string | number): void;
24
+ }>();
25
+
26
+ const { editorCtrl, errInfo } = useInputFactory();
27
+ const onChange = (checked: boolean | string | number) => {
28
+ if (errInfo?.value.errClass && editorCtrl) {
29
+ /// 重新开始验证
30
+ formValidate(editorCtrl);
31
+ }
32
+ emit('change', checked);
33
+ };
34
+ onMounted(() => {
35
+ if (!props.data || props.data.length != 2) {
36
+ console.error('Switch组件: ', props.data);
37
+ message.error('Switch组件必须有且只有两个选项');
38
+ return;
39
+ }
40
+ loadOption(false, props, switchOptions);
41
+ });
42
+
43
+ onUnmounted(() => {
44
+ unloadOption(props);
45
+ });
46
+ </script>
47
+ <template>
48
+ <Switch
49
+ v-if="switchOptions.length === 2"
50
+ :class="[errInfo?.errClass === 'error' ? 'error !border-red-300 shadow-[0_0_3px_0px_#ff4d4f]' : '', 'bg-blue-300', 'w-[58px]']"
51
+ :checkedChildren="switchOptions[0].label"
52
+ :checkedValue="switchOptions[0].value"
53
+ :unCheckedChildren="switchOptions[1].label"
54
+ :unCheckedValue="switchOptions[1].value"
55
+ @change="onChange"
56
+ v-bind="$attrs"
57
+ />
58
+ </template>
@@ -0,0 +1,23 @@
1
+ <script setup lang="ts">
2
+ import { formValidate, useInputFactory } from '@skyfox2000/webbase';
3
+ import { Textarea } from 'ant-design-vue';
4
+
5
+ const { editorCtrl, labelText, errInfo } = useInputFactory();
6
+ const onBlur = () => {
7
+ if (errInfo?.value.errClass && editorCtrl) {
8
+ /// 重新开始验证
9
+ formValidate(editorCtrl);
10
+ }
11
+ };
12
+ </script>
13
+ <template>
14
+ <Textarea
15
+ :class="errInfo?.errClass === 'error' ? ['error', '!border-red-300', 'shadow-[0_0_3px_0px_#ff4d4f]'] : ''"
16
+ :allow-clear="true"
17
+ :placeholder="'请输入' + labelText"
18
+ @blur="onBlur"
19
+ @keyup.enter.native.stop
20
+ @keydown.enter.native.stop
21
+ v-bind="$attrs"
22
+ />
23
+ </template>
@@ -0,0 +1,95 @@
1
+ <script setup lang="ts">
2
+ import { ref, onMounted, watch } from 'vue';
3
+ import { AnyControl, doQuery, formValidate, OptionItemProps, useInputFactory } from '@skyfox2000/webbase';
4
+ import { Transfer } from 'ant-design-vue';
5
+ import { IUrlInfo, ReqParams } from '@skyfox2000/fapi';
6
+ const props = defineProps<{
7
+ /**
8
+ * 是否自动加载数据
9
+ */
10
+ autoload?: boolean;
11
+ /**
12
+ * 接口地址和参数
13
+ */
14
+ url?: IUrlInfo;
15
+ /**
16
+ * 查询参数
17
+ */
18
+ params?: ReqParams;
19
+ /**
20
+ * 值
21
+ */
22
+ value?: string[];
23
+ }>();
24
+
25
+ const url = ref({ ...props.url });
26
+
27
+ const { editorCtrl, labelText, errInfo } = useInputFactory();
28
+ const emit = defineEmits(['change', 'update:value']);
29
+
30
+ const dataSource = ref<OptionItemProps[]>([]);
31
+ const targetKeys = ref<string[]>([]);
32
+ if (props.value) {
33
+ /// TODO 数据表字段是数字的话,可能存在问题
34
+ props.value.every((value) => {
35
+ targetKeys.value.push(value.toString());
36
+ });
37
+ }
38
+
39
+ watch(
40
+ () => props.value,
41
+ (newVal) => {
42
+ if (newVal) {
43
+ targetKeys.value = newVal;
44
+ }
45
+ },
46
+ );
47
+
48
+ const onChange = (nextTargetKeys: string[]) => {
49
+ emit('update:value', nextTargetKeys);
50
+ emit('change', nextTargetKeys);
51
+ targetKeys.value = nextTargetKeys;
52
+ if (errInfo?.value.errClass && editorCtrl) {
53
+ /// 重新开始验证
54
+ formValidate(editorCtrl);
55
+ }
56
+ };
57
+
58
+ onMounted(async () => {
59
+ if (url.value) {
60
+ const pageCtrl = editorCtrl?.page;
61
+ if (!url.value.api) url.value.api = pageCtrl?.api;
62
+ if (url.value.authorize === undefined) url.value.authorize = pageCtrl?.authorize;
63
+ if (props.autoload) {
64
+ const result = await doQuery<OptionItemProps[]>(editorCtrl as AnyControl, {
65
+ urlKey: 'list',
66
+ url: { ...url.value, url: url.value.url! },
67
+ loadingText: false,
68
+ params: props.params,
69
+ });
70
+ dataSource.value = (result?.data ?? []) as OptionItemProps[];
71
+ }
72
+ }
73
+ });
74
+ </script>
75
+ <template>
76
+ <Transfer
77
+ :class="errInfo?.errClass === 'error' ? ['error', '!border-red-300', 'shadow-[0_0_3px_0px_#ff4d4f]'] : ''"
78
+ :placeholder="'请输入' + labelText"
79
+ :targetKeys="targetKeys"
80
+ @change="onChange"
81
+ v-bind="$attrs"
82
+ >
83
+ <template #children="{ direction, disabled, filteredItems, onItemSelectAll, onItemSelect, selectedKeys }">
84
+ <slot
85
+ name="children"
86
+ :direction="direction"
87
+ :disabled="disabled"
88
+ :filteredItems="filteredItems"
89
+ :onItemSelectAll="onItemSelectAll"
90
+ :onItemSelect="onItemSelect"
91
+ :selectedKeys="selectedKeys"
92
+ />
93
+ </template>
94
+ </Transfer>
95
+ </template>
@@ -0,0 +1,124 @@
1
+ <script lang="ts" setup>
2
+ import Transfer from './index.vue';
3
+ import { Table } from 'ant-design-vue';
4
+ import { AnyData } from '@skyfox2000/fapi';
5
+ import { doQuery, GridControl, PrimaryKey } from '@skyfox2000/webbase';
6
+ import { onMounted, PropType, ref, watch } from 'vue';
7
+ const props = defineProps({
8
+ /**
9
+ * 是否自动加载
10
+ */
11
+ autoload: {
12
+ type: Boolean,
13
+ default: true,
14
+ },
15
+ /**
16
+ * 表格控制器
17
+ */
18
+ gridCtrl: {
19
+ type: Object as PropType<GridControl<AnyData>>,
20
+ required: true,
21
+ },
22
+ /**
23
+ * 选择结果
24
+ */
25
+ value: {
26
+ type: Array as PropType<string[]>,
27
+ default: () => [],
28
+ },
29
+ });
30
+
31
+ const emit = defineEmits(['update:value']);
32
+ const autoload = ref(props.autoload);
33
+ const targetKeys = ref<string[]>(props.value);
34
+ const primaryKey = ref(props.gridCtrl.primaryKey);
35
+
36
+ watch(
37
+ () => targetKeys.value,
38
+ (newVal) => {
39
+ emit('update:value', newVal);
40
+ },
41
+ );
42
+
43
+ watch(
44
+ () => props.value,
45
+ (newVal) => {
46
+ if (newVal) {
47
+ targetKeys.value = newVal;
48
+ }
49
+ },
50
+ );
51
+
52
+ /// 默认设置
53
+ props.gridCtrl.autoload = false;
54
+ // 禁用远程分页
55
+ props.gridCtrl.remotePage = false;
56
+ props.gridCtrl.selectable = ref(true);
57
+ props.gridCtrl.buttons = ref([]);
58
+ props.gridCtrl.tools = [];
59
+
60
+ const getRowSelection = ({ disabled, selectedKeys, onItemSelectAll, onItemSelect }: Record<string, any>) => {
61
+ return {
62
+ getCheckboxProps: (item: Record<string, string | boolean>) => ({
63
+ // 控制是否禁止
64
+ disabled: disabled || item.disabled,
65
+ }),
66
+ onSelectAll(selected: boolean, selectedRows: Record<string, PrimaryKey>[]) {
67
+ // 全选,只选中未禁用的行
68
+ const treeSelectedKeys = selectedRows
69
+ .filter((item) => !item.disabled)
70
+ .map(({ [primaryKey.value]: key }) => key);
71
+ onItemSelectAll(treeSelectedKeys, selected);
72
+ },
73
+ onSelect({ [primaryKey.value]: key }: Record<string, PrimaryKey>, selected: boolean) {
74
+ // 单行选中行
75
+ onItemSelect(key, selected);
76
+ },
77
+ selectedRowKeys: selectedKeys,
78
+ };
79
+ };
80
+
81
+ const transferData = ref<AnyData[]>([]);
82
+ onMounted(async () => {
83
+ if (autoload.value) {
84
+ const result = await doQuery<AnyData[]>(props.gridCtrl, {
85
+ urlKey: 'list',
86
+ url: { ...props.gridCtrl.gridUrl, url: props.gridCtrl.gridUrl!.url },
87
+ params: props.gridCtrl.gridQuery,
88
+ loadingText: false,
89
+ });
90
+ transferData.value = result?.data ?? [];
91
+ }
92
+ });
93
+ </script>
94
+ <template>
95
+ <Transfer :data-source="transferData" :row-key="(record: AnyData) => record[primaryKey]" v-model:value="targetKeys"
96
+ :list-style="{
97
+ width: '300px',
98
+ height: '500px',
99
+ }" :show-select-all="false" :show-search="true" :filter-option="(inputValue: string, item: AnyData) => {
100
+ for (const column of props.gridCtrl.columns.value) {
101
+ if (item[column.dataIndex].toString().indexOf(inputValue) !== -1) {
102
+ return true;
103
+ }
104
+ }
105
+ return false;
106
+ }
107
+ " v-bind="$attrs">
108
+ <template #children="{ filteredItems, onItemSelectAll, onItemSelect, selectedKeys }">
109
+ <Table :columns="gridCtrl.columns.value" :row-key="primaryKey" :row-selection="getRowSelection({
110
+ disabled: false,
111
+ selectedKeys,
112
+ onItemSelectAll,
113
+ onItemSelect,
114
+ })
115
+ " :bordered="false" size="small" :data-source="filteredItems" :scroll="{ x: 300 }" :custom-row="(record) => ({
116
+ onClick: () => {
117
+ const key = record[primaryKey];
118
+ onItemSelect(key, !selectedKeys.includes(key));
119
+ },
120
+ })
121
+ " />
122
+ </template>
123
+ </Transfer>
124
+ </template>
@@ -0,0 +1,108 @@
1
+ <script lang="ts" setup>
2
+ import { ref, watch, onMounted, PropType } from 'vue';
3
+ import { TreeSelect } from 'ant-design-vue';
4
+ import { queryTree } from '@skyfox2000/webbase';
5
+ import type { SelectValue, TreeControl, TreeNode } from '@skyfox2000/webbase';
6
+ import { useInputFactory } from '@skyfox2000/webbase';
7
+ import { fieldMapping } from '@skyfox2000/fapi';
8
+
9
+ const props = defineProps({
10
+ multiple: {
11
+ type: Boolean,
12
+ default: false,
13
+ },
14
+ treeCtrl: {
15
+ type: Object as PropType<TreeControl>,
16
+ required: true,
17
+ },
18
+ value: {
19
+ type: [String, Number, Array] as PropType<SelectValue>,
20
+ required: true,
21
+ },
22
+ });
23
+
24
+ const treeCtrl = props.treeCtrl;
25
+
26
+ const inputFactory = useInputFactory();
27
+ const { errInfo, labelText } = inputFactory;
28
+
29
+ // 定义事件
30
+ const emit = defineEmits(['change', 'update:value']);
31
+ inputFactory.inputEmit = emit;
32
+
33
+ // 树选择数据
34
+ const selectTreeData = ref<TreeNode[]>([]);
35
+ // 当前选中值
36
+ const currentValue = ref<SelectValue>();
37
+
38
+ // 监听值变化
39
+ watch(
40
+ () => props.value,
41
+ (newVal) => {
42
+ currentValue.value = newVal ?? null;
43
+ },
44
+ { immediate: true },
45
+ );
46
+
47
+ // 监听树数据变化
48
+ watch(
49
+ () => treeCtrl.data.value,
50
+ (newVal) => {
51
+ if (newVal) {
52
+ selectTreeData.value = treeCtrl.fieldMap ? fieldMapping(treeCtrl.fieldMap, newVal) : newVal;
53
+ }
54
+ },
55
+ { immediate: true },
56
+ );
57
+
58
+ // 值变化事件
59
+ const handleChange = (value: SelectValue) => {
60
+ if (props.multiple) {
61
+ currentValue.value = value ?? [];
62
+ } else {
63
+ currentValue.value = value ?? '';
64
+ }
65
+ emit('change', currentValue.value);
66
+ emit('update:value', currentValue.value);
67
+ };
68
+
69
+ // 组件挂载时加载数据
70
+ onMounted(() => {
71
+ if (!treeCtrl.fieldMap) {
72
+ treeCtrl.fieldMap = {
73
+ label: 'Name',
74
+ key: 'Id',
75
+ value: 'Id',
76
+ };
77
+ }
78
+ if (treeCtrl.data.value) {
79
+ selectTreeData.value = treeCtrl.fieldMap
80
+ ? fieldMapping(treeCtrl.fieldMap, treeCtrl.data.value)
81
+ : treeCtrl.data.value;
82
+ } else if (props.treeCtrl.autoload) {
83
+ queryTree(props.treeCtrl);
84
+ }
85
+ });
86
+ </script>
87
+
88
+ <template>
89
+ <TreeSelect
90
+ :class="[errInfo?.errClass]"
91
+ tree-line
92
+ :multiple="multiple"
93
+ :tree-default-expanded-keys="['-']"
94
+ v-model:value="currentValue"
95
+ :tree-data="selectTreeData"
96
+ :placeholder="'请选择' + labelText"
97
+ :allow-clear="true"
98
+ class="w-full"
99
+ @change="handleChange"
100
+ v-bind="$attrs"
101
+ />
102
+ </template>
103
+ <style scoped>
104
+ .error :deep(.ant-select-selector) {
105
+ border-color: #ef444480;
106
+ box-shadow: 0 0 3px 0 #ff4d4f;
107
+ }
108
+ </style>