存客宝 - 修复添加设备二维码有时会错误的问题
This commit is contained in:
@@ -7,6 +7,7 @@ import { Card } from "@/components/ui/card";
|
|||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Alert, AlertDescription } from "@/components/ui/alert";
|
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||||
import { AlertCircle } from "lucide-react";
|
import { AlertCircle } from "lucide-react";
|
||||||
|
import { toast } from "@/components/ui/use-toast";
|
||||||
|
|
||||||
interface ContactData {
|
interface ContactData {
|
||||||
mobile: number;
|
mobile: number;
|
||||||
|
|||||||
@@ -134,13 +134,9 @@ export default function DeviceDetailPage() {
|
|||||||
} else if (serverData.taskConfig) {
|
} else if (serverData.taskConfig) {
|
||||||
try {
|
try {
|
||||||
// 解析taskConfig字段
|
// 解析taskConfig字段
|
||||||
let taskConfig = serverData.taskConfig
|
const taskConfig = JSON.parse(serverData.taskConfig || '{}');
|
||||||
if (typeof taskConfig === 'string') {
|
|
||||||
taskConfig = JSON.parse(taskConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (taskConfig) {
|
if (taskConfig) {
|
||||||
console.log('解析的taskConfig:', taskConfig);
|
|
||||||
formattedDevice.features = {
|
formattedDevice.features = {
|
||||||
autoAddFriend: Boolean(taskConfig.autoAddFriend),
|
autoAddFriend: Boolean(taskConfig.autoAddFriend),
|
||||||
autoReply: Boolean(taskConfig.autoReply),
|
autoReply: Boolean(taskConfig.autoReply),
|
||||||
|
|||||||
@@ -171,26 +171,37 @@ export default function DevicesPage() {
|
|||||||
setIsLoadingQRCode(true)
|
setIsLoadingQRCode(true)
|
||||||
setQrCodeImage("") // 清空当前二维码
|
setQrCodeImage("") // 清空当前二维码
|
||||||
|
|
||||||
|
// 获取保存的accountId
|
||||||
|
const accountId = localStorage.getItem('s2_accountId')
|
||||||
|
if (!accountId) {
|
||||||
|
toast({
|
||||||
|
title: "获取二维码失败",
|
||||||
|
description: "未获取到用户信息,请重新登录",
|
||||||
|
variant: "destructive",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 发起请求获取二维码 - 直接使用fetch避免api工具添加基础URL
|
// 发起请求获取二维码 - 直接使用fetch避免api工具添加基础URL
|
||||||
const response = await fetch('http://yi.54word.com/v1/api/device/add', {
|
const response = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/v1/api/device/add`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Accept': 'application/json'
|
'Accept': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({})
|
body: JSON.stringify({
|
||||||
|
accountId: accountId
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// 保存原始响应文本以便调试
|
// 保存原始响应文本以便调试
|
||||||
const responseText = await response.text();
|
const responseText = await response.text();
|
||||||
console.log("原始响应内容:", responseText);
|
|
||||||
|
|
||||||
// 尝试将响应解析为JSON
|
// 尝试将响应解析为JSON
|
||||||
let result;
|
let result;
|
||||||
try {
|
try {
|
||||||
result = JSON.parse(responseText);
|
result = JSON.parse(responseText);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("响应不是有效的JSON:", e);
|
|
||||||
toast({
|
toast({
|
||||||
title: "获取二维码失败",
|
title: "获取二维码失败",
|
||||||
description: "服务器返回的数据格式无效",
|
description: "服务器返回的数据格式无效",
|
||||||
@@ -199,25 +210,19 @@ export default function DevicesPage() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("二维码响应数据:", result);
|
|
||||||
|
|
||||||
if (result && result.code === 200) {
|
if (result && result.code === 200) {
|
||||||
// 尝试多种可能的返回数据结构
|
// 尝试多种可能的返回数据结构
|
||||||
let qrcodeData = null;
|
let qrcodeData = null;
|
||||||
|
|
||||||
if (result.data?.qrCode) {
|
if (result.data?.qrCode) {
|
||||||
qrcodeData = result.data.qrCode;
|
qrcodeData = result.data.qrCode;
|
||||||
console.log("找到二维码数据在 result.data.qrCode");
|
|
||||||
} else if (result.data?.qrcode) {
|
} else if (result.data?.qrcode) {
|
||||||
qrcodeData = result.data.qrcode;
|
qrcodeData = result.data.qrcode;
|
||||||
console.log("找到二维码数据在 result.data.qrcode");
|
|
||||||
} else if (result.data?.image) {
|
} else if (result.data?.image) {
|
||||||
qrcodeData = result.data.image;
|
qrcodeData = result.data.image;
|
||||||
console.log("找到二维码数据在 result.data.image");
|
|
||||||
} else if (result.data?.url) {
|
} else if (result.data?.url) {
|
||||||
// 如果返回的是URL而不是base64
|
// 如果返回的是URL而不是base64
|
||||||
qrcodeData = result.data.url;
|
qrcodeData = result.data.url;
|
||||||
console.log("找到二维码URL在 result.data.url");
|
|
||||||
setQrCodeImage(qrcodeData);
|
setQrCodeImage(qrcodeData);
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
@@ -229,9 +234,7 @@ export default function DevicesPage() {
|
|||||||
} else if (typeof result.data === 'string') {
|
} else if (typeof result.data === 'string') {
|
||||||
// 如果data直接是字符串
|
// 如果data直接是字符串
|
||||||
qrcodeData = result.data;
|
qrcodeData = result.data;
|
||||||
console.log("二维码数据直接在 result.data 字符串中");
|
|
||||||
} else {
|
} else {
|
||||||
console.error("无法找到二维码数据:", result);
|
|
||||||
toast({
|
toast({
|
||||||
title: "获取二维码失败",
|
title: "获取二维码失败",
|
||||||
description: "返回数据格式不正确",
|
description: "返回数据格式不正确",
|
||||||
@@ -242,7 +245,6 @@ export default function DevicesPage() {
|
|||||||
|
|
||||||
// 检查数据是否为空
|
// 检查数据是否为空
|
||||||
if (!qrcodeData) {
|
if (!qrcodeData) {
|
||||||
console.error("二维码数据为空");
|
|
||||||
toast({
|
toast({
|
||||||
title: "获取二维码失败",
|
title: "获取二维码失败",
|
||||||
description: "服务器返回的二维码数据为空",
|
description: "服务器返回的二维码数据为空",
|
||||||
@@ -251,16 +253,12 @@ export default function DevicesPage() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("处理前的二维码数据:", qrcodeData);
|
|
||||||
|
|
||||||
// 检查是否已经是完整的data URL
|
// 检查是否已经是完整的data URL
|
||||||
if (qrcodeData.startsWith('data:image')) {
|
if (qrcodeData.startsWith('data:image')) {
|
||||||
console.log("数据已包含data:image前缀");
|
|
||||||
setQrCodeImage(qrcodeData);
|
setQrCodeImage(qrcodeData);
|
||||||
}
|
}
|
||||||
// 检查是否是URL
|
// 检查是否是URL
|
||||||
else if (qrcodeData.startsWith('http')) {
|
else if (qrcodeData.startsWith('http')) {
|
||||||
console.log("数据是HTTP URL");
|
|
||||||
setQrCodeImage(qrcodeData);
|
setQrCodeImage(qrcodeData);
|
||||||
}
|
}
|
||||||
// 尝试作为base64处理
|
// 尝试作为base64处理
|
||||||
@@ -268,7 +266,6 @@ export default function DevicesPage() {
|
|||||||
try {
|
try {
|
||||||
// 确保base64字符串没有空格等干扰字符
|
// 确保base64字符串没有空格等干扰字符
|
||||||
const cleanedBase64 = qrcodeData.trim();
|
const cleanedBase64 = qrcodeData.trim();
|
||||||
console.log("处理后的base64数据:", cleanedBase64.substring(0, 30) + "...");
|
|
||||||
|
|
||||||
// 直接以图片src格式设置
|
// 直接以图片src格式设置
|
||||||
setQrCodeImage(`data:image/png;base64,${cleanedBase64}`);
|
setQrCodeImage(`data:image/png;base64,${cleanedBase64}`);
|
||||||
@@ -276,10 +273,9 @@ export default function DevicesPage() {
|
|||||||
// 预加载图片,确认是否有效
|
// 预加载图片,确认是否有效
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
console.log("二维码图片加载成功");
|
// 图片加载成功
|
||||||
};
|
};
|
||||||
img.onerror = (e) => {
|
img.onerror = (e) => {
|
||||||
console.error("二维码图片加载失败:", e);
|
|
||||||
toast({
|
toast({
|
||||||
title: "二维码加载失败",
|
title: "二维码加载失败",
|
||||||
description: "服务器返回的数据无法显示为图片",
|
description: "服务器返回的数据无法显示为图片",
|
||||||
@@ -288,7 +284,6 @@ export default function DevicesPage() {
|
|||||||
};
|
};
|
||||||
img.src = `data:image/png;base64,${cleanedBase64}`;
|
img.src = `data:image/png;base64,${cleanedBase64}`;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("处理base64数据出错:", e);
|
|
||||||
toast({
|
toast({
|
||||||
title: "获取二维码失败",
|
title: "获取二维码失败",
|
||||||
description: "图片数据处理失败",
|
description: "图片数据处理失败",
|
||||||
@@ -303,7 +298,6 @@ export default function DevicesPage() {
|
|||||||
description: "请使用手机扫描新的二维码添加设备",
|
description: "请使用手机扫描新的二维码添加设备",
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.error("获取二维码失败:", result);
|
|
||||||
toast({
|
toast({
|
||||||
title: "获取二维码失败",
|
title: "获取二维码失败",
|
||||||
description: result?.msg || "请稍后重试",
|
description: result?.msg || "请稍后重试",
|
||||||
@@ -311,7 +305,6 @@ export default function DevicesPage() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("获取二维码失败", error);
|
|
||||||
toast({
|
toast({
|
||||||
title: "获取二维码失败",
|
title: "获取二维码失败",
|
||||||
description: "请检查网络连接后重试",
|
description: "请检查网络连接后重试",
|
||||||
@@ -343,7 +336,6 @@ export default function DevicesPage() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
setIsSubmittingImei(true);
|
setIsSubmittingImei(true);
|
||||||
console.log("正在添加设备,IMEI:", deviceImei, "设备名称:", deviceName);
|
|
||||||
|
|
||||||
// 使用api.post发送请求到/v1/devices
|
// 使用api.post发送请求到/v1/devices
|
||||||
const response = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/v1/devices`, {
|
const response = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/v1/devices`, {
|
||||||
@@ -359,18 +351,14 @@ export default function DevicesPage() {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("添加设备响应状态:", response.status);
|
|
||||||
|
|
||||||
// 保存原始响应文本以便调试
|
// 保存原始响应文本以便调试
|
||||||
const responseText = await response.text();
|
const responseText = await response.text();
|
||||||
console.log("原始响应内容:", responseText);
|
|
||||||
|
|
||||||
// 尝试将响应解析为JSON
|
// 尝试将响应解析为JSON
|
||||||
let result;
|
let result;
|
||||||
try {
|
try {
|
||||||
result = JSON.parse(responseText);
|
result = JSON.parse(responseText);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("响应不是有效的JSON:", e);
|
|
||||||
toast({
|
toast({
|
||||||
title: "添加设备失败",
|
title: "添加设备失败",
|
||||||
description: "服务器返回的数据格式无效",
|
description: "服务器返回的数据格式无效",
|
||||||
@@ -379,8 +367,6 @@ export default function DevicesPage() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("添加设备响应:", result);
|
|
||||||
|
|
||||||
if (result && result.code === 200) {
|
if (result && result.code === 200) {
|
||||||
toast({
|
toast({
|
||||||
title: "设备添加成功",
|
title: "设备添加成功",
|
||||||
@@ -395,7 +381,6 @@ export default function DevicesPage() {
|
|||||||
// 刷新设备列表
|
// 刷新设备列表
|
||||||
loadDevices(1, true);
|
loadDevices(1, true);
|
||||||
} else {
|
} else {
|
||||||
console.error("添加设备失败:", result);
|
|
||||||
toast({
|
toast({
|
||||||
title: "添加设备失败",
|
title: "添加设备失败",
|
||||||
description: result?.msg || "请检查设备信息是否正确",
|
description: result?.msg || "请检查设备信息是否正确",
|
||||||
@@ -403,7 +388,6 @@ export default function DevicesPage() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("添加设备请求失败:", error);
|
|
||||||
toast({
|
toast({
|
||||||
title: "请求失败",
|
title: "请求失败",
|
||||||
description: "网络错误,请稍后重试",
|
description: "网络错误,请稍后重试",
|
||||||
@@ -675,7 +659,7 @@ export default function DevicesPage() {
|
|||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<Tabs defaultValue="scan" value={activeTab} onValueChange={setActiveTab} className="mt-4">
|
<Tabs defaultValue="scan" value={activeTab} onValueChange={setActiveTab} className="mt-4">
|
||||||
<TabsList className="grid grid-cols-2 w-full">
|
{/* <TabsList className="grid grid-cols-2 w-full">
|
||||||
<TabsTrigger value="scan" className="flex items-center">
|
<TabsTrigger value="scan" className="flex items-center">
|
||||||
<QrCode className="h-4 w-4 mr-2" />
|
<QrCode className="h-4 w-4 mr-2" />
|
||||||
扫码添加
|
扫码添加
|
||||||
@@ -684,7 +668,7 @@ export default function DevicesPage() {
|
|||||||
<Smartphone className="h-4 w-4 mr-2" />
|
<Smartphone className="h-4 w-4 mr-2" />
|
||||||
手动添加
|
手动添加
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList> */}
|
||||||
|
|
||||||
<TabsContent value="scan" className="space-y-4 py-4">
|
<TabsContent value="scan" className="space-y-4 py-4">
|
||||||
<div className="flex flex-col items-center justify-center p-6 space-y-4">
|
<div className="flex flex-col items-center justify-center p-6 space-y-4">
|
||||||
|
|||||||
@@ -20,18 +20,23 @@ const menuItems = [
|
|||||||
|
|
||||||
export default function ProfilePage() {
|
export default function ProfilePage() {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { isAuthenticated, user, logout } = useAuth()
|
|
||||||
const [showLogoutDialog, setShowLogoutDialog] = useState(false)
|
const [showLogoutDialog, setShowLogoutDialog] = useState(false)
|
||||||
|
const [userInfo, setUserInfo] = useState<any>(null)
|
||||||
|
|
||||||
// 处理身份验证状态,将路由重定向逻辑移至useEffect
|
// 从localStorage获取用户信息
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isAuthenticated) {
|
const userInfoStr = localStorage.getItem('userInfo')
|
||||||
router.push("/login")
|
if (userInfoStr) {
|
||||||
|
setUserInfo(JSON.parse(userInfoStr))
|
||||||
}
|
}
|
||||||
}, [isAuthenticated, router])
|
}, [])
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
logout() // 使用AuthProvider中的logout方法删除本地保存的用户信息
|
// 清除本地存储的用户信息
|
||||||
|
localStorage.removeItem('token')
|
||||||
|
localStorage.removeItem('token_expired')
|
||||||
|
localStorage.removeItem('s2_accountId')
|
||||||
|
localStorage.removeItem('userInfo')
|
||||||
setShowLogoutDialog(false)
|
setShowLogoutDialog(false)
|
||||||
router.push("/login")
|
router.push("/login")
|
||||||
}
|
}
|
||||||
@@ -57,14 +62,14 @@ export default function ProfilePage() {
|
|||||||
<Card className="p-6">
|
<Card className="p-6">
|
||||||
<div className="flex items-center space-x-4">
|
<div className="flex items-center space-x-4">
|
||||||
<Avatar className="w-20 h-20">
|
<Avatar className="w-20 h-20">
|
||||||
<AvatarImage src={user?.avatar || ""} />
|
<AvatarImage src={userInfo?.avatar || ""} />
|
||||||
<AvatarFallback>{user?.username ? user.username.slice(0, 2) : "用户"}</AvatarFallback>
|
<AvatarFallback>{userInfo?.username ? userInfo.username.slice(0, 2) : "用户"}</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h2 className="text-xl font-semibold text-blue-600">{user?.username || "用户"}</h2>
|
<h2 className="text-xl font-semibold text-blue-600">{userInfo?.username || "用户"}</h2>
|
||||||
<p className="text-gray-500">
|
<p className="text-gray-500">
|
||||||
账号: <ClientOnly fallback="加载中...">
|
账号: <ClientOnly fallback="加载中...">
|
||||||
{user?.account || Math.floor(10000000 + Math.random() * 90000000).toString()}
|
{userInfo?.account || Math.floor(10000000 + Math.random() * 90000000).toString()}
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { BasicSettings } from "../components/basic-settings"
|
|||||||
import { GroupSelector } from "../components/group-selector"
|
import { GroupSelector } from "../components/group-selector"
|
||||||
import { ContentSelector } from "../components/content-selector"
|
import { ContentSelector } from "../components/content-selector"
|
||||||
import type { WechatGroup, ContentLibrary } from "@/types/group-sync"
|
import type { WechatGroup, ContentLibrary } from "@/types/group-sync"
|
||||||
|
import { toast } from "@/components/ui/use-toast"
|
||||||
|
|
||||||
const steps = [
|
const steps = [
|
||||||
{ id: 1, title: "步骤 1", subtitle: "基础设置" },
|
{ id: 1, title: "步骤 1", subtitle: "基础设置" },
|
||||||
@@ -46,11 +47,39 @@ export default function NewGroupSyncPage() {
|
|||||||
setFormData((prev) => ({ ...prev, contentLibraries }))
|
setFormData((prev) => ({ ...prev, contentLibraries }))
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSave = () => {
|
const handleSubmit = async (formData: any) => {
|
||||||
// 这里可以添加保存逻辑,例如API调用
|
try {
|
||||||
console.log("保存表单数据:", formData)
|
const response = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/v1/api/group-sync`, {
|
||||||
router.push("/workspace/group-sync")
|
method: 'POST',
|
||||||
}
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${localStorage.getItem('token')}`
|
||||||
|
},
|
||||||
|
body: JSON.stringify(formData)
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.code === 200) {
|
||||||
|
toast({
|
||||||
|
title: "创建成功",
|
||||||
|
description: "群同步计划已创建",
|
||||||
|
});
|
||||||
|
router.push('/workspace/group-sync');
|
||||||
|
} else {
|
||||||
|
toast({
|
||||||
|
title: "创建失败",
|
||||||
|
description: data.msg || "请稍后重试",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
toast({
|
||||||
|
title: "创建失败",
|
||||||
|
description: "网络错误,请稍后重试",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
router.push("/workspace/group-sync")
|
router.push("/workspace/group-sync")
|
||||||
@@ -81,7 +110,7 @@ export default function NewGroupSyncPage() {
|
|||||||
isEnabled: formData.isEnabled,
|
isEnabled: formData.isEnabled,
|
||||||
}}
|
}}
|
||||||
onNext={handleBasicSettingsNext}
|
onNext={handleBasicSettingsNext}
|
||||||
onSave={handleSave}
|
onSave={handleSubmit}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -92,7 +121,7 @@ export default function NewGroupSyncPage() {
|
|||||||
onGroupsChange={handleGroupsChange}
|
onGroupsChange={handleGroupsChange}
|
||||||
onPrevious={() => setCurrentStep(1)}
|
onPrevious={() => setCurrentStep(1)}
|
||||||
onNext={() => setCurrentStep(3)}
|
onNext={() => setCurrentStep(3)}
|
||||||
onSave={handleSave}
|
onSave={handleSubmit}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -103,7 +132,7 @@ export default function NewGroupSyncPage() {
|
|||||||
onLibrariesChange={handleLibrariesChange}
|
onLibrariesChange={handleLibrariesChange}
|
||||||
onPrevious={() => setCurrentStep(2)}
|
onPrevious={() => setCurrentStep(2)}
|
||||||
onNext={() => setCurrentStep(4)}
|
onNext={() => setCurrentStep(4)}
|
||||||
onSave={handleSave}
|
onSave={handleSubmit}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -118,7 +147,7 @@ export default function NewGroupSyncPage() {
|
|||||||
<Button type="button" variant="outline" onClick={() => setCurrentStep(3)}>
|
<Button type="button" variant="outline" onClick={() => setCurrentStep(3)}>
|
||||||
上一步
|
上一步
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="button" onClick={handleSave}>
|
<Button type="button" onClick={handleSubmit}>
|
||||||
完成
|
完成
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="button" variant="outline" onClick={handleCancel}>
|
<Button type="button" variant="outline" onClick={handleCancel}>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"
|
|||||||
import { Slider } from "@/components/ui/slider"
|
import { Slider } from "@/components/ui/slider"
|
||||||
import { Badge } from "@/components/ui/badge"
|
import { Badge } from "@/components/ui/badge"
|
||||||
import { TrafficPoolSelector } from "@/app/components/traffic-pool-selector"
|
import { TrafficPoolSelector } from "@/app/components/traffic-pool-selector"
|
||||||
|
import { toast } from "@/components/ui/use-toast"
|
||||||
|
|
||||||
// 模拟数据
|
// 模拟数据
|
||||||
const planDetails = {
|
const planDetails = {
|
||||||
@@ -123,11 +124,39 @@ export default function EditTrafficDistributionPage({ params }: { params: { id:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = async (formData: any) => {
|
||||||
// 这里处理表单提交逻辑
|
try {
|
||||||
console.log("提交表单数据:", formData)
|
const response = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/v1/api/traffic-distribution/${params.id}`, {
|
||||||
router.push(`/workspace/traffic-distribution/${params.id}`)
|
method: 'PUT',
|
||||||
}
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${localStorage.getItem('token')}`
|
||||||
|
},
|
||||||
|
body: JSON.stringify(formData)
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.code === 200) {
|
||||||
|
toast({
|
||||||
|
title: "保存成功",
|
||||||
|
description: "流量分配计划已更新",
|
||||||
|
});
|
||||||
|
router.push('/workspace/traffic-distribution');
|
||||||
|
} else {
|
||||||
|
toast({
|
||||||
|
title: "保存失败",
|
||||||
|
description: data.msg || "请稍后重试",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
toast({
|
||||||
|
title: "保存失败",
|
||||||
|
description: "网络错误,请稍后重试",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const isStep1Valid = formData.name && formData.source
|
const isStep1Valid = formData.name && formData.source
|
||||||
const isStep2Valid = formData.targetGroups.length > 0 || formData.targetDevices.length > 0
|
const isStep2Valid = formData.targetGroups.length > 0 || formData.targetDevices.length > 0
|
||||||
@@ -463,7 +492,7 @@ export default function EditTrafficDistributionPage({ params }: { params: { id:
|
|||||||
<ArrowLeft className="mr-2 h-4 w-4" />
|
<ArrowLeft className="mr-2 h-4 w-4" />
|
||||||
上一步
|
上一步
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={handleSubmit} disabled={!isStep3Valid}>
|
<Button onClick={() => handleSubmit(formData)} disabled={!isStep3Valid}>
|
||||||
保存修改
|
保存修改
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use app\common\model\User as UserModel;
|
|||||||
use app\common\util\JwtUtil;
|
use app\common\util\JwtUtil;
|
||||||
use Exception;
|
use Exception;
|
||||||
use library\ResponseHelper;
|
use library\ResponseHelper;
|
||||||
use think\response\Json;
|
|
||||||
use think\Validate;
|
use think\Validate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,12 +23,16 @@ class PasswordLoginController extends BaseController
|
|||||||
*/
|
*/
|
||||||
protected function getUserProfileWithAccountAndType(string $account, int $typeId): UserModel
|
protected function getUserProfileWithAccountAndType(string $account, int $typeId): UserModel
|
||||||
{
|
{
|
||||||
$user = UserModel::where(function ($query) use ($account) {
|
$user = UserModel::where(
|
||||||
$query->where('phone', $account)->whereOr('account', $account);
|
function ($query) use ($account) {
|
||||||
})
|
$query->where('phone', $account)->whereOr('account', $account);
|
||||||
->where(function ($query) use ($typeId) {
|
}
|
||||||
$query->where('status', 1)->where('typeId', $typeId);
|
)
|
||||||
})->find();
|
->where(
|
||||||
|
function ($query) use ($typeId) {
|
||||||
|
$query->where('status', 1)->where('typeId', $typeId);
|
||||||
|
}
|
||||||
|
)->find();
|
||||||
|
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
@@ -54,7 +57,10 @@ class PasswordLoginController extends BaseController
|
|||||||
throw new \Exception('账号或密码错误', 403);
|
throw new \Exception('账号或密码错误', 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $user->toArray();
|
return array_merge($user->toArray(), [
|
||||||
|
'lastLoginIp' => $this->request->ip(),
|
||||||
|
'lastLoginTime' => time()
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -100,8 +106,8 @@ class PasswordLoginController extends BaseController
|
|||||||
$member = $this->getUser($account, $password, $typeId);
|
$member = $this->getUser($account, $password, $typeId);
|
||||||
|
|
||||||
// 生成JWT令牌
|
// 生成JWT令牌
|
||||||
$token = JwtUtil::createToken($member, 7200);
|
$token = JwtUtil::createToken($member, 86400);
|
||||||
$token_expired = time() + 7200;
|
$token_expired = time() + 86400;
|
||||||
|
|
||||||
return compact('member', 'token', 'token_expired');
|
return compact('member', 'token', 'token_expired');
|
||||||
}
|
}
|
||||||
@@ -109,7 +115,7 @@ class PasswordLoginController extends BaseController
|
|||||||
/**
|
/**
|
||||||
* 用户登录
|
* 用户登录
|
||||||
*
|
*
|
||||||
* @return Json
|
* @return \think\response\Json
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user