101 lines
4.2 KiB
TypeScript
101 lines
4.2 KiB
TypeScript
"use client";
|
|
import { MonitorDot, LayoutDashboard } from "lucide-react";
|
|
import { useLang } from "@/lib/language";
|
|
|
|
const t = {
|
|
zh: {
|
|
badge: "产品组成",
|
|
h2: "两个界面,一套完整体验",
|
|
subtitle: "客户端是主体验,Manager 是辅助控制台,用户不在网页上编码",
|
|
products: [
|
|
{
|
|
name: "Heicode 客户端",
|
|
badge: "主体验",
|
|
description: "用户的主入口。在本地输入产品想法、继续任务、查看 Agnet 执行反馈、接收交付结果、审批高危操作。登录 Heicode 即可使用,无需配置模型。",
|
|
features: ["任务驾驶舱", "高危审批", "执行反馈", "本地服务"],
|
|
},
|
|
{
|
|
name: "Heicode Manager",
|
|
badge: "辅助控制台",
|
|
description: "浏览器端辅助控制台。负责账号与安全、客户端下载、Git 与云资源绑定、Agnet 部署、任务状态总览、模型余额与用量、审计与日志查看。",
|
|
features: ["资源绑定", "Agnet 部署", "余额与用量", "审计日志"],
|
|
},
|
|
],
|
|
},
|
|
en: {
|
|
badge: "Product Components",
|
|
h2: "Two interfaces, one complete experience",
|
|
subtitle: "The client is the main experience, Manager is the auxiliary console",
|
|
products: [
|
|
{
|
|
name: "Heicode Client",
|
|
badge: "Main experience",
|
|
description: "The user's primary entry point. Input product ideas locally, continue tasks, view Agnet execution feedback, receive delivery results, approve high-risk operations. Log in to Heicode — no model configuration needed.",
|
|
features: ["Task dashboard", "Approval flow", "Exec feedback", "Local service"],
|
|
},
|
|
{
|
|
name: "Heicode Manager",
|
|
badge: "Aux console",
|
|
description: "Browser-based auxiliary console. Handles account & security, client download, Git & cloud resource binding, Agnet deployment, task status overview, model balance & usage, audit & log viewing.",
|
|
features: ["Resource binding", "Agnet deploy", "Balance & usage", "Audit log"],
|
|
},
|
|
],
|
|
},
|
|
};
|
|
|
|
const icons = [MonitorDot, LayoutDashboard];
|
|
|
|
export function Products() {
|
|
const { lang } = useLang();
|
|
const tx = t[lang];
|
|
|
|
return (
|
|
<section id="products" className="py-20 sm:py-32">
|
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
|
<div className="mx-auto max-w-2xl text-center">
|
|
<p className="text-sm font-medium tracking-widest text-accent uppercase">
|
|
{tx.badge}
|
|
</p>
|
|
<h2 className="mt-4 text-3xl font-bold tracking-tight sm:text-4xl">{tx.h2}</h2>
|
|
<p className="mt-4 text-muted-foreground">{tx.subtitle}</p>
|
|
</div>
|
|
|
|
<div className="mt-16 grid gap-8 md:grid-cols-2">
|
|
{tx.products.map((product, idx) => {
|
|
const Icon = icons[idx];
|
|
return (
|
|
<div
|
|
key={product.name}
|
|
className="group relative rounded-xl border border-border bg-card/50 p-8 transition-colors hover:border-accent/50 hover:bg-card"
|
|
>
|
|
<div className="mb-6 flex items-center gap-3">
|
|
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-secondary">
|
|
<Icon className="h-6 w-6 text-accent" />
|
|
</div>
|
|
<span className="rounded-full bg-accent/10 px-3 py-1 text-xs font-medium text-accent">
|
|
{product.badge}
|
|
</span>
|
|
</div>
|
|
<h3 className="text-xl font-semibold">{product.name}</h3>
|
|
<p className="mt-3 text-sm leading-relaxed text-muted-foreground">
|
|
{product.description}
|
|
</p>
|
|
<div className="mt-6 flex flex-wrap gap-2">
|
|
{product.features.map((feature) => (
|
|
<span
|
|
key={feature}
|
|
className="rounded-full bg-secondary px-3 py-1 text-xs text-muted-foreground"
|
|
>
|
|
{feature}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|