diff --git a/src/components/pages/MallsPage.tsx b/src/components/pages/MallsPage.tsx index f760a8e..28880a6 100644 --- a/src/components/pages/MallsPage.tsx +++ b/src/components/pages/MallsPage.tsx @@ -4,6 +4,7 @@ import { Button } from "../ui/button" import { Input } from "../ui/input" import { Card, CardContent, CardHeader, CardTitle } from "../ui/card" import { Badge } from "../ui/badge" +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../ui/table" import { Dialog, DialogContent, @@ -28,6 +29,7 @@ import { Store, Edit, Trash2, + Eye, } from "lucide-react" // 省份数据类型 @@ -97,6 +99,10 @@ export default function MallsPage() { const [userRole, setUserRole] = useState("") const [mallMerchants, setMallMerchants] = useState<{[key: string]: any[]}>({}) const [loadingMallMerchants, setLoadingMallMerchants] = useState<{[key: string]: boolean}>({}) + const [selectedMerchant, setSelectedMerchant] = useState(null) + const [isEquipmentDialogOpen, setIsEquipmentDialogOpen] = useState(false) + const [merchantEquipments, setMerchantEquipments] = useState([]) + const [loadingEquipments, setLoadingEquipments] = useState(false) const [newMall, setNewMall] = useState({ name: "", address: "", @@ -181,9 +187,24 @@ export default function MallsPage() { 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 + const merchantsData = response.rows || [] + + // 为每个商户获取设备数量 + const merchantsWithCounts = await Promise.all( + merchantsData.map(async (merchant: any) => { + const equipmentCount = await fetchMerchantEquipmentCount(merchant.merchantsId || merchant.id) + return { + ...merchant, + equipmentCount: equipmentCount?.totalCount || 0, + normalCount: equipmentCount?.count || 0, + expiringCount: equipmentCount?.countEnd || 0, + expiredCount: equipmentCount?.countExpire || 0 + } + }) + ) + + setMallMerchants(prev => ({ ...prev, [mallId]: merchantsWithCounts })) + return merchantsWithCounts } return [] } catch (error) { @@ -194,6 +215,64 @@ export default function MallsPage() { } } + // 获取单个商户的设备数量 + const fetchMerchantEquipmentCount = async (merchantId: string) => { + try { + const response = await apiGet(`/back/equipment/merchant/${merchantId}/count`) + if (response.code === 200) { + return response.data + } + return null + } catch (error) { + console.error(`获取商户${merchantId}设备数量失败:`, error) + return null + } + } + + // 获取商户设备列表 + const fetchMerchantEquipments = async (merchantId: string) => { + setLoadingEquipments(true) + try { + const response = await apiGet(`/back/equipment/list?pageNum=1&pageSize=100&merchantId=${merchantId}`) + if (response.code === 200) { + setMerchantEquipments(response.rows || []) + return response.rows || [] + } + return [] + } catch (error) { + console.error(`获取商户${merchantId}设备列表失败:`, error) + setMerchantEquipments([]) + return [] + } finally { + setLoadingEquipments(false) + } + } + + // 打开设备查看对话框 + const handleViewEquipment = (merchant: any) => { + setSelectedMerchant(merchant) + setIsEquipmentDialogOpen(true) + const merchantId = merchant.merchantsId || merchant.id + fetchMerchantEquipments(merchantId) + } + + // 获取设备状态徽章 + const getEquipmentStatusBadge = (status: string) => { + switch (status) { + case "1": + case "normal": + return 正常 + case "2": + case "expiring": + return 即将到期 + case "3": + case "expired": + return 已过期 + default: + return 未知 + } + } + // 页面加载时获取数据 useEffect(() => { fetchUserRole() @@ -535,39 +614,76 @@ export default function MallsPage() {

加载中...

) : (mallMerchants[mall.mallId || ''] || []).length > 0 ? ( -
- {(mallMerchants[mall.mallId || ''] || []).map((merchant: any) => ( -
-
-
-
- - {merchant.merchantName} +
+ + + + 商户编号 + 商户名称 + 联系人 + 地址 + 设备数量 + 状态 + 操作 + + + + {(mallMerchants[mall.mallId || ''] || []).map((merchant: any) => ( + + {merchant.id} + +
+ + {merchant.merchantName} +
+
+ +
+

{merchant.contactPerson || '无'}

+

{merchant.contactPhone || '无'}

+
+
+ +
+ +
+

{merchant.detailedAddress || '无'}

+

{merchant.fullAddress || ''}

+
+
+
+ +
+

{merchant.equipmentCount || 0}

+
+ {merchant.normalCount || 0} + {merchant.expiringCount || 0} + {merchant.expiredCount || 0} +
+
+
+ {merchant.status === "1" ? "正常" : "停用"} - -
-
- 联系人: - {merchant.contactPerson || '无'} -
-
- 电话: - {merchant.contactPhone || '无'} -
-
- - {merchant.fullAddress || merchant.detailedAddress || '无'} -
-
- - - - ))} +
+ + + +
+ ))} +
+
) : ( -
+

该商场暂无商户入驻

@@ -580,6 +696,99 @@ export default function MallsPage() {
+ + {/* 设备详情对话框 */} + + + + {selectedMerchant?.merchantName} - 设备详情 + 查看该商户的所有设备信息和状态 + +
+
+ + +
+

{selectedMerchant?.normalCount || 0}

+

正常设备

+
+
+
+ + +
+

{selectedMerchant?.expiringCount || 0}

+

即将到期

+
+
+
+ + +
+

{selectedMerchant?.expiredCount || 0}

+

已过期

+
+
+
+
+ +
+
+ + + + 设备编号 + 设备名称 + 类型 + 安装日期 + 安装位置 + 状态 + + + + {loadingEquipments ? ( + + + 加载中... + + + ) : merchantEquipments.length > 0 ? ( + merchantEquipments.map((equipment: any) => ( + + + {equipment.equipmentId} + + + {equipment.equipmentName} + + + {equipment.equipmentType} + + + {equipment.installationDate} + + + {equipment.installationLocation} + + + {getEquipmentStatusBadge(equipment.status)} + + + )) + ) : ( + + + 暂无设备数据 + + + )} + +
+
+
+
+
+
) } diff --git a/vite.config.ts b/vite.config.ts index 643134c..02e2000 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -16,6 +16,11 @@ export default defineConfig({ }, server: { port: 3000, + host: true, // 允许外部访问 + allowedHosts: [ + 'pc687bfe.natappfree.cc', + '.natappfree.cc', // 允许所有 natappfree.cc 子域名 + ], }, })