feat: 优化系统更新功能
- 系统更新模块移到系统设置页面最上方 - 版本号显示使用 Tag 格式(gitTag) - 版本号 Tag 根据是否有新版本显示不同颜色(黄色=有新版本,绿色=无新版本) - 版本号使用镂空样式,字号 8px - 支持 Markdown 渲染更新内容 - 美化系统更新页面样式 - 在 Layout 中添加版本更新检查,有新版本时显示提示
This commit is contained in:
@@ -8,6 +8,8 @@ import {
|
||||
InfoCircleOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { apiClient } from '../services/api'
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
|
||||
const { Title, Text, Paragraph } = Typography
|
||||
|
||||
@@ -172,145 +174,302 @@ const SystemUpdate: React.FC = () => {
|
||||
<Card
|
||||
title={
|
||||
<Space>
|
||||
<CloudUploadOutlined />
|
||||
<span>系统更新</span>
|
||||
<CloudUploadOutlined style={{ fontSize: '18px', color: '#1890ff' }} />
|
||||
<span style={{ fontSize: '16px', fontWeight: 600 }}>系统更新</span>
|
||||
</Space>
|
||||
}
|
||||
style={{ marginBottom: '16px' }}
|
||||
style={{
|
||||
marginBottom: '16px',
|
||||
borderRadius: '8px',
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.06)'
|
||||
}}
|
||||
>
|
||||
<Space direction="vertical" style={{ width: '100%' }} size="large">
|
||||
{/* 当前版本信息 */}
|
||||
<div>
|
||||
<Title level={5}>当前版本</Title>
|
||||
<Space>
|
||||
<Tag color="blue" style={{ fontSize: '14px', padding: '4px 12px' }}>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
padding: '16px',
|
||||
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
||||
borderRadius: '8px',
|
||||
color: '#fff'
|
||||
}}>
|
||||
<div>
|
||||
<div style={{ fontSize: '13px', opacity: 0.9, marginBottom: '4px' }}>
|
||||
当前版本
|
||||
</div>
|
||||
<div style={{ fontSize: '20px', fontWeight: 600 }}>
|
||||
v{currentVersion || 'unknown'}
|
||||
</Tag>
|
||||
</Space>
|
||||
</div>
|
||||
</div>
|
||||
<CheckCircleOutlined style={{ fontSize: '32px', opacity: 0.8 }} />
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
|
||||
{/* 更新状态 */}
|
||||
{updateStatus.updating && (
|
||||
<Alert
|
||||
message="系统正在更新"
|
||||
message={
|
||||
<span style={{ fontSize: '15px', fontWeight: 500 }}>系统正在更新</span>
|
||||
}
|
||||
description={
|
||||
<div>
|
||||
<p>{updateStatus.message}</p>
|
||||
<div style={{ marginTop: '12px' }}>
|
||||
<div style={{
|
||||
marginBottom: '12px',
|
||||
fontSize: '14px',
|
||||
color: '#595959'
|
||||
}}>
|
||||
{updateStatus.message}
|
||||
</div>
|
||||
<Progress
|
||||
percent={updateStatus.progress}
|
||||
status="active"
|
||||
strokeColor={{ '0%': '#108ee9', '100%': '#87d068' }}
|
||||
strokeColor={{
|
||||
'0%': '#667eea',
|
||||
'50%': '#764ba2',
|
||||
'100%': '#f093fb'
|
||||
}}
|
||||
strokeWidth={8}
|
||||
showInfo
|
||||
format={(percent) => `${percent}%`}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
type="info"
|
||||
showIcon
|
||||
icon={<Spin />}
|
||||
style={{
|
||||
borderRadius: '8px',
|
||||
border: '1px solid #91d5ff'
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{updateStatus.error && (
|
||||
<Alert
|
||||
message="更新失败"
|
||||
description={updateStatus.error}
|
||||
message={<span style={{ fontSize: '15px', fontWeight: 500 }}>更新失败</span>}
|
||||
description={
|
||||
<div style={{
|
||||
marginTop: '8px',
|
||||
fontSize: '14px',
|
||||
color: '#595959'
|
||||
}}>
|
||||
{updateStatus.error}
|
||||
</div>
|
||||
}
|
||||
type="error"
|
||||
showIcon
|
||||
closable
|
||||
onClose={() => setUpdateStatus(prev => ({ ...prev, error: null }))}
|
||||
style={{
|
||||
borderRadius: '8px'
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 检查更新 */}
|
||||
{!updateStatus.updating && (
|
||||
<Space>
|
||||
<div>
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
icon={<ReloadOutlined />}
|
||||
onClick={handleCheckUpdate}
|
||||
loading={updateChecking}
|
||||
style={{
|
||||
height: '40px',
|
||||
borderRadius: '6px',
|
||||
fontWeight: 500,
|
||||
boxShadow: '0 2px 4px rgba(24, 144, 255, 0.2)'
|
||||
}}
|
||||
>
|
||||
检查更新
|
||||
</Button>
|
||||
|
||||
{updateInfo && !updateInfo.hasUpdate && (
|
||||
<Alert
|
||||
message="当前已是最新版本"
|
||||
message={
|
||||
<span style={{ fontSize: '15px', fontWeight: 500 }}>
|
||||
当前已是最新版本
|
||||
</span>
|
||||
}
|
||||
type="success"
|
||||
showIcon
|
||||
icon={<CheckCircleOutlined />}
|
||||
style={{
|
||||
marginTop: '12px',
|
||||
borderRadius: '8px',
|
||||
border: '1px solid #b7eb8f'
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 更新信息 */}
|
||||
{updateInfo && updateInfo.hasUpdate && !updateStatus.updating && (
|
||||
<Alert
|
||||
message={
|
||||
<Space>
|
||||
<span>发现新版本:</span>
|
||||
<Tag color="green" style={{ fontSize: '14px' }}>
|
||||
v{updateInfo.latestVersion}
|
||||
</Tag>
|
||||
{updateInfo.prerelease && (
|
||||
<Tag color="orange">Pre-release</Tag>
|
||||
)}
|
||||
</Space>
|
||||
}
|
||||
description={
|
||||
<div style={{ marginTop: '12px' }}>
|
||||
<Paragraph>
|
||||
<Text strong>发布时间:</Text>
|
||||
<Text type="secondary">{formatDate(updateInfo.publishedAt)}</Text>
|
||||
</Paragraph>
|
||||
|
||||
{updateInfo.releaseNotes && (
|
||||
<div>
|
||||
<Text strong>更新内容:</Text>
|
||||
<div style={{
|
||||
marginTop: '8px',
|
||||
padding: '12px',
|
||||
background: '#f5f5f5',
|
||||
borderRadius: '4px',
|
||||
maxHeight: '200px',
|
||||
overflowY: 'auto'
|
||||
}}>
|
||||
<pre style={{
|
||||
margin: 0,
|
||||
whiteSpace: 'pre-wrap',
|
||||
fontFamily: 'inherit'
|
||||
}}>
|
||||
{updateInfo.releaseNotes}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div style={{ marginTop: '16px' }}>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<CloudUploadOutlined />}
|
||||
onClick={handleExecuteUpdate}
|
||||
<div style={{
|
||||
padding: '20px',
|
||||
background: 'linear-gradient(135deg, #fff5f5 0%, #fff1f0 100%)',
|
||||
borderRadius: '8px',
|
||||
border: '1px solid #ffccc7'
|
||||
}}>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
marginBottom: '16px',
|
||||
paddingBottom: '16px',
|
||||
borderBottom: '1px solid #ffccc7'
|
||||
}}>
|
||||
<div>
|
||||
<div style={{
|
||||
fontSize: '13px',
|
||||
color: '#8c8c8c',
|
||||
marginBottom: '6px'
|
||||
}}>
|
||||
发现新版本
|
||||
</div>
|
||||
<Space size="small">
|
||||
<Tag
|
||||
color="success"
|
||||
style={{
|
||||
fontSize: '16px',
|
||||
padding: '4px 16px',
|
||||
fontWeight: 600,
|
||||
borderRadius: '4px'
|
||||
}}
|
||||
>
|
||||
立即升级
|
||||
</Button>
|
||||
v{updateInfo.latestVersion}
|
||||
</Tag>
|
||||
{updateInfo.prerelease && (
|
||||
<Tag
|
||||
color="orange"
|
||||
style={{
|
||||
fontSize: '12px',
|
||||
padding: '4px 12px',
|
||||
borderRadius: '4px'
|
||||
}}
|
||||
>
|
||||
Pre-release
|
||||
</Tag>
|
||||
)}
|
||||
</Space>
|
||||
</div>
|
||||
<CloudUploadOutlined style={{
|
||||
fontSize: '32px',
|
||||
color: '#ff4d4f',
|
||||
opacity: 0.8
|
||||
}} />
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: '16px' }}>
|
||||
<div style={{
|
||||
fontSize: '13px',
|
||||
color: '#8c8c8c',
|
||||
marginBottom: '4px'
|
||||
}}>
|
||||
发布时间
|
||||
</div>
|
||||
<div style={{
|
||||
fontSize: '14px',
|
||||
color: '#595959'
|
||||
}}>
|
||||
{formatDate(updateInfo.publishedAt)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{updateInfo.releaseNotes && (
|
||||
<div style={{ marginBottom: '20px' }}>
|
||||
<div style={{
|
||||
fontSize: '13px',
|
||||
color: '#8c8c8c',
|
||||
marginBottom: '8px',
|
||||
fontWeight: 500
|
||||
}}>
|
||||
更新内容
|
||||
</div>
|
||||
<div style={{
|
||||
padding: '16px',
|
||||
background: '#fff',
|
||||
borderRadius: '6px',
|
||||
border: '1px solid #e8e8e8',
|
||||
maxHeight: '500px',
|
||||
overflowY: 'auto',
|
||||
lineHeight: '1.6',
|
||||
boxShadow: 'inset 0 1px 2px rgba(0,0,0,0.06)'
|
||||
}}>
|
||||
<div style={{
|
||||
color: '#262626',
|
||||
fontSize: '14px'
|
||||
}}>
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm]}
|
||||
components={{
|
||||
h1: ({node, ...props}) => <h1 style={{ fontSize: '20px', fontWeight: 600, marginTop: '16px', marginBottom: '12px', color: '#262626', borderBottom: '2px solid #e8e8e8', paddingBottom: '8px' }} {...props} />,
|
||||
h2: ({node, ...props}) => <h2 style={{ fontSize: '18px', fontWeight: 600, marginTop: '16px', marginBottom: '10px', color: '#262626' }} {...props} />,
|
||||
h3: ({node, ...props}) => <h3 style={{ fontSize: '16px', fontWeight: 600, marginTop: '14px', marginBottom: '8px', color: '#262626' }} {...props} />,
|
||||
h4: ({node, ...props}) => <h4 style={{ fontSize: '15px', fontWeight: 600, marginTop: '12px', marginBottom: '6px', color: '#262626' }} {...props} />,
|
||||
p: ({node, ...props}) => <p style={{ marginBottom: '12px', color: '#595959' }} {...props} />,
|
||||
ul: ({node, ...props}) => <ul style={{ marginBottom: '12px', paddingLeft: '24px', color: '#595959' }} {...props} />,
|
||||
ol: ({node, ...props}) => <ol style={{ marginBottom: '12px', paddingLeft: '24px', color: '#595959' }} {...props} />,
|
||||
li: ({node, ...props}) => <li style={{ marginBottom: '6px', lineHeight: '1.6' }} {...props} />,
|
||||
code: ({node, inline, ...props}: any) =>
|
||||
inline
|
||||
? <code style={{ background: '#f0f0f0', padding: '2px 6px', borderRadius: '3px', fontSize: '13px', fontFamily: 'Monaco, Menlo, "Ubuntu Mono", Consolas, monospace', color: '#d73a49' }} {...props} />
|
||||
: <code style={{ display: 'block', background: '#282c34', color: '#abb2bf', padding: '12px', borderRadius: '4px', overflowX: 'auto', fontSize: '13px', fontFamily: 'Monaco, Menlo, "Ubuntu Mono", Consolas, monospace', marginBottom: '12px', lineHeight: '1.5' }} {...props} />,
|
||||
pre: ({node, ...props}) => <pre style={{ background: '#282c34', borderRadius: '4px', padding: '12px', overflowX: 'auto', marginBottom: '12px' }} {...props} />,
|
||||
blockquote: ({node, ...props}) => <blockquote style={{ borderLeft: '4px solid #1890ff', paddingLeft: '12px', margin: '12px 0', color: '#8c8c8c', fontStyle: 'italic' }} {...props} />,
|
||||
a: ({node, ...props}) => <a style={{ color: '#1890ff', textDecoration: 'none' }} target="_blank" rel="noopener noreferrer" {...props} />,
|
||||
strong: ({node, ...props}) => <strong style={{ fontWeight: 600, color: '#262626' }} {...props} />,
|
||||
table: ({node, ...props}) => <table style={{ width: '100%', borderCollapse: 'collapse', marginBottom: '12px' }} {...props} />,
|
||||
th: ({node, ...props}) => <th style={{ border: '1px solid #e8e8e8', padding: '8px 12px', background: '#fafafa', fontWeight: 600, textAlign: 'left' }} {...props} />,
|
||||
td: ({node, ...props}) => <td style={{ border: '1px solid #e8e8e8', padding: '8px 12px' }} {...props} />,
|
||||
hr: ({node, ...props}) => <hr style={{ border: 'none', borderTop: '1px solid #e8e8e8', margin: '16px 0' }} {...props} />
|
||||
}}
|
||||
>
|
||||
{updateInfo.releaseNotes}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
type="warning"
|
||||
showIcon
|
||||
icon={<InfoCircleOutlined />}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
icon={<CloudUploadOutlined />}
|
||||
onClick={handleExecuteUpdate}
|
||||
block
|
||||
style={{
|
||||
height: '44px',
|
||||
borderRadius: '6px',
|
||||
fontWeight: 500,
|
||||
fontSize: '15px',
|
||||
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
||||
border: 'none',
|
||||
boxShadow: '0 4px 12px rgba(102, 126, 234, 0.4)'
|
||||
}}
|
||||
>
|
||||
立即升级到 v{updateInfo.latestVersion}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 使用提示 */}
|
||||
{!updateStatus.updating && (
|
||||
{!updateStatus.updating && !(updateInfo && updateInfo.hasUpdate) && (
|
||||
<Alert
|
||||
message="使用说明"
|
||||
message={
|
||||
<span style={{ fontSize: '15px', fontWeight: 500 }}>使用说明</span>
|
||||
}
|
||||
description={
|
||||
<ul style={{ marginBottom: 0, paddingLeft: '20px' }}>
|
||||
<ul style={{
|
||||
marginBottom: 0,
|
||||
paddingLeft: '20px',
|
||||
fontSize: '14px',
|
||||
color: '#595959',
|
||||
lineHeight: '1.8'
|
||||
}}>
|
||||
<li>点击"检查更新"按钮检查是否有新版本</li>
|
||||
<li>更新过程约需30-60秒,期间系统将暂时不可用</li>
|
||||
<li>更新成功后页面将自动刷新</li>
|
||||
@@ -319,6 +478,10 @@ const SystemUpdate: React.FC = () => {
|
||||
}
|
||||
type="info"
|
||||
showIcon
|
||||
style={{
|
||||
borderRadius: '8px',
|
||||
border: '1px solid #91d5ff'
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
|
||||
Reference in New Issue
Block a user