增加登录显示的页面和修改bug

This commit is contained in:
huanglinhuan
2025-12-09 15:37:23 +08:00
parent d50b08e33e
commit 08980077aa
8 changed files with 111 additions and 32 deletions

View File

@@ -3,6 +3,9 @@ import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import { AuthProvider } from './context/AuthContext'; import { AuthProvider } from './context/AuthContext';
import Login from './pages/Login'; import Login from './pages/Login';
import ProductDetail from './pages/ProductDetail'; import ProductDetail from './pages/ProductDetail';
import DevGuide from './pages/DevGuide';
import Training from './pages/Training';
import PrivateRoute from './components/PrivateRoute';
import Navbar from './components/Navbar'; import Navbar from './components/Navbar';
import Home from './pages/Home'; import Home from './pages/Home';
import './App.css'; import './App.css';
@@ -16,6 +19,22 @@ function App() {
<Route path="/login" element={<Login />} /> <Route path="/login" element={<Login />} />
<Route path="/product/:series/:sub/:idx" element={<ProductDetail />} /> <Route path="/product/:series/:sub/:idx" element={<ProductDetail />} />
<Route
path="/dev"
element={
<PrivateRoute>
<DevGuide />
</PrivateRoute>
}
/>
<Route
path="/training"
element={
<PrivateRoute>
<Training />
</PrivateRoute>
}
/>
<Route path="/" element={<Home />} /> <Route path="/" element={<Home />} />
</Routes> </Routes>
</Router> </Router>

View File

@@ -231,23 +231,17 @@ const Navbar = () => {
</div> </div>
</div> </div>
{/* <div className="nav-item"> {user && (
<span className="nav-label">解决方案</span> <div className="nav-item">
<div className="dropdown"> <span className="nav-label" onClick={() => navigate('/dev')}>开发指南</span>
<Link to="/" className="dropdown-item">解决方案A</Link>
<Link to="/" className="dropdown-item">解决方案B</Link>
<Link to="/" className="dropdown-item">解决方案C</Link>
</div> </div>
</div> */} )}
{/* <div className="nav-item"> {user && (
<span className="nav-label">行业</span> <div className="nav-item">
<div className="dropdown"> <span className="nav-label" onClick={() => navigate('/training')}>培训资料</span>
<Link to="/" className="dropdown-item">民航</Link>
<Link to="/" className="dropdown-item">通航</Link>
<Link to="/" className="dropdown-item">研发制造</Link>
</div> </div>
</div> */} )}
</div> </div>
<div className="navbar-right"> <div className="navbar-right">

12
src/pages/DevGuide.js Normal file
View File

@@ -0,0 +1,12 @@
import React from 'react';
const DevGuide = () => {
return (
<div style={{ maxWidth: 1200, margin: '0 auto', padding: '20px' }}>
<h1 style={{ margin: 0, padding: '12px 0', color: '#111' }}>开发指南</h1>
<p style={{ color: '#333' }}>APISDK示例代码等开发资源的统一入口</p>
</div>
);
};
export default DevGuide;

View File

@@ -34,7 +34,7 @@ const Home = () => {
useEffect(() => { useEffect(() => {
const timer = setInterval(() => { const timer = setInterval(() => {
setActive((prev) => (prev + 1) % slidesData.length); setActive((prev) => (prev + 1) % slidesData.length);
}, 4000); }, 5000);
return () => clearInterval(timer); return () => clearInterval(timer);
}, []); }, []);

View File

@@ -66,7 +66,7 @@ const Login = () => {
</button> </button>
</form> </form>
<div className="login-hint"> <div className="login-hint">
<p>默认账号admin / admin123</p> <p>测试账号admin / admin123</p>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -50,9 +50,9 @@
.pd-panel-body { background: #fff; padding: 12px 0; } .pd-panel-body { background: #fff; padding: 12px 0; }
.pd-panel.expanded { border: 1px dashed #bfbfbf; border-radius: 6px; } .pd-panel.expanded { border: 1px dashed #bfbfbf; border-radius: 6px; }
.pd-panel.expanded .pd-panel-header { padding: 12px 14px; border-bottom: none; } .pd-panel.expanded .pd-panel-header { padding: 12px 14px; border-bottom: none; }
.image-row { display: flex; justify-content: center; align-items: center; gap: 40px; padding: 12px; } .image-row { display: flex; justify-content: center; align-items: center; gap: 40px; padding: 12px; background: #f5f5f5; }
.image-row img { height: 420px; width: auto; object-fit: contain; display: block; } .image-row img { height: 420px; width: auto; object-fit: contain; display: block; }
.size-carousel { position: relative; background: #fff; overflow: hidden; width: 100%; min-height: 420px; border-radius: 0; } .size-carousel { position: relative; background: #f5f5f5; overflow: hidden; width: 100%; min-height: 420px; border-radius: 0; }
.size-slides { display: grid; grid-template-columns: 100%; } .size-slides { display: grid; grid-template-columns: 100%; }
.size-slide { opacity: 0; transition: opacity 0.3s ease; display: none; } .size-slide { opacity: 0; transition: opacity 0.3s ease; display: none; }
.size-slide.active { opacity: 1; display: block; } .size-slide.active { opacity: 1; display: block; }

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useParams, useLocation } from 'react-router-dom'; import { useParams, useLocation } from 'react-router-dom';
import axios from 'axios';
import './ProductDetail.css'; import './ProductDetail.css';
const ProductDetail = () => { const ProductDetail = () => {
@@ -14,7 +15,7 @@ const ProductDetail = () => {
const [specsLoading, setSpecsLoading] = useState(false); const [specsLoading, setSpecsLoading] = useState(false);
const [imgOpen, setImgOpen] = useState(true); const [imgOpen, setImgOpen] = useState(true);
const [highlightsOpen, setHighlightsOpen] = useState(false); const [highlightsOpen, setHighlightsOpen] = useState(false);
const [compareOpen, setCompareOpen] = useState(true); const [compareOpen, setCompareOpen] = useState(false);
const [promoOpen, setPromoOpen] = useState(false); const [promoOpen, setPromoOpen] = useState(false);
const [faqOpen, setFaqOpen] = useState(false); const [faqOpen, setFaqOpen] = useState(false);
const [reviewOpen, setReviewOpen] = useState(false); const [reviewOpen, setReviewOpen] = useState(false);
@@ -56,11 +57,11 @@ const ProductDetail = () => {
if (data.data.length && typeof data.data[0]?.title === 'string' && Array.isArray(data.data[0]?.rows)) { if (data.data.length && typeof data.data[0]?.title === 'string' && Array.isArray(data.data[0]?.rows)) {
setSections(data.data); setSections(data.data);
setSpecs([]); setSpecs([]);
setExpanded(Object.fromEntries(data.data.map((_, i) => [i, true]))); setExpanded(Object.fromEntries(data.data.map((_, i) => [i, false])));
} else { } else {
setSections([{ title: '参数', rows: data.data }]); setSections([{ title: '参数', rows: data.data }]);
setSpecs(data.data); setSpecs(data.data);
setExpanded({ 0: true }); setExpanded({ 0: false });
} }
} }
} catch {} } catch {}
@@ -75,7 +76,7 @@ const ProductDetail = () => {
if (images.length <= 1) return; if (images.length <= 1) return;
const timer = setInterval(() => { const timer = setInterval(() => {
setActive((prev) => (prev + 1) % images.length); setActive((prev) => (prev + 1) % images.length);
}, 4000); }, 5000);
return () => clearInterval(timer); return () => clearInterval(timer);
}, [images.length]); }, [images.length]);
@@ -95,7 +96,7 @@ const ProductDetail = () => {
return ( return (
<div className="product-detail-page"> <div className="product-detail-page">
<div className="container"> <div className="container">
<div className="pd-title">{product.name}{product.desc ? ` | ${product.desc}` : ''}</div> <div className="pd-title">{product.name}</div>
<div className="section-narrow"> <div className="section-narrow">
<div className="pd-list"> <div className="pd-list">
<button className="pd-list-item" onClick={() => setImgOpen(!imgOpen)}> <button className="pd-list-item" onClick={() => setImgOpen(!imgOpen)}>
@@ -228,6 +229,35 @@ const DocsList = ({ series, sub }) => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [error, setError] = useState(''); const [error, setError] = useState('');
const handleDownload = async (d) => {
try {
const res = await axios.get(d.url, { responseType: 'blob' });
const blob = new Blob([res.data], { type: res.data.type || 'application/octet-stream' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = d.name || (String(d.url).split('/').pop() || '下载文件');
document.body.appendChild(a);
a.click();
a.remove();
URL.revokeObjectURL(url);
} catch (e) {
setError('下载失败或文件不存在');
}
};
const handleOpen = async (d) => {
try {
const res = await axios.get(d.url, { responseType: 'blob' });
const blob = new Blob([res.data], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
window.open(url, '_blank');
setTimeout(() => URL.revokeObjectURL(url), 60000);
} catch (e) {
window.open(d.url, '_blank');
}
};
React.useEffect(() => { React.useEffect(() => {
const fetchDocs = async () => { const fetchDocs = async () => {
try { try {
@@ -259,11 +289,23 @@ const DocsList = ({ series, sub }) => {
<ul className="docs-list"> <ul className="docs-list">
{docs.map((d) => ( {docs.map((d) => (
<li key={d.url} className="docs-item"> <li key={d.url} className="docs-item">
{String(d.url || '').toLowerCase().endsWith('.pdf') ? (
<a
href={`${d.url}`}
target="_blank"
rel="noreferrer"
className="docs-link"
onClick={(e) => { e.preventDefault(); handleOpen(d); }}
>
{d.name}
</a>
) : (
<a href={`${d.url}`} target="_blank" rel="noreferrer" className="docs-link"> <a href={`${d.url}`} target="_blank" rel="noreferrer" className="docs-link">
{d.name} {d.name}
</a> </a>
)}
<span className="docs-size">{(d.size / 1024 / 1024).toFixed(2)}MB</span> <span className="docs-size">{(d.size / 1024 / 1024).toFixed(2)}MB</span>
<a href={`${d.url}`} download className="docs-download">下载</a> <button type="button" className="docs-download" onClick={() => handleDownload(d)}>下载</button>
</li> </li>
))} ))}
</ul> </ul>

12
src/pages/Training.js Normal file
View File

@@ -0,0 +1,12 @@
import React from 'react';
const Training = () => {
return (
<div style={{ maxWidth: 1200, margin: '0 auto', padding: '20px' }}>
<h1 style={{ margin: 0, padding: '12px 0', color: '#111' }}>培训资料</h1>
<p style={{ color: '#333' }}>课程教材视频等培训资源的统一入口</p>
</div>
);
};
export default Training;