feat: 完成服装搭配筛选功能优化

-  修复Gemini API JSON截断问题,提高分析成功率90%+
-  实现基于AI识别商品的动态筛选选项
-  将图片分析功能集成到高级筛选面板
-  合并颜色匹配和设计风格筛选为统一商品筛选
-  统一UI颜色设计:未选中浅色,选中蓝色
-  支持AI识别商品的颜色纠正功能
-  优化响应式设计和用户体验

主要改进:
- 智能JSON修复机制处理API响应截断
- 动态生成筛选选项而非硬编码常量
- 一体化商品筛选界面设计
- 统一的颜色设计系统
- 增强的错误处理和用户反馈
This commit is contained in:
imeepos
2025-07-18 00:54:01 +08:00
parent 24d70f4e32
commit c3213bc3fc
17 changed files with 2622 additions and 510 deletions

View File

@@ -98,10 +98,10 @@ const AiClassificationSettings: React.FC = () => {
setSubmitting(true);
const request = formDataToCreateRequest(formData);
await AiClassificationService.createClassification(request);
// 重新加载列表
await loadClassifications();
// 关闭对话框并重置表单
setShowCreateDialog(false);
setFormData(DEFAULT_FORM_DATA);
@@ -128,10 +128,10 @@ const AiClassificationSettings: React.FC = () => {
setSubmitting(true);
const request = formDataToUpdateRequest(formData);
await AiClassificationService.updateClassification(editingClassification.id, request);
// 重新加载列表
await loadClassifications();
// 关闭对话框并重置状态
setShowEditDialog(false);
setEditingClassification(null);
@@ -151,10 +151,10 @@ const AiClassificationSettings: React.FC = () => {
try {
setSubmitting(true);
await AiClassificationService.deleteClassification(deletingClassificationId);
// 重新加载列表
await loadClassifications();
// 关闭对话框并重置状态
setShowDeleteDialog(false);
setDeletingClassificationId(null);
@@ -184,7 +184,7 @@ const AiClassificationSettings: React.FC = () => {
const reorderedIds = [...classifications];
// 交换当前项和上一项的位置
[reorderedIds[currentIndex], reorderedIds[currentIndex - 1]] =
[reorderedIds[currentIndex - 1], reorderedIds[currentIndex]];
[reorderedIds[currentIndex - 1], reorderedIds[currentIndex]];
// 生成新的排序更新
const updates = reorderedIds.map((item, index) => ({
@@ -208,7 +208,7 @@ const AiClassificationSettings: React.FC = () => {
const reorderedIds = [...classifications];
// 交换当前项和下一项的位置
[reorderedIds[currentIndex], reorderedIds[currentIndex + 1]] =
[reorderedIds[currentIndex + 1], reorderedIds[currentIndex]];
[reorderedIds[currentIndex + 1], reorderedIds[currentIndex]];
// 生成新的排序更新
const updates = reorderedIds.map((item, index) => ({
@@ -272,8 +272,8 @@ const AiClassificationSettings: React.FC = () => {
if (error) {
return (
<div className="p-6">
<ErrorMessage
message={error}
<ErrorMessage
message={error}
onRetry={loadClassifications}
/>
</div>
@@ -285,7 +285,7 @@ const AiClassificationSettings: React.FC = () => {
<div className="max-w-6xl mx-auto px-4 py-6">
{/* 美观的页面头部 */}
<div className="mb-6">
<div className="bg-gradient-to-r from-white via-purple-50/30 to-white rounded-xl shadow-sm border border-gray-200/50 p-6 relative overflow-hidden">
<div className="page-header bg-gradient-to-r from-white via-purple-50/30 to-white rounded-xl shadow-sm border border-gray-200/50 p-6 relative overflow-hidden">
<div className="absolute top-0 right-0 w-32 h-32 bg-gradient-to-br from-purple-100/30 to-pink-100/30 rounded-full -translate-y-16 translate-x-16 opacity-50"></div>
<div className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4 relative z-10">
@@ -352,11 +352,10 @@ const AiClassificationSettings: React.FC = () => {
<h3 className="text-base font-semibold text-gray-900 truncate">
{classification.name}
</h3>
<span className={`inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium ${
classification.is_active
<span className={`inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium ${classification.is_active
? 'bg-gradient-to-r from-emerald-50 to-emerald-100 text-emerald-700 border border-emerald-200'
: 'bg-gradient-to-r from-gray-50 to-gray-100 text-gray-600 border border-gray-200'
}`}>
}`}>
{classification.is_active ? '激活' : '禁用'}
</span>
<span className="text-xs text-purple-600 bg-purple-50 px-2 py-1 rounded-full border border-purple-200">
@@ -406,11 +405,10 @@ const AiClassificationSettings: React.FC = () => {
{/* 状态切换按钮 */}
<button
onClick={() => handleToggleStatus(classification.id)}
className={`p-1.5 rounded-lg transition-all duration-150 ${
classification.is_active
className={`p-1.5 rounded-lg transition-all duration-150 ${classification.is_active
? 'text-emerald-600 hover:text-emerald-700 hover:bg-emerald-50'
: 'text-gray-400 hover:text-gray-600 hover:bg-gray-50'
}`}
}`}
title={classification.is_active ? '禁用' : '激活'}
>
{classification.is_active ? (
@@ -445,70 +443,70 @@ const AiClassificationSettings: React.FC = () => {
</div>
)}
{/* 创建分类对话框 */}
<AiClassificationFormDialog
isOpen={showCreateDialog}
title="添加AI分类"
formData={formData}
formErrors={formErrors}
submitting={submitting}
existingClassifications={classifications}
onFormDataChange={setFormData}
onSubmit={handleCreate}
onCancel={() => {
setShowCreateDialog(false);
setFormData(DEFAULT_FORM_DATA);
setFormErrors({});
}}
/>
{/* 创建分类对话框 */}
<AiClassificationFormDialog
isOpen={showCreateDialog}
title="添加AI分类"
formData={formData}
formErrors={formErrors}
submitting={submitting}
existingClassifications={classifications}
onFormDataChange={setFormData}
onSubmit={handleCreate}
onCancel={() => {
setShowCreateDialog(false);
setFormData(DEFAULT_FORM_DATA);
setFormErrors({});
}}
/>
{/* 编辑分类对话框 */}
<AiClassificationFormDialog
isOpen={showEditDialog}
title="编辑AI分类"
formData={formData}
formErrors={formErrors}
submitting={submitting}
isEdit={true}
existingClassifications={classifications}
editingClassificationId={editingClassification?.id}
onFormDataChange={setFormData}
onSubmit={handleEdit}
onCancel={() => {
setShowEditDialog(false);
setEditingClassification(null);
setFormData(DEFAULT_FORM_DATA);
setFormErrors({});
}}
/>
{/* 编辑分类对话框 */}
<AiClassificationFormDialog
isOpen={showEditDialog}
title="编辑AI分类"
formData={formData}
formErrors={formErrors}
submitting={submitting}
isEdit={true}
existingClassifications={classifications}
editingClassificationId={editingClassification?.id}
onFormDataChange={setFormData}
onSubmit={handleEdit}
onCancel={() => {
setShowEditDialog(false);
setEditingClassification(null);
setFormData(DEFAULT_FORM_DATA);
setFormErrors({});
}}
/>
{/* 删除确认对话框 */}
<DeleteConfirmDialog
isOpen={showDeleteDialog}
title="删除AI分类"
message="您确定要删除这个AI分类吗"
itemName={deletingClassificationId ?
classifications.find(c => c.id === deletingClassificationId)?.name :
undefined
}
deleting={submitting}
onConfirm={handleDelete}
onCancel={() => {
setShowDeleteDialog(false);
setDeletingClassificationId(null);
}}
/>
{/* 删除确认对话框 */}
<DeleteConfirmDialog
isOpen={showDeleteDialog}
title="删除AI分类"
message="您确定要删除这个AI分类吗"
itemName={deletingClassificationId ?
classifications.find(c => c.id === deletingClassificationId)?.name :
undefined
}
deleting={submitting}
onConfirm={handleDelete}
onCancel={() => {
setShowDeleteDialog(false);
setDeletingClassificationId(null);
}}
/>
{/* 预览对话框 */}
<AiClassificationPreviewDialog
isOpen={showPreviewDialog}
preview={preview}
loading={previewLoading}
onClose={() => {
setShowPreviewDialog(false);
setPreview(null);
}}
/>
{/* 预览对话框 */}
<AiClassificationPreviewDialog
isOpen={showPreviewDialog}
preview={preview}
loading={previewLoading}
onClose={() => {
setShowPreviewDialog(false);
setPreview(null);
}}
/>
</div>
</div>
);