wo
This commit is contained in:
@@ -85,36 +85,105 @@ export default function LoginPage() {
|
|||||||
|
|
||||||
console.log("Login attempt:", loginData)
|
console.log("Login attempt:", loginData)
|
||||||
|
|
||||||
// 使用统一的 API 客户端发送登录请求
|
// 先调用登录接口
|
||||||
const result = await apiPost('/login', loginData)
|
const result = await apiPost('/login', loginData)
|
||||||
|
|
||||||
if (result.code === 200) {
|
if (result.code !== 200) {
|
||||||
// 获取选择的角色信息
|
|
||||||
const selectedRole = roles.find(role => role.roleId === formData.role)
|
|
||||||
|
|
||||||
// 登录成功,保存用户信息(包含 token 和角色信息)
|
|
||||||
const userData = {
|
|
||||||
username: formData.username,
|
|
||||||
role: formData.role,
|
|
||||||
roleId: formData.role, // 保存角色ID
|
|
||||||
roleName: selectedRole?.roleName || '', // 保存角色名称
|
|
||||||
roleKey: selectedRole?.roleKey || '', // 保存角色键
|
|
||||||
loginTime: new Date().toISOString(),
|
|
||||||
token: result.token, // 保存后端返回的 token
|
|
||||||
...result.data // 保存后端返回的其他用户信息
|
|
||||||
}
|
|
||||||
|
|
||||||
setStorageItem("user", JSON.stringify(userData))
|
|
||||||
|
|
||||||
// 刷新路由配置(根据新登录的用户角色获取路由)
|
|
||||||
await refreshRoutes()
|
|
||||||
|
|
||||||
// 跳转到管理后台
|
|
||||||
navigate("/admin")
|
|
||||||
} else {
|
|
||||||
// 登录失败,显示错误信息
|
// 登录失败,显示错误信息
|
||||||
alert(result.msg || '登录失败,请检查用户名和密码')
|
alert(result.msg || '登录失败,请检查用户名和密码')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("登录成功,开始验证路由数据")
|
||||||
|
|
||||||
|
// 临时保存 token,以便后续的 API 请求可以使用
|
||||||
|
const tempUserData = {
|
||||||
|
username: formData.username,
|
||||||
|
role: formData.role,
|
||||||
|
token: result.token,
|
||||||
|
}
|
||||||
|
setStorageItem("user", JSON.stringify(tempUserData))
|
||||||
|
|
||||||
|
// 登录成功后,验证该角色的路由数据是否有效
|
||||||
|
const routeValidationResult = await apiGet(`/getRoutersByRoleId?roleId=${formData.role}`)
|
||||||
|
|
||||||
|
if (routeValidationResult.code !== 200) {
|
||||||
|
alert(`路由验证失败: ${routeValidationResult.msg || '未知错误'},请联系管理员`)
|
||||||
|
// 清除临时保存的用户信息
|
||||||
|
setStorageItem("user", "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查路由数据是否存在
|
||||||
|
if (!routeValidationResult.data) {
|
||||||
|
alert('路由数据不存在,请联系管理员配置角色权限')
|
||||||
|
// 清除临时保存的用户信息
|
||||||
|
setStorageItem("user", "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证路由数据格式
|
||||||
|
const routeData = routeValidationResult.data
|
||||||
|
console.log("获取到的路由数据:", routeData)
|
||||||
|
|
||||||
|
if (!Array.isArray(routeData) || routeData.length === 0) {
|
||||||
|
alert('路由数据格式错误或为空,请联系管理员')
|
||||||
|
// 清除临时保存的用户信息
|
||||||
|
setStorageItem("user", "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证路由数据的基本字段(放宽验证条件)
|
||||||
|
const hasInvalidRoute = routeData.some((route: any) => {
|
||||||
|
console.log("验证路由项:", route)
|
||||||
|
|
||||||
|
// 必须有 path 字段
|
||||||
|
if (!route.path || typeof route.path !== 'string') {
|
||||||
|
console.error('无效的路由数据,缺少或错误的 path 字段:', route)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// name 字段不是必需的(某些布局路由可能没有 name)
|
||||||
|
// 只验证如果有 name 字段,它必须是字符串类型
|
||||||
|
if (route.name !== undefined && typeof route.name !== 'string') {
|
||||||
|
console.error('无效的路由数据,name 字段类型错误:', route)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
if (hasInvalidRoute) {
|
||||||
|
alert('路由数据包含错误信息,请联系管理员检查配置')
|
||||||
|
// 清除临时保存的用户信息
|
||||||
|
setStorageItem("user", "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("路由数据验证通过,保存用户信息并跳转")
|
||||||
|
|
||||||
|
// 获取选择的角色信息
|
||||||
|
const selectedRole = roles.find(role => role.roleId === formData.role)
|
||||||
|
|
||||||
|
// 登录成功且路由验证通过,保存用户信息(包含 token 和角色信息)
|
||||||
|
const userData = {
|
||||||
|
username: formData.username,
|
||||||
|
role: formData.role,
|
||||||
|
roleId: formData.role, // 保存角色ID
|
||||||
|
roleName: selectedRole?.roleName || '', // 保存角色名称
|
||||||
|
roleKey: selectedRole?.roleKey || '', // 保存角色键
|
||||||
|
loginTime: new Date().toISOString(),
|
||||||
|
token: result.token, // 保存后端返回的 token
|
||||||
|
...result.data // 保存后端返回的其他用户信息
|
||||||
|
}
|
||||||
|
|
||||||
|
setStorageItem("user", JSON.stringify(userData))
|
||||||
|
|
||||||
|
// 刷新路由配置(根据新登录的用户角色获取路由)
|
||||||
|
await refreshRoutes()
|
||||||
|
|
||||||
|
// 跳转到管理后台
|
||||||
|
navigate("/admin")
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('登录请求失败:', error)
|
console.error('登录请求失败:', error)
|
||||||
alert('网络错误,请稍后重试')
|
alert('网络错误,请稍后重试')
|
||||||
|
@@ -95,6 +95,8 @@ export default function MallsPage() {
|
|||||||
const [mallUsers, setMallUsers] = useState<MallUser[]>([])
|
const [mallUsers, setMallUsers] = useState<MallUser[]>([])
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [userRole, setUserRole] = useState<string>("")
|
const [userRole, setUserRole] = useState<string>("")
|
||||||
|
const [mallMerchants, setMallMerchants] = useState<{[key: string]: any[]}>({})
|
||||||
|
const [loadingMallMerchants, setLoadingMallMerchants] = useState<{[key: string]: boolean}>({})
|
||||||
const [newMall, setNewMall] = useState({
|
const [newMall, setNewMall] = useState({
|
||||||
name: "",
|
name: "",
|
||||||
address: "",
|
address: "",
|
||||||
@@ -171,6 +173,27 @@ export default function MallsPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取商场下的商户列表
|
||||||
|
const fetchMallMerchants = async (mallId: string) => {
|
||||||
|
if (!mallId) return []
|
||||||
|
|
||||||
|
setLoadingMallMerchants(prev => ({ ...prev, [mallId]: true }))
|
||||||
|
try {
|
||||||
|
const response = await apiGet(`/back/merchants/list?mallId=${mallId}`)
|
||||||
|
if (response.code === 200) {
|
||||||
|
const merchants = response.rows || []
|
||||||
|
setMallMerchants(prev => ({ ...prev, [mallId]: merchants }))
|
||||||
|
return merchants
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`获取商场${mallId}商户列表失败:`, error)
|
||||||
|
return []
|
||||||
|
} finally {
|
||||||
|
setLoadingMallMerchants(prev => ({ ...prev, [mallId]: false }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 页面加载时获取数据
|
// 页面加载时获取数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchUserRole()
|
fetchUserRole()
|
||||||
@@ -234,8 +257,19 @@ export default function MallsPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const toggleMallExpansion = (mallId: string) => {
|
const toggleMallExpansion = (mall: Mall) => {
|
||||||
setExpandedMalls((prev) => (prev.includes(mallId) ? prev.filter((id) => id !== mallId) : [...prev, mallId]))
|
const isExpanding = !expandedMalls.includes(mall.id)
|
||||||
|
|
||||||
|
setExpandedMalls((prev) =>
|
||||||
|
prev.includes(mall.id)
|
||||||
|
? prev.filter((id) => id !== mall.id)
|
||||||
|
: [...prev, mall.id]
|
||||||
|
)
|
||||||
|
|
||||||
|
// 如果是展开操作,获取该商场的商户列表
|
||||||
|
if (isExpanding && mall.mallId) {
|
||||||
|
fetchMallMerchants(mall.mallId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getStatusBadge = (status: string) => {
|
const getStatusBadge = (status: string) => {
|
||||||
@@ -442,7 +476,7 @@ export default function MallsPage() {
|
|||||||
<div key={mall.id} className="border rounded-lg">
|
<div key={mall.id} className="border rounded-lg">
|
||||||
<div
|
<div
|
||||||
className="w-full p-4 flex items-center justify-between hover:bg-gray-50 transition-colors cursor-pointer"
|
className="w-full p-4 flex items-center justify-between hover:bg-gray-50 transition-colors cursor-pointer"
|
||||||
onClick={() => toggleMallExpansion(mall.id)}
|
onClick={() => toggleMallExpansion(mall)}
|
||||||
>
|
>
|
||||||
<div className="flex items-center space-x-4">
|
<div className="flex items-center space-x-4">
|
||||||
{expandedMalls.includes(mall.id) ? (
|
{expandedMalls.includes(mall.id) ? (
|
||||||
@@ -495,10 +529,49 @@ export default function MallsPage() {
|
|||||||
<div className="px-4 pb-4 border-t bg-gray-50">
|
<div className="px-4 pb-4 border-t bg-gray-50">
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
<h4 className="font-medium mb-3">商户列表</h4>
|
<h4 className="font-medium mb-3">商户列表</h4>
|
||||||
<div className="text-center py-8 text-gray-500">
|
{loadingMallMerchants[mall.mallId || ''] ? (
|
||||||
<Store className="h-8 w-8 mx-auto mb-2 opacity-50" />
|
<div className="text-center py-8 text-gray-500">
|
||||||
<p>该商场暂无商户入驻</p>
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900 mx-auto"></div>
|
||||||
</div>
|
<p className="mt-2">加载中...</p>
|
||||||
|
</div>
|
||||||
|
) : (mallMerchants[mall.mallId || ''] || []).length > 0 ? (
|
||||||
|
<div className="space-y-3">
|
||||||
|
{(mallMerchants[mall.mallId || ''] || []).map((merchant: any) => (
|
||||||
|
<div key={merchant.id} className="bg-white p-4 rounded-lg border hover:shadow-sm transition-shadow">
|
||||||
|
<div className="flex items-start justify-between">
|
||||||
|
<div className="flex-1">
|
||||||
|
<div className="flex items-center space-x-2 mb-2">
|
||||||
|
<Store className="h-4 w-4 text-blue-600" />
|
||||||
|
<span className="font-medium">{merchant.merchantName}</span>
|
||||||
|
<Badge className={merchant.status === "1" ? "bg-green-100 text-green-800" : "bg-red-100 text-red-800"}>
|
||||||
|
{merchant.status === "1" ? "正常" : "停用"}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-2 gap-2 text-sm text-gray-600">
|
||||||
|
<div>
|
||||||
|
<span className="font-medium">联系人:</span>
|
||||||
|
{merchant.contactPerson || '无'}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span className="font-medium">电话:</span>
|
||||||
|
{merchant.contactPhone || '无'}
|
||||||
|
</div>
|
||||||
|
<div className="col-span-2 flex items-start">
|
||||||
|
<MapPin className="h-3 w-3 mr-1 mt-0.5 flex-shrink-0" />
|
||||||
|
<span>{merchant.fullAddress || merchant.detailedAddress || '无'}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="text-center py-8 text-gray-500">
|
||||||
|
<Store className="h-8 w-8 mx-auto mb-2 opacity-50" />
|
||||||
|
<p>该商场暂无商户入驻</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
Reference in New Issue
Block a user