api-integrations.ts 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. import { Component, OnInit, signal } from '@angular/core';
  2. import { CommonModule } from '@angular/common';
  3. import { RouterModule } from '@angular/router';
  4. import { FormsModule } from '@angular/forms';
  5. import { MatButtonModule } from '@angular/material/button';
  6. import { MatIconModule } from '@angular/material/icon';
  7. import { MatTableModule } from '@angular/material/table';
  8. import { MatInputModule } from '@angular/material/input';
  9. import { MatSelectModule } from '@angular/material/select';
  10. import { MatPaginatorModule } from '@angular/material/paginator';
  11. import { MatDialogModule, MatDialog } from '@angular/material/dialog';
  12. import { MatSortModule } from '@angular/material/sort';
  13. import { MatTabsModule } from '@angular/material/tabs';
  14. import { MatExpansionModule } from '@angular/material/expansion';
  15. import { MatSlideToggleModule } from '@angular/material/slide-toggle';
  16. import { MatDatepickerModule } from '@angular/material/datepicker';
  17. import { MatNativeDateModule } from '@angular/material/core';
  18. import { ApiDialogComponent } from './api-dialog/api-dialog';
  19. interface ApiIntegration {
  20. id: string;
  21. name: string;
  22. type: string;
  23. status: 'active' | 'inactive' | 'error';
  24. endpoint: string;
  25. authentication: string;
  26. lastTested?: string;
  27. description: string;
  28. configuration: Record<string, any>;
  29. createdBy: string;
  30. createdAt: string;
  31. updatedAt: string;
  32. }
  33. interface ApiLog {
  34. id: string;
  35. timestamp: string;
  36. integrationId: string;
  37. integrationName: string;
  38. requestMethod: string;
  39. requestUrl: string;
  40. statusCode: number;
  41. duration: number;
  42. status: 'success' | 'error';
  43. errorMessage?: string;
  44. }
  45. @Component({
  46. selector: 'app-api-integrations',
  47. standalone: true,
  48. imports: [
  49. CommonModule,
  50. RouterModule,
  51. FormsModule,
  52. MatButtonModule,
  53. MatIconModule,
  54. MatTableModule,
  55. MatInputModule,
  56. MatSelectModule,
  57. MatPaginatorModule,
  58. MatDialogModule,
  59. MatSortModule,
  60. MatTabsModule,
  61. MatExpansionModule,
  62. MatSlideToggleModule,
  63. MatDatepickerModule,
  64. MatNativeDateModule
  65. ],
  66. templateUrl: './api-integrations.html',
  67. styleUrl: './api-integrations.scss'
  68. })
  69. export class ApiIntegrations implements OnInit {
  70. // 激活的标签页
  71. activeTab = 'integrations';
  72. // API集成数据
  73. apiIntegrations = signal<ApiIntegration[]>([]);
  74. filteredIntegrations = signal<ApiIntegration[]>([]);
  75. integrationSearchTerm = '';
  76. integrationTypeFilter = '';
  77. integrationStatusFilter = '';
  78. integrationSortColumn = 'createdAt';
  79. integrationSortDirection = 'desc';
  80. integrationPageSize = 10;
  81. integrationCurrentPage = 0;
  82. // API日志数据
  83. apiLogs = signal<ApiLog[]>([]);
  84. filteredLogs = signal<ApiLog[]>([]);
  85. logSearchTerm = '';
  86. logIntegrationFilter = '';
  87. logStatusFilter = '';
  88. logStartDate: Date | null = null;
  89. logEndDate: Date | null = null;
  90. logSortColumn = 'timestamp';
  91. logSortDirection = 'desc';
  92. logPageSize = 20;
  93. logCurrentPage = 0;
  94. // 可用的筛选选项
  95. integrationTypes = ['渲染农场', '设计素材库', '客户管理', '财务系统', '项目管理', '人力资源', '其他系统'];
  96. integrationStatuses = [
  97. { value: 'active', label: '已激活' },
  98. { value: 'inactive', label: '已禁用' },
  99. { value: 'error', label: '错误' }
  100. ];
  101. logStatuses = [
  102. { value: 'success', label: '成功' },
  103. { value: 'error', label: '失败' }
  104. ];
  105. // 状态颜色映射
  106. statusColors: Record<string, string> = {
  107. 'active': '#00B42A',
  108. 'inactive': '#F53F3F',
  109. 'error': '#FFAA00'
  110. };
  111. // 状态图标映射
  112. statusIcons: Record<string, string> = {
  113. 'active': 'check_circle',
  114. 'inactive': 'cancel',
  115. 'error': 'error'
  116. };
  117. constructor(private dialog: MatDialog) {}
  118. ngOnInit(): void {
  119. this.loadApiIntegrations();
  120. this.loadApiLogs();
  121. }
  122. // 加载API集成数据
  123. loadApiIntegrations(): void {
  124. // 模拟API集成数据
  125. this.apiIntegrations.set([
  126. {
  127. id: '1',
  128. name: '渲染农场API',
  129. type: '渲染农场',
  130. status: 'active',
  131. endpoint: 'https://render-farm.example.com/api/v1',
  132. authentication: 'API Key',
  133. lastTested: '2025-09-15 10:30:00',
  134. description: '与外部渲染农场服务的集成,用于提交和管理渲染任务',
  135. configuration: {
  136. apiKey: '********',
  137. timeout: 300,
  138. retryCount: 3,
  139. priority: 'medium'
  140. },
  141. createdBy: '超级管理员',
  142. createdAt: '2025-09-01 14:20:00',
  143. updatedAt: '2025-09-10 09:15:00'
  144. },
  145. {
  146. id: '2',
  147. name: '设计素材库API',
  148. type: '设计素材库',
  149. status: 'active',
  150. endpoint: 'https://design-assets.example.com/api/v2',
  151. authentication: 'OAuth 2.0',
  152. lastTested: '2025-09-14 16:45:00',
  153. description: '与设计素材库服务的集成,用于搜索和获取设计素材',
  154. configuration: {
  155. clientId: 'design_assets_client',
  156. clientSecret: '********',
  157. scope: 'read write',
  158. tokenUrl: 'https://design-assets.example.com/oauth/token'
  159. },
  160. createdBy: '超级管理员',
  161. createdAt: '2025-08-25 11:30:00',
  162. updatedAt: '2025-09-05 15:20:00'
  163. },
  164. {
  165. id: '3',
  166. name: '客户管理系统API',
  167. type: '客户管理',
  168. status: 'error',
  169. endpoint: 'https://crm.example.com/api',
  170. authentication: 'API Key',
  171. lastTested: '2025-09-15 08:10:00',
  172. description: '与客户管理系统的集成,用于同步客户信息和订单数据',
  173. configuration: {
  174. apiKey: '********',
  175. syncInterval: 'daily',
  176. syncFields: ['name', 'email', 'phone', 'address']
  177. },
  178. createdBy: '超级管理员',
  179. createdAt: '2025-08-20 09:45:00',
  180. updatedAt: '2025-09-12 14:30:00'
  181. },
  182. {
  183. id: '4',
  184. name: '财务系统API',
  185. type: '财务系统',
  186. status: 'inactive',
  187. endpoint: 'https://finance.example.com/api/v3',
  188. authentication: 'OAuth 2.0',
  189. lastTested: '2025-09-10 11:20:00',
  190. description: '与财务系统的集成,用于同步项目财务数据和生成报表',
  191. configuration: {
  192. clientId: 'finance_api_client',
  193. clientSecret: '********',
  194. scope: 'read',
  195. tokenUrl: 'https://finance.example.com/oauth/token'
  196. },
  197. createdBy: '超级管理员',
  198. createdAt: '2025-08-15 16:00:00',
  199. updatedAt: '2025-09-01 10:15:00'
  200. },
  201. {
  202. id: '5',
  203. name: '项目管理工具API',
  204. type: '项目管理',
  205. status: 'active',
  206. endpoint: 'https://project-tool.example.com/api',
  207. authentication: 'Webhook',
  208. lastTested: '2025-09-15 13:40:00',
  209. description: '与项目管理工具的集成,用于创建和更新项目任务',
  210. configuration: {
  211. webhookUrl: 'https://example.com/webhooks/project-updates',
  212. secretToken: '********',
  213. eventTypes: ['task_created', 'task_updated', 'task_completed']
  214. },
  215. createdBy: '超级管理员',
  216. createdAt: '2025-08-10 14:50:00',
  217. updatedAt: '2025-09-08 16:25:00'
  218. }
  219. ]);
  220. this.filteredIntegrations = this.apiIntegrations;
  221. this.applyIntegrationFilters();
  222. }
  223. // 加载API日志数据
  224. loadApiLogs(): void {
  225. // 模拟API日志数据
  226. const mockLogs: ApiLog[] = [
  227. {
  228. id: '1',
  229. timestamp: '2025-09-15 14:30:25',
  230. integrationId: '1',
  231. integrationName: '渲染农场API',
  232. requestMethod: 'POST',
  233. requestUrl: '/render-jobs',
  234. statusCode: 200,
  235. duration: 1250,
  236. status: 'success'
  237. },
  238. {
  239. id: '2',
  240. timestamp: '2025-09-15 14:25:10',
  241. integrationId: '2',
  242. integrationName: '设计素材库API',
  243. requestMethod: 'GET',
  244. requestUrl: '/assets?category=3d-models',
  245. statusCode: 200,
  246. duration: 850,
  247. status: 'success'
  248. },
  249. {
  250. id: '3',
  251. timestamp: '2025-09-15 14:20:45',
  252. integrationId: '3',
  253. integrationName: '客户管理系统API',
  254. requestMethod: 'POST',
  255. requestUrl: '/customers/sync',
  256. statusCode: 401,
  257. duration: 450,
  258. status: 'error',
  259. errorMessage: '认证失败:无效的API密钥'
  260. },
  261. {
  262. id: '4',
  263. timestamp: '2025-09-15 14:15:30',
  264. integrationId: '1',
  265. integrationName: '渲染农场API',
  266. requestMethod: 'GET',
  267. requestUrl: '/render-jobs/12345/status',
  268. statusCode: 200,
  269. duration: 620,
  270. status: 'success'
  271. },
  272. {
  273. id: '5',
  274. timestamp: '2025-09-15 14:10:20',
  275. integrationId: '5',
  276. integrationName: '项目管理工具API',
  277. requestMethod: 'POST',
  278. requestUrl: '/webhooks/task-created',
  279. statusCode: 200,
  280. duration: 380,
  281. status: 'success'
  282. },
  283. {
  284. id: '6',
  285. timestamp: '2025-09-15 14:05:15',
  286. integrationId: '2',
  287. integrationName: '设计素材库API',
  288. requestMethod: 'POST',
  289. requestUrl: '/assets/upload',
  290. statusCode: 201,
  291. duration: 2350,
  292. status: 'success'
  293. },
  294. {
  295. id: '7',
  296. timestamp: '2025-09-15 14:00:55',
  297. integrationId: '3',
  298. integrationName: '客户管理系统API',
  299. requestMethod: 'GET',
  300. requestUrl: '/customers?updatedSince=2025-09-01',
  301. statusCode: 401,
  302. duration: 320,
  303. status: 'error',
  304. errorMessage: '认证失败:无效的API密钥'
  305. },
  306. {
  307. id: '8',
  308. timestamp: '2025-09-15 13:55:30',
  309. integrationId: '1',
  310. integrationName: '渲染农场API',
  311. requestMethod: 'PUT',
  312. requestUrl: '/render-jobs/12345/cancel',
  313. statusCode: 200,
  314. duration: 580,
  315. status: 'success'
  316. }
  317. ];
  318. // 生成更多日志数据以模拟大量记录
  319. const generatedLogs: ApiLog[] = [];
  320. let idCounter = 9;
  321. // 复制模拟数据多次以创建大量日志
  322. for (let i = 0; i < 3; i++) {
  323. mockLogs.forEach(log => {
  324. // 为每条日志创建一个变体,更改时间戳
  325. const logDate = new Date(log.timestamp);
  326. logDate.setHours(logDate.getHours() - i * 2);
  327. logDate.setMinutes(Math.floor(Math.random() * 60));
  328. logDate.setSeconds(Math.floor(Math.random() * 60));
  329. generatedLogs.push({
  330. ...log,
  331. id: idCounter.toString(),
  332. timestamp: logDate.toLocaleString('zh-CN', {
  333. year: 'numeric',
  334. month: '2-digit',
  335. day: '2-digit',
  336. hour: '2-digit',
  337. minute: '2-digit',
  338. second: '2-digit'
  339. }).replace(/\//g, '-')
  340. });
  341. idCounter++;
  342. });
  343. }
  344. // 合并原始数据和生成的数据
  345. this.apiLogs.set([...mockLogs, ...generatedLogs].sort((a, b) =>
  346. new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
  347. ));
  348. this.filteredLogs = this.apiLogs;
  349. this.applyLogFilters();
  350. }
  351. // 标签页切换
  352. switchTab(tab: string): void {
  353. this.activeTab = tab;
  354. }
  355. // API集成筛选方法
  356. applyIntegrationFilters(): void {
  357. let result = [...this.apiIntegrations()];
  358. // 搜索词筛选
  359. if (this.integrationSearchTerm) {
  360. const term = this.integrationSearchTerm.toLowerCase();
  361. result = result.filter(integration =>
  362. integration.name.toLowerCase().includes(term) ||
  363. integration.description.toLowerCase().includes(term) ||
  364. integration.endpoint.toLowerCase().includes(term)
  365. );
  366. }
  367. // 类型筛选
  368. if (this.integrationTypeFilter) {
  369. result = result.filter(integration => integration.type === this.integrationTypeFilter);
  370. }
  371. // 状态筛选
  372. if (this.integrationStatusFilter) {
  373. result = result.filter(integration => integration.status === this.integrationStatusFilter);
  374. }
  375. // 排序
  376. result.sort((a, b) => {
  377. if (this.integrationSortColumn === 'createdAt' || this.integrationSortColumn === 'updatedAt' || this.integrationSortColumn === 'lastTested') {
  378. return this.integrationSortDirection === 'asc'
  379. ? new Date(a[this.integrationSortColumn] || 0).getTime() - new Date(b[this.integrationSortColumn] || 0).getTime()
  380. : new Date(b[this.integrationSortColumn] || 0).getTime() - new Date(a[this.integrationSortColumn] || 0).getTime();
  381. } else {
  382. const valueA = a[this.integrationSortColumn as keyof ApiIntegration]?.toString().toLowerCase() || '';
  383. const valueB = b[this.integrationSortColumn as keyof ApiIntegration]?.toString().toLowerCase() || '';
  384. return this.integrationSortDirection === 'asc'
  385. ? valueA.localeCompare(valueB)
  386. : valueB.localeCompare(valueA);
  387. }
  388. });
  389. this.filteredIntegrations.set(result);
  390. this.integrationCurrentPage = 0; // 重置到第一页
  391. }
  392. // API日志筛选方法
  393. applyLogFilters(): void {
  394. let result = [...this.apiLogs()];
  395. // 搜索词筛选
  396. if (this.logSearchTerm) {
  397. const term = this.logSearchTerm.toLowerCase();
  398. result = result.filter(log =>
  399. log.integrationName.toLowerCase().includes(term) ||
  400. log.requestUrl.toLowerCase().includes(term) ||
  401. (log.errorMessage && log.errorMessage.toLowerCase().includes(term))
  402. );
  403. }
  404. // 集成筛选
  405. if (this.logIntegrationFilter) {
  406. result = result.filter(log => log.integrationId === this.logIntegrationFilter);
  407. }
  408. // 状态筛选
  409. if (this.logStatusFilter) {
  410. result = result.filter(log => log.status === this.logStatusFilter);
  411. }
  412. // 日期范围筛选
  413. if (this.logStartDate) {
  414. const startDateTime = new Date(this.logStartDate).setHours(0, 0, 0, 0);
  415. result = result.filter(log => new Date(log.timestamp).getTime() >= startDateTime);
  416. }
  417. if (this.logEndDate) {
  418. const endDateTime = new Date(this.logEndDate).setHours(23, 59, 59, 999);
  419. result = result.filter(log => new Date(log.timestamp).getTime() <= endDateTime);
  420. }
  421. // 排序
  422. result.sort((a, b) => {
  423. if (this.logSortColumn === 'timestamp') {
  424. return this.logSortDirection === 'asc'
  425. ? new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
  426. : new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime();
  427. } else if (this.logSortColumn === 'duration' || this.logSortColumn === 'statusCode') {
  428. // 安全地获取数字值
  429. const valueA = Number(a[this.logSortColumn as keyof ApiLog]) || 0;
  430. const valueB = Number(b[this.logSortColumn as keyof ApiLog]) || 0;
  431. return this.logSortDirection === 'asc'
  432. ? valueA - valueB
  433. : valueB - valueA;
  434. } else {
  435. const valueA = a[this.logSortColumn as keyof ApiLog]?.toString().toLowerCase() || '';
  436. const valueB = b[this.logSortColumn as keyof ApiLog]?.toString().toLowerCase() || '';
  437. return this.logSortDirection === 'asc'
  438. ? valueA.localeCompare(valueB)
  439. : valueB.localeCompare(valueA);
  440. }
  441. });
  442. this.filteredLogs.set(result);
  443. this.logCurrentPage = 0; // 重置到第一页
  444. }
  445. // 集成相关方法
  446. onIntegrationSearch(): void {
  447. this.applyIntegrationFilters();
  448. }
  449. onIntegrationFilterChange(): void {
  450. this.applyIntegrationFilters();
  451. }
  452. onIntegrationSort(column: string): void {
  453. if (this.integrationSortColumn === column) {
  454. this.integrationSortDirection = this.integrationSortDirection === 'asc' ? 'desc' : 'asc';
  455. } else {
  456. this.integrationSortColumn = column;
  457. this.integrationSortDirection = 'asc';
  458. }
  459. this.applyIntegrationFilters();
  460. }
  461. // 日志相关方法
  462. onLogSearch(): void {
  463. this.applyLogFilters();
  464. }
  465. onLogFilterChange(): void {
  466. this.applyLogFilters();
  467. }
  468. onLogSort(column: string): void {
  469. if (this.logSortColumn === column) {
  470. this.logSortDirection = this.logSortDirection === 'asc' ? 'desc' : 'asc';
  471. } else {
  472. this.logSortColumn = column;
  473. this.logSortDirection = 'asc';
  474. }
  475. this.applyLogFilters();
  476. }
  477. // 打开API对话框
  478. openApiDialog(integration?: ApiIntegration): void {
  479. const dialogRef = this.dialog.open(ApiDialogComponent, {
  480. width: '600px',
  481. data: integration ? { ...integration } : {
  482. id: '',
  483. name: '',
  484. type: '',
  485. endpoint: '',
  486. authentication: 'none',
  487. description: '',
  488. configuration: {},
  489. status: 'inactive',
  490. lastTested: '',
  491. createdBy: '超级管理员',
  492. createdAt: new Date().toLocaleString('zh-CN'),
  493. updatedAt: new Date().toLocaleString('zh-CN')
  494. }
  495. });
  496. dialogRef.afterClosed().subscribe(result => {
  497. if (result) {
  498. if (result.id) {
  499. // 更新集成
  500. this.updateIntegration(result);
  501. } else {
  502. // 创建新集成
  503. this.createIntegration(result);
  504. }
  505. }
  506. });
  507. }
  508. // 集成操作方法
  509. createIntegration(integrationData: Omit<ApiIntegration, 'id'>): void {
  510. const newIntegration: ApiIntegration = {
  511. ...integrationData,
  512. id: (this.apiIntegrations().length + 1).toString(),
  513. createdAt: new Date().toLocaleString('zh-CN'),
  514. updatedAt: new Date().toLocaleString('zh-CN')
  515. };
  516. this.apiIntegrations.set([newIntegration, ...this.apiIntegrations()]);
  517. this.applyIntegrationFilters();
  518. }
  519. updateIntegration(updatedIntegration: ApiIntegration): void {
  520. this.apiIntegrations.set(this.apiIntegrations().map(integration =>
  521. integration.id === updatedIntegration.id ? updatedIntegration : integration
  522. ));
  523. this.applyIntegrationFilters();
  524. }
  525. deleteIntegration(id: string): void {
  526. if (confirm('确定要删除这个API集成吗?')) {
  527. this.apiIntegrations.set(this.apiIntegrations().filter(integration => integration.id !== id));
  528. this.applyIntegrationFilters();
  529. }
  530. }
  531. toggleIntegrationStatus(id: string, status: 'active' | 'inactive'): void {
  532. this.apiIntegrations.set(this.apiIntegrations().map(integration =>
  533. integration.id === id ? { ...integration, status, updatedAt: new Date().toLocaleString('zh-CN') } : integration
  534. ));
  535. this.applyIntegrationFilters();
  536. }
  537. testIntegration(id: string): void {
  538. // 模拟测试操作
  539. alert(`正在测试API集成...\n测试完成!`);
  540. this.apiIntegrations.set(this.apiIntegrations().map(integration =>
  541. integration.id === id ? { ...integration, lastTested: new Date().toLocaleString('zh-CN') } : integration
  542. ));
  543. this.applyIntegrationFilters();
  544. }
  545. // 分页相关方法
  546. get paginatedIntegrations(): ApiIntegration[] {
  547. const startIndex = this.integrationCurrentPage * this.integrationPageSize;
  548. return this.filteredIntegrations().slice(startIndex, startIndex + this.integrationPageSize);
  549. }
  550. get totalIntegrationPages(): number {
  551. return Math.ceil(this.filteredIntegrations().length / this.integrationPageSize);
  552. }
  553. onIntegrationPageChange(page: number): void {
  554. this.integrationCurrentPage = page;
  555. }
  556. get paginatedLogs(): ApiLog[] {
  557. const startIndex = this.logCurrentPage * this.logPageSize;
  558. return this.filteredLogs().slice(startIndex, startIndex + this.logPageSize);
  559. }
  560. get totalLogPages(): number {
  561. return Math.ceil(this.filteredLogs().length / this.logPageSize);
  562. }
  563. onLogPageChange(page: number): void {
  564. this.logCurrentPage = page;
  565. }
  566. // 格式化日期显示
  567. formatDate(dateString: string): string {
  568. const date = new Date(dateString);
  569. return date.toLocaleString('zh-CN', {
  570. year: 'numeric',
  571. month: '2-digit',
  572. day: '2-digit',
  573. hour: '2-digit',
  574. minute: '2-digit',
  575. second: '2-digit'
  576. });
  577. }
  578. // 获取状态文本
  579. getStatusText(status: string): string {
  580. const statusMap = {
  581. 'active': '已激活',
  582. 'inactive': '已禁用',
  583. 'error': '错误'
  584. };
  585. return statusMap[status as keyof typeof statusMap] || status;
  586. }
  587. // 导出日志
  588. exportLogs(): void {
  589. // 模拟导出功能
  590. alert(`已导出 ${this.filteredLogs().length} 条API日志记录`);
  591. }
  592. // 清除筛选条件
  593. clearIntegrationFilters(): void {
  594. this.integrationSearchTerm = '';
  595. this.integrationTypeFilter = '';
  596. this.integrationStatusFilter = '';
  597. this.applyIntegrationFilters();
  598. }
  599. clearLogFilters(): void {
  600. this.logSearchTerm = '';
  601. this.logIntegrationFilter = '';
  602. this.logStatusFilter = '';
  603. this.logStartDate = null;
  604. this.logEndDate = null;
  605. this.applyLogFilters();
  606. }
  607. // 获取集成ID选项
  608. get integrationIdOptions(): { id: string; name: string }[] {
  609. return this.apiIntegrations().map(integration => ({
  610. id: integration.id,
  611. name: integration.name
  612. }));
  613. }
  614. // 获取页码数组
  615. getPageNumbers(): number[] {
  616. const pages = [];
  617. const totalPages = this.totalIntegrationPages;
  618. const currentPage = this.integrationCurrentPage;
  619. const maxVisiblePages = 5;
  620. let startPage = Math.max(0, currentPage - Math.floor(maxVisiblePages / 2));
  621. let endPage = startPage + maxVisiblePages - 1;
  622. if (endPage >= totalPages) {
  623. endPage = totalPages - 1;
  624. startPage = Math.max(0, endPage - maxVisiblePages + 1);
  625. }
  626. for (let i = startPage; i <= endPage; i++) {
  627. pages.push(i);
  628. }
  629. return pages;
  630. }
  631. // 计算平均响应时间
  632. calculateAverageDuration(): number {
  633. if (this.apiLogs().length === 0) return 0;
  634. const totalDuration = this.apiLogs().reduce((sum, log) => sum + log.duration, 0);
  635. return Math.round(totalDuration / this.apiLogs().length);
  636. }
  637. // 封装Math对象的方法
  638. mathMin(a: number, b: number): number {
  639. return Math.min(a, b);
  640. }
  641. // 封装Object对象的方法
  642. objectEntries(obj: Record<string, any>): [string, any][] {
  643. return Object.entries(obj);
  644. }
  645. // 计算活跃集成数量
  646. get activeIntegrationsCount(): number {
  647. return this.apiIntegrations().filter(i => i.status === 'active').length;
  648. }
  649. // 计算禁用集成数量
  650. get inactiveIntegrationsCount(): number {
  651. return this.apiIntegrations().filter(i => i.status === 'inactive').length;
  652. }
  653. // 计算错误集成数量
  654. get errorIntegrationsCount(): number {
  655. return this.apiIntegrations().filter(i => i.status === 'error').length;
  656. }
  657. // 计算成功日志数量
  658. get successLogsCount(): number {
  659. return this.apiLogs().filter(l => l.status === 'success').length;
  660. }
  661. // 计算失败日志数量
  662. get errorLogsCount(): number {
  663. return this.apiLogs().filter(l => l.status === 'error').length;
  664. }
  665. // 计算总API日志数量
  666. get totalApiLogsCount(): number {
  667. return this.apiLogs().length;
  668. }
  669. // 计算平均响应时间(计算属性版本)
  670. get averageResponseTime(): number {
  671. return this.calculateAverageDuration();
  672. }
  673. }