ChatModeSelector.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. "use client";
  2. import { useState, useEffect } from "react";
  3. import { Button } from "@/components/ui/button";
  4. import { Card } from "@/components/ui/card";
  5. import { fetchPublicAIModels, type AIConfig } from "@/features/agent/services/aiConfigApi";
  6. interface ChatModeSelectorProps {
  7. onSelect: (mode: "human" | "ai", aiConfigId?: number) => void;
  8. loading?: boolean;
  9. }
  10. export function ChatModeSelector({ onSelect, loading }: ChatModeSelectorProps) {
  11. const [aiModels, setAiModels] = useState<AIConfig[]>([]);
  12. const [loadingModels, setLoadingModels] = useState(true);
  13. const [selectedModel, setSelectedModel] = useState<number | null>(null);
  14. // 加载开放的 AI 模型列表
  15. useEffect(() => {
  16. async function loadModels() {
  17. try {
  18. const models = await fetchPublicAIModels("text");
  19. setAiModels(models);
  20. // 如果有模型,默认选择第一个
  21. if (models.length > 0) {
  22. setSelectedModel(models[0].id);
  23. }
  24. } catch (error) {
  25. console.error("加载模型列表失败:", error);
  26. } finally {
  27. setLoadingModels(false);
  28. }
  29. }
  30. loadModels();
  31. }, []);
  32. const handleSelectHuman = () => {
  33. onSelect("human");
  34. };
  35. const handleSelectAI = () => {
  36. if (selectedModel) {
  37. onSelect("ai", selectedModel);
  38. } else if (aiModels.length > 0) {
  39. // 如果没有选择,使用第一个模型
  40. onSelect("ai", aiModels[0].id);
  41. }
  42. };
  43. return (
  44. <div className="flex flex-col items-center justify-center min-h-screen bg-background p-4">
  45. <div className="w-full max-w-2xl">
  46. <h1 className="text-3xl font-bold text-center mb-2 text-gray-800">
  47. 欢迎使用客服系统
  48. </h1>
  49. <p className="text-center text-gray-600 mb-8">
  50. 请选择您需要的服务方式
  51. </p>
  52. <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
  53. {/* 人工客服选项 */}
  54. <Card className="p-6 cursor-pointer hover:shadow-lg transition-shadow border-2 hover:border-primary">
  55. <div className="flex flex-col items-center text-center">
  56. <div className="w-16 h-16 rounded-full bg-blue-100 flex items-center justify-center mb-4">
  57. <svg
  58. className="w-8 h-8 text-blue-600"
  59. fill="none"
  60. stroke="currentColor"
  61. viewBox="0 0 24 24"
  62. >
  63. <path
  64. strokeLinecap="round"
  65. strokeLinejoin="round"
  66. strokeWidth={2}
  67. d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
  68. />
  69. </svg>
  70. </div>
  71. <h3 className="text-xl font-semibold mb-2">人工客服</h3>
  72. <p className="text-sm text-gray-600 mb-4">
  73. 由专业客服人员为您提供一对一服务
  74. </p>
  75. <Button
  76. onClick={handleSelectHuman}
  77. disabled={loading}
  78. className="w-full"
  79. >
  80. {loading ? "连接中..." : "选择人工客服"}
  81. </Button>
  82. </div>
  83. </Card>
  84. {/* AI 客服选项 */}
  85. <Card className="p-6 cursor-pointer hover:shadow-lg transition-shadow border-2 hover:border-primary">
  86. <div className="flex flex-col items-center text-center">
  87. <div className="w-16 h-16 rounded-full bg-purple-100 flex items-center justify-center mb-4">
  88. <svg
  89. className="w-8 h-8 text-purple-600"
  90. fill="none"
  91. stroke="currentColor"
  92. viewBox="0 0 24 24"
  93. >
  94. <path
  95. strokeLinecap="round"
  96. strokeLinejoin="round"
  97. strokeWidth={2}
  98. d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"
  99. />
  100. </svg>
  101. </div>
  102. <h3 className="text-xl font-semibold mb-2">AI 客服</h3>
  103. <p className="text-sm text-gray-600 mb-4">
  104. 智能 AI 助手,24 小时在线为您服务
  105. </p>
  106. {loadingModels ? (
  107. <div className="w-full py-2 text-sm text-gray-500">
  108. 加载模型中...
  109. </div>
  110. ) : aiModels.length === 0 ? (
  111. <div className="w-full py-2 text-sm text-red-500">
  112. 暂无可用的 AI 模型
  113. </div>
  114. ) : (
  115. <>
  116. {/* 模型选择下拉框 */}
  117. <select
  118. value={selectedModel || ""}
  119. onChange={(e) => setSelectedModel(Number(e.target.value))}
  120. className="w-full mb-4 px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-primary"
  121. disabled={loading}
  122. >
  123. {aiModels.map((model) => (
  124. <option key={model.id} value={model.id}>
  125. {model.provider} - {model.model}
  126. {model.description ? ` (${model.description})` : ""}
  127. </option>
  128. ))}
  129. </select>
  130. <Button
  131. onClick={handleSelectAI}
  132. disabled={loading || !selectedModel}
  133. variant="default"
  134. className="w-full"
  135. >
  136. {loading ? "连接中..." : "选择 AI 客服"}
  137. </Button>
  138. </>
  139. )}
  140. </div>
  141. </Card>
  142. </div>
  143. </div>
  144. </div>
  145. );
  146. }