faqApi.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import { apiUrl, getAgentHeaders } from "@/lib/config";
  2. // FAQ 摘要信息
  3. export interface FAQSummary {
  4. id: number;
  5. question: string; // 问题
  6. answer: string; // 答案
  7. keywords: string; // 关键词(用于搜索)
  8. created_at: string; // 创建时间
  9. updated_at: string; // 更新时间
  10. }
  11. // 创建 FAQ 请求
  12. export interface CreateFAQRequest {
  13. question: string; // 问题(必需)
  14. answer: string; // 答案(必需)
  15. keywords?: string; // 关键词(可选)
  16. }
  17. // 更新 FAQ 请求
  18. export interface UpdateFAQRequest {
  19. question?: string; // 问题(可选)
  20. answer?: string; // 答案(可选)
  21. keywords?: string; // 关键词(可选)
  22. }
  23. // 获取 FAQ 列表(支持关键词搜索)
  24. // query 格式:关键词之间用 % 分隔,例如 "openai%api%调用"
  25. export async function fetchFAQs(query?: string): Promise<FAQSummary[]> {
  26. // 使用相对路径构建 URL,支持查询参数
  27. let url = apiUrl("/faqs");
  28. if (query) {
  29. url += `?query=${encodeURIComponent(query)}`;
  30. }
  31. const res = await fetch(url, {
  32. cache: "no-store",
  33. headers: getAgentHeaders(),
  34. });
  35. if (!res.ok) {
  36. const error = await res.json().catch(() => ({}));
  37. throw new Error((error as { error?: string }).error || "获取 FAQ 列表失败");
  38. }
  39. const data = await res.json();
  40. return data.faqs || [];
  41. }
  42. // 获取 FAQ 详情
  43. export async function fetchFAQ(id: number): Promise<FAQSummary> {
  44. const res = await fetch(apiUrl(`/faqs/${id}`), {
  45. cache: "no-store",
  46. headers: getAgentHeaders(),
  47. });
  48. if (!res.ok) {
  49. if (res.status === 404) {
  50. throw new Error("FAQ 不存在");
  51. }
  52. throw new Error("获取 FAQ 详情失败");
  53. }
  54. return res.json();
  55. }
  56. // 创建 FAQ
  57. export async function createFAQ(data: CreateFAQRequest): Promise<FAQSummary> {
  58. const res = await fetch(apiUrl("/faqs"), {
  59. method: "POST",
  60. headers: { "Content-Type": "application/json", ...getAgentHeaders() },
  61. body: JSON.stringify(data),
  62. });
  63. if (!res.ok) {
  64. const error = await res.json().catch(() => ({}));
  65. throw new Error(error.error || "创建 FAQ 失败");
  66. }
  67. return res.json();
  68. }
  69. // 更新 FAQ
  70. export async function updateFAQ(
  71. id: number,
  72. data: UpdateFAQRequest
  73. ): Promise<FAQSummary> {
  74. const res = await fetch(apiUrl(`/faqs/${id}`), {
  75. method: "PUT",
  76. headers: { "Content-Type": "application/json", ...getAgentHeaders() },
  77. body: JSON.stringify(data),
  78. });
  79. if (!res.ok) {
  80. const error = await res.json().catch(() => ({}));
  81. if (res.status === 404) {
  82. throw new Error("FAQ 不存在");
  83. }
  84. throw new Error(error.error || "更新 FAQ 失败");
  85. }
  86. return res.json();
  87. }
  88. export interface FAQQuickResult {
  89. id: number;
  90. question: string;
  91. answer: string;
  92. keywords: string;
  93. }
  94. /** FAQ 快速搜索(聊天输入框 `/` 触发) */
  95. export async function quickSearchFAQs(
  96. q: string,
  97. limit: number = 10
  98. ): Promise<FAQQuickResult[]> {
  99. const url = apiUrl(
  100. `/faqs-search?q=${encodeURIComponent(q)}&limit=${limit}`
  101. );
  102. const res = await fetch(url, {
  103. cache: "no-store",
  104. headers: getAgentHeaders(),
  105. });
  106. if (!res.ok) {
  107. const error = await res.json().catch(() => ({}));
  108. throw new Error(
  109. (error as { error?: string }).error || "FAQ 搜索失败"
  110. );
  111. }
  112. const data = await res.json();
  113. return data.faqs || [];
  114. }
  115. // 删除 FAQ
  116. export async function deleteFAQ(id: number): Promise<void> {
  117. const res = await fetch(apiUrl(`/faqs/${id}`), {
  118. method: "DELETE",
  119. headers: getAgentHeaders(),
  120. });
  121. if (!res.ok) {
  122. const error = await res.json().catch(() => ({}));
  123. if (res.status === 404) {
  124. throw new Error("FAQ 不存在");
  125. }
  126. throw new Error(error.error || "删除 FAQ 失败");
  127. }
  128. }