index.tsx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. import { Badge, Input, Modal } from 'antd';
  2. import { EditOutlined } from '@ant-design/icons';
  3. import type { Key } from 'react';
  4. import { useRef, useState } from 'react';
  5. import type { ActionType, ProColumns } from '@jetlinks/pro-table';
  6. import ProTable from '@jetlinks/pro-table';
  7. import type { DeviceInstance } from '@/pages/device/Instance/typings';
  8. import { useIntl } from '@@/plugin-locale/localeExports';
  9. import Service from '@/pages/device/Instance/service';
  10. import SearchComponent from '../SearchComponent';
  11. import { observer } from '@formily/react';
  12. import { model } from '@formily/reactive';
  13. import moment from 'moment';
  14. interface Props {
  15. id?: string;
  16. value?: Partial<DeviceInstance>[];
  17. onChange?: (data: Partial<DeviceInstance>[]) => void;
  18. productId?: string;
  19. disabled?: boolean;
  20. }
  21. const deviceStatus = new Map();
  22. deviceStatus.set('online', <Badge status="success" text={'在线'} />);
  23. deviceStatus.set('offline', <Badge status="error" text={'离线'} />);
  24. deviceStatus.set('notActive', <Badge status="processing" text={'禁用'} />);
  25. const service = new Service('device/instance');
  26. const State = model<{
  27. visible: boolean;
  28. }>({
  29. visible: false,
  30. });
  31. const FSelectDevices = observer((props: Props) => {
  32. // todo 考虑与单选设备合并
  33. const intl = useIntl();
  34. const actionRef1 = useRef<ActionType>();
  35. const [searchParam, setSearchParam] = useState({});
  36. const columns: ProColumns<DeviceInstance>[] = [
  37. {
  38. title: 'ID',
  39. dataIndex: 'id',
  40. ellipsis: true,
  41. },
  42. {
  43. title: intl.formatMessage({
  44. id: 'pages.table.deviceName',
  45. defaultMessage: '设备名称',
  46. }),
  47. dataIndex: 'name',
  48. ellipsis: true,
  49. },
  50. {
  51. title: '固件版本',
  52. dataIndex: 'firmwareInfo',
  53. ellipsis: true,
  54. render: (text: any, record: any) => record?.version || '',
  55. },
  56. {
  57. title: intl.formatMessage({
  58. id: 'pages.device.instance.registrationTime',
  59. defaultMessage: '注册时间',
  60. }),
  61. dataIndex: 'registryTime',
  62. width: '200px',
  63. valueType: 'dateTime',
  64. render: (text: any, record: any) =>
  65. record?.registerTime ? moment(record?.registerTime).format('YYYY-MM-DD HH:mm:ss') : '',
  66. },
  67. {
  68. title: '状态',
  69. dataIndex: 'state',
  70. render: (text: any, record: any) =>
  71. record?.state?.value ? deviceStatus.get(record?.state?.value) : '',
  72. ellipsis: true,
  73. },
  74. ];
  75. const [data, setData] = useState<Partial<DeviceInstance>[]>(props?.value || []);
  76. const rowSelection = {
  77. onSelect: (selectedRow: any, selected: any) => {
  78. let newSelectKeys = [...data];
  79. if (selected) {
  80. newSelectKeys.push({ ...selectedRow });
  81. } else {
  82. newSelectKeys = newSelectKeys.filter((item) => item.id !== selectedRow.id);
  83. }
  84. setData(newSelectKeys);
  85. },
  86. onSelectAll: (selected: boolean, _: any, changeRows: any) => {
  87. let newSelectKeys = [...data];
  88. if (selected) {
  89. changeRows.forEach((item: any) => {
  90. newSelectKeys.push({ ...item });
  91. });
  92. } else {
  93. newSelectKeys = newSelectKeys.filter((a) => {
  94. return !changeRows.some((b: any) => b.id === a.id);
  95. });
  96. }
  97. setData(newSelectKeys);
  98. },
  99. selectedRowKeys: data?.map((item) => item.id) as Key[],
  100. };
  101. const reload = () => {
  102. actionRef1.current?.reset?.();
  103. setSearchParam({});
  104. };
  105. return (
  106. <>
  107. <Input
  108. disabled
  109. value={props.value?.map((item) => item.name).join(',')}
  110. id={props?.id}
  111. addonAfter={
  112. <EditOutlined
  113. onClick={() => {
  114. if (props.disabled) {
  115. State.visible = false;
  116. } else {
  117. State.visible = true;
  118. }
  119. }}
  120. />
  121. }
  122. />
  123. {State.visible && (
  124. <Modal
  125. maskClosable={false}
  126. visible
  127. title="选择设备"
  128. width="80vw"
  129. onCancel={() => {
  130. State.visible = false;
  131. reload();
  132. }}
  133. onOk={() => {
  134. State.visible = false;
  135. reload();
  136. if (props.onChange) {
  137. props.onChange(data);
  138. }
  139. }}
  140. >
  141. <SearchComponent<DeviceInstance>
  142. field={columns}
  143. enableSave={false}
  144. model="simple"
  145. onSearch={(data1) => {
  146. actionRef1.current?.reset?.();
  147. setSearchParam(data1);
  148. }}
  149. target="choose-devices"
  150. />
  151. <ProTable<DeviceInstance>
  152. tableAlertRender={false}
  153. rowSelection={{
  154. type: 'checkbox',
  155. ...rowSelection,
  156. }}
  157. search={false}
  158. columnEmptyText={''}
  159. rowKey="id"
  160. params={searchParam}
  161. columns={columns}
  162. actionRef={actionRef1}
  163. request={async (params) => {
  164. return service.queryDetailList({
  165. context: {
  166. includeTags: false,
  167. includeBind: false,
  168. includeRelations: false,
  169. },
  170. ...params,
  171. terms: [
  172. ...(params?.terms || []),
  173. {
  174. terms: [
  175. {
  176. column: 'productId',
  177. value: props?.productId,
  178. },
  179. ],
  180. type: 'and',
  181. },
  182. ],
  183. sorts: [{ name: 'createTime', order: 'desc' }],
  184. });
  185. }}
  186. />
  187. </Modal>
  188. )}
  189. </>
  190. );
  191. });
  192. export default FSelectDevices;