api.ts 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. import axios from 'axios';
  2. import * as THREE from 'three';
  3. import {
  4. AlarmDeviceData,
  5. CategoryChartData,
  6. CategoryChartDataWithPercent,
  7. OnlineRateChartData,
  8. StateChartData,
  9. StateChartDataWithPercent,
  10. AlarmChartData,
  11. DeviceWithAssetInfo,
  12. } from '../share/monitorTypes.ts';
  13. // API请求参数类型定义
  14. interface OnlineRateChartParams {
  15. created_at?: {
  16. $gte: string;
  17. $lte: string;
  18. };
  19. dimension?: {
  20. $eq: 'hour' | 'day' | 'month';
  21. };
  22. pagination?: {
  23. page: number;
  24. pageSize: number;
  25. };
  26. }
  27. interface AlarmChartParams {
  28. created_at?: {
  29. $gte: string;
  30. $lte: string;
  31. };
  32. dimension?: {
  33. $eq: 'hour' | 'day' | 'month';
  34. };
  35. }
  36. interface DeviceInstancesParams {
  37. is_deleted?: number;
  38. }
  39. interface RackQueryParams {
  40. is_deleted?: number;
  41. }
  42. interface RackServerQueryParams {
  43. rack_id?: number;
  44. is_deleted?: number;
  45. }
  46. interface RackServerTypeParams {
  47. is_enabled?: number;
  48. is_deleted?: number;
  49. page?: number;
  50. pageSize?: number;
  51. }
  52. // 机柜数据
  53. interface RackData {
  54. id: number;
  55. rack_name: string;
  56. rack_code: string;
  57. capacity: number;
  58. position_x: number;
  59. position_y: number;
  60. position_z: number;
  61. area?: string;
  62. room?: string;
  63. remark?: string;
  64. is_disabled: number;
  65. is_deleted: number;
  66. created_at: string;
  67. updated_at: string;
  68. }
  69. // 机柜服务器数据
  70. interface RackServerData {
  71. id: number;
  72. rack_id: number;
  73. asset_id: number;
  74. start_position: number;
  75. size: number;
  76. server_type?: string;
  77. remark?: string;
  78. is_disabled: number;
  79. is_deleted: number;
  80. created_at: string;
  81. updated_at: string;
  82. // 关联字段 asset
  83. asset_name: string;
  84. device_category: number;
  85. ip_address?: string;
  86. device_status: number;
  87. network_status: number;
  88. packet_loss: number;
  89. cpu?: string;
  90. memory?: string;
  91. disk?: string;
  92. // 关联字段 rack
  93. rack_name: string;
  94. rack_code: string;
  95. }
  96. // 设备类型图标数据
  97. interface DeviceIconData {
  98. id: number;
  99. category_id: number;
  100. icon: string;
  101. icon_name?: string;
  102. icon_type: string;
  103. sort: number;
  104. is_default: number;
  105. is_disabled: number;
  106. is_deleted: number;
  107. created_at: string;
  108. updated_at: string;
  109. category?: {
  110. name: string;
  111. };
  112. }
  113. // 机柜服务器类型数据
  114. interface RackServerType {
  115. /** 主键ID */
  116. id: number;
  117. /** 类型名称 */
  118. name: string;
  119. /** 类型编码 */
  120. code: string;
  121. /** 类型图片 */
  122. image_url?: string;
  123. /** 类型描述 */
  124. description?: string;
  125. /** 是否启用 (0否 1是) */
  126. is_enabled?: number;
  127. /** 是否被删除 (0否 1是) */
  128. is_deleted?: number;
  129. /** 创建时间 */
  130. created_at: string;
  131. /** 更新时间 */
  132. updated_at: string;
  133. }
  134. // 服务器基本信息接口
  135. export interface ServerData {
  136. id: number;
  137. slot: number;
  138. u: number;
  139. type: number;
  140. name: string;
  141. ip: string;
  142. cpu: string;
  143. memory: string;
  144. disk: string;
  145. deviceStatus: number;
  146. networkStatus: number;
  147. packetLoss: number;
  148. }
  149. // 设备状态和监控数据接口
  150. export interface DeviceStatusInfo {
  151. status: 'online' | 'offline' | 'warning';
  152. usage: {
  153. cpu: number;
  154. memory: number;
  155. disk: number;
  156. };
  157. }
  158. // 机柜配置接口
  159. export interface RackConfig {
  160. position: THREE.Vector3;
  161. serverCount: number;
  162. id: number;
  163. name: string;
  164. servers: ServerData[];
  165. }
  166. // 服务器图标接口
  167. export interface ServerIconConfig {
  168. textureUrl: string | null;
  169. color: number;
  170. }
  171. export interface ServerIconConfigs {
  172. [key: number]: ServerIconConfig;
  173. }
  174. const API_BASE_URL = '/api';
  175. // 从全局配置中获取OSS_HOST,如果不存在则使用默认值
  176. const OSS_BASE_URL = window.CONFIG?.OSS_BASE_URL || '';
  177. // 计算风险等级
  178. const calculateRiskLevel = (onlineRate: number): { level: string; color: string } => {
  179. if (onlineRate >= 95) {
  180. return { level: '健康', color: '#52c41a' }; // 绿色
  181. } else if (onlineRate >= 80) {
  182. return { level: '风险低', color: '#faad14' }; // 黄色
  183. } else if (onlineRate >= 70) {
  184. return { level: '风险中', color: '#faad14' }; // 黄色
  185. } else {
  186. return { level: '高风险', color: '#f5222d' }; // 红色
  187. }
  188. };
  189. // 统一将查询函数提取到顶部
  190. export const queryFns = {
  191. // 资产分类数据查询
  192. fetchCategoryData: async (): Promise<CategoryChartDataWithPercent[]> => {
  193. const res = await axios.get<CategoryChartData[]>(`${API_BASE_URL}/big/zichan_category_chart`);
  194. // 预先计算百分比
  195. const data = res.data;
  196. const total = data.reduce((sum: number, item: CategoryChartData) => sum + item['设备数'], 0);
  197. // 为每个数据项添加百分比字段
  198. return data.map(item => ({
  199. ...item,
  200. 百分比: total > 0 ? (item['设备数'] / total * 100).toFixed(1) : '0'
  201. }));
  202. },
  203. // 在线率变化数据查询
  204. fetchOnlineRateData: async (): Promise<OnlineRateChartData[]> => {
  205. // 直接使用扁平化参数
  206. const params = {
  207. // created_at_gte: dayjs().subtract(7, 'day').format('YYYY-MM-DD HH:mm:ss'),
  208. // created_at_lte: dayjs().format('YYYY-MM-DD HH:mm:ss'),
  209. // dimension: 'day',
  210. // page: 1,
  211. // pageSize: 1000
  212. };
  213. const res = await axios.get<OnlineRateChartData[]>(`${API_BASE_URL}/big/zichan_online_rate_chart`, { params });
  214. return res.data;
  215. },
  216. // 资产流转状态数据查询
  217. fetchStateData: async (): Promise<StateChartDataWithPercent[]> => {
  218. const res = await axios.get<StateChartData[]>(`${API_BASE_URL}/big/zichan_state_chart`);
  219. // 预先计算百分比
  220. const data = res.data;
  221. const total = data.reduce((sum: number, item: StateChartData) => sum + item['设备数'], 0);
  222. // 为每个数据项添加百分比字段
  223. return data.map(item => ({
  224. ...item,
  225. 百分比: total > 0 ? (item['设备数'] / total * 100).toFixed(1) : '0'
  226. }));
  227. },
  228. // 告警数据变化查询
  229. fetchAlarmData: async (): Promise<AlarmChartData[]> => {
  230. // 直接使用扁平化参数
  231. const params = {
  232. // created_at_gte: dayjs().startOf('day').format('YYYY-MM-DD HH:mm:ss'),
  233. // created_at_lte: dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss'),
  234. // dimension: 'hour'
  235. };
  236. const res = await axios.get<AlarmChartData[]>(`${API_BASE_URL}/big/zichan_alarm_chart`, { params });
  237. return res.data;
  238. },
  239. // 获取设备数据
  240. fetchDeviceMetrics: async () => {
  241. const params = {
  242. is_deleted: 0
  243. };
  244. const response = await axios.get<DeviceWithAssetInfo[]>(`${API_BASE_URL}/big/device-instances`, { params });
  245. const devices = response.data;
  246. const totalDevices = devices.length;
  247. const onlineDevices = devices.filter(device => device.device_status === 1).length;
  248. const offlineDevices = totalDevices - onlineDevices;
  249. const onlineRate = totalDevices ? ((onlineDevices / totalDevices) * 100) : 0;
  250. const riskLevel = calculateRiskLevel(onlineRate);
  251. return {
  252. totalDevices,
  253. onlineDevices,
  254. offlineDevices,
  255. onlineRate: onlineRate.toFixed(2),
  256. riskLevel
  257. };
  258. },
  259. // 获取告警设备数据
  260. fetchTopAlarmDevices: async (): Promise<AlarmDeviceData[]> => {
  261. const response = await axios.get<AlarmDeviceData[]>(`${API_BASE_URL}/big/zichan_alarm_device`);
  262. return response.data;
  263. },
  264. // 获取机柜配置数据
  265. fetchRackConfigs: async (): Promise<RackConfig[]> => {
  266. const params: RackQueryParams = {
  267. is_deleted: 0
  268. }
  269. // 1. 获取机柜数据
  270. const rackResponse = await axios.get<RackData[]>(`${API_BASE_URL}/big/rack`, { params });
  271. const racks = rackResponse.data;
  272. // 2. 获取所有机柜的服务器数据
  273. const serverPromises = racks.map(async (rack: RackData) => {
  274. const params: RackServerQueryParams = {
  275. rack_id: rack.id,
  276. is_deleted: 0
  277. }
  278. const serverResponse = await axios.get<RackServerData[]>(`${API_BASE_URL}/big/rack-server`, { params });
  279. // 3. 获取每个服务器对应的基本信息
  280. let servers: ServerData[] = [];
  281. try {
  282. servers = serverResponse.data.map((server: RackServerData) => ({
  283. id: server.id,
  284. slot: server.start_position,
  285. u: server.size,
  286. type: server.device_category,
  287. name: server.asset_name || '',
  288. ip: server.ip_address || '',
  289. cpu: server.cpu || '',
  290. memory: server.memory || '',
  291. disk: server.disk || '',
  292. deviceStatus: server.device_status || 0,
  293. networkStatus: server.network_status || 0,
  294. packetLoss: server.packet_loss || 0
  295. }));
  296. } catch (error) {
  297. console.error("error", error);
  298. }
  299. // 返回包含服务器数据的机柜配置
  300. return {
  301. position: new THREE.Vector3(Number(rack.position_x) || 0, Number(rack.position_y) || 0, Number(rack.position_z) || 0),
  302. serverCount: rack.capacity || 42,
  303. id: rack.id,
  304. name: rack.rack_name,
  305. servers
  306. };
  307. });
  308. // 等待所有数据获取完成
  309. return Promise.all(serverPromises);
  310. },
  311. // 获取服务器类型图标配置
  312. fetchDeviceIcons: async (): Promise<ServerIconConfigs> => {
  313. const params: RackServerTypeParams = {
  314. is_enabled: 1,
  315. is_deleted: 0,
  316. page: 1,
  317. pageSize: 100
  318. }
  319. const response = await axios.get<RackServerType[]>(`${API_BASE_URL}/big/rack/server/type/image`, { params });
  320. const ossHost = OSS_BASE_URL;
  321. return response.data.reduce((acc: ServerIconConfigs, type: RackServerType) => {
  322. acc[type.id] = {
  323. textureUrl: type.image_url ? `${ossHost}/${type.image_url}` : null,
  324. color: 0x444444
  325. };
  326. return acc;
  327. }, {});
  328. }
  329. }