aura-web/src/pages/MarketplacePage/components/MarketplacePageH5.tsx

244 lines
9.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import { PlusOutlined, SearchOutlined, CompassOutlined, FireOutlined } from '@ant-design/icons';
import { Col, Row, Empty, Button, Tag, Space, Input, Spin } from 'antd';
import { useNavigate } from 'react-router-dom';
import type { MarketplaceAgent } from '../../../api';
import type { MarketplacePageLogicOutput } from '../MarketplacePageLogic';
interface Props {
logic: MarketplacePageLogicOutput;
}
export default function MarketplacePageH5({ logic }: Props) {
const navigate = useNavigate();
const { loading, q, filtered, setQ, handleFork, isImageUrl } = logic;
return (
<div className="h5-marketplace-page">
<div className="page-hero h5-page-hero" style={{ padding: '20px 16px' }}>
<div>
<div
style={{
display: 'inline-flex',
alignItems: 'center',
gap: 6,
padding: '4px 10px',
borderRadius: 999,
background: 'var(--color-surface)',
border: '1px solid var(--color-border)',
color: 'var(--color-text-secondary)',
fontSize: 11,
fontWeight: 500,
marginBottom: 12,
}}
>
<CompassOutlined style={{ color: 'var(--color-brand)', fontSize: 12 }} />
</div>
<h1 className="hero-title h5-hero-title" style={{ fontSize: 28, marginBottom: 8 }}>
<br />AI
</h1>
<p className="hero-subtitle h5-hero-subtitle" style={{ fontSize: 14, lineHeight: 1.6 }}>
</p>
</div>
</div>
<div className="page-container h5-page-container" style={{ paddingTop: 20, paddingLeft: 12, paddingRight: 12 }}>
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: 12,
marginBottom: 20,
}}
>
<div style={{ width: '100%' }}>
<Input
placeholder="搜索智能体名称、描述或作者..."
prefix={<SearchOutlined style={{ color: 'var(--color-text-tertiary)' }} />}
value={q}
onChange={(e) => setQ(e.target.value)}
style={{ height: 40, borderRadius: 10 }}
allowClear
/>
</div>
<Button
type="primary"
size="middle"
icon={<PlusOutlined />}
onClick={() => navigate('/agents/new')}
style={{
height: 40,
width: '100%',
borderRadius: 10,
fontWeight: 600,
}}
>
</Button>
</div>
{loading ? (
<div style={{ padding: '40px 0', textAlign: 'center' }}>
<Spin size="large" />
</div>
) : (
<Row gutter={[12, 12]}>
{/* Create New Card - always show on H5 */}
<Col xs={24} sm={24} key="create-new">
<div onClick={() => navigate('/agents/new')} className="create-card h5-create-card" style={{ padding: 16 }}>
<div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between' }}>
<div className="create-icon" style={{ width: 44, height: 44 }}>
<PlusOutlined style={{ fontSize: 20, color: '#0891b2' }} />
</div>
</div>
<div style={{ marginTop: 12 }}>
<div style={{ fontWeight: 700, fontSize: 15, color: 'var(--color-text)', marginBottom: 4 }}>
</div>
<div style={{ fontSize: 12, color: 'var(--color-text-tertiary)', marginBottom: 8 }}>
</div>
<div className="desc" style={{ minHeight: 36, fontSize: 12 }}>
AI
</div>
</div>
<div style={{ marginTop: 'auto', paddingTop: 12 }}>
<Button
type="default"
block
style={{
height: 36,
borderRadius: 8,
fontWeight: 600,
borderStyle: 'dashed',
}}
>
</Button>
</div>
</div>
</Col>
{filtered.map((a) => (
<Col xs={24} sm={24} key={a.id}>
<div className="agent-card h5-agent-card" style={{ padding: 14, borderRadius: 12 }}>
<div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 8 }}>
<div
style={{
width: 44,
height: 44,
borderRadius: '50%',
background: a.avatar || 'var(--gradient-brand)',
color: '#fff',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontWeight: 700,
fontSize: 18,
boxShadow: 'var(--shadow-sm)',
overflow: 'hidden',
}}
>
{isImageUrl(a.avatar) ? (
<img src={a.avatar} className="w-full h-full object-cover" alt="avatar" />
) : (
(a.name?.charAt(0) || '?').toUpperCase()
)}
</div>
{a.fork_count > 10 && (
<Tag
bordered={false}
icon={<FireOutlined />}
style={{
borderRadius: 999,
margin: 0,
background: 'var(--color-warning-soft)',
color: 'var(--color-warning)',
fontSize: 11,
}}
>
</Tag>
)}
</div>
<div style={{ marginTop: 12 }}>
<div
style={{
fontWeight: 700,
fontSize: 15,
color: 'var(--color-text)',
marginBottom: 4,
letterSpacing: '-0.01em',
}}
>
{a.name}
</div>
<div style={{ fontSize: 12, color: 'var(--color-text-tertiary)', marginBottom: 8 }}>
by {a.ownerName || '匿名作者'}
</div>
<div className="desc" style={{ minHeight: 36, fontSize: 12 }}>{a.description || '暂无详细描述'}</div>
</div>
<div style={{ marginTop: 'auto', paddingTop: 12 }}>
<Space size={4} wrap style={{ marginBottom: 12 }}>
{a.kbCount > 0 && (
<Tag
bordered={false}
style={{
background: 'var(--color-info-soft)',
color: 'var(--color-info)',
borderRadius: 999,
fontSize: 11,
margin: 0,
}}
>
📚 {a.kbCount}
</Tag>
)}
{a.skillCount > 0 && (
<Tag
bordered={false}
style={{
background: 'var(--color-success-soft)',
color: 'var(--color-success)',
borderRadius: 999,
fontSize: 11,
margin: 0,
}}
>
🛠 {a.skillCount}
</Tag>
)}
</Space>
<Button
type="default"
block
onClick={() => handleFork(a)}
style={{
height: 36,
borderRadius: 8,
fontWeight: 600,
}}
>
📥
</Button>
</div>
</div>
</Col>
))}
</Row>
)}
{filtered.length === 0 && !loading && (
<Empty description="没有找到匹配的智能体" style={{ marginTop: 40 }} />
)}
</div>
</div>
);
}