Files
deerflow-code/web-code/components/square/AppCard.tsx
T
2026-05-28 18:29:37 +08:00

151 lines
4.6 KiB
TypeScript

import { Edit, PlayCircle, Trash2 } from "lucide-react";
import React, { useState, useMemo, useEffect } from "react";
import { Popconfirm } from "tdesign-react";
import { requestCrudService } from "@/service/request-axios-service";
import { format } from "date-fns";
import logoSvg from "@/assets/icon/轻应用logo-DB.svg";
interface analysisListItem {
id: number;
categoryName: string;
category: string;
appName: string;
appDesc: string;
appIcon: string;
jumpUrl: string;
appType: number;
}
const service = requestCrudService;
const zncmUrl = import.meta.env.VITE_API_BASE_URL || "";
export const AppCard: React.FC<{
app: analysisListItem;
isDark: boolean;
hoverColor: string;
btnClass: string;
delDataChange: (item: analysisListItem) => void;
editShowChange: (item: analysisListItem) => void;
}> = ({ app, isDark, hoverColor, btnClass, delDataChange, editShowChange }) => {
const listDataChange = (item: analysisListItem) => {
historyCreateSearch(item);
// if (item.appType === 1) {
// internalDataChange(item);
// } else if (item.appType === 2) {
// externalDataChange(item);
// }
};
const internalDataChange = (item: analysisListItem) => {
// 内部接口跳转
};
const externalDataChange = (item: analysisListItem) => {
// 外部应用接口跳转
window.open(item.jumpUrl);
};
const handleConfirm = (item: analysisListItem) => {
// 确认删除逻辑
console.log("用户点击了确认");
delDataChange(item);
return true; // 返回 true 表示确认执行
};
const handleCancel = () => {
// 取消删除逻辑
console.log("用户点击了取消");
return true; // 返回 true 表示取消
};
const historyCreateSearch = async (item: analysisListItem) => {
const time = format(new Date(), "yyyy-MM-dd HH:mm:ss");
console.log("time", time);
const param = {
appId: item.id,
appName: item.appName,
runTime: time,
};
const res = await service.post(`${zncmUrl}/app/history/create`, param);
console.log("res", res);
};
return (
<div
className={`rounded-xl border p-5 transition-all relative duration-200 hover:shadow-lg group ${
isDark
? "bg-slate-800/50 border-slate-700 hover:border-slate-600"
: "bg-white border-gray-200 hover:border-gray-300"
}`}
>
{/* 头部信息 */}
<div className="flex items-start gap-4 mb-4">
<div className="rounded-lg overflow-hidden flex-shrink-0">
<img
className="w-[47px] h-[47px] object-cover"
src={app.appIcon}
alt={app.appName}
onError={(e) => {
const target = e.target as HTMLImageElement;
target.src = logoSvg;
}}
/>
</div>
<div className="flex-1 min-w-0">
<h3
className={`font-semibold truncate transition-colors ${hoverColor} ${
isDark ? "text-white" : "text-gray-900"
}`}
>
{app.appName}
</h3>
<p
className={`mt-1 text-sm line-clamp-2 ${
isDark ? "text-slate-400" : "text-gray-500"
}`}
>
{app.appDesc}
</p>
</div>
<div className="absolute right-[10px] top-[10px] flex items-center cursor-pointer opacity-100 group-hover:opacity-100 transition-opacity">
<Edit
className="w-4 h-4 text-[gray] mr-[10px]"
onClick={() => editShowChange(app)}
></Edit>
<Popconfirm
content="确认删除吗"
onConfirm={() => handleConfirm(app)}
onCancel={handleCancel}
>
<div>
<Trash2 className="w-4 h-4 text-[#ce2d39]"></Trash2>
</div>
</Popconfirm>
</div>
</div>
{/* 输入输出信息 */}
<div
className={`text-xs space-y-1 mb-4 ${
isDark ? "text-slate-500" : "text-gray-400"
}`}
>
<div className="flex items-start gap-2">
<span className="font-medium">输入:</span>
<span>信息文本/链接/素材</span>
</div>
<div className="flex items-start gap-2">
<span className="font-medium">输出:</span>
<span>信息特征、重点摘要、分析判断</span>
</div>
</div>
{/* 按钮 */}
<button
className={`w-full py-2.5 rounded-lg font-medium flex items-center justify-center gap-2 transition-all border ${btnClass}`}
onClick={() => listDataChange(app)}
>
<PlayCircle className="w-4 h-4" />
立即使用
</button>
</div>
);
};