plain-design 1.0.0-beta.160 → 1.0.0-beta.162
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/dist/plain-design.commonjs.min.js +1 -1
- package/dist/plain-design.min.js +1 -1
- package/dist/report.html +2 -2
- package/package.json +1 -1
- package/src/packages/components/$ai/index.tsx +5 -1
- package/src/packages/components/AiChatBox/index.tsx +25 -6
- package/src/packages/components/AutoTable/use/useTableOption.ai.tsx +225 -67
- package/src/packages/components/FilterFormSingle/index.tsx +178 -178
- package/src/packages/components/FilterService/filter/filter.number.tsx +2 -2
- package/src/packages/components/NumberRange/index.tsx +94 -93
- package/src/packages/entry.tsx +1 -1
|
@@ -1,178 +1,178 @@
|
|
|
1
|
-
import {computed, designComponent, Fragment, PropType, reactive, watch} from "@peryl/react-compose";
|
|
2
|
-
import {PlainObject} from "@peryl/utils/event";
|
|
3
|
-
import {iFilterOption, iFilterQueryParam} from "../FilterService/utils/filter.service.utils";
|
|
4
|
-
import {InputGroup} from "../InputGroup";
|
|
5
|
-
import {Select} from "../Select";
|
|
6
|
-
import {Button} from "../Button";
|
|
7
|
-
import {FilterService} from "../FilterService";
|
|
8
|
-
import {SelectOption} from "../SelectOption";
|
|
9
|
-
import {incrementalMerge} from "../../utils/incrementalMerge";
|
|
10
|
-
import {mergeQueryParam} from "../FilterService/utils/mergeQueryParam";
|
|
11
|
-
import {deepcopy} from "@peryl/utils/deepcopy";
|
|
12
|
-
import i18n from "../i18n";
|
|
13
|
-
|
|
14
|
-
export interface iFilterFormSingleState {
|
|
15
|
-
field: string,
|
|
16
|
-
filterHandler: string,
|
|
17
|
-
formData: PlainObject,
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export type iFilterFormSingleData = iFilterFormSingleState & { filterQueryParam: iFilterQueryParam }
|
|
21
|
-
|
|
22
|
-
export const FilterFormSingle = designComponent({
|
|
23
|
-
name: 'filter-form-single',
|
|
24
|
-
props: {
|
|
25
|
-
filterOptions: { type: Array as PropType<iFilterOption[]> },
|
|
26
|
-
initialState: { type: Object as PropType<iFilterFormSingleState> },
|
|
27
|
-
hideFieldSelector: { type: Boolean },
|
|
28
|
-
hideHandlerSelector: { type: Boolean },
|
|
29
|
-
hideSearchButton: { type: Boolean },
|
|
30
|
-
width: { type: String, default: '440px' },
|
|
31
|
-
handleSearch: { type: Function as PropType<(data: iFilterFormSingleData) => void | Promise<void>> },
|
|
32
|
-
},
|
|
33
|
-
emits: {
|
|
34
|
-
onSearch: (data: iFilterFormSingleData) => true,
|
|
35
|
-
},
|
|
36
|
-
slots: ['prepend', 'append'],
|
|
37
|
-
setup({ props, event: { emit }, slots }) {
|
|
38
|
-
|
|
39
|
-
const utils = {
|
|
40
|
-
createState: ({ defaultField, filterOptions }: { defaultField?: string, filterOptions: iFilterOption[] }): iFilterFormSingleState => {
|
|
41
|
-
const defaultOption = filterOptions.find(i => !!defaultField ? i?.field === defaultField : i?.defaultSearch) || (filterOptions[0] as iFilterOption | undefined) || { label: i18n.$it('base.id').d('编号'), filterType: 'text', filterHandler: 'like', field: 'id' };
|
|
42
|
-
const formData = FilterService.getDefaultFormData(filterOptions);
|
|
43
|
-
return {
|
|
44
|
-
field: defaultOption.field,
|
|
45
|
-
filterHandler: defaultOption.filterHandler,
|
|
46
|
-
formData,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const state: iFilterFormSingleState = reactive(
|
|
52
|
-
deepcopy(props.initialState) ||
|
|
53
|
-
utils.createState({ filterOptions: props.filterOptions || [] })
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* 正在使用的目标filterOptions
|
|
58
|
-
* @author 韦胜健
|
|
59
|
-
* @date 2023.1.6 16:00
|
|
60
|
-
*/
|
|
61
|
-
const usingFilterOption = computed((): iFilterOption => ({
|
|
62
|
-
...(props.filterOptions || []).find(i => i.field === state.field)!,
|
|
63
|
-
filterHandler: state.filterHandler,
|
|
64
|
-
}));
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* props.filterOptions变化时更新内部状态
|
|
68
|
-
* @author 韦胜健
|
|
69
|
-
* @date 2023.1.6 15:57
|
|
70
|
-
*/
|
|
71
|
-
watch(() => props.filterOptions, newFilterOptions => methods.updateFilterOptions(newFilterOptions || []));
|
|
72
|
-
|
|
73
|
-
const methods = {
|
|
74
|
-
/**
|
|
75
|
-
* 获取当前内部状态
|
|
76
|
-
* @author 韦胜健
|
|
77
|
-
* @date 2023.1.6 16:12
|
|
78
|
-
*/
|
|
79
|
-
getState: (): iFilterFormSingleState => ({ ...state }),
|
|
80
|
-
/**
|
|
81
|
-
* 更新当前内部状态
|
|
82
|
-
* @author 韦胜健
|
|
83
|
-
* @date 2023.1.6 16:12
|
|
84
|
-
*/
|
|
85
|
-
update: (newState: iFilterFormSingleState | null | undefined) => {
|
|
86
|
-
if (!!newState) {
|
|
87
|
-
Object.assign(state, newState);
|
|
88
|
-
} else {
|
|
89
|
-
Object.assign(state, utils.createState({ filterOptions: props.filterOptions || [] }));
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
/**
|
|
93
|
-
* 合并新的filterOptions
|
|
94
|
-
* @author 韦胜健
|
|
95
|
-
* @date 2023.1.6 15:49
|
|
96
|
-
*/
|
|
97
|
-
updateFilterOptions: (filterOptions: iFilterOption[]) => {
|
|
98
|
-
const { formData, filterHandler } = utils.createState({ defaultField: state.field, filterOptions: filterOptions || [] });
|
|
99
|
-
state.formData = incrementalMerge(state.formData, formData);
|
|
100
|
-
state.filterHandler = filterHandler;
|
|
101
|
-
},
|
|
102
|
-
/**
|
|
103
|
-
* 获取查询数据
|
|
104
|
-
* @author 韦胜健
|
|
105
|
-
* @date 2023.1.6 18:32
|
|
106
|
-
*/
|
|
107
|
-
getData: async () => {
|
|
108
|
-
const { field, formData, filterHandler } = state;
|
|
109
|
-
const queryParam = await FilterService.getQueryParam({ option: usingFilterOption.value, formData: state.formData });
|
|
110
|
-
const filterQueryParam = !queryParam ? {} : mergeQueryParam(queryParam, {});
|
|
111
|
-
return deepcopy({ field, formData, filterHandler, filterQueryParam });
|
|
112
|
-
},
|
|
113
|
-
/**
|
|
114
|
-
* 搜索
|
|
115
|
-
* @author 韦胜健
|
|
116
|
-
* @date 2023.1.6 12:46
|
|
117
|
-
*/
|
|
118
|
-
search: async () => {
|
|
119
|
-
const data = await methods.getData();
|
|
120
|
-
emit.onSearch(data);
|
|
121
|
-
await props.handleSearch?.(data);
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
const handler = {
|
|
126
|
-
onUpdateField: (field: any) => {
|
|
127
|
-
const newState = utils.createState({ defaultField: field, filterOptions: props.filterOptions || [] });
|
|
128
|
-
const handler = FilterService.getHandler(usingFilterOption.value)!;
|
|
129
|
-
handler.clearValue({ formData: state.formData, option: usingFilterOption.value });
|
|
130
|
-
state.filterHandler = newState.filterHandler;
|
|
131
|
-
state.field = field;
|
|
132
|
-
// console.log({ ...state }, props.filterOptions);
|
|
133
|
-
},
|
|
134
|
-
onUpdateHandler: (filterHandler?: any) => {
|
|
135
|
-
const handler = FilterService.getHandler(usingFilterOption.value)!;
|
|
136
|
-
handler.clearValue({ formData: state.formData, option: usingFilterOption.value });
|
|
137
|
-
state.filterHandler = filterHandler;
|
|
138
|
-
},
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
const inputAttrs = { noClear: true };
|
|
142
|
-
|
|
143
|
-
return {
|
|
144
|
-
refer: {
|
|
145
|
-
state,
|
|
146
|
-
...methods,
|
|
147
|
-
},
|
|
148
|
-
render: () => (
|
|
149
|
-
<InputGroup style={{ width: props.width }}>
|
|
150
|
-
{slots.prepend()}
|
|
151
|
-
{!props.hideFieldSelector && (
|
|
152
|
-
<Select key="field_selector" width={90} modelValue={state.field} onUpdateModelValue={handler.onUpdateField} inputAttrs={inputAttrs}>
|
|
153
|
-
{(props.filterOptions || []).map((option) => (
|
|
154
|
-
<SelectOption label={option.label} val={option.field} key={option.label + option.field}/>
|
|
155
|
-
))}
|
|
156
|
-
</Select>
|
|
157
|
-
)}
|
|
158
|
-
{!props.hideHandlerSelector && (
|
|
159
|
-
<Select key={state.field} width={90} modelValue={state.filterHandler} onUpdateModelValue={handler.onUpdateHandler} inputAttrs={inputAttrs}>
|
|
160
|
-
{(FilterService.touch(usingFilterOption.value.filterType)).state.list.map((handler) => (
|
|
161
|
-
<SelectOption label={handler.label()} val={handler.name} key={handler.name}/>
|
|
162
|
-
))}
|
|
163
|
-
</Select>
|
|
164
|
-
)}
|
|
165
|
-
<Fragment key={state.filterHandler}>
|
|
166
|
-
{FilterService.getHandler(usingFilterOption.value)!.render({ formData: state.formData, option: usingFilterOption.value, confirm: methods.search })}
|
|
167
|
-
</Fragment>
|
|
168
|
-
{!props.hideSearchButton && (
|
|
169
|
-
<Button label={i18n.$it('base.query').d('查询')} icon="pi-search" mode="fill" asyncHandler={methods.search}/>
|
|
170
|
-
)}
|
|
171
|
-
{slots.append()}
|
|
172
|
-
</InputGroup>
|
|
173
|
-
)
|
|
174
|
-
};
|
|
175
|
-
},
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
export default FilterFormSingle;
|
|
1
|
+
import {computed, designComponent, Fragment, PropType, reactive, watch} from "@peryl/react-compose";
|
|
2
|
+
import {PlainObject} from "@peryl/utils/event";
|
|
3
|
+
import {iFilterOption, iFilterQueryParam} from "../FilterService/utils/filter.service.utils";
|
|
4
|
+
import {InputGroup} from "../InputGroup";
|
|
5
|
+
import {Select} from "../Select";
|
|
6
|
+
import {Button} from "../Button";
|
|
7
|
+
import {FilterService} from "../FilterService";
|
|
8
|
+
import {SelectOption} from "../SelectOption";
|
|
9
|
+
import {incrementalMerge} from "../../utils/incrementalMerge";
|
|
10
|
+
import {mergeQueryParam} from "../FilterService/utils/mergeQueryParam";
|
|
11
|
+
import {deepcopy} from "@peryl/utils/deepcopy";
|
|
12
|
+
import i18n from "../i18n";
|
|
13
|
+
|
|
14
|
+
export interface iFilterFormSingleState {
|
|
15
|
+
field: string,
|
|
16
|
+
filterHandler: string,
|
|
17
|
+
formData: PlainObject,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type iFilterFormSingleData = iFilterFormSingleState & { filterQueryParam: iFilterQueryParam }
|
|
21
|
+
|
|
22
|
+
export const FilterFormSingle = designComponent({
|
|
23
|
+
name: 'filter-form-single',
|
|
24
|
+
props: {
|
|
25
|
+
filterOptions: { type: Array as PropType<iFilterOption[]> },
|
|
26
|
+
initialState: { type: Object as PropType<iFilterFormSingleState> },
|
|
27
|
+
hideFieldSelector: { type: Boolean },
|
|
28
|
+
hideHandlerSelector: { type: Boolean },
|
|
29
|
+
hideSearchButton: { type: Boolean },
|
|
30
|
+
width: { type: String, default: '440px' },
|
|
31
|
+
handleSearch: { type: Function as PropType<(data: iFilterFormSingleData) => void | Promise<void>> },
|
|
32
|
+
},
|
|
33
|
+
emits: {
|
|
34
|
+
onSearch: (data: iFilterFormSingleData) => true,
|
|
35
|
+
},
|
|
36
|
+
slots: ['prepend', 'append'],
|
|
37
|
+
setup({ props, event: { emit }, slots }) {
|
|
38
|
+
|
|
39
|
+
const utils = {
|
|
40
|
+
createState: ({ defaultField, filterOptions }: { defaultField?: string, filterOptions: iFilterOption[] }): iFilterFormSingleState => {
|
|
41
|
+
const defaultOption = filterOptions.find(i => !!defaultField ? i?.field === defaultField : i?.defaultSearch) || (filterOptions[0] as iFilterOption | undefined) || { label: i18n.$it('base.id').d('编号'), filterType: 'text', filterHandler: 'like', field: 'id' };
|
|
42
|
+
const formData = FilterService.getDefaultFormData(filterOptions);
|
|
43
|
+
return {
|
|
44
|
+
field: defaultOption.field,
|
|
45
|
+
filterHandler: defaultOption.filterHandler,
|
|
46
|
+
formData,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const state: iFilterFormSingleState = reactive(
|
|
52
|
+
deepcopy(props.initialState) ||
|
|
53
|
+
utils.createState({ filterOptions: props.filterOptions || [] })
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 正在使用的目标filterOptions
|
|
58
|
+
* @author 韦胜健
|
|
59
|
+
* @date 2023.1.6 16:00
|
|
60
|
+
*/
|
|
61
|
+
const usingFilterOption = computed((): iFilterOption => ({
|
|
62
|
+
...(props.filterOptions || []).find(i => i.field === state.field)!,
|
|
63
|
+
filterHandler: state.filterHandler,
|
|
64
|
+
}));
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* props.filterOptions变化时更新内部状态
|
|
68
|
+
* @author 韦胜健
|
|
69
|
+
* @date 2023.1.6 15:57
|
|
70
|
+
*/
|
|
71
|
+
watch(() => props.filterOptions, newFilterOptions => methods.updateFilterOptions(newFilterOptions || []));
|
|
72
|
+
|
|
73
|
+
const methods = {
|
|
74
|
+
/**
|
|
75
|
+
* 获取当前内部状态
|
|
76
|
+
* @author 韦胜健
|
|
77
|
+
* @date 2023.1.6 16:12
|
|
78
|
+
*/
|
|
79
|
+
getState: (): iFilterFormSingleState => ({ ...state }),
|
|
80
|
+
/**
|
|
81
|
+
* 更新当前内部状态
|
|
82
|
+
* @author 韦胜健
|
|
83
|
+
* @date 2023.1.6 16:12
|
|
84
|
+
*/
|
|
85
|
+
update: (newState: iFilterFormSingleState | null | undefined) => {
|
|
86
|
+
if (!!newState) {
|
|
87
|
+
Object.assign(state, newState);
|
|
88
|
+
} else {
|
|
89
|
+
Object.assign(state, utils.createState({ filterOptions: props.filterOptions || [] }));
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
/**
|
|
93
|
+
* 合并新的filterOptions
|
|
94
|
+
* @author 韦胜健
|
|
95
|
+
* @date 2023.1.6 15:49
|
|
96
|
+
*/
|
|
97
|
+
updateFilterOptions: (filterOptions: iFilterOption[]) => {
|
|
98
|
+
const { formData, filterHandler } = utils.createState({ defaultField: state.field, filterOptions: filterOptions || [] });
|
|
99
|
+
state.formData = incrementalMerge(state.formData, formData);
|
|
100
|
+
state.filterHandler = filterHandler;
|
|
101
|
+
},
|
|
102
|
+
/**
|
|
103
|
+
* 获取查询数据
|
|
104
|
+
* @author 韦胜健
|
|
105
|
+
* @date 2023.1.6 18:32
|
|
106
|
+
*/
|
|
107
|
+
getData: async () => {
|
|
108
|
+
const { field, formData, filterHandler } = state;
|
|
109
|
+
const queryParam = await FilterService.getQueryParam({ option: usingFilterOption.value, formData: state.formData });
|
|
110
|
+
const filterQueryParam = !queryParam ? {} : mergeQueryParam(queryParam, {});
|
|
111
|
+
return deepcopy({ field, formData, filterHandler, filterQueryParam });
|
|
112
|
+
},
|
|
113
|
+
/**
|
|
114
|
+
* 搜索
|
|
115
|
+
* @author 韦胜健
|
|
116
|
+
* @date 2023.1.6 12:46
|
|
117
|
+
*/
|
|
118
|
+
search: async () => {
|
|
119
|
+
const data = await methods.getData();
|
|
120
|
+
emit.onSearch(data);
|
|
121
|
+
await props.handleSearch?.(data);
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const handler = {
|
|
126
|
+
onUpdateField: (field: any) => {
|
|
127
|
+
const newState = utils.createState({ defaultField: field, filterOptions: props.filterOptions || [] });
|
|
128
|
+
const handler = FilterService.getHandler(usingFilterOption.value)!;
|
|
129
|
+
handler.clearValue({ formData: state.formData, option: usingFilterOption.value });
|
|
130
|
+
state.filterHandler = newState.filterHandler;
|
|
131
|
+
state.field = field;
|
|
132
|
+
// console.log({ ...state }, props.filterOptions);
|
|
133
|
+
},
|
|
134
|
+
onUpdateHandler: (filterHandler?: any) => {
|
|
135
|
+
const handler = FilterService.getHandler(usingFilterOption.value)!;
|
|
136
|
+
handler.clearValue({ formData: state.formData, option: usingFilterOption.value });
|
|
137
|
+
state.filterHandler = filterHandler;
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const inputAttrs = { noClear: true };
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
refer: {
|
|
145
|
+
state,
|
|
146
|
+
...methods,
|
|
147
|
+
},
|
|
148
|
+
render: () => (
|
|
149
|
+
<InputGroup style={{ width: props.width }}>
|
|
150
|
+
{slots.prepend()}
|
|
151
|
+
{!props.hideFieldSelector && (
|
|
152
|
+
<Select key="field_selector" width={90} modelValue={state.field} onUpdateModelValue={handler.onUpdateField} inputAttrs={inputAttrs}>
|
|
153
|
+
{(props.filterOptions || []).map((option) => (
|
|
154
|
+
<SelectOption label={option.label} val={option.field} key={option.label + option.field}/>
|
|
155
|
+
))}
|
|
156
|
+
</Select>
|
|
157
|
+
)}
|
|
158
|
+
{!props.hideHandlerSelector && (
|
|
159
|
+
<Select key={state.field} width={90} modelValue={state.filterHandler} onUpdateModelValue={handler.onUpdateHandler} inputAttrs={inputAttrs}>
|
|
160
|
+
{(FilterService.touch(usingFilterOption.value.filterType)).state.list.map((handler) => (
|
|
161
|
+
<SelectOption label={handler.label()} val={handler.name} key={handler.name}/>
|
|
162
|
+
))}
|
|
163
|
+
</Select>
|
|
164
|
+
)}
|
|
165
|
+
<Fragment key={state.filterHandler}>
|
|
166
|
+
{FilterService.getHandler(usingFilterOption.value)!.render({ formData: state.formData, option: usingFilterOption.value, confirm: methods.search })}
|
|
167
|
+
</Fragment>
|
|
168
|
+
{!props.hideSearchButton && (
|
|
169
|
+
<Button label={i18n.$it('base.query').d('查询')} icon="pi-search" mode="fill" asyncHandler={methods.search}/>
|
|
170
|
+
)}
|
|
171
|
+
{slots.append()}
|
|
172
|
+
</InputGroup>
|
|
173
|
+
)
|
|
174
|
+
};
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
export default FilterFormSingle;
|
|
@@ -30,8 +30,8 @@ export function installFilterNumber(
|
|
|
30
30
|
<NumberRange
|
|
31
31
|
v-model:start={formData[option.startField]}
|
|
32
32
|
v-model:end={formData[option.endField]}
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
onEnterStart={confirm}
|
|
34
|
+
onEnterEnd={confirm}
|
|
35
35
|
noGroupWrapper
|
|
36
36
|
/>
|
|
37
37
|
),
|
|
@@ -1,93 +1,94 @@
|
|
|
1
|
-
import {computed, designComponent, PropType, useModel} from "@peryl/react-compose";
|
|
2
|
-
import {InputGroup} from "../InputGroup";
|
|
3
|
-
import {InputNumber} from "../InputNumber";
|
|
4
|
-
import {Input} from "../Input";
|
|
5
|
-
import {PlainObject} from "@peryl/utils/event";
|
|
6
|
-
|
|
7
|
-
export const NumberRange = designComponent({
|
|
8
|
-
name: 'number-range',
|
|
9
|
-
props: {
|
|
10
|
-
start: { type: [String, Number] },
|
|
11
|
-
end: { type: [String, Number] },
|
|
12
|
-
startAttrs: { type: Object as PropType<PlainObject> },
|
|
13
|
-
endAttrs: { type: Object as PropType<PlainObject> },
|
|
14
|
-
noGroupWrapper: { type: Boolean },
|
|
15
|
-
},
|
|
16
|
-
emits: {
|
|
17
|
-
onUpdateStart: (val?: string | number) => true,
|
|
18
|
-
onUpdateEnd: (val?: string | number) => true,
|
|
19
|
-
onBlur: () => true,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
let
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
let
|
|
37
|
-
let
|
|
38
|
-
let
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
1
|
+
import {computed, designComponent, PropType, useModel} from "@peryl/react-compose";
|
|
2
|
+
import {InputGroup} from "../InputGroup";
|
|
3
|
+
import {InputNumber} from "../InputNumber";
|
|
4
|
+
import {Input} from "../Input";
|
|
5
|
+
import {PlainObject} from "@peryl/utils/event";
|
|
6
|
+
|
|
7
|
+
export const NumberRange = designComponent({
|
|
8
|
+
name: 'number-range',
|
|
9
|
+
props: {
|
|
10
|
+
start: { type: [String, Number] },
|
|
11
|
+
end: { type: [String, Number] },
|
|
12
|
+
startAttrs: { type: Object as PropType<PlainObject> },
|
|
13
|
+
endAttrs: { type: Object as PropType<PlainObject> },
|
|
14
|
+
noGroupWrapper: { type: Boolean },
|
|
15
|
+
},
|
|
16
|
+
emits: {
|
|
17
|
+
onUpdateStart: (val?: string | number) => true,
|
|
18
|
+
onUpdateEnd: (val?: string | number) => true,
|
|
19
|
+
onBlur: () => true,
|
|
20
|
+
onClear: () => true,
|
|
21
|
+
onEnterStart: () => true,
|
|
22
|
+
onEnterEnd: () => true,
|
|
23
|
+
},
|
|
24
|
+
setup({ props, event: { emit } }) {
|
|
25
|
+
|
|
26
|
+
const startModel = useModel(() => props.start, emit.onUpdateStart);
|
|
27
|
+
const endModel = useModel(() => props.end, emit.onUpdateEnd);
|
|
28
|
+
|
|
29
|
+
const placeValue = computed(() => {
|
|
30
|
+
let start = startModel.value == null ? '' : String(startModel.value).trim();
|
|
31
|
+
let end = endModel.value == null ? '' : String(endModel.value).trim();
|
|
32
|
+
return start + end;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const checkRange = () => {
|
|
36
|
+
let start = startModel.value;
|
|
37
|
+
let end = endModel.value;
|
|
38
|
+
let startNum = Number(start);
|
|
39
|
+
let endNum = Number(end);
|
|
40
|
+
if (start == null || end == null || isNaN(startNum) || isNaN(endNum)) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (startNum > endNum) {
|
|
44
|
+
[startNum, endNum] = [endNum, startNum];
|
|
45
|
+
startModel.value = startNum;
|
|
46
|
+
endModel.value = endNum;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const handler = {
|
|
51
|
+
onBlur: (): void => {
|
|
52
|
+
checkRange();
|
|
53
|
+
emit.onBlur();
|
|
54
|
+
},
|
|
55
|
+
onEnter: (type: 'start' | 'end') => {
|
|
56
|
+
checkRange();
|
|
57
|
+
type === "start" ? emit.onEnterStart() : emit.onEnterEnd();
|
|
58
|
+
},
|
|
59
|
+
onClear: () => {
|
|
60
|
+
startModel.value = undefined;
|
|
61
|
+
endModel.value = undefined;
|
|
62
|
+
emit.onClear();
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
return () => {
|
|
67
|
+
const content = (
|
|
68
|
+
<Input
|
|
69
|
+
suffixIcon="pi-original-size"
|
|
70
|
+
placeValue={placeValue.value}
|
|
71
|
+
clearHandler={handler.onClear}
|
|
72
|
+
>
|
|
73
|
+
<InputNumber v-model={startModel.value} onBlur={handler.onBlur} button={null} align="center" onEnter={() => handler.onEnter('start')} {...{
|
|
74
|
+
...props.startAttrs || {},
|
|
75
|
+
inputAttrs: {
|
|
76
|
+
...props.startAttrs?.inputAttrs,
|
|
77
|
+
bare: true,
|
|
78
|
+
},
|
|
79
|
+
}}/>
|
|
80
|
+
<InputNumber v-model={endModel.value} onBlur={handler.onBlur} button={null} align="center" onEnter={() => handler.onEnter('end')} {...{
|
|
81
|
+
...props.endAttrs || {},
|
|
82
|
+
inputAttrs: {
|
|
83
|
+
...props.endAttrs?.inputAttrs,
|
|
84
|
+
bare: true,
|
|
85
|
+
},
|
|
86
|
+
}}/>
|
|
87
|
+
</Input>
|
|
88
|
+
);
|
|
89
|
+
return (props.noGroupWrapper ? content : (<InputGroup>{content}</InputGroup>));
|
|
90
|
+
};
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
export default NumberRange;
|
package/src/packages/entry.tsx
CHANGED
|
@@ -136,7 +136,7 @@ export {Corner} from './components/Corner';
|
|
|
136
136
|
export {useContextmenuOptions} from './components/useContextmenuOptions';
|
|
137
137
|
export type {iContextmenuOption} from './components/useContextmenuOptions';
|
|
138
138
|
export {AiChatBox} from './components/AiChatBox';
|
|
139
|
-
export type {iChatBoxHistory} from './components/AiChatBox';
|
|
139
|
+
export type {iChatBoxHandleMessage, iChatBoxHistory} from './components/AiChatBox';
|
|
140
140
|
export {$ai} from './components/$ai';
|
|
141
141
|
export type {iAiChoice, iAiChatResponse, iAiConfiguration, iAiHistory} from './components/$ai';
|
|
142
142
|
export {IconPicker} from './components/IconPicker';
|