plain-design 1.0.0-beta.101 → 1.0.0-beta.103
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/plain-design.commonjs.min.js +2 -2
- package/dist/plain-design.min.css +2 -2
- package/dist/plain-design.min.js +2 -2
- package/dist/report.html +2 -2
- package/package.json +1 -1
- package/src/packages/components/Cascade/CascadeKeys.tsx +158 -0
- package/src/packages/components/CascadeKeys/index.tsx +5 -0
- package/src/packages/components/Input/index.scss +1 -1
- package/src/packages/components/InputNumber/number.scss +3 -0
- package/src/packages/components/TreeCore/createTreeNode.tsx +4 -4
- package/src/packages/entry.tsx +1 -0
- package/src/packages/utils/inheritSlots.ts +2 -0
package/package.json
CHANGED
@@ -0,0 +1,158 @@
|
|
1
|
+
import {computed, designComponent, PropType, reactive, useModel} from "plain-design-composition";
|
2
|
+
import {CascadeEmitOptions, CascadePropsOptions} from "./cascade.utils";
|
3
|
+
import {TreeScopeSlotsOption} from "../TreeCore/TreeCore.type";
|
4
|
+
import Cascade from "./index";
|
5
|
+
import {omit} from "plain-utils/object/omit";
|
6
|
+
import {inheritSlots} from "../../utils/inheritSlots";
|
7
|
+
import {PlainObject} from "plain-utils/utils/event";
|
8
|
+
|
9
|
+
/**
|
10
|
+
* 用来编辑key可能冲突的级联数据,仅支持单选不支持多选
|
11
|
+
* @author 韦胜健
|
12
|
+
* @date 2024.8.7 18:43
|
13
|
+
*/
|
14
|
+
export const CascadeKeys = designComponent({
|
15
|
+
name: 'conflict-cascade',
|
16
|
+
inheritPropsType: Cascade,
|
17
|
+
props: {
|
18
|
+
/*key有冲突的情况下,不支持多选,多选必须保证key为唯一标识不能有冲突,并且singleValueType必须是all*/
|
19
|
+
...omit(CascadePropsOptions, ['keyField', 'multiple', 'singleValueType', "modelValue"]),
|
20
|
+
/*绑定值一定是数组,可能是nodeData对象数组,也可能是key字符串数组*/
|
21
|
+
modelValue: { type: Array as PropType<(string | PlainObject)[]> },
|
22
|
+
/*keyField一定要存在*/
|
23
|
+
keyField: { type: [String, Function] as PropType<string | ((nodeData: any) => string)>, required: true },
|
24
|
+
/*值类型设置,为true则表明绑定值modelValue为字符串数组,否则为object对象数组*/
|
25
|
+
useKeysValue: { type: Boolean },
|
26
|
+
},
|
27
|
+
emits: CascadeEmitOptions,
|
28
|
+
scopeSlots: {
|
29
|
+
...TreeScopeSlotsOption,
|
30
|
+
},
|
31
|
+
setup({ props, scopeSlots, event: { emit } }) {
|
32
|
+
|
33
|
+
const dataModel = useModel(() => props.data, emit.onUpdateData);
|
34
|
+
|
35
|
+
const model = useModel(() => props.modelValue, emit.onUpdateModelValue);
|
36
|
+
|
37
|
+
const utils = reactive({
|
38
|
+
getDataLabel: computed((): iUseCascadeDataPropsLabelFunction => {
|
39
|
+
const { labelField } = props;
|
40
|
+
return typeof labelField === "function" ? labelField : ((nodeData) => (nodeData as any)[labelField]);
|
41
|
+
}),
|
42
|
+
getDataKey: computed((): iUseCascadeDataPropsValFunction => {
|
43
|
+
const { keyField } = props;
|
44
|
+
return typeof keyField === "function" ? keyField : ((nodeData) => (nodeData as any)[keyField]);
|
45
|
+
}),
|
46
|
+
getDataChildren: computed((): iUseCascadeDataPropsChildrenFunction => {
|
47
|
+
const { childrenField } = props;
|
48
|
+
return typeof childrenField === "function" ? childrenField : ((nodeData) => (nodeData as any)[childrenField]);
|
49
|
+
}),
|
50
|
+
formatData2CascadeData: (nodeData: any, getParent: iCascadeWrapData['getParent'] = (() => undefined)): iCascadeWrapData => {
|
51
|
+
const label = utils.getDataLabel(nodeData);
|
52
|
+
const key = utils.getDataKey(nodeData);
|
53
|
+
const children = utils.getDataChildren(nodeData);
|
54
|
+
const keys: string[] = [...getParent()?.keys || [], key];
|
55
|
+
const ret: iCascadeWrapData = { label, key, nodeData, getParent, keys, keyString: keys.join('.') };
|
56
|
+
if (!!children) {
|
57
|
+
const formatChildren = children.map(child => utils.formatData2CascadeData(child, () => ret));
|
58
|
+
ret.children = formatChildren;
|
59
|
+
}
|
60
|
+
return ret;
|
61
|
+
},
|
62
|
+
});
|
63
|
+
|
64
|
+
const cascadeData = computed((): iCascadeWrapData[] | undefined => props.data?.map(item => utils.formatData2CascadeData(item)));
|
65
|
+
|
66
|
+
const cascadeModelValue = computed((): iCascadeWrapData[] | undefined => {
|
67
|
+
if (!model.value?.length) {return undefined;}
|
68
|
+
const modelValueList = [...model.value];
|
69
|
+
const ret: iCascadeWrapData[] = [];
|
70
|
+
|
71
|
+
let list = cascadeData.value;
|
72
|
+
let itemModelValue = modelValueList.shift();
|
73
|
+
while (itemModelValue && !!list?.length) {
|
74
|
+
const itemModelValueKey = props.useKeysValue ? itemModelValue : utils.getDataKey(itemModelValue);
|
75
|
+
const matchItem = list.find(i => i.key == itemModelValueKey);
|
76
|
+
if (!!matchItem) {
|
77
|
+
ret.push(matchItem);
|
78
|
+
list = matchItem.children || [];
|
79
|
+
itemModelValue = modelValueList.shift();
|
80
|
+
} else {
|
81
|
+
break;
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
return ret;
|
86
|
+
});
|
87
|
+
|
88
|
+
const handler = {
|
89
|
+
onUpdateData: (newData: iCascadeWrapData[] | undefined | null) => {
|
90
|
+
if (!newData) {dataModel.value = newData;}
|
91
|
+
dataModel.value = cascadeData.value?.map(itemData => itemData.nodeData);
|
92
|
+
},
|
93
|
+
onUpdateModelValue: (val: iCascadeWrapData[] | null | undefined) => {
|
94
|
+
model.value = props.useKeysValue ?
|
95
|
+
val?.map(i => i.key) :
|
96
|
+
val?.map(i => i.nodeData);
|
97
|
+
},
|
98
|
+
setChildrenData: (cascadeWrapData: iCascadeWrapData, childrenData: any[] | null | undefined) => {
|
99
|
+
const { childrenField, setChildrenData } = props;
|
100
|
+
if (typeof childrenField === "string") {
|
101
|
+
(cascadeWrapData.nodeData as any)[childrenField] = childrenData;
|
102
|
+
} else {
|
103
|
+
if (!!setChildrenData) {
|
104
|
+
setChildrenData(cascadeWrapData.nodeData, childrenData);
|
105
|
+
} else {
|
106
|
+
throw new Error('tree: props.setChildrenData is required when childrenField is function');
|
107
|
+
}
|
108
|
+
}
|
109
|
+
},
|
110
|
+
isCheckAble: (cascadeWrapData: iCascadeWrapData) => {return props.isCheckAble!(cascadeWrapData.nodeData);},
|
111
|
+
isLeaf: (cascadeWrapData: iCascadeWrapData) => {return props.isLeaf!(cascadeWrapData.nodeData);},
|
112
|
+
filterMethod: (cascadeWrapData: iCascadeWrapData, filterText: string) => {return props.filterMethod!(cascadeWrapData.nodeData, filterText);},
|
113
|
+
};
|
114
|
+
|
115
|
+
const cascadeAttrs = computed(() => {
|
116
|
+
const { useKeysValue, ..._props } = props;
|
117
|
+
return {
|
118
|
+
..._props,
|
119
|
+
data: cascadeData.value,
|
120
|
+
onUpdateData: handler.onUpdateData,
|
121
|
+
modelValue: cascadeModelValue.value,
|
122
|
+
onUpdateModelValue: handler.onUpdateModelValue,
|
123
|
+
|
124
|
+
setChildrenData: !props.setChildrenData ? undefined : handler.setChildrenData,
|
125
|
+
isCheckAble: !props.isCheckAble ? undefined : handler.isCheckAble,
|
126
|
+
isLeaf: !props.isLeaf ? undefined : handler.isLeaf,
|
127
|
+
filterMethod: !props.filterMethod ? undefined : handler.filterMethod,
|
128
|
+
|
129
|
+
labelField: "label",
|
130
|
+
keyField: "keyString",
|
131
|
+
childrenField: "children",
|
132
|
+
singleValueType: "all" as const,
|
133
|
+
};
|
134
|
+
});
|
135
|
+
|
136
|
+
return () => (
|
137
|
+
<Cascade{...cascadeAttrs.value} v-slots={inheritSlots({ scopeSlots })}/>
|
138
|
+
);
|
139
|
+
},
|
140
|
+
});
|
141
|
+
|
142
|
+
|
143
|
+
interface iCascadeWrapData {
|
144
|
+
label: string,
|
145
|
+
key: string,
|
146
|
+
children?: iCascadeWrapData[],
|
147
|
+
|
148
|
+
keys: string[],
|
149
|
+
keyString: string,
|
150
|
+
nodeData: any,
|
151
|
+
getParent: () => iCascadeWrapData | undefined,
|
152
|
+
}
|
153
|
+
|
154
|
+
interface iUseCascadeDataPropsLabelFunction {(nodeData: any): string;}
|
155
|
+
|
156
|
+
interface iUseCascadeDataPropsValFunction {(nodeData: any): string;}
|
157
|
+
|
158
|
+
interface iUseCascadeDataPropsChildrenFunction {(nodeData: any): any[] | undefined | null;}
|
@@ -30,6 +30,7 @@
|
|
30
30
|
&.number-button-type-right {
|
31
31
|
.number-button-container {
|
32
32
|
display: flex;
|
33
|
+
color: plv(text-2);
|
33
34
|
flex-direction: column;
|
34
35
|
align-items: stretch;
|
35
36
|
justify-content: center;
|
@@ -73,6 +74,8 @@
|
|
73
74
|
@include prefix(number-resize) {
|
74
75
|
padding-left: 100%;
|
75
76
|
position: relative;
|
77
|
+
color: plv(text-2);
|
78
|
+
|
76
79
|
& > div {
|
77
80
|
position: absolute;
|
78
81
|
@include inset;
|
@@ -53,11 +53,11 @@ export function createTreeNode(
|
|
53
53
|
/*设置子节点数据*/
|
54
54
|
const setChildrenData = (childrenData: any[] | null | undefined) => {
|
55
55
|
const { childrenField, setChildrenData } = props;
|
56
|
-
if (
|
57
|
-
(data
|
56
|
+
if (!!setChildrenData) {
|
57
|
+
setChildrenData(data, childrenData);
|
58
58
|
} else {
|
59
|
-
if (
|
60
|
-
|
59
|
+
if (typeof childrenField === "string") {
|
60
|
+
(data as any)[childrenField] = childrenData;
|
61
61
|
} else {
|
62
62
|
throw new Error('tree: props.setChildrenData is required when childrenField is function');
|
63
63
|
}
|
package/src/packages/entry.tsx
CHANGED
@@ -66,6 +66,7 @@ export {SelectGroup} from './components/SelectGroup';
|
|
66
66
|
export {Form} from './components/Form';
|
67
67
|
export {FormItem} from './components/FormItem';
|
68
68
|
export {Cascade} from './components/Cascade';
|
69
|
+
export {CascadeKeys} from './components/CascadeKeys';
|
69
70
|
export {Image} from './components/Image';
|
70
71
|
export {Tooltip} from './components/Tooltip';
|
71
72
|
export {useImage} from './components/useImage';
|
@@ -24,5 +24,7 @@ export function inheritSlots<
|
|
24
24
|
!!slots && Object.keys(slots).forEach((k: keyof Slots) => {if (slots[k].isExist()) {ret[k] = () => slots[k]();}});
|
25
25
|
!!scopeSlots && Object.keys(scopeSlots).forEach((k: keyof ScopeSlots) => {if (scopeSlots[k].isExist()) {ret[k] = (...args: any[]) => scopeSlots[k](...args);}});
|
26
26
|
|
27
|
+
if (!Object.keys(ret).length) {return undefined;}
|
28
|
+
|
27
29
|
return ret;
|
28
30
|
}
|