From aa9c8e4e657814b871b6a5d5105e8498e33edc5f Mon Sep 17 00:00:00 2001 From: wang-xh Date: Sun, 9 Oct 2022 18:16:17 +0800 Subject: [PATCH] feature: commit checkbox-group component --- .vscode/settings.json | 2 +- packages/ui-vue/components/checkbox/index.ts | 12 ++ .../checkbox/src/checkbox-group.component.tsx | 56 +++++++++ .../checkbox/src/checkbox-group.props.ts | 61 ++++++++++ .../checkbox/src/composition/types.ts | 37 ++++++ .../src/composition/use-checkbox-group.ts | 107 +++++++++++++++++ .../src/composition/change-radio.ts | 4 +- .../radio-group/src/radio-group.props.ts | 1 + packages/ui-vue/src/App.vue | 4 +- packages/ui-vue/src/components/checkbox.vue | 108 ++++++++++++++++++ .../ui-vue/src/components/radio-group.vue | 3 +- 11 files changed, 389 insertions(+), 6 deletions(-) create mode 100644 packages/ui-vue/components/checkbox/index.ts create mode 100644 packages/ui-vue/components/checkbox/src/checkbox-group.component.tsx create mode 100644 packages/ui-vue/components/checkbox/src/checkbox-group.props.ts create mode 100644 packages/ui-vue/components/checkbox/src/composition/types.ts create mode 100644 packages/ui-vue/components/checkbox/src/composition/use-checkbox-group.ts create mode 100644 packages/ui-vue/src/components/checkbox.vue diff --git a/.vscode/settings.json b/.vscode/settings.json index 927bc3d..7fa8c2a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,7 @@ { "editor.defaultFormatter": "esbenp.prettier-vscode", "[typescript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "vscode.typescript-language-features" }, "[typescriptreact]": { "editor.defaultFormatter": "vscode.typescript-language-features" diff --git a/packages/ui-vue/components/checkbox/index.ts b/packages/ui-vue/components/checkbox/index.ts new file mode 100644 index 0000000..9b664fc --- /dev/null +++ b/packages/ui-vue/components/checkbox/index.ts @@ -0,0 +1,12 @@ +import type { App } from 'vue'; +import CheckBoxGroup from './src/checkbox-group.component'; + +export * from './src/checkbox-group.props'; + +export { CheckBoxGroup }; + +export default { + install(app: App): void { + app.component(CheckBoxGroup.name, CheckBoxGroup); + } +}; diff --git a/packages/ui-vue/components/checkbox/src/checkbox-group.component.tsx b/packages/ui-vue/components/checkbox/src/checkbox-group.component.tsx new file mode 100644 index 0000000..e5710d8 --- /dev/null +++ b/packages/ui-vue/components/checkbox/src/checkbox-group.component.tsx @@ -0,0 +1,56 @@ +import { defineComponent, computed, ref } from 'vue'; +import type { SetupContext } from 'vue'; +import { CheckboxGroupProps, checkboxGroupProps } from './checkbox-group.props'; +import { useCheckboxGroup } from './composition/use-checkbox-group'; + +export default defineComponent({ + name: 'FCheckboxGroup', + props: checkboxGroupProps, + emits: [ + 'changeValue', + 'update:modelValue', + ], + setup(props: CheckboxGroupProps, context: SetupContext) { + const modelValue = ref(props.modelValue); + const { enumData, onClickCheckbox, getValue, getText, checked, loadData } = useCheckboxGroup(props, context, modelValue); + + // 异步数据 + loadData(); + + const horizontalClass = computed(() => ({ + 'farris-checkradio-hor': props.horizontal + })); + + return () => { + return ( +
+ { + enumData.value.map((item, index) => { + const id = 'checkbox_' + props.name + index; + + return ( +
+ onClickCheckbox(item, event)} + /> + +
+ ); + }) + } + +
+ ); + }; + }, +}); diff --git a/packages/ui-vue/components/checkbox/src/checkbox-group.props.ts b/packages/ui-vue/components/checkbox/src/checkbox-group.props.ts new file mode 100644 index 0000000..7907687 --- /dev/null +++ b/packages/ui-vue/components/checkbox/src/checkbox-group.props.ts @@ -0,0 +1,61 @@ +import { ExtractPropTypes } from 'vue'; +import { Checkbox } from './composition/types'; + +export const checkboxGroupProps = { + /** + * 组件标识 + */ + id: String, + /** + * 组件名称 + */ + name: { type: String, default: '' }, + /** + * 单选组枚举数组 + */ + enumData: Array, + /** + * 枚举数组中展示文本的key值。 + */ + textField: { type: String, default: 'name' }, + /** + * 枚举数组中枚举值的key值。 + */ + valueField: { type: String, default: 'value' }, + /** + * 组件是否水平排列 + */ + horizontal: { type: Boolean, default: false }, + /** + * 禁用组件,不允许切换单选值 + */ + disable: { type: Boolean, default: false }, + + /** + * 组件值,字符串或者数组 + */ + modelValue: [String, Array], + + /** + * 输入框Tab键索引 + */ + tabIndex: { type: Number, default: 0 }, + + /** + * 分隔符,默认逗号 + */ + separator: { type: String, default: ',' }, + + /** + * 值类型是否为字符串 + */ + isStringValue: { type: Boolean, default: true }, + + /** + * 异步获取枚举数组方法 + */ + // loadData: () => Observable < { data: Array } > + loadData: { type: Function } +}; + +export type CheckboxGroupProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/checkbox/src/composition/types.ts b/packages/ui-vue/components/checkbox/src/composition/types.ts new file mode 100644 index 0000000..1eb0bae --- /dev/null +++ b/packages/ui-vue/components/checkbox/src/composition/types.ts @@ -0,0 +1,37 @@ +import { ComputedRef, Ref } from 'vue'; + +export interface Checkbox { + /** + * 枚举值 + */ + value: ComputedRef; + /** + * 枚举展示文本 + */ + name: ComputedRef; +} + +export interface ChangeCheckbox { + + enumData: ComputedRef>; + + /** + * 获取枚举值 + */ + getValue(item: Checkbox): any; + /** + * 获取枚举文本 + */ + getText(item: Checkbox): any; + + /** + * 校验复选框是否为选中状态 + */ + checked(item: Checkbox): boolean; + + /** + * 点击复选框事件 + */ + onClickCheckbox: (item: Checkbox, $event: Event) => void; + +} diff --git a/packages/ui-vue/components/checkbox/src/composition/use-checkbox-group.ts b/packages/ui-vue/components/checkbox/src/composition/use-checkbox-group.ts new file mode 100644 index 0000000..2b9f547 --- /dev/null +++ b/packages/ui-vue/components/checkbox/src/composition/use-checkbox-group.ts @@ -0,0 +1,107 @@ +import { ChangeCheckbox, Checkbox } from './types'; +import { computed, Ref, SetupContext, ref } from 'vue'; +import { CheckboxGroupProps } from '../checkbox-group.props'; + +export function useCheckboxGroup(props: CheckboxGroupProps, context: SetupContext, modelValue: Ref): ChangeCheckbox { + + const canChangeRadioButton = computed(() => !props.disable); + const enumData = ref(props.enumData || []); + + function getValue(item: Checkbox): any { + return item[props.valueField]; + }; + + function getText(item: Checkbox): any { + return item[props.textField]; + }; + + /** + * 值到数组值的转换 + */ + function transformToArr(value: any): string[] { + if (!value) { + return []; + } + if (!props.isStringValue) { + return value; + } + + return value.split(props.separator); + } + + /** + * 值到字符串值的转换 + */ + function transformToStr(value: Array) { + + const allVals = enumData.value.map(n => getValue(n)); + const r = []; + allVals.forEach(n => { + if (value.some(item => item === n)) { + r.push(n); + } + }); + + if (!props.isStringValue) { + return r; + } + return r.join(props.separator); + } + /** + * 校验复选框是否为选中状态 + */ + function checked(item: Checkbox) { + const val = String(getValue(item)); + const checkedValue = transformToArr(modelValue.value); + + // 多值 + return checkedValue.some(item => item === val); + } + + /** + * 点击复选框事件 + */ + function onClickCheckbox(item: Checkbox, $event: Event) { + if (canChangeRadioButton.value) { + let arrValue = transformToArr(modelValue.value) || []; + + const val = String(getValue(item)); + if (!arrValue || !arrValue.length) { + arrValue.push(val); + } else if (arrValue.some(item => item === val)) { + arrValue = arrValue.filter(n => n !== val); + } else { + arrValue.push(val); + } + + // 更新value值 + modelValue.value = transformToStr(arrValue); + + context.emit('changeValue', modelValue.value); + + // 不可少,用于更新组件绑定值 + context.emit('update:modelValue', modelValue.value); + + } + + $event.stopPropagation(); + } + + + function loadData() { + if (props.loadData) { + props.loadData().subscribe(res => { + enumData.value = res.data || []; + }); + } + } + return { + enumData, + + getValue, + getText, + checked, + onClickCheckbox, + loadData + }; +} diff --git a/packages/ui-vue/components/radio-group/src/composition/change-radio.ts b/packages/ui-vue/components/radio-group/src/composition/change-radio.ts index a3e7575..890c7e5 100644 --- a/packages/ui-vue/components/radio-group/src/composition/change-radio.ts +++ b/packages/ui-vue/components/radio-group/src/composition/change-radio.ts @@ -15,10 +15,10 @@ export function changeRadio(props: RadioGroupProps, context: SetupContext, model return item[props.textField]; }; - function onClickRadio(item, $event: Event) { + function onClickRadio(item: Radio, $event: Event) { if (canChangeRadioButton.value) { const newValue = getValue(item); - if (modelValue.value !== item) { + if (modelValue.value !== newValue) { modelValue.value = newValue; context.emit('changeValue', newValue); diff --git a/packages/ui-vue/components/radio-group/src/radio-group.props.ts b/packages/ui-vue/components/radio-group/src/radio-group.props.ts index b81a920..4047dd9 100644 --- a/packages/ui-vue/components/radio-group/src/radio-group.props.ts +++ b/packages/ui-vue/components/radio-group/src/radio-group.props.ts @@ -1,5 +1,6 @@ import { ExtractPropTypes, PropType } from 'vue'; import { Radio } from './composition/types'; +import { Observable, Subscription } from 'rxjs'; export const radioGroupProps = { /** diff --git a/packages/ui-vue/src/App.vue b/packages/ui-vue/src/App.vue index 9fc0e56..302edf6 100644 --- a/packages/ui-vue/src/App.vue +++ b/packages/ui-vue/src/App.vue @@ -13,6 +13,7 @@ import Section from "./components/section.vue"; import Notify from "./components/notify.vue"; import Accordion from "./components/accordion.vue"; import ComboList from "./components/combo-list.vue"; +import CheckboxGroup from "./components/checkbox.vue"; const canEdit = ref(true); const disable = ref(false); @@ -40,12 +41,13 @@ const canAutoComplete = ref(false); -
+ +