269 lines
11 KiB
TypeScript
269 lines
11 KiB
TypeScript
import {
|
||
DeleteOutlined,
|
||
EditOutlined,
|
||
PlusOutlined,
|
||
TeamOutlined,
|
||
UserAddOutlined,
|
||
UserOutlined,
|
||
} from '@ant-design/icons';
|
||
import { Card, Button, List, Tag, Space, Popconfirm, App as AntApp, Modal, Form, Input, Empty } from 'antd';
|
||
import { TeamAPI, type Team } from '../../../api';
|
||
import type { TeamsPageLogicOutput } from '../TeamsPageLogic';
|
||
import '../styles/teams-page-h5.css';
|
||
|
||
interface Props {
|
||
logic: TeamsPageLogicOutput;
|
||
}
|
||
|
||
export default function TeamsPageH5({ logic }: Props) {
|
||
const { message } = AntApp.useApp();
|
||
const {
|
||
list,
|
||
active,
|
||
handleDelete,
|
||
handleRename,
|
||
handleRemoveMember,
|
||
handleAddMember,
|
||
setCreateOpen,
|
||
setRenameOpen,
|
||
setAddMemberOpen,
|
||
} = logic;
|
||
|
||
return (
|
||
<div className="feature-cover-container">
|
||
<div className="page-container h5-page-container">
|
||
<div className="teams-page-h5-hero">
|
||
<div className="teams-page-h5-hero-header">
|
||
<div style={{ width: '100%' }}>
|
||
<div className="teams-page-h5-badge">
|
||
<TeamOutlined className="teams-page-h5-member-avatar-icon" />
|
||
协作组织空间
|
||
</div>
|
||
<h1 className="page-title h5-page-title teams-page-h5-title">团队管理</h1>
|
||
<div className="page-subtitle h5-page-subtitle teams-page-h5-subtitle">
|
||
团队不只是成员列表,更是共享智能体、协同运营和权限分工的组织单元。
|
||
</div>
|
||
</div>
|
||
<Button
|
||
type="primary"
|
||
size="middle"
|
||
icon={<PlusOutlined />}
|
||
onClick={() => setCreateOpen(true)}
|
||
className="teams-page-h5-create-btn"
|
||
>
|
||
创建团队
|
||
</Button>
|
||
</div>
|
||
|
||
<div className="teams-page-h5-stats-grid">
|
||
{[
|
||
{ label: '团队数量', value: list.length, type: 'brand' },
|
||
{ label: '当前成员数', value: active?.members?.length ?? 0, type: 'info' },
|
||
{ label: '共享智能体', value: active?.agentCount ?? 0, type: 'success' },
|
||
].map((item) => (
|
||
<div key={item.label} className="teams-page-h5-stat-card">
|
||
<div className="teams-page-h5-stat-label">{item.label}</div>
|
||
<div className="teams-page-h5-stat-row">
|
||
<span className="teams-page-h5-stat-value">{item.value}</span>
|
||
<span className={`teams-page-h5-stat-chip teams-page-h5-stat-chip-${item.type}`}>
|
||
当前选中
|
||
</span>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{list.length > 0 && (
|
||
<div className="teams-page-h5-list-panel">
|
||
<div className="teams-page-h5-list-head">
|
||
<div className="teams-page-h5-section-title">团队列表</div>
|
||
<div className="teams-page-h5-section-desc">点击选择一个团队</div>
|
||
</div>
|
||
{list.map((item) => (
|
||
<div
|
||
key={item.id}
|
||
className={`teams-page-h5-nav-item ${active?.id === item.id ? 'active' : ''}`}
|
||
onClick={async () => {
|
||
logic.setActive(await TeamAPI.detail(item.id));
|
||
}}
|
||
>
|
||
<div className="teams-page-h5-nav-item-name">{item.name}</div>
|
||
<div className="teams-page-h5-nav-item-count">
|
||
{item.agentCount ?? 0} 个智能体
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
)}
|
||
|
||
{active ? (
|
||
<Card className="teams-page-h5-detail-card">
|
||
<div className="teams-page-h5-detail-head">
|
||
<div>
|
||
<div className="teams-page-h5-active-title-row">
|
||
<span className="teams-page-h5-active-title">{active.name}</span>
|
||
<Button
|
||
type="text"
|
||
size="small"
|
||
icon={<EditOutlined />}
|
||
onClick={() => setRenameOpen(true)}
|
||
className="teams-page-h5-edit-btn"
|
||
/>
|
||
<Tag bordered={false} className="teams-page-h5-tag teams-page-h5-tag-brand">{active.myRole}</Tag>
|
||
<Tag bordered={false} className="teams-page-h5-tag teams-page-h5-tag-neutral">{active.agentCount ?? 0} 智能体</Tag>
|
||
</div>
|
||
<div className="teams-page-h5-section-desc">
|
||
管理成员权限、邀请新伙伴。
|
||
</div>
|
||
</div>
|
||
<Space wrap>
|
||
{active.myRole === 'owner' && (
|
||
<Popconfirm
|
||
title="确定删除该团队?团队内的智能体会变成 owner 私有"
|
||
onConfirm={async () => {
|
||
await handleDelete(active.id);
|
||
message.success('已删除');
|
||
}}
|
||
>
|
||
<Button danger size="small" icon={<DeleteOutlined />} className="teams-page-web-soft-btn">
|
||
删除团队
|
||
</Button>
|
||
</Popconfirm>
|
||
)}
|
||
</Space>
|
||
</div>
|
||
|
||
<div className="teams-page-h5-mini-grid">
|
||
<div className="teams-page-h5-mini-card teams-page-h5-mini-card-brand">
|
||
<div className="teams-page-h5-mini-label">成员规模</div>
|
||
<div className="teams-page-h5-mini-value">{active.members?.length || 0}</div>
|
||
</div>
|
||
<div className="teams-page-h5-mini-card teams-page-h5-mini-card-success">
|
||
<div className="teams-page-h5-mini-label">共享智能体</div>
|
||
<div className="teams-page-h5-mini-value">{active.agentCount ?? 0}</div>
|
||
</div>
|
||
<div className="teams-page-h5-mini-card teams-page-h5-mini-card-warning">
|
||
<div className="teams-page-h5-mini-label">当前身份</div>
|
||
<div className="teams-page-h5-mini-value" style={{ textTransform: 'capitalize' }}>{active.myRole}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="teams-page-h5-members-title-row">
|
||
<div className="teams-page-h5-members-title">
|
||
成员 ({active.members?.length || 0})
|
||
</div>
|
||
{(active.myRole === 'owner' || active.myRole === 'admin') && (
|
||
<Button
|
||
type="primary"
|
||
size="small"
|
||
ghost
|
||
icon={<UserAddOutlined />}
|
||
onClick={() => setAddMemberOpen(true)}
|
||
className="teams-page-web-soft-btn"
|
||
>
|
||
添加成员
|
||
</Button>
|
||
)}
|
||
</div>
|
||
<List
|
||
dataSource={active.members || []}
|
||
renderItem={(m) => (
|
||
<List.Item
|
||
className="teams-page-h5-member-item"
|
||
actions={
|
||
(active.myRole === 'owner' || active.myRole === 'admin') && m.role !== 'owner'
|
||
? [
|
||
<Popconfirm
|
||
key="kick"
|
||
title="移除该成员?"
|
||
onConfirm={async () => {
|
||
await handleRemoveMember(m.id);
|
||
}}
|
||
>
|
||
<Button size="small" danger className="teams-page-web-soft-btn">
|
||
移除
|
||
</Button>
|
||
</Popconfirm>,
|
||
]
|
||
: []
|
||
}
|
||
>
|
||
<List.Item.Meta
|
||
avatar={
|
||
<div className="teams-page-h5-member-avatar">
|
||
<UserOutlined />
|
||
</div>
|
||
}
|
||
title={
|
||
<Space>
|
||
<span className="teams-page-h5-member-name">{m.name}</span>
|
||
<Tag
|
||
bordered={false}
|
||
className={`teams-page-h5-tag teams-page-h5-tag-role-${m.role}`}
|
||
>
|
||
{m.role}
|
||
</Tag>
|
||
</Space>
|
||
}
|
||
description={
|
||
<div className="teams-page-h5-member-desc">
|
||
<span className="teams-page-h5-member-email">{m.email}</span>
|
||
<span className="teams-page-h5-member-time">
|
||
加入时间 {new Date(m.joinedAt).toLocaleDateString('zh-CN')}
|
||
</span>
|
||
</div>
|
||
}
|
||
/>
|
||
</List.Item>
|
||
)}
|
||
/>
|
||
</Card>
|
||
) : (
|
||
<Empty description="选择或创建一个团队" style={{ marginTop: 20 }} />
|
||
)}
|
||
|
||
<Modal
|
||
open={logic.createOpen}
|
||
title="新建团队"
|
||
onCancel={() => logic.setCreateOpen(false)}
|
||
footer={null}
|
||
width="95%"
|
||
destroyOnHidden
|
||
>
|
||
<Form layout="vertical" onFinish={logic.handleCreate}>
|
||
<Form.Item name="name" label="团队名称" rules={[{ required: true }]}>
|
||
<Input placeholder="如:AI 实验小组" autoFocus />
|
||
</Form.Item>
|
||
<Button type="primary" htmlType="submit" block>
|
||
创建
|
||
</Button>
|
||
</Form>
|
||
</Modal>
|
||
|
||
<Modal open={logic.renameOpen} title="重命名团队" onCancel={() => logic.setRenameOpen(false)} footer={null} width="95%" destroyOnHidden>
|
||
<Form layout="vertical" onFinish={logic.handleRename} initialValues={{ name: active?.name }}>
|
||
<Form.Item name="name" label="新团队名称" rules={[{ required: true }]}>
|
||
<Input placeholder="输入新的团队名称" autoFocus />
|
||
</Form.Item>
|
||
<Button type="primary" htmlType="submit" block>
|
||
确定
|
||
</Button>
|
||
</Form>
|
||
</Modal>
|
||
|
||
<Modal open={logic.addMemberOpen} title={`向 ${active?.name} 添加成员`} onCancel={() => logic.setAddMemberOpen(false)} footer={null} width="95%" destroyOnHidden>
|
||
<Form layout="vertical" onFinish={logic.handleAddMember}>
|
||
<Form.Item name="phone" label="成员手机号" rules={[{ required: true, message: '请输入手机号' }]}>
|
||
<Input placeholder="输入成员绑定的手机号" autoFocus />
|
||
</Form.Item>
|
||
<Button type="primary" htmlType="submit" block>
|
||
添加
|
||
</Button>
|
||
</Form>
|
||
</Modal>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|