Commit a05ae88da6b092e5cdd1c8218bff4dabad55c8f2

Authored by 邱嘉伟
2 parents 8bb182d5 a53e7466

Merge branch 'feature/dataflow' of http://gitlab.qgutech.com/tianqiang/qx-common…

… into feature/dataflow

# Conflicts:
#	src/index.ts
#	src/qx-parameter-setting/ParameterModal.tsx
#	src/qx-parameter-setting/index.tsx
1 { 1 {
2 "name": "@qx/common", 2 "name": "@qx/common",
3 - "version": "3.0.0-alpha.2", 3 + "version": "3.0.0-alpha.5",
4 "lockfileVersion": 2, 4 "lockfileVersion": 2,
5 "requires": true, 5 "requires": true,
6 "packages": { 6 "packages": {
7 "": { 7 "": {
8 "name": "@qx/common", 8 "name": "@qx/common",
9 - "version": "3.0.0-alpha.2", 9 + "version": "3.0.0-alpha.5",
10 "license": "MIT", 10 "license": "MIT",
11 "dependencies": { 11 "dependencies": {
12 "@ant-design/icons": "^5.2.5", 12 "@ant-design/icons": "^5.2.5",
1 { 1 {
2 "name": "@qx/common", 2 "name": "@qx/common",
3 - "version": "3.0.0-alpha.2", 3 + "version": "3.0.0-alpha.5",
4 "description": "A react library developed with dumi", 4 "description": "A react library developed with dumi",
5 "license": "MIT", 5 "license": "MIT",
6 "module": "dist/index.js", 6 "module": "dist/index.js",
@@ -45,13 +45,13 @@ @@ -45,13 +45,13 @@
45 "dependencies": { 45 "dependencies": {
46 "@ant-design/icons": "^5.2.5", 46 "@ant-design/icons": "^5.2.5",
47 "@qx/ui": "0.0.3-beta.1", 47 "@qx/ui": "0.0.3-beta.1",
  48 + "ahooks": "^3.7.5",
  49 + "classnames": "^2.3.2",
48 "codemirror": "5.65.8", 50 "codemirror": "5.65.8",
49 "dayjs": "^1.11.9", 51 "dayjs": "^1.11.9",
50 "lodash-es": "^4.17.21", 52 "lodash-es": "^4.17.21",
51 "rc-virtual-list": "^3.4.13", 53 "rc-virtual-list": "^3.4.13",
52 - "react-codemirror2": "^7.2.1",  
53 - "classnames": "^2.3.2",  
54 - "ahooks": "^3.7.5" 54 + "react-codemirror2": "^7.2.1"
55 }, 55 },
56 "devDependencies": { 56 "devDependencies": {
57 "@commitlint/cli": "^17.1.2", 57 "@commitlint/cli": "^17.1.2",
@@ -74,16 +74,16 @@ @@ -74,16 +74,16 @@
74 "react": "^18.0.0", 74 "react": "^18.0.0",
75 "react-cookies": ">=0.1.1", 75 "react-cookies": ">=0.1.1",
76 "react-dom": "^18.0.0", 76 "react-dom": "^18.0.0",
77 - "stylelint": "^14.9.1",  
78 - "react-router": ">=4.3.1" 77 + "react-router": ">=4.3.1",
  78 + "stylelint": "^14.9.1"
79 }, 79 },
80 "peerDependencies": { 80 "peerDependencies": {
  81 + "@qx/utils": "0.0.58",
  82 + "ahooks": "^3.7.5",
81 "antd": ">=5.8.4", 83 "antd": ">=5.8.4",
82 "react": ">=16.9.0", 84 "react": ">=16.9.0",
83 "react-dom": ">=16.9.0", 85 "react-dom": ">=16.9.0",
84 - "ahooks": "^3.7.5",  
85 - "react-router": ">=4.3.1",  
86 - "@qx/utils": "0.0.58" 86 + "react-router": ">=4.3.1"
87 }, 87 },
88 "publishConfig": { 88 "publishConfig": {
89 "access": "public" 89 "access": "public"
@@ -4,8 +4,11 @@ export * from './qx-sort-condition'; @@ -4,8 +4,11 @@ export * from './qx-sort-condition';
4 export * from './qx-base-icon'; 4 export * from './qx-base-icon';
5 export * from './qx-tags-input'; 5 export * from './qx-tags-input';
6 export * from './qx-user-selector'; 6 export * from './qx-user-selector';
  7 +export * from './qx-org-selector';
7 export * from './qx-form-select'; 8 export * from './qx-form-select';
8 export * from './qx-app-selector'; 9 export * from './qx-app-selector';
9 export * from './utils'; 10 export * from './utils';
  11 +export * from './qx-field';
10 export * from './qx-field-setter'; 12 export * from './qx-field-setter';
11 -// export { default as FieldSetter } from './qx-field-setter'; 13 +
  14 +// export * from './qx-btn';
1 -@import '~@qx/ui/src/style/variable.less';  
2 -  
3 -.qx-fields-popover {  
4 - &.ant-popover {  
5 - padding-top: 0;  
6 - padding-bottom: 0;  
7 - overflow: hidden;  
8 - background: #fff;  
9 - border-radius: 8px;  
10 - box-shadow: 0 4px 10px 0 rgba(0, 0, 0, 0.1);  
11 - }  
12 -  
13 - .ant-popover-arrow {  
14 - display: none;  
15 - }  
16 -  
17 - .ant-popover-inner {  
18 - padding: 0;  
19 - }  
20 -  
21 - .ant-popover-inner-content {  
22 - padding: 0;  
23 - overflow: auto;  
24 - }  
25 -  
26 - &__search {  
27 - height: 36px;  
28 -  
29 - .ant-input-prefix {  
30 - color: @N7;  
31 - font-size: 16px;  
32 - }  
33 - }  
34 -}  
35 -  
36 -.qx-popover-fields {  
37 - max-height: 260px;  
38 - margin: 0;  
39 - padding: 0;  
40 - overflow: auto;  
41 -  
42 - > li {  
43 - padding: 5px 5px 5px 12px;  
44 - cursor: pointer;  
45 -  
46 - &:hover {  
47 - background-color: @N3;  
48 - }  
49 - }  
50 -}  
51 -  
52 -.qx-fields-pop-content {  
53 - width: 100%;  
54 - max-height: 260px;  
55 - overflow-x: hidden;  
56 -  
57 - &.ant-menu-inline > .ant-menu-submenu > .ant-menu-submenu-title {  
58 - margin-top: 0;  
59 - margin-bottom: 1px;  
60 - background-color: @N2;  
61 - }  
62 -  
63 - .ant-menu-sub.ant-menu-inline {  
64 - background-color: #fff;  
65 - }  
66 -  
67 - &.ant-menu-inline > .ant-menu-item,  
68 - .ant-menu-sub.ant-menu-inline > .ant-menu-item {  
69 - height: 32px;  
70 - line-height: 32px;  
71 - border-radius: 4px;  
72 -  
73 - &:hover {  
74 - color: inherit;  
75 - background-color: @N3;  
76 - }  
77 - }  
78 -  
79 - .ant-menu-title-content {  
80 - .ant-typography + span {  
81 - overflow: hidden;  
82 - text-overflow: ellipsis;  
83 - }  
84 - }  
85 -}  
86 -.qx-field-pop__footer {  
87 - padding-top: 5px;  
88 - padding-bottom: 5px;  
89 - padding-left: 24px;  
90 - border-top: 1px solid @N4;  
91 -}  
1 -import { Divider, Input, Menu, Popover } from 'antd';  
2 -  
3 -import * as React from 'react';  
4 -import type { ReactElement } from 'react';  
5 -import { useEffect, useState } from 'react';  
6 -import QxFieldItem from '../qx-field/src/item';  
7 -import { useDebounceFn } from 'ahooks';  
8 -import { isEmpty } from 'lodash-es';  
9 -import { QxBaseIcon } from '@qx/common';  
10 -import './index.less';  
11 -  
12 -export type OptionFieldExtract = {  
13 - fieldType?: string;  
14 - widget: string;  
15 - design?: any;  
16 - relId?: string;  
17 - //关联数据集的才有  
18 - optionsRef?: string;  
19 - //关联属性,真实的字段组件  
20 - refWidget?: string;  
21 - //关联属性,真实的字段类型  
22 - refType?: string;  
23 - required?: boolean;  
24 - // 是否是默认系统字段,值为true时是未配置的系统字段  
25 - $default?: boolean;  
26 - // 卡片设计 特殊字段配置 回显所用  
27 - renderData?: any;  
28 -};  
29 -  
30 -export type OptionField = {  
31 - code: string;  
32 - name: string;  
33 - disabled?: boolean;  
34 - //当disabled=true的时候extract不存在  
35 - extract?: OptionFieldExtract;  
36 -};  
37 -  
38 -interface QxFieldPopoverProp {  
39 - data: OptionField[];  
40 - widgets?: string[]; //需要展示的widgets  
41 - exclude?: string[]; //排除的字段  
42 - width?: string; //pop 宽度  
43 - trigger?: 'click' | 'hover' | undefined;  
44 - onSelect: (field: OptionField) => void;  
45 - disabled?: boolean;  
46 - hiddenAfterTrigger?: boolean;  
47 - popFooter?: ReactElement;  
48 - children?: any;  
49 -}  
50 -  
51 -export const QxFieldPopover: React.FC<QxFieldPopoverProp> = (props) => {  
52 - // const [fieldFlatten, setFieldFlatten] = useState<any>({})  
53 - const [fields, setFields] = useState<any>([]);  
54 - const [filterFields, setFilterFields] = useState<any>([]);  
55 - const [visible, setVisible] = useState<boolean>(false);  
56 - //TODO 搜索  
57 - const [keyword, setKeyword] = useState<string>();  
58 -  
59 - const getUsefulFieldProp = (field: any) => {  
60 - let mode = 'widget'; //TODO 接口废弃,后续要删掉  
61 - if (field?.extract) {  
62 - mode = 'option';  
63 - }  
64 - let widget = field?.propertyWidget || field.widget;  
65 - let code = field?.fieldName || field.code;  
66 - let name = field?.fieldComment || field.title;  
67 - let relFunId = field?.relFunId;  
68 - if (mode === 'option') {  
69 - widget = field?.extract.widget;  
70 - relFunId = field?.extract.relId;  
71 - code = field?.code;  
72 - name = field?.name;  
73 - }  
74 - return {  
75 - widget,  
76 - code,  
77 - name,  
78 - relFunId,  
79 - };  
80 - };  
81 - // @ts-ignore  
82 - const excludeFields = (list: OptionField[]) => {  
83 - // @ts-ignore  
84 - return list.filter((item: any) => {  
85 - if (item.children && item.children.length === 0) {  
86 - return false;  
87 - }  
88 -  
89 - let allow = true;  
90 - const { widget, code } = getUsefulFieldProp(item);  
91 - if (props.widgets && props.widgets.length > 0 && props.widgets.indexOf(widget) === -1) {  
92 - return false;  
93 - }  
94 - if (!props.exclude || props.exclude.length === 0) {  
95 - allow = true;  
96 - } else {  
97 - allow = props.exclude.indexOf(code) === -1;  
98 - }  
99 - return allow;  
100 - });  
101 - };  
102 - useEffect(() => {  
103 - if (!isEmpty(props.data)) {  
104 - const _fields = excludeFields(props.data);  
105 - setFields(_fields);  
106 - setFilterFields(_fields);  
107 - // setFieldFlatten(flatFields(_fields))  
108 - }  
109 - }, [props.data]);  
110 -  
111 - const handleClick = (item: any) => {  
112 - if (props.hiddenAfterTrigger) {  
113 - setVisible(false);  
114 - }  
115 - props.onSelect(item);  
116 - };  
117 -  
118 - const { run } = useDebounceFn((field) => handleClick(field), {  
119 - wait: 300,  
120 - leading: true,  
121 - trailing: false,  
122 - });  
123 -  
124 - useEffect(() => {  
125 - if (!keyword) {  
126 - setFilterFields([...fields]);  
127 - } else {  
128 - const _filterFields: any = [];  
129 -  
130 - fields.forEach((item: any) => {  
131 - const _item = { ...item };  
132 - _item.children = [];  
133 - if (item?.children?.length) {  
134 - item?.children.forEach((children: any) => {  
135 - if (  
136 - children?.titleStr?.indexOf(keyword) > -1 ||  
137 - children?.name?.indexOf(keyword) > -1  
138 - ) {  
139 - _item.children.push(children);  
140 - }  
141 - });  
142 - if (_item.children?.length) {  
143 - _filterFields.push(_item);  
144 - }  
145 - } else {  
146 - if (item?.titleStr?.indexOf(keyword) > -1 || item?.name?.indexOf(keyword) > -1) {  
147 - _filterFields.push(item);  
148 - }  
149 - }  
150 - });  
151 - /*const _filterFields = fields.filter(  
152 - (item) => item?.titleStr?.indexOf(keyword) > -1 || item?.name?.indexOf(keyword) > -1,  
153 - );*/  
154 - setFilterFields(_filterFields);  
155 - }  
156 - }, [keyword, fields]);  
157 -  
158 - const handleChange = (_keyword: string) => {  
159 - setKeyword(_keyword.trim());  
160 - };  
161 -  
162 - const fieldsPopContent = () => {  
163 - return (  
164 - <div style={{ width: props.width || '192px' }}>  
165 - {!fields?.length ? (  
166 - <div  
167 - className={'ant-empty-normal'}  
168 - style={{  
169 - textAlign: 'center',  
170 - margin: '10px 0',  
171 - }}  
172 - >  
173 - 没有可选字段  
174 - </div>  
175 - ) : (  
176 - <>  
177 - <div  
178 - onMouseDown={(e) => {  
179 - e.preventDefault();  
180 - }}  
181 - >  
182 - <Input  
183 - bordered={false}  
184 - value={keyword}  
185 - className={'qx-fields-popover__search'}  
186 - placeholder={'搜索'}  
187 - allowClear  
188 - prefix={<QxBaseIcon type={'icon-app-search-line'} />}  
189 - onChange={(e) => {  
190 - handleChange(e.target.value);  
191 - }}  
192 - />  
193 - </div>  
194 - <Divider style={{ margin: 0 }} />  
195 - {!filterFields.length ? (  
196 - <div  
197 - className={'ant-empty-normal'}  
198 - style={{  
199 - textAlign: 'center',  
200 - margin: '10px 0',  
201 - }}  
202 - >  
203 - 暂无相关字段  
204 - </div>  
205 - ) : (  
206 - <Menu  
207 - mode="inline"  
208 - className={'qx-fields-pop-content'}  
209 - selectedKeys={[]}  
210 - inlineIndent={12}  
211 - >  
212 - {filterFields.map((field: any) => {  
213 - if (!!field?.children?.length) {  
214 - return (  
215 - <Menu.SubMenu  
216 - key={field.code}  
217 - title={  
218 - field.title || (  
219 - <QxFieldItem  
220 - widget={field.extract && field.extract.widget}  
221 - name={field.name}  
222 - />  
223 - )  
224 - }  
225 - >  
226 - {field.children.map((item: any) => {  
227 - if ((item.children || []).length) {  
228 - return (  
229 - <Menu.SubMenu  
230 - key={item.code}  
231 - title={  
232 - item.title || (  
233 - <QxFieldItem  
234 - widget={field.extract && field.extract.widget}  
235 - name={field.name}  
236 - />  
237 - )  
238 - }  
239 - >  
240 - {(item.children || []).map((_it: any) => {  
241 - return (  
242 - <Menu.Item  
243 - key={_it.code}  
244 - onClick={() => {  
245 - handleClick(_it);  
246 - }}  
247 - >  
248 - {_it.title || (  
249 - <QxFieldItem  
250 - widget={field.extract && field.extract.widget}  
251 - name={field.name}  
252 - />  
253 - )}  
254 - </Menu.Item>  
255 - );  
256 - })}  
257 - </Menu.SubMenu>  
258 - );  
259 - } else {  
260 - return (  
261 - <Menu.Item  
262 - key={item.code}  
263 - onClick={() => {  
264 - handleClick(item);  
265 - }}  
266 - >  
267 - {item.title || (  
268 - <QxFieldItem  
269 - widget={field.extract && field.extract.widget}  
270 - name={field.name}  
271 - />  
272 - )}  
273 - </Menu.Item>  
274 - );  
275 - }  
276 - })}  
277 - </Menu.SubMenu>  
278 - );  
279 - } else {  
280 - return (  
281 - <Menu.Item  
282 - style={{  
283 - display:  
284 - keyword && field?.name?.indexOf(keyword) === -1 ? 'none' : 'block',  
285 - }}  
286 - onClick={() => {  
287 - run(field);  
288 - }}  
289 - key={field.code}  
290 - >  
291 - {field.title || (  
292 - <QxFieldItem  
293 - widget={field.extract && field.extract.widget}  
294 - name={field.name}  
295 - />  
296 - )}  
297 - </Menu.Item>  
298 - );  
299 - }  
300 - })}  
301 - </Menu>  
302 - )}  
303 - </>  
304 - )}  
305 - {props.popFooter ? <div className="qx-field-pop__footer">{props.popFooter}</div> : null}  
306 - </div>  
307 - );  
308 - };  
309 -  
310 - return (  
311 - <Popover  
312 - overlayClassName={'qx-fields-popover'}  
313 - // getPopupContainer={(triggerNode) => triggerNode}  
314 - content={fieldsPopContent()}  
315 - placement={'bottomRight'}  
316 - trigger={props.disabled ? undefined : props.trigger || 'click'}  
317 - open={visible}  
318 - onOpenChange={(v) => {  
319 - if (!v) {  
320 - setTimeout(() => {  
321 - setKeyword('');  
322 - setFilterFields([...fields]);  
323 - }, 0);  
324 - }  
325 - setVisible(v);  
326 - }}  
327 - >  
328 - {props.children}  
329 - </Popover>  
330 - );  
331 -}  
@@ -17,7 +17,7 @@ import { CloseOutlined, ControlOutlined, RightOutlined } from '@ant-design/icons @@ -17,7 +17,7 @@ import { CloseOutlined, ControlOutlined, RightOutlined } from '@ant-design/icons
17 import { cloneDeep, isEqual, isEmpty, findIndex, size } from 'lodash-es'; 17 import { cloneDeep, isEqual, isEmpty, findIndex, size } from 'lodash-es';
18 import { RelTreeSetter } from './components/rel-tree-setter'; 18 import { RelTreeSetter } from './components/rel-tree-setter';
19 import { AddressSetter } from './components/address-setter'; 19 import { AddressSetter } from './components/address-setter';
20 -import {QxFieldPopover} from '../qx-field-popover'; 20 +import {QxFieldPopover} from '@qx/common';
21 import { InputSetter } from './components/input-setter'; 21 import { InputSetter } from './components/input-setter';
22 import { OrgSetter } from './components/org-setter'; 22 import { OrgSetter } from './components/org-setter';
23 import { RelSetter } from './components/rel-setter'; 23 import { RelSetter } from './components/rel-setter';
@@ -157,7 +157,7 @@ export interface paramColSelectProps extends ColSelectProps { @@ -157,7 +157,7 @@ export interface paramColSelectProps extends ColSelectProps {
157 allowClear?: boolean; 157 allowClear?: boolean;
158 } 158 }
159 159
160 -export const FieldSetter: React.FC<paramColSelectProps> = ({ 160 +export const QxFieldSetter: React.FC<paramColSelectProps> = ({
161 value, 161 value,
162 fieldGroupType, 162 fieldGroupType,
163 fieldType, 163 fieldType,
@@ -15,7 +15,7 @@ group: @@ -15,7 +15,7 @@ group:
15 15
16 ```tsx 16 ```tsx
17 import React from 'react'; 17 import React from 'react';
18 -import { QxFieldItem } from './index'; 18 +import { QxFieldItem } from '@qx/common';
19 19
20 export default () => { 20 export default () => {
21 return <QxFieldItem name={'标题'} widget={'qxInput'} />; 21 return <QxFieldItem name={'标题'} widget={'qxInput'} />;
1 import QxFieldItem from './src/item'; 1 import QxFieldItem from './src/item';
2 import QxFieldSelect from './src/select'; 2 import QxFieldSelect from './src/select';
  3 +import QxFieldPopover from './src/popover';
  4 +// import QxCheckboxFieldPopover from './src/popover/checkbox';
3 5
4 -export { QxFieldItem, QxFieldSelect }; 6 +export { QxFieldItem, QxFieldSelect, QxFieldPopover };
@@ -4,7 +4,7 @@ import * as React from 'react'; @@ -4,7 +4,7 @@ import * as React from 'react';
4 import { FC, ReactElement, useEffect, useState } from 'react'; 4 import { FC, ReactElement, useEffect, useState } from 'react';
5 import type { OptionField } from '../type'; 5 import type { OptionField } from '../type';
6 import { getUsefulFieldProp } from '../util'; 6 import { getUsefulFieldProp } from '../util';
7 -import QxFieldItem from '../item'; 7 +import { QxFieldItem } from '@qx/common';
8 import './style.less'; 8 import './style.less';
9 import Checkbox from 'antd/es/checkbox/Checkbox'; 9 import Checkbox from 'antd/es/checkbox/Checkbox';
10 import {QxBaseIcon} from '@qx/common'; 10 import {QxBaseIcon} from '@qx/common';
@@ -6,7 +6,7 @@ import { useEffect, useState } from 'react'; @@ -6,7 +6,7 @@ import { useEffect, useState } from 'react';
6 import type { OptionField } from '../type'; 6 import type { OptionField } from '../type';
7 import { getUsefulFieldProp } from '../util'; 7 import { getUsefulFieldProp } from '../util';
8 // import {flatFields, getUsefulFieldProp} from '../util'; 8 // import {flatFields, getUsefulFieldProp} from '../util';
9 -import QxFieldItem from '../item'; 9 +import { QxFieldItem } from '@qx/common';
10 import {QxBaseIcon} from '@qx/common'; 10 import {QxBaseIcon} from '@qx/common';
11 import './style.less'; 11 import './style.less';
12 import { useDebounceFn } from 'ahooks'; 12 import { useDebounceFn } from 'ahooks';
@@ -127,107 +127,131 @@ const QxFieldPopover: React.FC<QxFieldPopoverProp> = (props) => { @@ -127,107 +127,131 @@ const QxFieldPopover: React.FC<QxFieldPopoverProp> = (props) => {
127 </div> 127 </div>
128 ) : ( 128 ) : (
129 <> 129 <>
130 - <Input  
131 - className={'qx-selector-sub-search'}  
132 - placeholder={'搜索'}  
133 - allowClear  
134 - prefix={<QxBaseIcon type={'icon-app-search-line'} />}  
135 - style={{ paddingTop: '6px' }}  
136 - onChange={(e) => {  
137 - handleChange(e.target.value); 130 + <div
  131 + onMouseDown={(e) => {
  132 + e.preventDefault();
138 }} 133 }}
139 - /> 134 + >
  135 + <Input
  136 + bordered={false}
  137 + value={keyword}
  138 + className={'qx-fields-popover__search'}
  139 + placeholder={'搜索'}
  140 + allowClear
  141 + prefix={<QxBaseIcon type={'icon-app-search-line'} />}
  142 + onChange={(e) => {
  143 + handleChange(e.target.value);
  144 + }}
  145 + />
  146 + </div>
140 <Divider style={{ margin: 0 }} /> 147 <Divider style={{ margin: 0 }} />
141 - <Menu mode="inline" className={'qx-fields-pop-content'} selectedKeys={[]}>  
142 - {filterFields.map((field: any) => {  
143 - if (field.children) {  
144 - return (  
145 - <Menu.SubMenu  
146 - key={field.code}  
147 - title={  
148 - field.title || (  
149 - <QxFieldItem  
150 - widget={field.extract && field.extract.widget}  
151 - name={field.name}  
152 - />  
153 - )  
154 - }  
155 - >  
156 - {field.children.map((item: any) => {  
157 - if ((item.children || []).length) {  
158 - return (  
159 - <Menu.SubMenu  
160 - key={item.code}  
161 - title={  
162 - item.title || ( 148 + {!filterFields.length ? (
  149 + <div
  150 + className={'ant-empty-normal'}
  151 + style={{
  152 + textAlign: 'center',
  153 + margin: '10px 0',
  154 + }}
  155 + >
  156 + 暂无相关字段
  157 + </div>
  158 + ) : (
  159 + <Menu
  160 + mode="inline"
  161 + className={'qx-fields-pop-content'}
  162 + selectedKeys={[]}
  163 + inlineIndent={12}
  164 + >
  165 + {filterFields.map((field: any) => {
  166 + if (!!field?.children?.length) {
  167 + return (
  168 + <Menu.SubMenu
  169 + key={field.code}
  170 + title={
  171 + field.title || (
  172 + <QxFieldItem
  173 + widget={field.extract && field.extract.widget}
  174 + name={field.name}
  175 + />
  176 + )
  177 + }
  178 + >
  179 + {field.children.map((item: any) => {
  180 + if ((item.children || []).length) {
  181 + return (
  182 + <Menu.SubMenu
  183 + key={item.code}
  184 + title={
  185 + item.title || (
  186 + <QxFieldItem
  187 + widget={field.extract && field.extract.widget}
  188 + name={field.name}
  189 + />
  190 + )
  191 + }
  192 + >
  193 + {(item.children || []).map((_it: any) => {
  194 + return (
  195 + <Menu.Item
  196 + key={_it.code}
  197 + onClick={() => {
  198 + handleClick(_it);
  199 + }}
  200 + >
  201 + {_it.title || (
  202 + <QxFieldItem
  203 + widget={field.extract && field.extract.widget}
  204 + name={field.name}
  205 + />
  206 + )}
  207 + </Menu.Item>
  208 + );
  209 + })}
  210 + </Menu.SubMenu>
  211 + );
  212 + } else {
  213 + return (
  214 + <Menu.Item
  215 + key={item.code}
  216 + onClick={() => {
  217 + handleClick(item);
  218 + }}
  219 + >
  220 + {item.title || (
163 <QxFieldItem 221 <QxFieldItem
164 widget={field.extract && field.extract.widget} 222 widget={field.extract && field.extract.widget}
165 name={field.name} 223 name={field.name}
166 /> 224 />
167 - )  
168 - }  
169 - >  
170 - {(item.children || []).map((_it: any) => {  
171 - return (  
172 - <Menu.Item  
173 - key={_it.code}  
174 - onClick={() => {  
175 - handleClick(_it);  
176 - }}  
177 - >  
178 - {_it.title || (  
179 - <QxFieldItem  
180 - widget={field.extract && field.extract.widget}  
181 - name={field.name}  
182 - />  
183 - )}  
184 - </Menu.Item>  
185 - );  
186 - })}  
187 - </Menu.SubMenu>  
188 - );  
189 - } else {  
190 - return (  
191 - <Menu.Item  
192 - key={item.code}  
193 - onClick={() => {  
194 - handleClick(item);  
195 - }}  
196 - >  
197 - {item.title || (  
198 - <QxFieldItem  
199 - widget={field.extract && field.extract.widget}  
200 - name={field.name}  
201 - />  
202 - )}  
203 - </Menu.Item>  
204 - );  
205 - }  
206 - })}  
207 - </Menu.SubMenu>  
208 - );  
209 - } else {  
210 - return (  
211 - <Menu.Item  
212 - style={{  
213 - display: keyword && field?.name?.indexOf(keyword) === -1 ? 'none' : 'block',  
214 - }}  
215 - onClick={() => {  
216 - run(field);  
217 - }}  
218 - key={field.code}  
219 - >  
220 - {field.title || (  
221 - <QxFieldItem  
222 - widget={field.extract && field.extract.widget}  
223 - name={field.name}  
224 - />  
225 - )}  
226 - </Menu.Item>  
227 - );  
228 - }  
229 - })}  
230 - </Menu> 225 + )}
  226 + </Menu.Item>
  227 + );
  228 + }
  229 + })}
  230 + </Menu.SubMenu>
  231 + );
  232 + } else {
  233 + return (
  234 + <Menu.Item
  235 + style={{
  236 + display: keyword && field?.name?.indexOf(keyword) === -1 ? 'none' : 'block',
  237 + }}
  238 + onClick={() => {
  239 + run(field);
  240 + }}
  241 + key={field.code}
  242 + >
  243 + {field.title || (
  244 + <QxFieldItem
  245 + widget={field.extract && field.extract.widget}
  246 + name={field.name}
  247 + />
  248 + )}
  249 + </Menu.Item>
  250 + );
  251 + }
  252 + })}
  253 + </Menu>
  254 + )}
231 </> 255 </>
232 )} 256 )}
233 {props.popFooter ? <div className="qx-field-pop__footer">{props.popFooter}</div> : null} 257 {props.popFooter ? <div className="qx-field-pop__footer">{props.popFooter}</div> : null}
@@ -244,6 +268,12 @@ const QxFieldPopover: React.FC<QxFieldPopoverProp> = (props) => { @@ -244,6 +268,12 @@ const QxFieldPopover: React.FC<QxFieldPopoverProp> = (props) => {
244 trigger={props.disabled ? undefined : props.trigger || 'hover'} 268 trigger={props.disabled ? undefined : props.trigger || 'hover'}
245 open={visible} 269 open={visible}
246 onOpenChange={(v) => { 270 onOpenChange={(v) => {
  271 + if (!v) {
  272 + setTimeout(() => {
  273 + setKeyword('');
  274 + setFilterFields([...fields]);
  275 + }, 0);
  276 + }
247 setVisible(v); 277 setVisible(v);
248 }} 278 }}
249 > 279 >
1 @import '~@qx/ui/src/style/variable.less'; 1 @import '~@qx/ui/src/style/variable.less';
2 2
3 .qx-fields-popover { 3 .qx-fields-popover {
4 - padding-top: 0; 4 + &.ant-popover {
  5 + padding-top: 0;
  6 + padding-bottom: 0;
  7 + overflow: hidden;
  8 + background: #fff;
  9 + border-radius: 8px;
  10 + border: 1px solid #e5e6eb;
  11 + box-shadow: 0 4px 10px 0 rgba(0, 0, 0, 0.1);
  12 + }
  13 +
  14 + .ant-popover-inner {
  15 + padding: 0;
  16 + }
5 17
6 .ant-popover-arrow { 18 .ant-popover-arrow {
7 display: none; 19 display: none;
@@ -11,6 +23,15 @@ @@ -11,6 +23,15 @@
11 padding: 0; 23 padding: 0;
12 overflow: auto; 24 overflow: auto;
13 } 25 }
  26 +
  27 + &__search {
  28 + height: 36px;
  29 +
  30 + .ant-input-prefix {
  31 + color: @N7;
  32 + font-size: 16px;
  33 + }
  34 + }
14 } 35 }
15 36
16 .qx-popover-fields { 37 .qx-popover-fields {
@@ -47,15 +68,23 @@ @@ -47,15 +68,23 @@
47 &.ant-menu-inline > .ant-menu-item, 68 &.ant-menu-inline > .ant-menu-item,
48 .ant-menu-sub.ant-menu-inline > .ant-menu-item { 69 .ant-menu-sub.ant-menu-inline > .ant-menu-item {
49 height: 32px; 70 height: 32px;
50 - margin: 1px;  
51 line-height: 32px; 71 line-height: 32px;
  72 + border-radius: 4px;
52 73
53 &:hover { 74 &:hover {
54 color: inherit; 75 color: inherit;
55 background-color: @N3; 76 background-color: @N3;
56 } 77 }
57 } 78 }
  79 +
  80 + .ant-menu-title-content {
  81 + .ant-typography + span {
  82 + overflow: hidden;
  83 + text-overflow: ellipsis;
  84 + }
  85 + }
58 } 86 }
  87 +
59 .qx-field-pop__footer { 88 .qx-field-pop__footer {
60 padding-top: 5px; 89 padding-top: 5px;
61 padding-bottom: 5px; 90 padding-bottom: 5px;
@@ -3,19 +3,14 @@ import * as React from 'react'; @@ -3,19 +3,14 @@ import * as React from 'react';
3 import { useEffect, useState } from 'react'; 3 import { useEffect, useState } from 'react';
4 import type { OptionField, WidgetField } from '../type'; 4 import type { OptionField, WidgetField } from '../type';
5 import { getUsefulFieldProp } from '../util'; 5 import { getUsefulFieldProp } from '../util';
6 -import QxFieldItem from '../item';  
7 -import { useLocation } from 'react-router'; 6 +import { QxFieldItem } from '@qx/common';
8 import { getFieldOptions } from '../../service'; 7 import { getFieldOptions } from '../../service';
9 import './style.less'; 8 import './style.less';
10 9
11 const QxFieldSelect: React.FC = (props: any) => { 10 const QxFieldSelect: React.FC = (props: any) => {
  11 + const {appCode, funCode, schema} = props
12 const [fields, setFields] = useState<WidgetField[] | OptionField[]>([]); 12 const [fields, setFields] = useState<WidgetField[] | OptionField[]>([]);
13 - const schemaProps = props.schema.props;  
14 - // @ts-ignore  
15 - const {query} = useLocation();  
16 -  
17 - const appCode = query?.appCode|| props?.appCode || '8yo7v';  
18 - const funCode = query?.funCode|| props?.funCode ||'2eg66'; 13 + const schemaProps = schema?.props;
19 const includeFields = (list: WidgetField[] | OptionField[]) => { 14 const includeFields = (list: WidgetField[] | OptionField[]) => {
20 // console.log(list,schemaProps.viewable); 15 // console.log(list,schemaProps.viewable);
21 // @ts-ignore 16 // @ts-ignore
1 import React, { useEffect, useState } from 'react'; 1 import React, { useEffect, useState } from 'react';
2 -import type { ColsTreeProps } from '../qx-field-setter';  
3 -import { FieldSetter } from '../qx-field-setter';  
4 -import { QxFieldPopover } from '../qx-field-popover'; 2 +import type { ColsTreeProps } from '@qx/common';
  3 +import { QxFieldSetter } from '@qx/common';
  4 +import {QxFieldPopover} from '@qx/common';
5 import { QxBaseIcon } from '@qx/common'; 5 import { QxBaseIcon } from '@qx/common';
6 import { FunctionOutlined } from '@ant-design/icons'; 6 import { FunctionOutlined } from '@ant-design/icons';
7 import { 7 import {
@@ -625,7 +625,7 @@ export const QxFilterCondition: React.FC<paramFilterConditionProps> = ({ @@ -625,7 +625,7 @@ export const QxFilterCondition: React.FC<paramFilterConditionProps> = ({
625 {Boolean(isUseValOption) ? ( 625 {Boolean(isUseValOption) ? (
626 <div style={{position: 'relative'}}> 626 <div style={{position: 'relative'}}>
627 <Button 627 <Button
628 - disabled={!(paramMappings && paramMappings?.length < 20)} 628 + disabled={(paramMappings && paramMappings?.length > 20)}
629 size="small" 629 size="small"
630 type={'link'} 630 type={'link'}
631 onClick={() => setTreeSelectShow(!treeSelectShow)} 631 onClick={() => setTreeSelectShow(!treeSelectShow)}
@@ -682,10 +682,10 @@ export const QxFilterCondition: React.FC<paramFilterConditionProps> = ({ @@ -682,10 +682,10 @@ export const QxFilterCondition: React.FC<paramFilterConditionProps> = ({
682 <QxFieldPopover 682 <QxFieldPopover
683 data={getFields(tableFields || [])} 683 data={getFields(tableFields || [])}
684 onSelect={(field) => onAddCondition(field.code)} 684 onSelect={(field) => onAddCondition(field.code)}
685 - trigger={'click'} 685 + trigger={(paramMappings && paramMappings?.length > 20) ? undefined : 'click'}
686 > 686 >
687 <Button 687 <Button
688 - disabled={!(paramMappings && paramMappings?.length < 20)} 688 + disabled={(paramMappings && paramMappings?.length > 20)}
689 size="small" 689 size="small"
690 type={'link'} 690 type={'link'}
691 > 691 >
@@ -863,7 +863,7 @@ export const QxFilterCondition: React.FC<paramFilterConditionProps> = ({ @@ -863,7 +863,7 @@ export const QxFilterCondition: React.FC<paramFilterConditionProps> = ({
863 </span> 863 </span>
864 </div> 864 </div>
865 {/* 值选项 TODO field 在工作流那可能有问题 */} 865 {/* 值选项 TODO field 在工作流那可能有问题 */}
866 - <FieldSetter 866 + <QxFieldSetter
867 value={item?.valuesObj} 867 value={item?.valuesObj}
868 params={props.params || fieldInfo?.params} 868 params={props.params || fieldInfo?.params}
869 field={getResultField( 869 field={getResultField(
@@ -24,6 +24,8 @@ export const QxFormSelect: React.FC<FormSelectProps> = (props) => { @@ -24,6 +24,8 @@ export const QxFormSelect: React.FC<FormSelectProps> = (props) => {
24 appId, 24 appId,
25 request, 25 request,
26 disabled, 26 disabled,
  27 + placeholder,
  28 + title
27 } = props; 29 } = props;
28 30
29 const [state, setState] = useSetState<FormSelectState>({ 31 const [state, setState] = useSetState<FormSelectState>({
@@ -59,7 +61,7 @@ export const QxFormSelect: React.FC<FormSelectProps> = (props) => { @@ -59,7 +61,7 @@ export const QxFormSelect: React.FC<FormSelectProps> = (props) => {
59 ref={inputSelectRef} 61 ref={inputSelectRef}
60 value={value?.name} 62 value={value?.name}
61 defaultValue={value?.name} 63 defaultValue={value?.name}
62 - placeholder="请选择数据源" 64 + placeholder={placeholder || '请选择数据源'}
63 prefix={<BlockOutlined style={{ color: '#52c41a' }} />} 65 prefix={<BlockOutlined style={{ color: '#52c41a' }} />}
64 options={options} 66 options={options}
65 onChange={handleChange} 67 onChange={handleChange}
@@ -82,7 +84,7 @@ export const QxFormSelect: React.FC<FormSelectProps> = (props) => { @@ -82,7 +84,7 @@ export const QxFormSelect: React.FC<FormSelectProps> = (props) => {
82 84
83 {state.modalVisible ? ( 85 {state.modalVisible ? (
84 <QxAppSelector 86 <QxAppSelector
85 - title="选择数据源" 87 + title={title || placeholder || "选择数据源"}
86 item={{ 88 item={{
87 flag: 'SINGLE', 89 flag: 'SINGLE',
88 currentId: '', 90 currentId: '',
@@ -94,7 +96,7 @@ export const QxFormSelect: React.FC<FormSelectProps> = (props) => { @@ -94,7 +96,7 @@ export const QxFormSelect: React.FC<FormSelectProps> = (props) => {
94 modalProps={{ 96 modalProps={{
95 width: 550, 97 width: 550,
96 destroyOnClose: true, 98 destroyOnClose: true,
97 - visible: state.modalVisible, 99 + open: state.modalVisible,
98 onOk: () => setState({ modalVisible: false }), 100 onOk: () => setState({ modalVisible: false }),
99 onCancel: () => setState({ modalVisible: false }), 101 onCancel: () => setState({ modalVisible: false }),
100 }} 102 }}
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 2
3 .qx-form-select { 3 .qx-form-select {
4 width: 100%; 4 width: 100%;
  5 + border-radius: 4px;
5 6
6 &__dropdown-bottom { 7 &__dropdown-bottom {
7 width: 100% !important; 8 width: 100% !important;
@@ -10,4 +11,13 @@ @@ -10,4 +11,13 @@
10 background-color: #fff !important; 11 background-color: #fff !important;
11 border-top: 1px solid @N4 !important; 12 border-top: 1px solid @N4 !important;
12 } 13 }
  14 + .qx-input-select-dropdown__list-empty {
  15 + display: flex;
  16 + align-items: center;
  17 + justify-content: center;
  18 + flex-direction: column;
  19 + overflow: hidden;
  20 + height: 100%;
  21 + margin: 0;
  22 + }
13 } 23 }
  1 +### 选部门组件
  2 +
  3 +```tsx
  4 +/**
  5 + * debug: true
  6 + */
  7 +import { QxOrgSelector, request } from '@qx/common';
  8 +import React from 'react';
  9 +
  10 +export default () => {
  11 + return (
  12 + <div>
  13 + <QxOrgSelector request={request} />
  14 + </div>
  15 + );
  16 +};
  17 +```
  18 +
  19 +### 弹框
  20 +
  21 +```tsx
  22 +import { QxOrgSelector, request } from '@qx/common';
  23 +import React, { useState } from 'react';
  24 +
  25 +export default () => {
  26 + const [visible, setVisible] = useState(false);
  27 + return (
  28 + <div>
  29 + <div onClick={() => setVisible(true)}>点一下</div>
  30 + <QxOrgSelector.Dialog
  31 + request={request}
  32 + checkStrictly
  33 + title={'添加部门'}
  34 + visible={visible}
  35 + multiple={true}
  36 + onOk={(orgIds: any) => {
  37 + console.log(orgIds, 'lllll');
  38 + }}
  39 + onCancel={() => {
  40 + setVisible(false);
  41 + }}
  42 + />
  43 + </div>
  44 + );
  45 +};
  46 +```
@@ -30,7 +30,7 @@ import React, { @@ -30,7 +30,7 @@ import React, {
30 } from 'react'; 30 } from 'react';
31 import JSONEditor from './codeMirror'; 31 import JSONEditor from './codeMirror';
32 import './style.less'; 32 import './style.less';
33 -import { FieldSetter } from '@qx/common'; 33 +import { QxFieldSetter } from '@qx/common';
34 import { formatEnum } from './constant'; 34 import { formatEnum } from './constant';
35 import { 35 import {
36 typeTranslateFieIdtype, 36 typeTranslateFieIdtype,
@@ -705,7 +705,7 @@ const ParameterModal: React.FC<ParameterSettingProps> = (props) => { @@ -705,7 +705,7 @@ const ParameterModal: React.FC<ParameterSettingProps> = (props) => {
705 ref={inputRef} 705 ref={inputRef}
706 onBlur={() => save('qxProps-default')} 706 onBlur={() => save('qxProps-default')}
707 /> */} 707 /> */}
708 - <FieldSetter 708 + <QxFieldSetter
709 value={record.valuesObj || []} 709 value={record.valuesObj || []}
710 // value={[{ 710 // value={[{
711 // type: typeTranslateItemtype(record.type) || '', 711 // type: typeTranslateItemtype(record.type) || '',
@@ -19,7 +19,7 @@ import { @@ -19,7 +19,7 @@ import {
19 } from 'antd'; 19 } from 'antd';
20 import type { TreeProps } from 'antd/lib/tree'; 20 import type { TreeProps } from 'antd/lib/tree';
21 import ParameterModal from './ParameterModal'; 21 import ParameterModal from './ParameterModal';
22 -import { FieldSetter } from '@qx/common'; 22 +import { QxFieldSetter } from '@qx/common';
23 import { formatEnum } from './constant'; 23 import { formatEnum } from './constant';
24 // import type { InputRef } from 'antd'; 24 // import type { InputRef } from 'antd';
25 import { 25 import {
@@ -29,7 +29,7 @@ import { @@ -29,7 +29,7 @@ import {
29 typeTranslateItemtype, 29 typeTranslateItemtype,
30 } from './constant'; 30 } from './constant';
31 31
32 -import { cloneDeep, debounce } from 'lodash-es'; 32 +import { cloneDeep } from 'lodash-es';
33 import moment from 'dayjs'; 33 import moment from 'dayjs';
34 import type { ParamDesignModel } from './constant'; 34 import type { ParamDesignModel } from './constant';
35 import { uidGen } from './stringUtil'; 35 import { uidGen } from './stringUtil';
@@ -662,7 +662,7 @@ export const QxParameterSetting: React.FC<ParameterSettingProps> = (props) => { @@ -662,7 +662,7 @@ export const QxParameterSetting: React.FC<ParameterSettingProps> = (props) => {
662 </div> 662 </div>
663 {props?.isShowField && ( 663 {props?.isShowField && (
664 <div className="opt-left-down"> 664 <div className="opt-left-down">
665 - <FieldSetter 665 + <QxFieldSetter
666 disabled={disabled} 666 disabled={disabled}
667 value={nodeData.valuesObj || []} 667 value={nodeData.valuesObj || []}
668 // value={[ 668 // value={[
@@ -163,7 +163,10 @@ export const QxSortCondition: React.FC<QxSortConditionProps> = (props) => { @@ -163,7 +163,10 @@ export const QxSortCondition: React.FC<QxSortConditionProps> = (props) => {
163 style={{ width: '100%' }} 163 style={{ width: '100%' }}
164 > 164 >
165 {(sorts || []).map((v: any, k: any) => ( 165 {(sorts || []).map((v: any, k: any) => (
166 - <div style={{ marginBottom: '1em' }} key={v.key}> 166 + <div
  167 + style={{ marginBottom: sorts?.length - 1 === k ? 0 : '1em' }}
  168 + key={v.key}
  169 + >
167 {columns && ( 170 {columns && (
168 <Select 171 <Select
169 defaultValue={v.key} 172 defaultValue={v.key}
@@ -6,77 +6,26 @@ @@ -6,77 +6,26 @@
6 */ 6 */
7 import { QxUserSelector } from '@qx/common'; 7 import { QxUserSelector } from '@qx/common';
8 import React from 'react'; 8 import React from 'react';
9 -import request from 'umi-request';  
10 -  
11 -request.interceptors.request.use((url, options) => {  
12 - if (url.startsWith('/api/')) {  
13 - return { url, options };  
14 - }  
15 - const headers = { Authorization: 'dev_session:ZGuqjkCF3GMzorijXw7' };  
16 - // headers['SERVER-IP'] = '192.168.181.112';  
17 -  
18 - const fullUrl = url.startsWith('http')  
19 - ? url  
20 - : `http://10.9.1.180/qx-api${url}`;  
21 - return {  
22 - url: fullUrl,  
23 - options: {  
24 - ...options,  
25 - ...{  
26 - headers: { ...headers, ...(options.customHeaders || {}) },  
27 - isInternal: true,  
28 - timeout: 30000,  
29 - },  
30 - },  
31 - };  
32 -});  
33 -  
34 -request.interceptors.response.use(async (response, options) => {  
35 - if (response.status !== 200) {  
36 - return Promise.reject(response);  
37 - }  
38 -  
39 - if (!response.headers.get('content-type')?.includes('application/json')) {  
40 - return response.blob();  
41 - }  
42 -  
43 - const body = await response.clone().json();  
44 -  
45 - // 按正常逻辑处理"文件上传"系列接口  
46 - const fsUploadApis = ['/file/checkFile', '/file/uploadByExist', '/fss/file/'];  
47 - const isFsUploadApis = fsUploadApis.filter(  
48 - (api: string) => options.url.indexOf(api) !== -1,  
49 - );  
50 - if (isFsUploadApis.length > 0) {  
51 - return Promise.resolve(body || null);  
52 - }  
53 -  
54 - if (body.success) {  
55 - return Promise.resolve(body.data || null);  
56 - }  
57 -  
58 - console.error('网络请求出错:', body.msg);  
59 -  
60 - return Promise.reject(body);  
61 -}); 9 +import { request } from '@qx/common';
62 10
63 export default () => { 11 export default () => {
64 return ( 12 return (
65 <div> 13 <div>
66 - <QxUserSelector  
67 - request={request}  
68 - params={{  
69 - org: [{ relType: 'APPOINT_ORG', relIds: [''] }],  
70 - pos: null,  
71 - range: [  
72 - 'ORG:MubDrwZm8IMxuLDU9FM',  
73 - 'ORG:a0WZVI96GAdoI5g9IwX',  
74 - 'ORG:QPLEku2yJU8hmbpLTtg',  
75 - ],  
76 - }}  
77 - /> 14 + <QxUserSelector request={request} />
  15 +
78 <br /> 16 <br />
79 - <QxUserSelector request={request} /> 17 + <QxUserSelector
  18 + request={request}
  19 + params={{
  20 + org: [{ relType: 'APPOINT_ORG', relIds: [''] }],
  21 + pos: null,
  22 + range: [
  23 + 'ORG:MubDrwZm8IMxuLDU9FM',
  24 + 'ORG:a0WZVI96GAdoI5g9IwX',
  25 + 'ORG:QPLEku2yJU8hmbpLTtg',
  26 + ],
  27 + }}
  28 + />
80 <br /> 29 <br />
81 <QxUserSelector 30 <QxUserSelector
82 readOnly 31 readOnly
@@ -89,6 +38,38 @@ export default () => { @@ -89,6 +38,38 @@ export default () => {
89 }; 38 };
90 ``` 39 ```
91 40
  41 +### 弹框
  42 +
  43 +```tsx
  44 +/**
  45 + * debug: true
  46 + */
  47 +import {QxUserSelector} from '@qx/common';
  48 +import React, {useState} from 'react';
  49 +import {request} from '@qx/common';
  50 +
  51 +export default () => {
  52 + const [visible, setVisible] = useState(false)
  53 + return (
  54 + <div>
  55 + <div onClick={()=> setVisible(true)}>点一下</div>
  56 + <QxUserSelector.Dialog
  57 + request={request}
  58 + title={'添加人员'}
  59 + visible={visible}
  60 + multiple={true}
  61 + onOk={(userIds: any) => {
  62 + console.log(userIds,'lllll')
  63 + }}
  64 + onCancel={() => {
  65 + setVisible(false);
  66 + }}
  67 + />
  68 + </div>
  69 + );
  70 +};
  71 +```
  72 +
92 ## API 73 ## API
93 74
94 | 参数 | 说明 | 类型 | 默认值 | 75 | 参数 | 说明 | 类型 | 默认值 |