index.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import React from 'react';
  2. import { Card } from 'antd';
  3. import { CardProps } from 'antd/lib/card';
  4. import { ArrayField } from '@formily/core';
  5. import { observer, RecursionField, useField, useFieldSchema } from '@formily/react';
  6. import cls from 'classnames';
  7. import { ISchema } from '@formily/json-schema';
  8. import { usePrefixCls } from '@formily/antd/lib/__builtins__';
  9. import { ArrayBase, ArrayBaseMixins } from '@formily/antd';
  10. import { Empty } from '@/components';
  11. type ComposedArrayCards = React.FC<CardProps> & ArrayBaseMixins;
  12. const isAdditionComponent = (schema: ISchema) => {
  13. return schema['x-component']?.indexOf('Addition') > -1;
  14. };
  15. const isIndexComponent = (schema: ISchema) => {
  16. return schema['x-component']?.indexOf('Index') > -1;
  17. };
  18. const isRemoveComponent = (schema: ISchema) => {
  19. return schema['x-component']?.indexOf('Remove') > -1;
  20. };
  21. const isMoveUpComponent = (schema: ISchema) => {
  22. return schema['x-component']?.indexOf('MoveUp') > -1;
  23. };
  24. const isMoveDownComponent = (schema: ISchema) => {
  25. return schema['x-component']?.indexOf('MoveDown') > -1;
  26. };
  27. const isOperationComponent = (schema: ISchema) => {
  28. return (
  29. isAdditionComponent(schema) ||
  30. isRemoveComponent(schema) ||
  31. isMoveDownComponent(schema) ||
  32. isMoveUpComponent(schema)
  33. );
  34. };
  35. export const FTermArrayCards: ComposedArrayCards = observer((props) => {
  36. const field = useField<ArrayField>();
  37. const schema = useFieldSchema();
  38. const dataSource = Array.isArray(field.value) ? field.value : [];
  39. const prefixCls = usePrefixCls('formily-array-cards', props);
  40. if (!schema) throw new Error('can not found schema object');
  41. const renderItems = () => {
  42. return dataSource?.map((item, index) => {
  43. const items = Array.isArray(schema.items)
  44. ? schema.items[index] || schema.items[0]
  45. : schema.items;
  46. const title = (
  47. <span>
  48. <RecursionField
  49. schema={items!}
  50. name={index}
  51. filterProperties={(schema4) => {
  52. if (!isIndexComponent(schema4)) return false;
  53. return true;
  54. }}
  55. onlyRenderProperties
  56. />
  57. {props.title || field.title}
  58. </span>
  59. );
  60. const extra = (
  61. <span>
  62. <RecursionField
  63. schema={items!}
  64. name={index}
  65. filterProperties={(schema1) => {
  66. if (!isOperationComponent(schema1)) return false;
  67. return true;
  68. }}
  69. onlyRenderProperties
  70. />
  71. {props.extra}
  72. </span>
  73. );
  74. const content = (
  75. <RecursionField
  76. schema={items!}
  77. name={index}
  78. filterProperties={(schema2) => {
  79. if (isIndexComponent(schema2)) return false;
  80. if (isOperationComponent(schema2)) return false;
  81. return true;
  82. }}
  83. />
  84. );
  85. return (
  86. ArrayBase.Item && (
  87. <ArrayBase.Item key={index} index={index} record={item}>
  88. {index > 0 && (
  89. <div style={{ marginTop: 20, display: 'flex', justifyContent: 'center' }}>
  90. <RecursionField
  91. schema={
  92. {
  93. type: 'object',
  94. properties: {
  95. type: {
  96. 'x-decorator': 'FormItem',
  97. 'x-component': 'Select',
  98. 'x-component-props': {
  99. style: {
  100. width: 100,
  101. },
  102. },
  103. 'x-value': 'and',
  104. enum: [
  105. { label: '并且', value: 'and' },
  106. { label: '或者', value: 'or' },
  107. ],
  108. },
  109. },
  110. } as any
  111. }
  112. name={index}
  113. filterProperties={(schema2) => {
  114. if (isIndexComponent(schema2)) return false;
  115. if (isOperationComponent(schema2)) return false;
  116. return true;
  117. }}
  118. />
  119. </div>
  120. )}
  121. <Card
  122. {...props}
  123. onChange={() => {}}
  124. className={cls(`${prefixCls}-item`, props.className)}
  125. title={title}
  126. extra={extra}
  127. >
  128. {content}
  129. </Card>
  130. </ArrayBase.Item>
  131. )
  132. );
  133. });
  134. };
  135. const renderAddition = () => {
  136. return schema.reduceProperties((addition: any, schema3: any, key: any) => {
  137. if (isAdditionComponent(schema3)) {
  138. return <RecursionField schema={schema3} name={key} />;
  139. }
  140. return addition;
  141. }, null);
  142. };
  143. const renderEmpty = () => {
  144. if (dataSource?.length) return;
  145. return (
  146. <Card
  147. {...props}
  148. onChange={() => {}}
  149. className={cls(`${prefixCls}-item`, props.className)}
  150. title={props.title || field.title}
  151. >
  152. <Empty />
  153. </Card>
  154. );
  155. };
  156. return (
  157. <ArrayBase>
  158. {renderEmpty()}
  159. {renderItems()}
  160. {renderAddition()}
  161. </ArrayBase>
  162. );
  163. });
  164. FTermArrayCards.displayName = 'FTermArrayCards';
  165. ArrayBase.mixin!(FTermArrayCards);
  166. export default FTermArrayCards;