index.tsx 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import React, { useEffect, useState } from 'react';
  2. import { PageContainer } from '@ant-design/pro-components';
  3. import { Card, Space, Table } from 'antd';
  4. import type { ColumnsType } from 'antd/es/table';
  5. import { queryScenes } from '@/services/scene';
  6. import SceneHistory from '@/pages/SceneManagement/sceneHistory';
  7. interface DataType {
  8. name: string;
  9. home_name: number;
  10. type_name: string;
  11. creator_name: string;
  12. description_expr: string;
  13. record_id: string;
  14. }
  15. /**
  16. * 场景管理
  17. * @constructor
  18. */
  19. const SceneManagement: React.FC = () => {
  20. const [loading, setLoading] = useState(false);
  21. const [pagination, setPagination] = useState({ total: 0, current: 1, pageSize: 10 });
  22. const [dataList, setDataList] = useState([]);
  23. const [visible, setVisible] = useState(false);
  24. const [recordId, setRecordId] = useState('');
  25. const weekArray = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
  26. // 获取列表数据
  27. const getList = () => {
  28. const params = {
  29. q: 'page',
  30. current: pagination.current,
  31. pageSize: pagination.pageSize,
  32. };
  33. queryScenes(params).then((res) => {
  34. if (res && res.code === 0) {
  35. setDataList(res.data.list);
  36. setPagination(res.data.pagination);
  37. setLoading(false);
  38. }
  39. });
  40. };
  41. useEffect(() => {
  42. setLoading(true);
  43. getList();
  44. }, []);
  45. // 分页切换
  46. const tableChange = (page: any) => {
  47. setLoading(true);
  48. const params = {
  49. q: 'page',
  50. current: page.current,
  51. pageSize: page.pageSize,
  52. };
  53. queryScenes(params).then((res) => {
  54. if (res && res.code === 0) {
  55. setDataList(res.data.list);
  56. setPagination(res.data.pagination);
  57. setLoading(false);
  58. }
  59. });
  60. };
  61. // 跳转到历史记录弹框中
  62. const toHistory = (record: any) => {
  63. setVisible(true);
  64. setRecordId(record.record_id);
  65. };
  66. // 历史弹框回调
  67. const onHistoryCallback = () => {
  68. setVisible(false);
  69. };
  70. // 转换成星期 例: 0,1,1,1,1,1,1 => 周一,周二,周三,周四,周五,周六
  71. const convertToWeekdays = (binaryStr: string) => {
  72. // 判断 binaryStr 是否存在
  73. if (!binaryStr || typeof binaryStr !== 'string') {
  74. return '';
  75. }
  76. const days = binaryStr.split(',');
  77. // 判断是否全为 0(仅此一次)
  78. if (days.every((day) => parseInt(day) === 0)) {
  79. return '仅此一次';
  80. }
  81. // 判断是否全为 1(每天)
  82. if (days.every((day) => parseInt(day) === 1)) {
  83. return '每天';
  84. }
  85. // 其他情况按原逻辑处理
  86. return days
  87. .map((day, index) => (parseInt(day) === 1 ? weekArray[index] : ''))
  88. .filter((day) => day !== '')
  89. .join(',');
  90. };
  91. const columns: ColumnsType<DataType> = [
  92. {
  93. title: '序号',
  94. align: 'center',
  95. key: 'index',
  96. width: 80,
  97. render: (_: any, row: any, index: number) => index + 1,
  98. },
  99. {
  100. title: '房间名称',
  101. dataIndex: 'home_name',
  102. key: 'home_name',
  103. width: 250,
  104. },
  105. {
  106. title: '场景名称',
  107. dataIndex: 'name',
  108. key: 'name',
  109. width: 250,
  110. },
  111. {
  112. title: '场景类型',
  113. dataIndex: 'type_name',
  114. key: 'type_name',
  115. width: 250,
  116. },
  117. {
  118. title: '关联设备数',
  119. dataIndex: 'device_infos',
  120. key: 'device_infos',
  121. width: 250,
  122. render: (v) => {
  123. if (v) {
  124. return `${v.length}个`;
  125. } else {
  126. return `0个`;
  127. }
  128. },
  129. },
  130. {
  131. title: '动作',
  132. dataIndex: 'action_desc',
  133. key: 'action_desc',
  134. width: 250,
  135. render: (v: string) => {
  136. if (!v || typeof v !== 'string') {
  137. return <div style={{ color: 'gray' }}>暂无动作数据</div>;
  138. }
  139. return v.split(';').map((item: string) => {
  140. return <div key={item}>{item}</div>;
  141. });
  142. },
  143. },
  144. {
  145. title: '条件',
  146. dataIndex: 'conditions',
  147. key: 'conditions',
  148. width: 350,
  149. render: (v: string) => {
  150. if (!v || !Array.isArray(v) || v.length === 0) {
  151. return <div style={{ color: 'gray' }}>暂无条件数据</div>;
  152. }
  153. return v.map((item: any, index: number) => {
  154. const key = item.record_id || `condition-${index}`;
  155. switch (item.entity_type) {
  156. case 'timer':
  157. const time = item.expr?.time || '';
  158. const loops = item.expr?.loops || '';
  159. return <div key={key}>{`定时:${time} | ${convertToWeekdays(loops)};`}</div>;
  160. case 'weather':
  161. const weatherName = item.weather_name || '';
  162. const weatherValueName = item.weather_value_name || '';
  163. const location = item.expr?.location || '';
  164. return (
  165. <div key={key}>{`${weatherName}: ${weatherValueName} | 地址:${location};`}</div>
  166. );
  167. case 'device_status':
  168. const statusFuncName = item.status_func_name || '';
  169. const statusFuncValueName = item.status_func_value_name || '';
  170. const deviceName = item.device_name || '';
  171. return (
  172. <div key={key}>{`${statusFuncName}: ${statusFuncValueName} | ${deviceName};`}</div>
  173. );
  174. default:
  175. return (
  176. <div key={key} style={{ color: 'gray' }}>
  177. 暂无条件数据
  178. </div>
  179. );
  180. }
  181. });
  182. },
  183. },
  184. {
  185. title: '执行条件',
  186. dataIndex: 'description_expr',
  187. key: 'description_expr',
  188. width: 250,
  189. render: (v: string) => {
  190. return <span>{{ or: '满足任一条件', and: '满足所有条件' }[v]}</span>;
  191. },
  192. },
  193. {
  194. title: '创建者',
  195. dataIndex: 'creator_name',
  196. key: 'creator_name',
  197. width: 250,
  198. },
  199. {
  200. title: '操作',
  201. key: 'action',
  202. width: 150,
  203. render: (_, record) => (
  204. <Space size="middle">
  205. <a
  206. onClick={() => {
  207. toHistory(record);
  208. }}
  209. >
  210. 历史记录
  211. </a>
  212. </Space>
  213. ),
  214. },
  215. ];
  216. const paginationProps = {
  217. showSizeChanger: true,
  218. showQuickJumper: true,
  219. showTotal: (total: number) => {
  220. return <span> 共 {total}条 </span>;
  221. },
  222. ...pagination,
  223. };
  224. return (
  225. <PageContainer>
  226. <div>
  227. <Card>
  228. <Table
  229. columns={columns}
  230. dataSource={dataList}
  231. rowKey={(record) => record.record_id}
  232. pagination={paginationProps}
  233. loading={loading}
  234. onChange={tableChange}
  235. />
  236. {visible && (
  237. <SceneHistory
  238. visible={visible}
  239. editCallback={() => {
  240. onHistoryCallback();
  241. }}
  242. recordId={recordId}
  243. />
  244. )}
  245. </Card>
  246. </div>
  247. </PageContainer>
  248. );
  249. };
  250. export default SceneManagement;