增加生产批次筛选功能
This commit is contained in:
parent
cc6dc177e4
commit
184c0d092b
|
|
@ -1,6 +1,30 @@
|
||||||
{
|
{
|
||||||
"pages": {
|
"pages": {
|
||||||
"/_app": []
|
"/_app": [
|
||||||
|
"static/chunks/node_modules_next_dist_compiled_0o6l_m6._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_shared_lib_0~pg0mt._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_client_0pe1dg-._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_0u_w_5s._.js",
|
||||||
|
"static/chunks/node_modules_next_app_0jt-zj..js",
|
||||||
|
"static/chunks/[next]_entry_page-loader_ts_0j~flwh._.js",
|
||||||
|
"static/chunks/node_modules_react-dom_0bruynb._.js",
|
||||||
|
"static/chunks/node_modules_0lx093h._.js",
|
||||||
|
"static/chunks/[root-of-the-server]__0c0okpg._.js",
|
||||||
|
"static/chunks/pages__app_07xvfw~._.js",
|
||||||
|
"static/chunks/turbopack-pages__app_0_wu8vy._.js"
|
||||||
|
],
|
||||||
|
"/_error": [
|
||||||
|
"static/chunks/node_modules_next_dist_compiled_0o6l_m6._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_shared_lib_12bi_n7._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_client_0pe1dg-._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_0rt-2cr._.js",
|
||||||
|
"static/chunks/[next]_entry_page-loader_ts_0rqw6yo._.js",
|
||||||
|
"static/chunks/node_modules_react-dom_0bruynb._.js",
|
||||||
|
"static/chunks/node_modules_0lx093h._.js",
|
||||||
|
"static/chunks/[root-of-the-server]__01mw43t._.js",
|
||||||
|
"static/chunks/pages__error_07xvfw~._.js",
|
||||||
|
"static/chunks/turbopack-pages__error_016chbq._.js"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"devFiles": [],
|
"devFiles": [],
|
||||||
"polyfillFiles": [
|
"polyfillFiles": [
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,30 @@
|
||||||
{
|
{
|
||||||
"pages": {
|
"pages": {
|
||||||
"/_app": []
|
"/_app": [
|
||||||
|
"static/chunks/node_modules_next_dist_compiled_0o6l_m6._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_shared_lib_0~pg0mt._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_client_0pe1dg-._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_0u_w_5s._.js",
|
||||||
|
"static/chunks/node_modules_next_app_0jt-zj..js",
|
||||||
|
"static/chunks/[next]_entry_page-loader_ts_0j~flwh._.js",
|
||||||
|
"static/chunks/node_modules_react-dom_0bruynb._.js",
|
||||||
|
"static/chunks/node_modules_0lx093h._.js",
|
||||||
|
"static/chunks/[root-of-the-server]__0c0okpg._.js",
|
||||||
|
"static/chunks/pages__app_07xvfw~._.js",
|
||||||
|
"static/chunks/turbopack-pages__app_0_wu8vy._.js"
|
||||||
|
],
|
||||||
|
"/_error": [
|
||||||
|
"static/chunks/node_modules_next_dist_compiled_0o6l_m6._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_shared_lib_12bi_n7._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_client_0pe1dg-._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_0rt-2cr._.js",
|
||||||
|
"static/chunks/[next]_entry_page-loader_ts_0rqw6yo._.js",
|
||||||
|
"static/chunks/node_modules_react-dom_0bruynb._.js",
|
||||||
|
"static/chunks/node_modules_0lx093h._.js",
|
||||||
|
"static/chunks/[root-of-the-server]__01mw43t._.js",
|
||||||
|
"static/chunks/pages__error_07xvfw~._.js",
|
||||||
|
"static/chunks/turbopack-pages__error_016chbq._.js"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"devFiles": [],
|
"devFiles": [],
|
||||||
"polyfillFiles": [],
|
"polyfillFiles": [],
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,20 @@
|
||||||
{"timestamp":"00:00:03.305","source":"Browser","level":"INFO","message":"%cDownload the React DevTools for a better development experience: https://react.dev/link/react-devtools font-weight:bold"}
|
{"timestamp":"00:00:03.305","source":"Browser","level":"INFO","message":"%cDownload the React DevTools for a better development experience: https://react.dev/link/react-devtools font-weight:bold"}
|
||||||
{"timestamp":"19:08:22.325","source":"Browser","level":"INFO","message":"%cDownload the React DevTools for a better development experience: https://react.dev/link/react-devtools font-weight:bold"}
|
{"timestamp":"19:08:22.325","source":"Browser","level":"INFO","message":"%cDownload the React DevTools for a better development experience: https://react.dev/link/react-devtools font-weight:bold"}
|
||||||
{"timestamp":"19:08:25.916","source":"Browser","level":"INFO","message":"%cDownload the React DevTools for a better development experience: https://react.dev/link/react-devtools font-weight:bold"}
|
{"timestamp":"19:08:25.916","source":"Browser","level":"INFO","message":"%cDownload the React DevTools for a better development experience: https://react.dev/link/react-devtools font-weight:bold"}
|
||||||
|
{"timestamp":"117:32:37.131","source":"Server","level":"LOG","message":"✓ Compiled in 153ms"}
|
||||||
|
{"timestamp":"117:32:38.097","source":"Server","level":"ERROR","message":"⨯ Error: The default export is not a React Component in \"/devices/page\""}
|
||||||
|
{"timestamp":"117:32:38.544","source":"Server","level":"ERROR","message":"⨯ Error: The default export is not a React Component in \"/devices/page\""}
|
||||||
|
{"timestamp":"117:32:38.547","source":"Server","level":"WARN","message":"⚠ Fast Refresh had to perform a full reload when ./src/app/devices/page.tsx changed. Read more: https://nextjs.org/docs/messages/fast-refresh-reload"}
|
||||||
|
{"timestamp":"117:32:38.940","source":"Server","level":"ERROR","message":"⨯ Error: The default export is not a React Component in \"/devices/page\""}
|
||||||
|
{"timestamp":"117:32:39.220","source":"Server","level":"ERROR","message":"⨯ Error: The default export is not a React Component in \"/devices/page\""}
|
||||||
|
{"timestamp":"117:32:40.255","source":"Server","level":"ERROR","message":"⨯ Error: The default export is not a React Component in \"/devices/page\""}
|
||||||
|
{"timestamp":"117:32:40.535","source":"Server","level":"ERROR","message":"⨯ Error: The default export is not a React Component in \"/devices/page\""}
|
||||||
|
{"timestamp":"117:32:40.837","source":"Server","level":"ERROR","message":"⨯ Error: The default export is not a React Component in \"/devices/page\""}
|
||||||
|
{"timestamp":"117:32:41.104","source":"Server","level":"ERROR","message":"⨯ Error: The default export is not a React Component in \"/devices/page\""}
|
||||||
|
{"timestamp":"117:32:41.590","source":"Server","level":"ERROR","message":"⨯ Error: The default export is not a React Component in \"/devices/page\""}
|
||||||
|
{"timestamp":"117:32:41.994","source":"Server","level":"ERROR","message":"⨯ Error: The default export is not a React Component in \"/devices/page\""}
|
||||||
|
{"timestamp":"117:32:42.214","source":"Browser","level":"ERROR","message":"uncaughtError: Error: The default export is not a React Component in \"/devices/page\""}
|
||||||
|
{"timestamp":"117:32:42.258","source":"Server","level":"ERROR","message":"[browser] \"\\u001b[31mUncaught Error: The default export is not a React Component in \\\"/devices/page\\\"\\u001b[39m\""}
|
||||||
|
{"timestamp":"117:32:42.259","source":"Browser","level":"ERROR","message":"\u001b[31mUncaught Error: The default export is not a React Component in \"/devices/page\"\u001b[39m"}
|
||||||
|
{"timestamp":"117:33:29.348","source":"Server","level":"LOG","message":"✓ Compiled in 274ms"}
|
||||||
|
{"timestamp":"117:33:30.697","source":"Browser","level":"INFO","message":"%cDownload the React DevTools for a better development experience: https://react.dev/link/react-devtools font-weight:bold"}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,30 @@
|
||||||
globalThis.__BUILD_MANIFEST = {
|
globalThis.__BUILD_MANIFEST = {
|
||||||
"pages": {
|
"pages": {
|
||||||
"/_app": []
|
"/_app": [
|
||||||
|
"static/chunks/node_modules_next_dist_compiled_0o6l_m6._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_shared_lib_0~pg0mt._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_client_0pe1dg-._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_0u_w_5s._.js",
|
||||||
|
"static/chunks/node_modules_next_app_0jt-zj..js",
|
||||||
|
"static/chunks/[next]_entry_page-loader_ts_0j~flwh._.js",
|
||||||
|
"static/chunks/node_modules_react-dom_0bruynb._.js",
|
||||||
|
"static/chunks/node_modules_0lx093h._.js",
|
||||||
|
"static/chunks/[root-of-the-server]__0c0okpg._.js",
|
||||||
|
"static/chunks/pages__app_07xvfw~._.js",
|
||||||
|
"static/chunks/turbopack-pages__app_0_wu8vy._.js"
|
||||||
|
],
|
||||||
|
"/_error": [
|
||||||
|
"static/chunks/node_modules_next_dist_compiled_0o6l_m6._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_shared_lib_12bi_n7._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_client_0pe1dg-._.js",
|
||||||
|
"static/chunks/node_modules_next_dist_0rt-2cr._.js",
|
||||||
|
"static/chunks/[next]_entry_page-loader_ts_0rqw6yo._.js",
|
||||||
|
"static/chunks/node_modules_react-dom_0bruynb._.js",
|
||||||
|
"static/chunks/node_modules_0lx093h._.js",
|
||||||
|
"static/chunks/[root-of-the-server]__01mw43t._.js",
|
||||||
|
"static/chunks/pages__error_07xvfw~._.js",
|
||||||
|
"static/chunks/turbopack-pages__error_016chbq._.js"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"devFiles": [],
|
"devFiles": [],
|
||||||
"polyfillFiles": [
|
"polyfillFiles": [
|
||||||
|
|
|
||||||
|
|
@ -1 +1,5 @@
|
||||||
{}
|
{
|
||||||
|
"/_app": "pages/_app.js",
|
||||||
|
"/_document": "pages/_document.js",
|
||||||
|
"/_error": "pages/_error.js"
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
self.__BUILD_MANIFEST = {
|
self.__BUILD_MANIFEST = {
|
||||||
|
"/_error": [
|
||||||
|
"static/chunks/pages/_error.js"
|
||||||
|
],
|
||||||
"__rewrites": {
|
"__rewrites": {
|
||||||
"afterFiles": [],
|
"afterFiles": [],
|
||||||
"beforeFiles": [],
|
"beforeFiles": [],
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,21 +1,21 @@
|
||||||
'use client'
|
'use client'
|
||||||
import { useState } from 'react'
|
import { useState, useMemo } from 'react'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { Download, Plus, Search, ChevronLeft, ChevronRight, Monitor, Cpu, Wifi, Power } from 'lucide-react'
|
import { Download, Plus, Search, ChevronLeft, ChevronRight, Monitor, Cpu, Wifi, Power, Tag } from 'lucide-react'
|
||||||
|
|
||||||
const devicesData = [
|
const devicesData = [
|
||||||
{ id: 1, sn: 'GD30-2025-000001', model: 'GD-30 Supreme', type: '高密度电法仪', status: '已激活', firmware: 'v2.3.5', productionDate: '2025-01-15 14:30', customer: '北京地质研究院' },
|
{ id: 1, sn: 'GD30-2025-000001', model: 'GD-30 Supreme', type: '高密度电法仪', status: '已激活', firmware: 'v2.3.5', productionDate: '2025-01-15 14:30', customer: '北京地质研究院', batch: 'B2025-01' },
|
||||||
{ id: 2, sn: 'GD30-2025-000002', model: 'GD-30 Supreme', type: '高密度电法仪', status: '已激活', firmware: 'v2.3.5', productionDate: '2025-01-18 09:15', customer: '中国地质大学' },
|
{ id: 2, sn: 'GD30-2025-000002', model: 'GD-30 Supreme', type: '高密度电法仪', status: '已激活', firmware: 'v2.3.5', productionDate: '2025-01-18 09:15', customer: '中国地质大学', batch: 'B2025-01' },
|
||||||
{ id: 3, sn: 'GD30-2024-000056', model: 'GD-30 Supreme', type: '高密度电法仪', status: '已出厂', firmware: 'v2.3.4', productionDate: '2024-12-20 16:00', customer: '成都理工大学' },
|
{ id: 3, sn: 'GD30-2024-000056', model: 'GD-30 Supreme', type: '高密度电法仪', status: '已出厂', firmware: 'v2.3.4', productionDate: '2024-12-20 16:00', customer: '成都理工大学', batch: 'B2024-12' },
|
||||||
{ id: 4, sn: 'GT20-2025-000045', model: 'GD-20', type: '二维电法仪', status: '已激活', firmware: 'v1.8.5', productionDate: '2025-02-10 11:20', customer: '武汉地质调查中心' },
|
{ id: 4, sn: 'GT20-2025-000045', model: 'GD-20', type: '二维电法仪', status: '已激活', firmware: 'v1.8.5', productionDate: '2025-02-10 11:20', customer: '武汉地质调查中心', batch: 'B2025-02' },
|
||||||
{ id: 5, sn: 'GT20-2025-000046', model: 'GD-20', type: '二维电法仪', status: '装配中', firmware: 'v1.8.5', productionDate: '2025-03-01 08:45', customer: '-' },
|
{ id: 5, sn: 'GT20-2025-000046', model: 'GD-20', type: '二维电法仪', status: '装配中', firmware: 'v1.8.5', productionDate: '2025-03-01 08:45', customer: '-', batch: 'B2025-03' },
|
||||||
{ id: 6, sn: 'GD30-2024-000078', model: 'GD-30 Supreme', type: '高密度电法仪', status: '已出厂', firmware: 'v2.3.4', productionDate: '2024-11-05 13:30', customer: '长安大学' },
|
{ id: 6, sn: 'GD30-2024-000078', model: 'GD-30 Supreme', type: '高密度电法仪', status: '已出厂', firmware: 'v2.3.4', productionDate: '2024-11-05 13:30', customer: '长安大学', batch: 'B2024-11' },
|
||||||
{ id: 7, sn: 'GD10-2024-000033', model: 'GD-10 Supreme', type: '入门级电法仪', status: '已激活', firmware: 'v1.5.2', productionDate: '2024-09-12 10:00', customer: '河海大学' },
|
{ id: 7, sn: 'GD10-2024-000033', model: 'GD-10 Supreme', type: '入门级电法仪', status: '已激活', firmware: 'v1.5.2', productionDate: '2024-09-12 10:00', customer: '河海大学', batch: 'B2024-09' },
|
||||||
{ id: 8, sn: 'GD30-2024-000089', model: 'GD-30 Supreme', type: '高密度电法仪', status: '装配中', firmware: 'v2.3.5', productionDate: '2025-03-05 15:10', customer: '-' },
|
{ id: 8, sn: 'GD30-2024-000089', model: 'GD-30 Supreme', type: '高密度电法仪', status: '装配中', firmware: 'v2.3.5', productionDate: '2025-03-05 15:10', customer: '-', batch: 'B2025-03' },
|
||||||
{ id: 9, sn: 'GT20-2025-000012', model: 'GD-20', type: '二维电法仪', status: '已激活', firmware: 'v1.8.5', productionDate: '2025-01-22 09:30', customer: '中南大学' },
|
{ id: 9, sn: 'GT20-2025-000012', model: 'GD-20', type: '二维电法仪', status: '已激活', firmware: 'v1.8.5', productionDate: '2025-01-22 09:30', customer: '中南大学', batch: 'B2025-01' },
|
||||||
{ id: 10, sn: 'GD30-2024-000102', model: 'GD-30 Supreme', type: '高密度电法仪', status: '已出厂', firmware: 'v2.3.4', productionDate: '2024-10-18 14:00', customer: '吉林大学' },
|
{ id: 10, sn: 'GD30-2024-000102', model: 'GD-30 Supreme', type: '高密度电法仪', status: '已出厂', firmware: 'v2.3.4', productionDate: '2024-10-18 14:00', customer: '吉林大学', batch: 'B2024-10' },
|
||||||
{ id: 11, sn: 'GD10-2024-000034', model: 'GD-10 Supreme', type: '入门级电法仪', status: '装配中', firmware: 'v1.5.2', productionDate: '2025-03-08 11:45', customer: '-' },
|
{ id: 11, sn: 'GD10-2024-000034', model: 'GD-10 Supreme', type: '入门级电法仪', status: '装配中', firmware: 'v1.5.2', productionDate: '2025-03-08 11:45', customer: '-', batch: 'B2025-03' },
|
||||||
{ id: 12, sn: 'GD30-2024-000145', model: 'GD-30 Supreme', type: '高密度电法仪', status: '已激活', firmware: 'v2.3.5', productionDate: '2024-08-25 16:20', customer: '同济大学' },
|
{ id: 12, sn: 'GD30-2024-000145', model: 'GD-30 Supreme', type: '高密度电法仪', status: '已激活', firmware: 'v2.3.5', productionDate: '2024-08-25 16:20', customer: '同济大学', batch: 'B2024-08' },
|
||||||
]
|
]
|
||||||
|
|
||||||
const modelOptions = ['全部', 'GD-30 Supreme', 'GD-20', 'GD-10 Supreme']
|
const modelOptions = ['全部', 'GD-30 Supreme', 'GD-20', 'GD-10 Supreme']
|
||||||
|
|
@ -44,10 +44,23 @@ export default function DevicesPage() {
|
||||||
const [filterStatus, setFilterStatus] = useState('全部')
|
const [filterStatus, setFilterStatus] = useState('全部')
|
||||||
const [filterDate, setFilterDate] = useState('')
|
const [filterDate, setFilterDate] = useState('')
|
||||||
const [searchText, setSearchText] = useState('')
|
const [searchText, setSearchText] = useState('')
|
||||||
|
const [selectedBatch, setSelectedBatch] = useState('全部')
|
||||||
const [currentPage, setCurrentPage] = useState(1)
|
const [currentPage, setCurrentPage] = useState(1)
|
||||||
const pageSize = 8
|
const pageSize = 8
|
||||||
|
|
||||||
|
// 从数据中提取所有批次并按时间倒序排列,统计每个批次的设备数量
|
||||||
|
const batchList = useMemo(() => {
|
||||||
|
const batchMap = new Map<string, number>()
|
||||||
|
devicesData.forEach(d => {
|
||||||
|
batchMap.set(d.batch, (batchMap.get(d.batch) || 0) + 1)
|
||||||
|
})
|
||||||
|
return Array.from(batchMap.entries())
|
||||||
|
.sort((a, b) => b[0].localeCompare(a[0]))
|
||||||
|
.map(([batch, count]) => ({ batch, count }))
|
||||||
|
}, [])
|
||||||
|
|
||||||
const filtered = devicesData.filter(d => {
|
const filtered = devicesData.filter(d => {
|
||||||
|
if (selectedBatch !== '全部' && d.batch !== selectedBatch) return false
|
||||||
if (filterModel !== '全部' && d.model !== filterModel) return false
|
if (filterModel !== '全部' && d.model !== filterModel) return false
|
||||||
if (filterStatus !== '全部' && d.status !== filterStatus) return false
|
if (filterStatus !== '全部' && d.status !== filterStatus) return false
|
||||||
if (filterDate && !d.productionDate.startsWith(filterDate)) return false
|
if (filterDate && !d.productionDate.startsWith(filterDate)) return false
|
||||||
|
|
@ -57,6 +70,11 @@ export default function DevicesPage() {
|
||||||
const totalPages = Math.ceil(filtered.length / pageSize)
|
const totalPages = Math.ceil(filtered.length / pageSize)
|
||||||
const paged = filtered.slice((currentPage - 1) * pageSize, currentPage * pageSize)
|
const paged = filtered.slice((currentPage - 1) * pageSize, currentPage * pageSize)
|
||||||
|
|
||||||
|
const handleBatchSelect = (batch: string) => {
|
||||||
|
setSelectedBatch(batch)
|
||||||
|
setCurrentPage(1)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ padding: 24 }}>
|
<div style={{ padding: 24 }}>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
|
|
@ -104,17 +122,69 @@ export default function DevicesPage() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Main content: Batch sidebar + Device cards */}
|
||||||
|
<div style={{ display: 'flex', gap: 20 }}>
|
||||||
|
{/* Batch sidebar */}
|
||||||
|
<div style={{ width: 200, flexShrink: 0, backgroundColor: '#fff', borderRadius: 8, boxShadow: '0 1px 2px rgba(0,0,0,0.05)', padding: 16, alignSelf: 'flex-start' }}>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 16 }}>
|
||||||
|
<Tag size={15} style={{ color: '#4a7c59' }} />
|
||||||
|
<span style={{ fontSize: 14, fontWeight: 600, color: 'rgba(0,0,0,0.85)' }}>生产批次</span>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
||||||
|
<button
|
||||||
|
onClick={() => handleBatchSelect('全部')}
|
||||||
|
style={{
|
||||||
|
display: 'flex', justifyContent: 'space-between', alignItems: 'center',
|
||||||
|
padding: '8px 12px', borderRadius: 6, border: 'none', cursor: 'pointer', fontSize: 13, textAlign: 'left',
|
||||||
|
backgroundColor: selectedBatch === '全部' ? '#eef5f0' : 'transparent',
|
||||||
|
color: selectedBatch === '全部' ? '#4a7c59' : 'rgba(0,0,0,0.65)',
|
||||||
|
fontWeight: selectedBatch === '全部' ? 600 : 400,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>全部批次</span>
|
||||||
|
<span style={{
|
||||||
|
fontSize: 12, padding: '1px 8px', borderRadius: 10,
|
||||||
|
backgroundColor: selectedBatch === '全部' ? '#4a7c59' : '#f0f0f0',
|
||||||
|
color: selectedBatch === '全部' ? '#fff' : 'rgba(0,0,0,0.45)',
|
||||||
|
}}>{devicesData.length}</span>
|
||||||
|
</button>
|
||||||
|
{batchList.map(({ batch, count }) => (
|
||||||
|
<button
|
||||||
|
key={batch}
|
||||||
|
onClick={() => handleBatchSelect(batch)}
|
||||||
|
style={{
|
||||||
|
display: 'flex', justifyContent: 'space-between', alignItems: 'center',
|
||||||
|
padding: '8px 12px', borderRadius: 6, border: 'none', cursor: 'pointer', fontSize: 13, textAlign: 'left',
|
||||||
|
backgroundColor: selectedBatch === batch ? '#eef5f0' : 'transparent',
|
||||||
|
color: selectedBatch === batch ? '#4a7c59' : 'rgba(0,0,0,0.65)',
|
||||||
|
fontWeight: selectedBatch === batch ? 600 : 400,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>{batch}</span>
|
||||||
|
<span style={{
|
||||||
|
fontSize: 12, padding: '1px 8px', borderRadius: 10,
|
||||||
|
backgroundColor: selectedBatch === batch ? '#4a7c59' : '#f0f0f0',
|
||||||
|
color: selectedBatch === batch ? '#fff' : 'rgba(0,0,0,0.45)',
|
||||||
|
}}>{count}</span>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right content area */}
|
||||||
|
<div style={{ flex: 1, minWidth: 0 }}>
|
||||||
{/* Device Cards */}
|
{/* Device Cards */}
|
||||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 16, marginBottom: 24 }}>
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16, marginBottom: 24 }}>
|
||||||
{paged.map(device => (
|
{paged.map(device => (
|
||||||
<div key={device.id} style={{ backgroundColor: '#fff', borderRadius: 8, boxShadow: '0 1px 2px rgba(0,0,0,0.05)', overflow: 'hidden' }}>
|
<div key={device.id} style={{ backgroundColor: '#fff', borderRadius: 8, boxShadow: '0 1px 2px rgba(0,0,0,0.05)', overflow: 'hidden' }}>
|
||||||
<div style={{ padding: 20 }}>
|
<div style={{ padding: 20 }}>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>
|
||||||
<span style={{ fontSize: 15, fontWeight: 600, color: 'rgba(0,0,0,0.85)' }}>{device.sn}</span>
|
<span style={{ fontSize: 15, fontWeight: 600, color: 'rgba(0,0,0,0.85)' }}>{device.sn}</span>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 10 }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 4 }}>
|
||||||
{getStatusIcon(device.status)}
|
{getStatusIcon(device.status)}
|
||||||
<span style={{ ...getStatusStyle(device.status), padding: '2px 8px', borderRadius: 4, fontSize: 12 }}>{device.status}</span>
|
<span style={{ ...getStatusStyle(device.status), padding: '2px 8px', borderRadius: 4, fontSize: 12 }}>{device.status}</span>
|
||||||
|
<span style={{ fontSize: 11, padding: '2px 8px', borderRadius: 4, backgroundColor: '#f5f5f5', color: 'rgba(0,0,0,0.45)', border: '1px solid #e8e8e8' }}>{device.batch}</span>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontSize: 13, color: 'rgba(0,0,0,0.65)', lineHeight: 2 }}>
|
<div style={{ fontSize: 13, color: 'rgba(0,0,0,0.65)', lineHeight: 2 }}>
|
||||||
<div>型号:{device.model} {device.type}</div>
|
<div>型号:{device.model} {device.type}</div>
|
||||||
|
|
@ -142,14 +212,16 @@ export default function DevicesPage() {
|
||||||
{/* Pagination */}
|
{/* Pagination */}
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
<span style={{ fontSize: 14, color: 'rgba(0,0,0,0.45)' }}>
|
<span style={{ fontSize: 14, color: 'rgba(0,0,0,0.45)' }}>
|
||||||
显示 {(currentPage - 1) * pageSize + 1}-{Math.min(currentPage * pageSize, filtered.length)} / 共 {filtered.length} 台
|
显示 {filtered.length > 0 ? (currentPage - 1) * pageSize + 1 : 0}-{Math.min(currentPage * pageSize, filtered.length)} / 共 {filtered.length} 台
|
||||||
</span>
|
</span>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
|
||||||
<button onClick={() => setCurrentPage(p => Math.max(1, p - 1))} disabled={currentPage === 1} style={{ padding: '4px 8px', border: '1px solid #D9D9D9', borderRadius: 4, backgroundColor: '#fff', cursor: currentPage === 1 ? 'not-allowed' : 'pointer', opacity: currentPage === 1 ? 0.4 : 1 }}><ChevronLeft size={16} /></button>
|
<button onClick={() => setCurrentPage(p => Math.max(1, p - 1))} disabled={currentPage === 1} style={{ padding: '4px 8px', border: '1px solid #D9D9D9', borderRadius: 4, backgroundColor: '#fff', cursor: currentPage === 1 ? 'not-allowed' : 'pointer', opacity: currentPage === 1 ? 0.4 : 1 }}><ChevronLeft size={16} /></button>
|
||||||
{Array.from({ length: totalPages }, (_, i) => (
|
{Array.from({ length: totalPages }, (_, i) => (
|
||||||
<button key={i} onClick={() => setCurrentPage(i + 1)} style={{ width: 32, height: 32, borderRadius: 4, fontSize: 14, border: currentPage === i + 1 ? '1px solid #4a7c59' : '1px solid #D9D9D9', color: currentPage === i + 1 ? '#4a7c59' : 'rgba(0,0,0,0.65)', backgroundColor: currentPage === i + 1 ? '#eef5f0' : '#fff', cursor: 'pointer' }}>{i + 1}</button>
|
<button key={i} onClick={() => setCurrentPage(i + 1)} style={{ width: 32, height: 32, borderRadius: 4, fontSize: 14, border: currentPage === i + 1 ? '1px solid #4a7c59' : '1px solid #D9D9D9', color: currentPage === i + 1 ? '#4a7c59' : 'rgba(0,0,0,0.65)', backgroundColor: currentPage === i + 1 ? '#eef5f0' : '#fff', cursor: 'pointer' }}>{i + 1}</button>
|
||||||
))}
|
))}
|
||||||
<button onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))} disabled={currentPage === totalPages} style={{ padding: '4px 8px', border: '1px solid #D9D9D9', borderRadius: 4, backgroundColor: '#fff', cursor: currentPage === totalPages ? 'not-allowed' : 'pointer', opacity: currentPage === totalPages ? 0.4 : 1 }}><ChevronRight size={16} /></button>
|
<button onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))} disabled={currentPage === totalPages || totalPages === 0} style={{ padding: '4px 8px', border: '1px solid #D9D9D9', borderRadius: 4, backgroundColor: '#fff', cursor: currentPage === totalPages || totalPages === 0 ? 'not-allowed' : 'pointer', opacity: currentPage === totalPages || totalPages === 0 ? 0.4 : 1 }}><ChevronRight size={16} /></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue