feat: 服装搭配页面UI美化和UX改进

UI优化内容:
- 重新设计页面头部,使用优雅的渐变背景和现代化图标
- 优化标签导航,采用卡片式设计和平滑动画效果
- 美化搜索面板,改进输入框、筛选器和按钮的视觉设计
- 重构图片上传组件,添加拖拽区域样式和上传进度动画
- 优化搜索结果展示,使用网格布局和悬停效果
- 改进AI分析结果展示,采用卡片式布局和颜色编码
- 增强LLM聊天界面,现代化消息气泡和打字动画

 响应式设计:
- 实现移动优先的响应式布局
- 优化平板端和桌面端适配
- 修复1200px宽度下的左右布局显示问题
- 添加触摸友好的交互元素

 用户体验提升:
- 统一设计语言和视觉风格
- 添加流畅的页面切换和组件加载动画
- 优化加载状态、错误提示和空状态设计
- 改进信息层次和视觉可读性

 技术改进:
- 使用Tailwind CSS类替代内联样式
- 统一使用Lucide React图标库
- 完善CSS变量和设计令牌系统
- 添加兼容性变量支持旧的命名格式

符合promptx/frontend-developer规定的前端开发规范,确保界面美观、操作流畅、动画优美,符合用户操作习惯和大众审美习惯。
This commit is contained in:
imeepos
2025-07-17 23:27:52 +08:00
parent 504b1a6577
commit fa194a5db2
14 changed files with 4097 additions and 8 deletions

View File

@@ -0,0 +1,300 @@
import { ColorHSV } from '../types/outfitSearch';
/**
* 颜色工具函数
* 遵循 Tauri 开发规范的工具函数设计原则
*/
/**
* HSV颜色转换为十六进制字符串
*/
export function hsvToHex(color: ColorHSV): string {
const [r, g, b] = hsvToRgb(color);
return `#${Math.round(r).toString(16).padStart(2, '0')}${Math.round(g).toString(16).padStart(2, '0')}${Math.round(b).toString(16).padStart(2, '0')}`.toUpperCase();
}
/**
* 十六进制字符串转换为HSV颜色
*/
export function hexToHsv(hex: string): ColorHSV {
const cleanHex = hex.replace('#', '');
if (cleanHex.length !== 6) {
throw new Error('Invalid hex color format');
}
const r = parseInt(cleanHex.substring(0, 2), 16);
const g = parseInt(cleanHex.substring(2, 4), 16);
const b = parseInt(cleanHex.substring(4, 6), 16);
return rgbToHsv(r, g, b);
}
/**
* RGB值转换为HSV颜色
*/
export function rgbToHsv(r: number, g: number, b: number): ColorHSV {
r = r / 255;
g = g / 255;
b = b / 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const delta = max - min;
let hue = 0;
if (delta !== 0) {
if (max === r) {
hue = ((g - b) / delta) % 6;
} else if (max === g) {
hue = (b - r) / delta + 2;
} else {
hue = (r - g) / delta + 4;
}
hue = hue / 6;
}
const saturation = max === 0 ? 0 : delta / max;
const value = max;
return {
hue: Math.max(0, Math.min(1, hue)),
saturation: Math.max(0, Math.min(1, saturation)),
value: Math.max(0, Math.min(1, value)),
};
}
/**
* HSV颜色转换为RGB值
*/
export function hsvToRgb(color: ColorHSV): [number, number, number] {
const { hue, saturation, value } = color;
const c = value * saturation;
const x = c * (1 - Math.abs(((hue * 6) % 2) - 1));
const m = value - c;
let r = 0, g = 0, b = 0;
const hueSegment = Math.floor(hue * 6);
switch (hueSegment) {
case 0:
r = c; g = x; b = 0;
break;
case 1:
r = x; g = c; b = 0;
break;
case 2:
r = 0; g = c; b = x;
break;
case 3:
r = 0; g = x; b = c;
break;
case 4:
r = x; g = 0; b = c;
break;
case 5:
r = c; g = 0; b = x;
break;
}
return [
Math.round((r + m) * 255),
Math.round((g + m) * 255),
Math.round((b + m) * 255),
];
}
/**
* 计算两个颜色的距离
*/
export function colorDistance(color1: ColorHSV, color2: ColorHSV): number {
// 色相环形距离计算
const hueDiff = Math.abs(color1.hue - color2.hue);
const hueDistance = Math.min(hueDiff, 1 - hueDiff);
// 饱和度和明度线性距离
const satDistance = Math.abs(color1.saturation - color2.saturation);
const valDistance = Math.abs(color1.value - color2.value);
// 加权距离计算色相50%饱和度30%明度20%
return hueDistance * 0.5 + satDistance * 0.3 + valDistance * 0.2;
}
/**
* 计算颜色相似度 (0-11表示完全相同)
*/
export function colorSimilarity(color1: ColorHSV, color2: ColorHSV): number {
return 1 - colorDistance(color1, color2);
}
/**
* 判断颜色是否在指定阈值范围内匹配
*/
export function colorsMatch(
color1: ColorHSV,
color2: ColorHSV,
hueThreshold: number = 0.05,
satThreshold: number = 0.05,
valThreshold: number = 0.20
): boolean {
const hueDiff = Math.abs(color1.hue - color2.hue);
const hueDistance = Math.min(hueDiff, 1 - hueDiff);
const satDiff = Math.abs(color1.saturation - color2.saturation);
const valDiff = Math.abs(color1.value - color2.value);
return hueDistance <= hueThreshold &&
satDiff <= satThreshold &&
valDiff <= valThreshold;
}
/**
* 生成颜色的互补色
*/
export function getComplementaryColor(color: ColorHSV): ColorHSV {
return {
hue: (color.hue + 0.5) % 1,
saturation: color.saturation,
value: color.value,
};
}
/**
* 生成颜色的类似色(相邻色)
*/
export function getAnalogousColors(color: ColorHSV, count: number = 2): ColorHSV[] {
const colors: ColorHSV[] = [];
const step = 0.083; // 30度 / 360度 = 0.083
for (let i = 1; i <= count; i++) {
colors.push({
hue: (color.hue + step * i) % 1,
saturation: color.saturation,
value: color.value,
});
colors.push({
hue: (color.hue - step * i + 1) % 1,
saturation: color.saturation,
value: color.value,
});
}
return colors;
}
/**
* 生成颜色的三元色
*/
export function getTriadicColors(color: ColorHSV): ColorHSV[] {
return [
{
hue: (color.hue + 0.333) % 1,
saturation: color.saturation,
value: color.value,
},
{
hue: (color.hue + 0.667) % 1,
saturation: color.saturation,
value: color.value,
},
];
}
/**
* 调整颜色亮度
*/
export function adjustBrightness(color: ColorHSV, factor: number): ColorHSV {
return {
hue: color.hue,
saturation: color.saturation,
value: Math.max(0, Math.min(1, color.value * factor)),
};
}
/**
* 调整颜色饱和度
*/
export function adjustSaturation(color: ColorHSV, factor: number): ColorHSV {
return {
hue: color.hue,
saturation: Math.max(0, Math.min(1, color.saturation * factor)),
value: color.value,
};
}
/**
* 获取颜色的可读性文本颜色(黑色或白色)
*/
export function getContrastTextColor(color: ColorHSV): string {
const [r, g, b] = hsvToRgb(color);
// 计算相对亮度
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
return luminance > 0.5 ? '#000000' : '#FFFFFF';
}
/**
* 验证HSV颜色值的有效性
*/
export function isValidHSV(color: ColorHSV): boolean {
return (
typeof color.hue === 'number' && color.hue >= 0 && color.hue <= 1 &&
typeof color.saturation === 'number' && color.saturation >= 0 && color.saturation <= 1 &&
typeof color.value === 'number' && color.value >= 0 && color.value <= 1
);
}
/**
* 创建默认HSV颜色
*/
export function createDefaultHSV(): ColorHSV {
return { hue: 0, saturation: 0, value: 0.5 };
}
/**
* 从CSS颜色名称转换为HSV
*/
export function cssColorToHsv(cssColor: string): ColorHSV {
// 创建临时元素来获取计算后的颜色
const div = document.createElement('div');
div.style.color = cssColor;
document.body.appendChild(div);
const computedColor = window.getComputedStyle(div).color;
document.body.removeChild(div);
// 解析 rgb(r, g, b) 格式
const rgbMatch = computedColor.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
if (rgbMatch) {
const r = parseInt(rgbMatch[1]);
const g = parseInt(rgbMatch[2]);
const b = parseInt(rgbMatch[3]);
return rgbToHsv(r, g, b);
}
// 如果解析失败,返回默认颜色
return createDefaultHSV();
}
/**
* 颜色工具对象
*/
export const ColorUtils = {
hsvToHex,
hexToHsv,
rgbToHsv,
hsvToRgb,
colorDistance,
colorSimilarity,
colorsMatch,
getComplementaryColor,
getAnalogousColors,
getTriadicColors,
adjustBrightness,
adjustSaturation,
getContrastTextColor,
isValidHSV,
createDefaultHSV,
cssColorToHsv,
};