VisionModelSelector.tsx 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import React, { useState, useEffect } from 'react';
  2. import { Eye } from 'lucide-react';
  3. import { settingsService } from '../services/settingsService';
  4. import { useLanguage } from '../contexts/LanguageContext';
  5. interface VisionModel {
  6. id: string;
  7. name: string;
  8. modelId: string;
  9. }
  10. const VisionModelSelector: React.FC = () => {
  11. const { t } = useLanguage();
  12. const [visionModels, setVisionModels] = useState<VisionModel[]>([]);
  13. const [selectedModelId, setSelectedModelId] = useState<string>('');
  14. const [loading, setLoading] = useState(true);
  15. const [error, setError] = useState<string>('');
  16. useEffect(() => {
  17. loadData();
  18. }, []);
  19. const loadData = async () => {
  20. try {
  21. setLoading(true);
  22. setError('');
  23. const [models, current] = await Promise.all([
  24. settingsService.getVisionModels(),
  25. settingsService.getVisionModel()
  26. ]);
  27. console.log('Vision models loaded:', models);
  28. console.log('Current vision model:', current);
  29. setVisionModels(models || []);
  30. setSelectedModelId(current?.visionModelId || '');
  31. } catch (error) {
  32. console.error(t('loadVisionModelFailed'), error);
  33. setError(t('loadFailed'));
  34. } finally {
  35. setLoading(false);
  36. }
  37. };
  38. const handleChange = async (modelId: string) => {
  39. try {
  40. setSelectedModelId(modelId);
  41. if (modelId) {
  42. await settingsService.updateVisionModel(modelId);
  43. }
  44. } catch (error) {
  45. console.error(t('saveVisionModelFailed'), error);
  46. }
  47. };
  48. return (
  49. <div className="bg-white p-4 rounded-xl border border-slate-200 shadow-sm">
  50. <div className="flex items-center gap-2 mb-4 text-slate-800 font-semibold border-b border-slate-100 pb-2">
  51. <Eye className="w-4 h-4 text-purple-600" />
  52. {t('visionModelSettings')}
  53. </div>
  54. <div>
  55. <label className="block text-xs font-medium text-slate-500 mb-1.5">
  56. {t('defaultVisionModel')}
  57. </label>
  58. {error ? (
  59. <div className="text-red-500 text-sm p-2 bg-red-50 rounded">
  60. {error}
  61. </div>
  62. ) : (
  63. <select
  64. value={selectedModelId}
  65. onChange={(e) => handleChange(e.target.value)}
  66. disabled={loading}
  67. className="w-full text-sm bg-slate-50 border border-slate-200 rounded-lg px-3 py-2 text-slate-700 focus:outline-none focus:border-blue-500"
  68. >
  69. <option value="">
  70. {loading ? t('loading') : visionModels.length === 0 ? t('noVisionModels') : `--- ${t('selectVisionModel')} ---`}
  71. </option>
  72. {visionModels.map(model => (
  73. <option key={model.id} value={model.id}>
  74. {model.name} ({model.modelId})
  75. </option>
  76. ))}
  77. </select>
  78. )}
  79. <p className="text-[10px] text-slate-400 mt-1">
  80. {t('visionModelHelp')}
  81. </p>
  82. </div>
  83. </div>
  84. );
  85. };
  86. export default VisionModelSelector;