| 
									
										
										
										
											2025-10-22 14:43:42 +08:00
										 |  |  | import { DownOutlined, UpOutlined } from "@ant-design/icons"; | 
					
						
							|  |  |  | import { Button, Col, Form, Row } from "antd"; | 
					
						
							|  |  |  | import { useEffect, useRef, useState } from "react"; | 
					
						
							|  |  |  | import FormItemsRenderer from "../FormBuilder/FormItemsRenderer"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * 搜索表单组件 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const Search = (props) => { | 
					
						
							|  |  |  |   const { | 
					
						
							|  |  |  |     labelCol = { span: 4 }, | 
					
						
							|  |  |  |     options = [], | 
					
						
							|  |  |  |     values, | 
					
						
							|  |  |  |     onFinish, | 
					
						
							|  |  |  |     onSubmit, | 
					
						
							|  |  |  |     onReset, | 
					
						
							|  |  |  |     searchText = "搜索", | 
					
						
							|  |  |  |     resetText = "重置", | 
					
						
							|  |  |  |     showSearchButton = true, | 
					
						
							|  |  |  |     showResetButton = true, | 
					
						
							|  |  |  |     extraButtons, | 
					
						
							|  |  |  |     form, | 
					
						
							|  |  |  |     ...restProps | 
					
						
							|  |  |  |   } = props; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const [collapse, setCollapse] = useState(true); | 
					
						
							|  |  |  |   const [span, setSpan] = useState(6); | 
					
						
							|  |  |  |   const [showCollapseButton, setShowCollapseButton] = useState(false); | 
					
						
							|  |  |  |   const classNameRef = useRef(`search-${Date.now()}`); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // 计算是否需要显示展开/收起按钮
 | 
					
						
							|  |  |  |   useEffect(() => { | 
					
						
							|  |  |  |     if (!options || options.length === 0) | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const calculateLayout = () => { | 
					
						
							|  |  |  |       const colEl = document.querySelectorAll( | 
					
						
							|  |  |  |         `.${classNameRef.current}>.${window.process.env.app.antd["ant-prefix"]}-col`, | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  |       const colElLength = colEl.length; | 
					
						
							|  |  |  |       const excludeLast = colElLength - (extraButtons ? 2 : 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const spanMap = { 0: 24, 1: 18, 2: 12, 3: 6 }; | 
					
						
							|  |  |  |       setSpan(spanMap[excludeLast % 4] || 6); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       setShowCollapseButton(excludeLast > 3); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 延迟执行以确保 DOM 已渲染
 | 
					
						
							|  |  |  |     setTimeout(calculateLayout, 0); | 
					
						
							|  |  |  |   }, [options, extraButtons]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // 处理表单提交
 | 
					
						
							|  |  |  |   const handleSubmit = () => { | 
					
						
							|  |  |  |     const values = form.getFieldsValue(); | 
					
						
							|  |  |  |     onFinish?.(values, "submit"); | 
					
						
							|  |  |  |     onSubmit?.(values); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // 处理重置
 | 
					
						
							|  |  |  |   const handleReset = () => { | 
					
						
							|  |  |  |     form.resetFields(); | 
					
						
							|  |  |  |     const values = form.getFieldsValue(); | 
					
						
							|  |  |  |     onFinish?.(values, "reset"); | 
					
						
							|  |  |  |     onReset?.(values); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // 切换展开/收起
 | 
					
						
							|  |  |  |   const toggleCollapse = () => { | 
					
						
							|  |  |  |     setCollapse(!collapse); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <Form | 
					
						
							|  |  |  |       form={form} | 
					
						
							|  |  |  |       labelCol={labelCol} | 
					
						
							|  |  |  |       initialValues={values} | 
					
						
							|  |  |  |       {...restProps} | 
					
						
							|  |  |  |     > | 
					
						
							|  |  |  |       <Row className={classNameRef.current}> | 
					
						
							|  |  |  |         <FormItemsRenderer | 
					
						
							|  |  |  |           options={options} | 
					
						
							| 
									
										
										
										
											2025-10-28 12:30:57 +08:00
										 |  |  |           labelCol={labelCol} | 
					
						
							| 
									
										
										
										
											2025-10-22 14:43:42 +08:00
										 |  |  |           span={6} | 
					
						
							|  |  |  |           collapse={collapse} | 
					
						
							|  |  |  |           useAutoGenerateRequired={false} | 
					
						
							|  |  |  |         /> | 
					
						
							|  |  |  |         <Col span={showCollapseButton ? (collapse ? 6 : span) : span}> | 
					
						
							|  |  |  |           <Form.Item label=" " colon={false} style={{ textAlign: "right" }}> | 
					
						
							|  |  |  |             {showSearchButton && ( | 
					
						
							|  |  |  |               <Button type="primary" onClick={handleSubmit}> | 
					
						
							|  |  |  |                 {searchText} | 
					
						
							|  |  |  |               </Button> | 
					
						
							|  |  |  |             )} | 
					
						
							|  |  |  |             {showResetButton && ( | 
					
						
							|  |  |  |               <Button style={{ marginLeft: 8 }} onClick={handleReset}> | 
					
						
							|  |  |  |                 {resetText} | 
					
						
							|  |  |  |               </Button> | 
					
						
							|  |  |  |             )} | 
					
						
							|  |  |  |             {showCollapseButton && ( | 
					
						
							|  |  |  |               <Button | 
					
						
							|  |  |  |                 type="link" | 
					
						
							|  |  |  |                 icon={collapse ? <DownOutlined /> : <UpOutlined />} | 
					
						
							|  |  |  |                 onClick={toggleCollapse} | 
					
						
							|  |  |  |                 style={{ marginLeft: 8 }} | 
					
						
							|  |  |  |               > | 
					
						
							|  |  |  |                 {collapse ? "展开" : "收起"} | 
					
						
							|  |  |  |               </Button> | 
					
						
							|  |  |  |             )} | 
					
						
							|  |  |  |           </Form.Item> | 
					
						
							|  |  |  |         </Col> | 
					
						
							|  |  |  |         {extraButtons && ( | 
					
						
							|  |  |  |           <Col span={24}> | 
					
						
							|  |  |  |             <Form.Item label=" " colon={false} labelCol={{ span: 0 }}> | 
					
						
							|  |  |  |               {extraButtons} | 
					
						
							|  |  |  |             </Form.Item> | 
					
						
							|  |  |  |           </Col> | 
					
						
							|  |  |  |         )} | 
					
						
							|  |  |  |       </Row> | 
					
						
							|  |  |  |     </Form> | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Search.displayName = "Search"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default Search; |