docs: 生成项目文档并优化项目结构

- 生成完整的 README.md 项目文档
- 统一图片路径为相对引用
- 完善 .gitignore 配置,添加常见忽略项
- 清理未使用的临时文件和图片资源
- 删除废弃的脚本文件
This commit is contained in:
yi
2026-06-18 11:35:56 +08:00
parent 706dcc24eb
commit ffc7eef984
19 changed files with 343 additions and 162 deletions
+2 -2
View File
@@ -3,12 +3,12 @@ FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
RUN npm install
COPY . .
RUN npm run build
FROM nginx:alpine
FROM nginx:1.26-alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
+3 -3
View File
@@ -7,11 +7,11 @@
<meta name="theme-color" content="#1890ff" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<meta name="apple-mobile-web-app-title" content="轻远ERP" />
<meta name="description" content="轻远电力老挝分公司财务管理系统" />
<meta name="apple-mobile-web-app-title" content="云海财务系统" />
<meta name="description" content="云海财务系统 - 企业管理平台" />
<link rel="apple-touch-icon" href="/logo.png" />
<link rel="manifest" href="/manifest.json" />
<title>轻远电力老挝ERP - Qingyuan Power Laos</title>
<title>云海财务系统</title>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "轻远电力老挝ERP",
"short_name": "轻远ERP",
"description": "轻远电力老挝分公司财务管理系统",
"name": "云海财务系统",
"short_name": "云海财务",
"description": "云海财务系统 - 企业管理平台",
"start_url": "/",
"display": "standalone",
"orientation": "portrait",
@@ -1,16 +1,17 @@
import React from 'react'
import { Space, Typography } from 'antd'
import { ThunderboltOutlined } from '@ant-design/icons'
import { CloudOutlined } from '@ant-design/icons'
import { useLanguageStore } from '../../store/languageStore'
const { Text, Title } = Typography
interface CompanyLogoProps {
collapsed?: boolean
showText?: boolean
size?: 'small' | 'medium' | 'large'
}
const CompanyLogo: React.FC<CompanyLogoProps> = ({ showText = true, size = 'medium' }) => {
const CompanyLogo: React.FC<CompanyLogoProps> = ({ collapsed = false, showText = true, size = 'medium' }) => {
const { t, currentLanguage } = useLanguageStore()
const sizeMap = {
small: { fontSize: 14, iconSize: 20 },
@@ -19,11 +20,12 @@ const CompanyLogo: React.FC<CompanyLogoProps> = ({ showText = true, size = 'medi
}
const { fontSize, iconSize } = sizeMap[size]
const displayContent = showText && !collapsed
return (
<Space align="center" style={{ cursor: 'pointer' }}>
{/* 图标 */}
<ThunderboltOutlined
<CloudOutlined
style={{
fontSize: iconSize,
color: '#1890ff',
@@ -32,7 +34,7 @@ const CompanyLogo: React.FC<CompanyLogoProps> = ({ showText = true, size = 'medi
/>
{/* 公司名称 */}
{showText && (
{displayContent && (
<div>
<Title
level={5}
@@ -53,7 +55,7 @@ const CompanyLogo: React.FC<CompanyLogoProps> = ({ showText = true, size = 'medi
marginTop: -2
}}
>
Qingyuan Power Laos
Yunhai Finance System
</Text>
</div>
)}
@@ -224,6 +224,11 @@ const MainLayout: React.FC = () => {
label: t('menu.logisticsManagement')
}
]
},
{
key: 'xinmi-code',
icon: <FileSearchOutlined />,
label: <a href="http://code.xinmi.cloud/" target="_blank" rel="noopener noreferrer" aria-label="新觅源码库"></a>
}
], [t, currentLanguage])
@@ -461,6 +466,14 @@ const MainLayout: React.FC = () => {
}}>
<Outlet />
</Content>
<Layout.Footer style={{ textAlign: 'center', background: '#f5f5f5', padding: '12px 24px' }}>
<Space direction="vertical" size={2}>
<Text type="secondary" style={{ fontFamily: 'monospace', fontSize: '13px' }}></Text>
<Text type="secondary">
- <a href="http://code.xinmi.cloud/" target="_blank" rel="noopener noreferrer" aria-label="访问 新觅源码库 平台">访 </a>
</Text>
</Space>
</Layout.Footer>
</Layout>
<Modal
+4 -4
View File
@@ -87,7 +87,7 @@ export default {
},
login: {
title: '轻远电力老挝ERP',
title: '云海财务系统',
subtitle: '项目管理与财务报销一体化平台',
username: '用户名',
password: '密码',
@@ -2208,11 +2208,11 @@ export default {
description: '系统信息与版本',
systemInfo: '系统信息',
systemName: '系统名称',
systemNameValue: '轻远电力老挝ERP',
systemNameValue: '云海财务系统',
version: '系统版本',
versionValue: 'V1.0.0',
devTeam: '开发团队',
devTeamValue: '轻远电力信息技术部',
devTeamValue: '云海技术部',
onlineDate: '上线日期',
onlineDateValue: '2026年3月',
techArchitecture: '技术架构',
@@ -2237,7 +2237,7 @@ export default {
connectionStatus: '连接状态',
normal: '正常',
lastBackup: '最近备份',
footer: '© 2026 轻远电力老挝ERP系统 - 版本 V1.0.0',
footer: '© 2026 云海财务系统系统 - 版本 V1.0.0',
},
backup: {
+40 -7
View File
@@ -1,11 +1,12 @@
import React from 'react';
import { Card, Typography, Descriptions, Tag, Row, Col, Progress, Divider } from 'antd';
import { Card, Typography, Descriptions, Tag, Row, Col, Progress, Divider, Button } from 'antd';
import {
CloudServerOutlined,
DatabaseOutlined,
NodeIndexOutlined,
CheckCircleOutlined,
InfoCircleOutlined
InfoCircleOutlined,
RocketOutlined
} from '@ant-design/icons';
import { useLanguageStore } from '../../store/languageStore';
@@ -15,11 +16,43 @@ const AboutPage: React.FC = () => {
const { t, currentLanguage } = useLanguageStore();
return (
<div style={{ padding: 24 }}>
<div style={{ marginBottom: 24 }}>
<Title level={3} style={{ marginBottom: 8 }}>{t('about.title')}</Title>
<Paragraph type="secondary">{t('about.description')}</Paragraph>
</div>
<div style={{ padding: 24, maxWidth: 1400, margin: '0 auto' }}>
<Card
style={{
marginBottom: 32,
background: 'linear-gradient(135deg, #1890ff 0%, #0050b3 100%)',
color: 'white',
borderRadius: 16,
border: 'none',
boxShadow: '0 10px 30px rgba(0, 80, 179, 0.2)'
}}
>
<div style={{ textAlign: 'center', padding: '60px 20px' }}>
<Title level={1} style={{ color: 'white', marginBottom: 16, fontSize: 42 }}>{t('about.systemNameValue')}</Title>
<Text style={{ color: 'rgba(255,255,255,0.85)', fontSize: 20, display: 'block', marginBottom: 40, fontWeight: 300 }}>
</Text>
<Button
type="primary"
size="large"
shape="round"
icon={<RocketOutlined />}
href="http://code.xinmi.cloud/"
target="_blank"
style={{
backgroundColor: 'white',
color: '#1890ff',
fontWeight: 'bold',
height: 54,
padding: '0 40px',
fontSize: 18,
boxShadow: '0 8px 16px rgba(0,0,0,0.1)'
}}
>
</Button>
</div>
</Card>
<Row gutter={24}>
<Col span={16}>
+45 -36
View File
@@ -74,19 +74,39 @@ const LoginPage: React.FC = () => {
return (
<div style={{
minHeight: '100vh',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
backgroundImage: 'url(https://images.unsplash.com/photo-1497366216548-37526070297c?auto=format&fit=crop&w=1920&q=80)',
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
padding: '20px'
padding: '20px',
position: 'relative'
}}>
{/* 遮罩层以确保表单可读性 */}
<div style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.4)',
backdropFilter: 'blur(3px)'
}} />
<Card
className="login-card"
style={{
width: '100%',
maxWidth: 480,
borderRadius: 16,
boxShadow: '0 20px 60px rgba(0,0,0,0.3)'
boxShadow: '0 20px 60px rgba(0,0,0,0.3)',
border: 'none',
position: 'relative',
zIndex: 1,
backgroundColor: 'rgba(255, 255, 255, 0.95)',
backdropFilter: 'blur(10px)'
}}
styles={{ body: { padding: 40 } }}
>
@@ -102,13 +122,9 @@ const LoginPage: React.FC = () => {
<div style={{
textAlign: 'center',
padding: '12px',
background: '#f0f2f5',
background: 'transparent',
borderRadius: '8px',
border: '2px solid #1890ff'
}}>
<div style={{ marginBottom: 8, color: '#1890ff', fontWeight: 'bold' }}>
{t('login.selectLanguage')}
</div>
<LanguageSelector size="large" style={{ width: '200px' }} />
</div>
@@ -127,51 +143,61 @@ const LoginPage: React.FC = () => {
layout="vertical"
onFinish={handleSubmit}
autoComplete="off"
initialValues={{ username: 'admin', password: QUICK_PASSWORD }}
>
<Form.Item
name="username"
label={t('login.username')}
rules={[
{ required: true, message: t('login.usernameRequired') },
{ min: 3, message: t('login.usernameMin') }
]}
>
<Input
prefix={<UserOutlined />}
prefix={<UserOutlined style={{ color: '#1890ff' }} />}
placeholder={t('login.usernamePlaceholder')}
size="large"
style={{ borderRadius: 8 }}
/>
</Form.Item>
<Form.Item
name="password"
label={t('login.password')}
rules={[
{ required: true, message: t('login.passwordRequired') },
{ min: 6, message: t('login.passwordMin') }
]}
>
<Input.Password
prefix={<LockOutlined />}
prefix={<LockOutlined style={{ color: '#1890ff' }} />}
placeholder={t('login.passwordPlaceholder')}
size="large"
style={{ borderRadius: 8 }}
/>
</Form.Item>
<Form.Item>
<Form.Item style={{ marginBottom: 12 }}>
<Button
type="primary"
htmlType="submit"
loading={loading}
size="large"
block
style={{ borderRadius: 8, height: 48, fontSize: 16 }}
>
{t('login.loginButton')}
</Button>
</Form.Item>
<div style={{ textAlign: 'right', marginBottom: 24 }}>
<a href="#" style={{ color: '#1890ff', fontSize: 14 }}></a>
</div>
</Form>
<Divider>{t('login.testAccounts')}</Divider>
<div style={{ textAlign: 'center', background: '#e6f7ff', padding: '12px', borderRadius: 8, border: '1px solid #91d5ff' }}>
<Text strong style={{ color: '#1890ff' }}>默认管理员账号: admin / {QUICK_PASSWORD}</Text>
</div>
<Divider style={{ margin: '16px 0' }}>{t('login.testAccounts')}</Divider>
<Space direction="vertical" style={{ width: '100%' }}>
{testAccounts.map((account, index) => (
@@ -180,14 +206,14 @@ const LoginPage: React.FC = () => {
size="small"
hoverable
onClick={() => handleTestLogin(account.username)}
style={{ cursor: 'pointer' }}
style={{ cursor: 'pointer', borderRadius: 8, backgroundColor: '#fafafa', border: '1px solid #f0f0f0' }}
>
<Flex justify="space-between" align="center">
<Space>
{account.role === t('user.admin') && <DashboardOutlined style={{ color: 'red' }} />}
{account.role === t('user.finance') && <DollarOutlined style={{ color: 'orange' }} />}
{account.role === t('user.manager') && <ProjectOutlined style={{ color: 'blue' }} />}
{account.role === t('user.employee') && <TeamOutlined style={{ color: 'green' }} />}
{account.role === t('user.admin') && <DashboardOutlined style={{ color: '#f5222d' }} />}
{account.role === t('user.finance') && <DollarOutlined style={{ color: '#fa8c16' }} />}
{account.role === t('user.manager') && <ProjectOutlined style={{ color: '#1890ff' }} />}
{account.role === t('user.employee') && <TeamOutlined style={{ color: '#52c41a' }} />}
<Text strong>{account.name}</Text>
</Space>
<Text type="secondary">
@@ -197,23 +223,6 @@ const LoginPage: React.FC = () => {
</Card>
))}
</Space>
<Card size="small" type="inner">
<Space direction="vertical" size="small" style={{ width: '100%' }}>
<Text strong>{t('menu.dashboard')}:</Text>
<Text type="secondary"> {t('features.projectManage')}</Text>
<Text type="secondary"> {t('features.advanceManage')}</Text>
<Text type="secondary"> {t('features.reimburseManage')}</Text>
<Text type="secondary"> {t('features.financeReport')}</Text>
<Text type="secondary"> {t('features.mobileSupport')}</Text>
</Space>
</Card>
<div style={{ textAlign: 'center', marginTop: 20 }}>
<Text type="secondary">
{t('login.techSupport')}
</Text>
</div>
</Space>
</Card>
</div>