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

修复
This commit is contained in:
笔记本里的永平
2025-07-07 22:24:14 +08:00
parent bdd4dc3832
commit 70a1016dc0
23 changed files with 3202 additions and 1073 deletions

View File

@@ -109,7 +109,7 @@ export default function ScenarioDetail() {
todayCustomers,
growth: `+${Math.floor(Math.random() * 20) + 5}%`,
};
setScenario(scenarioData);
} catch (error) {
console.error('获取场景数据失败:', error);
@@ -345,8 +345,8 @@ export default function ScenarioDetail() {
>
</button>
</div>
</div>
</div>
</Layout>
);
}
@@ -367,7 +367,7 @@ export default function ScenarioDetail() {
<Loader2 className="h-8 w-8 animate-spin text-blue-500" />
<p className="text-gray-500">...</p>
</div>
</div>
</div>
</Layout>
);
}
@@ -375,65 +375,65 @@ export default function ScenarioDetail() {
return (
<Layout
header={
<PageHeader
title={scenario.name}
defaultBackPath="/scenarios"
rightContent={
<button
<PageHeader
title={scenario.name}
defaultBackPath="/scenarios"
rightContent={
<button
onClick={handleCreateNewPlan}
className="flex items-center px-3 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors text-sm"
>
<Plus className="h-4 w-4 mr-1" />
</button>
}
/>
className="flex items-center px-3 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors text-sm"
>
<Plus className="h-4 w-4 mr-1" />
</button>
}
/>
}
footer={<BottomNav />}
>
<div className="bg-gray-50 min-h-screen pb-20">
<div className="p-4">
{/* 场景描述 */}
<div className="bg-white rounded-lg p-4 mb-6">
<p className="text-gray-600 text-sm">{scenario.description}</p>
</div>
<div className="p-4">
{/* 场景描述 */}
<div className="bg-white rounded-lg p-4 mb-6">
<p className="text-gray-600 text-sm">{scenario.description}</p>
</div>
{/* 数据统计 */}
<div className="grid grid-cols-2 gap-4 mb-6">
<div className="bg-white rounded-lg p-4">
<div className="flex items-center justify-between">
<div>
<p className="text-gray-500 text-sm"></p>
<p className="text-2xl font-bold text-gray-900">{scenario.totalCustomers}</p>
</div>
<Users className="h-8 w-8 text-blue-500" />
</div>
<div className="flex items-center mt-2 text-green-500 text-sm">
<TrendingUp className="h-4 w-4 mr-1" />
<span>{scenario.growth}</span>
{/* 数据统计 */}
<div className="grid grid-cols-2 gap-4 mb-6">
<div className="bg-white rounded-lg p-4">
<div className="flex items-center justify-between">
<div>
<p className="text-gray-500 text-sm"></p>
<p className="text-2xl font-bold text-gray-900">{scenario.totalCustomers}</p>
</div>
<Users className="h-8 w-8 text-blue-500" />
</div>
<div className="bg-white rounded-lg p-4">
<div className="flex items-center justify-between">
<div>
<p className="text-gray-500 text-sm"></p>
<p className="text-2xl font-bold text-gray-900">{scenario.todayCustomers}</p>
</div>
<Calendar className="h-8 w-8 text-green-500" />
</div>
<div className="flex items-center mt-2 text-gray-500 text-sm">
<span>: {scenario.totalPlans}</span>
</div>
<div className="flex items-center mt-2 text-green-500 text-sm">
<TrendingUp className="h-4 w-4 mr-1" />
<span>{scenario.growth}</span>
</div>
</div>
{/* 计划列表 */}
<div className="bg-white rounded-lg">
<div className="p-4 border-b">
<h2 className="text-lg font-medium"></h2>
<div className="bg-white rounded-lg p-4">
<div className="flex items-center justify-between">
<div>
<p className="text-gray-500 text-sm"></p>
<p className="text-2xl font-bold text-gray-900">{scenario.todayCustomers}</p>
</div>
<Calendar className="h-8 w-8 text-green-500" />
</div>
<div className="flex items-center mt-2 text-gray-500 text-sm">
<span>: {scenario.totalPlans}</span>
</div>
</div>
</div>
{/* 计划列表 */}
<div className="bg-white rounded-lg">
<div className="p-4 border-b">
<h2 className="text-lg font-medium"></h2>
</div>
{tasks.length === 0 ? (
<div className="p-8 text-center">
<div className="mb-4">
@@ -441,33 +441,33 @@ export default function ScenarioDetail() {
<p className="text-gray-500 text-lg font-medium mb-2"></p>
<p className="text-gray-400 text-sm"></p>
</div>
<button
<button
onClick={handleCreateNewPlan}
className="inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
>
>
<Plus className="h-4 w-4 mr-2" />
</button>
</div>
) : (
<div className="divide-y">
</button>
</div>
) : (
<div className="divide-y">
{tasks.map((task) => (
<div key={task.id} className="p-4 hover:bg-gray-50">
<div className="flex items-center justify-between">
<div className="flex-1">
<div className="flex items-center mb-2">
<div className="flex items-center justify-between">
<div className="flex-1">
<div className="flex items-center mb-2">
<h3 className="font-medium text-gray-900">{task.name}</h3>
<span className={`ml-2 px-2 py-1 text-xs rounded-full ${getStatusColor(task.status)}`}>
{getStatusText(task.status)}
</span>
</div>
<div className="flex items-center text-sm text-gray-500">
<Calendar className="h-4 w-4 mr-1" />
</span>
</div>
<div className="flex items-center text-sm text-gray-500">
<Calendar className="h-4 w-4 mr-1" />
<span>: {task.lastUpdated}</span>
</div>
</div>
<div className="flex items-center mt-2 text-sm text-gray-500">
<span>: {task.stats?.devices || 0} | : {task.stats?.acquired || 0} | : {task.stats?.added || 0}</span>
</div>
</div>
</div>
<div className="flex items-center space-x-2">
@@ -502,15 +502,15 @@ export default function ScenarioDetail() {
>
<Trash2 className="h-4 w-4" />
</button>
</div>
</div>
</div>
))}
</div>
)}
</div>
</div>
))}
</div>
)}
</div>
</div>
</div>
{/* API接口设置对话框 */}
{showApiDialog && (

View File

@@ -187,13 +187,13 @@ export default function GongzhonghaoScenario() {
const task = tasks.find((t) => t.id === taskId);
if (task) {
// 直接使用列表数据不调用详情API
setCurrentApiSettings({
setCurrentApiSettings({
apiKey: `api_key_${taskId}`, // 使用任务ID生成API密钥
webhookUrl: `${API_BASE_URL}/v1/api/scenarios/${taskId}`,
fullUrl: `${API_BASE_URL}/v1/api/scenarios/${taskId}/text`,
taskId,
});
setShowApiDialog(true);
taskId,
});
setShowApiDialog(true);
}
};
@@ -217,58 +217,58 @@ export default function GongzhonghaoScenario() {
return (
<Layout
header={
<PageHeader
title={channelName}
defaultBackPath="/scenarios"
rightContent={
<Button onClick={handleCreateNewPlan} size="sm" className="bg-blue-600 hover:bg-blue-700 text-white">
<Plus className="h-4 w-4 mr-1" />
</Button>
}
/>
<PageHeader
title={channelName}
defaultBackPath="/scenarios"
rightContent={
<Button onClick={handleCreateNewPlan} size="sm" className="bg-blue-600 hover:bg-blue-700 text-white">
<Plus className="h-4 w-4 mr-1" />
</Button>
}
/>
}
>
<div className="bg-gradient-to-b from-blue-50 to-white">
<div className="p-4 md:p-6 lg:p-8 max-w-7xl mx-auto">
<div className="space-y-4">
{loading ? (
<div className="text-center py-12 text-gray-400">...</div>
) : error ? (
<div className="text-center py-12 text-red-500">{error}</div>
) : tasks.length > 0 ? (
<>
{tasks.map((task) => (
<div key={task.id}>
<ScenarioAcquisitionCard
task={task}
channel={channel}
onEdit={() => handleEditPlan(task.id)}
onCopy={handleCopyPlan}
onDelete={handleDeletePlan}
onStatusChange={handleStatusChange}
onOpenSettings={handleOpenApiSettings}
/>
</div>
))}
<div className="flex justify-center mt-6 gap-2">
<Button disabled={page === 1} onClick={() => setPage(page - 1)}></Button>
<span className="px-2"> {page} / {Math.max(1, Math.ceil(total / pageSize))} </span>
<Button disabled={page * pageSize >= total} onClick={() => setPage(page + 1)}></Button>
<div className="p-4 md:p-6 lg:p-8 max-w-7xl mx-auto">
<div className="space-y-4">
{loading ? (
<div className="text-center py-12 text-gray-400">...</div>
) : error ? (
<div className="text-center py-12 text-red-500">{error}</div>
) : tasks.length > 0 ? (
<>
{tasks.map((task) => (
<div key={task.id}>
<ScenarioAcquisitionCard
task={task}
channel={channel}
onEdit={() => handleEditPlan(task.id)}
onCopy={handleCopyPlan}
onDelete={handleDeletePlan}
onStatusChange={handleStatusChange}
onOpenSettings={handleOpenApiSettings}
/>
</div>
</>
) : (
<div className="text-center py-12 bg-white rounded-lg shadow-sm md:col-span-2 lg:col-span-3">
<div className="text-gray-400 mb-4"></div>
<Button onClick={handleCreateNewPlan} className="bg-blue-600 hover:bg-blue-700 text-white">
<Plus className="h-4 w-4 mr-1" />
</Button>
))}
<div className="flex justify-center mt-6 gap-2">
<Button disabled={page === 1} onClick={() => setPage(page - 1)}></Button>
<span className="px-2"> {page} / {Math.max(1, Math.ceil(total / pageSize))} </span>
<Button disabled={page * pageSize >= total} onClick={() => setPage(page + 1)}></Button>
</div>
)}
</div>
</>
) : (
<div className="text-center py-12 bg-white rounded-lg shadow-sm md:col-span-2 lg:col-span-3">
<div className="text-gray-400 mb-4"></div>
<Button onClick={handleCreateNewPlan} className="bg-blue-600 hover:bg-blue-700 text-white">
<Plus className="h-4 w-4 mr-1" />
</Button>
</div>
)}
</div>
</div>
</div>
{/* API接口设置对话框 */}
<Dialog open={showApiDialog} onOpenChange={setShowApiDialog}>
<DialogContent className="sm:max-w-md">

View File

@@ -126,124 +126,124 @@ export default function HaibaoScenario() {
return (
<Layout
header={
<PageHeader
title="海报获客"
defaultBackPath="/scenarios"
rightContent={
<button
onClick={() => navigate('/scenarios/new?scenario=haibao')}
<PageHeader
title="海报获客"
defaultBackPath="/scenarios"
rightContent={
<button
onClick={() => navigate('/scenarios/new?scenario=haibao')}
className="flex items-center px-3 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors text-sm"
>
<Plus className="h-4 w-4 mr-1" />
</button>
}
/>
>
<Plus className="h-4 w-4 mr-1" />
</button>
}
/>
}
>
<div className="bg-gradient-to-b from-blue-50 to-white">
<div className="p-4 max-w-7xl mx-auto">
{tasks.map((task) => (
<div key={task.id} className="bg-white rounded-lg shadow-sm border border-gray-100 mb-4 overflow-hidden">
{/* 任务头部 */}
<div className="p-4 border-b border-gray-100">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<div className={`p-2 rounded-lg ${getStatusColor(task.status)}`}>
{getStatusIcon(task.status)}
</div>
<div>
<h3 className="font-medium text-gray-900">{task.name}</h3>
<div className="flex items-center space-x-4 text-sm text-gray-500 mt-1">
<span className={`px-2 py-1 rounded-full text-xs font-medium ${getStatusColor(task.status)}`}>
{getStatusText(task.status)}
</span>
<span>: {task.lastUpdated}</span>
</div>
</div>
<div className="p-4 max-w-7xl mx-auto">
{tasks.map((task) => (
<div key={task.id} className="bg-white rounded-lg shadow-sm border border-gray-100 mb-4 overflow-hidden">
{/* 任务头部 */}
<div className="p-4 border-b border-gray-100">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<div className={`p-2 rounded-lg ${getStatusColor(task.status)}`}>
{getStatusIcon(task.status)}
</div>
<div className="flex items-center space-x-2">
<button
onClick={() => handleCopyPlan(task.id)}
className="p-2 text-gray-400 hover:text-orange-600 hover:bg-orange-50 rounded-lg transition-colors"
title="复制计划"
>
<Copy className="h-4 w-4" />
</button>
<button
onClick={() => handleDeletePlan(task.id)}
className="p-2 text-gray-400 hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors"
title="删除计划"
>
<Trash2 className="h-4 w-4" />
</button>
<div>
<h3 className="font-medium text-gray-900">{task.name}</h3>
<div className="flex items-center space-x-4 text-sm text-gray-500 mt-1">
<span className={`px-2 py-1 rounded-full text-xs font-medium ${getStatusColor(task.status)}`}>
{getStatusText(task.status)}
</span>
<span>: {task.lastUpdated}</span>
</div>
</div>
</div>
</div>
{/* 统计信息 */}
<div className="p-4">
<div className="grid grid-cols-3 gap-4 mb-4">
<div className="text-center">
<div className="flex items-center justify-center text-gray-500 mb-1">
<Users className="h-4 w-4 mr-1" />
<span className="text-sm"></span>
</div>
<div className="text-xl font-bold text-orange-600">{task.stats.devices}</div>
</div>
<div className="text-center">
<div className="flex items-center justify-center text-gray-500 mb-1">
<TrendingUp className="h-4 w-4 mr-1" />
<span className="text-sm"></span>
</div>
<div className="text-xl font-bold text-green-600">{task.stats.acquired}</div>
</div>
<div className="text-center">
<div className="flex items-center justify-center text-gray-500 mb-1">
<Users className="h-4 w-4 mr-1" />
<span className="text-sm"></span>
</div>
<div className="text-xl font-bold text-purple-600">{task.stats.added}</div>
</div>
</div>
{/* 趋势图表 */}
<div className="mb-4">
<h4 className="text-sm font-medium text-gray-700 mb-2">7</h4>
<div className="flex items-end space-x-1 h-20">
{task.trend.map((item, index) => (
<div key={index} className="flex-1 flex flex-col items-center">
<div
className="w-full bg-orange-200 rounded-t"
style={{ height: `${(item.customers / 30) * 100}%` }}
></div>
<span className="text-xs text-gray-500 mt-1">{item.date}</span>
</div>
))}
</div>
</div>
{/* 执行信息 */}
<div className="bg-gray-50 rounded-lg p-3">
<div className="flex items-center justify-between text-sm">
<span className="text-gray-600">: {task.executionTime}</span>
<span className="text-orange-600">{task.nextExecutionTime}</span>
</div>
<div className="flex items-center space-x-2">
<button
onClick={() => handleCopyPlan(task.id)}
className="p-2 text-gray-400 hover:text-orange-600 hover:bg-orange-50 rounded-lg transition-colors"
title="复制计划"
>
<Copy className="h-4 w-4" />
</button>
<button
onClick={() => handleDeletePlan(task.id)}
className="p-2 text-gray-400 hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors"
title="删除计划"
>
<Trash2 className="h-4 w-4" />
</button>
</div>
</div>
</div>
))}
{/* 海报管理 */}
<div className="bg-white rounded-lg shadow-sm border border-gray-100 p-4">
<h3 className="text-lg font-medium text-gray-900 mb-4"></h3>
<div className="text-center py-8 text-gray-500">
<Image className="h-12 w-12 mx-auto mb-2 text-gray-300" />
<p>...</p>
{/* 统计信息 */}
<div className="p-4">
<div className="grid grid-cols-3 gap-4 mb-4">
<div className="text-center">
<div className="flex items-center justify-center text-gray-500 mb-1">
<Users className="h-4 w-4 mr-1" />
<span className="text-sm"></span>
</div>
<div className="text-xl font-bold text-orange-600">{task.stats.devices}</div>
</div>
<div className="text-center">
<div className="flex items-center justify-center text-gray-500 mb-1">
<TrendingUp className="h-4 w-4 mr-1" />
<span className="text-sm"></span>
</div>
<div className="text-xl font-bold text-green-600">{task.stats.acquired}</div>
</div>
<div className="text-center">
<div className="flex items-center justify-center text-gray-500 mb-1">
<Users className="h-4 w-4 mr-1" />
<span className="text-sm"></span>
</div>
<div className="text-xl font-bold text-purple-600">{task.stats.added}</div>
</div>
</div>
{/* 趋势图表 */}
<div className="mb-4">
<h4 className="text-sm font-medium text-gray-700 mb-2">7</h4>
<div className="flex items-end space-x-1 h-20">
{task.trend.map((item, index) => (
<div key={index} className="flex-1 flex flex-col items-center">
<div
className="w-full bg-orange-200 rounded-t"
style={{ height: `${(item.customers / 30) * 100}%` }}
></div>
<span className="text-xs text-gray-500 mt-1">{item.date}</span>
</div>
))}
</div>
</div>
{/* 执行信息 */}
<div className="bg-gray-50 rounded-lg p-3">
<div className="flex items-center justify-between text-sm">
<span className="text-gray-600">: {task.executionTime}</span>
<span className="text-orange-600">{task.nextExecutionTime}</span>
</div>
</div>
</div>
</div>
))}
{/* 海报管理 */}
<div className="bg-white rounded-lg shadow-sm border border-gray-100 p-4">
<h3 className="text-lg font-medium text-gray-900 mb-4"></h3>
<div className="text-center py-8 text-gray-500">
<Image className="h-12 w-12 mx-auto mb-2 text-gray-300" />
<p>...</p>
</div>
</div>
</div>
</div>
</Layout>
);
}