plain-design 1.0.0-beta.161 → 1.0.0-beta.163
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 +8 -1
- package/src/packages/components/AiChatBox/index.tsx +35 -9
- package/src/packages/components/FilterFormSingle/index.tsx +178 -178
- package/src/packages/components/FilterService/filter/filter.number.tsx +2 -2
- package/src/packages/components/Icon/icon.external.tsx +10 -0
- package/src/packages/components/NumberRange/index.tsx +94 -93
package/package.json
CHANGED
|
@@ -10,6 +10,7 @@ import {uuid} from "@peryl/utils/uuid";
|
|
|
10
10
|
import {PlainObject} from "@peryl/utils/event";
|
|
11
11
|
import {defer} from "@peryl/utils/defer";
|
|
12
12
|
import {toArray} from "@peryl/utils/toArray";
|
|
13
|
+
import {iEffects} from "@peryl/utils/createEffects";
|
|
13
14
|
|
|
14
15
|
export const $ai = (() => {
|
|
15
16
|
|
|
@@ -100,9 +101,13 @@ export const $ai = (() => {
|
|
|
100
101
|
onThinking,
|
|
101
102
|
onThinkEnd,
|
|
102
103
|
onThinkStart,
|
|
104
|
+
abortEffects,
|
|
103
105
|
}: iAiChatStreamParameter
|
|
104
106
|
) => {
|
|
105
107
|
const aiConfig = _aiConfig ?? getConfig();
|
|
108
|
+
|
|
109
|
+
const controller = new AbortController();
|
|
110
|
+
!!abortEffects && abortEffects.push(() => {controller.abort('abort stream.');});
|
|
106
111
|
// 发送请求
|
|
107
112
|
const response = await fetch(aiConfig.url, {
|
|
108
113
|
method: 'POST',
|
|
@@ -115,7 +120,8 @@ export const $ai = (() => {
|
|
|
115
120
|
"messages": messages,
|
|
116
121
|
// "messages": [{ role: 'user', content: '你好' }],
|
|
117
122
|
stream: true // 请求流式响应
|
|
118
|
-
})
|
|
123
|
+
}),
|
|
124
|
+
signal: controller.signal,
|
|
119
125
|
});
|
|
120
126
|
|
|
121
127
|
if (!response.ok || !response.body) {throw response;}
|
|
@@ -357,4 +363,5 @@ export interface iAiChatStreamParameter {
|
|
|
357
363
|
onThinking?: (thinkText: string) => void,
|
|
358
364
|
onThinkStart?: () => void,
|
|
359
365
|
onThinkEnd?: () => void,
|
|
366
|
+
abortEffects?: iEffects,
|
|
360
367
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {designComponent, getComponentCls, iKeyboardEvent, PropType, reactive, useClasses, useRefs} from "@peryl/react-compose";
|
|
1
|
+
import {designComponent, getComponentCls, iKeyboardEvent, PropType, reactive, useClasses, useModel, useRefs} from "@peryl/react-compose";
|
|
2
2
|
import Input from "../Input";
|
|
3
3
|
import {EditProps, useEdit} from "../../uses/useEdit";
|
|
4
4
|
import {StyleProps, useStyle} from "../../uses/useStyle";
|
|
@@ -13,6 +13,7 @@ import Scroll from "../Scroll";
|
|
|
13
13
|
import {delay} from "@peryl/utils/delay";
|
|
14
14
|
import {toArray} from "@peryl/utils/toArray";
|
|
15
15
|
import {lastItem} from "@peryl/utils/lastItem";
|
|
16
|
+
import {createEffects} from "@peryl/utils/createEffects";
|
|
16
17
|
|
|
17
18
|
export const AiChatBox = designComponent({
|
|
18
19
|
props: {
|
|
@@ -26,6 +27,8 @@ export const AiChatBox = designComponent({
|
|
|
26
27
|
histories: { type: Array as PropType<iChatBoxHistory[]> },
|
|
27
28
|
/*系统提示词*/
|
|
28
29
|
systemContent: { type: String },
|
|
30
|
+
/*用户输入的内容*/
|
|
31
|
+
modelValue: { type: String },
|
|
29
32
|
/*手动处理大模型返回的message*/
|
|
30
33
|
handleMessage: { type: Function as PropType<iChatBoxHandleMessage> },
|
|
31
34
|
handleReceive: { type: Function as PropType<(data: { fullText?: string, chunkText?: string }) => void> },
|
|
@@ -33,9 +36,16 @@ export const AiChatBox = designComponent({
|
|
|
33
36
|
handleChatStream: { type: Function as PropType<(parameter: iAiChatStreamParameter & { userContent: string }) => Promise<any>> },
|
|
34
37
|
inputMinHeight: { type: String, default: '80px' },
|
|
35
38
|
inputMaxHeight: { type: String, default: '225px' },
|
|
39
|
+
enableMemory: { type: Boolean },
|
|
40
|
+
memoryLimit: { type: Number, default: 15 },
|
|
36
41
|
},
|
|
37
42
|
slots: ['prepend'],
|
|
38
|
-
|
|
43
|
+
emits: {
|
|
44
|
+
onUpdateModelValue: (val?: string) => true,
|
|
45
|
+
},
|
|
46
|
+
setup({ props, slots, event: { emit } }) {
|
|
47
|
+
|
|
48
|
+
const model = useModel(() => props.modelValue, emit.onUpdateModelValue);
|
|
39
49
|
|
|
40
50
|
const { refs, onRef } = useRefs({ scroll: Scroll });
|
|
41
51
|
|
|
@@ -53,11 +63,12 @@ export const AiChatBox = designComponent({
|
|
|
53
63
|
]);
|
|
54
64
|
|
|
55
65
|
const state = reactive({
|
|
56
|
-
userContent: '',
|
|
57
66
|
histories: props.histories || [] as iChatBoxHistory[],
|
|
58
67
|
loading: false
|
|
59
68
|
});
|
|
60
69
|
|
|
70
|
+
const { effects: abortEffects } = createEffects();
|
|
71
|
+
|
|
61
72
|
const methods = {
|
|
62
73
|
scrollEnd: async () => {
|
|
63
74
|
if (!!refs.scroll) {
|
|
@@ -73,11 +84,16 @@ export const AiChatBox = designComponent({
|
|
|
73
84
|
},
|
|
74
85
|
send: async (userContent: string) => {
|
|
75
86
|
await delay(23);
|
|
76
|
-
|
|
77
|
-
|
|
87
|
+
model.value = '';
|
|
88
|
+
const newUserHistory: iChatBoxHistory = { role: 'user', content: userContent, id: uuid() };
|
|
89
|
+
await methods.addHistory(newUserHistory);
|
|
78
90
|
|
|
79
91
|
/*const { message, chatData } = await $ai.chatSystem(userContent, props.systemContent, aiConfig);*/
|
|
80
|
-
|
|
92
|
+
let messages: iAiHistory[] = props.enableMemory ? state.histories : (() => {
|
|
93
|
+
const { role, content } = newUserHistory;
|
|
94
|
+
return [{ role, content }];
|
|
95
|
+
})();
|
|
96
|
+
messages = messages.slice(props.memoryLimit * -1);
|
|
81
97
|
await props.beforeSendUserContent?.({ userContent, messages });
|
|
82
98
|
if (!!props.systemContent?.trim().length) {messages.unshift({ role: 'system', content: props.systemContent });}
|
|
83
99
|
let chatBoxHistory: iChatBoxHistory | undefined = undefined;
|
|
@@ -87,6 +103,7 @@ export const AiChatBox = designComponent({
|
|
|
87
103
|
aiConfig,
|
|
88
104
|
messages,
|
|
89
105
|
userContent,
|
|
106
|
+
abortEffects,
|
|
90
107
|
onReceiving: ({ fullText, chunkText }) => {
|
|
91
108
|
// console.log('receiving', fullText);
|
|
92
109
|
props.handleReceive?.({ fullText, chunkText });
|
|
@@ -133,9 +150,18 @@ export const AiChatBox = designComponent({
|
|
|
133
150
|
|
|
134
151
|
const handler = {
|
|
135
152
|
onClickSend: async () => {
|
|
153
|
+
if (state.loading) {
|
|
154
|
+
console.log('abort');
|
|
155
|
+
abortEffects.clear();
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
console.log('send');
|
|
160
|
+
abortEffects.clear();
|
|
161
|
+
abortEffects.push(() => state.loading = false);
|
|
136
162
|
state.loading = true;
|
|
137
163
|
try {
|
|
138
|
-
const userContent =
|
|
164
|
+
const userContent = model.value;
|
|
139
165
|
if (!userContent?.trim().length) {
|
|
140
166
|
$message.error(i18n.$it('ai.require').d('提问的内容不能为空'));
|
|
141
167
|
return;
|
|
@@ -187,13 +213,13 @@ export const AiChatBox = designComponent({
|
|
|
187
213
|
<Input
|
|
188
214
|
readonly={state.loading}
|
|
189
215
|
textarea
|
|
190
|
-
v-model={
|
|
216
|
+
v-model={model.value}
|
|
191
217
|
placeholder={props.placeholder || i18n.$it('ai.placeholder').d('请输入要发送给ai的内容如:你是谁')}
|
|
192
218
|
minHeight={props.inputMinHeight}
|
|
193
219
|
maxHeight={props.inputMaxHeight}
|
|
194
220
|
onEnter={handler.onEnterTextarea}
|
|
195
221
|
/>
|
|
196
|
-
<Button shape="round" mode="fill" icon=
|
|
222
|
+
<Button shape="round" mode="fill" icon={state.loading ? 'ie-stop' : 'ie-send'} className="ai-chat-box-send-button" onClick={handler.onClickSend}/>
|
|
197
223
|
</div>
|
|
198
224
|
</div>
|
|
199
225
|
)
|
|
@@ -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
|
),
|
|
@@ -103,5 +103,15 @@ export const IconExternal: Record<string, () => RenderNode> = {
|
|
|
103
103
|
<path
|
|
104
104
|
d="M15.5355 2.80744C17.0976 1.24534 19.6303 1.24534 21.1924 2.80744C22.7545 4.36953 22.7545 6.90219 21.1924 8.46429L18.3638 11.2929L18.7175 11.6466C19.108 12.0371 19.108 12.6703 18.7175 13.0608C18.327 13.4513 17.6938 13.4513 17.3033 13.0608L16.9498 12.7073L10.7351 18.922C10.1767 19.4804 9.46547 19.861 8.6911 20.0159L6.93694 20.3667C6.54976 20.4442 6.19416 20.6345 5.91496 20.9137L4.92894 21.8997C4.53841 22.2902 3.90525 22.2902 3.51472 21.8997L2.10051 20.4855C1.70999 20.095 1.70999 19.4618 2.10051 19.0713L3.08653 18.0852C3.36574 17.806 3.55605 17.4504 3.63348 17.0633L3.98431 15.3091C4.13919 14.5347 4.51981 13.8235 5.07821 13.2651L11.2929 7.05045L10.9393 6.69686C10.5488 6.30634 10.5488 5.67317 10.9393 5.28265C11.3299 4.89212 11.963 4.89212 12.3535 5.28265L12.7069 5.63604L15.5355 2.80744ZM12.7071 8.46466L6.49242 14.6794C6.21322 14.9586 6.02291 15.3142 5.94548 15.7013L5.59464 17.4555C5.43977 18.2299 5.05915 18.9411 4.50075 19.4995C5.05915 18.9411 5.77035 18.5604 6.54471 18.4056L8.29887 18.0547C8.68605 17.9773 9.04165 17.787 9.32085 17.5078L15.5355 11.2931L12.7071 8.46466Z"></path>
|
|
105
105
|
</svg>
|
|
106
|
+
),
|
|
107
|
+
'ie-send': () => (
|
|
108
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
|
109
|
+
<path d="M1.94607 9.31543C1.42353 9.14125 1.4194 8.86022 1.95682 8.68108L21.043 2.31901C21.5715 2.14285 21.8746 2.43866 21.7265 2.95694L16.2733 22.0432C16.1223 22.5716 15.8177 22.59 15.5944 22.0876L11.9999 14L17.9999 6.00005L9.99992 12L1.94607 9.31543Z"></path>
|
|
110
|
+
</svg>
|
|
111
|
+
),
|
|
112
|
+
'ie-stop': () => (
|
|
113
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
|
114
|
+
<path d="M6 5H18C18.5523 5 19 5.44772 19 6V18C19 18.5523 18.5523 19 18 19H6C5.44772 19 5 18.5523 5 18V6C5 5.44772 5.44772 5 6 5Z"></path>
|
|
115
|
+
</svg>
|
|
106
116
|
)
|
|
107
117
|
};
|