111
This commit is contained in:
@@ -9,6 +9,7 @@ import UsersPage from './components/pages/UsersPage'
|
|||||||
import EquipmentPage from './components/pages/EquipmentPage'
|
import EquipmentPage from './components/pages/EquipmentPage'
|
||||||
import StatisticsPage from './components/pages/StatisticsPage'
|
import StatisticsPage from './components/pages/StatisticsPage'
|
||||||
import MallsPage from './components/pages/MallsPage'
|
import MallsPage from './components/pages/MallsPage'
|
||||||
|
import VersionPage from './components/pages/VersionPage'
|
||||||
import DynamicPage from './components/DynamicPage'
|
import DynamicPage from './components/DynamicPage'
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
@@ -25,6 +26,7 @@ function App() {
|
|||||||
<Route path="users" element={<UsersPage />} />
|
<Route path="users" element={<UsersPage />} />
|
||||||
<Route path="equipment" element={<EquipmentPage />} />
|
<Route path="equipment" element={<EquipmentPage />} />
|
||||||
<Route path="malls" element={<MallsPage />} />
|
<Route path="malls" element={<MallsPage />} />
|
||||||
|
<Route path="version" element={<VersionPage />} />
|
||||||
<Route path=":slug" element={<DynamicPage />} />
|
<Route path=":slug" element={<DynamicPage />} />
|
||||||
<Route path=":slug/*" element={<DynamicPage />} />
|
<Route path=":slug/*" element={<DynamicPage />} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogTrigger,
|
DialogTrigger,
|
||||||
} from "../ui/dialog"
|
} from "../ui/dialog"
|
||||||
import { Plus, Search, Filter, Download, Calendar, AlertTriangle, Store, Eye, Building2, MapPin } from "lucide-react"
|
import { Plus, Search, Filter, Download, Calendar, AlertTriangle, Store, Eye, Building2, MapPin, ChevronLeft, ChevronRight } from "lucide-react"
|
||||||
import { apiGet, apiPost, apiPut } from "../../lib/services/api"
|
import { apiGet, apiPost, apiPut } from "../../lib/services/api"
|
||||||
|
|
||||||
// 总商户数据类型
|
// 总商户数据类型
|
||||||
@@ -77,6 +77,8 @@ export default function MerchantsPage() {
|
|||||||
const [merchantEquipments, setMerchantEquipments] = useState<{[key: string]: any[]}>({})
|
const [merchantEquipments, setMerchantEquipments] = useState<{[key: string]: any[]}>({})
|
||||||
const [loadingMerchantEquipments, setLoadingMerchantEquipments] = useState<{[key: string]: boolean}>({})
|
const [loadingMerchantEquipments, setLoadingMerchantEquipments] = useState<{[key: string]: boolean}>({})
|
||||||
const [userRole, setUserRole] = useState<string>("")
|
const [userRole, setUserRole] = useState<string>("")
|
||||||
|
const [currentPage, setCurrentPage] = useState(1)
|
||||||
|
const [pageSize, setPageSize] = useState(10)
|
||||||
|
|
||||||
const [newMerchant, setNewMerchant] = useState({
|
const [newMerchant, setNewMerchant] = useState({
|
||||||
name: "",
|
name: "",
|
||||||
@@ -213,10 +215,10 @@ export default function MerchantsPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取商户列表
|
// 获取商户列表
|
||||||
const fetchMerchants = async () => {
|
const fetchMerchants = async (page = currentPage, size = pageSize) => {
|
||||||
setLoadingMerchants(true)
|
setLoadingMerchants(true)
|
||||||
try {
|
try {
|
||||||
const response = await apiGet('/back/merchants/list')
|
const response = await apiGet(`/back/merchants/list?pageNum=${page}&pageSize=${size}`)
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
const merchantsData = response.rows || []
|
const merchantsData = response.rows || []
|
||||||
setTotal(parseInt(response.total) || 0)
|
setTotal(parseInt(response.total) || 0)
|
||||||
@@ -245,6 +247,19 @@ export default function MerchantsPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 页码变化处理
|
||||||
|
const handlePageChange = (page: number) => {
|
||||||
|
setCurrentPage(page)
|
||||||
|
fetchMerchants(page, pageSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 每页大小变化处理
|
||||||
|
const handlePageSizeChange = (size: number) => {
|
||||||
|
setPageSize(size)
|
||||||
|
setCurrentPage(1)
|
||||||
|
fetchMerchants(1, size)
|
||||||
|
}
|
||||||
|
|
||||||
// 组件加载时获取数据
|
// 组件加载时获取数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchUserRole()
|
fetchUserRole()
|
||||||
@@ -323,7 +338,7 @@ export default function MerchantsPage() {
|
|||||||
setIsAddMerchantOpen(false)
|
setIsAddMerchantOpen(false)
|
||||||
|
|
||||||
// 刷新商户列表
|
// 刷新商户列表
|
||||||
fetchMerchants()
|
fetchMerchants(currentPage, pageSize)
|
||||||
} else {
|
} else {
|
||||||
console.error('添加商户失败:', result)
|
console.error('添加商户失败:', result)
|
||||||
alert('添加商户失败:' + (result.msg || '未知错误'))
|
alert('添加商户失败:' + (result.msg || '未知错误'))
|
||||||
@@ -460,7 +475,7 @@ export default function MerchantsPage() {
|
|||||||
console.log('编辑商户成功:', result)
|
console.log('编辑商户成功:', result)
|
||||||
alert('编辑商户成功!')
|
alert('编辑商户成功!')
|
||||||
setIsEditMerchantOpen(false)
|
setIsEditMerchantOpen(false)
|
||||||
fetchMerchants()
|
fetchMerchants(currentPage, pageSize)
|
||||||
} else {
|
} else {
|
||||||
console.error('编辑商户失败:', result)
|
console.error('编辑商户失败:', result)
|
||||||
alert('编辑商户失败:' + (result.msg || '未知错误'))
|
alert('编辑商户失败:' + (result.msg || '未知错误'))
|
||||||
@@ -576,7 +591,7 @@ export default function MerchantsPage() {
|
|||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>商户列表</CardTitle>
|
<CardTitle>商户列表</CardTitle>
|
||||||
<CardDescription>查看和管理所有商户信息及设备状态</CardDescription>
|
<CardDescription>查看和管理所有商户信息及设备状态 - 共 {total} 条记录,当前第 {currentPage} 页</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="flex flex-col sm:flex-row gap-4 mb-6">
|
<div className="flex flex-col sm:flex-row gap-4 mb-6">
|
||||||
@@ -705,6 +720,56 @@ export default function MerchantsPage() {
|
|||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Pagination */}
|
||||||
|
<div className="flex items-center justify-between space-x-2 py-4">
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<p className="text-sm font-medium">每页显示</p>
|
||||||
|
<Select
|
||||||
|
value={pageSize.toString()}
|
||||||
|
onValueChange={(value) => handlePageSizeChange(parseInt(value))}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="h-8 w-[70px]">
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent side="top">
|
||||||
|
<SelectItem value="5">5</SelectItem>
|
||||||
|
<SelectItem value="10">10</SelectItem>
|
||||||
|
<SelectItem value="20">20</SelectItem>
|
||||||
|
<SelectItem value="50">50</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
共 {total} 条记录
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<p className="text-sm font-medium">
|
||||||
|
第 {currentPage} 页,共 {Math.ceil(total / pageSize)} 页
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center space-x-1">
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => handlePageChange(currentPage - 1)}
|
||||||
|
disabled={currentPage <= 1 || loadingMerchants}
|
||||||
|
>
|
||||||
|
<ChevronLeft className="h-4 w-4" />
|
||||||
|
<span className="sr-only">上一页</span>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => handlePageChange(currentPage + 1)}
|
||||||
|
disabled={currentPage >= Math.ceil(total / pageSize) || loadingMerchants}
|
||||||
|
>
|
||||||
|
<ChevronRight className="h-4 w-4" />
|
||||||
|
<span className="sr-only">下一页</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
|||||||
803
src/components/pages/VersionPage.tsx
Normal file
803
src/components/pages/VersionPage.tsx
Normal file
@@ -0,0 +1,803 @@
|
|||||||
|
import React, { useState, useEffect } from "react"
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from "../ui/card"
|
||||||
|
import { Button } from "../ui/button"
|
||||||
|
import { Input } from "../ui/input"
|
||||||
|
import { Badge } from "../ui/badge"
|
||||||
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../ui/table"
|
||||||
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select"
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from "../ui/dialog"
|
||||||
|
import { Label } from "../ui/label"
|
||||||
|
import { Textarea } from "../ui/textarea"
|
||||||
|
import {
|
||||||
|
Plus,
|
||||||
|
Search,
|
||||||
|
Download,
|
||||||
|
Edit,
|
||||||
|
Trash2,
|
||||||
|
Upload,
|
||||||
|
RefreshCw,
|
||||||
|
ChevronLeft,
|
||||||
|
ChevronRight,
|
||||||
|
} from "lucide-react"
|
||||||
|
import { apiGet, apiPost, apiPut, apiDelete } from "../../lib/services/api"
|
||||||
|
import { getUserToken } from "../../lib/utils/storage"
|
||||||
|
|
||||||
|
// 版本信息数据类型接口
|
||||||
|
interface Version {
|
||||||
|
id: string
|
||||||
|
versionCode: number
|
||||||
|
versionName: string
|
||||||
|
isForce: string
|
||||||
|
channel: string
|
||||||
|
downloadUrl: string
|
||||||
|
updateLog: string
|
||||||
|
size: string
|
||||||
|
createTime: string
|
||||||
|
updateTime: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 渠道中文名称映射
|
||||||
|
const channelNameMap: Record<string, string> = {
|
||||||
|
'official': '官方',
|
||||||
|
'xiaomi': '小米',
|
||||||
|
'huawei': '华为',
|
||||||
|
'oppo': 'OPPO',
|
||||||
|
'vivo': 'VIVO',
|
||||||
|
'meizu': '魅族',
|
||||||
|
'honor': '荣耀',
|
||||||
|
'yingyongbao': '应用宝',
|
||||||
|
'ios': 'iOS'
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function VersionPage() {
|
||||||
|
const [versions, setVersions] = useState<Version[]>([])
|
||||||
|
const [channels, setChannels] = useState<string[]>([])
|
||||||
|
const [searchTerm, setSearchTerm] = useState("")
|
||||||
|
const [isForceFilter, setIsForceFilter] = useState("all")
|
||||||
|
const [channelFilter, setChannelFilter] = useState("all")
|
||||||
|
const [isAddDialogOpen, setIsAddDialogOpen] = useState(false)
|
||||||
|
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false)
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [submitting, setSubmitting] = useState(false)
|
||||||
|
const [currentPage, setCurrentPage] = useState(1)
|
||||||
|
const [pageSize, setPageSize] = useState(10)
|
||||||
|
const [total, setTotal] = useState(0)
|
||||||
|
const [selectedFile, setSelectedFile] = useState<File | null>(null)
|
||||||
|
const [uploadProgress, setUploadProgress] = useState(0)
|
||||||
|
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
versionName: "",
|
||||||
|
versionCode: 4,
|
||||||
|
isForce: "0",
|
||||||
|
channel: "",
|
||||||
|
downloadUrl: "",
|
||||||
|
updateLog: "",
|
||||||
|
size: "",
|
||||||
|
})
|
||||||
|
|
||||||
|
const [editData, setEditData] = useState<Version | null>(null)
|
||||||
|
|
||||||
|
// 获取版本列表
|
||||||
|
const fetchVersions = async (page = currentPage, size = pageSize) => {
|
||||||
|
setLoading(true)
|
||||||
|
try {
|
||||||
|
const params: any = {
|
||||||
|
pageNum: page,
|
||||||
|
pageSize: size,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchTerm) params.versionName = searchTerm
|
||||||
|
if (isForceFilter !== "all") params.isForce = isForceFilter
|
||||||
|
if (channelFilter !== "all") params.channel = channelFilter
|
||||||
|
|
||||||
|
const response = await apiGet('/back/version/list', params)
|
||||||
|
if (response.code === 200) {
|
||||||
|
setVersions(response.rows || [])
|
||||||
|
setTotal(parseInt(response.total) || 0)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取版本列表失败:', error)
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取渠道列表
|
||||||
|
const fetchChannels = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiGet('/back/version/getChannel')
|
||||||
|
if (response.code === 200) {
|
||||||
|
setChannels(response.data || [])
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取渠道列表失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组件加载时获取数据
|
||||||
|
useEffect(() => {
|
||||||
|
fetchVersions()
|
||||||
|
fetchChannels()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
// 分页变化时重新获取数据
|
||||||
|
useEffect(() => {
|
||||||
|
fetchVersions(currentPage, pageSize)
|
||||||
|
}, [currentPage, pageSize])
|
||||||
|
|
||||||
|
// 处理文件选择
|
||||||
|
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const file = e.target.files?.[0]
|
||||||
|
if (!file) {
|
||||||
|
console.log('没有选择文件')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('选择的文件:', file.name, '大小:', file.size)
|
||||||
|
|
||||||
|
// 检查文件大小(500MB限制)
|
||||||
|
const maxSize = 500 * 1024 * 1024
|
||||||
|
if (file.size > maxSize) {
|
||||||
|
alert('上传文件大小不能超过 500MB!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelectedFile(file)
|
||||||
|
|
||||||
|
// 计算文件大小
|
||||||
|
const fileSize = file.size
|
||||||
|
let sizeText = ''
|
||||||
|
if (fileSize < 1024) {
|
||||||
|
sizeText = fileSize + ' B'
|
||||||
|
} else if (fileSize < 1024 * 1024) {
|
||||||
|
sizeText = (fileSize / 1024).toFixed(2) + ' KB'
|
||||||
|
} else if (fileSize < 1024 * 1024 * 1024) {
|
||||||
|
sizeText = (fileSize / (1024 * 1024)).toFixed(2) + ' MB'
|
||||||
|
} else {
|
||||||
|
sizeText = (fileSize / (1024 * 1024 * 1024)).toFixed(2) + ' GB'
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('文件大小:', sizeText)
|
||||||
|
|
||||||
|
if (isEditDialogOpen && editData) {
|
||||||
|
setEditData({ ...editData, size: sizeText })
|
||||||
|
} else {
|
||||||
|
setFormData({ ...formData, size: sizeText })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传文件
|
||||||
|
console.log('开始上传文件...')
|
||||||
|
await uploadFile(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传文件到服务器
|
||||||
|
const uploadFile = async (file: File) => {
|
||||||
|
console.log('uploadFile 函数被调用')
|
||||||
|
const formDataUpload = new FormData()
|
||||||
|
formDataUpload.append('file', file)
|
||||||
|
|
||||||
|
console.log('准备上传的文件:', file.name)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const token = getUserToken()
|
||||||
|
console.log('Token:', token ? '存在' : '不存在')
|
||||||
|
|
||||||
|
// 使用当前页面的域名和端口,自动适配开发和生产环境
|
||||||
|
const baseUrl = window.location.origin.includes('localhost')
|
||||||
|
? 'http://localhost:8080/api'
|
||||||
|
: '/api'
|
||||||
|
const url = `${baseUrl}/back/version/upload`
|
||||||
|
console.log('上传URL:', url)
|
||||||
|
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${token}`
|
||||||
|
},
|
||||||
|
body: formDataUpload
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('响应状态:', response.status)
|
||||||
|
const result = await response.json()
|
||||||
|
console.log('响应结果:', result)
|
||||||
|
|
||||||
|
if (result.code === 200) {
|
||||||
|
if (isEditDialogOpen && editData) {
|
||||||
|
setEditData({ ...editData, downloadUrl: result.data })
|
||||||
|
} else {
|
||||||
|
setFormData({ ...formData, downloadUrl: result.data })
|
||||||
|
}
|
||||||
|
alert('文件上传成功')
|
||||||
|
} else {
|
||||||
|
alert('文件上传失败:' + result.msg)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('文件上传失败:', error)
|
||||||
|
alert('文件上传失败: ' + (error instanceof Error ? error.message : '未知错误'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加版本
|
||||||
|
const handleAddVersion = async () => {
|
||||||
|
if (!formData.versionName || !formData.versionCode || !formData.channel || !formData.downloadUrl) {
|
||||||
|
alert('请填写所有必填字段')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setSubmitting(true)
|
||||||
|
try {
|
||||||
|
const response = await apiPost('/back/version', {
|
||||||
|
...formData,
|
||||||
|
versionCode: Number(formData.versionCode)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (response.code === 200) {
|
||||||
|
alert('新增成功')
|
||||||
|
setIsAddDialogOpen(false)
|
||||||
|
resetForm()
|
||||||
|
fetchVersions(currentPage, pageSize)
|
||||||
|
} else {
|
||||||
|
alert('新增失败:' + response.msg)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('新增版本失败:', error)
|
||||||
|
alert('新增失败,请稍后重试')
|
||||||
|
} finally {
|
||||||
|
setSubmitting(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开编辑对话框
|
||||||
|
const handleEditVersion = async (version: Version) => {
|
||||||
|
setEditData(version)
|
||||||
|
setIsEditDialogOpen(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新版本
|
||||||
|
const handleUpdateVersion = async () => {
|
||||||
|
if (!editData) return
|
||||||
|
|
||||||
|
if (!editData.versionName || !editData.versionCode || !editData.channel || !editData.downloadUrl) {
|
||||||
|
alert('请填写所有必填字段')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setSubmitting(true)
|
||||||
|
try {
|
||||||
|
const response = await apiPut('/back/version', {
|
||||||
|
...editData,
|
||||||
|
versionCode: Number(editData.versionCode)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (response.code === 200) {
|
||||||
|
alert('修改成功')
|
||||||
|
setIsEditDialogOpen(false)
|
||||||
|
setEditData(null)
|
||||||
|
fetchVersions(currentPage, pageSize)
|
||||||
|
} else {
|
||||||
|
alert('修改失败:' + response.msg)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('修改版本失败:', error)
|
||||||
|
alert('修改失败,请稍后重试')
|
||||||
|
} finally {
|
||||||
|
setSubmitting(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除版本
|
||||||
|
const handleDeleteVersion = async (id: string) => {
|
||||||
|
if (!window.confirm('是否确认删除该版本信息?')) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await apiDelete(`/back/version/${id}`)
|
||||||
|
if (response.code === 200) {
|
||||||
|
alert('删除成功')
|
||||||
|
fetchVersions(currentPage, pageSize)
|
||||||
|
} else {
|
||||||
|
alert('删除失败:' + response.msg)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('删除版本失败:', error)
|
||||||
|
alert('删除失败,请稍后重试')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置表单
|
||||||
|
const resetForm = () => {
|
||||||
|
setFormData({
|
||||||
|
versionName: "",
|
||||||
|
versionCode: 4,
|
||||||
|
isForce: "0",
|
||||||
|
channel: "",
|
||||||
|
downloadUrl: "",
|
||||||
|
updateLog: "",
|
||||||
|
size: "",
|
||||||
|
})
|
||||||
|
setSelectedFile(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索
|
||||||
|
const handleSearch = () => {
|
||||||
|
setCurrentPage(1)
|
||||||
|
fetchVersions(1, pageSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置搜索
|
||||||
|
const handleReset = () => {
|
||||||
|
setSearchTerm("")
|
||||||
|
setIsForceFilter("all")
|
||||||
|
setChannelFilter("all")
|
||||||
|
setCurrentPage(1)
|
||||||
|
fetchVersions(1, pageSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出
|
||||||
|
const handleExport = () => {
|
||||||
|
// 实现导出功能
|
||||||
|
alert('导出功能开发中')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页处理
|
||||||
|
const handlePageChange = (page: number) => {
|
||||||
|
setCurrentPage(page)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePageSizeChange = (size: number) => {
|
||||||
|
setPageSize(size)
|
||||||
|
setCurrentPage(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
{/* 页面标题 */}
|
||||||
|
<div>
|
||||||
|
<h1 className="text-3xl font-bold text-gray-900">版本管理</h1>
|
||||||
|
<p className="text-gray-600">管理应用版本更新信息</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 搜索表单 */}
|
||||||
|
<Card>
|
||||||
|
<CardContent className="pt-6">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-4 mb-4">
|
||||||
|
<div>
|
||||||
|
<Label>版本名称</Label>
|
||||||
|
<Input
|
||||||
|
placeholder="请输入版本名称"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
onKeyPress={(e) => e.key === 'Enter' && handleSearch()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label>是否强制更新</Label>
|
||||||
|
<Select value={isForceFilter} onValueChange={setIsForceFilter}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="请选择" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="all">全部</SelectItem>
|
||||||
|
<SelectItem value="0">否</SelectItem>
|
||||||
|
<SelectItem value="1">是</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label>渠道标识</Label>
|
||||||
|
<Select value={channelFilter} onValueChange={setChannelFilter}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="请选择" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="all">全部渠道</SelectItem>
|
||||||
|
{channels.map((channel) => (
|
||||||
|
<SelectItem key={channel} value={channel.toLowerCase()}>
|
||||||
|
{channelNameMap[channel.toLowerCase()] || channel.toLowerCase()}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-end gap-2">
|
||||||
|
<Button onClick={handleSearch}>
|
||||||
|
<Search className="h-4 w-4 mr-2" />
|
||||||
|
搜索
|
||||||
|
</Button>
|
||||||
|
<Button variant="outline" onClick={handleReset}>
|
||||||
|
<RefreshCw className="h-4 w-4 mr-2" />
|
||||||
|
重置
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* 操作按钮 */}
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Button onClick={() => setIsAddDialogOpen(true)}>
|
||||||
|
<Plus className="h-4 w-4 mr-2" />
|
||||||
|
新增
|
||||||
|
</Button>
|
||||||
|
<Button variant="outline" onClick={handleExport}>
|
||||||
|
<Download className="h-4 w-4 mr-2" />
|
||||||
|
导出
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 版本列表 */}
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>版本列表</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="rounded-md border">
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>主键ID</TableHead>
|
||||||
|
<TableHead>版本代码</TableHead>
|
||||||
|
<TableHead>版本名称</TableHead>
|
||||||
|
<TableHead>强制更新</TableHead>
|
||||||
|
<TableHead>渠道标识</TableHead>
|
||||||
|
<TableHead>APK下载</TableHead>
|
||||||
|
<TableHead>更新日志</TableHead>
|
||||||
|
<TableHead>安装包</TableHead>
|
||||||
|
<TableHead>操作</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{loading ? (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={9} className="text-center py-8">
|
||||||
|
<div className="text-gray-500">加载中...</div>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
) : versions.length === 0 ? (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={9} className="text-center py-8">
|
||||||
|
<div className="text-gray-500">暂无数据</div>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
) : (
|
||||||
|
versions.map((version) => (
|
||||||
|
<TableRow key={version.id}>
|
||||||
|
<TableCell>{version.id}</TableCell>
|
||||||
|
<TableCell>{version.versionCode}</TableCell>
|
||||||
|
<TableCell>{version.versionName}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Badge className={version.isForce === '1' ? "bg-red-100 text-red-800" : "bg-green-100 text-green-800"}>
|
||||||
|
{version.isForce === '1' ? '是' : '否'}
|
||||||
|
</Badge>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Badge variant="outline">
|
||||||
|
{channelNameMap[version.channel] || version.channel}
|
||||||
|
</Badge>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<div className="max-w-xs truncate" title={version.downloadUrl}>
|
||||||
|
{version.downloadUrl}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<div className="max-w-xs truncate" title={version.updateLog}>
|
||||||
|
{version.updateLog || '-'}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>{version.size}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => handleEditVersion(version)}
|
||||||
|
>
|
||||||
|
<Edit className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => handleDeleteVersion(version.id)}
|
||||||
|
>
|
||||||
|
<Trash2 className="h-4 w-4 text-red-600" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 分页 */}
|
||||||
|
<div className="flex items-center justify-between space-x-2 py-4">
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<p className="text-sm font-medium">每页显示</p>
|
||||||
|
<Select
|
||||||
|
value={pageSize.toString()}
|
||||||
|
onValueChange={(value) => handlePageSizeChange(parseInt(value))}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="h-8 w-[70px]">
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent side="top">
|
||||||
|
<SelectItem value="10">10</SelectItem>
|
||||||
|
<SelectItem value="20">20</SelectItem>
|
||||||
|
<SelectItem value="50">50</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
共 {total} 条记录
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<p className="text-sm font-medium">
|
||||||
|
第 {currentPage} 页,共 {Math.ceil(total / pageSize)} 页
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center space-x-1">
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => handlePageChange(currentPage - 1)}
|
||||||
|
disabled={currentPage <= 1 || loading}
|
||||||
|
>
|
||||||
|
<ChevronLeft className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => handlePageChange(currentPage + 1)}
|
||||||
|
disabled={currentPage >= Math.ceil(total / pageSize) || loading}
|
||||||
|
>
|
||||||
|
<ChevronRight className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* 新增对话框 */}
|
||||||
|
<Dialog open={isAddDialogOpen} onOpenChange={setIsAddDialogOpen}>
|
||||||
|
<DialogContent className="max-w-2xl">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>添加应用版本更新信息</DialogTitle>
|
||||||
|
<DialogDescription>填写版本信息并上传APK文件</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="grid gap-4 py-4">
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="versionName">版本名称 <span className="text-red-500">*</span></Label>
|
||||||
|
<Input
|
||||||
|
id="versionName"
|
||||||
|
value={formData.versionName}
|
||||||
|
onChange={(e) => setFormData({ ...formData, versionName: e.target.value })}
|
||||||
|
placeholder="请输入版本名称"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="versionCode">版本代码 <span className="text-red-500">*</span></Label>
|
||||||
|
<Input
|
||||||
|
id="versionCode"
|
||||||
|
type="number"
|
||||||
|
min="4"
|
||||||
|
value={formData.versionCode}
|
||||||
|
onChange={(e) => setFormData({ ...formData, versionCode: parseInt(e.target.value) || 4 })}
|
||||||
|
placeholder="请输入版本代码"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="isForce">强制更新 <span className="text-red-500">*</span></Label>
|
||||||
|
<Select value={formData.isForce} onValueChange={(value) => setFormData({ ...formData, isForce: value })}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="请选择" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="0">否</SelectItem>
|
||||||
|
<SelectItem value="1">是</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="channel">渠道标识 <span className="text-red-500">*</span></Label>
|
||||||
|
<Select value={formData.channel} onValueChange={(value) => setFormData({ ...formData, channel: value })}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="请选择渠道" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{channels.map((channel) => (
|
||||||
|
<SelectItem key={channel} value={channel.toLowerCase()}>
|
||||||
|
{channelNameMap[channel.toLowerCase()] || channel.toLowerCase()}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="file">APK下载 <span className="text-red-500">*</span></Label>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Input
|
||||||
|
id="file"
|
||||||
|
type="file"
|
||||||
|
accept=".apk"
|
||||||
|
onChange={handleFileChange}
|
||||||
|
className="hidden"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => document.getElementById('file')?.click()}
|
||||||
|
>
|
||||||
|
<Upload className="h-4 w-4 mr-2" />
|
||||||
|
点击上传
|
||||||
|
</Button>
|
||||||
|
<span className="text-sm text-gray-500">文件大小不超过500MB</span>
|
||||||
|
</div>
|
||||||
|
<Input
|
||||||
|
value={formData.downloadUrl}
|
||||||
|
placeholder="文件上传后自动填入地址"
|
||||||
|
readOnly
|
||||||
|
className="mt-2 bg-gray-50"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="updateLog">更新日志</Label>
|
||||||
|
<Textarea
|
||||||
|
id="updateLog"
|
||||||
|
value={formData.updateLog}
|
||||||
|
onChange={(e) => setFormData({ ...formData, updateLog: e.target.value })}
|
||||||
|
placeholder="请输入更新日志"
|
||||||
|
rows={3}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="size">安装包大小</Label>
|
||||||
|
<Input
|
||||||
|
id="size"
|
||||||
|
value={formData.size}
|
||||||
|
onChange={(e) => setFormData({ ...formData, size: e.target.value })}
|
||||||
|
placeholder="上传文件后自动填入"
|
||||||
|
readOnly
|
||||||
|
className="bg-gray-50"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button variant="outline" onClick={() => { setIsAddDialogOpen(false); resetForm(); }}>
|
||||||
|
取消
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleAddVersion} disabled={submitting}>
|
||||||
|
{submitting ? "提交中..." : "确定"}
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
{/* 编辑对话框 */}
|
||||||
|
<Dialog open={isEditDialogOpen} onOpenChange={setIsEditDialogOpen}>
|
||||||
|
<DialogContent className="max-w-2xl">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>修改应用版本更新信息</DialogTitle>
|
||||||
|
<DialogDescription>修改版本信息</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
{editData && (
|
||||||
|
<div className="grid gap-4 py-4">
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="edit-versionName">版本名称 <span className="text-red-500">*</span></Label>
|
||||||
|
<Input
|
||||||
|
id="edit-versionName"
|
||||||
|
value={editData.versionName}
|
||||||
|
onChange={(e) => setEditData({ ...editData, versionName: e.target.value })}
|
||||||
|
placeholder="请输入版本名称"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="edit-versionCode">版本代码 <span className="text-red-500">*</span></Label>
|
||||||
|
<Input
|
||||||
|
id="edit-versionCode"
|
||||||
|
type="number"
|
||||||
|
min="4"
|
||||||
|
value={editData.versionCode}
|
||||||
|
onChange={(e) => setEditData({ ...editData, versionCode: parseInt(e.target.value) || 4 })}
|
||||||
|
placeholder="请输入版本代码"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="edit-isForce">强制更新 <span className="text-red-500">*</span></Label>
|
||||||
|
<Select value={editData.isForce} onValueChange={(value) => setEditData({ ...editData, isForce: value })}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="请选择" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="0">否</SelectItem>
|
||||||
|
<SelectItem value="1">是</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="edit-channel">渠道标识 <span className="text-red-500">*</span></Label>
|
||||||
|
<Select value={editData.channel} onValueChange={(value) => setEditData({ ...editData, channel: value })}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="请选择渠道" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{channels.map((channel) => (
|
||||||
|
<SelectItem key={channel} value={channel.toLowerCase()}>
|
||||||
|
{channelNameMap[channel.toLowerCase()] || channel.toLowerCase()}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="edit-file">APK下载 <span className="text-red-500">*</span></Label>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Input
|
||||||
|
id="edit-file"
|
||||||
|
type="file"
|
||||||
|
accept=".apk"
|
||||||
|
onChange={handleFileChange}
|
||||||
|
className="hidden"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => document.getElementById('edit-file')?.click()}
|
||||||
|
>
|
||||||
|
<Upload className="h-4 w-4 mr-2" />
|
||||||
|
点击上传
|
||||||
|
</Button>
|
||||||
|
<span className="text-sm text-gray-500">文件大小不超过500MB</span>
|
||||||
|
</div>
|
||||||
|
<Input
|
||||||
|
value={editData.downloadUrl}
|
||||||
|
placeholder="文件上传后自动填入地址"
|
||||||
|
readOnly
|
||||||
|
className="mt-2 bg-gray-50"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="edit-updateLog">更新日志</Label>
|
||||||
|
<Textarea
|
||||||
|
id="edit-updateLog"
|
||||||
|
value={editData.updateLog}
|
||||||
|
onChange={(e) => setEditData({ ...editData, updateLog: e.target.value })}
|
||||||
|
placeholder="请输入更新日志"
|
||||||
|
rows={3}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="edit-size">安装包大小</Label>
|
||||||
|
<Input
|
||||||
|
id="edit-size"
|
||||||
|
value={editData.size}
|
||||||
|
onChange={(e) => setEditData({ ...editData, size: e.target.value })}
|
||||||
|
placeholder="上传文件后自动填入"
|
||||||
|
readOnly
|
||||||
|
className="bg-gray-50"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<DialogFooter>
|
||||||
|
<Button variant="outline" onClick={() => { setIsEditDialogOpen(false); setEditData(null); }}>
|
||||||
|
取消
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleUpdateVersion} disabled={submitting}>
|
||||||
|
{submitting ? "提交中..." : "确定"}
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@@ -594,12 +594,15 @@ function CreateWorkOrderForm({ onClose }: { onClose: () => void }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取商户设备列表
|
// 获取商户设备列表
|
||||||
const fetchMerchantEquipments = async (merchantsId: string) => {
|
const fetchMerchantEquipments = async (merchantId: string) => {
|
||||||
setLoadingEquipment(true)
|
setLoadingEquipment(true)
|
||||||
|
console.log('获取商户设备,商户ID:', merchantId)
|
||||||
try {
|
try {
|
||||||
const response = await apiGet(`/back/equipment/list?pageNum=1&pageSize=9999&merchantsId=${merchantsId}`)
|
const response = await apiGet(`/back/equipment/list?pageNum=1&pageSize=9999&merchantId=${merchantId}`)
|
||||||
|
console.log('设备列表响应:', response)
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
setAvailableEquipment(response.rows || [])
|
setAvailableEquipment(response.rows || [])
|
||||||
|
console.log('设备列表:', response.rows)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取设备列表失败:', error)
|
console.error('获取设备列表失败:', error)
|
||||||
@@ -626,16 +629,17 @@ function CreateWorkOrderForm({ onClose }: { onClose: () => void }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleMerchantChange = (merchantId: string) => {
|
const handleMerchantChange = (merchantId: string) => {
|
||||||
|
console.log('选择商户,ID:', merchantId)
|
||||||
setSelectedMerchant(merchantId)
|
setSelectedMerchant(merchantId)
|
||||||
setFormData({ ...formData, merchantId, equipmentId: "" })
|
setFormData({ ...formData, merchantId, equipmentId: "" })
|
||||||
|
|
||||||
// 找到选中的商户对象,获取merchantsId
|
// 找到选中的商户对象,使用 merchantsId 来获取设备列表
|
||||||
const selectedMerchantObj = merchants.find(m => m.id === merchantId)
|
const selectedMerchantObj = merchants.find(m => m.id === merchantId)
|
||||||
if (selectedMerchantObj && selectedMerchantObj.merchantsId) {
|
if (selectedMerchantObj) {
|
||||||
fetchMerchantEquipments(selectedMerchantObj.merchantsId)
|
// 使用 merchantsId 来查询设备,如果没有则使用 id
|
||||||
} else {
|
const merchantIdForEquipment = selectedMerchantObj.merchantsId || selectedMerchantObj.id
|
||||||
// 如果没有merchantsId,使用id作为fallback
|
console.log('用于查询设备的 merchantId:', merchantIdForEquipment)
|
||||||
fetchMerchantEquipments(merchantId)
|
fetchMerchantEquipments(merchantIdForEquipment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user