1、后台/teams需要可以设置管理人,后台只给这个管理人分配积分,然后前台管理员自己分配积分
2、前台判断用户是管理人,左下角显示团队管理 3、团队管理可以看到团队的人员、分配人员积分、人员的积分情况的功能 4、团队管理还可以邀请用户,比如生成个链接,未注册需要注册绑定团队,已注册用户访问弹窗是否加入这个团队,然后都需要管理同意才可以加入团队
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { Button, Card, Form, Input, InputNumber, message, Modal, Popconfirm, Select, Space, Table, Tag, Typography } from 'antd';
|
||||
import { DeleteOutlined, EditOutlined, PlusOutlined, ReloadOutlined, SearchOutlined, TeamOutlined } from '@ant-design/icons';
|
||||
import { deleteAdminTeam, getAdminTeams, saveAdminTeam } from '../api';
|
||||
import type { AdminTeam } from '../types';
|
||||
import { DeleteOutlined, EditOutlined, PlusOutlined, ReloadOutlined, SearchOutlined, SettingOutlined, TeamOutlined, UserOutlined } from '@ant-design/icons';
|
||||
import { deleteAdminTeam, getAdminTeams, getTeamMembersForAdmin, saveAdminTeam, setTeamManager } from '../api';
|
||||
import type { AdminTeam, AdminUser } from '../types';
|
||||
import { formatDate } from '../utils/formatDate';
|
||||
|
||||
const statusOptions = [
|
||||
@@ -34,6 +34,12 @@ const AdminTeams: React.FC = () => {
|
||||
const [modal, setModal] = useState<{ open: boolean; item: AdminTeam | null }>({ open: false, item: null });
|
||||
const [form] = Form.useForm();
|
||||
|
||||
// 管理人弹窗状态
|
||||
const [managerModal, setManagerModal] = useState<{ open: boolean; team: AdminTeam | null }>({ open: false, team: null });
|
||||
const [members, setMembers] = useState<AdminUser[]>([]);
|
||||
const [managerLoading, setManagerLoading] = useState(false);
|
||||
const [selectedManagerId, setSelectedManagerId] = useState<string | null>(null);
|
||||
|
||||
const query = useMemo(() => ({
|
||||
page,
|
||||
pageSize,
|
||||
@@ -107,6 +113,36 @@ const AdminTeams: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const openManagerModal = async (team: AdminTeam) => {
|
||||
setManagerModal({ open: true, team });
|
||||
setSelectedManagerId(team.managerId || null);
|
||||
setManagerLoading(true);
|
||||
try {
|
||||
const res = await getTeamMembersForAdmin(team.id);
|
||||
setMembers(res.items || []);
|
||||
} catch (e: any) {
|
||||
message.error(e?.message || '加载成员失败');
|
||||
setMembers([]);
|
||||
} finally {
|
||||
setManagerLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSetManager = async () => {
|
||||
if (!managerModal.team) return;
|
||||
try {
|
||||
setManagerLoading(true);
|
||||
await setTeamManager(managerModal.team.id, selectedManagerId);
|
||||
message.success(selectedManagerId ? '已设置管理人' : '已取消管理人');
|
||||
setManagerModal({ open: false, team: null });
|
||||
load();
|
||||
} catch (e: any) {
|
||||
message.error(e?.message || '设置失败');
|
||||
} finally {
|
||||
setManagerLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '团队名称',
|
||||
@@ -136,6 +172,16 @@ const AdminTeams: React.FC = () => {
|
||||
width: 100,
|
||||
render: (v: number) => <Typography.Text strong>{Number(v || 0).toLocaleString()}</Typography.Text>,
|
||||
},
|
||||
{
|
||||
title: '管理人',
|
||||
key: 'manager',
|
||||
width: 140,
|
||||
render: (_: any, r: AdminTeam) => (
|
||||
<Typography.Text style={{ fontSize: 13 }}>
|
||||
{r.managerName || <span style={{ color: '#94a3b8' }}>未设置</span>}
|
||||
</Typography.Text>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
dataIndex: 'sortOrder',
|
||||
@@ -161,6 +207,7 @@ const AdminTeams: React.FC = () => {
|
||||
fixed: 'right' as const,
|
||||
render: (_: any, r: AdminTeam) => (
|
||||
<Space size={4}>
|
||||
<Button type="link" size="small" icon={<SettingOutlined />} onClick={() => openManagerModal(r)}>管理人</Button>
|
||||
<Button type="link" size="small" icon={<EditOutlined />} onClick={() => openEdit(r)}>编辑</Button>
|
||||
<Popconfirm
|
||||
title="确定删除该团队?"
|
||||
@@ -239,6 +286,41 @@ const AdminTeams: React.FC = () => {
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
{/* 设置管理人弹窗 */}
|
||||
<Modal
|
||||
title={<Space><UserOutlined />设置团队管理人</Space>}
|
||||
open={managerModal.open}
|
||||
confirmLoading={managerLoading}
|
||||
onOk={handleSetManager}
|
||||
onCancel={() => { setManagerModal({ open: false, team: null }); setSelectedManagerId(null); }}
|
||||
okText="保存"
|
||||
cancelText="取消"
|
||||
width={480}
|
||||
>
|
||||
<div style={{ marginTop: 16 }}>
|
||||
<Typography.Text style={{ fontSize: 13, color: '#64748b', display: 'block', marginBottom: 8 }}>
|
||||
团队:{managerModal.team?.name || '-'}
|
||||
</Typography.Text>
|
||||
<Typography.Text style={{ fontSize: 13, color: '#64748b', display: 'block', marginBottom: 12 }}>
|
||||
选择该团队的一名成员作为管理人。管理人可在前台管理团队成员和分配积分。
|
||||
</Typography.Text>
|
||||
<Select
|
||||
style={{ width: '100%' }}
|
||||
placeholder="选择管理人(可清空取消)"
|
||||
value={selectedManagerId}
|
||||
onChange={(v) => setSelectedManagerId(v || null)}
|
||||
allowClear
|
||||
loading={managerLoading}
|
||||
optionFilterProp="label"
|
||||
options={members.map((m) => ({
|
||||
value: m.id,
|
||||
label: `${m.username}${m.phone ? ` (${m.phone})` : ''}`,
|
||||
}))}
|
||||
showSearch
|
||||
/>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user