feat: 本次提交更新内容如下

样式调整
This commit is contained in:
笔记本里的永平
2025-07-21 18:18:45 +08:00
parent 340bd3e2f5
commit 0658292354
12 changed files with 1070 additions and 69 deletions

View File

@@ -82,13 +82,12 @@ const Scene: React.FC = () => {
<Layout
header={
<NavBar back={null} style={{ background: "#fff" }}>
<div className={style["nav-title"]}></div>
<div className="nav-title"></div>
<Button
size="small"
color="primary"
onClick={handleNewPlan}
className={style["new-plan-btn"]}
style={{ marginLeft: "auto" }}
className="new-plan-btn"
>
<PlusOutlined />
</Button>
@@ -113,21 +112,19 @@ const Scene: React.FC = () => {
<NavBar
back={null}
style={{ background: "#fff" }}
left={<div className={style["nav-title"]}></div>}
left={<div className="nav-title"></div>}
right={
<Button
size="small"
color="primary"
onClick={handleNewPlan}
className={style["new-plan-btn"]}
style={{ marginLeft: "auto" }}
className="new-plan-btn"
>
<PlusOutlined />
</Button>
}
></NavBar>
}
footer={<MeauMobile />}
>
<div className={style["scene-page"]}>
<div className={style["scenarios-grid"]}>

View File

@@ -2,18 +2,6 @@
padding:0 16px;
}
.nav-title {
font-size: 18px;
font-weight: 600;
color: #333;
}
.new-plan-btn {
font-size: 14px;
height: 32px;
padding: 0 12px;
}
.loading {
display: flex;
flex-direction: column;

View File

@@ -356,8 +356,8 @@ const ScenarioList: React.FC = () => {
back={null}
style={{ background: "#fff" }}
left={
<div className={style["nav-title"]}>
<span style={{ verticalAlign: "middle" }}>
<div className="nav-title">
<span className="nav-back-btn">
<LeftOutline onClick={() => navigate(-1)} fontSize={24} />
</span>
{scenarioName}
@@ -368,7 +368,7 @@ const ScenarioList: React.FC = () => {
size="small"
color="primary"
onClick={handleCreateNewPlan}
className={style["new-plan-btn"]}
className="new-plan-btn"
>
<PlusOutlined />
</Button>

View File

@@ -248,41 +248,36 @@ const NewPlan: React.FC = () => {
return (
<Layout
header={
<NavBar
back={null}
style={{ background: "#fff" }}
left={
<div className={style["nav-title"]}>
{isEdit ? "编辑计划" : "新建计划"}
</div>
}
right={
<Button
size="small"
onClick={() => navigate(-1)}
className={style["back-btn"]}
>
<LeftOutline />
</Button>
}
/>
<>
<NavBar
back={null}
style={{ background: "#fff" }}
left={
<div className="nav-title">
<span className="nav-back-btn">
<LeftOutline onClick={() => navigate(-1)} fontSize={24} />
</span>
{isEdit ? "编辑计划" : "新建计划"}
</div>
}
/>
{/* 步骤指示器 */}
<div className={style["steps-container"]}>
<Steps current={currentStep - 1}>
{steps.map((step) => (
<Steps.Step
key={step.id}
title={step.title}
description={step.subtitle}
/>
))}
</Steps>
</div>
</>
}
footer={<MeauMobile />}
>
<div className={style["new-plan-page"]}>
{/* 步骤指示器 */}
<div className={style["steps-container"]}>
<Steps current={currentStep - 1}>
{steps.map((step) => (
<Steps.Step
key={step.id}
title={step.title}
description={step.subtitle}
/>
))}
</Steps>
</div>
{/* 步骤内容 */}
<div className={style["step-content"]}>{renderStepContent()}</div>
</div>

View File

@@ -1,6 +1,4 @@
.new-plan-page {
background: #f5f5f5;
min-height: 100vh;
}
.nav-title {
@@ -31,10 +29,8 @@
}
.steps-container {
background: white;
padding: 20px 16px;
background: #ffffff;
margin-bottom: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.step-content {

View File

@@ -1,3 +1,149 @@
.autoGroupDetail {
// 这里写详情页样式
padding: 16px 0 80px 0;
background: #f7f8fa;
min-height: 100vh;
}
.headerBar {
display: flex;
align-items: center;
height: 48px;
background: #fff;
border-bottom: 1px solid #f0f0f0;
font-size: 18px;
font-weight: 600;
padding: 0 16px;
}
.title {
font-size: 18px;
font-weight: 600;
color: #222;
flex: 1;
text-align: center;
}
.infoCard {
margin-bottom: 16px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.03);
border: none;
background: #fff;
padding: 16px;
}
.infoGrid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
}
.infoTitle {
font-size: 14px;
font-weight: 500;
color: #1677ff;
margin-bottom: 4px;
}
.infoItem {
font-size: 13px;
color: #444;
margin-bottom: 2px;
}
.progressSection {
margin-top: 16px;
}
.progressCard {
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.03);
border: none;
background: #fff;
padding: 16px;
margin-bottom: 16px;
}
.progressHeader {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 15px;
font-weight: 500;
margin-bottom: 8px;
}
.groupList {
margin-top: 8px;
display: flex;
flex-direction: column;
gap: 12px;
}
.groupCard {
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.03);
border: none;
background: #fff;
padding: 12px 16px;
}
.groupHeader {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 15px;
font-weight: 500;
margin-bottom: 8px;
}
.memberGrid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 6px;
margin-top: 8px;
}
.memberItem {
background: #f5f7fa;
border-radius: 8px;
padding: 4px 8px;
font-size: 13px;
color: #333;
display: flex;
align-items: center;
}
.warnText {
color: #faad14;
font-size: 13px;
margin-top: 8px;
display: flex;
align-items: center;
}
.successText {
color: #389e0d;
font-size: 13px;
margin-top: 8px;
display: flex;
align-items: center;
}
.successAlert {
color: #389e0d;
background: #f6ffed;
border-radius: 8px;
padding: 8px 0;
text-align: center;
margin-top: 12px;
font-size: 14px;
}
.emptyCard {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px 0;
background: #fff;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.03);
margin-top: 32px;
}
.emptyTitle {
font-size: 16px;
color: #888;
margin: 12px 0 4px 0;
}
.emptyDesc {
font-size: 13px;
color: #bbb;
margin-bottom: 16px;
}

View File

@@ -1,7 +1,384 @@
import React from "react";
import React, { useEffect, useState } from "react";
import { useParams, useNavigate } from "react-router-dom";
import {
Card,
Button,
Toast,
ProgressBar,
Tag,
SpinLoading,
} from "antd-mobile";
import { TeamOutline, LeftOutline } from "antd-mobile-icons";
import { AlertOutlined } from "@ant-design/icons";
import Layout from "@/components/Layout/Layout";
import MeauMobile from "@/components/MeauMobile/MeauMoible";
import style from "./index.module.scss";
interface GroupMember {
id: string;
nickname: string;
wechatId: string;
tags: string[];
}
interface Group {
id: string;
members: GroupMember[];
}
interface GroupTaskDetail {
id: string;
name: string;
status: "preparing" | "creating" | "completed" | "paused";
totalGroups: number;
currentGroupIndex: number;
groups: Group[];
createTime: string;
lastUpdateTime: string;
creator: string;
deviceCount: number;
targetFriends: number;
groupSize: { min: number; max: number };
timeRange: { start: string; end: string };
targetTags: string[];
groupNameTemplate: string;
groupDescription: string;
}
const mockTaskDetail: GroupTaskDetail = {
id: "1",
name: "VIP客户建群",
status: "creating",
totalGroups: 5,
currentGroupIndex: 2,
groups: Array.from({ length: 5 }).map((_, index) => ({
id: `group-${index}`,
members: Array.from({ length: Math.floor(Math.random() * 10) + 30 }).map(
(_, mIndex) => ({
id: `member-${index}-${mIndex}`,
nickname: `用户${mIndex + 1}`,
wechatId: `wx_${mIndex}`,
tags: [`标签${(mIndex % 3) + 1}`],
})
),
})),
createTime: "2024-11-20 19:04:14",
lastUpdateTime: "2025-02-06 13:12:35",
creator: "admin",
deviceCount: 2,
targetFriends: 156,
groupSize: { min: 20, max: 50 },
timeRange: { start: "09:00", end: "21:00" },
targetTags: ["VIP客户", "高价值"],
groupNameTemplate: "VIP客户交流群{序号}",
groupDescription: "VIP客户专属交流群提供优质服务",
};
const GroupPreview: React.FC<{
groupIndex: number;
members: GroupMember[];
isCreating: boolean;
isCompleted: boolean;
onRetry?: () => void;
}> = ({ groupIndex, members, isCreating, isCompleted, onRetry }) => {
const [expanded, setExpanded] = useState(false);
const targetSize = 38;
return (
<Card className={style.groupCard}>
<div className={style.groupHeader}>
<div>
{groupIndex + 1}
<Tag
color={isCompleted ? "success" : isCreating ? "warning" : "default"}
style={{ marginLeft: 8 }}
>
{isCompleted ? "已完成" : isCreating ? "创建中" : "等待中"}
</Tag>
</div>
<div style={{ color: "#888", fontSize: 12 }}>
<TeamOutline style={{ marginRight: 4 }} />
{members.length}/{targetSize}
</div>
</div>
{isCreating && !isCompleted && (
<ProgressBar
percent={Math.round((members.length / targetSize) * 100)}
style={{ margin: "8px 0" }}
/>
)}
{expanded ? (
<>
<div className={style.memberGrid}>
{members.map((member) => (
<div key={member.id} className={style.memberItem}>
<span>{member.nickname}</span>
{member.tags.length > 0 && (
<Tag color="primary" style={{ marginLeft: 4 }}>
{member.tags[0]}
</Tag>
)}
</div>
))}
</div>
<Button
size="mini"
fill="none"
block
onClick={() => setExpanded(false)}
style={{ marginTop: 8 }}
>
</Button>
</>
) : (
<Button
size="mini"
fill="none"
block
onClick={() => setExpanded(true)}
style={{ marginTop: 8 }}
>
({members.length})
</Button>
)}
{!isCompleted && members.length < targetSize && (
<div className={style.warnText}>
<AlertOutlined style={{ marginRight: 4 }} />
{targetSize}
{onRetry && (
<Button
size="mini"
fill="none"
color="primary"
style={{ marginLeft: 8 }}
onClick={onRetry}
>
</Button>
)}
</div>
)}
{isCompleted && <div className={style.successText}></div>}
</Card>
);
};
const GroupCreationProgress: React.FC<{
taskDetail: GroupTaskDetail;
onComplete: () => void;
}> = ({ taskDetail, onComplete }) => {
const [groups, setGroups] = useState<Group[]>(taskDetail.groups);
const [currentGroupIndex, setCurrentGroupIndex] = useState(
taskDetail.currentGroupIndex
);
const [status, setStatus] = useState<GroupTaskDetail["status"]>(
taskDetail.status
);
useEffect(() => {
if (status === "creating" && currentGroupIndex < groups.length) {
const timer = setTimeout(() => {
if (currentGroupIndex === groups.length - 1) {
setStatus("completed");
onComplete();
} else {
setCurrentGroupIndex((prev) => prev + 1);
}
}, 3000);
return () => clearTimeout(timer);
}
}, [status, currentGroupIndex, groups.length, onComplete]);
const handleRetryGroup = (groupIndex: number) => {
setGroups((prev) =>
prev.map((group, index) => {
if (index === groupIndex) {
return {
...group,
members: [
...group.members,
{
id: `retry-member-${Date.now()}`,
nickname: `补充用户${group.members.length + 1}`,
wechatId: `wx_retry_${Date.now()}`,
tags: ["新加入"],
},
],
};
}
return group;
})
);
};
return (
<div className={style.progressSection}>
<Card className={style.progressCard}>
<div className={style.progressHeader}>
<div>
<Tag
color={
status === "completed"
? "success"
: status === "creating"
? "warning"
: "default"
}
style={{ marginLeft: 8 }}
>
{status === "preparing"
? "准备中"
: status === "creating"
? "创建中"
: "已完成"}
</Tag>
</div>
<div style={{ color: "#888", fontSize: 12 }}>
{currentGroupIndex + 1}/{groups.length}
</div>
</div>
<ProgressBar
percent={Math.round(((currentGroupIndex + 1) / groups.length) * 100)}
style={{ marginTop: 8 }}
/>
</Card>
<div className={style.groupList}>
{groups.map((group, index) => (
<GroupPreview
key={group.id}
groupIndex={index}
members={group.members}
isCreating={status === "creating" && index === currentGroupIndex}
isCompleted={status === "completed" || index < currentGroupIndex}
onRetry={() => handleRetryGroup(index)}
/>
))}
</div>
{status === "completed" && (
<div className={style.successAlert}></div>
)}
</div>
);
};
const AutoGroupDetail: React.FC = () => {
return <div></div>;
const { id } = useParams();
const navigate = useNavigate();
const [loading, setLoading] = useState(true);
const [taskDetail, setTaskDetail] = useState<GroupTaskDetail | null>(null);
useEffect(() => {
setLoading(true);
setTimeout(() => {
setTaskDetail(mockTaskDetail);
setLoading(false);
}, 800);
}, [id]);
const handleComplete = () => {
Toast.show({ content: "所有群组已创建完成" });
};
if (loading) {
return (
<Layout
header={
<div className={style.headerBar}>
<Button fill="none" size="small" onClick={() => navigate(-1)}>
<LeftOutline />
</Button>
<div className={style.title}></div>
</div>
}
footer={<MeauMobile />}
loading={true}
>
<div style={{ minHeight: 300 }} />
</Layout>
);
}
if (!taskDetail) {
return (
<Layout
header={
<div className={style.headerBar}>
<Button fill="none" size="small" onClick={() => navigate(-1)}>
<LeftOutline />
</Button>
<div className={style.title}></div>
</div>
}
footer={<MeauMobile />}
>
<Card className={style.emptyCard}>
<AlertOutlined style={{ fontSize: 48, color: "#ccc" }} />
<div className={style.emptyTitle}></div>
<div className={style.emptyDesc}>ID是否正确</div>
<Button
color="primary"
onClick={() => navigate("/workspace/auto-group")}
>
</Button>
</Card>
</Layout>
);
}
return (
<Layout
header={
<div className={style.headerBar}>
<Button fill="none" size="small" onClick={() => navigate(-1)}>
<LeftOutline />
</Button>
<div className={style.title}>{taskDetail.name} - </div>
</div>
}
footer={<MeauMobile />}
>
<div className={style.autoGroupDetail}>
<Card className={style.infoCard}>
<div className={style.infoGrid}>
<div>
<div className={style.infoTitle}></div>
<div className={style.infoItem}>{taskDetail.name}</div>
<div className={style.infoItem}>
{taskDetail.createTime}
</div>
<div className={style.infoItem}>{taskDetail.creator}</div>
<div className={style.infoItem}>
{taskDetail.deviceCount}
</div>
</div>
<div>
<div className={style.infoTitle}></div>
<div className={style.infoItem}>
{taskDetail.groupSize.min}-{taskDetail.groupSize.max}{" "}
</div>
<div className={style.infoItem}>
{taskDetail.timeRange.start} -{" "}
{taskDetail.timeRange.end}
</div>
<div className={style.infoItem}>
{taskDetail.targetTags.join(", ")}
</div>
<div className={style.infoItem}>
{taskDetail.groupNameTemplate}
</div>
</div>
</div>
</Card>
<GroupCreationProgress
taskDetail={taskDetail}
onComplete={handleComplete}
/>
</div>
</Layout>
);
};
export default AutoGroupDetail;

View File

@@ -1,3 +1,34 @@
.autoGroupForm {
// 这里写新建/编辑页样式
padding: 10px;
background: #f7f8fa;
}
.headerBar {
display: flex;
align-items: center;
height: 48px;
background: #fff;
border-bottom: 1px solid #f0f0f0;
font-size: 18px;
font-weight: 600;
padding: 0 16px;
}
.title {
font-size: 18px;
font-weight: 600;
color: #222;
flex: 1;
text-align: center;
}
.timeRangeRow {
display: flex;
align-items: center;
gap: 8px;
}
.groupSizeRow {
display: flex;
align-items: center;
gap: 8px;
}

View File

@@ -1,7 +1,245 @@
import React from "react";
import React, { useState, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import {
Form,
Input,
Button,
Toast,
Switch,
Selector,
TextArea,
} from "antd-mobile";
import { LeftOutline } from "antd-mobile-icons";
import Layout from "@/components/Layout/Layout";
import MeauMobile from "@/components/MeauMobile/MeauMoible";
import style from "./index.module.scss";
import { createAutoGroup, updateAutoGroup } from "./api";
const defaultForm = {
name: "",
deviceCount: 1,
targetFriends: 0,
createInterval: 300,
maxGroupsPerDay: 10,
timeRange: { start: "09:00", end: "21:00" },
groupSize: { min: 20, max: 50 },
targetTags: [],
groupNameTemplate: "VIP客户交流群{序号}",
groupDescription: "",
};
const tagOptions = [
{ label: "VIP客户", value: "VIP客户" },
{ label: "高价值", value: "高价值" },
{ label: "潜在客户", value: "潜在客户" },
{ label: "中意向", value: "中意向" },
];
const AutoGroupForm: React.FC = () => {
return <div>/</div>;
const navigate = useNavigate();
const { id } = useParams();
const isEdit = Boolean(id);
const [form, setForm] = useState<any>(defaultForm);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (isEdit) {
// 这里应请求详情接口回填表单演示用mock
setForm({
...defaultForm,
name: "VIP客户建群",
deviceCount: 2,
targetFriends: 156,
createInterval: 300,
maxGroupsPerDay: 20,
timeRange: { start: "09:00", end: "21:00" },
groupSize: { min: 20, max: 50 },
targetTags: ["VIP客户", "高价值"],
groupNameTemplate: "VIP客户交流群{序号}",
groupDescription: "VIP客户专属交流群提供优质服务",
});
}
}, [isEdit, id]);
const handleSubmit = async () => {
setLoading(true);
try {
if (isEdit) {
await updateAutoGroup(id as string, form);
Toast.show({ content: "编辑成功" });
} else {
await createAutoGroup(form);
Toast.show({ content: "创建成功" });
}
navigate("/workspace/auto-group");
} catch (e) {
Toast.show({ content: "提交失败" });
} finally {
setLoading(false);
}
};
return (
<Layout
header={
<div className={style.headerBar}>
<Button fill="none" size="small" onClick={() => navigate(-1)}>
<LeftOutline />
</Button>
<div className={style.title}>
{isEdit ? "编辑建群任务" : "新建建群任务"}
</div>
</div>
}
>
<div className={style.autoGroupForm}>
<Form
layout="vertical"
footer={
<Button
block
color="primary"
loading={loading}
onClick={handleSubmit}
>
{isEdit ? "保存修改" : "创建任务"}
</Button>
}
>
<Form.Item label="任务名称" name="name" required>
<Input
value={form.name}
onChange={(val) => setForm((f: any) => ({ ...f, name: val }))}
placeholder="请输入任务名称"
/>
</Form.Item>
<Form.Item label="执行设备数量" name="deviceCount" required>
<Input
type="number"
value={form.deviceCount}
onChange={(val) =>
setForm((f: any) => ({ ...f, deviceCount: Number(val) }))
}
placeholder="请输入设备数量"
/>
</Form.Item>
<Form.Item label="目标好友数" name="targetFriends" required>
<Input
type="number"
value={form.targetFriends}
onChange={(val) =>
setForm((f: any) => ({ ...f, targetFriends: Number(val) }))
}
placeholder="请输入目标好友数"
/>
</Form.Item>
<Form.Item label="建群间隔(秒)" name="createInterval" required>
<Input
type="number"
value={form.createInterval}
onChange={(val) =>
setForm((f: any) => ({ ...f, createInterval: Number(val) }))
}
placeholder="请输入建群间隔"
/>
</Form.Item>
<Form.Item label="每日最大建群数" name="maxGroupsPerDay" required>
<Input
type="number"
value={form.maxGroupsPerDay}
onChange={(val) =>
setForm((f: any) => ({ ...f, maxGroupsPerDay: Number(val) }))
}
placeholder="请输入最大建群数"
/>
</Form.Item>
<Form.Item label="执行时间段" name="timeRange" required>
<div className={style.timeRangeRow}>
<Input
value={form.timeRange.start}
onChange={(val) =>
setForm((f: any) => ({
...f,
timeRange: { ...f.timeRange, start: val },
}))
}
placeholder="开始时间"
/>
<span style={{ margin: "0 8px" }}>-</span>
<Input
value={form.timeRange.end}
onChange={(val) =>
setForm((f: any) => ({
...f,
timeRange: { ...f.timeRange, end: val },
}))
}
placeholder="结束时间"
/>
</div>
</Form.Item>
<Form.Item label="群组规模" name="groupSize" required>
<div className={style.groupSizeRow}>
<Input
type="number"
value={form.groupSize.min}
onChange={(val) =>
setForm((f: any) => ({
...f,
groupSize: { ...f.groupSize, min: Number(val) },
}))
}
placeholder="最小人数"
/>
<span style={{ margin: "0 8px" }}>-</span>
<Input
type="number"
value={form.groupSize.max}
onChange={(val) =>
setForm((f: any) => ({
...f,
groupSize: { ...f.groupSize, max: Number(val) },
}))
}
placeholder="最大人数"
/>
</div>
</Form.Item>
<Form.Item label="目标标签" name="targetTags">
<Selector
options={tagOptions}
multiple
value={form.targetTags}
onChange={(val) =>
setForm((f: any) => ({ ...f, targetTags: val }))
}
/>
</Form.Item>
<Form.Item label="群名称模板" name="groupNameTemplate" required>
<Input
value={form.groupNameTemplate}
onChange={(val) =>
setForm((f: any) => ({ ...f, groupNameTemplate: val }))
}
placeholder="请输入群名称模板"
/>
</Form.Item>
<Form.Item label="群描述" name="groupDescription">
<TextArea
value={form.groupDescription}
onChange={(val) =>
setForm((f: any) => ({ ...f, groupDescription: val }))
}
placeholder="请输入群描述"
rows={3}
maxLength={100}
showCount
/>
</Form.Item>
</Form>
</div>
</Layout>
);
};
export default AutoGroupForm;

View File

@@ -1,3 +1,203 @@
.autoGroupList {
// 这里写列表页样式
padding: 16px 0 80px 0;
background: #f7f8fa;
min-height: 100vh;
}
.headerBar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 16px;
height: 48px;
background: #fff;
border-bottom: 1px solid #f0f0f0;
font-size: 18px;
font-weight: 600;
}
.title {
font-size: 18px;
font-weight: 600;
color: #222;
}
.searchBar {
display: flex;
align-items: center;
padding: 12px 16px 0 16px;
background: #fff;
gap: 8px;
}
.taskList {
margin-top: 16px;
padding: 0 8px;
}
.taskCard {
margin-bottom: 16px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.03);
border: none;
background: #fff;
padding: 16px;
}
.taskHeader {
display: flex;
align-items: center;
gap: 8px;
font-size: 16px;
font-weight: 500;
margin-bottom: 8px;
}
.taskTitle {
flex: 1;
font-size: 16px;
font-weight: 500;
color: #222;
}
.statusRunning {
background: #e6f7e6;
color: #389e0d;
border-radius: 8px;
padding: 2px 8px;
font-size: 12px;
margin-left: 8px;
}
.statusPaused {
background: #f5f5f5;
color: #888;
border-radius: 8px;
padding: 2px 8px;
font-size: 12px;
margin-left: 8px;
}
.statusCompleted {
background: #e6f4ff;
color: #1677ff;
border-radius: 8px;
padding: 2px 8px;
font-size: 12px;
margin-left: 8px;
}
.taskInfoGrid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 8px 16px;
margin-bottom: 8px;
font-size: 13px;
}
.infoLabel {
color: #888;
font-size: 12px;
}
.infoValue {
color: #222;
font-weight: 500;
font-size: 14px;
}
.taskFooter {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 12px;
color: #888;
border-top: 1px solid #f0f0f0;
padding-top: 8px;
margin-top: 8px;
}
.footerLeft {
display: flex;
align-items: center;
}
.footerRight {
display: flex;
align-items: center;
}
.expandPanel {
margin-top: 16px;
padding-top: 12px;
border-top: 1px dashed #e0e0e0;
}
.expandGrid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
}
.expandTitle {
font-size: 14px;
font-weight: 500;
margin-bottom: 4px;
display: flex;
align-items: center;
color: #1677ff;
}
.expandInfo {
font-size: 13px;
color: #444;
margin-bottom: 2px;
}
.expandTags {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.tag {
background: #f0f5ff;
color: #1677ff;
border-radius: 8px;
padding: 2px 8px;
font-size: 12px;
}
.menuItem {
padding: 8px 12px;
font-size: 14px;
color: #222;
cursor: pointer;
border-radius: 6px;
transition: background 0.2s;
}
.menuItem:hover {
background: #f5f5f5;
}
.menuItemDanger {
padding: 8px 12px;
font-size: 14px;
color: #e53e3e;
cursor: pointer;
border-radius: 6px;
transition: background 0.2s;
}
.menuItemDanger:hover {
background: #fff1f0;
}
.emptyCard {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px 0;
background: #fff;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.03);
margin-top: 32px;
}
.emptyTitle {
font-size: 16px;
color: #888;
margin: 12px 0 4px 0;
}
.emptyDesc {
font-size: 13px;
color: #bbb;
margin-bottom: 16px;
}

View File

@@ -195,7 +195,6 @@ const AutoGroupList: React.FC = () => {
placeholder="搜索任务名称"
value={searchTerm}
onChange={(val) => setSearchTerm(val)}
prefix={<SearchOutline />}
clearable
/>
<Button size="small" fill="outline" style={{ marginLeft: 8 }}>

View File

@@ -123,12 +123,46 @@ input, textarea {
body, input, textarea, select, button {
touch-action: manipulation;
}
//导航左右结构的样式
// 导航样式
.nav-title {
font-size: 18px;
font-weight: 600;
color: var(--primary-color);
}
.nav-text {
color: var(--primary-color);
}
.nav-back-btn{
color: #333;
vertical-align: middle;
}
.nav-left {
color: var(--primary-color);
font-weight: 700;
font-size: 16px;
}
.nav-right {
margin-left: 4px;
font-size: 12px;
}
}
.new-plan-btn {
border-radius: 20px;
padding: 4px 12px;
height: 32px;
font-size: 12px;
background: var(--primary-gradient);
border: none;
box-shadow: 0 2px 8px var(--primary-shadow);
&:active {
transform: translateY(1px);
box-shadow: 0 1px 4px var(--primary-shadow);
}
}