@aoao-y33/ui 0.0.2

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 (211) hide show
  1. package/README.md +811 -0
  2. package/dist/button/components/button/button.vue.d.ts +22 -0
  3. package/dist/button/components/button/button.vue.d.ts.map +1 -0
  4. package/dist/button/components/button/index.d.ts +3 -0
  5. package/dist/button/components/button/index.d.ts.map +1 -0
  6. package/dist/button/components/button/props.d.ts +21 -0
  7. package/dist/button/components/button/props.d.ts.map +1 -0
  8. package/dist/button/components/fields/index.d.ts +2 -0
  9. package/dist/button/components/fields/index.d.ts.map +1 -0
  10. package/dist/button/hoc/index.d.ts +2 -0
  11. package/dist/button/hoc/index.d.ts.map +1 -0
  12. package/dist/button/hoc/useButton.d.ts +19 -0
  13. package/dist/button/hoc/useButton.d.ts.map +1 -0
  14. package/dist/button/index.d.ts +5 -0
  15. package/dist/button/index.d.ts.map +1 -0
  16. package/dist/button/utils/index.d.ts +4 -0
  17. package/dist/button/utils/index.d.ts.map +1 -0
  18. package/dist/common/index.d.ts +2 -0
  19. package/dist/common/index.d.ts.map +1 -0
  20. package/dist/common/utils/iconUtils.d.ts +2 -0
  21. package/dist/common/utils/iconUtils.d.ts.map +1 -0
  22. package/dist/common/utils/index.d.ts +2 -0
  23. package/dist/common/utils/index.d.ts.map +1 -0
  24. package/dist/form/components/fields/index.d.ts +2 -0
  25. package/dist/form/components/fields/index.d.ts.map +1 -0
  26. package/dist/form/components/form/form.vue.d.ts +42 -0
  27. package/dist/form/components/form/form.vue.d.ts.map +1 -0
  28. package/dist/form/components/form/index.d.ts +90 -0
  29. package/dist/form/components/form/index.d.ts.map +1 -0
  30. package/dist/form/components/form/props.d.ts +21 -0
  31. package/dist/form/components/form/props.d.ts.map +1 -0
  32. package/dist/form/components/form-item/form-item.vue.d.ts +19 -0
  33. package/dist/form/components/form-item/form-item.vue.d.ts.map +1 -0
  34. package/dist/form/components/form-item/index.d.ts +31 -0
  35. package/dist/form/components/form-item/index.d.ts.map +1 -0
  36. package/dist/form/components/form-item/props.d.ts +14 -0
  37. package/dist/form/components/form-item/props.d.ts.map +1 -0
  38. package/dist/form/hoc/index.d.ts +4 -0
  39. package/dist/form/hoc/index.d.ts.map +1 -0
  40. package/dist/form/hoc/useForm.d.ts +13 -0
  41. package/dist/form/hoc/useForm.d.ts.map +1 -0
  42. package/dist/form/hoc/useFormExpose.d.ts +24 -0
  43. package/dist/form/hoc/useFormExpose.d.ts.map +1 -0
  44. package/dist/form/hoc/useFormFetch.d.ts +25 -0
  45. package/dist/form/hoc/useFormFetch.d.ts.map +1 -0
  46. package/dist/form/index.d.ts +6 -0
  47. package/dist/form/index.d.ts.map +1 -0
  48. package/dist/form/utils/index.d.ts +9 -0
  49. package/dist/form/utils/index.d.ts.map +1 -0
  50. package/dist/global.d.ts +33 -0
  51. package/dist/global.d.ts.map +1 -0
  52. package/dist/index.css +3 -0
  53. package/dist/index.d.ts +12 -0
  54. package/dist/index.d.ts.map +1 -0
  55. package/dist/index.js +38948 -0
  56. package/dist/layout/components/fields/basic/basic.vue.d.ts +20 -0
  57. package/dist/layout/components/fields/basic/basic.vue.d.ts.map +1 -0
  58. package/dist/layout/components/fields/index.d.ts +2 -0
  59. package/dist/layout/components/fields/index.d.ts.map +1 -0
  60. package/dist/layout/components/fields/side/side.vue.d.ts +20 -0
  61. package/dist/layout/components/fields/side/side.vue.d.ts.map +1 -0
  62. package/dist/layout/components/fields/top/top.vue.d.ts +18 -0
  63. package/dist/layout/components/fields/top/top.vue.d.ts.map +1 -0
  64. package/dist/layout/components/layout/index.d.ts +22 -0
  65. package/dist/layout/components/layout/index.d.ts.map +1 -0
  66. package/dist/layout/components/layout/layout.vue.d.ts +15 -0
  67. package/dist/layout/components/layout/layout.vue.d.ts.map +1 -0
  68. package/dist/layout/components/layout/props.d.ts +4 -0
  69. package/dist/layout/components/layout/props.d.ts.map +1 -0
  70. package/dist/layout/hoc/index.d.ts +2 -0
  71. package/dist/layout/hoc/index.d.ts.map +1 -0
  72. package/dist/layout/hoc/useLayout.d.ts +12 -0
  73. package/dist/layout/hoc/useLayout.d.ts.map +1 -0
  74. package/dist/layout/index.d.ts +5 -0
  75. package/dist/layout/index.d.ts.map +1 -0
  76. package/dist/layout/utils/index.d.ts +4 -0
  77. package/dist/layout/utils/index.d.ts.map +1 -0
  78. package/dist/modal/components/form-modal/form-modal.vue.d.ts +46 -0
  79. package/dist/modal/components/form-modal/form-modal.vue.d.ts.map +1 -0
  80. package/dist/modal/components/form-modal/index.d.ts +101 -0
  81. package/dist/modal/components/form-modal/index.d.ts.map +1 -0
  82. package/dist/modal/components/form-modal/props.d.ts +19 -0
  83. package/dist/modal/components/form-modal/props.d.ts.map +1 -0
  84. package/dist/modal/components/modal/index.d.ts +53 -0
  85. package/dist/modal/components/modal/index.d.ts.map +1 -0
  86. package/dist/modal/components/modal/modal.vue.d.ts +29 -0
  87. package/dist/modal/components/modal/modal.vue.d.ts.map +1 -0
  88. package/dist/modal/components/modal/props.d.ts +24 -0
  89. package/dist/modal/components/modal/props.d.ts.map +1 -0
  90. package/dist/modal/hoc/index.d.ts +4 -0
  91. package/dist/modal/hoc/index.d.ts.map +1 -0
  92. package/dist/modal/hoc/useFormModal.d.ts +13 -0
  93. package/dist/modal/hoc/useFormModal.d.ts.map +1 -0
  94. package/dist/modal/hoc/useModal.d.ts +12 -0
  95. package/dist/modal/hoc/useModal.d.ts.map +1 -0
  96. package/dist/modal/hoc/useModalExpose.d.ts +8 -0
  97. package/dist/modal/hoc/useModalExpose.d.ts.map +1 -0
  98. package/dist/modal/index.d.ts +4 -0
  99. package/dist/modal/index.d.ts.map +1 -0
  100. package/dist/table/components/fields/action-column/action-column.vue.d.ts +6 -0
  101. package/dist/table/components/fields/action-column/action-column.vue.d.ts.map +1 -0
  102. package/dist/table/components/fields/action-column/props.d.ts +8 -0
  103. package/dist/table/components/fields/action-column/props.d.ts.map +1 -0
  104. package/dist/table/components/fields/index.d.ts +2 -0
  105. package/dist/table/components/fields/index.d.ts.map +1 -0
  106. package/dist/table/components/table/index.d.ts +58 -0
  107. package/dist/table/components/table/index.d.ts.map +1 -0
  108. package/dist/table/components/table/props.d.ts +43 -0
  109. package/dist/table/components/table/props.d.ts.map +1 -0
  110. package/dist/table/components/table/table.vue.d.ts +33 -0
  111. package/dist/table/components/table/table.vue.d.ts.map +1 -0
  112. package/dist/table/components/table-column/index.d.ts +6 -0
  113. package/dist/table/components/table-column/index.d.ts.map +1 -0
  114. package/dist/table/components/table-column/props.d.ts +6 -0
  115. package/dist/table/components/table-column/props.d.ts.map +1 -0
  116. package/dist/table/components/table-column/table-column.vue.d.ts +6 -0
  117. package/dist/table/components/table-column/table-column.vue.d.ts.map +1 -0
  118. package/dist/table/components/table-page/index.d.ts +12 -0
  119. package/dist/table/components/table-page/index.d.ts.map +1 -0
  120. package/dist/table/components/table-page/props.d.ts +13 -0
  121. package/dist/table/components/table-page/props.d.ts.map +1 -0
  122. package/dist/table/components/table-page/table-page.vue.d.ts +11 -0
  123. package/dist/table/components/table-page/table-page.vue.d.ts.map +1 -0
  124. package/dist/table/components/table-select/index.d.ts +73 -0
  125. package/dist/table/components/table-select/index.d.ts.map +1 -0
  126. package/dist/table/components/table-select/props.d.ts +21 -0
  127. package/dist/table/components/table-select/props.d.ts.map +1 -0
  128. package/dist/table/components/table-select/table-select.vue.d.ts +36 -0
  129. package/dist/table/components/table-select/table-select.vue.d.ts.map +1 -0
  130. package/dist/table/hoc/index.d.ts +3 -0
  131. package/dist/table/hoc/index.d.ts.map +1 -0
  132. package/dist/table/hoc/useTable.d.ts +33 -0
  133. package/dist/table/hoc/useTable.d.ts.map +1 -0
  134. package/dist/table/hoc/useTableExpose.d.ts +7 -0
  135. package/dist/table/hoc/useTableExpose.d.ts.map +1 -0
  136. package/dist/table/index.d.ts +8 -0
  137. package/dist/table/index.d.ts.map +1 -0
  138. package/dist/table/utils/index.d.ts +4 -0
  139. package/dist/table/utils/index.d.ts.map +1 -0
  140. package/package.json +42 -0
  141. package/src/button/components/button/button.vue +64 -0
  142. package/src/button/components/button/index.ts +2 -0
  143. package/src/button/components/button/props.ts +75 -0
  144. package/src/button/components/fields/index.ts +6 -0
  145. package/src/button/hoc/index.ts +1 -0
  146. package/src/button/hoc/useButton.ts +27 -0
  147. package/src/button/index.ts +4 -0
  148. package/src/button/utils/index.ts +32 -0
  149. package/src/common/index.ts +1 -0
  150. package/src/common/utils/iconUtils.ts +21 -0
  151. package/src/common/utils/index.ts +1 -0
  152. package/src/form/components/fields/index.ts +35 -0
  153. package/src/form/components/form/form.vue +130 -0
  154. package/src/form/components/form/index.ts +6 -0
  155. package/src/form/components/form/props.ts +73 -0
  156. package/src/form/components/form-item/form-item.vue +90 -0
  157. package/src/form/components/form-item/index.ts +6 -0
  158. package/src/form/components/form-item/props.ts +50 -0
  159. package/src/form/hoc/index.ts +3 -0
  160. package/src/form/hoc/useForm.ts +106 -0
  161. package/src/form/hoc/useFormExpose.ts +97 -0
  162. package/src/form/hoc/useFormFetch.ts +103 -0
  163. package/src/form/index.ts +5 -0
  164. package/src/form/utils/index.ts +149 -0
  165. package/src/global.ts +40 -0
  166. package/src/index.ts +37 -0
  167. package/src/layout/components/fields/basic/basic.vue +18 -0
  168. package/src/layout/components/fields/index.ts +10 -0
  169. package/src/layout/components/fields/side/side.vue +26 -0
  170. package/src/layout/components/fields/top/top.vue +13 -0
  171. package/src/layout/components/layout/index.ts +6 -0
  172. package/src/layout/components/layout/layout.vue +19 -0
  173. package/src/layout/components/layout/props.ts +3 -0
  174. package/src/layout/hoc/index.ts +1 -0
  175. package/src/layout/hoc/useLayout.ts +32 -0
  176. package/src/layout/index.ts +4 -0
  177. package/src/layout/utils/index.ts +31 -0
  178. package/src/modal/components/form-modal/form-modal.vue +158 -0
  179. package/src/modal/components/form-modal/index.ts +5 -0
  180. package/src/modal/components/form-modal/props.ts +61 -0
  181. package/src/modal/components/modal/index.ts +6 -0
  182. package/src/modal/components/modal/modal.vue +127 -0
  183. package/src/modal/components/modal/props.ts +78 -0
  184. package/src/modal/hoc/index.ts +3 -0
  185. package/src/modal/hoc/useFormModal.ts +140 -0
  186. package/src/modal/hoc/useModal.ts +151 -0
  187. package/src/modal/hoc/useModalExpose.ts +52 -0
  188. package/src/modal/index.ts +3 -0
  189. package/src/style/index.css +21 -0
  190. package/src/table/components/fields/action-column/action-column.vue +34 -0
  191. package/src/table/components/fields/action-column/props.ts +8 -0
  192. package/src/table/components/fields/index.ts +6 -0
  193. package/src/table/components/table/index.ts +6 -0
  194. package/src/table/components/table/props.ts +148 -0
  195. package/src/table/components/table/table.vue +77 -0
  196. package/src/table/components/table-column/index.ts +6 -0
  197. package/src/table/components/table-column/props.ts +26 -0
  198. package/src/table/components/table-column/table-column.vue +31 -0
  199. package/src/table/components/table-page/index.ts +6 -0
  200. package/src/table/components/table-page/props.ts +48 -0
  201. package/src/table/components/table-page/table-page.vue +51 -0
  202. package/src/table/components/table-select/index.ts +6 -0
  203. package/src/table/components/table-select/props.ts +79 -0
  204. package/src/table/components/table-select/table-select.vue +70 -0
  205. package/src/table/hoc/index.ts +2 -0
  206. package/src/table/hoc/useTable.ts +206 -0
  207. package/src/table/hoc/useTableExpose.ts +46 -0
  208. package/src/table/index.ts +7 -0
  209. package/src/table/utils/index.ts +37 -0
  210. package/tsconfig.json +30 -0
  211. package/vite.config.ts +49 -0
@@ -0,0 +1,75 @@
1
+ import {buttonFields} from "@/button";
2
+ import type {ButtonProps} from "element-plus";
3
+ import type {EmitsToEventProps} from '@aoao-y33/utils';
4
+ import type {Component} from "vue";
5
+
6
+ /**
7
+ * AxButton 按钮组件属性接口
8
+ * @template E - 事件数据类型,用于控制按钮显示/隐藏的上下文数据
9
+ * @template T - Element Plus ButtonProps 类型扩展
10
+ */
11
+ export interface AxButtonProps<E = any, T = ButtonProps> {
12
+ /** 按钮显示的文本内容 */
13
+ text?: string
14
+
15
+ /**
16
+ * 按钮类型,对应预定义的按钮样式配置
17
+ * @see buttonFields - 预定义的按钮类型映射表
18
+ */
19
+ type?: keyof typeof buttonFields
20
+
21
+ /** Element Plus 按钮的额外属性配置 */
22
+ componentProps?: T
23
+
24
+ /** 自定义 CSS 类名 */
25
+ className?: string,
26
+
27
+ /**
28
+ * 按钮图标,支持字符串(图标类名)或 Vue 组件形式
29
+ * @example "el-icon-search" | IconComponent
30
+ */
31
+ icon?:string|Component,
32
+
33
+ /**
34
+ * 按钮禁用状态控制
35
+ * - 布尔值:直接设置禁用状态
36
+ * - 函数:根据上下文数据动态计算禁用状态
37
+ * @param data - 传入的上下文数据
38
+ * @returns 是否禁用
39
+ */
40
+ disabled?: ((data: E) => boolean) | (boolean)
41
+
42
+ /**
43
+ * 按钮隐藏状态控制
44
+ * - 布尔值:直接设置隐藏状态
45
+ * - 函数:根据上下文数据动态计算隐藏状态
46
+ * @param data - 传入的上下文数据
47
+ * @returns 是否隐藏
48
+ */
49
+ hidden?: ((data: E) => boolean) | (boolean)
50
+
51
+ /** 是否添加左边距,用于按钮间距控制 */
52
+ isMl?:boolean
53
+ }
54
+
55
+ /**
56
+ * AxButton 按钮组件事件发射接口
57
+ * @template T - 事件携带的数据类型
58
+ */
59
+ export interface AxButtonEmits<T = any> {
60
+ /** 单击事件 */
61
+ "click": [data: T]
62
+ /** 双击事件 */
63
+ "dblClick": [data: T]
64
+ }
65
+
66
+ /**
67
+ * AxButton 按钮配置选项接口
68
+ * 继承自 AxButtonProps 并合并事件处理属性
69
+ * @template E - 事件数据类型
70
+ * @template T - Element Plus ButtonProps 类型扩展
71
+ */
72
+ export interface AxButtonOptions<E = any, T = ButtonProps>
73
+ extends AxButtonProps<E, T>,
74
+ Partial<EmitsToEventProps<AxButtonEmits<E>>> {
75
+ }
@@ -0,0 +1,6 @@
1
+ import {ElButton} from "element-plus";
2
+ import {addButtonField} from "@/button";
3
+
4
+ export const initButtonFields=()=>{
5
+ addButtonField("default",ElButton);
6
+ }
@@ -0,0 +1 @@
1
+ export * from './useButton';
@@ -0,0 +1,27 @@
1
+ import {AxButton, type AxButtonOptions} from "@/button";
2
+ import {useState} from "@aoao-y33/hooks";
3
+ import {defineComponent, h} from "vue";
4
+ import type {ButtonProps} from "element-plus";
5
+
6
+ /**
7
+ * 按钮高阶函数 - 用于创建可动态配置的按钮组件
8
+ *
9
+ * @template E - 事件类型,默认为 any
10
+ * @template T - 按钮属性类型,默认为 ButtonProps
11
+ * @param options - 按钮初始配置选项
12
+ * @returns 返回一个元组 [Button组件, setButton更新函数]
13
+ *
14
+ * @example
15
+ * const [MyButton, setButton] = useButton({ text: '点击' });
16
+ * // 后续可以通过 setButton 动态更新按钮属性
17
+ * setButton({ text: '新文本', disabled: true });
18
+ */
19
+ export function useButton<E=any,T=ButtonProps>(options:AxButtonOptions<E,T>={}){
20
+ const [props,setButton] = useState(options);
21
+ const Button = defineComponent({
22
+ setup(){
23
+ return ()=>h(AxButton as any,{...props.value})
24
+ }
25
+ })
26
+ return [Button,setButton] as const;
27
+ }
@@ -0,0 +1,4 @@
1
+ export * from './hoc';
2
+ export * from './components/button';
3
+ export * from './components/fields';
4
+ export * from './utils';
@@ -0,0 +1,32 @@
1
+ import type {Component} from "vue";
2
+
3
+ /**
4
+ * 按钮类型注册表
5
+ * 存储自定义按钮类型与对应组件的映射关系
6
+ * @example
7
+ * // 注册自定义按钮
8
+ * addButtonField('primary', CustomButtonComponent)
9
+ */
10
+ export const buttonFields:Record<string, Component>= {};
11
+
12
+ /**
13
+ * 注册新的按钮类型
14
+ * 将自定义按钮组件添加到按钮类型注册表中
15
+ *
16
+ * @param type - 按钮类型标识符(唯一)
17
+ * @param component - 对应的 Vue 组件
18
+ *
19
+ * @warning 如果类型已存在,会输出警告信息但不会阻止注册
20
+ *
21
+ * @example
22
+ * import CustomButton from './CustomButton.vue'
23
+ * addButtonField('custom', CustomButton)
24
+ */
25
+ export const addButtonField =(type:string,component:Component)=>{
26
+ // 检查是否已存在相同类型的按钮
27
+ for (type in buttonFields){
28
+ console.warn(`[AxButton] Button type ${type} already exists`)
29
+ }
30
+ // 注册新的按钮类型
31
+ buttonFields[type] = component;
32
+ }
@@ -0,0 +1 @@
1
+ export * from './utils';
@@ -0,0 +1,21 @@
1
+ import * as Icons from '@element-plus/icons-vue';
2
+
3
+ /**
4
+ * 根据图标名称获取 Element Plus 图标组件
5
+ *
6
+ * @param icon - 图标名称(需与 Element Plus Icons 中的导出名称一致)
7
+ * @returns 对应的图标组件,如果不存在则返回 undefined
8
+ *
9
+ * @example
10
+ * // 获取搜索图标
11
+ * const SearchIcon = getIcons('Search')
12
+ *
13
+ * @example
14
+ * // 在模板中使用
15
+ * <component :is="getIcons('HomeFilled')" />
16
+ *
17
+ * @see {@link https://element-plus.org/zh-CN/component/icon.html Element Plus Icons}
18
+ */
19
+ export const getIcons = (icon: string) => {
20
+ return (Icons as any)[icon];
21
+ }
@@ -0,0 +1 @@
1
+ export * from './iconUtils';
@@ -0,0 +1,35 @@
1
+ import {
2
+ ElInput,
3
+ ElSelect,
4
+ ElCascader,
5
+ ElRadioGroup,
6
+ ElCheckboxGroup,
7
+ ElColorPicker,
8
+ ElColorPickerPanel,
9
+ ElDatePicker, ElTimePicker, ElInputNumber,
10
+ ElInputOtp,
11
+ ElSwitch, ElRate, ElSlider, ElUpload,
12
+ ElSelectV2, ElTransfer, ElTreeSelect,
13
+ } from "element-plus";
14
+ import {addFormField} from "@/form";
15
+
16
+ export const initFormFields = () => {
17
+ addFormField('text', ElInput);
18
+ addFormField('select', ElSelect);
19
+ addFormField('cascade', ElCascader);
20
+ addFormField('radio', ElRadioGroup);
21
+ addFormField('checkbox', ElCheckboxGroup);
22
+ addFormField("color", ElColorPicker);
23
+ addFormField("date", ElDatePicker);
24
+ addFormField("time", ElTimePicker);
25
+ addFormField("number", ElInputNumber);
26
+ addFormField("color-panel", ElColorPickerPanel);
27
+ addFormField("otp", ElInputOtp);
28
+ addFormField("rate", ElRate);
29
+ addFormField("switch", ElSwitch);
30
+ addFormField("slider", ElSlider);
31
+ addFormField("upload", ElUpload);
32
+ addFormField("transfer", ElTransfer);
33
+ addFormField("select-v2", ElSelectV2);
34
+ addFormField("tree", ElTreeSelect);
35
+ }
@@ -0,0 +1,130 @@
1
+ <script setup lang="ts">
2
+ import {ElForm, ElFormItem, vLoading, type FormInstance} from "element-plus";
3
+ import {AxButton} from "@/button";
4
+ import type {AxFormEmits, AxFormProps} from "./props";
5
+ import {useDefineProps, useFetch} from "@aoao-y33/hooks";
6
+ import {computed, provide, reactive, type Ref, ref, useSlots, watch} from "vue";
7
+
8
+ defineOptions({name: 'AxForm'})
9
+ const {
10
+ isDefault = true,
11
+ submitButton = {},
12
+ loading = false,
13
+ api = null,
14
+ apiConfig = {},
15
+ ...props
16
+ } = defineProps<AxFormProps>();
17
+
18
+ const emits = defineEmits<AxFormEmits>()
19
+
20
+ const slots = useSlots();
21
+
22
+ const formProps = useDefineProps(props);
23
+
24
+ const defaultButton = useDefineProps(submitButton, {
25
+ text: "提交",
26
+ icon: "CircleCheckFilled",
27
+ componentProps: {
28
+ type: "primary",
29
+ nativeType: "submit",
30
+ }
31
+ })
32
+
33
+ const formData = reactive({});
34
+
35
+ provide("formData", formData);
36
+
37
+ provide("clickData", formData);
38
+
39
+ const defaultData = reactive({});
40
+
41
+ provide("defaultData", defaultData);
42
+
43
+ const [, requestApi] = useFetch(api, apiConfig)
44
+
45
+ watch(() => formData, () => {
46
+ emits("change", formData);
47
+ }, {immediate: true})
48
+
49
+ const formRef = ref<FormInstance>() as Ref<FormInstance>;
50
+
51
+ const _loading = computed(() => {
52
+ return Boolean(loading || requestApi.getConfig().loading);
53
+ })
54
+
55
+ const onSubmit = () => {
56
+ formRef.value?.validate().then(async (res) => {
57
+ if (res) {
58
+ if (requestApi.getReady()) {
59
+ await requestApi.load(formData);
60
+ } else {
61
+ emits("submit", formData);
62
+ }
63
+ }
64
+ })
65
+ }
66
+
67
+
68
+ const getElForm = () => {
69
+ return formRef.value
70
+ }
71
+
72
+ const getValues = () => {
73
+ return Object.assign({}, formData);
74
+ }
75
+
76
+ const getValue = (fieldName: string) => {
77
+ return (formData as Record<string, any>)[fieldName]
78
+ }
79
+ const getFields = () => {
80
+ return Object.keys(formData);
81
+ }
82
+
83
+ const getDefaultValues = () => {
84
+ return Object.assign({}, defaultData);
85
+ }
86
+
87
+ const setValues = (values: Record<string, any>) => {
88
+ Object.assign(formData, values);
89
+ }
90
+
91
+ const resetValues = () => {
92
+ Object.assign(formData, defaultData);
93
+ }
94
+
95
+ const clearValues = () => {
96
+ Object.keys(formData).forEach(fieldName => {
97
+ (formData as Record<string, any>)[fieldName] = undefined;
98
+ })
99
+ }
100
+
101
+ defineExpose({
102
+ getElForm,
103
+ getValues,
104
+ getValue,
105
+ getFields,
106
+ getDefaultValues,
107
+ setValues,
108
+ resetValues,
109
+ clearValues,
110
+ ...requestApi
111
+ })
112
+
113
+ </script>
114
+ <template>
115
+ <ElForm v-bind="formProps"
116
+ :model="formData"
117
+ ref="formRef"
118
+ @submit.prevent
119
+ v-loading="_loading">
120
+ <slot></slot>
121
+ <ElFormItem
122
+ v-if="slots.button||isDefault"
123
+ :label="labelWidth=='auto'?' ':''">
124
+ <ax-button v-if="isDefault"
125
+ v-bind="defaultButton"
126
+ @click="onSubmit"></ax-button>
127
+ <slot name="button"/>
128
+ </ElFormItem>
129
+ </ElForm>
130
+ </template>
@@ -0,0 +1,6 @@
1
+ import form from './form.vue';
2
+
3
+ export * from './props';
4
+ export const AxForm = form;
5
+ export type AxFormInstance = InstanceType<typeof form>;
6
+ export default AxForm;
@@ -0,0 +1,73 @@
1
+ import type {FormProps} from "element-plus";
2
+ import type {AxButtonOptions, AxButtonProps} from "@/button";
3
+ import type {FetchOptions, FieldsConfig, RequestFetch} from "@aoao-y33/hooks";
4
+ import type {EmitsToEventProps} from "@aoao-y33/utils";
5
+ import type {AxFormItemOptions} from "@/form";
6
+
7
+ /**
8
+ * AxForm 表单组件属性接口
9
+ * 继承自 Element Plus FormProps,扩展了自定义功能
10
+ * @template T - 表单数据类型,必须是对象类型
11
+ */
12
+ export interface AxFormProps<T extends Record<string, any> = any> extends Omit<FormProps, 'model'> {
13
+ /** 是否使用默认配置,启用后将自动应用预设的表单样式和行为 */
14
+ isDefault?:boolean;
15
+
16
+ /** 提交按钮的配置项,用于自定义表单提交按钮的外观和行为 */
17
+ submitButton?: AxButtonProps;
18
+
19
+ /** 表单提交时的加载状态,通常在异步请求期间显示 */
20
+ loading?:boolean,
21
+
22
+ /**
23
+ * API 请求函数,用于表单数据提交
24
+ * @see RequestFetch - 请求函数类型定义
25
+ */
26
+ api?:RequestFetch<T,any>;
27
+
28
+ /**
29
+ * API 请求配置项,包含请求参数、拦截器等配置
30
+ * @see FetchOptions - 请求配置选项类型
31
+ */
32
+ apiConfig?:FetchOptions<T, any>;
33
+ }
34
+
35
+ /**
36
+ * AxForm 表单组件事件发射接口
37
+ * @template T - 表单数据类型
38
+ */
39
+ export interface AxFormEmits<T extends Record<string, any> = Record<string, any>> {
40
+ /**
41
+ * 表单提交事件
42
+ * @param data - 表单提交的数据
43
+ */
44
+ 'submit':[data:T];
45
+
46
+ /**
47
+ * 表单数据变化事件
48
+ * @param data - 变化后的表单数据
49
+ */
50
+ 'change':[data:T];
51
+ }
52
+
53
+ /**
54
+ * AxForm 表单配置选项接口
55
+ * 继承自 AxFormProps 并合并事件处理属性和字段配置
56
+ * @template T - 表单数据类型
57
+ */
58
+ export interface AxFormOptions<T extends Record<string, any> = any>
59
+ extends AxFormProps<T>,Partial<EmitsToEventProps<AxFormEmits<T>>>{
60
+ /**
61
+ * 按钮配置映射表,用于配置表单中的各种按钮(提交、重置等)
62
+ * @see FieldsConfig - 字段配置类型
63
+ * @see AxButtonOptions - 按钮选项类型
64
+ */
65
+ buttonConfig?:FieldsConfig<AxButtonOptions>
66
+
67
+ /**
68
+ * 表单项配置映射表,用于配置表单中各个字段的属性、验证规则等
69
+ * @see FieldsConfig - 字段配置类型
70
+ * @see AxFormItemOptions - 表单项选项类型
71
+ */
72
+ fieldConfig?:FieldsConfig<AxFormItemOptions>
73
+ }
@@ -0,0 +1,90 @@
1
+ <script setup lang="ts">
2
+ import {ElFormItem, type FormItemInstance} from "element-plus";
3
+ import type {AxFormItemProps} from "./props";
4
+ import {computed, inject, onUnmounted, ref, useAttrs, useSlots} from "vue";
5
+ import {formFields, formRules, isTip} from "@/form";
6
+ import {useDefineProps} from "@aoao-y33/hooks";
7
+
8
+ defineOptions({name: 'ax-form-item'});
9
+ const {
10
+ type = 'text',
11
+ fieldName,
12
+ label = "",
13
+ componentProps = {},
14
+ placeholder,
15
+ vtypes = [],
16
+ rules = [],
17
+ defaultValue,
18
+ ...props
19
+ } = defineProps<AxFormItemProps>()
20
+ const attrs = useAttrs();
21
+ const slots = useSlots();
22
+ const itemProps = useDefineProps(props);
23
+ const formData = inject('formData', null) as Record<string, any> | null;
24
+ const defaultData = inject('defaultData', {}) as Record<string, any>;
25
+ if (formData) {
26
+ defaultData[fieldName] = defaultValue;
27
+ formData[fieldName] = defaultData[fieldName];
28
+ }
29
+ const FormField = computed(() => {
30
+ return formFields[type];
31
+ })
32
+ const _placeholder = computed(() => {
33
+ if (placeholder) {
34
+ return placeholder;
35
+ }
36
+ return isTip(type) + (label || '');
37
+ })
38
+ const _rules = computed(() => {
39
+ const validates = vtypes.map(item => {
40
+ if (typeof formRules[item] === 'function') {
41
+ return formRules[item](type, label);
42
+ }
43
+ return formRules[item];
44
+ });
45
+ return validates.concat(rules) as any;
46
+ })
47
+
48
+ onUnmounted(() => {
49
+ if (formData) {
50
+ delete formData[fieldName as string];
51
+ }
52
+ })
53
+
54
+ const formItemRef = ref<FormItemInstance>();
55
+
56
+ const instanceRef = ref<typeof FormField.value>();
57
+
58
+ const getElFormItem=()=>{
59
+ return formItemRef.value as FormItemInstance;
60
+ }
61
+ const getFormField=()=>{
62
+ return instanceRef.value as any
63
+ }
64
+
65
+ defineExpose({
66
+ getElFormItem,
67
+ getFormField
68
+ })
69
+ </script>
70
+ <template>
71
+ <ElFormItem
72
+ v-if="formData"
73
+ v-bind="itemProps"
74
+ :label="label"
75
+ :prop="fieldName"
76
+ :rules="_rules"
77
+ ref="formItemRef"
78
+ >
79
+ <FormField
80
+ ref="instanceRef"
81
+ v-bind="{...componentProps,...attrs}"
82
+ v-model="formData[fieldName]"
83
+ :placeholder="_placeholder"
84
+ >
85
+ <template v-for="slot in Object.keys(slots)" #[slot]>
86
+ <slot :name="slot"></slot>
87
+ </template>
88
+ </FormField>
89
+ </ElFormItem>
90
+ </template>
@@ -0,0 +1,6 @@
1
+ import FormItem from './form-item.vue';
2
+
3
+ export * from './props';
4
+ export const AxFormItem = FormItem;
5
+ export type AxFormItemInstance = InstanceType<typeof FormItem>;
6
+ export default AxFormItem;
@@ -0,0 +1,50 @@
1
+ import type {FormItemProps} from "element-plus";
2
+
3
+ /**
4
+ * AxFormItem 表单项组件属性接口
5
+ * 继承自 Element Plus FormItemProps,扩展了自定义字段配置功能
6
+ */
7
+ export interface AxFormItemProps extends FormItemProps{
8
+ /** 字段名称,用于表单数据绑定和验证的唯一标识 */
9
+ fieldName:string;
10
+
11
+ /** 表单项的标签文本,显示在输入框左侧或上方 */
12
+ label?: string;
13
+
14
+ /**
15
+ * 表单项类型,决定渲染的输入组件类型
16
+ * @example 'input' | 'select' | 'textarea' | 'date-picker' 等
17
+ */
18
+ type?: string;
19
+
20
+ /**
21
+ * 验证规则类型数组,用于表单字段验证
22
+ * @example ['required', 'email', 'phone'] 等预定义验证规则
23
+ */
24
+ vtypes?: string[];
25
+
26
+ /** 字段的默认值,当表单初始化时自动填充 */
27
+ defaultValue?: any;
28
+
29
+ /**
30
+ * 底层组件的额外属性配置
31
+ * 透传给实际渲染的输入组件(如 Input、Select 等)
32
+ */
33
+ componentProps?:Record<string, any>
34
+
35
+ /** 输入框的占位符文本,提示用户输入内容 */
36
+ placeholder?:string
37
+ }
38
+
39
+ /**
40
+ * AxFormItem 表单项配置选项接口
41
+ * 继承自 AxFormItemProps,增加了插槽配置能力
42
+ */
43
+ export interface AxFormItemOptions extends AxFormItemProps{
44
+ /**
45
+ * 自定义插槽配置,用于覆盖表单项的默认渲染内容
46
+ * key 为插槽名称,value 为插槽内容或渲染函数
47
+ * @example { default: () => h('div', '自定义内容') }
48
+ */
49
+ slots?:Record<string, any>
50
+ }
@@ -0,0 +1,3 @@
1
+ export * from './useForm';
2
+ export * from './useFormExpose';
3
+ export * from './useFormFetch';
@@ -0,0 +1,106 @@
1
+ import {AxForm, AxFormItem, type AxFormItemOptions, useFormExpose, useFormFetch} from "@/form";
2
+ import {AxButton} from '@/button';
3
+ import { type AxButtonOptions} from "@/button";
4
+ import {type FieldsApi, useComponentPool, useState} from "@aoao-y33/hooks";
5
+ import {omit} from "lodash";
6
+ import type {AxFormInstance, AxFormOptions, FormApi, FormFetchApi} from '@/form';
7
+ import type { StateApi} from "@aoao-y33/hooks";
8
+ import {type Component, defineComponent, h, type Ref, ref} from "vue";
9
+
10
+ /**
11
+ * UseForm 返回值中的 API 接口
12
+ * 扩展了基础表单 API,提供完整的表单控制能力
13
+ * @template T - 表单数据类型
14
+ */
15
+ export interface UseFormApi<T extends Record<string, any>> extends FormApi<T> {
16
+ /**
17
+ * 表单属性状态管理器
18
+ * 用于动态更新表单配置(不包含 buttonConfig 和 fieldConfig)
19
+ */
20
+ setForm: StateApi<Omit<AxFormOptions, 'buttonConfig'|'fieldConfig'>>
21
+
22
+ /** 表单请求 API,用于执行表单提交等异步操作 */
23
+ requestApi: FormFetchApi<T>
24
+
25
+ /** 按钮组件池 API,用于管理表单中的按钮配置 */
26
+ buttonsApi: FieldsApi<AxButtonOptions>
27
+
28
+ /** 表单项组件池 API,用于管理表单字段的配置 */
29
+ fieldsApi: FieldsApi<AxFormItemOptions>
30
+ }
31
+
32
+ /**
33
+ * UseForm Hook 的返回类型
34
+ * 包含渲染组件和 API 接口的元组
35
+ * @template T - 表单数据类型
36
+ */
37
+ export type UseFormReturn<T extends Record<string, any>> = [Component, UseFormApi<T>];
38
+
39
+ /**
40
+ * 表单 Hook,用于创建可配置的表单组件
41
+ *
42
+ * 该 Hook 封装了表单的核心逻辑,包括:
43
+ * - 表单状态管理
44
+ * - 按钮和表单项的动态配置
45
+ * - 表单验证和提交
46
+ * - 组件渲染
47
+ *
48
+ * @param options - 表单初始配置选项
49
+ * @returns [Form 组件, Form API] 元组
50
+ *
51
+ * @example
52
+ * const [Form, formApi] = useForm({
53
+ * api: submitData,
54
+ * fieldConfig: { /* 字段配置 *\/ },
55
+ * buttonConfig: { /* 按钮配置 *\/ }
56
+ * })
57
+ *
58
+ * // 在模板中使用
59
+ * <Form />
60
+ *
61
+ * // 通过 API 操作表单
62
+ * formApi.fieldsApi.addField('username', { label: '用户名', type: 'input' })
63
+ * formApi.requestApi.submit()
64
+ */
65
+ export function useForm<T extends Record<string, any>>(options: AxFormOptions<T> = {}): UseFormReturn<T> {
66
+ // 创建表单属性状态,排除 buttonConfig 和 fieldConfig(它们由独立的组件池管理)
67
+ const [props, setForm] = useState(omit(options, ['buttonConfig','fieldConfig']));
68
+
69
+ // 创建按钮组件池,用于管理和渲染表单按钮
70
+ const [Buttons, buttonsApi] = useComponentPool<AxButtonOptions>(AxButton,options.buttonConfig);
71
+
72
+ // 创建表单项组件池,用于管理和渲染表单字段
73
+ const [Fields, fieldsApi] = useComponentPool<AxFormItemOptions>(AxFormItem, options.fieldConfig);
74
+
75
+ // 创建表单引用,用于访问表单实例的方法
76
+ const formRef = ref() as Ref<AxFormInstance>;
77
+
78
+ // 获取表单暴露的 API(验证、重置等方法)
79
+ const formApi = useFormExpose<T>(formRef);
80
+
81
+ // 获取表单请求 API(提交、数据获取等异步操作)
82
+ const requestApi = useFormFetch<T>(formRef);
83
+
84
+ // 定义表单渲染组件
85
+ const Form = defineComponent({
86
+ setup() {
87
+ const slots: Record<string, Component> = {};
88
+
89
+ // 如果存在按钮配置,创建按钮插槽
90
+ if (buttonsApi.getList().length) {
91
+ slots['button'] = () => h(Buttons);
92
+ }
93
+
94
+ // 如果存在字段配置,创建默认插槽(表单项列表)
95
+ if(fieldsApi.getList().length){
96
+ slots['default'] = () => h(Fields);
97
+ }
98
+
99
+ // 渲染 AxForm 组件,传入 ref、属性和插槽
100
+ return () => h(AxForm as any, {ref:formRef,...props.value}, slots);
101
+ }
102
+ })
103
+
104
+ // 返回表单组件和完整的 API 集合
105
+ return [Form, {setForm, ...formApi,fieldsApi, requestApi, buttonsApi}] as const;
106
+ }