index.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. // 视频设备列表
  2. import { PageContainer } from '@ant-design/pro-layout';
  3. import { useEffect, useRef, useState } from 'react';
  4. import type { ActionType, ProColumns } from '@jetlinks/pro-table';
  5. import { Button, message, Tooltip } from 'antd';
  6. import {
  7. DeleteOutlined,
  8. EditOutlined,
  9. EyeOutlined,
  10. PartitionOutlined,
  11. PlusOutlined,
  12. SyncOutlined,
  13. } from '@ant-design/icons';
  14. import type { DeviceItem } from '@/pages/media/Device/typings';
  15. import { useHistory, useIntl } from 'umi';
  16. import { BadgeStatus, PermissionButton, ProTableCard } from '@/components';
  17. import useLocation from '@/hooks/route/useLocation';
  18. import { StatusColorEnum } from '@/components/BadgeStatus';
  19. import SearchComponent from '@/components/SearchComponent';
  20. import MediaDevice from '@/components/ProTableCard/CardItems/mediaDevice';
  21. import { getMenuPathByCode, getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
  22. import Service from './service';
  23. import Save from './Save';
  24. export const service = new Service('media/device');
  25. export const providerType = {
  26. 'gb28181-2016': 'GB/T28181',
  27. 'fixed-media': '固定地址',
  28. };
  29. export const ProviderValue = {
  30. GB281: 'gb28181-2016',
  31. FIXED: 'fixed-media',
  32. };
  33. const Device = () => {
  34. const intl = useIntl();
  35. const actionRef = useRef<ActionType>();
  36. const [visible, setVisible] = useState<boolean>(false);
  37. const [current, setCurrent] = useState<DeviceItem>();
  38. const [queryParam, setQueryParam] = useState({});
  39. const history = useHistory<Record<string, string>>();
  40. const { permission } = PermissionButton.usePermission('media/Device');
  41. const location = useLocation();
  42. useEffect(() => {
  43. const { state } = location;
  44. if (state && state.save) {
  45. setVisible(true);
  46. }
  47. }, [location]);
  48. /**
  49. * table 查询参数
  50. * @param data
  51. */
  52. const searchFn = (data: any) => {
  53. setQueryParam(data);
  54. };
  55. const deleteItem = async (id: string) => {
  56. const response: any = await service.remove(id);
  57. if (response.status === 200) {
  58. message.success(
  59. intl.formatMessage({
  60. id: 'pages.data.option.success',
  61. defaultMessage: '操作成功!',
  62. }),
  63. );
  64. actionRef.current?.reload();
  65. }
  66. };
  67. /**
  68. * 更新通道
  69. * @param id 视频设备ID
  70. */
  71. const updateChannel = async (id: string) => {
  72. const resp = await service.updateChannels(id);
  73. if (resp.status === 200) {
  74. actionRef.current?.reload();
  75. message.success('通道更新成功');
  76. } else {
  77. message.error('通道更新失败');
  78. }
  79. };
  80. const columns: ProColumns<DeviceItem>[] = [
  81. {
  82. dataIndex: 'id',
  83. title: 'ID',
  84. ellipsis: true,
  85. fixed: 'left',
  86. },
  87. {
  88. dataIndex: 'name',
  89. ellipsis: true,
  90. title: intl.formatMessage({
  91. id: 'pages.table.name',
  92. defaultMessage: '名称',
  93. }),
  94. },
  95. {
  96. dataIndex: 'provider',
  97. title: '接入方式',
  98. render: (_, row) => {
  99. return providerType[row.provider];
  100. },
  101. valueType: 'select',
  102. valueEnum: {
  103. [ProviderValue.FIXED]: {
  104. text: '固定地址',
  105. status: ProviderValue.FIXED,
  106. },
  107. [ProviderValue.GB281]: {
  108. text: 'GB/T28181',
  109. status: ProviderValue.GB281,
  110. },
  111. },
  112. filterMultiple: false,
  113. },
  114. {
  115. dataIndex: 'channelNumber',
  116. title: intl.formatMessage({
  117. id: 'pages.media.device.channelNumber',
  118. defaultMessage: '通道数量',
  119. }),
  120. valueType: 'digit',
  121. hideInSearch: true,
  122. },
  123. {
  124. dataIndex: 'manufacturer',
  125. ellipsis: true,
  126. title: intl.formatMessage({
  127. id: 'pages.media.device.manufacturer',
  128. defaultMessage: '设备厂家',
  129. }),
  130. },
  131. // {
  132. // dataIndex: 'model',
  133. // title: intl.formatMessage({
  134. // id: 'pages.media.device.model',
  135. // defaultMessage: '型号',
  136. // }),
  137. // },
  138. // {
  139. // dataIndex: 'firmware',
  140. // title: intl.formatMessage({
  141. // id: 'pages.media.device.firmware',
  142. // defaultMessage: '固件版本',
  143. // }),
  144. // },
  145. {
  146. dataIndex: 'state',
  147. title: intl.formatMessage({
  148. id: 'pages.searchTable.titleStatus',
  149. defaultMessage: '状态',
  150. }),
  151. render: (_, record) => (
  152. <BadgeStatus
  153. status={record.state.value}
  154. statusNames={{
  155. online: StatusColorEnum.success,
  156. offline: StatusColorEnum.error,
  157. notActive: StatusColorEnum.processing,
  158. }}
  159. text={record.state.text}
  160. />
  161. ),
  162. valueType: 'select',
  163. valueEnum: {
  164. offline: {
  165. text: intl.formatMessage({
  166. id: 'pages.device.instance.status.offLine',
  167. defaultMessage: '离线',
  168. }),
  169. status: 'offline',
  170. },
  171. online: {
  172. text: intl.formatMessage({
  173. id: 'pages.device.instance.status.onLine',
  174. defaultMessage: '在线',
  175. }),
  176. status: 'online',
  177. },
  178. },
  179. filterMultiple: false,
  180. },
  181. {
  182. title: intl.formatMessage({
  183. id: 'pages.data.option',
  184. defaultMessage: '操作',
  185. }),
  186. valueType: 'option',
  187. align: 'center',
  188. width: 200,
  189. fixed: 'right',
  190. render: (text, record) => [
  191. <PermissionButton
  192. key="edit"
  193. tooltip={{
  194. title: intl.formatMessage({
  195. id: 'pages.data.option.edit',
  196. defaultMessage: '编辑',
  197. }),
  198. }}
  199. isPermission={permission.update}
  200. style={{ padding: 0 }}
  201. type={'link'}
  202. onClick={() => {
  203. setCurrent(record);
  204. setVisible(true);
  205. }}
  206. >
  207. <EditOutlined />
  208. </PermissionButton>,
  209. <PermissionButton
  210. tooltip={{
  211. title: '查看设备',
  212. }}
  213. style={{ padding: 0 }}
  214. type={'link'}
  215. onClick={() => {
  216. history.push(
  217. `${getMenuPathByCode(MENUS_CODE['media/Device/Channel'])}?id=${record.id}&type=${
  218. record.provider
  219. }`,
  220. );
  221. }}
  222. isPermission={true}
  223. key={'view'}
  224. >
  225. <PartitionOutlined />
  226. </PermissionButton>,
  227. <Tooltip key={'deviceDetail'} title={'查看'}>
  228. <Button
  229. style={{ padding: 0 }}
  230. type={'link'}
  231. onClick={() => {
  232. history.push(
  233. `${getMenuPathByParams(MENUS_CODE['device/Instance/Detail'], record.id)}`,
  234. );
  235. }}
  236. >
  237. <EyeOutlined />
  238. </Button>
  239. </Tooltip>,
  240. <PermissionButton
  241. tooltip={{
  242. title:
  243. record.provider === ProviderValue.FIXED
  244. ? '接入方式为固定地址时不支持更新通道'
  245. : '更新通道',
  246. }}
  247. key={'updateChannel'}
  248. isPermission={permission.action}
  249. disabled={record.state.value === 'offline' || record.provider === ProviderValue.FIXED}
  250. style={{ padding: 0 }}
  251. type={'link'}
  252. onClick={() => {
  253. updateChannel(record.id);
  254. }}
  255. >
  256. <SyncOutlined />
  257. </PermissionButton>,
  258. <PermissionButton
  259. key={'delete'}
  260. tooltip={{
  261. title: '删除',
  262. }}
  263. popConfirm={{
  264. title: intl.formatMessage({
  265. id:
  266. record.state.value === 'offline'
  267. ? 'pages.device.productDetail.deleteTip'
  268. : 'page.table.isDelete',
  269. defaultMessage: '是否删除?',
  270. }),
  271. onConfirm: async () => {
  272. if (record.state.value !== 'offline') {
  273. await deleteItem(record.id);
  274. } else {
  275. message.error('在线设备不能进行删除操作');
  276. }
  277. },
  278. }}
  279. type={'link'}
  280. style={{ padding: 0 }}
  281. isPermission={permission.delete}
  282. disabled={record.state.value !== 'offline'}
  283. >
  284. <DeleteOutlined />
  285. </PermissionButton>,
  286. ],
  287. },
  288. ];
  289. return (
  290. <PageContainer>
  291. <SearchComponent field={columns} onSearch={searchFn} target="media-device" />
  292. <ProTableCard<DeviceItem>
  293. columns={columns}
  294. actionRef={actionRef}
  295. options={{ fullScreen: true }}
  296. params={queryParam}
  297. scroll={{ x: 1366 }}
  298. request={(params = {}) =>
  299. service.query({
  300. ...params,
  301. sorts: [
  302. {
  303. name: 'createTime',
  304. order: 'desc',
  305. },
  306. ],
  307. })
  308. }
  309. rowKey="id"
  310. search={false}
  311. headerTitle={[
  312. <PermissionButton
  313. onClick={() => {
  314. setCurrent(undefined);
  315. setVisible(true);
  316. }}
  317. key="button"
  318. icon={<PlusOutlined />}
  319. type="primary"
  320. isPermission={permission.add}
  321. >
  322. {intl.formatMessage({
  323. id: 'pages.data.option.add',
  324. defaultMessage: '新增',
  325. })}
  326. </PermissionButton>,
  327. ]}
  328. cardRender={(record) => (
  329. <MediaDevice
  330. {...record}
  331. detail={
  332. <div
  333. style={{ fontSize: 18, padding: 8 }}
  334. onClick={() => {
  335. history.push(
  336. `${getMenuPathByParams(MENUS_CODE['device/Instance/Detail'], record.id)}`,
  337. );
  338. }}
  339. >
  340. <EyeOutlined />
  341. </div>
  342. }
  343. actions={[
  344. <PermissionButton
  345. key="edit"
  346. isPermission={permission.update}
  347. onClick={() => {
  348. setCurrent(record);
  349. setVisible(true);
  350. }}
  351. type={'link'}
  352. style={{ padding: 0 }}
  353. >
  354. <EditOutlined />
  355. {intl.formatMessage({
  356. id: 'pages.data.option.edit',
  357. defaultMessage: '编辑',
  358. })}
  359. </PermissionButton>,
  360. <Button
  361. key={'viewChannel'}
  362. onClick={() => {
  363. history.push(
  364. `${getMenuPathByCode(MENUS_CODE['media/Device/Channel'])}?id=${
  365. record.id
  366. }&type=${record.provider}`,
  367. );
  368. }}
  369. >
  370. <PartitionOutlined />
  371. 查看通道
  372. </Button>,
  373. <PermissionButton
  374. key={'updateChannel'}
  375. isPermission={permission.update}
  376. tooltip={
  377. record.state.value === 'offline' ||
  378. record.provider === providerType['fixed-media']
  379. ? {
  380. title:
  381. record.provider === providerType['fixed-media']
  382. ? '固定地址无法更新通道'
  383. : record.state.value === 'offline'
  384. ? '设备已离线'
  385. : '',
  386. }
  387. : undefined
  388. }
  389. disabled={
  390. record.state.value === 'offline' ||
  391. record.provider === providerType['fixed-media']
  392. }
  393. onClick={() => {
  394. updateChannel(record.id);
  395. }}
  396. >
  397. <SyncOutlined />
  398. 更新通道
  399. </PermissionButton>,
  400. <PermissionButton
  401. key="delete"
  402. popConfirm={{
  403. title: intl.formatMessage({
  404. id:
  405. record.state.value !== 'offline'
  406. ? 'pages.device.instance.deleteTip'
  407. : 'page.table.isDelete',
  408. defaultMessage: '是否删除?',
  409. }),
  410. onConfirm: async () => {
  411. if (record.state.value === 'offline') {
  412. await deleteItem(record.id);
  413. } else {
  414. message.error('在线设备不能进行删除操作');
  415. }
  416. },
  417. }}
  418. type={'link'}
  419. style={{ padding: 0 }}
  420. isPermission={permission.delete}
  421. disabled={record.state.value !== 'offline'}
  422. >
  423. <DeleteOutlined />
  424. </PermissionButton>,
  425. ]}
  426. />
  427. )}
  428. />
  429. <Save
  430. model={!current ? 'add' : 'edit'}
  431. data={current}
  432. close={() => {
  433. setVisible(false);
  434. }}
  435. reload={() => {
  436. actionRef.current?.reload();
  437. }}
  438. visible={visible}
  439. />
  440. </PageContainer>
  441. );
  442. };
  443. export default Device;