From ffc7eef984c30179fdcb5eed540634e5872455db Mon Sep 17 00:00:00 2001 From: yi <100551693+yi1108@users.noreply.github.com> Date: Thu, 18 Jun 2026 11:35:56 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E7=94=9F=E6=88=90=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E5=B9=B6=E4=BC=98=E5=8C=96=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 生成完整的 README.md 项目文档 - 统一图片路径为相对引用 - 完善 .gitignore 配置,添加常见忽略项 - 清理未使用的临时文件和图片资源 - 删除废弃的脚本文件 --- .gitignore | 3 + README.md | 108 +++++++++++++----- backend/Dockerfile | 2 +- .../migrations/001_create_category_tree.sql | 16 +-- .../002_create_purchase_inventory.sql | 6 +- ...03_create_procurement_logistics_tables.sql | 14 +-- ...005_create_subcontractor_payment_infos.sql | 6 +- backend/migrations/999_init_sample_data.sql | 0 docker-compose.full.yml | 59 ++++++++++ docker-compose.yml | 56 ++------- frontend/Dockerfile | 4 +- frontend/index.html | 6 +- frontend/public/manifest.json | 6 +- .../src/components/common/CompanyLogo.tsx | 12 +- frontend/src/components/layout/MainLayout.tsx | 13 +++ frontend/src/locales/zh-CN.ts | 8 +- frontend/src/pages/admin/AboutPage.tsx | 47 ++++++-- frontend/src/pages/auth/LoginPage.tsx | 81 +++++++------ scripts/init_sample_data.sql | 58 ++++++++++ 19 files changed, 343 insertions(+), 162 deletions(-) create mode 100644 backend/migrations/999_init_sample_data.sql create mode 100644 docker-compose.full.yml create mode 100644 scripts/init_sample_data.sql diff --git a/.gitignore b/.gitignore index 0e9e700..90d3192 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,6 @@ backups/ # Cache .cache/ *.cache + +# Workflow +.work/ diff --git a/README.md b/README.md index c3dcd59..24fafbc 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,87 @@ -# 轻远电力老挝ERP系统 +# 云海财务系统 -## 系统访问 -- **前端地址**: http://43.161.248.209:3001/ -- **后端API**: http://43.161.248.209:3000/ +## 1. 项目简介 -## 测试账号 -| 用户名 | 密码 | 角色 | -|--------|------|------| -| admin | 123456 | 系统管理员 | -| finance1 | 123456 | 财务专员 | -| shejianjun | 123456 | 管理员 | +- **项目概述**:云海财务系统是一款高效、智能、专业的企业财务与项目管理平台,能够全方位提升企业的项目监控与资金流转效率。 +- **项目定位**:主要面向中大型企业、工程建设及跨国分公司,提供财务报销、项目预算与进度管理服务。 +- **核心价值**:实现项目与财务数据的无缝对接,简化审批流,实时监控预算使用情况,确保企业资金健康与合规。 -## 功能模块 -1. **仪表板** - 数据概览和统计 -2. **项目管理** - 项目创建、查看、编辑 -3. **财务管理** - 预支申请、报销申请 -4. **报表中心** - 财务报表查看 +## 2. 整体架构与技术栈 -## 技术栈 -- 前端:React + TypeScript + Ant Design + Vite -- 后端:Node.js + Express -- 数据库:PostgreSQL +本系统采用前后端分离的现代化架构,通过 Docker 容器化部署以确保高可用性。 -## 服务管理 -```bash -# 查看服务状态 -netstat -tlnp | grep -E ':3000|:3001' +### 技术栈展示: +- **后端技术**:Node.js + Express +- **前端技术**:React 18 + TypeScript + Ant Design 5 + Vite +- **数据库**:PostgreSQL 15 +- **部署技术**:Docker / Docker Compose -# 重启后端 -cd /opt/qingyuan-erp/backend -node api-complete.js & +### 系统架构图 +*(暂无架构图,系统分为前端应用容器、后端 API 容器及独立的 PostgreSQL 数据库容器)* -# 重启前端 -cd /opt/qingyuan-erp/frontend -npm run dev -- --host 0.0.0.0 & +## 3. 项目目录概览 + +```text +├── backend/ # 后端服务源码 +│ ├── routes/ # API路由 +│ ├── services/ # 业务逻辑 +│ ├── migrations/ # 数据库迁移脚本 +│ └── app.js # 后端主程序 +├── frontend/ # 前端服务源码 +│ ├── src/ # React源码及组件 +│ └── vite.config.ts # Vite配置 +├── scripts/ # 初始化脚本 (如 init_sample_data.sql) +└── docker-compose.full.yml # Docker本地部署配置 ``` + +## 4. 核心业务功能 + +- **项目管理**:支持项目的创建、进度跟踪、合同与里程碑管理。 +- **财务管理**:包括财务报销、预支款申请、付款申请与核销流程。 +- **采购与供应链**:商品管理、采购申请、订单管理与入库记录。 +- **伙伴管理**:集中管理供应商、分包商与客户信息。 +- **数据分析与仪表盘**:直观展示核心财务数据及项目状态。 + +## 5. 实际应用场景示例 + +- **跨国分公司财务管控**:海外分公司提交预支与报销申请,总部可在线审核,统一汇率转换及预算扣减。 +- **工程类项目核算**:将施工日志与项目付款节点绑定,确保按进度结算分包商款项。 +- **企业日常运营**:员工出差报销、办公采购,全流程数字化审批与记录。 + +## 6. 帮助解决的核心问题 + +- **财务数据孤岛**:项目信息与财务开销割裂,难以追踪真实成本。 +- **审批效率低下**:传统纸质或邮件审批慢、易遗漏。 +- **预算超支风险**:缺乏实时的数据监控及超支预警机制。 + +## 7. 快速开始 + +### 环境要求 +- Docker 及 Docker Compose +- Node.js (如需本地独立运行) + +### 安装与运行步骤 (基于 Docker) + +本系统内置了 `docker-compose.full.yml` 文件及示例数据初始化脚本,可一键启动全套服务。 + +1. **一键构建与启动**: + ```bash + docker-compose -f docker-compose.full.yml up -d --build + ``` +2. **检查服务状态**: + ```bash + docker-compose -f docker-compose.full.yml ps + ``` + +### 访问地址与默认账号 +- **前端访问地址**:`http://localhost:10050` +- **后端 API 地址**:`http://localhost:10051` +- **默认管理员账号**:`admin` / `X123c321@` (具体密码请参考登录页提示) + +### 常见问题 +- **数据库未初始化**:如果首次启动未完成数据装载,可执行 `docker-compose down -v` 删除未初始化的数据卷后重新启动。 +- **端口冲突**:如果 `10050` 或 `10051` 端口已被占用,请修改 `docker-compose.full.yml` 中的端口映射。 + +## 8. 运行示例截图 + +*(截图预留位置)* diff --git a/backend/Dockerfile b/backend/Dockerfile index 35022cd..892b056 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -3,7 +3,7 @@ FROM node:18-alpine WORKDIR /app COPY package*.json ./ -RUN npm ci --production +RUN npm install --production COPY . . diff --git a/backend/migrations/001_create_category_tree.sql b/backend/migrations/001_create_category_tree.sql index f741cfd..1f93022 100644 --- a/backend/migrations/001_create_category_tree.sql +++ b/backend/migrations/001_create_category_tree.sql @@ -5,7 +5,7 @@ -- 1. 创建新的分类表(树状结构) CREATE TABLE IF NOT EXISTS category_tree ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, name TEXT NOT NULL, -- 分类名称 parent_id INTEGER DEFAULT NULL, -- 父分类ID(NULL表示一级分类) level INTEGER DEFAULT 1, -- 层级(1=一级,2=二级) @@ -26,7 +26,7 @@ ALTER TABLE products RENAME TO products_backup; -- 创建新的商品表 CREATE TABLE products ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, name TEXT NOT NULL, -- 商品名称 model TEXT, -- 型号 category_id INTEGER, -- 二级分类ID(关联category_tree) @@ -206,17 +206,9 @@ FROM category_tree WHERE name = '其他材料' AND level = 1; -- ============================================ -- 创建触发器:自动更新updated_at -- ============================================ -CREATE TRIGGER IF NOT EXISTS update_category_tree_timestamp -AFTER UPDATE ON category_tree -BEGIN - UPDATE category_tree SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id; -END; -CREATE TRIGGER IF NOT EXISTS update_products_timestamp -AFTER UPDATE ON products -BEGIN - UPDATE products SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id; -END; + + -- ============================================ -- 迁移完成 diff --git a/backend/migrations/002_create_purchase_inventory.sql b/backend/migrations/002_create_purchase_inventory.sql index 09c2456..97dc0d1 100644 --- a/backend/migrations/002_create_purchase_inventory.sql +++ b/backend/migrations/002_create_purchase_inventory.sql @@ -5,7 +5,7 @@ -- 表1:采购申请表 (purchase_requests) -- ============================================ CREATE TABLE IF NOT EXISTS purchase_requests ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, request_code TEXT UNIQUE NOT NULL, project_id INTEGER NOT NULL, applicant TEXT NOT NULL, @@ -28,7 +28,7 @@ CREATE TABLE IF NOT EXISTS purchase_requests ( -- 表2:采购明细表 (purchase_request_items) -- ============================================ CREATE TABLE IF NOT EXISTS purchase_request_items ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, purchase_request_id INTEGER NOT NULL, product_id INTEGER, product_name TEXT NOT NULL, @@ -46,7 +46,7 @@ CREATE TABLE IF NOT EXISTS purchase_request_items ( -- 表3:库存记录表 (inventory_records) -- ============================================ CREATE TABLE IF NOT EXISTS inventory_records ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, record_type TEXT NOT NULL, project_id INTEGER, purchase_request_id INTEGER, diff --git a/backend/migrations/003_create_procurement_logistics_tables.sql b/backend/migrations/003_create_procurement_logistics_tables.sql index ca06469..a431066 100644 --- a/backend/migrations/003_create_procurement_logistics_tables.sql +++ b/backend/migrations/003_create_procurement_logistics_tables.sql @@ -12,7 +12,7 @@ -- 表1:跨境物流公司表 (logistics_companies) -- 设计方案章节:9.9 跨境物流公司表 CREATE TABLE IF NOT EXISTS logistics_companies ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, code TEXT UNIQUE NOT NULL, name TEXT NOT NULL, address TEXT, @@ -31,7 +31,7 @@ CREATE INDEX IF NOT EXISTS idx_logistics_companies_status ON logistics_companies -- 表2:物流公司收款信息表 (logistics_company_payment_infos) -- 设计方案章节:9.10 物流公司收款信息表 CREATE TABLE IF NOT EXISTS logistics_company_payment_infos ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, logistics_company_id INTEGER NOT NULL, account_name TEXT, account_number TEXT, @@ -48,7 +48,7 @@ CREATE INDEX IF NOT EXISTS idx_lc_payment_infos_company ON logistics_company_pay -- 表3:物流单表 (logistics_records) -- 设计方案章节:9.4 物流单表 CREATE TABLE IF NOT EXISTS logistics_records ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, code TEXT UNIQUE NOT NULL, purchase_order_id INTEGER NOT NULL, @@ -102,7 +102,7 @@ CREATE INDEX IF NOT EXISTS idx_logistics_records_company ON logistics_records(lo -- 表4:验收单表 (verification_records) -- 设计方案章节:9.5 验收单表 CREATE TABLE IF NOT EXISTS verification_records ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, code TEXT UNIQUE NOT NULL, purchase_order_id INTEGER NOT NULL, logistics_record_id INTEGER, @@ -137,7 +137,7 @@ CREATE INDEX IF NOT EXISTS idx_verification_records_status ON verification_recor -- 表5:退库单表 (return_records) -- 设计方案章节:9.6 退库单表 CREATE TABLE IF NOT EXISTS return_records ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, code TEXT UNIQUE NOT NULL, project_id INTEGER NOT NULL, @@ -167,7 +167,7 @@ CREATE INDEX IF NOT EXISTS idx_return_records_status ON return_records(status); -- 表6:材料价格历史表 (material_price_history) -- 设计方案章节:9.7 材料价格历史表 CREATE TABLE IF NOT EXISTS material_price_history ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, product_id INTEGER NOT NULL, purchase_order_id INTEGER, supplier_id INTEGER, @@ -191,7 +191,7 @@ CREATE INDEX IF NOT EXISTS idx_material_price_history_date ON material_price_his -- 表7:项目材料库存表 (project_material_inventory) -- 设计方案章节:9.8 项目材料库存表 CREATE TABLE IF NOT EXISTS project_material_inventory ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, project_id INTEGER NOT NULL, product_id INTEGER NOT NULL, product_name TEXT, diff --git a/backend/migrations/005_create_subcontractor_payment_infos.sql b/backend/migrations/005_create_subcontractor_payment_infos.sql index a0ab321..a03d084 100644 --- a/backend/migrations/005_create_subcontractor_payment_infos.sql +++ b/backend/migrations/005_create_subcontractor_payment_infos.sql @@ -1,14 +1,14 @@ -- 创建分包商收款信息表 CREATE TABLE IF NOT EXISTS subcontractor_payment_infos ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, subcontractor_id INTEGER NOT NULL, account_name TEXT NOT NULL, bank_account TEXT NOT NULL, bank_name TEXT NOT NULL, qr_code TEXT, is_primary INTEGER DEFAULT 0, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (subcontractor_id) REFERENCES subcontractors(id) ON DELETE CASCADE ); diff --git a/backend/migrations/999_init_sample_data.sql b/backend/migrations/999_init_sample_data.sql new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.full.yml b/docker-compose.full.yml new file mode 100644 index 0000000..96f47fe --- /dev/null +++ b/docker-compose.full.yml @@ -0,0 +1,59 @@ +version: '3.8' + +services: + postgres: + image: postgres:15-alpine + container_name: yunhaifinance-postgres + ports: + - "10052:5432" + volumes: + - yunhaifinance-postgres-data:/var/lib/postgresql/data + - ./scripts/init_sample_data.sql:/docker-entrypoint-initdb.d/999_init_sample_data.sql:ro + environment: + POSTGRES_USER: ${DB_USER:-postgres} + POSTGRES_PASSWORD: ${DB_PASSWORD:-changeme} + POSTGRES_DB: ${DB_NAME:-company_finance} + POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=zh_CN.UTF-8" + + backend: + build: + context: ./backend + dockerfile: Dockerfile + container_name: yunhaifinance-backend + ports: + - "10051:3000" + environment: + NODE_ENV: production + PORT: 3000 + DB_HOST: postgres + DB_PORT: 5432 + DB_NAME: ${DB_NAME:-company_finance} + DB_USER: ${DB_USER:-postgres} + DB_PASSWORD: ${DB_PASSWORD:-changeme} + JWT_SECRET: ${JWT_SECRET:-please-change-this-secret} + CORS_ORIGIN: ${CORS_ORIGIN:-} + depends_on: + - postgres + volumes: + - yunhaifinance-upload-data:/app/uploads + networks: + - yunhaifinance-network + + frontend: + build: + context: ./frontend + dockerfile: Dockerfile + container_name: yunhaifinance-frontend + ports: + - "10050:80" + depends_on: + - backend + networks: + - yunhaifinance-network + +volumes: + yunhaifinance-postgres-data: + yunhaifinance-upload-data: + +networks: + yunhaifinance-network: \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 4cd4f8c..e01bcf8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,59 +3,21 @@ version: '3.8' services: postgres: image: postgres:15-alpine - restart: unless-stopped + container_name: yunhaifinance-postgres environment: POSTGRES_USER: ${DB_USER:-postgres} POSTGRES_PASSWORD: ${DB_PASSWORD:-changeme} POSTGRES_DB: ${DB_NAME:-company_finance} ports: - - "5432:5432" + - "10052:5432" volumes: - - postgres_data:/var/lib/postgresql/data + - yunhaifinance-postgres-data:/var/lib/postgresql/data - ./backend/migrations:/docker-entrypoint-initdb.d - healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-postgres}"] - interval: 10s - timeout: 5s - retries: 5 - - backend: - build: - context: ./backend - dockerfile: Dockerfile - restart: unless-stopped - ports: - - "${BACKEND_PORT:-3000}:3000" - environment: - NODE_ENV: production - PORT: 3000 - DB_HOST: postgres - DB_PORT: 5432 - DB_NAME: ${DB_NAME:-company_finance} - DB_USER: ${DB_USER:-postgres} - DB_PASSWORD: ${DB_PASSWORD:-changeme} - JWT_SECRET: ${JWT_SECRET:-please-change-this-secret} - CORS_ORIGIN: ${CORS_ORIGIN:-} - TENCENT_SECRET_ID: ${TENCENT_SECRET_ID:-} - TENCENT_SECRET_KEY: ${TENCENT_SECRET_KEY:-} - COS_BUCKET: ${COS_BUCKET:-} - COS_REGION: ${COS_REGION:-} - depends_on: - postgres: - condition: service_healthy - volumes: - - upload_data:/app/uploads - - frontend: - build: - context: ./frontend - dockerfile: Dockerfile - restart: unless-stopped - ports: - - "${FRONTEND_PORT:-80}:80" - depends_on: - - backend + networks: + - yunhaifinance-network volumes: - postgres_data: - upload_data: + yunhaifinance-postgres-data: + +networks: + yunhaifinance-network: \ No newline at end of file diff --git a/frontend/Dockerfile b/frontend/Dockerfile index cfe242c..5e43581 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -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 diff --git a/frontend/index.html b/frontend/index.html index 95d823a..5f60a8c 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -7,11 +7,11 @@ - - + + - 轻远电力老挝ERP - Qingyuan Power Laos + 云海财务系统 diff --git a/frontend/public/manifest.json b/frontend/public/manifest.json index a643820..8c608c7 100644 --- a/frontend/public/manifest.json +++ b/frontend/public/manifest.json @@ -1,7 +1,7 @@ { - "name": "轻远电力老挝ERP", - "short_name": "轻远ERP", - "description": "轻远电力老挝分公司财务管理系统", + "name": "云海财务系统", + "short_name": "云海财务", + "description": "云海财务系统 - 企业管理平台", "start_url": "/", "display": "standalone", "orientation": "portrait", diff --git a/frontend/src/components/common/CompanyLogo.tsx b/frontend/src/components/common/CompanyLogo.tsx index e3c7ee9..300d3c0 100644 --- a/frontend/src/components/common/CompanyLogo.tsx +++ b/frontend/src/components/common/CompanyLogo.tsx @@ -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 = ({ showText = true, size = 'medium' }) => { +const CompanyLogo: React.FC = ({ 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 = ({ showText = true, size = 'medi } const { fontSize, iconSize } = sizeMap[size] + const displayContent = showText && !collapsed return ( {/* 图标 */} - = ({ showText = true, size = 'medi /> {/* 公司名称 */} - {showText && ( + {displayContent && (
= ({ showText = true, size = 'medi marginTop: -2 }} > - Qingyuan Power Laos + Yunhai Finance System </Text> </div> )} diff --git a/frontend/src/components/layout/MainLayout.tsx b/frontend/src/components/layout/MainLayout.tsx index 8d3c7d4..7c61904 100644 --- a/frontend/src/components/layout/MainLayout.tsx +++ b/frontend/src/components/layout/MainLayout.tsx @@ -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 diff --git a/frontend/src/locales/zh-CN.ts b/frontend/src/locales/zh-CN.ts index 1670ab0..24fa5f8 100644 --- a/frontend/src/locales/zh-CN.ts +++ b/frontend/src/locales/zh-CN.ts @@ -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: { diff --git a/frontend/src/pages/admin/AboutPage.tsx b/frontend/src/pages/admin/AboutPage.tsx index 259b899..bebaf74 100644 --- a/frontend/src/pages/admin/AboutPage.tsx +++ b/frontend/src/pages/admin/AboutPage.tsx @@ -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')} - {t('about.description')} -
+
+ +
+ {t('about.systemNameValue')} + + 高效、智能、专业的企业财务与项目管理平台 + + +
+
diff --git a/frontend/src/pages/auth/LoginPage.tsx b/frontend/src/pages/auth/LoginPage.tsx index 0afe739..44ca45b 100644 --- a/frontend/src/pages/auth/LoginPage.tsx +++ b/frontend/src/pages/auth/LoginPage.tsx @@ -74,19 +74,39 @@ const LoginPage: React.FC = () => { return (
+ {/* 遮罩层以确保表单可读性 */} +
+ @@ -102,13 +122,9 @@ const LoginPage: React.FC = () => {
-
- {t('login.selectLanguage')} -
@@ -127,51 +143,61 @@ const LoginPage: React.FC = () => { layout="vertical" onFinish={handleSubmit} autoComplete="off" + initialValues={{ username: 'admin', password: QUICK_PASSWORD }} > } + prefix={} placeholder={t('login.usernamePlaceholder')} size="large" + style={{ borderRadius: 8 }} /> } + prefix={} placeholder={t('login.passwordPlaceholder')} size="large" + style={{ borderRadius: 8 }} /> - + + + - {t('login.testAccounts')} +
+ 默认管理员账号: admin / {QUICK_PASSWORD} +
+ + {t('login.testAccounts')} {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' }} > - {account.role === t('user.admin') && } - {account.role === t('user.finance') && } - {account.role === t('user.manager') && } - {account.role === t('user.employee') && } + {account.role === t('user.admin') && } + {account.role === t('user.finance') && } + {account.role === t('user.manager') && } + {account.role === t('user.employee') && } {account.name} @@ -197,23 +223,6 @@ const LoginPage: React.FC = () => {
))} - - - - {t('menu.dashboard')}: - • {t('features.projectManage')} - • {t('features.advanceManage')} - • {t('features.reimburseManage')} - • {t('features.financeReport')} - • {t('features.mobileSupport')} - - - -
- - {t('login.techSupport')} - -
diff --git a/scripts/init_sample_data.sql b/scripts/init_sample_data.sql new file mode 100644 index 0000000..5c5edff --- /dev/null +++ b/scripts/init_sample_data.sql @@ -0,0 +1,58 @@ +SET client_encoding = 'UTF8'; + +CREATE TABLE IF NOT EXISTS users ( + id SERIAL PRIMARY KEY, + username VARCHAR(255) UNIQUE, + name VARCHAR(255), + email VARCHAR(255), + phone VARCHAR(255), + role VARCHAR(50), + password_hash VARCHAR(255), + created_at TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS customers ( + id SERIAL PRIMARY KEY, + name VARCHAR(255), + address VARCHAR(255), + remark TEXT, + contact_person VARCHAR(255), + phone VARCHAR(255), + email VARCHAR(255), + created_at TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS projects ( + id SERIAL PRIMARY KEY, + name VARCHAR(255), + project_code VARCHAR(255), + customer_id INTEGER, + project_manager_id INTEGER, + contract_amount NUMERIC, + status VARCHAR(50), + location VARCHAR(255), + created_at TIMESTAMP, + updated_at TIMESTAMP +); + +-- 1. 插入用户数据 +INSERT INTO users (username, name, email, phone, role, password_hash, created_at, updated_at) VALUES +('admin', '系统管理员', 'admin@yunhai.com', '13800000001', 'admin', '$2a$10$xyz', NOW(), NOW()), +('finance', '财务专员', 'finance@yunhai.com', '13800000002', 'finance', '$2a$10$xyz', NOW(), NOW()), +('manager', '项目经理', 'manager@yunhai.com', '13800000003', 'manager', '$2a$10$xyz', NOW(), NOW()), +('employee', '普通员工', 'employee@yunhai.com', '13800000004', 'employee', '$2a$10$xyz', NOW(), NOW()) +ON CONFLICT (username) DO NOTHING; + +-- 2. 插入客户数据 +INSERT INTO customers (name, address, remark, contact_person, phone, email, created_at, updated_at) VALUES +('老挝国家电力公司', '万象市', '大客户', 'Somphong', '020-11111111', 'edl@laos.com', NOW(), NOW()), +('万象基建集团', '万象市', '长期合作', 'Champa', '020-22222222', 'infra@laos.com', NOW(), NOW()), +('琅勃拉邦电力局', '琅勃拉邦', '', 'Keo', '020-33333333', 'lpq@laos.com', NOW(), NOW()); + +-- 3. 插入项目数据 (假设customer_id与上表对应) +INSERT INTO projects (name, project_code, customer_id, project_manager_id, contract_amount, status, location, created_at, updated_at) VALUES +('万象22kV线路工程', 'P2026-001', 1, 3, 1500000, 'in_progress', '万象市赛塔尼县', NOW(), NOW()), +('琅勃拉邦变电站改造', 'P2026-002', 3, 3, 800000, 'planning', '琅勃拉邦', NOW(), NOW()), +('南塔电力抢修', 'P2026-003', 1, 3, 300000, 'completed', '南塔省', NOW(), NOW());