From 36f72e1948931fef552cead58a8615ca5d83b15f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AC=94=E8=AE=B0=E6=9C=AC=E9=87=8C=E7=9A=84=E6=B0=B8?= =?UTF-8?q?=E5=B9=B3?= Date: Thu, 17 Jul 2025 15:57:20 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E6=9C=AC=E6=AC=A1=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E6=9B=B4=E6=96=B0=E5=86=85=E5=AE=B9=E5=A6=82=E4=B8=8B?= =?UTF-8?q?=20=E4=BF=9D=E5=AD=98=E4=B8=80=E4=B8=8B=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cunkebao/src/api/scenarios.ts | 19 +- Cunkebao/src/pages/scenarios/ScenarioList.tsx | 193 ++++++++++++------ 2 files changed, 151 insertions(+), 61 deletions(-) diff --git a/Cunkebao/src/api/scenarios.ts b/Cunkebao/src/api/scenarios.ts index 88e10dc1..74202095 100644 --- a/Cunkebao/src/api/scenarios.ts +++ b/Cunkebao/src/api/scenarios.ts @@ -308,4 +308,21 @@ export async function createScenarioPlan(data: any) { // 编辑计划 export async function updateScenarioPlan(planId: number | string, data: any) { return await put(`/v1/plan/update?planId=${planId}`, data); -} \ No newline at end of file +} + +/** + * 获取计划小程序二维码 + * @param taskid 任务ID + * @returns base64二维码 + */ +export const getWxMinAppCode = async (taskId: string): Promise<{ code: number; base64?: string; msg?: string }> => { + try { + return await get<{ code: number; base64?: string; msg?: string }>( + `/v1/plan/getWxMinAppCode?taskId=${ taskId }`, + + ); + } catch (error) { + console.error('获取小程序二维码失败:', error); + return { code: 500, msg: '获取小程序二维码失败' }; + } +}; \ No newline at end of file diff --git a/Cunkebao/src/pages/scenarios/ScenarioList.tsx b/Cunkebao/src/pages/scenarios/ScenarioList.tsx index 6c110961..aae47189 100644 --- a/Cunkebao/src/pages/scenarios/ScenarioList.tsx +++ b/Cunkebao/src/pages/scenarios/ScenarioList.tsx @@ -15,6 +15,7 @@ import { Code, Search, RefreshCw, + QrCode, } from "lucide-react"; import { fetchPlanList, @@ -22,6 +23,7 @@ import { copyPlan, deletePlan, type Task, + getWxMinAppCode, } from "@/api/scenarios"; import { useToast } from "@/components/ui/toast"; import "@/components/Layout.css"; @@ -65,6 +67,11 @@ export default function ScenarioDetail() { }); const [searchTerm, setSearchTerm] = useState(""); const [loadingTasks, setLoadingTasks] = useState(false); + // 二维码弹窗相关 + const [showQrDialog, setShowQrDialog] = useState(false); + const [qrLoading, setQrLoading] = useState(false); + const [qrImg, setQrImg] = useState(""); + const [qrTaskId, setQrTaskId] = useState(""); // 获取渠道中文名称 const getChannelName = (channel: string) => { @@ -310,6 +317,33 @@ export default function ScenarioDetail() { navigate(`/scenarios/new/${scenarioId}`); }; + const handleShowQrCode = async (taskId: string) => { + setQrTaskId(taskId); + setShowQrDialog(true); + setQrLoading(true); + setQrImg(""); + try { + const data = await getWxMinAppCode(taskId); + if (data && data.base64) { + setQrImg(`data:image/png;base64,${data.base64}`); + } else { + toast({ + title: "获取二维码失败", + description: data?.msg || "未知错误", + variant: "destructive", + }); + } + } catch (e) { + toast({ + title: "获取二维码失败", + description: "网络错误", + variant: "destructive", + }); + } finally { + setQrLoading(false); + } + }; + const getStatusColor = (status: number) => { switch (status) { case 1: @@ -463,70 +497,75 @@ export default function ScenarioDetail() { ) : ( -
+
{filteredTasks.map((task) => ( -
-
-
-
-

- {task.name} -

- - {getStatusText(task.status)} - -
-
- - 最后更新: {task.lastUpdated} -
-
- - 设备: {task.stats?.devices || 0} | 获客:{" "} - {task.stats?.acquired || 0} | 添加:{" "} - {task.stats?.added || 0} - -
+
+ {/* 头部:标题和状态 */} +
+

+ {task.name} +

+ + {getStatusText(task.status)} + +
+ {/* 中部:更新时间和统计 */} +
+
+ + 最后更新: {task.lastUpdated}
- -
- - - - - - - +
+ 设备: {task.stats?.devices || 0} | 获客:{" "} + {task.stats?.acquired || 0} | 添加:{" "} + {task.stats?.added || 0}
+ {/* 底部:操作按钮 */} +
+ + + + + +
))}
@@ -658,6 +697,40 @@ export default function ScenarioDetail() {
)} + {/* 二维码弹窗 */} + {showQrDialog && ( +
+
+ +
+ +
小程序二维码
+
+ 可扫码进入对应计划 +
+
+ {qrLoading ? ( +
+ +
二维码加载中...
+
+ ) : qrImg ? ( + 二维码 + ) : ( +
二维码加载失败
+ )} +
+
+ )} ); } From 576765e78e4cee91ca44d7083ae8508cfd6c849c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AC=94=E8=AE=B0=E6=9C=AC=E9=87=8C=E7=9A=84=E6=B0=B8?= =?UTF-8?q?=E5=B9=B3?= Date: Thu, 17 Jul 2025 16:08:34 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=E6=9C=AC=E6=AC=A1=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E6=9B=B4=E6=96=B0=E5=86=85=E5=AE=B9=E5=A6=82=E4=B8=8B?= =?UTF-8?q?=20=E5=BC=B9=E7=AA=97=E4=BA=8C=E7=BB=B4=E7=A0=81=E6=90=9E?= =?UTF-8?q?=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cunkebao/.eslintrc.js | 40 +++++++++++++++++++ Cunkebao/src/api/scenarios.ts | 5 +-- Cunkebao/src/pages/scenarios/ScenarioList.tsx | 34 ++-------------- 3 files changed, 46 insertions(+), 33 deletions(-) create mode 100644 Cunkebao/.eslintrc.js diff --git a/Cunkebao/.eslintrc.js b/Cunkebao/.eslintrc.js new file mode 100644 index 00000000..72eb95a9 --- /dev/null +++ b/Cunkebao/.eslintrc.js @@ -0,0 +1,40 @@ +module.exports = { + root: true, + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint', 'react'], + extends: [ + 'eslint:recommended', + 'plugin:react/recommended', + 'plugin:@typescript-eslint/recommended', + 'react-app', + 'react-app/jest', + ], + env: { + browser: true, + es2021: true, + node: true, + }, + settings: { + react: { + version: 'detect', + }, + }, + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + ecmaVersion: 'latest', + sourceType: 'module', + }, + rules: { + 'react/react-in-jsx-scope': 'off', + '@typescript-eslint/no-unused-vars': [ + 'warn', + { argsIgnorePattern: '^_', varsIgnorePattern: '^_' } + ], + 'react/prop-types': 'off', + 'no-console': 'warn', + 'no-debugger': 'warn', + }, + ignorePatterns: ['node_modules/', 'build/', 'dist/'], +}; \ No newline at end of file diff --git a/Cunkebao/src/api/scenarios.ts b/Cunkebao/src/api/scenarios.ts index 74202095..ee3774a1 100644 --- a/Cunkebao/src/api/scenarios.ts +++ b/Cunkebao/src/api/scenarios.ts @@ -315,14 +315,13 @@ export async function updateScenarioPlan(planId: number | string, data: any) { * @param taskid 任务ID * @returns base64二维码 */ -export const getWxMinAppCode = async (taskId: string): Promise<{ code: number; base64?: string; msg?: string }> => { +export const getWxMinAppCode = async (taskId: string): Promise<{ code: number; data?: string; msg?: string }> => { try { - return await get<{ code: number; base64?: string; msg?: string }>( + return await get<{ code: number; data?: string; msg?: string }>( `/v1/plan/getWxMinAppCode?taskId=${ taskId }`, ); } catch (error) { - console.error('获取小程序二维码失败:', error); return { code: 500, msg: '获取小程序二维码失败' }; } }; \ No newline at end of file diff --git a/Cunkebao/src/pages/scenarios/ScenarioList.tsx b/Cunkebao/src/pages/scenarios/ScenarioList.tsx index aae47189..7ab94cb3 100644 --- a/Cunkebao/src/pages/scenarios/ScenarioList.tsx +++ b/Cunkebao/src/pages/scenarios/ScenarioList.tsx @@ -71,7 +71,6 @@ export default function ScenarioDetail() { const [showQrDialog, setShowQrDialog] = useState(false); const [qrLoading, setQrLoading] = useState(false); const [qrImg, setQrImg] = useState(""); - const [qrTaskId, setQrTaskId] = useState(""); // 获取渠道中文名称 const getChannelName = (channel: string) => { @@ -257,29 +256,6 @@ export default function ScenarioDetail() { } }; - const handleStatusChange = async (taskId: string, newStatus: 1 | 0) => { - try { - // 这里应该调用状态切换API,暂时模拟 - setTasks((prev) => - prev.map((task) => - task.id === taskId ? { ...task, status: newStatus } : task - ) - ); - - toast({ - title: "状态已更新", - description: `计划已${newStatus === 1 ? "启动" : "暂停"}`, - }); - } catch (error) { - console.error("状态切换失败:", error); - toast({ - title: "状态切换失败", - description: "请稍后重试", - variant: "destructive", - }); - } - }; - const handleOpenApiSettings = async (taskId: string) => { try { const response = await fetchPlanDetail(taskId); @@ -318,18 +294,17 @@ export default function ScenarioDetail() { }; const handleShowQrCode = async (taskId: string) => { - setQrTaskId(taskId); setShowQrDialog(true); setQrLoading(true); setQrImg(""); try { - const data = await getWxMinAppCode(taskId); - if (data && data.base64) { - setQrImg(`data:image/png;base64,${data.base64}`); + const res = await getWxMinAppCode(taskId); + if (res.data) { + setQrImg(res.data); } else { toast({ title: "获取二维码失败", - description: data?.msg || "未知错误", + description: res?.msg || "未知错误", variant: "destructive", }); } @@ -708,7 +683,6 @@ export default function ScenarioDetail() { ×
-
小程序二维码
可扫码进入对应计划