fix: fix agent list style
parent
6dc5f1f750
commit
eea532371b
|
|
@ -0,0 +1,119 @@
|
||||||
|
.h5-agent-list-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 12px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||||
|
gap: 12px;
|
||||||
|
position: relative;
|
||||||
|
transition: all 0.2s;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-agent-list-item:active {
|
||||||
|
background: #f8fafc;
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-agent-item-avatar {
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
overflow: hidden;
|
||||||
|
flex-shrink: 0;
|
||||||
|
border: 2px solid #fff;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-agent-item-avatar img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-agent-item-content {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-agent-item-title-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-agent-item-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1a1a1a;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-agent-item-tag {
|
||||||
|
font-size: 10px;
|
||||||
|
padding: 0 6px;
|
||||||
|
height: 18px;
|
||||||
|
line-height: 18px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-public {
|
||||||
|
background: #e6f4ff;
|
||||||
|
color: #1677ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-team {
|
||||||
|
background: #f6ffed;
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-private {
|
||||||
|
background: #fff7e6;
|
||||||
|
color: #fa8c16;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-agent-item-desc {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin: 2px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-agent-item-author {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #999;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-agent-item-actions {
|
||||||
|
flex-shrink: 0;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-agent-item-more-btn {
|
||||||
|
color: #bfbfbf;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-agent-item-more-btn:hover {
|
||||||
|
color: #1677ff;
|
||||||
|
background: rgba(0, 0, 0, 0.04);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,146 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
EllipsisOutlined,
|
||||||
|
MessageOutlined,
|
||||||
|
EditOutlined,
|
||||||
|
DeleteOutlined,
|
||||||
|
} from '@ant-design/icons';
|
||||||
|
import { Button, Tag, Dropdown, Modal, App as AntApp } from 'antd';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import type { Agent } from '../api';
|
||||||
|
import './AgentListItemH5.css';
|
||||||
|
|
||||||
|
export interface AgentListItemH5Props {
|
||||||
|
agent: Agent;
|
||||||
|
onDelete?: (id: string) => Promise<void>;
|
||||||
|
isImageUrl: (url?: string) => boolean;
|
||||||
|
authorName?: string;
|
||||||
|
extraActions?: {
|
||||||
|
key: string;
|
||||||
|
label: string;
|
||||||
|
icon: React.ReactNode;
|
||||||
|
onClick: (agent: Agent) => void;
|
||||||
|
danger?: boolean;
|
||||||
|
}[];
|
||||||
|
onClick?: (agent: Agent) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AgentListItemH5: React.FC<AgentListItemH5Props> = ({
|
||||||
|
agent,
|
||||||
|
onDelete,
|
||||||
|
isImageUrl,
|
||||||
|
authorName,
|
||||||
|
extraActions = [],
|
||||||
|
onClick,
|
||||||
|
}) => {
|
||||||
|
const { message } = AntApp.useApp();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const handleDefaultClick = () => {
|
||||||
|
if (onClick) {
|
||||||
|
onClick(agent);
|
||||||
|
} else {
|
||||||
|
navigate(`/chat/${agent.id}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const menuItems = [
|
||||||
|
{
|
||||||
|
key: 'chat',
|
||||||
|
label: '开始对话',
|
||||||
|
icon: <MessageOutlined />,
|
||||||
|
onClick: () => navigate(`/chat/${agent.id}`),
|
||||||
|
},
|
||||||
|
...extraActions.map(action => ({
|
||||||
|
key: action.key,
|
||||||
|
label: action.label,
|
||||||
|
icon: action.icon,
|
||||||
|
danger: action.danger,
|
||||||
|
onClick: () => action.onClick(agent),
|
||||||
|
})),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (onDelete) {
|
||||||
|
menuItems.push({
|
||||||
|
key: 'edit',
|
||||||
|
label: '修改',
|
||||||
|
icon: <EditOutlined />,
|
||||||
|
onClick: () => navigate(`/agents/${agent.id}`),
|
||||||
|
});
|
||||||
|
menuItems.push({
|
||||||
|
key: 'delete',
|
||||||
|
label: '删除',
|
||||||
|
danger: true,
|
||||||
|
icon: <DeleteOutlined />,
|
||||||
|
onClick: () => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确定删除?',
|
||||||
|
content: '删除后无法恢复',
|
||||||
|
okText: '删除',
|
||||||
|
okType: 'danger',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: async () => {
|
||||||
|
await onDelete(agent.id);
|
||||||
|
message.success('已删除');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="h5-agent-list-item">
|
||||||
|
<div
|
||||||
|
className="h5-agent-item-avatar"
|
||||||
|
style={{ background: agent.avatar && !isImageUrl(agent.avatar) ? agent.avatar : 'var(--gradient-brand)' }}
|
||||||
|
onClick={handleDefaultClick}
|
||||||
|
>
|
||||||
|
{isImageUrl(agent.avatar) ? (
|
||||||
|
<img src={agent.avatar} alt="avatar" />
|
||||||
|
) : (
|
||||||
|
(agent.name?.charAt(0) || '?').toUpperCase()
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="h5-agent-item-content" onClick={handleDefaultClick}>
|
||||||
|
<div className="h5-agent-item-title-row">
|
||||||
|
<span className="h5-agent-item-name">{agent.name}</span>
|
||||||
|
{agent.visibility === 'public' && !authorName && (
|
||||||
|
<Tag bordered={false} className="h5-agent-item-tag tag-public">
|
||||||
|
公开
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
|
{agent.visibility === 'team' && (
|
||||||
|
<Tag bordered={false} className="h5-agent-item-tag tag-team">
|
||||||
|
团队
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
|
{agent.visibility === 'private' && (
|
||||||
|
<Tag bordered={false} className="h5-agent-item-tag tag-private">
|
||||||
|
私有
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="h5-agent-item-desc">{agent.description || '暂无描述'}</div>
|
||||||
|
{authorName && <div className="h5-agent-item-author">by {authorName}</div>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="h5-agent-item-actions">
|
||||||
|
<Dropdown
|
||||||
|
menu={{ items: menuItems }}
|
||||||
|
placement="bottomRight"
|
||||||
|
trigger={['click']}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
shape="circle"
|
||||||
|
icon={<EllipsisOutlined />}
|
||||||
|
className="h5-agent-item-more-btn"
|
||||||
|
/>
|
||||||
|
</Dropdown>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AgentListItemH5;
|
||||||
|
|
@ -3,6 +3,25 @@ import { KnowledgeStatus, SkillType } from '../../api';
|
||||||
export const DEFAULT_AVATAR = 'https://static.svipdata.com/hoyidata/materials/B7lNeTYQM1_0/materials.jpg';
|
export const DEFAULT_AVATAR = 'https://static.svipdata.com/hoyidata/materials/B7lNeTYQM1_0/materials.jpg';
|
||||||
|
|
||||||
export const PRESET_AVATARS: string[] = [
|
export const PRESET_AVATARS: string[] = [
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/a1ed5d166a9bcda1.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/da4d3c387956cd91.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/9f3eff849389bdd3.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/0bdcc398dd0423ca.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/18e35c04462fc56c.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/7a4d55fc295e65ce.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/5755088edf226f3c.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/5ec020c29804a8cd.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/31265f843ca7099b.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/f4a2df94f05ed9f6.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/dfec7aa91c1c5144.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/fa8ca9d432b555bd.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/796e8ba7f5781bb0.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/12a397b565a1ce78.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/15f78f9a3e0d120c.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/3ec3ff2af8d61123.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/ef90579ba571476e.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/c555806777e127ec.png',
|
||||||
|
'https://static.svipdata.com/images/mock-dev-user-id/40778045ad8c2620.png',
|
||||||
'https://static.svipdata.com/hoyidata/materials/PkM0iQCaAY_0/materials.png',
|
'https://static.svipdata.com/hoyidata/materials/PkM0iQCaAY_0/materials.png',
|
||||||
'https://static.svipdata.com/hoyidata/materials/tmPDm2FhJY_1/materials.png',
|
'https://static.svipdata.com/hoyidata/materials/tmPDm2FhJY_1/materials.png',
|
||||||
'https://static.svipdata.com/hoyidata/materials/hNCyP4RvJL_2/materials.png',
|
'https://static.svipdata.com/hoyidata/materials/hNCyP4RvJL_2/materials.png',
|
||||||
|
|
|
||||||
|
|
@ -255,6 +255,7 @@
|
||||||
width: 5rem;
|
width: 5rem;
|
||||||
height: 5rem;
|
height: 5rem;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
padding: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ export function useAgentListLogic() {
|
||||||
load();
|
load();
|
||||||
};
|
};
|
||||||
|
|
||||||
const isImageUrl = (url: string) => url?.startsWith('http') || url?.startsWith('/');
|
const isImageUrl = (url?: string): boolean => !!(url?.startsWith('http') || url?.startsWith('/'));
|
||||||
|
|
||||||
const getModelLabel = (value: unknown): string => {
|
const getModelLabel = (value: unknown): string => {
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
|
|
|
||||||
|
|
@ -105,173 +105,11 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.h5-agent-card-item {
|
/* 智能体列表容器 */
|
||||||
border-radius: 12px;
|
.h5-agent-list {
|
||||||
padding: 12px;
|
|
||||||
background: linear-gradient(180deg, rgba(255,255,255,0.98) 0%, rgba(252,252,253,1) 100%);
|
|
||||||
box-shadow: 0 4px 12px rgba(15, 23, 42, 0.04);
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 4px;
|
|
||||||
position: relative; /* 为右上角标签提供定位参考 */
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h5-agent-card-badge {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h5-agent-card-badge .h5-agent-tag-item {
|
|
||||||
border-top-left-radius: 0 !important;
|
|
||||||
border-top-right-radius: 0 !important;
|
|
||||||
border-bottom-right-radius: 0 !important;
|
|
||||||
border-bottom-left-radius: 8px !important;
|
|
||||||
padding: 2px 8px !important;
|
|
||||||
height: auto !important;
|
|
||||||
font-size: 10px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h5-agent-card-header {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
text-align: center;
|
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding-top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h5-agent-avatar {
|
|
||||||
border-radius: 50%;
|
|
||||||
overflow: hidden;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: #fff;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 16px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h5-agent-info {
|
|
||||||
flex: 1;
|
|
||||||
min-width: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h5-agent-name {
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 12px;
|
|
||||||
color: var(--color-text);
|
|
||||||
margin-bottom: 0;
|
|
||||||
/* 支持最多展示两行 */
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
line-height: 1.3;
|
|
||||||
min-height: 1.4em; /* 调整为单行高度占位,因为下面加了描述 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.h5-agent-desc {
|
|
||||||
font-size: 11px;
|
|
||||||
color: var(--color-text-tertiary);
|
|
||||||
margin-top: 4px;
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
line-height: 1.4;
|
|
||||||
min-height: 2.8em;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h5-agent-tags {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 4px;
|
|
||||||
justify-content: center;
|
|
||||||
min-height: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h5-agent-tag-item {
|
|
||||||
border-radius: 999px !important;
|
|
||||||
margin: 0 !important;
|
|
||||||
font-size: 10px !important;
|
|
||||||
border: none !important;
|
|
||||||
display: inline-flex !important;
|
|
||||||
align-items: center !important;
|
|
||||||
justify-content: center !important;
|
|
||||||
padding: 0 6px !important;
|
|
||||||
height: 18px !important;
|
|
||||||
line-height: 1 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag-public {
|
|
||||||
background: var(--color-success-soft) !important;
|
|
||||||
color: var(--color-success) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag-team {
|
|
||||||
background: var(--color-info-soft) !important;
|
|
||||||
color: var(--color-info) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag-private {
|
|
||||||
background: var(--color-surface-2) !important;
|
|
||||||
color: var(--color-text-secondary) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag-model {
|
|
||||||
background: var(--color-brand-soft) !important;
|
|
||||||
color: var(--color-brand) !important;
|
|
||||||
max-width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h5-agent-actions {
|
|
||||||
display: flex;
|
|
||||||
gap: 4px;
|
|
||||||
margin-top: auto;
|
|
||||||
border-top: 1px solid var(--color-border);
|
|
||||||
justify-content: space-around;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h5-agent-action-link {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h5-agent-action-btn {
|
|
||||||
border-radius: 6px !important;
|
|
||||||
height: 28px !important;
|
|
||||||
width: 28px !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
display: flex !important;
|
|
||||||
align-items: center !important;
|
|
||||||
justify-content: center !important;
|
|
||||||
color: var(--color-text-secondary) !important;
|
|
||||||
background: transparent !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h5-agent-action-btn:hover {
|
|
||||||
background: var(--color-surface-2) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h5-agent-action-btn .anticon {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h5-agent-delete-btn {
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.h5-footer-promo {
|
.h5-footer-promo {
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,11 @@
|
||||||
import {
|
import {
|
||||||
ArrowRightOutlined,
|
|
||||||
CompassOutlined,
|
CompassOutlined,
|
||||||
DeleteOutlined,
|
|
||||||
EditOutlined,
|
|
||||||
MessageOutlined,
|
|
||||||
RobotOutlined,
|
RobotOutlined,
|
||||||
|
ArrowRightOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { Button, Col, Row, Empty, Popconfirm, App as AntApp, Tag, Space } from 'antd';
|
import { Button, Empty } from 'antd';
|
||||||
import { Link, useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import dayjs from 'dayjs';
|
import AgentListItemH5 from '../../../components/AgentListItemH5';
|
||||||
import type { Agent } from '../../../api';
|
|
||||||
import type { AgentListLogicOutput } from '../AgentListLogic';
|
import type { AgentListLogicOutput } from '../AgentListLogic';
|
||||||
import './AgentListH5.css';
|
import './AgentListH5.css';
|
||||||
|
|
||||||
|
|
@ -18,9 +14,8 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AgentListH5({ logic }: Props) {
|
export default function AgentListH5({ logic }: Props) {
|
||||||
const { message } = AntApp.useApp();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { list, loading, stats, handleDelete, isImageUrl, getModelLabel } = logic;
|
const { list, loading, stats, handleDelete, isImageUrl } = logic;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="page-container h5-page-container h5-agent-list-container">
|
<div className="page-container h5-page-container h5-agent-list-container">
|
||||||
|
|
@ -80,74 +75,16 @@ export default function AgentListH5({ logic }: Props) {
|
||||||
</Empty>
|
</Empty>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Row gutter={[8, 8]}>
|
<div className="h5-agent-list">
|
||||||
{list.map((a) => (
|
{list.map((a) => (
|
||||||
<Col xs={12} sm={12} md={12} key={a.id}>
|
<AgentListItemH5
|
||||||
<div className="agent-card h5-agent-card h5-agent-card-item">
|
key={a.id}
|
||||||
{/* 右上角可见性标签 */}
|
agent={a}
|
||||||
<div className="h5-agent-card-badge">
|
onDelete={handleDelete}
|
||||||
{a.visibility === 'public' && (
|
isImageUrl={isImageUrl}
|
||||||
<Tag bordered={false} className="h5-agent-tag-item tag-public">
|
/>
|
||||||
公开
|
|
||||||
</Tag>
|
|
||||||
)}
|
|
||||||
{a.visibility === 'team' && (
|
|
||||||
<Tag bordered={false} className="h5-agent-tag-item tag-team">
|
|
||||||
团队
|
|
||||||
</Tag>
|
|
||||||
)}
|
|
||||||
{a.visibility === 'private' && (
|
|
||||||
<Tag bordered={false} className="h5-agent-tag-item tag-private">
|
|
||||||
私有
|
|
||||||
</Tag>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="h5-agent-card-header">
|
|
||||||
<div
|
|
||||||
className="avatar h5-agent-avatar"
|
|
||||||
style={{ background: a.avatar || 'var(--gradient-brand)' }}
|
|
||||||
>
|
|
||||||
{isImageUrl(a.avatar) ? (
|
|
||||||
<img src={a.avatar} className="w-full h-full object-cover" alt="avatar" />
|
|
||||||
) : (
|
|
||||||
(a.name?.charAt(0) || '?').toUpperCase()
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="h5-agent-info">
|
|
||||||
<div className="h5-agent-name">{a.name}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{a.description && (
|
|
||||||
<div className="h5-agent-desc">
|
|
||||||
{a.description}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="h5-agent-actions">
|
|
||||||
<Link to={`/chat/${a.id}`} className="h5-agent-action-link">
|
|
||||||
<Button type="text" size="small" block icon={<MessageOutlined />} className="h5-agent-action-btn" />
|
|
||||||
</Link>
|
|
||||||
<Link to={`/agents/${a.id}`} className="h5-agent-action-link">
|
|
||||||
<Button type="text" size="small" block icon={<EditOutlined />} className="h5-agent-action-btn" />
|
|
||||||
</Link>
|
|
||||||
<Popconfirm
|
|
||||||
title="确定删除?"
|
|
||||||
onConfirm={() => {
|
|
||||||
handleDelete(a.id);
|
|
||||||
message.success('已删除');
|
|
||||||
}}
|
|
||||||
okText="删除"
|
|
||||||
cancelText="取消"
|
|
||||||
>
|
|
||||||
<Button type="text" size="small" icon={<DeleteOutlined />} className="h5-agent-action-btn h5-agent-delete-btn" />
|
|
||||||
</Popconfirm>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Col>
|
|
||||||
))}
|
))}
|
||||||
</Row>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{list.length > 0 && (
|
{list.length > 0 && (
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,6 @@
|
||||||
.agent-card {
|
.agent-card {
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
min-height: 292px;
|
|
||||||
background: linear-gradient(180deg, rgba(255,255,255,0.98) 0%, rgba(252,252,253,1) 100%);
|
background: linear-gradient(180deg, rgba(255,255,255,0.98) 0%, rgba(252,252,253,1) 100%);
|
||||||
box-shadow: 0 12px 28px rgba(15, 23, 42, 0.045);
|
box-shadow: 0 12px 28px rgba(15, 23, 42, 0.045);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,14 @@ export default function LoginFormCard({ logic }: { logic: LoginPageLogic }) {
|
||||||
onFinish={onLogin}
|
onFinish={onLogin}
|
||||||
className="login-form"
|
className="login-form"
|
||||||
>
|
>
|
||||||
<Form.Item name="phone" label="手机号" rules={[{ required: true, message: '请填写手机号' }]}>
|
<Form.Item
|
||||||
|
name="phone"
|
||||||
|
label="手机号"
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: '请填写手机号' },
|
||||||
|
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号格式' }
|
||||||
|
]}
|
||||||
|
>
|
||||||
<Input placeholder="13800138000" size="large" autoFocus />
|
<Input placeholder="13800138000" size="large" autoFocus />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="password" label="密码" rules={[{ required: true }]}>
|
<Form.Item name="password" label="密码" rules={[{ required: true }]}>
|
||||||
|
|
@ -59,7 +66,14 @@ export default function LoginFormCard({ logic }: { logic: LoginPageLogic }) {
|
||||||
onFinish={handleRegister}
|
onFinish={handleRegister}
|
||||||
className="login-form"
|
className="login-form"
|
||||||
>
|
>
|
||||||
<Form.Item name="phone" label="手机号" rules={[{ required: true, message: '请填写手机号' }]}>
|
<Form.Item
|
||||||
|
name="phone"
|
||||||
|
label="手机号"
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: '请填写手机号' },
|
||||||
|
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号格式' }
|
||||||
|
]}
|
||||||
|
>
|
||||||
<Input placeholder="13800138000" size="large" />
|
<Input placeholder="13800138000" size="large" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="name" label="昵称" rules={[{ required: true }]}>
|
<Form.Item name="name" label="昵称" rules={[{ required: true }]}>
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ export function useMarketplacePageLogic() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const isImageUrl = (url: string) => url?.startsWith('http') || url?.startsWith('/');
|
const isImageUrl = (url?: string): boolean => !!(url?.startsWith('http') || url?.startsWith('/'));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
list,
|
list,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
.h5-marketplace-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-page-hero {
|
||||||
|
background: linear-gradient(135deg, rgba(255,255,255,0.98) 0%, rgba(236,253,245,0.92) 48%, rgba(239,246,255,0.96) 100%);
|
||||||
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-hero-title {
|
||||||
|
color: var(--color-text);
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-hero-subtitle {
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-page-container {
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-marketplace-list {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-create-card {
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-create-card:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
background: rgba(8, 145, 178, 0.05);
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import { PlusOutlined, SearchOutlined, CompassOutlined, FireOutlined } from '@ant-design/icons';
|
import { PlusOutlined, SearchOutlined, CompassOutlined } from '@ant-design/icons';
|
||||||
import { Col, Row, Empty, Button, Tag, Space, Input, Spin } from 'antd';
|
import { Empty, Button, Input, Spin } from 'antd';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import type { MarketplaceAgent } from '../../../api';
|
import AgentListItemH5 from '../../../components/AgentListItemH5';
|
||||||
import type { MarketplacePageLogicOutput } from '../MarketplacePageLogic';
|
import type { MarketplacePageLogicOutput } from '../MarketplacePageLogic';
|
||||||
|
import './MarketplacePageH5.css';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
logic: MarketplacePageLogicOutput;
|
logic: MarketplacePageLogicOutput;
|
||||||
|
|
@ -83,155 +84,24 @@ export default function MarketplacePageH5({ logic }: Props) {
|
||||||
<Spin size="large" />
|
<Spin size="large" />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Row gutter={[12, 12]}>
|
<div className="h5-marketplace-list" style={{ display: 'flex', flexDirection: 'column', gap: 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) => (
|
{filtered.map((a) => (
|
||||||
<Col xs={24} sm={24} key={a.id}>
|
<AgentListItemH5
|
||||||
<div className="agent-card h5-agent-card" style={{ padding: 14, borderRadius: 12 }}>
|
key={a.id}
|
||||||
<div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 8 }}>
|
agent={a}
|
||||||
<div
|
isImageUrl={isImageUrl}
|
||||||
style={{
|
authorName={a.ownerName}
|
||||||
width: 44,
|
extraActions={[
|
||||||
height: 44,
|
{
|
||||||
borderRadius: '50%',
|
key: 'fork',
|
||||||
background: a.avatar || 'var(--gradient-brand)',
|
label: '复制到我的',
|
||||||
color: '#fff',
|
icon: <PlusOutlined />,
|
||||||
display: 'flex',
|
onClick: (agent) => handleFork(agent as any),
|
||||||
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>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{filtered.length === 0 && !loading && (
|
{filtered.length === 0 && !loading && (
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { PlusOutlined, SearchOutlined, CompassOutlined, FireOutlined } from '@ant-design/icons';
|
import { PlusOutlined, SearchOutlined, CompassOutlined, FireOutlined } from '@ant-design/icons';
|
||||||
import { Col, Row, Empty, Button, Tag, Space, Input, Spin } from 'antd';
|
import { Col, Row, Empty, Button, Tag, Space, Input, Spin } from 'antd';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import type { MarketplaceAgent } from '../../../api';
|
|
||||||
import type { MarketplacePageLogicOutput } from '../MarketplacePageLogic';
|
import type { MarketplacePageLogicOutput } from '../MarketplacePageLogic';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
|
||||||
|
|
@ -114,9 +114,10 @@ function TokenCharts({ logic }: { logic: StatsPageLogic }) {
|
||||||
pagination={false}
|
pagination={false}
|
||||||
rowKey={(row) => `${row.providerKind}:${row.model}`}
|
rowKey={(row) => `${row.providerKind}:${row.model}`}
|
||||||
dataSource={tokenData.byModel || []}
|
dataSource={tokenData.byModel || []}
|
||||||
|
scroll={{ x: 'max-content' }}
|
||||||
columns={[
|
columns={[
|
||||||
{ title: 'Provider', dataIndex: 'providerKind', width: 110 },
|
{ title: 'Provider', dataIndex: 'providerKind', width: 110 },
|
||||||
{ title: 'Model', dataIndex: 'model' },
|
{ title: 'Model', dataIndex: 'model', minWidth: 150 },
|
||||||
{ title: 'Calls', dataIndex: 'calls', width: 80 },
|
{ title: 'Calls', dataIndex: 'calls', width: 80 },
|
||||||
{ title: 'Tokens', dataIndex: 'totalTokens', width: 110, render: (value) => Number(value || 0).toLocaleString() },
|
{ title: 'Tokens', dataIndex: 'totalTokens', width: 110, render: (value) => Number(value || 0).toLocaleString() },
|
||||||
{ title: 'Cost', dataIndex: 'costUSD', width: 110, render: (value) => logic.formatUSD(value) }
|
{ title: 'Cost', dataIndex: 'costUSD', width: 110, render: (value) => logic.formatUSD(value) }
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,12 @@
|
||||||
.stats-page-h5 .points-integration-row,
|
.stats-page-h5 .points-integration-row,
|
||||||
.stats-page-h5 .stats-page-token-charts-grid {
|
.stats-page-h5 .stats-page-token-charts-grid {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-page-h5 .stats-page-token-charts-grid > * {
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats-page-h5 .stats-page-token-cards-grid {
|
.stats-page-h5 .stats-page-token-cards-grid {
|
||||||
|
|
@ -102,7 +108,12 @@
|
||||||
.stats-page-h5 .stats-page-chart-container,
|
.stats-page-h5 .stats-page-chart-container,
|
||||||
.stats-page-h5 .stats-page-token-chart-container {
|
.stats-page-h5 .stats-page-token-chart-container {
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
padding-bottom: 0.25rem;
|
padding-bottom: 0.75rem;
|
||||||
|
display: flex !important;
|
||||||
|
align-items: flex-end;
|
||||||
|
gap: 12px;
|
||||||
|
width: 100%;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats-page-h5 .stats-page-chart-container {
|
.stats-page-h5 .stats-page-chart-container {
|
||||||
|
|
@ -112,7 +123,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats-page-h5 .stats-page-chart-bar-group {
|
.stats-page-h5 .stats-page-chart-bar-group {
|
||||||
min-width: 1.625rem;
|
min-width: 2rem;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-page-h5 .stats-page-token-chart-bar {
|
||||||
|
width: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats-page-h5 .stats-page-chart-card .ant-card-head {
|
.stats-page-h5 .stats-page-chart-card .ant-card-head {
|
||||||
|
|
@ -143,3 +159,15 @@
|
||||||
.stats-page-h5 .ant-card-body {
|
.stats-page-h5 .ant-card-body {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stats-page-h5 .ant-table-wrapper {
|
||||||
|
margin-top: 12px;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-page-h5 .ant-table-cell {
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 8px 4px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -353,8 +353,14 @@ export default function TeamsPageH5({ logic }: Props) {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Form layout="vertical" onFinish={logic.handleInvite}>
|
<Form layout="vertical" onFinish={logic.handleInvite}>
|
||||||
<Form.Item name="email" label="限定邮箱(可选)">
|
<Form.Item
|
||||||
<Input placeholder="只允许该邮箱使用此邀请码" />
|
name="phone"
|
||||||
|
label="限定手机号(可选)"
|
||||||
|
rules={[
|
||||||
|
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号格式' }
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input placeholder="只允许该手机号使用此邀请码" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="ttlHours" label="有效期(小时)" initialValue={168}>
|
<Form.Item name="ttlHours" label="有效期(小时)" initialValue={168}>
|
||||||
<Input type="number" placeholder="168 = 7 天" />
|
<Input type="number" placeholder="168 = 7 天" />
|
||||||
|
|
|
||||||
|
|
@ -355,8 +355,14 @@ export default function TeamsPageWeb({ logic }: Props) {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Form layout="vertical" onFinish={logic.handleInvite}>
|
<Form layout="vertical" onFinish={logic.handleInvite}>
|
||||||
<Form.Item name="email" label="限定邮箱(可选)">
|
<Form.Item
|
||||||
<Input placeholder="只允许该邮箱使用此邀请码" />
|
name="phone"
|
||||||
|
label="限定手机号(可选)"
|
||||||
|
rules={[
|
||||||
|
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号格式' }
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input placeholder="只允许该手机号使用此邀请码" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="ttlHours" label="有效期(小时)" initialValue={168}>
|
<Form.Item name="ttlHours" label="有效期(小时)" initialValue={168}>
|
||||||
<Input type="number" placeholder="168 = 7 天" />
|
<Input type="number" placeholder="168 = 7 天" />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue