docs: 生成项目文档并优化项目结构
- 生成完整的 README.md 项目文档 - 统一图片路径为相对引用 - 完善 .gitignore 配置,添加常见忽略项 - 清理未使用的临时文件和图片资源 - 删除废弃的脚本文件
This commit is contained in:
+2
-2
@@ -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
@@ -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">
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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}>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user