Browse Source

feat(data-form): 新增 RadioGroup 组件并优化 DataForm 相关功能

- 添加自定义 RadioGroup 组件,支持 options 属性
- 更新 DataFormConstant,替换 Element Plus 的 ElRadioGroup 为自定义组件
- 新增 mergeExpose 函数,用于合并组件的 expose 对象
- 在 DataFormUtils 中添加新函数,增强组件合并功能
- 更新示例页面,展示 RadioGroup 组件的使用方法
master
lizw-2015 6 months ago
parent
commit
b878d659e3
  1. 4
      src/components/data-form/DataFormConstant.ts
  2. 45
      src/components/data-form/DataFormUtils.tsx
  3. 96
      src/components/data-form/inputs/RadioGroup.vue
  4. 5
      src/pages/DataForm01.vue

4
src/components/data-form/DataFormConstant.ts

@ -11,7 +11,6 @@ import {
ElInputTag, ElInputTag,
ElMention, ElMention,
ElRadio, ElRadio,
ElRadioGroup,
ElRate, ElRate,
ElSelect, ElSelect,
ElSelectV2, ElSelectV2,
@ -23,6 +22,7 @@ import {
ElTreeSelect, ElTreeSelect,
ElUpload, ElUpload,
} from "element-plus"; } from "element-plus";
import RadioGroup from "./inputs/RadioGroup.vue";
import type { DisplayMode } from "./DataFormTypes.ts"; import type { DisplayMode } from "./DataFormTypes.ts";
/** 内建的表单输入组件 */ /** 内建的表单输入组件 */
@ -32,7 +32,7 @@ const builtInInputComponents = {
Checkbox: markRaw<any>(ElCheckbox), Checkbox: markRaw<any>(ElCheckbox),
CheckboxGroup: markRaw<any>(ElCheckboxGroup), CheckboxGroup: markRaw<any>(ElCheckboxGroup),
Radio: markRaw<any>(ElRadio), Radio: markRaw<any>(ElRadio),
RadioGroup: markRaw<any>(ElRadioGroup), RadioGroup: markRaw<any>(RadioGroup),
Switch: markRaw<any>(ElSwitch), Switch: markRaw<any>(ElSwitch),
Select: markRaw<any>(ElSelect), Select: markRaw<any>(ElSelect),
SelectV2: markRaw<any>(ElSelectV2), SelectV2: markRaw<any>(ElSelectV2),

45
src/components/data-form/DataFormUtils.tsx

@ -1,4 +1,5 @@
import lodash from "lodash"; import lodash from "lodash";
import { toRaw } from "vue";
import { Typeof } from "@ease-forge/shared"; import { Typeof } from "@ease-forge/shared";
/** /**
@ -28,10 +29,54 @@ function dataPathToNamePath(dataPath: string): string | number | Array<string |
return namePath; return namePath;
} }
// 空函数
function _emptyFun() {
}
/**
* vue组件的expose对象sources中存在且expose中不存在的属性合并到expose对象
* @param expose expose对象
* @param sources
* @param onlyFun
*/
function mergeExpose(expose: Record<string, any>, sources: any, onlyFun: boolean = false) {
if (!expose) return;
sources = toRaw(sources);
if (!sources || Typeof.isDate(sources) || Typeof.isArray(sources) || !Typeof.isObj(sources)) return;
// sources 是 dom 对象
if (sources instanceof HTMLElement || (sources.constructor?.name?.includes("HTML") && sources.constructor?.name?.includes("Element"))) {
expose.$el = sources;
return;
}
// 压制警告[Vue warn] Object.keys(sources)
const rawConsoleWarn = console.warn;
console.warn = _emptyFun;
let keys = Object.keys(sources);
console.warn = rawConsoleWarn;
// 处理 expose
for (let key of keys) {
const newValue = sources[key];
if (Typeof.noValue(newValue)) continue;
if (onlyFun && !Typeof.isFun(newValue)) continue;
expose[key] = newValue;
}
if (!onlyFun) {
// 处理 vue 组件内置属性
keys = ["$data", "$props", "$attrs", "$slots", "$refs", "$emit", "$on", "$off", "$once", "$forceUpdate", "$nextTick", "$watch", "$el", "$options", "$parent", "$root"];
for (let key of keys) {
const newValue = sources[key];
if (Typeof.noValue(newValue)) continue;
expose[key] = newValue;
}
}
}
export default { export default {
dataPathToNamePath, dataPathToNamePath,
mergeExpose,
} }
export { export {
dataPathToNamePath, dataPathToNamePath,
mergeExpose,
} }

96
src/components/data-form/inputs/RadioGroup.vue

@ -0,0 +1,96 @@
<script setup lang="ts">
import lodash from "lodash";
import { computed, createVNode, defineExpose, onMounted, reactive, useAttrs, useSlots, useTemplateRef } from "vue";
import { ElRadio, ElRadioGroup } from "element-plus";
import { Typeof } from "@ease-forge/shared";
import { mergeExpose } from "../DataFormUtils.tsx";
defineOptions({
name: 'RadioGroup',
});
//
const attrs = useAttrs();
//
const slots = useSlots();
interface OptionItem {
value: string | number | boolean;
label: string;
[key: string]: any;
}
// Props
interface RadioGroupProps {
options?: Array<OptionItem>;
}
// props
const props = withDefaults(defineProps<RadioGroupProps>(), {
options: () => ([]),
});
// State
interface RadioGroupState {
}
// state
const state = reactive<RadioGroupState>({
loading: false,
});
//
const input = useTemplateRef<InstanceType<typeof ElRadioGroup>>("inputRef");
//
const options = computed(() => {
let opts: Array<OptionItem> = [];
let options = props.options;
if (options) {
if (Typeof.isArray(options)) {
opts = options;
} else {
console.log("options 配置必须是数组类型");
}
}
return opts;
});
// props
const inputProps = computed<any>(() => {
const res: any = { ...attrs };
if (Typeof.hasValue(res.modelValue) && !Typeof.isStr(res.modelValue)) res.modelValue = lodash.toString(res.modelValue);
return res;
});
function toString(val: any) {
if (Typeof.hasValue(val) && !Typeof.isStr(val)) return lodash.toString(val);
return val;
}
const expose = {
/** 组件状态 */
state,
};
onMounted(() => {
if (input.value) mergeExpose(expose, input.value);
});
//
defineExpose(expose);
export type {
OptionItem,
RadioGroupProps,
RadioGroupState,
}
</script>
<template>
<component ref="inputRef" :is="createVNode(ElRadioGroup, inputProps, slots)">
<ElRadio v-for="(item, idx) in options" v-bind="item" :value="toString(item.value)"/>
</component>
</template>
<style scoped>
</style>

5
src/pages/DataForm01.vue

@ -105,7 +105,10 @@ const dataForm1 = reactive<DataFormProps>({
{ {
dataPath: 'radio_group_1', label: '单选组', input: 'RadioGroup', dataPath: 'radio_group_1', label: '单选组', input: 'RadioGroup',
inputProps: { inputProps: {
// TODO options options: [
{ value: "001", label: "选项1" },
{ value: "002", label: "选项2" },
],
}, },
}, },
{ {

Loading…
Cancel
Save