181 lines
6.1 KiB
TypeScript
181 lines
6.1 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import { Input, Button, Card, message, Spin, Result } from 'antd';
|
|
import { QrcodeOutlined, SearchOutlined, ArrowLeftOutlined, CheckCircleOutlined, CloseCircleOutlined } from '@ant-design/icons';
|
|
import { serialApi } from '@/services/api';
|
|
import type { Serial } from '@/types';
|
|
import './styles/PublicQuery.css';
|
|
import logo from '@/assets/img/logo.png?url';
|
|
import beian from '@/assets/img/beian.png?url';
|
|
|
|
function PublicQueryPage() {
|
|
const [serialNumber, setSerialNumber] = useState('');
|
|
const [loading, setLoading] = useState(false);
|
|
const [result, setResult] = useState<Serial | null>(null);
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [showResult, setShowResult] = useState(false);
|
|
|
|
const performQuery = async (serialToQuery: string) => {
|
|
setLoading(true);
|
|
setError(null);
|
|
setResult(null);
|
|
|
|
try {
|
|
const data = await serialApi.query(serialToQuery);
|
|
setResult(data);
|
|
} catch (err: any) {
|
|
setError(err.message || '查询失败');
|
|
setResult(null);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const serialFromUrl = urlParams.get('serial');
|
|
if (serialFromUrl) {
|
|
setSerialNumber(serialFromUrl);
|
|
setShowResult(true);
|
|
performQuery(serialFromUrl);
|
|
}
|
|
}, []);
|
|
|
|
const handleQuery = async () => {
|
|
if (!serialNumber.trim()) {
|
|
message.error('请输入授权序列号');
|
|
return;
|
|
}
|
|
setShowResult(true);
|
|
performQuery(serialNumber.trim());
|
|
};
|
|
|
|
const handleReset = () => {
|
|
setShowResult(false);
|
|
setSerialNumber('');
|
|
setResult(null);
|
|
setError(null);
|
|
};
|
|
|
|
return (
|
|
<div className="public-query-container">
|
|
{!showResult ? (
|
|
<Card className="query-card" bordered={false}>
|
|
<div className="query-header">
|
|
<div className="query-logo">
|
|
<img src={logo} alt="Logo" style={{ height: '24px' }} />
|
|
</div>
|
|
<h1 className="query-title">
|
|
<QrcodeOutlined /> 授权查询
|
|
</h1>
|
|
<p className="query-subtitle">请输入您的授权序列号进行查询</p>
|
|
</div>
|
|
|
|
<div className="query-form">
|
|
<Input
|
|
size="large"
|
|
placeholder="请输入或扫描您的授权序列号"
|
|
value={serialNumber}
|
|
onChange={(e) => setSerialNumber(e.target.value)}
|
|
onPressEnter={handleQuery}
|
|
prefix={<SearchOutlined />}
|
|
/>
|
|
<Button
|
|
type="primary"
|
|
size="large"
|
|
block
|
|
icon={<SearchOutlined />}
|
|
onClick={handleQuery}
|
|
>
|
|
立即查询
|
|
</Button>
|
|
</div>
|
|
</Card>
|
|
) : (
|
|
<Card className={`result-card show`} bordered={false}>
|
|
<div className="result-header">
|
|
<div className="query-logo">
|
|
<img src={logo} alt="Logo" style={{ height: '24px' }} />
|
|
</div>
|
|
</div>
|
|
{loading ? (
|
|
<div className="loading-container">
|
|
<Spin size="large" />
|
|
<p>正在查询授权信息...</p>
|
|
</div>
|
|
) : result ? (
|
|
<div className="success-container">
|
|
{result.status !== 'active' ? (
|
|
<Result
|
|
icon={<CloseCircleOutlined style={{ color: '#ff4d4f', fontSize: '72px' }} />}
|
|
title="授权已吊销"
|
|
subTitle={`序列号验证通过,但已被吊销。企业:${result.companyName}`}
|
|
/>
|
|
) : (
|
|
<Result
|
|
icon={<CheckCircleOutlined style={{ color: '#52c41a', fontSize: '72px' }} />}
|
|
title="授权有效"
|
|
subTitle="您的序列号已验证通过"
|
|
/>
|
|
)}
|
|
|
|
<div className="result-details">
|
|
<div className="detail-item">
|
|
<span className="label">序列号</span>
|
|
<span className="value serial">{result.serialNumber}</span>
|
|
</div>
|
|
<div className="detail-item">
|
|
<span className="label">企业名称</span>
|
|
<span className="value">{result.companyName}</span>
|
|
</div>
|
|
<div className="detail-item">
|
|
<span className="label">有效期至</span>
|
|
<span className="value">{new Date(result.validUntil).toLocaleString('zh-CN')}</span>
|
|
</div>
|
|
<div className="detail-item">
|
|
<span className="label">授权状态</span>
|
|
<span className="value status">
|
|
{result.status === 'active' ? '有效' : '已吊销'}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<div className="error-container">
|
|
<Result
|
|
icon={<CloseCircleOutlined style={{ color: '#ff4d4f', fontSize: '72px' }} />}
|
|
title="无效序列号"
|
|
subTitle={error}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
<Button
|
|
size="large"
|
|
block
|
|
icon={<ArrowLeftOutlined />}
|
|
onClick={handleReset}
|
|
>
|
|
重新查询
|
|
</Button>
|
|
</Card>
|
|
)}
|
|
|
|
<div className="copyright">
|
|
<p>
|
|
Copyright © 2026 浙江贝凡网络科技有限公司. All Rights Reserved. |
|
|
<a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener noreferrer">
|
|
浙ICP备2025170226号-4
|
|
</a>
|
|
</p>
|
|
<p>
|
|
<a href="https://beian.mps.gov.cn/#/query/webSearch?code=33011002018371" target="_blank" rel="noopener noreferrer">
|
|
<img src={beian} alt="备案图标" style={{ height: '20px', marginRight: '5px', verticalAlign: 'middle' }} />
|
|
浙公网安备33011002018371号
|
|
</a>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default PublicQueryPage; |