diff --git a/nkebao/src/pages/scenarios/plan/list/index.module.scss b/nkebao/src/pages/scenarios/plan/list/index.module.scss index b9c3b93e..f8b8ddb0 100644 --- a/nkebao/src/pages/scenarios/plan/list/index.module.scss +++ b/nkebao/src/pages/scenarios/plan/list/index.module.scss @@ -304,6 +304,7 @@ background: white; border-radius: 16px; padding: 20px; + width: 100%; } .qr-loading { @@ -329,4 +330,72 @@ color: #ff4d4f; font-size: 14px; padding: 40px 20px; +} + +.qr-link-section { + margin-top: 20px; + width: 100%; + padding: 0 10px; +} + +.link-label { + font-size: 14px; + font-weight: 500; + color: #333; + margin-bottom: 8px; + text-align: left; +} + +.link-input-wrapper { + display: flex; + gap: 8px; + align-items: center; + width: 100%; + + @media (max-width: 480px) { + flex-direction: column; + gap: 12px; + } +} + +.link-input { + flex: 1; + + .ant-input { + border-radius: 8px; + font-size: 12px; + color: #666; + background-color: #f8f9fa; + border: 1px solid #e9ecef; + + &:focus { + border-color: #1890ff; + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); + } + } + + @media (max-width: 480px) { + width: 100%; + } +} + +.copy-button { + height: 32px; + padding: 0 12px; + border-radius: 8px; + font-size: 12px; + display: flex; + align-items: center; + gap: 4px; + white-space: nowrap; + flex-shrink: 0; + + .anticon { + font-size: 12px; + } + + @media (max-width: 480px) { + width: 100%; + justify-content: center; + } } \ No newline at end of file diff --git a/nkebao/src/pages/scenarios/plan/list/index.tsx b/nkebao/src/pages/scenarios/plan/list/index.tsx index 7f13eefa..ebeb8f46 100644 --- a/nkebao/src/pages/scenarios/plan/list/index.tsx +++ b/nkebao/src/pages/scenarios/plan/list/index.tsx @@ -37,6 +37,7 @@ import { import style from "./index.module.scss"; import { Task, ApiSettings, PlanDetail } from "./data"; import PlanApi from "./planApi"; +import { buildApiUrl } from "@/utils/apiUrl"; const ScenarioList: React.FC = () => { const { scenarioId, scenarioName } = useParams<{ @@ -57,6 +58,7 @@ const ScenarioList: React.FC = () => { const [showQrDialog, setShowQrDialog] = useState(false); const [qrLoading, setQrLoading] = useState(false); const [qrImg, setQrImg] = useState(""); + const [currentTaskId, setCurrentTaskId] = useState(""); const [showActionMenu, setShowActionMenu] = useState(null); // 分页相关状态 @@ -208,11 +210,14 @@ const ScenarioList: React.FC = () => { try { const response: PlanDetail = await getPlanDetail(taskId); if (response) { + // 处理webhook URL,使用工具函数构建完整地址 + const webhookUrl = buildApiUrl( + response.textUrl?.fullUrl || `webhook/${taskId}` + ); + setCurrentApiSettings({ apiKey: response.apiKey || "demo-api-key-123456", - webhookUrl: - response.textUrl?.fullUrl || - `https://api.example.com/webhook/${taskId}`, + webhookUrl: webhookUrl, taskId: taskId, }); setShowApiDialog(true); @@ -233,6 +238,7 @@ const ScenarioList: React.FC = () => { setQrLoading(true); setShowQrDialog(true); setQrImg(""); + setCurrentTaskId(taskId); // 设置当前任务ID try { const response = await getWxMinAppCode(taskId); @@ -566,11 +572,40 @@ const ScenarioList: React.FC = () => {
生成二维码中...
) : qrImg ? ( - 小程序二维码 + <> + 小程序二维码 + {/* 链接复制区域 */} +
+
小程序链接
+
+ + +
+
+ ) : (
二维码生成失败
)} diff --git a/nkebao/src/pages/scenarios/plan/list/planApi.tsx b/nkebao/src/pages/scenarios/plan/list/planApi.tsx index 954037fd..7fc94b1a 100644 --- a/nkebao/src/pages/scenarios/plan/list/planApi.tsx +++ b/nkebao/src/pages/scenarios/plan/list/planApi.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState, useMemo } from "react"; import { Popup, Button, Toast, SpinLoading } from "antd-mobile"; import { Modal, Input, Tabs, Card, Tag, Space } from "antd"; import { @@ -12,6 +12,7 @@ import { CheckCircleOutlined, } from "@ant-design/icons"; import style from "./planApi.module.scss"; +import { buildApiUrl } from "@/utils/apiUrl"; /** * 计划接口配置弹窗组件 @@ -40,6 +41,7 @@ import style from "./planApi.module.scss"; * - 支持多种编程语言的代码示例 * - 响应式设计,自适应不同屏幕尺寸 * - 支持暗色主题 + * - 自动拼接API地址前缀 */ interface PlanApiProps { @@ -65,9 +67,17 @@ const PlanApi: React.FC = ({ }) => { const [activeTab, setActiveTab] = useState("config"); const [activeLanguage, setActiveLanguage] = useState("javascript"); - const [testUrl, setTestUrl] = useState( - `${webhookUrl}?name=测试客户&phone=13800138000&source=API测试` - ); + + // 处理webhook URL,确保包含完整的API地址 + const fullWebhookUrl = useMemo(() => { + return buildApiUrl(webhookUrl); + }, [webhookUrl]); + + // 生成测试URL + const testUrl = useMemo(() => { + if (!fullWebhookUrl) return ""; + return `${fullWebhookUrl}?name=测试客户&phone=13800138000&source=API测试`; + }, [fullWebhookUrl]); // 检测是否为移动端 const isMobile = window.innerWidth <= 768; @@ -122,10 +132,14 @@ const PlanApi: React.FC = ({ POST请求
- +