polish(operator cards): improve icon color distinction and subtle UI … (#217)

polish(operator cards): improve icon color distinction and subtle UI details
This commit is contained in:
Kecheng Sha
2025-12-31 10:54:34 +08:00
committed by GitHub
parent f183b9f2f3
commit 01e1c6c7e9
5 changed files with 679 additions and 601 deletions

View File

@@ -181,7 +181,7 @@ function CardView<T extends BaseCardDataType>(props: CardViewProps<T>) {
{data.map((item) => (
<div
key={item.id}
className="border-card p-4 bg-white hover:shadow-lg transition-shadow duration-200"
className="border-card p-4 bg-white duration-200 transition-shadow transition-transform hover:-translate-y-0.5 hover:shadow-[0_8px_24px_rgba(0,0,0,0.06)]"
>
<div className="flex flex-col space-y-4 h-full">
<div
@@ -194,9 +194,22 @@ function CardView<T extends BaseCardDataType>(props: CardViewProps<T>) {
<div className="flex items-center gap-3 min-w-0">
{item?.icon && (
<div
className={`flex-shrink-0 w-12 h-12 bg-gradient-to-br from-sky-300 to-blue-500 text-white rounded-lg flex items-center justify-center`}
className={`flex-shrink-0 w-12 h-12 rounded-lg flex items-center justify-center ${
item?.iconColor
? ""
: "bg-gradient-to-br from-sky-300 to-blue-500 text-white"
}`}
style={{
...(item?.iconColor
? { backgroundColor: item.iconColor }
: {}),
backgroundImage:
"linear-gradient(180deg, rgba(255,255,255,0.35), rgba(255,255,255,0.05))",
boxShadow:
"inset 0 0 0 1px rgba(255,255,255,0.25)",
}}
>
<div className="w-6 h-6 text-gray-50">{item?.icon}</div>
<div className="w-[2.1rem] h-[2.1rem] text-gray-50">{item?.icon}</div>
</div>
)}
<div className="flex-1 min-w-0">
@@ -236,7 +249,7 @@ function CardView<T extends BaseCardDataType>(props: CardViewProps<T>) {
<TagsRenderer tags={item?.tags || []} />
{/* Description */}
<p className="text-gray-600 text-xs text-ellipsis overflow-hidden whitespace-nowrap text-xs line-clamp-2 mt-2">
<p className="text-gray-400 text-xs text-ellipsis overflow-hidden whitespace-nowrap text-xs line-clamp-2 mt-2">
<Tooltip title={item?.description}>
{item?.description}
</Tooltip>
@@ -258,8 +271,9 @@ function CardView<T extends BaseCardDataType>(props: CardViewProps<T>) {
</div>
</div>
{/* Actions */}
<div className="flex items-center justify-between pt-3 border-t border-t-gray-200">
{/* Divider & Actions */}
<div className="w-2/3 border-t border-t-gray-200 mt-2" />
<div className="flex items-center justify-between pt-3">
<div className=" text-gray-500 text-right">
<div className="flex items-center gap-1">
<ClockCircleOutlined className="w-4 h-4" />{" "}

View File

@@ -49,9 +49,14 @@ function DetailHeader<T>({
<div className="flex items-start justify-between">
<div className="flex items-start gap-4 flex-1">
<div
className={`w-16 h-16 text-white rounded-lg flex-center shadow-lg bg-gradient-to-br from-sky-300 to-blue-500 text-white`}
className={`w-16 h-16 text-white rounded-lg flex-center shadow-lg ${
(data as any)?.iconColor
? ""
: "bg-gradient-to-br from-sky-300 to-blue-500 text-white"
}`}
style={(data as any)?.iconColor ? { backgroundColor: (data as any).iconColor } : undefined}
>
{<div className="w-8 h-8 text-gray-50">{data?.icon}</div> || (
{<div className="w-[2.8rem] h-[2.8rem] text-gray-50">{(data as any)?.icon}</div> || (
<Database className="w-8 h-8 text-white" />
)}
</div>

View File

@@ -56,8 +56,19 @@ export function ListView({ operators = [], pagination, operations }) {
>
<List.Item.Meta
avatar={
<div className="w-12 h-12 bg-gradient-to-br from-sky-300 to-blue-500 rounded-lg flex items-center justify-center">
<div className="w-8 h-8 text-white">{operator?.icon}</div>
<div
className={`w-12 h-12 rounded-lg flex items-center justify-center ${
operator?.iconColor
? ""
: "bg-gradient-to-br from-sky-300 to-blue-500"
}`}
style={
operator?.iconColor
? { backgroundColor: operator.iconColor }
: undefined
}
>
<div className="w-[2.8rem] h-[2.8rem] text-white">{operator?.icon}</div>
</div>
}
title={

View File

@@ -1,12 +1,59 @@
import { Code } from "lucide-react";
import React from "react";
import { Code, FileSliders, Image } from "lucide-react";
import { OperatorI } from "./operator.model";
import {formatDateTime} from "@/utils/unit.ts";
import { formatDateTime } from "@/utils/unit.ts";
const getOperatorVisual = (
op: OperatorI
): { icon: React.ReactNode; iconColor?: string } => {
const type = (op?.type || "").toLowerCase();
const categories = (op?.categories || []).map((c) => (c || "").toLowerCase());
const inputs = (op?.inputs || "").toLowerCase();
const outputs = (op?.outputs || "").toLowerCase();
const isImageOp =
["image", "图像", "图像类"].includes(type) ||
categories.some((c) => c.includes("image") || c.includes("图像")) ||
inputs.includes("image") ||
outputs.includes("image");
const isTextOp =
["text", "文本", "文本类"].includes(type) ||
categories.some((c) => c.includes("text") || c.includes("文本")) ||
inputs.includes("text") ||
outputs.includes("text");
if (isImageOp) {
return {
icon: <Image className="w-full h-full" />,
iconColor: "#38BDF8", // 图像算子背景色
};
}
if (isTextOp) {
return {
icon: <FileSliders className="w-full h-full" />,
iconColor: "#A78BFA", // 文本算子背景色
};
}
export const mapOperator = (op: OperatorI) => {
return {
...op,
icon: <Code className="w-full h-full" />,
createdAt: formatDateTime(op?.createdAt) || "--",
updatedAt: formatDateTime(op?.updatedAt) || formatDateTime(op?.createdAt) || "--",
iconColor: undefined,
};
};
export const mapOperator = (op: OperatorI) => {
const visual = getOperatorVisual(op);
return {
...op,
icon: visual.icon,
iconColor: visual.iconColor,
createdAt: formatDateTime(op?.createdAt) || "--",
updatedAt:
formatDateTime(op?.updatedAt) ||
formatDateTime(op?.createdAt) ||
"--",
};
};

View File

@@ -29,6 +29,7 @@ export interface OperatorI {
inputs: string;
outputs: string;
icon: React.ReactNode;
iconColor?: string; // 图标背景色,用于区分不同类型算子
description: string;
tags: string[];
isStar?: boolean;