refactor(contact-import): 重构通讯录导入任务类型定义和样式

- 将ContactImportTask相关类型统一为Allocation类型
- 优化详情页样式和布局
- 移除冗余样式和代码
This commit is contained in:
超级老白兔
2025-09-11 14:36:49 +08:00
parent b69ad40013
commit dc60dacb02
5 changed files with 215 additions and 89 deletions

View File

@@ -1,7 +1,5 @@
.container {
padding: 12px;
background-color: #f5f5f5;
min-height: 100vh;
}
.loading {
@@ -25,8 +23,7 @@
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
margin-bottom: 16px;
:global(.adm-card-body) {
padding: 16px;
}
@@ -61,8 +58,8 @@
.actions {
display: flex;
gap: 8px;
gap: 20px;
:global(.adm-button) {
flex: 1;
border-radius: 6px;
@@ -75,21 +72,21 @@
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
overflow: hidden;
:global(.adm-tabs-header) {
background: #fafafa;
border-bottom: 1px solid #f0f0f0;
}
:global(.adm-tabs-tab) {
font-size: 15px;
font-weight: 500;
&.adm-tabs-tab-active {
color: #1890ff;
}
}
:global(.adm-tabs-tab-line) {
background: #1890ff;
}
@@ -106,7 +103,7 @@
background: #fff;
border-radius: 8px;
border: 1px solid #f0f0f0;
:global(.adm-card-body) {
padding: 16px;
}
@@ -158,11 +155,11 @@
border-radius: 8px;
border: 1px solid #f0f0f0;
margin-bottom: 12px;
:global(.adm-list-item-content) {
padding: 16px;
}
&:last-child {
margin-bottom: 0;
}
@@ -201,12 +198,12 @@
display: flex;
align-items: center;
font-size: 13px;
.label {
min-width: 70px;
color: #666;
}
.value {
color: #333;
}
@@ -237,19 +234,19 @@
border-radius: 12px;
font-size: 12px;
padding: 2px 8px;
&.adm-tag-success {
background: #f6ffed;
border-color: #b7eb8f;
color: #52c41a;
}
&.adm-tag-danger {
background: #fff2f0;
border-color: #ffccc7;
color: #ff4d4f;
}
&.adm-tag-warning {
background: #fff7e6;
border-color: #ffd591;
@@ -267,47 +264,43 @@
// 响应式设计
@media (max-width: 480px) {
.container {
padding: 8px;
}
.taskName {
font-size: 16px;
}
.taskStatus {
font-size: 13px;
padding: 3px 10px;
}
.cardTitle {
font-size: 15px;
}
.infoItem {
font-size: 13px;
}
.label {
min-width: 70px;
}
.recordDevice {
font-size: 13px;
}
.recordTime {
font-size: 11px;
}
.recordDetail {
font-size: 12px;
.label {
min-width: 60px;
}
}
.recordError {
font-size: 12px;
padding: 6px 10px;
@@ -317,16 +310,16 @@
// 空状态样式
:global(.adm-empty) {
padding: 40px 20px;
.adm-empty-image {
width: 60px;
height: 60px;
opacity: 0.3;
}
.adm-empty-description {
color: #999;
font-size: 14px;
margin-top: 12px;
}
}
}

View File

@@ -21,10 +21,7 @@ import {
triggerImport,
toggleContactImportTask,
} from "../list/api";
import {
ContactImportTask,
ContactImportRecord,
} from "../list/data";
import { ContactImportTask, ContactImportRecord } from "../list/data";
import {
PlayCircleOutlined,
PauseCircleOutlined,
@@ -39,7 +36,7 @@ import style from "./index.module.scss";
const ContactImportDetail: React.FC = () => {
const navigate = useNavigate();
const { id } = useParams<{ id: string }>();
const [task, setTask] = useState<ContactImportTask | null>(null);
const [records, setRecords] = useState<ContactImportRecord[]>([]);
const [loading, setLoading] = useState(false);
@@ -51,7 +48,7 @@ const ContactImportDetail: React.FC = () => {
// 获取任务详情
const loadTaskDetail = async () => {
if (!id) return;
setLoading(true);
try {
const response = await fetchContactImportTaskDetail(id);
@@ -71,7 +68,7 @@ const ContactImportDetail: React.FC = () => {
// 获取导入记录
const loadRecords = async (pageNum: number = 1, reset: boolean = false) => {
if (!id) return;
setRecordsLoading(true);
try {
const response = await fetchImportRecords(id, pageNum, 20);
@@ -96,7 +93,7 @@ const ContactImportDetail: React.FC = () => {
// 切换任务状态
const handleToggleStatus = async () => {
if (!task) return;
try {
await toggleContactImportTask({
id: task.id,
@@ -118,7 +115,7 @@ const ContactImportDetail: React.FC = () => {
// 手动触发导入
const handleTriggerImport = async () => {
if (!task) return;
try {
await triggerImport(task.id);
Toast.show({
@@ -250,31 +247,20 @@ const ContactImportDetail: React.FC = () => {
return (
<Layout
header={
<NavCommon
left={
<Button
fill="none"
size="small"
onClick={() => navigate("/workspace/contact-import/list")}
>
</Button>
}
title="任务详情"
right={
<Button
fill="none"
size="small"
onClick={() => navigate(`/workspace/contact-import/form/${task.id}`)}
>
<EditOutlined />
</Button>
}
/>
}
>
<PullToRefresh onRefresh={handleRefresh}>
<div className={style.container}>
<>
<NavCommon
title="任务详情"
right={
<Button
color="primary"
onClick={() =>
navigate(`/workspace/contact-import/form/${task.id}`)
}
>
<EditOutlined />
</Button>
}
/>
{/* 任务操作栏 */}
<Card className={style.actionCard}>
<div className={style.taskHeader}>
@@ -290,14 +276,17 @@ const ContactImportDetail: React.FC = () => {
</div>
<div className={style.actions}>
<Button
size="small"
onClick={handleToggleStatus}
color={task.status === 1 ? "warning" : "primary"}
>
{task.status === 1 ? (
<><PauseCircleOutlined /> </>
<>
<PauseCircleOutlined />
</>
) : (
<><PlayCircleOutlined /> </>
<>
<PlayCircleOutlined />
</>
)}
</Button>
<Button
@@ -309,7 +298,11 @@ const ContactImportDetail: React.FC = () => {
</Button>
</div>
</Card>
</>
}
>
<PullToRefresh onRefresh={handleRefresh}>
<div className={style.container}>
{/* 标签页 */}
<Tabs
activeKey={activeTab}
@@ -328,7 +321,9 @@ const ContactImportDetail: React.FC = () => {
</div>
<div className={style.infoItem}>
<span className={style.label}>:</span>
<span className={style.value}>{task.deviceGroups?.length || 0}</span>
<span className={style.value}>
{task.deviceGroups?.length || 0}
</span>
</div>
<div className={style.infoItem}>
<span className={style.label}>:</span>
@@ -363,11 +358,15 @@ const ContactImportDetail: React.FC = () => {
</div>
<div className={style.infoItem}>
<span className={style.label}>:</span>
<span className={style.value}>{task.maxImportsPerDay}</span>
<span className={style.value}>
{task.maxImportsPerDay}
</span>
</div>
<div className={style.infoItem}>
<span className={style.label}>:</span>
<span className={style.value}>{task.importInterval}</span>
<span className={style.value}>
{task.importInterval}
</span>
</div>
</div>
</Card>
@@ -378,11 +377,15 @@ const ContactImportDetail: React.FC = () => {
<div className={style.infoList}>
<div className={style.infoItem}>
<span className={style.label}>:</span>
<span className={style.value}>{task.todayImportCount}</span>
<span className={style.value}>
{task.todayImportCount}
</span>
</div>
<div className={style.infoItem}>
<span className={style.label}>:</span>
<span className={style.value}>{task.totalImportCount}</span>
<span className={style.value}>
{task.totalImportCount}
</span>
</div>
<div className={style.infoItem}>
<span className={style.label}>:</span>
@@ -403,7 +406,7 @@ const ContactImportDetail: React.FC = () => {
<Empty description="暂无导入记录" />
) : (
<List className={style.recordList}>
{records.map((record) => (
{records.map(record => (
<List.Item key={record.id} className={style.recordItem}>
<div className={style.recordHeader}>
<div className={style.recordInfo}>
@@ -440,7 +443,7 @@ const ContactImportDetail: React.FC = () => {
))}
</List>
)}
<InfiniteScroll
loadMore={loadMoreRecords}
hasMore={hasMore}
@@ -461,4 +464,4 @@ const ContactImportDetail: React.FC = () => {
);
};
export default ContactImportDetail;
export default ContactImportDetail;

View File

@@ -1,6 +1,6 @@
import request from "@/api/request";
import {
ContactImportTask,
Allocation,
CreateContactImportTaskData,
UpdateContactImportTaskData,
ContactImportRecord,
@@ -21,16 +21,12 @@ export function fetchContactImportTaskDetail(id: number) {
}
// 创建通讯录导入任务
export function createContactImportTask(
data: CreateContactImportTaskData,
): Promise<any> {
export function createContactImportTask(data: Allocation): Promise<any> {
return request("/v1/workbench/create", { ...data, type: 6 }, "POST");
}
// 更新通讯录导入任务
export function updateContactImportTask(
data: UpdateContactImportTaskData,
): Promise<any> {
export function updateContactImportTask(data: Allocation): Promise<any> {
return request("/v1/workbench/update", { ...data, type: 6 }, "POST");
}

View File

@@ -35,3 +35,134 @@ export interface Allocation {
endTime?: string | null;
[key: string]: any;
}
// 通讯录导入任务状态
export type ContactImportTaskStatus = 1 | 2; // 1: 开启, 2: 关闭
// 设备组信息
export interface DeviceGroup {
id: string;
name: string;
deviceCount: number;
status: "online" | "offline";
lastActive: string;
}
// 通讯录导入记录
export interface ContactImportRecord {
id: string;
workbenchId: string;
wechatAccountId: string;
deviceId: string;
num: number;
clientId: string;
remarkType: string;
remarkValue: string;
startTime: string;
endTime: string;
createTime: string;
operatorName: string;
operatorAvatar: string;
deviceName: string;
importStatus: "success" | "failed" | "pending";
errorMessage?: string;
}
// 通讯录导入任务配置
export interface ContactImportTaskConfig {
id: number;
workbenchId: number;
devices: number[];
pools: number[];
num: number;
clearContact: number;
remarkType: number;
remark: string;
startTime: string;
endTime: string;
createTime: string;
}
// 通讯录导入任务
export interface ContactImportTask {
id: number;
companyId: number;
name: string;
type: number;
status: ContactImportTaskStatus;
autoStart: number;
userId: number;
createTime: string;
updateTime: string;
config: ContactImportTaskConfig;
creatorName: string;
auto_like: any;
moments_sync: any;
traffic_config: any;
group_push: any;
group_create: any;
// 计算属性,用于向后兼容
deviceGroups?: string[];
todayImportCount?: number;
totalImportCount?: number;
maxImportsPerDay?: number;
importInterval?: number;
}
// 创建通讯录导入任务数据
export interface CreateContactImportTaskData {
name: string;
type: number;
config: {
devices: number[];
pools: number[];
num: number;
clearContact: number;
remarkType: number;
remark: string;
startTime: string;
endTime: string;
};
}
// 更新通讯录导入任务数据
export interface UpdateContactImportTaskData
extends CreateContactImportTaskData {
id: number;
}
// 任务配置
export interface TaskConfig {
deviceGroups: string[];
num: number;
clientId: string;
remarkType: string;
remarkValue: string;
startTime: string;
endTime: string;
maxImportsPerDay: number;
importInterval: number;
}
// API响应
export interface ApiResponse<T = any> {
code: number;
msg: string;
data: T;
}
// 分页响应
export interface PaginatedResponse<T> {
list: T[];
total: number;
page: number;
limit: number;
}
// 统计数据
export interface ImportStats {
totalTasks: number;
activeTasks: number;
todayImports: number;
totalImports: number;
successRate: number;
}

View File

@@ -135,10 +135,13 @@ const ContactImportForm: React.FC = () => {
};
if (isEdit && id) {
await updateContactImportTask({ ...submitData, id: Number(id) });
await updateContactImportTask({
...submitData,
id: Number(id),
} as Allocation);
message.success("更新成功");
} else {
await createContactImportTask(submitData);
await createContactImportTask(submitData as Allocation);
message.success("创建成功");
}