126 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
		
			
		
	
	
			126 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
|  | 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} | ||
|  |           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; |