存进度
This commit is contained in:
@@ -1,32 +1,46 @@
|
||||
// 用户详情类型
|
||||
export interface TrafficPoolUserDetail {
|
||||
id: number;
|
||||
nickname: string;
|
||||
avatar: string;
|
||||
wechatId: string;
|
||||
status: number | string;
|
||||
addTime: string;
|
||||
lastInteraction: string;
|
||||
deviceName?: string;
|
||||
wechatAccountName?: string;
|
||||
customerServiceName?: string;
|
||||
poolNames?: string[];
|
||||
rfmScore?: {
|
||||
recency: number;
|
||||
frequency: number;
|
||||
monetary: number;
|
||||
segment?: string;
|
||||
userInfo: {
|
||||
wechatId: string;
|
||||
weight: number | null;
|
||||
activity: {
|
||||
totalMsgCount: number;
|
||||
sevenDayMsgCount: number;
|
||||
thirtyDayMsgCount: number;
|
||||
yesterdayMsgCount: number;
|
||||
};
|
||||
friendShip: {
|
||||
maleFriend: number;
|
||||
groupNumber: number;
|
||||
totalFriend: number;
|
||||
femaleFriend: number;
|
||||
unknowFriend: number;
|
||||
};
|
||||
nickname: string;
|
||||
alias: string;
|
||||
avatar: string;
|
||||
gender: number; // 0-未知, 1-男, 2-女
|
||||
};
|
||||
totalSpent?: number;
|
||||
interactionCount?: number;
|
||||
conversionRate?: number;
|
||||
tags?: string[];
|
||||
packages?: string[];
|
||||
interactions?: Array<{
|
||||
id: string;
|
||||
type: string;
|
||||
content: string;
|
||||
timestamp: string;
|
||||
value?: number;
|
||||
accountAge: string;
|
||||
activityLevel: {
|
||||
allTimes: number;
|
||||
dayTimes: number;
|
||||
};
|
||||
accountWeight: {
|
||||
ageWeight: number;
|
||||
activityWeigth: number;
|
||||
restrictWeight: number;
|
||||
realNameWeight: number;
|
||||
scope: number;
|
||||
};
|
||||
statistics: {
|
||||
todayAdded: number;
|
||||
addLimit: number;
|
||||
};
|
||||
restrictions: Array<{
|
||||
id: number;
|
||||
date: number | null;
|
||||
level: number; // 1-轻微, 2-中等, 3-严重
|
||||
reason: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,13 @@
|
||||
.wechatId {
|
||||
font-size: 14px;
|
||||
color: #1677ff;
|
||||
margin-bottom: 4px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.alias {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
margin-bottom: 8px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
@@ -51,7 +58,13 @@
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.packageTag {
|
||||
.genderTag {
|
||||
font-size: 12px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.weightTag {
|
||||
font-size: 12px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 12px;
|
||||
@@ -113,30 +126,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.rfmGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 16px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.rfmItem {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.rfmValue {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.rfmLabel {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.statsGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
@@ -161,43 +150,32 @@
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.interactionContent {
|
||||
.restrictionTitle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.purchaseValue {
|
||||
color: #22c55e;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tagsContainer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-bottom: 16px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.userTag {
|
||||
font-size: 12px;
|
||||
padding: 4px 12px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.addTagButton {
|
||||
margin: 0 16px 16px;
|
||||
height: 40px;
|
||||
.restrictionLevel {
|
||||
font-size: 10px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
|
||||
:global(.antd-mobile-icon) {
|
||||
margin-right: 4px;
|
||||
}
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.restrictionContent {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
line-height: 1.4;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.emptyState {
|
||||
@@ -239,19 +217,14 @@
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.alias {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.tabContent {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.rfmGrid {
|
||||
gap: 12px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.rfmValue {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.statsGrid {
|
||||
gap: 12px;
|
||||
padding: 12px;
|
||||
@@ -261,14 +234,12 @@
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tagsContainer {
|
||||
padding: 12px;
|
||||
.restrictionTitle {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.addTagButton {
|
||||
margin: 0 12px 12px;
|
||||
height: 36px;
|
||||
font-size: 13px;
|
||||
.restrictionContent {
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,16 +264,27 @@
|
||||
color: #4a9eff;
|
||||
}
|
||||
|
||||
.alias {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.infoCard :global(.adm-card-header) {
|
||||
color: #fff;
|
||||
border-bottom-color: #3a3a3a;
|
||||
}
|
||||
|
||||
.rfmLabel,
|
||||
.statLabel {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.restrictionTitle {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.restrictionContent {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.emptyText {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,9 @@ import { Card, Button, Avatar, Tag, Tabs, List, Badge } from "antd-mobile";
|
||||
import {
|
||||
UserOutlined,
|
||||
MessageOutlined,
|
||||
ShoppingOutlined,
|
||||
EyeOutlined,
|
||||
TeamOutlined,
|
||||
ClockCircleOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
PlusOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import Layout from "@/components/Layout/Layout";
|
||||
@@ -28,46 +29,72 @@ const TrafficPoolDetail: React.FC = () => {
|
||||
.finally(() => setLoading(false));
|
||||
}, [id]);
|
||||
|
||||
const getInteractionIcon = (type: string) => {
|
||||
switch (type) {
|
||||
case "click":
|
||||
return <UserOutlined style={{ color: "#ff6b35" }} />;
|
||||
case "message":
|
||||
return <MessageOutlined style={{ color: "#3b82f6" }} />;
|
||||
case "purchase":
|
||||
return <ShoppingOutlined style={{ color: "#22c55e" }} />;
|
||||
case "view":
|
||||
return <EyeOutlined style={{ color: "#8b5cf6" }} />;
|
||||
const getGenderText = (gender: number) => {
|
||||
switch (gender) {
|
||||
case 1:
|
||||
return "男";
|
||||
case 2:
|
||||
return "女";
|
||||
default:
|
||||
return <UserOutlined />;
|
||||
return "未知";
|
||||
}
|
||||
};
|
||||
|
||||
const getInteractionTitle = (type: string) => {
|
||||
switch (type) {
|
||||
case "click":
|
||||
return "点击行为";
|
||||
case "message":
|
||||
return "消息互动";
|
||||
case "purchase":
|
||||
return "购买行为";
|
||||
case "view":
|
||||
return "页面浏览";
|
||||
const getGenderColor = (gender: number) => {
|
||||
switch (gender) {
|
||||
case 1:
|
||||
return "#1677ff";
|
||||
case 2:
|
||||
return "#eb2f96";
|
||||
default:
|
||||
return "未知行为";
|
||||
return "#999";
|
||||
}
|
||||
};
|
||||
|
||||
const getStatusText = (status: string | number) => {
|
||||
if (status === "failed" || status === 0) return "添加失败";
|
||||
if (status === "added" || status === 1) return "添加成功";
|
||||
return "未添加";
|
||||
const getRestrictionLevelText = (level: number) => {
|
||||
switch (level) {
|
||||
case 1:
|
||||
return "轻微";
|
||||
case 2:
|
||||
return "中等";
|
||||
case 3:
|
||||
return "严重";
|
||||
default:
|
||||
return "未知";
|
||||
}
|
||||
};
|
||||
|
||||
const getStatusColor = (status: string | number) => {
|
||||
if (status === "failed" || status === 0) return "danger";
|
||||
if (status === "added" || status === 1) return "success";
|
||||
return "default";
|
||||
const getRestrictionLevelColor = (level: number) => {
|
||||
switch (level) {
|
||||
case 1:
|
||||
return "warning";
|
||||
case 2:
|
||||
return "danger";
|
||||
case 3:
|
||||
return "danger";
|
||||
default:
|
||||
return "default";
|
||||
}
|
||||
};
|
||||
|
||||
const formatDate = (timestamp: number | null) => {
|
||||
if (!timestamp) return "--";
|
||||
try {
|
||||
const date = new Date(timestamp * 1000);
|
||||
return date.toLocaleDateString("zh-CN");
|
||||
} catch (error) {
|
||||
return "--";
|
||||
}
|
||||
};
|
||||
|
||||
const formatAccountAge = (dateString: string) => {
|
||||
if (!dateString) return "--";
|
||||
try {
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleDateString("zh-CN");
|
||||
} catch (error) {
|
||||
return dateString;
|
||||
}
|
||||
};
|
||||
|
||||
if (!user) {
|
||||
@@ -87,24 +114,32 @@ const TrafficPoolDetail: React.FC = () => {
|
||||
<Card className={styles.userCard}>
|
||||
<div className={styles.userInfo}>
|
||||
<Avatar
|
||||
src={user.avatar}
|
||||
src={user.userInfo.avatar}
|
||||
className={styles.avatar}
|
||||
fallback={<UserOutlined />}
|
||||
/>
|
||||
<div className={styles.userDetails}>
|
||||
<div className={styles.nickname}>{user.nickname}</div>
|
||||
<div className={styles.wechatId}>{user.wechatId}</div>
|
||||
<div className={styles.nickname}>{user.userInfo.nickname}</div>
|
||||
<div className={styles.wechatId}>{user.userInfo.wechatId}</div>
|
||||
<div className={styles.alias}>别名:{user.userInfo.alias}</div>
|
||||
<div className={styles.tags}>
|
||||
{user.packages?.map((pkg) => (
|
||||
<Tag
|
||||
color="primary"
|
||||
fill="outline"
|
||||
className={styles.genderTag}
|
||||
style={{ color: getGenderColor(user.userInfo.gender) }}
|
||||
>
|
||||
{getGenderText(user.userInfo.gender)}
|
||||
</Tag>
|
||||
{user.userInfo.weight && (
|
||||
<Tag
|
||||
key={pkg}
|
||||
color="primary"
|
||||
color="success"
|
||||
fill="outline"
|
||||
className={styles.packageTag}
|
||||
className={styles.weightTag}
|
||||
>
|
||||
{pkg}
|
||||
权重: {user.userInfo.weight}
|
||||
</Tag>
|
||||
))}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -114,166 +149,224 @@ const TrafficPoolDetail: React.FC = () => {
|
||||
<Tabs className={styles.tabs}>
|
||||
<Tabs.Tab title="基本信息" key="base">
|
||||
<div className={styles.tabContent}>
|
||||
{/* 关键信息 */}
|
||||
<Card title="关键信息" className={styles.infoCard}>
|
||||
{/* 账户信息 */}
|
||||
<Card title="账户信息" className={styles.infoCard}>
|
||||
<List>
|
||||
<List.Item extra={user.deviceName || "--"}>设备</List.Item>
|
||||
<List.Item extra={user.wechatAccountName || "--"}>
|
||||
微信号
|
||||
<List.Item extra={formatAccountAge(user.accountAge)}>
|
||||
注册时间
|
||||
</List.Item>
|
||||
<List.Item extra={user.customerServiceName || "--"}>
|
||||
客服
|
||||
<List.Item
|
||||
extra={`${user.statistics.todayAdded}/${user.statistics.addLimit}`}
|
||||
>
|
||||
今日添加
|
||||
</List.Item>
|
||||
<List.Item extra={user.addTime || "--"}>添加时间</List.Item>
|
||||
<List.Item extra={user.lastInteraction || "--"}>
|
||||
最近互动
|
||||
<List.Item extra={user.activityLevel.allTimes}>
|
||||
总消息数
|
||||
</List.Item>
|
||||
<List.Item extra={user.activityLevel.dayTimes}>
|
||||
今日消息
|
||||
</List.Item>
|
||||
</List>
|
||||
</Card>
|
||||
|
||||
{/* RFM评分 */}
|
||||
<Card title="RFM评分" className={styles.infoCard}>
|
||||
<div className={styles.rfmGrid}>
|
||||
<div className={styles.rfmItem}>
|
||||
{/* 好友统计 */}
|
||||
<Card title="好友统计" className={styles.infoCard}>
|
||||
<div className={styles.statsGrid}>
|
||||
<div className={styles.statItem}>
|
||||
<div
|
||||
className={styles.rfmValue}
|
||||
className={styles.statValue}
|
||||
style={{ color: "#1677ff" }}
|
||||
>
|
||||
{user.rfmScore?.recency ?? "-"}
|
||||
{user.userInfo.friendShip.totalFriend}
|
||||
</div>
|
||||
<div className={styles.rfmLabel}>最近性(R)</div>
|
||||
<div className={styles.statLabel}>总好友</div>
|
||||
</div>
|
||||
<div className={styles.rfmItem}>
|
||||
<div className={styles.statItem}>
|
||||
<div
|
||||
className={styles.rfmValue}
|
||||
style={{ color: "#52c41a" }}
|
||||
className={styles.statValue}
|
||||
style={{ color: "#1677ff" }}
|
||||
>
|
||||
{user.rfmScore?.frequency ?? "-"}
|
||||
{user.userInfo.friendShip.maleFriend}
|
||||
</div>
|
||||
<div className={styles.rfmLabel}>频率(F)</div>
|
||||
<div className={styles.statLabel}>男性好友</div>
|
||||
</div>
|
||||
<div className={styles.rfmItem}>
|
||||
<div className={styles.statItem}>
|
||||
<div
|
||||
className={styles.rfmValue}
|
||||
className={styles.statValue}
|
||||
style={{ color: "#eb2f96" }}
|
||||
>
|
||||
{user.rfmScore?.monetary ?? "-"}
|
||||
{user.userInfo.friendShip.femaleFriend}
|
||||
</div>
|
||||
<div className={styles.rfmLabel}>金额(M)</div>
|
||||
<div className={styles.statLabel}>女性好友</div>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<div className={styles.statValue} style={{ color: "#999" }}>
|
||||
{user.userInfo.friendShip.unknowFriend}
|
||||
</div>
|
||||
<div className={styles.statLabel}>未知性别</div>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<div
|
||||
className={styles.statValue}
|
||||
style={{ color: "#52c41a" }}
|
||||
>
|
||||
{user.userInfo.friendShip.groupNumber}
|
||||
</div>
|
||||
<div className={styles.statLabel}>群聊数量</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* 统计数据 */}
|
||||
<Card title="统计数据" className={styles.infoCard}>
|
||||
{/* 活跃度统计 */}
|
||||
<Card title="活跃度统计" className={styles.infoCard}>
|
||||
<div className={styles.statsGrid}>
|
||||
<div className={styles.statItem}>
|
||||
<div
|
||||
className={styles.statValue}
|
||||
style={{ color: "#52c41a" }}
|
||||
>
|
||||
¥{user.totalSpent ?? "-"}
|
||||
{user.userInfo.activity.totalMsgCount}
|
||||
</div>
|
||||
<div className={styles.statLabel}>总消费</div>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<div
|
||||
className={styles.statValue}
|
||||
style={{ color: "#1677ff" }}
|
||||
>
|
||||
{user.interactionCount ?? "-"}
|
||||
</div>
|
||||
<div className={styles.statLabel}>互动次数</div>
|
||||
<div className={styles.statLabel}>总消息数</div>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<div
|
||||
className={styles.statValue}
|
||||
style={{ color: "#faad14" }}
|
||||
>
|
||||
{user.conversionRate ?? "-"}
|
||||
{user.userInfo.activity.sevenDayMsgCount}
|
||||
</div>
|
||||
<div className={styles.statLabel}>转化率</div>
|
||||
<div className={styles.statLabel}>7天消息</div>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<div
|
||||
className={styles.statValue}
|
||||
style={{ color: "#ff4d4f" }}
|
||||
style={{ color: "#722ed1" }}
|
||||
>
|
||||
{getStatusText(user.status)}
|
||||
{user.userInfo.activity.thirtyDayMsgCount}
|
||||
</div>
|
||||
<div className={styles.statLabel}>添加状态</div>
|
||||
<div className={styles.statLabel}>30天消息</div>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<div
|
||||
className={styles.statValue}
|
||||
style={{ color: "#13c2c2" }}
|
||||
>
|
||||
{user.userInfo.activity.yesterdayMsgCount}
|
||||
</div>
|
||||
<div className={styles.statLabel}>昨日消息</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* 账户权重 */}
|
||||
<Card title="账户权重" className={styles.infoCard}>
|
||||
<div className={styles.statsGrid}>
|
||||
<div className={styles.statItem}>
|
||||
<div
|
||||
className={styles.statValue}
|
||||
style={{ color: "#1677ff" }}
|
||||
>
|
||||
{user.accountWeight.ageWeight}
|
||||
</div>
|
||||
<div className={styles.statLabel}>年龄权重</div>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<div
|
||||
className={styles.statValue}
|
||||
style={{ color: "#52c41a" }}
|
||||
>
|
||||
{user.accountWeight.activityWeigth}
|
||||
</div>
|
||||
<div className={styles.statLabel}>活跃权重</div>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<div
|
||||
className={styles.statValue}
|
||||
style={{ color: "#faad14" }}
|
||||
>
|
||||
{user.accountWeight.restrictWeight}
|
||||
</div>
|
||||
<div className={styles.statLabel}>限制权重</div>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<div
|
||||
className={styles.statValue}
|
||||
style={{ color: "#722ed1" }}
|
||||
>
|
||||
{user.accountWeight.realNameWeight}
|
||||
</div>
|
||||
<div className={styles.statLabel}>实名权重</div>
|
||||
</div>
|
||||
<div className={styles.statItem}>
|
||||
<div
|
||||
className={styles.statValue}
|
||||
style={{ color: "#13c2c2" }}
|
||||
>
|
||||
{user.accountWeight.scope}
|
||||
</div>
|
||||
<div className={styles.statLabel}>综合评分</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</Tabs.Tab>
|
||||
|
||||
<Tabs.Tab title="用户旅程" key="journey">
|
||||
<Tabs.Tab title="限制记录" key="restrictions">
|
||||
<div className={styles.tabContent}>
|
||||
<Card title="互动记录" className={styles.infoCard}>
|
||||
{user.interactions && user.interactions.length > 0 ? (
|
||||
<Card title="限制记录" className={styles.infoCard}>
|
||||
{user.restrictions && user.restrictions.length > 0 ? (
|
||||
<List>
|
||||
{user.interactions.slice(0, 4).map((interaction) => (
|
||||
{user.restrictions.map((restriction) => (
|
||||
<List.Item
|
||||
key={interaction.id}
|
||||
prefix={getInteractionIcon(interaction.type)}
|
||||
title={getInteractionTitle(interaction.type)}
|
||||
description={
|
||||
<div className={styles.interactionContent}>
|
||||
<span>{interaction.content}</span>
|
||||
{interaction.type === "purchase" &&
|
||||
interaction.value && (
|
||||
<span className={styles.purchaseValue}>
|
||||
¥{interaction.value}
|
||||
</span>
|
||||
key={restriction.id}
|
||||
prefix={
|
||||
<ExclamationCircleOutlined
|
||||
style={{ color: "#ff4d4f" }}
|
||||
/>
|
||||
}
|
||||
title={
|
||||
<div className={styles.restrictionTitle}>
|
||||
<span>{restriction.reason || "未知原因"}</span>
|
||||
<Tag
|
||||
color={getRestrictionLevelColor(
|
||||
restriction.level
|
||||
)}
|
||||
fill="outline"
|
||||
className={styles.restrictionLevel}
|
||||
>
|
||||
{getRestrictionLevelText(restriction.level)}
|
||||
</Tag>
|
||||
</div>
|
||||
}
|
||||
description={
|
||||
<div className={styles.restrictionContent}>
|
||||
<span>限制ID: {restriction.id}</span>
|
||||
{restriction.date && (
|
||||
<span>
|
||||
限制时间: {formatDate(restriction.date)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
extra={interaction.timestamp}
|
||||
/>
|
||||
))}
|
||||
</List>
|
||||
) : (
|
||||
<div className={styles.emptyState}>
|
||||
<div className={styles.emptyText}>暂无互动记录</div>
|
||||
<div className={styles.emptyText}>暂无限制记录</div>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
</div>
|
||||
</Tabs.Tab>
|
||||
|
||||
<Tabs.Tab title="用户标签" key="tags">
|
||||
<Tabs.Tab title="操作记录" key="actions">
|
||||
<div className={styles.tabContent}>
|
||||
<Card title="用户标签" className={styles.infoCard}>
|
||||
<div className={styles.tagsContainer}>
|
||||
{user.tags && user.tags.length > 0 ? (
|
||||
user.tags.map((tag) => (
|
||||
<Tag
|
||||
key={tag}
|
||||
color="primary"
|
||||
fill="outline"
|
||||
className={styles.userTag}
|
||||
>
|
||||
{tag}
|
||||
</Tag>
|
||||
))
|
||||
) : (
|
||||
<div className={styles.emptyText}>暂无标签</div>
|
||||
)}
|
||||
<Card title="操作记录" className={styles.infoCard}>
|
||||
<div className={styles.emptyState}>
|
||||
<div className={styles.emptyText}>暂无操作记录</div>
|
||||
</div>
|
||||
<Button
|
||||
block
|
||||
color="default"
|
||||
fill="outline"
|
||||
className={styles.addTagButton}
|
||||
onClick={() => {
|
||||
// TODO: 实现添加标签功能
|
||||
console.log("添加新标签");
|
||||
}}
|
||||
>
|
||||
<PlusOutlined />
|
||||
添加新标签
|
||||
</Button>
|
||||
</Card>
|
||||
</div>
|
||||
</Tabs.Tab>
|
||||
|
||||
Reference in New Issue
Block a user