docs.js 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. /* Swagger UI uses the same origin as this page; no token or specification is sent to third parties. */
  2. 'use strict';
  3. const apiBase = `${window.location.origin}/api/mini/v1`;
  4. const statusElement = document.getElementById('service-status');
  5. const refreshButton = document.getElementById('refresh-status');
  6. document.getElementById('base-url').textContent = apiBase;
  7. async function refreshStatus() {
  8. refreshButton.disabled = true;
  9. statusElement.textContent = '正在检查服务状态…';
  10. const controller = new AbortController();
  11. const timeout = setTimeout(() => controller.abort(), 10000);
  12. try {
  13. const response = await fetch(`${apiBase}/config`, {
  14. cache: 'no-store', credentials: 'omit', signal: controller.signal,
  15. });
  16. const body = await response.json();
  17. if (!response.ok || body.code !== 0) throw new Error('服务状态读取失败');
  18. const capabilities = body.data.capabilities;
  19. statusElement.textContent = `服务可访问 · 微信登录${capabilities.wechat_login ? '已配置' : '未配置'} · 支付${capabilities.payment ? '已开放' : '未开放'}`;
  20. } catch {
  21. statusElement.textContent = '服务状态读取失败,请检查后端服务和来源白名单';
  22. } finally {
  23. clearTimeout(timeout);
  24. refreshButton.disabled = false;
  25. }
  26. }
  27. async function loadDocumentation() {
  28. try {
  29. if (typeof SwaggerUIBundle !== 'function') throw new Error('Swagger UI 静态资源加载失败');
  30. const response = await fetch('./openapi.json', { cache: 'no-store', credentials: 'omit' });
  31. if (!response.ok) throw new Error(`OpenAPI 文件加载失败(HTTP ${response.status})`);
  32. const specification = await response.json();
  33. specification.servers = [{ url: apiBase, description: '当前服务' }];
  34. const methods = new Set(['get', 'head', 'post', 'put', 'patch', 'delete', 'options', 'trace']);
  35. const count = Object.values(specification.paths)
  36. .reduce((total, item) => total + Object.keys(item).filter(key => methods.has(key)).length, 0);
  37. document.getElementById('operation-count').textContent = `${count} 个接口操作(含 HEAD)`;
  38. window.ui = SwaggerUIBundle({
  39. spec: specification,
  40. dom_id: '#swagger-ui',
  41. deepLinking: true,
  42. filter: true,
  43. docExpansion: 'list',
  44. defaultModelsExpandDepth: -1,
  45. displayRequestDuration: true,
  46. persistAuthorization: false,
  47. withCredentials: false,
  48. validatorUrl: null,
  49. queryConfigEnabled: false,
  50. presets: [SwaggerUIBundle.presets.apis],
  51. layout: 'BaseLayout',
  52. requestInterceptor(request) {
  53. const target = new URL(request.url, window.location.href);
  54. if (target.origin !== window.location.origin || !target.pathname.startsWith('/api/mini/v1/')) {
  55. throw new Error('此文档页面仅允许调用当前服务的小程序接口');
  56. }
  57. request.credentials = 'omit';
  58. return request;
  59. },
  60. });
  61. } catch (error) {
  62. const element = document.getElementById('load-error');
  63. element.textContent = `${error.message}。请刷新页面;也可以下载 OpenAPI 导入 Apifox。`;
  64. element.hidden = false;
  65. }
  66. }
  67. refreshButton.addEventListener('click', refreshStatus);
  68. refreshStatus();
  69. loadDocumentation();