@xclqmc/base-form 1.0.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.
- package/package.json +50 -0
- package/src/components/BaseForm/BaseForm.vue +440 -0
- package/src/components/BaseForm/FormContent.vue +179 -0
- package/src/components/BaseForm/rules.ts +234 -0
- package/src/components/BaseForm/types.ts +292 -0
- package/src/components/base/BaseDrawer.vue +197 -0
- package/src/components/base/BaseEditor.vue +215 -0
- package/src/components/base/BaseInput.vue +47 -0
- package/src/components/base/BasePopup.vue +366 -0
- package/src/components/base/BaseRadio.vue +113 -0
- package/src/components/base/BaseSelect.vue +136 -0
- package/src/components/base/registry.ts +39 -0
- package/src/hooks/component.ts +128 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/message.ts +97 -0
- package/src/hooks/props.ts +50 -0
- package/src/index.ts +36 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// hooks/useComponentAliasRefs.ts
|
|
2
|
+
import {computed, shallowRef} from 'vue'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 使用别名管理组件引用的Hook
|
|
6
|
+
*/
|
|
7
|
+
export function useComponent<T = any>() {
|
|
8
|
+
// 使用 Map 存储别名到组件的映射
|
|
9
|
+
const aliasMap = shallowRef<Map<string, T>>(new Map())
|
|
10
|
+
|
|
11
|
+
// 使用对象方便模板访问
|
|
12
|
+
const aliasObject = computed(() => {
|
|
13
|
+
const obj: Record<string, T> = {}
|
|
14
|
+
aliasMap.value.forEach((value, key) => {
|
|
15
|
+
obj[key] = value
|
|
16
|
+
})
|
|
17
|
+
return obj
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 设置组件引用(必须提供别名)
|
|
22
|
+
*/
|
|
23
|
+
const setComponentRef = (el: T, alias: string) => {
|
|
24
|
+
if (!el || !alias) return
|
|
25
|
+
aliasMap.value.set(alias, el)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 批量设置组件引用
|
|
30
|
+
*/
|
|
31
|
+
const setComponentRefs = (refs: Record<string, T>) => {
|
|
32
|
+
Object.entries(refs).forEach(([alias, el]) => {
|
|
33
|
+
if (el) {
|
|
34
|
+
aliasMap.value.set(alias, el)
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 获取指定别名的组件引用
|
|
41
|
+
*/
|
|
42
|
+
const getComponentByAlias = (alias: string): T | null => {
|
|
43
|
+
return aliasMap.value.get(alias) || null
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 根据条件获取当前显示的组件引用
|
|
48
|
+
*/
|
|
49
|
+
const getCurrentComponentRef = (
|
|
50
|
+
getCondition: () => { alias?: string | string[] }
|
|
51
|
+
): T | T[] | null => {
|
|
52
|
+
const condition = getCondition()
|
|
53
|
+
|
|
54
|
+
if (!condition.alias) {
|
|
55
|
+
return null
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (Array.isArray(condition.alias)) {
|
|
59
|
+
// 返回多个组件
|
|
60
|
+
return condition.alias
|
|
61
|
+
.map(alias => getComponentByAlias(alias))
|
|
62
|
+
.filter(Boolean) as T[]
|
|
63
|
+
} else {
|
|
64
|
+
// 返回单个组件
|
|
65
|
+
return getComponentByAlias(condition.alias)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 获取所有组件引用
|
|
71
|
+
*/
|
|
72
|
+
const getAllComponents = computed(() => {
|
|
73
|
+
return Array.from(aliasMap.value.values())
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 获取所有别名
|
|
78
|
+
*/
|
|
79
|
+
const getAllAliases = computed(() => {
|
|
80
|
+
return Array.from(aliasMap.value.keys())
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 获取组件数量
|
|
85
|
+
*/
|
|
86
|
+
const getComponentCount = computed(() => {
|
|
87
|
+
return aliasMap.value.size
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 检查别名是否存在
|
|
92
|
+
*/
|
|
93
|
+
const hasAlias = (alias: string) => {
|
|
94
|
+
return aliasMap.value.has(alias)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 移除指定别名的组件引用
|
|
99
|
+
*/
|
|
100
|
+
const removeComponentByAlias = (alias: string) => {
|
|
101
|
+
aliasMap.value.delete(alias)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* 清除所有引用
|
|
106
|
+
*/
|
|
107
|
+
const clearRefs = () => {
|
|
108
|
+
aliasMap.value.clear()
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
// 状态
|
|
113
|
+
aliasMap: aliasObject,
|
|
114
|
+
aliasMapRaw: aliasMap,
|
|
115
|
+
|
|
116
|
+
// 方法
|
|
117
|
+
setComponentRef,
|
|
118
|
+
setComponentRefs,
|
|
119
|
+
getComponentByAlias,
|
|
120
|
+
getCurrentComponentRef,
|
|
121
|
+
getAllComponents,
|
|
122
|
+
getAllAliases,
|
|
123
|
+
getComponentCount,
|
|
124
|
+
hasAlias,
|
|
125
|
+
removeComponentByAlias,
|
|
126
|
+
clearRefs
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 消息提示 Hook(自 pig-ui src/hooks/tool/message.ts 抽离)
|
|
3
|
+
* 相比源项目去掉了 vue-i18n 依赖,提示文案内置中文。
|
|
4
|
+
*/
|
|
5
|
+
import { ElMessage, ElMessageBox, ElLoading } from "element-plus";
|
|
6
|
+
import { ref } from "vue";
|
|
7
|
+
|
|
8
|
+
interface MessageImplements {
|
|
9
|
+
info(title: string): void;
|
|
10
|
+
warning(title: string): void;
|
|
11
|
+
success(title: string): void;
|
|
12
|
+
error(title: string): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function useMessage() {
|
|
16
|
+
class MessageClass implements MessageImplements {
|
|
17
|
+
// 普通提示
|
|
18
|
+
info(title: string): void {
|
|
19
|
+
ElMessage.info(title);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 警告提示
|
|
23
|
+
warning(title: string): void {
|
|
24
|
+
ElMessage.warning(title);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 成功提示
|
|
28
|
+
success(title: string): void {
|
|
29
|
+
ElMessage.success(title);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 错误提示
|
|
33
|
+
error(title: string): void {
|
|
34
|
+
ElMessage.error(title);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return new MessageClass();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const load = ref();
|
|
42
|
+
export function useMessageBox() {
|
|
43
|
+
class MessageBoxClass implements MessageImplements {
|
|
44
|
+
// 普通提示
|
|
45
|
+
info(msg: string): void {
|
|
46
|
+
ElMessageBox.alert(msg, "提示");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 警告提示
|
|
50
|
+
warning(msg: string): void {
|
|
51
|
+
ElMessageBox.alert(msg, "提示", { type: "warning" });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 成功提示
|
|
55
|
+
success(msg: string): void {
|
|
56
|
+
ElMessageBox.alert(msg, "提示", { type: "success" });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 错误提示
|
|
60
|
+
error(msg: string): void {
|
|
61
|
+
ElMessageBox.alert(msg, "提示", { type: "error" });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 确认窗体
|
|
65
|
+
confirm(msg: string) {
|
|
66
|
+
return ElMessageBox.confirm(msg, "提示", {
|
|
67
|
+
confirmButtonText: "确定",
|
|
68
|
+
cancelButtonText: "取消",
|
|
69
|
+
type: "warning",
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
// 提交内容
|
|
73
|
+
prompt(msg: string) {
|
|
74
|
+
return ElMessageBox.prompt(msg, "提示", {
|
|
75
|
+
confirmButtonText: "确定",
|
|
76
|
+
cancelButtonText: "取消",
|
|
77
|
+
type: "warning",
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
loading(msg: string = "Loading") {
|
|
81
|
+
load.value = ElLoading.service({
|
|
82
|
+
lock: true,
|
|
83
|
+
text: msg,
|
|
84
|
+
background: "rgba(0, 0, 0, 0.7)",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
closeLoading() {
|
|
88
|
+
load.value.close();
|
|
89
|
+
}
|
|
90
|
+
//更新加载提示词文本
|
|
91
|
+
updateLoadingText(text: any) {
|
|
92
|
+
load.value.setText(text); // 手动更新
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return new MessageBoxClass();
|
|
97
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { computed } from 'vue';
|
|
2
|
+
|
|
3
|
+
type SyncPropConfig = string | { prop: string; emit?: string };
|
|
4
|
+
|
|
5
|
+
export function useProps(props: any, emit: any, config?: string | string[] | SyncPropConfig[]) {
|
|
6
|
+
// 默认配置
|
|
7
|
+
if (config === undefined) {
|
|
8
|
+
config = 'modelValue';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// 归一化为数组
|
|
12
|
+
let configs: (string | SyncPropConfig)[] = [];
|
|
13
|
+
if (typeof config === 'string') {
|
|
14
|
+
configs = [config];
|
|
15
|
+
} else if (Array.isArray(config)) {
|
|
16
|
+
configs = config;
|
|
17
|
+
} else {
|
|
18
|
+
// 如果传入的是单个对象(虽然类型未标,但兼容)
|
|
19
|
+
configs = [config];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const result: Record<string, any> = {};
|
|
23
|
+
|
|
24
|
+
configs.forEach((item) => {
|
|
25
|
+
let propName: string;
|
|
26
|
+
let emitName: string;
|
|
27
|
+
if (typeof item === 'string') {
|
|
28
|
+
propName = item;
|
|
29
|
+
emitName = item;
|
|
30
|
+
} else {
|
|
31
|
+
propName = item.prop;
|
|
32
|
+
emitName = item.emit || item.prop;
|
|
33
|
+
}
|
|
34
|
+
const key = `_${propName}`;
|
|
35
|
+
result[key] = computed({
|
|
36
|
+
get: () => props[propName],
|
|
37
|
+
set: (val) => emit(`update:${emitName}`, val),
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// 向后兼容:如果原本是单个字符串,返回 { _value }
|
|
42
|
+
if (typeof config === 'string') {
|
|
43
|
+
// 此时 result 只有一个键,取出来封装为 _value
|
|
44
|
+
const singleKey = Object.keys(result)[0];
|
|
45
|
+
return { _value: result[singleKey] };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 数组场景,返回所有 _prop 键
|
|
49
|
+
return result;
|
|
50
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// 组件
|
|
2
|
+
export { default as BaseForm } from "./components/BaseForm/BaseForm.vue";
|
|
3
|
+
export { default as BaseFormContent } from "./components/BaseForm/FormContent.vue";
|
|
4
|
+
export { default as BasePopup } from "./components/base/BasePopup.vue";
|
|
5
|
+
export { default as BaseInput } from "./components/base/BaseInput.vue";
|
|
6
|
+
export { default as BaseRadio } from "./components/base/BaseRadio.vue";
|
|
7
|
+
export { default as BaseSelect } from "./components/base/BaseSelect.vue";
|
|
8
|
+
export { default as BaseDrawer } from "./components/base/BaseDrawer.vue";
|
|
9
|
+
export { default as BaseEditor } from "./components/base/BaseEditor.vue";
|
|
10
|
+
|
|
11
|
+
// 校验规则与默认配置
|
|
12
|
+
export {
|
|
13
|
+
buildRules,
|
|
14
|
+
buildFieldRules,
|
|
15
|
+
PATTERNS,
|
|
16
|
+
} from "./components/BaseForm/rules";
|
|
17
|
+
export {
|
|
18
|
+
defaultFormOptions,
|
|
19
|
+
setDefaultFormOptions,
|
|
20
|
+
} from "./components/BaseForm/types";
|
|
21
|
+
export type {
|
|
22
|
+
BaseFormOptions,
|
|
23
|
+
BaseFormField,
|
|
24
|
+
BaseFormConfig,
|
|
25
|
+
BaseFormApi,
|
|
26
|
+
BaseFormComponent,
|
|
27
|
+
BaseFormEvent,
|
|
28
|
+
BaseFormOpen,
|
|
29
|
+
BaseFormSubmit,
|
|
30
|
+
} from "./components/BaseForm/types";
|
|
31
|
+
|
|
32
|
+
// hooks
|
|
33
|
+
export { useProps, useComponent, useMessage, useMessageBox } from "./hooks";
|
|
34
|
+
|
|
35
|
+
// 字段组件注入:按 type 注册自定义渲染组件,重复 type 以最后一次注入为准
|
|
36
|
+
export { registerField } from "./components/base/registry";
|