Commit 417891d8 by luoqi

feat:项目精简

parent 8472f7f4
Pipeline #3219 failed with stage
in 5 seconds
# 使用 CircleCI 2.1 版本的配置语法
version: 2.1
# "Jobs" 定义了要执行的具体任务
jobs:
# 将这个任务命名为 "deploy"
deploy:
# 指定运行此任务的环境。我们选择一个预装了常用工具(如 git, ssh)的基础 Docker 镜像
docker:
- image: cimg/base:stable
# "steps" 定义了任务中要按顺序执行的具体步骤
steps:
# 第一步:添加 SSH 密钥,用于连接你的部署服务器
# CircleCI 会从你的项目设置中,加载你预先存好的那个 SSH 私钥
- add_ssh_keys:
fingerprints:
- "SHA256:xnKKtj4THMHlhsQ/KW+cWuRaMl1nU/jFz6BWdya/Zmk"
# 第二步:执行连接服务器并部署的命令
- run:
name: Connect and Deploy to Server
# 这里的 command 就是您提供的部署脚本
command: |
echo "准备连接到部署服务器..."
# 使用 ssh 命令连接你的服务器
# -p $SSH_PORT 指定了你修改后的端口
# -o StrictHostKeyChecking=no 避免了首次连接时需要手动确认主机的提示,这在自动化脚本中是必需的
# $SSH_USER 和 $SSH_HOST 是你需要在 CircleCI 网站上设置的环境变量
ssh -p 19822 -o StrictHostKeyChecking=no root@47.251.104.47 << 'EOF'
# --- 以下是在你的部署服务器上执行的命令 ---
echo "✅ 连接服务器成功,开始执行部署脚本..."
# 1. 进入你的项目工作目录
# 请确保这个目录在服务器上已经存在,并且已经从 GitLab 克隆过一次
echo "进入项目目录: performance-score"
cd performance-score
# 2. 从 master 分支拉取最新的代码
echo "正在从 GitLab (origin) 拉取最新代码..."
git pull origin master
# 3. 使用 Docker Compose 重新构建并启动服务
echo "正在使用 Docker Compose 部署..."
docker compose up -d --build
echo "🚀 部署流程执行完毕!"
# --- 远程服务器上的命令结束 ---
EOF
# "Workflows" 用来编排和组织 Jobs 的执行流程和触发条件
workflows:
# 将这个工作流命名为 "build-and-deploy"
build-and-deploy:
jobs:
- deploy:
# "filters" 是过滤器,用来定义触发此 Job 的条件
filters:
branches:
# "only" 表示只有当代码被推送到指定分支时,才执行这个 Job
only:
- master
# 前端环境变量配置 # ========================================
# 绩效计分系统 - 环境变量配置
# ========================================
# API 服务地址 - 指向外部API服务 # ==================== 前端配置 ====================
# API 服务地址 - 前端访问后端API的地址
VITE_API_BASE_URL=http://localhost:8000 VITE_API_BASE_URL=http://localhost:8000
# 应用配置 # ==================== 后端配置 ====================
VITE_APP_TITLE=绩效计分系统 # 数据库配置
VITE_APP_VERSION=8.8.0 DATABASE_URL=postgresql://performance_user:performance_pass@localhost:5431/performance_db
# 开发模式配置 # API 服务配置
VITE_DEV_MODE=true API_HOST=0.0.0.0
API_PORT=8000
# CORS 配置(允许的前端域名)
CORS_ORIGINS=http://localhost:5173,http://localhost:8080,http://localhost:4001
# 安全配置
SECRET_KEY=your-secret-key-here-change-in-production
# 日志配置
LOG_LEVEL=INFO
LOG_FILE=logs/api.log
# 数据迁移配置
MIGRATION_BATCH_SIZE=100
# 前端环境变量配置 # ========================================
# 绩效计分系统 - 环境变量配置示例
# ========================================
# 复制此文件为 .env 并根据实际情况修改配置
# API 服务地址 # ==================== 前端配置 ====================
# API 服务地址 - 前端访问后端API的地址
VITE_API_BASE_URL=http://localhost:8000 VITE_API_BASE_URL=http://localhost:8000
# 应用配置 # ==================== 后端配置 ====================
VITE_APP_TITLE=绩效计分系统 # 数据库配置
VITE_APP_VERSION=8.8.0 # 格式: postgresql://用户名:密码@主机:端口/数据库名
DATABASE_URL=postgresql://performance_user:performance_pass@localhost:5431/performance_db
# 开发模式配置 # API 服务配置
VITE_DEV_MODE=true API_HOST=0.0.0.0
API_PORT=8000
# CORS 配置(允许的前端域名,JSON数组格式)
CORS_ORIGINS=["http://localhost:5173","http://localhost:8080","http://localhost:4001"]
# 安全配置
# 生产环境请务必更改为强密码
SECRET_KEY=your-secret-key-here-change-in-production
# 日志配置
LOG_LEVEL=INFO
LOG_FILE=logs/api.log
# 数据迁移配置
MIGRATION_BATCH_SIZE=100
# ==================== 开发环境说明 ====================
# 开发环境默认配置:
# - 前端开发服务器: http://localhost:5173 (vite dev)
# - 前端预览服务器: http://localhost:4001 (vite preview)
# - 后端API服务器: http://localhost:8000 (FastAPI)
# - 数据库: PostgreSQL localhost:5431
# ==================== 生产环境说明 ====================
# 生产环境需要修改的配置:
# 1. SECRET_KEY - 使用强随机密钥
# 2. DATABASE_URL - 使用生产数据库地址
# 3. CORS_ORIGINS - 只允许生产域名
# 4. LOG_LEVEL - 可设置为 WARNING 或 ERROR
...@@ -14,6 +14,11 @@ build/ ...@@ -14,6 +14,11 @@ build/
.env.development.local .env.development.local
.env.test.local .env.test.local
.env.production.local .env.production.local
backend/.env
backend/.env.local
backend/.env.development.local
backend/.env.test.local
backend/.env.production.local
# IDE files # IDE files
.vscode/ .vscode/
......
# 绩效计分系统 Docker 部署指南 ++ /dev/null
# 绩效计分系统 Docker 部署指南
## 概述
本指南介绍如何使用Docker容器化部署绩效计分系统到生产环境。
## 系统架构
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Nginx Proxy │ │ Application │ │ PostgreSQL │
│ (Port 80/443) │────│ (Port 4001) │────│ (Port 5432) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌─────────────────┐
│ Redis │
│ (Port 6379) │
└─────────────────┘
```
## 前置要求
### 系统要求
- Windows 10/11 或 Windows Server 2019+
- 至少 4GB RAM
- 至少 10GB 可用磁盘空间
- 稳定的网络连接
### 软件要求
- Docker Desktop for Windows
- Docker Compose (通常包含在Docker Desktop中)
## 快速部署
### 1. 安装Docker Desktop
1. 下载Docker Desktop: https://www.docker.com/products/docker-desktop
2. 运行安装程序并重启计算机
3. 启动Docker Desktop并等待完全启动
### 2. 验证安装
```bash
docker --version
docker-compose --version
```
### 3. 一键部署
运行部署脚本:
```bash
deploy.bat
```
或手动执行:
```bash
# 构建并启动所有服务
docker-compose up -d --build
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f
```
## 服务配置
### 端口映射
- **80**: Nginx反向代理 (HTTP)
- **443**: Nginx反向代理 (HTTPS)
- **8080**: 应用主入口
- **4001**: 后端API服务
- **5432**: PostgreSQL数据库
- **6379**: Redis缓存
### 环境变量
`docker-compose.yml` 中配置:
```yaml
environment:
- NODE_ENV=production
- PORT=4001
- REDIS_URL=redis://redis:6379
- DB_HOST=postgres
- DB_PORT=5432
- DB_NAME=performance_db
- DB_USER=performance_user
- DB_PASSWORD=performance_pass
```
### 数据持久化
系统使用Docker卷来持久化数据:
- `postgres_data`: 数据库数据
- `redis_data`: Redis数据
- `app_data`: 应用数据
- `app_logs`: 应用日志
- `nginx_logs`: Nginx日志
## 生产环境配置
### SSL证书配置
1. 将SSL证书文件放置在 `ssl/` 目录:
```
ssl/
├── cert.pem
└── key.pem
```
2. 更新 `nginx.prod.conf` 中的证书路径
### 安全配置
1. **修改默认密码**:
```bash
# 进入数据库容器
docker-compose exec postgres psql -U performance_user -d performance_db
# 更新管理员密码
UPDATE users SET password_hash = '$2b$10$新的哈希密码' WHERE username = 'admin';
```
2. **配置防火墙**:
- 只开放必要端口 (80, 443)
- 限制数据库端口访问
3. **定期备份**:
```bash
# 数据库备份
docker-compose exec postgres pg_dump -U performance_user performance_db > backup.sql
# 恢复数据库
docker-compose exec -T postgres psql -U performance_user performance_db < backup.sql
```
## 监控和维护
### 健康检查
系统内置健康检查端点:
- 应用健康: `http://localhost:8080/health`
- 数据库健康: 自动检查
- Redis健康: 自动检查
### 日志管理
```bash
# 查看所有服务日志
docker-compose logs
# 查看特定服务日志
docker-compose logs app
docker-compose logs postgres
docker-compose logs redis
# 实时跟踪日志
docker-compose logs -f app
```
### 性能监控
```bash
# 查看容器资源使用
docker stats
# 查看服务状态
docker-compose ps
# 重启服务
docker-compose restart app
```
## 故障排除
### 常见问题
1. **端口冲突**:
```bash
# 检查端口占用
netstat -ano | findstr :8080
# 修改docker-compose.yml中的端口映射
```
2. **内存不足**:
```bash
# 增加Docker Desktop内存限制
# 设置 -> Resources -> Advanced -> Memory
```
3. **数据库连接失败**:
```bash
# 检查数据库容器状态
docker-compose logs postgres
# 重启数据库服务
docker-compose restart postgres
```
### 完全重置
```bash
# 停止所有服务
docker-compose down
# 删除所有数据卷(注意:会丢失所有数据)
docker-compose down -v
# 清理所有镜像
docker system prune -a
# 重新部署
docker-compose up -d --build
```
## 更新部署
```bash
# 拉取最新代码
git pull
# 重新构建并部署
docker-compose up -d --build
# 或使用部署脚本
deploy.bat
```
## 备份策略
### 自动备份脚本
创建 `backup.bat`:
```batch
@echo off
set BACKUP_DIR=backups\%date:~0,4%-%date:~5,2%-%date:~8,2%
mkdir %BACKUP_DIR%
docker-compose exec postgres pg_dump -U performance_user performance_db > %BACKUP_DIR%\database.sql
docker-compose exec redis redis-cli --rdb %BACKUP_DIR%\redis.rdb
echo 备份完成: %BACKUP_DIR%
```
### 定期备份
使用Windows任务计划程序设置定期备份:
1. 打开任务计划程序
2. 创建基本任务
3. 设置触发器(每日/每周)
4. 设置操作为运行 `backup.bat`
## 支持
如有问题,请检查:
1. Docker Desktop是否正常运行
2. 端口是否被占用
3. 系统资源是否充足
4. 网络连接是否正常
更多技术支持,请查看项目文档或联系系统管理员。
# 绩效计分系统 8.8 版本 - Docker 部署说明 ++ /dev/null
# 绩效计分系统 8.8 版本 - Docker 部署说明
## 🎉 部署成功!
绩效计分系统 8.8 版本已成功部署到 Docker 容器中,现在可以通过以下方式访问:
### 🌐 访问地址
- **主要访问地址**: http://localhost:4001/
- **管理员面板**: http://localhost:4001/admin
- **用户面板**: http://localhost:4001/user
### 👥 默认登录账号
- **管理员**: admin / admin123
- **张田田**: 13800138002 / 123456
- **陈锐屏**: 13800138001 / 123456
- **余芳飞**: 13800138003 / 123456
### 🐳 容器信息
- **容器名称**: scoring-system-8.8
- **镜像版本**: scoring-system:8.8
- **端口映射**: 4001:80
- **状态**: 运行中 (健康检查启用)
### 🛠️ 管理命令
#### 快速管理
- **一键管理**: 双击 `docker-manage.bat`
- **重新部署**: 双击 `docker-deploy.bat`
#### 手动命令
```bash
# 查看容器状态
docker ps
# 查看日志
docker logs scoring-system-8.8
# 重启容器
docker restart scoring-system-8.8
# 停止容器
docker stop scoring-system-8.8
# 启动容器
docker start scoring-system-8.8
# 删除容器
docker rm -f scoring-system-8.8
```
### 🔧 技术特性
- ✅ 前端路由支持 (刷新 /admin 不会 404)
- ✅ 图片上传权限修复
- ✅ 数据自动修复机制
- ✅ 响应式设计
- ✅ 健康检查
- ✅ 静态资源缓存优化
### 📁 项目结构
```
绩效计分系统7.24/
├── Dockerfile # Docker 构建文件
├── nginx.conf # Nginx 配置 (SPA 回退)
├── docker-compose.yml # Docker Compose 配置
├── docker-deploy.bat # 一键部署脚本
├── docker-manage.bat # 容器管理脚本
├── dist/ # 构建产物
└── src/ # 源代码
```
### 🚀 生产环境部署建议
#### 1. 使用 Docker Compose
```bash
docker-compose up -d
```
#### 2. 自定义端口
修改 docker-compose.yml 中的端口映射:
```yaml
ports:
- "8080:80" # 改为 8080 端口
```
#### 3. 数据持久化
如需数据持久化,可挂载数据目录:
```yaml
volumes:
- ./data:/app/data
```
### 🔍 故障排除
#### 端口被占用
```bash
# 查看端口占用
netstat -ano | findstr :4001
# 使用其他端口
docker run -d -p 8080:80 --name scoring-system-8.8 scoring-system:8.8
```
#### 容器无法启动
```bash
# 查看详细日志
docker logs scoring-system-8.8
# 重新构建镜像
docker build -t scoring-system:8.8 .
```
### 📞 支持信息
- **版本**: 8.8.0
- **构建时间**: 2025-08-08
- **技术栈**: Vue 3 + Element Plus + Nginx
- **容器化**: Docker + Alpine Linux
---
## 🎯 下一步
系统已成功部署并运行,你可以:
1. 访问 http://localhost:4001/ 开始使用
2. 使用管理员账号登录查看所有功能
3. 测试图片上传和删除功能
4. 根据需要调整端口或配置
# Node.js 安装指南 ++ /dev/null
# Node.js 安装指南
## 🚀 快速安装Node.js
### 步骤1:下载Node.js
1. 访问Node.js官方网站:[https://nodejs.org/](https://nodejs.org/)
2. 下载LTS(长期支持)版本(推荐)
3. 选择对应您操作系统的版本:
- Windows: `.msi` 文件
- macOS: `.pkg` 文件
- Linux: 二进制包或通过包管理器
### 步骤2:安装Node.js(Windows)
#### 使用安装包(推荐)
1. 双击下载的 `.msi` 文件
2. 按照安装向导进行安装:
- 点击"Next"继续
- 接受许可协议
- 选择安装路径(建议使用默认路径)
- **重要**:确保勾选"Add to PATH"选项
- 点击"Install"开始安装
3. 安装完成后点击"Finish"
### 步骤3:验证安装
安装完成后,**重新打开**命令提示符或PowerShell,然后运行以下命令:
```bash
# 检查Node.js版本
node --version
# 检查npm版本
npm --version
```
如果显示版本号,说明安装成功!
### 步骤4:启动项目
现在您可以运行项目了:
```bash
# 1. 进入项目目录
cd "D:\绩效计分系统7.24"
# 2. 安装依赖
npm install
# 3. 启动开发服务器
npm run dev
```
## 🔧 常见问题解决
### 问题1:安装后仍然提示npm命令不存在
**解决方案:**
1. **重启命令行工具**:关闭所有PowerShell/命令提示符窗口,重新打开
2. **检查环境变量**
-`Win + R`,输入`sysdm.cpl`
- 点击"高级"选项卡 → "环境变量"
- 在"系统变量"中找到"Path"
- 确保包含类似路径:`C:\Program Files\nodejs\`
3. **重启计算机**:某些情况下需要重启系统
### 问题2:下载速度慢
**解决方案:**
可以使用国内镜像下载:
- 淘宝镜像:[https://npm.taobao.org/mirrors/node/](https://npm.taobao.org/mirrors/node/)
- 中科大镜像:[https://mirrors.ustc.edu.cn/node/](https://mirrors.ustc.edu.cn/node/)
### 问题3:权限问题
**解决方案:**
- 以管理员身份运行安装程序
- 安装到用户目录而不是系统目录
## 📋 安装检查清单
安装完成后,请确认以下项目:
- [ ] Node.js版本显示正常(推荐16.x或更高)
- [ ] npm版本显示正常(通常随Node.js一起安装)
- [ ] 重新打开了命令行工具
- [ ] 在项目目录下可以运行npm命令
## 🎯 推荐版本
- **Node.js**: 18.x LTS 或 20.x LTS
- **npm**: 8.x 或更高版本(随Node.js自动安装)
## 🆘 如果仍有问题
1. **检查杀毒软件**:某些杀毒软件可能阻止Node.js的安装
2. **尝试不同的安装方式**:
- 使用Chocolatey:`choco install nodejs`
- 使用Scoop:`scoop install nodejs`
3. **联系技术支持**:提供错误截图和系统信息
---
**安装完成后,请返回项目目录重新尝试启动命令!** 🚀
\ No newline at end of file
# 绩效计分系统 # 绩效计分系统
一个基于Vue 3的现代化绩效管理系统,用于管理用户、机构和图片上传的绩效评分。 一个基于 Vue 3 + FastAPI 的现代化全栈绩效管理系统,支持用户管理、机构管理、图片上传统计和绩效评分。
## 🚀 项目概述 ## 🚀 项目概述
绩效计分系统是一个全功能的Web应用程序,旨在帮助组织管理用户绩效、机构数据和图片上传统计。系统提供了直观的管理界面和用户界面,支持数据导出、历史统计和月度重置等功能。 绩效计分系统是一个企业级全栈Web应用程序,采用前后端分离架构,提供完整的用户绩效管理、机构数据管理和图片上传统计功能。系统支持多种部署方式,具备完善的数据迁移机制和实时数据同步能力。
### ✨ 核心特性
- 🔐 **JWT认证系统** - 基于JWT的安全认证,支持token刷新
- 👥 **用户权限管理** - 管理员和普通用户角色,细粒度权限控制
- 🏢 **机构管理** - 完整的机构CRUD操作,支持批量导入和权限分配
- 📊 **实时数据统计** - 动态统计和历史数据分析,支持数据可视化
- 📈 **智能绩效评分** - 自动计算互动分数和绩效分数
- 📁 **多格式数据导出** - 支持CSV、Excel、ZIP等格式导出
- 🔄 **自动化月度重置** - 定时任务支持,数据备份和清理
- 📱 **响应式设计** - 适配桌面端和移动端
- 🐳 **容器化部署** - 支持Docker一键部署
- 🔧 **数据库迁移** - 完善的数据库版本管理和迁移机制
## 🛠️ 技术架构
### 前端技术栈
- **Vue 3** - 组合式API,响应式框架
- **Element Plus** - 企业级UI组件库
- **Pinia** - 轻量级状态管理
- **Vue Router** - 单页面路由管理
- **Vite** - 快速构建工具
- **Axios** - HTTP客户端
### 后端技术栈
- **FastAPI** - 现代Python Web框架
- **SQLAlchemy** - ORM数据库操作
- **PostgreSQL** - 关系型数据库
- **Pydantic** - 数据验证和序列化
- **JWT** - 安全认证机制
- **APScheduler** - 定时任务调度
- **Loguru** - 结构化日志
### 基础设施
- **Docker** - 容器化部署
- **Nginx** - 反向代理和静态文件服务
- **PostgreSQL** - 数据持久化
- **数据库迁移系统** - 自动化schema管理
## � 快速开始
### 主要特性 ### 环境要求
- 🔐 **用户认证系统** - 支持管理员和普通用户角色 - **Node.js** 18+
- 👥 **用户管理** - 完整的用户CRUD操作 - **Python** 3.11+
- 🏢 **机构管理** - 机构信息管理和权限控制 - **PostgreSQL** 15+
- 📊 **数据统计** - 实时统计和历史数据分析 - **Docker** (可选,用于容器化部署)
- 📈 **绩效评分** - 自动计算互动分数和绩效分数
- 📁 **数据导出** - 支持CSV和ZIP格式导出
- 🔄 **月度重置** - 自动化的月度数据管理
- 📱 **响应式设计** - 适配各种设备屏幕
## 🛠️ 技术栈 ### 🎯 启动方式
### 前端 项目支持两种启动方式:**分步启动****Docker一键启动**
- **Vue 3** - 渐进式JavaScript框架
- **Element Plus** - Vue 3组件库
- **Pinia** - Vue状态管理
- **Vue Router** - 路由管理
- **Vite** - 构建工具
### 后端 #### 方式一:分步启动(开发推荐)
- **Express.js** - Node.js Web框架
- **CORS** - 跨域资源共享
### 数据存储 **1. 启动数据库**
- **LocalStorage** - 客户端数据存储 ```bash
- **JSON** - 数据格式 # 使用Docker启动PostgreSQL
docker run -d \
--name performance_postgres \
-e POSTGRES_DB=performance_db \
-e POSTGRES_USER=performance_user \
-e POSTGRES_PASSWORD=performance_pass \
-p 5431:5432 \
postgres:15-alpine
```
### 工具库 **2. 启动后端服务**
- **XLSX** - Excel文件处理 ```bash
- **jsPDF** - PDF生成 cd backend
- **JSZip** - ZIP文件处理 pip install -r requirements.txt
- **html2canvas** - 截图功能 # 或使用uv(推荐)
- **File-saver** - 文件下载 uv pip install -r requirements.txt
## 📦 安装指南 # 运行数据库迁移
python migrate.py
### 环境要求 # 启动API服务
uvicorn main:app --host 0.0.0.0 --port 8000 --reload
```
- Node.js >= 16.0.0 **3. 启动前端服务**
- npm >= 8.0.0 ```bash
npm install
npm run dev
```
### 安装步骤 #### 方式二:Docker一键启动(生产推荐)
1. **克隆项目**
```bash ```bash
# 克隆项目
git clone <repository-url> git clone <repository-url>
cd score-management-system cd performance-score
# 配置环境变量
cp .env.example .env
# 编辑 .env 文件,配置数据库等信息
# 一键启动所有服务
docker compose up -d
# 查看服务状态
docker compose ps
``` ```
2. **安装依赖** ### 🔗 访问地址
```bash
npm install - **前端应用**:http://localhost:4001
- **后端API**:http://localhost:8000
- **API文档**:http://localhost:8000/docs
- **数据库**:localhost:5431
### 👤 默认账号
- **管理员**:admin / admin123
- **普通用户**:user1 / user123
## 📁 项目结构
```
performance-score/
├── frontend/ # 前端应用
│ ├── src/ # 源代码目录
│ │ ├── components/ # Vue组件
│ │ ├── views/ # 页面组件
│ │ │ ├── admin/ # 管理员页面
│ │ │ ├── auth/ # 认证页面
│ │ │ └── user/ # 用户页面
│ │ ├── store/ # Pinia状态管理
│ │ │ ├── auth.js # 认证状态
│ │ │ └── data.js # 数据状态
│ │ ├── router/ # 路由配置
│ │ ├── services/ # API服务
│ │ │ └── api.js # API接口封装
│ │ ├── utils/ # 工具函数
│ │ └── styles/ # 样式文件
│ ├── package.json # 前端依赖配置
│ └── vite.config.js # Vite构建配置
├── backend/ # 后端API服务
│ ├── routers/ # API路由
│ │ ├── auth.py # 认证路由
│ │ ├── users.py # 用户管理
│ │ ├── institutions.py # 机构管理
│ │ ├── history.py # 历史数据
│ │ └── system_config.py # 系统配置
│ ├── models/ # 数据模型
│ ├── migrations/ # 数据库迁移
│ │ ├── migrate.py # 迁移脚本
│ │ └── versions/ # 迁移版本
│ ├── database.py # 数据库配置
│ ├── main.py # FastAPI应用入口
│ └── requirements.txt # Python依赖
├── docker compose.yml # Docker编排配置
├── Dockerfile # 容器构建文件
├── .env.example # 环境变量模板
└── README.md # 项目说明
``` ```
3. **启动开发服务器** ## 🔧 数据库迁移策略
```bash
npm run dev 项目采用完善的数据库版本管理和迁移机制,确保数据库结构变更的安全性和一致性。
### 迁移系统特点
- **🔄 自动迁移检测** - 启动时自动检测并执行待迁移的版本
- **📝 版本化管理** - 每个数据库变更都有对应的迁移文件
- **🛡️ 安全回滚** - 支持迁移失败时的安全回滚机制
- **📊 迁移日志** - 详细记录每次迁移的执行状态和时间
### 迁移文件结构
```
backend/migrations/
├── migrate.py # 迁移执行器
├── versions/ # 迁移版本目录
│ ├── 001_initial.py # 初始化数据库结构
│ ├── 002_add_institutions_data.py # 添加机构数据字段
│ └── 003_add_indexes.py # 添加数据库索引
└── migration_log.txt # 迁移执行日志
``` ```
4. **构建生产版本** ### 使用方法
```bash ```bash
npm run build # 手动执行迁移
cd backend
python migrate.py
# 查看迁移状态
python migrate.py --status
# 回滚到指定版本
python migrate.py --rollback 001
``` ```
5. **预览生产版本** ### 新增迁移
当需要修改数据库结构时:
1.`backend/migrations/versions/` 目录下创建新的迁移文件
2. 按照版本号命名:`00X_description.py`
3. 实现 `upgrade()``downgrade()` 函数
4. 重启应用,迁移将自动执行
## 🎯 核心功能模块
### 🔐 认证与权限系统
- **JWT安全认证** - 基于Token的无状态认证
- **角色权限控制** - 管理员/普通用户权限分离
- **Token自动刷新** - 无感知的登录状态保持
- **安全登出** - 服务端Token失效机制
### 👥 用户管理系统
- **用户CRUD操作** - 完整的用户生命周期管理
- **批量用户导入** - 支持Excel/CSV批量导入
- **用户状态管理** - 启用/禁用用户账号
- **密码安全策略** - 密码加密存储和重置
### 🏢 机构管理系统
- **机构层级管理** - 支持多级机构结构
- **权限精细控制** - 机构级别的数据访问控制
- **批量机构操作** - 导入、导出、转移等批量操作
- **机构数据统计** - 实时统计机构相关数据
### 📊 数据统计分析
- **实时数据监控** - 用户活跃度、上传量等实时统计
- **历史数据分析** - 月度、季度、年度数据趋势
- **绩效评分算法** - 智能计算用户绩效分数
- **数据可视化** - 图表展示统计结果
### 📁 数据导出系统
- **多格式导出** - CSV、Excel、ZIP等格式支持
- **自定义导出** - 可选择导出字段和时间范围
- **批量文件打包** - 图片和数据文件批量下载
- **导出任务管理** - 大数据量异步导出
### 🔄 自动化任务系统
- **月度数据重置** - 定时清理和备份月度数据
- **数据备份策略** - 自动备份重要数据
- **系统维护任务** - 日志清理、缓存更新等
- **任务调度管理** - 灵活的定时任务配置
## 📚 API文档
### 接口概览
系统提供完整的RESTful API,支持前后端分离架构。
**基础信息**
- **API Base URL**: `http://localhost:8000/api`
- **认证方式**: Bearer Token (JWT)
- **数据格式**: JSON
- **API文档**: http://localhost:8000/docs (Swagger UI)
### 主要接口
| 模块 | 方法 | 路径 | 描述 |
|------|------|------|------|
| 认证 | POST | `/users/login` | 用户登录 |
| 认证 | POST | `/users/refresh` | 刷新Token |
| 用户 | GET | `/users` | 获取用户列表 |
| 用户 | POST | `/users` | 创建用户 |
| 用户 | PUT | `/users/{id}` | 更新用户 |
| 用户 | DELETE | `/users/{id}` | 删除用户 |
| 机构 | GET | `/institutions` | 获取机构列表 |
| 机构 | POST | `/institutions` | 创建机构 |
| 历史 | GET | `/history` | 获取历史数据 |
| 配置 | GET | `/config` | 获取系统配置 |
### 认证示例
```bash ```bash
npm run preview # 登录获取Token
curl -X POST "http://localhost:8000/api/users/login" \
-H "Content-Type: application/json" \
-d '{"phone":"admin","password":"admin123"}'
# 使用Token访问API
curl -X GET "http://localhost:8000/api/users" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
``` ```
### 快速启动 ## 🔧 环境配置
使用提供的批处理文件(Windows): ### 环境变量
- `启动开发服务器.bat` - 启动开发环境
- `启动生产环境.bat` - 构建并启动生产环境
- `启动.bat` - 一键启动
## 📁 项目结构 创建 `.env` 文件配置环境变量:
```bash
# 数据库配置
DATABASE_URL=postgresql://performance_user:performance_pass@localhost:5431/performance_db
# JWT配置
SECRET_KEY=your-secret-key-here
ACCESS_TOKEN_EXPIRE_MINUTES=30
REFRESH_TOKEN_EXPIRE_DAYS=7
# 应用配置
DEBUG=true
CORS_ORIGINS=["http://localhost:4001"]
``` ```
绩效计分系统/
├── src/ # 源代码目录
│ ├── components/ # Vue组件
│ ├── views/ # 页面组件
│ │ ├── admin/ # 管理员页面
│ │ │ └── AdminPanel.vue
│ │ ├── auth/ # 认证页面
│ │ │ └── Login.vue
│ │ └── user/ # 用户页面
│ │ └── UserPanel.vue
│ ├── store/ # Pinia状态管理
│ │ ├── auth.js # 认证状态
│ │ └── data.js # 数据状态
│ ├── router/ # 路由配置
│ │ └── index.js
│ ├── styles/ # 样式文件
│ │ ├── global.css
│ │ └── theme.css
│ ├── utils/ # 工具函数
│ │ ├── dataCleanup.js
│ │ └── index.js
│ ├── App.vue # 根组件
│ └── main.js # 入口文件
├── docs/ # 项目文档
│ ├── 使用指南.md # 详细使用说明
│ └── 部署指南.md # 部署说明
├── scripts/ # 启动脚本
│ ├── start-dev.bat # 开发环境启动
│ └── start-prod.bat # 生产环境启动
├── public/ # 静态资源
├── dist/ # 构建输出
├── server/ # 服务器文件
├── production-deploy/ # 生产部署文件
├── package.json # 项目配置
├── vite.config.js # Vite配置
├── VERSION.md # 版本信息
├── 启动.bat # 一键启动脚本
└── README.md # 项目文档
```
## 🎯 主要功能模块
### 1. 用户管理
- 用户注册和登录
- 用户信息编辑
- 密码重置
- 用户权限管理
### 2. 机构管理
- 机构创建和编辑
- 机构权限分配
- 批量导入机构
- 机构转移功能
### 3. 数据统计
- 实时数据统计
- 用户绩效排名
- 图片上传统计
- 历史数据查看
### 4. 数据导出
- CSV格式导出
- ZIP图片包导出
- 用户数据导出
- 历史数据导出
### 5. 月度重置
- 手动月度重置
- 数据备份到历史记录
- 图片数据清理
- 重置时间记录
## 🔧 配置说明
### 开发环境配置 ### 开发环境配置
系统默认运行在端口4001,可在`vite.config.js`中修改 前端开发服务器配置(`vite.config.js`
```javascript ```javascript
export default defineConfig({ export default defineConfig({
server: { server: {
port: 4001, port: 4001,
host: '0.0.0.0' host: '0.0.0.0',
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true
}
}
} }
}) })
``` ```
### 生产环境配置 ## 🚀 生产部署
### Docker Compose 部署(推荐)
```bash
# 生产环境一键部署
docker compose -f docker compose.prod.yml up -d
# 查看服务状态
docker compose ps
# 查看日志
docker compose logs -f
```
生产环境使用Express服务器,配置文件在`server.js`中。 ### 手动部署
## 🚀 部署指南 **后端部署**
```bash
cd backend
pip install -r requirements.txt
python migrate.py
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
```
### 本地部署 **前端部署**
```bash
npm run build
# 将 dist/ 目录部署到 Nginx 或其他静态文件服务器
```
### Nginx 配置示例
```nginx
server {
listen 80;
server_name your-domain.com;
# 前端静态文件
location / {
root /path/to/dist;
try_files $uri $uri/ /index.html;
}
# 后端API代理
location /api/ {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
1. 构建项目:`npm run build` ## 📝 使用指南
2. 启动服务器:`npm run preview`
### Docker部署 ### 🔑 首次使用
1. 构建镜像:`docker build -t score-system .` 1. **启动系统** - 选择合适的启动方式(分步启动或Docker)
2. 运行容器:`docker run -p 4001:4001 score-system` 2. **访问应用** - 打开浏览器访问 http://localhost:4001
3. **管理员登录** - 使用默认管理员账号:admin / admin123
4. **初始化数据** - 创建用户和机构,配置系统参数
### 生产环境部署 ### 👨‍💼 管理员操作流程
参考`Docker部署指南.md``部署说明.md`文件。 **用户管理**
- 创建用户账号,分配角色权限
- 批量导入用户数据(支持Excel/CSV)
- 管理用户状态(启用/禁用)
- 重置用户密码
## 📝 使用说明 **机构管理**
- 创建机构层级结构
- 分配机构给用户
- 批量导入机构数据
- 设置机构权限
### 管理员功能 **数据管理**
- 查看实时统计数据
- 导出各类报表
- 执行月度数据重置
- 管理历史数据
1. **登录系统** - 使用管理员账号登录 ### 👤 普通用户操作流程
2. **用户管理** - 添加、编辑、删除用户
3. **机构管理** - 管理机构信息和权限
4. **数据统计** - 查看系统统计数据
5. **数据导出** - 导出各种格式的数据
6. **月度重置** - 执行月度数据重置
### 用户功能 **日常操作**
- 登录个人账号
- 查看分配的机构
- 上传机构相关图片
- 查看个人绩效统计
1. **登录系统** - 使用个人账号登录 **数据查看**
2. **查看机构** - 查看分配的机构信息 - 个人上传统计
3. **上传图片** - 上传机构相关图片 - 绩效分数排名
4. **查看统计** - 查看个人绩效数据 - 历史数据查询
## ⚠️ 注意事项 ## ⚠️ 注意事项
1. **数据备份** - 定期备份重要数据 ### 🔒 安全相关
2. **浏览器兼容** - 推荐使用Chrome、Firefox等现代浏览器 - **生产环境密钥** - 务必修改默认的JWT密钥和数据库密码
3. **存储限制** - LocalStorage有容量限制,注意数据大小 - **HTTPS部署** - 生产环境建议使用HTTPS协议
4. **月度重置** - 月度重置操作不可逆,请谨慎操作 - **权限控制** - 严格控制管理员权限的分配
5. **权限管理** - 确保用户权限设置正确 - **定期备份** - 建立完善的数据备份策略
### 🛠️ 技术要求
- **浏览器兼容** - 推荐使用Chrome 90+、Firefox 88+、Safari 14+
- **数据库维护** - 定期清理日志和优化数据库性能
- **资源监控** - 监控服务器资源使用情况
- **版本管理** - 使用数据库迁移系统管理结构变更
### 📊 运维建议
- **监控告警** - 设置系统监控和告警机制
- **日志管理** - 定期清理和归档系统日志
- **性能优化** - 根据使用情况调整数据库和应用配置
- **容灾备份** - 建立异地备份和容灾恢复方案
## 🔄 版本更新
### v2.0.0 (2025-08-30) - 架构重构版本
#### 🎯 重大变更
- **全栈重构** - 从单体前端应用重构为前后端分离架构
- **数据库升级** - 从LocalStorage迁移到PostgreSQL数据库
- **认证系统** - 实现基于JWT的安全认证机制
- **API设计** - 设计完整的RESTful API接口
#### ✨ 新增功能
- **Docker支持** - 支持容器化部署和一键启动
- **数据库迁移** - 完善的数据库版本管理和迁移机制
- **API文档** - 自动生成的Swagger API文档
- **日志系统** - 结构化日志记录和错误追踪
- **定时任务** - 支持自动化的后台任务调度
#### 🔧 技术升级
- **后端框架** - 采用FastAPI构建高性能API服务
- **数据库ORM** - 使用SQLAlchemy进行数据库操作
- **状态管理** - 前端使用Pinia替代Vuex
- **构建工具** - 使用Vite提升开发和构建效率
#### 🚀 部署优化
- **多种部署方式** - 支持分步启动和Docker一键部署
- **环境配置** - 完善的环境变量配置管理
- **生产优化** - 针对生产环境的性能和安全优化
## �️ 故障排除
### 常见问题
**启动问题**
```bash
# 检查端口占用
lsof -i :8000 # 后端端口
lsof -i :4001 # 前端端口
lsof -i :5431 # 数据库端口
# 清理Docker容器
docker compose down
docker system prune -f
```
**数据库连接问题**
```bash
# 检查数据库状态
docker ps | grep postgres
# 查看数据库日志
docker logs performance_postgres
## 🔄 最近更新 # 重新创建数据库
docker compose down
docker compose up -d postgres
```
### v1.0.0 (2025-01-11) **API请求失败**
- 检查后端服务是否正常启动
- 确认API地址和端口配置正确
- 查看浏览器网络面板的错误信息
- 检查JWT Token是否有效
#### 重要修复 ### 日志查看
- **月度重置功能修复** - 修复了月度重置显示错误的问题
- **错误处理优化** - 改进了错误处理和用户反馈
- **代码清理** - 移除了不必要的调试代码和临时文件
#### 功能优化 ```bash
- **导出功能精简** - 保留CSV和ZIP格式,移除JSON和Excel格式 # 查看后端日志
- **数据管理简化** - 移除了复杂的数据修复功能 docker compose logs -f backend
- **界面优化** - 改进了用户界面的响应性和易用性
#### 技术改进 # 查看前端构建日志
- **存储错误处理** - 增强了LocalStorage操作的错误处理 npm run dev
- **方法调用修复** - 修复了未定义方法调用的问题
- **调试信息优化** - 添加了更好的调试和错误信息 # 查看数据库日志
docker compose logs postgres
```
## 📞 技术支持 ## 📞 技术支持
如遇到问题,请查看: ### 🔍 问题诊断步骤
1. 项目文档和使用指南
2. 浏览器控制台错误信息 1. **查看系统状态** - 确认所有服务正常运行
3. 系统日志输出 2. **检查日志输出** - 查看详细的错误信息
3. **验证配置** - 确认环境变量和配置文件正确
4. **测试API** - 使用Swagger文档测试API接口
5. **浏览器调试** - 检查浏览器控制台和网络面板
### 📚 参考资源
- **API文档**: http://localhost:8000/docs
- **FastAPI官方文档**: https://fastapi.tiangolo.com/
- **Vue 3官方文档**: https://vuejs.org/
- **Element Plus文档**: https://element-plus.org/
## 🤝 贡献指南
### 开发流程
1. **Fork项目** - 创建项目分支
2. **本地开发** - 在本地环境进行开发和测试
3. **代码规范** - 遵循项目的代码规范和最佳实践
4. **测试验证** - 确保新功能正常工作且不影响现有功能
5. **提交PR** - 提交Pull Request并描述变更内容
### 代码规范
- **Python**: 遵循PEP 8规范
- **JavaScript**: 使用ESLint和Prettier
- **Vue**: 遵循Vue官方风格指南
- **Git**: 使用语义化的提交信息
## 📄 许可证 ## 📄 许可证
本项目仅供内部使用 本项目采用 MIT 许可证。详见 [LICENSE](LICENSE) 文件
--- ---
**绩效计分系统** - 让绩效管理更简单、更高效! **绩效计分系统** - 现代化的企业级绩效管理解决方案
🌟 如果这个项目对您有帮助,请给我们一个Star!
# 绩效计分系统 - 版本信息
## 当前版本:v1.0.0
### 发布日期:2025-01-11
## 📋 版本特性
### 核心功能
-**用户管理系统** - 完整的用户CRUD操作
-**机构管理功能** - 机构信息管理和权限控制
-**图片上传统计** - 实时图片上传统计和管理
-**绩效评分计算** - 自动计算互动分数和绩效分数
-**数据导出功能** - 支持CSV和ZIP格式导出
-**月度重置机制** - 手动月度数据重置和历史备份
-**历史数据管理** - 月度统计数据查看和管理
-**响应式设计** - 适配各种设备屏幕
### 技术栈
- **前端框架**:Vue 3.3.8
- **UI组件库**:Element Plus 2.4.4
- **状态管理**:Pinia 2.1.7
- **路由管理**:Vue Router 4.2.5
- **构建工具**:Vite 5.0.0
- **后端框架**:Express.js 5.1.0
- **数据存储**:LocalStorage + JSON
### 工具库
- **文件处理**:XLSX 0.18.5, jsPDF 3.0.1, JSZip 3.10.1
- **图片处理**:html2canvas 1.4.1
- **文件下载**:file-saver 2.0.5
- **工具函数**:lodash-es 4.17.21, uuid 11.1.0
## 🔄 更新日志
### v1.0.0 (2025-01-11) - 正式版本
#### 🔧 重要修复
- **月度重置功能修复** - 修复了月度重置显示错误的问题
- **错误处理优化** - 改进了错误处理和用户反馈机制
- **存储操作增强** - 增强了LocalStorage操作的错误处理
#### ⚡ 功能优化
- **导出功能精简** - 保留CSV和ZIP格式,移除JSON和Excel格式
- **数据管理简化** - 移除了复杂的数据修复功能,保留核心功能
- **界面优化** - 改进了用户界面的响应性和易用性
- **月度重置改进** - 改为仅手动重置,移除自动重置机制
#### 🧹 代码清理
- **文件整理** - 删除了临时文件、测试文件和重复文档
- **项目结构优化** - 重新组织了项目目录结构
- **文档完善** - 创建了完整的README和使用指南
#### 🛠️ 技术改进
- **方法调用修复** - 修复了未定义方法调用的问题
- **调试信息优化** - 添加了更好的调试和错误信息
- **启动脚本优化** - 简化了启动流程和脚本
### 修复问题
- 🐛 修复了数据加载异常的问题
- 🐛 修复了界面显示不一致的问题
- 🐛 修复了用户权限验证的问题
### 技术栈
- Vue 3.4.29
- Element Plus 2.7.6
- Vite 5.4.19
- Node.js 环境
### 部署说明
- 支持开发环境快速启动
- 准备Docker容器化部署
- 计划支持多用户实时数据同步
---
## 下一版本计划 (8.9)
- 🔄 多用户多浏览器数据同步
- 📡 WebSocket实时通信
- 🔐 增强安全性和权限管理
# 数据库配置
DATABASE_URL=postgresql://performance_user:performance_pass@localhost:5431/performance_db
# API 服务配置
API_HOST=0.0.0.0
API_PORT=8000
# CORS 配置(JSON 数组格式)
CORS_ORIGINS=["http://localhost:5173","http://localhost:8080","http://localhost:4001"]
# 安全配置
SECRET_KEY=your-secret-key-here-change-in-production
# 日志配置
LOG_LEVEL=INFO
LOG_FILE=logs/api.log
# 数据迁移配置
MIGRATION_BATCH_SIZE=100
# 数据库配置
DATABASE_URL=postgresql://performance_user:performance_pass@localhost:5431/performance_db
# API 服务配置
API_HOST=0.0.0.0
API_PORT=8000
# CORS 配置(JSON 数组格式)
CORS_ORIGINS=["http://localhost:5173","http://localhost:8080","http://localhost:4001"]
# 安全配置
SECRET_KEY=your-secret-key-here-change-in-production
# 日志配置
LOG_LEVEL=INFO
LOG_FILE=logs/api.log
# 数据迁移配置
MIGRATION_BATCH_SIZE=100
#!/usr/bin/env python3
"""
检查数据库表结构脚本
"""
import asyncio
from sqlalchemy import text
from database import database
import logging
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
async def check_table_structure():
"""检查 monthly_history 表结构"""
try:
# 连接数据库
await database.connect()
logger.info("已连接到数据库")
# 查询表结构
query = text("""
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_name = 'monthly_history'
ORDER BY ordinal_position;
""")
result = await database.fetch_all(query)
logger.info("monthly_history 表结构:")
logger.info("-" * 50)
for row in result:
logger.info(f"列名: {row['column_name']}, 类型: {row['data_type']}, 可空: {row['is_nullable']}")
# 检查是否存在 institutions_data 列
institutions_data_exists = any(row['column_name'] == 'institutions_data' for row in result)
if institutions_data_exists:
logger.info("✅ institutions_data 列存在")
else:
logger.error("❌ institutions_data 列不存在")
# 尝试添加列
logger.info("正在尝试添加 institutions_data 列...")
alter_query = text("""
ALTER TABLE monthly_history
ADD COLUMN institutions_data JSONB;
""")
await database.execute(alter_query)
logger.info("✅ 成功添加 institutions_data 列")
await database.disconnect()
logger.info("数据库连接已关闭")
except Exception as e:
logger.error(f"❌ 检查表结构失败: {e}")
raise
if __name__ == "__main__":
asyncio.run(check_table_structure())
...@@ -37,7 +37,7 @@ class Settings(BaseSettings): ...@@ -37,7 +37,7 @@ class Settings(BaseSettings):
MAX_IMAGES_PER_INSTITUTION: int = 10 MAX_IMAGES_PER_INSTITUTION: int = 10
# CORS 配置 # CORS 配置
CORS_ORIGINS: str = "*" # 简化为字符串格式,避免 JSON 解析问题 CORS_ORIGINS: str = "http://localhost:5173,http://localhost:4001,http://localhost:8080" # 允许的前端域名
# WebSocket 配置 # WebSocket 配置
WEBSOCKET_HEARTBEAT_INTERVAL: int = 30 WEBSOCKET_HEARTBEAT_INTERVAL: int = 30
...@@ -56,7 +56,8 @@ class Settings(BaseSettings): ...@@ -56,7 +56,8 @@ class Settings(BaseSettings):
MIGRATION_BATCH_SIZE: int = 100 MIGRATION_BATCH_SIZE: int = 100
class Config: class Config:
env_file = ".env" # 从项目根目录读取 .env 文件
env_file = os.path.join(os.path.dirname(os.path.dirname(__file__)), ".env")
case_sensitive = True case_sensitive = True
extra = "ignore" # 忽略额外的环境变量 extra = "ignore" # 忽略额外的环境变量
......
...@@ -96,14 +96,22 @@ app = FastAPI( ...@@ -96,14 +96,22 @@ app = FastAPI(
cors_origins = settings.CORS_ORIGINS cors_origins = settings.CORS_ORIGINS
if isinstance(cors_origins, str): if isinstance(cors_origins, str):
if cors_origins == "*": if cors_origins == "*":
# 当允许所有来源时,不能同时设置 allow_credentials=True
cors_origins = ["*"] cors_origins = ["*"]
allow_credentials = False
else: else:
cors_origins = [cors_origins] # 支持逗号分隔的多个域名
cors_origins = [origin.strip() for origin in cors_origins.split(",")]
allow_credentials = True
else:
allow_credentials = True
logger.info(f"🌐 CORS配置: origins={cors_origins}, credentials={allow_credentials}")
app.add_middleware( app.add_middleware(
CORSMiddleware, CORSMiddleware,
allow_origins=cors_origins, allow_origins=cors_origins,
allow_credentials=True, allow_credentials=allow_credentials,
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"], allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
allow_headers=["*"], allow_headers=["*"],
) )
......
#!/usr/bin/env python3
"""
数据库迁移脚本:为 monthly_history 表添加 institutions_data 列
"""
import asyncio
from sqlalchemy import text
from database import database, engine
import logging
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
async def migrate_database():
"""执行数据库迁移"""
try:
# 连接数据库
await database.connect()
logger.info("已连接到数据库")
# 检查列是否已存在
check_column_query = text("""
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'monthly_history'
AND column_name = 'institutions_data';
""")
result = await database.fetch_all(check_column_query)
if result:
logger.info("institutions_data 列已存在,无需迁移")
else:
# 添加 institutions_data 列
alter_query = text("""
ALTER TABLE monthly_history
ADD COLUMN institutions_data JSONB;
""")
await database.execute(alter_query)
logger.info("✅ 成功添加 institutions_data 列")
# 验证列是否添加成功
verify_result = await database.fetch_all(check_column_query)
if verify_result:
logger.info("✅ 验证成功:institutions_data 列已添加")
else:
logger.error("❌ 验证失败:institutions_data 列未添加")
await database.disconnect()
logger.info("数据库连接已关闭")
except Exception as e:
logger.error(f"❌ 数据库迁移失败: {e}")
raise
if __name__ == "__main__":
asyncio.run(migrate_database())
...@@ -7,6 +7,7 @@ from fastapi import APIRouter, HTTPException, Depends ...@@ -7,6 +7,7 @@ from fastapi import APIRouter, HTTPException, Depends
from typing import List, Dict, Any from typing import List, Dict, Any
from loguru import logger from loguru import logger
from datetime import datetime from datetime import datetime
from sqlalchemy import func
from database import monthly_history_table, get_database, DatabaseManager from database import monthly_history_table, get_database, DatabaseManager
from models import MonthlyHistoryCreate, MonthlyHistoryResponse, BaseResponse, UserResponse from models import MonthlyHistoryCreate, MonthlyHistoryResponse, BaseResponse, UserResponse
...@@ -15,13 +16,14 @@ from dependencies import get_current_active_user, require_admin ...@@ -15,13 +16,14 @@ from dependencies import get_current_active_user, require_admin
router = APIRouter() router = APIRouter()
@router.get("/", response_model=List[MonthlyHistoryResponse], summary="获取所有历史记录") @router.get("", response_model=List[MonthlyHistoryResponse], summary="获取所有历史记录")
async def get_all_history( async def get_all_history(
db: DatabaseManager = Depends(get_database), db: DatabaseManager = Depends(get_database),
current_user: UserResponse = Depends(get_current_active_user) current_user: UserResponse = Depends(get_current_active_user)
): ):
"""获取所有月度历史统计记录""" """获取所有月度历史统计记录"""
try: try:
# 简单查询,让数据库处理字段选择
query = monthly_history_table.select().order_by(monthly_history_table.c.month.desc()) query = monthly_history_table.select().order_by(monthly_history_table.c.month.desc())
histories = await db.fetch_all(query) histories = await db.fetch_all(query)
...@@ -29,9 +31,11 @@ async def get_all_history( ...@@ -29,9 +31,11 @@ async def get_all_history(
for history in histories: for history in histories:
try: try:
# 安全地获取 institutions_data,确保兼容性 # 安全地获取 institutions_data,确保兼容性
institutions_data = history["institutions_data"] if "institutions_data" in history._mapping else []
if institutions_data is None:
institutions_data = [] institutions_data = []
if hasattr(history, '_mapping') and "institutions_data" in history._mapping:
institutions_data = history["institutions_data"] or []
elif hasattr(history, 'institutions_data'):
institutions_data = history.institutions_data or []
result.append(MonthlyHistoryResponse( result.append(MonthlyHistoryResponse(
id=history["id"], id=history["id"],
...@@ -45,7 +49,7 @@ async def get_all_history( ...@@ -45,7 +49,7 @@ async def get_all_history(
created_at=history["created_at"] created_at=history["created_at"]
)) ))
except Exception as e: except Exception as e:
history_id = history["id"] if "id" in history._mapping else "unknown" history_id = history.get("id", "unknown")
logger.error(f"处理历史记录失败: {history_id}, 错误: {e}") logger.error(f"处理历史记录失败: {history_id}, 错误: {e}")
# 跳过有问题的记录,继续处理其他记录 # 跳过有问题的记录,继续处理其他记录
continue continue
...@@ -54,6 +58,10 @@ async def get_all_history( ...@@ -54,6 +58,10 @@ async def get_all_history(
except Exception as e: except Exception as e:
logger.error(f"获取历史记录失败: {e}") logger.error(f"获取历史记录失败: {e}")
# 如果是表不存在或字段不存在的错误,返回空列表而不是抛出异常
if "does not exist" in str(e).lower():
logger.info("历史记录表或字段不存在,返回空列表")
return []
raise HTTPException(status_code=500, detail="获取历史记录失败") raise HTTPException(status_code=500, detail="获取历史记录失败")
...@@ -99,7 +107,7 @@ async def get_history_by_month( ...@@ -99,7 +107,7 @@ async def get_history_by_month(
raise HTTPException(status_code=500, detail="获取历史记录失败") raise HTTPException(status_code=500, detail="获取历史记录失败")
@router.post("/", response_model=BaseResponse, summary="保存月度历史记录") @router.post("", response_model=BaseResponse, summary="保存月度历史记录")
async def save_monthly_history( async def save_monthly_history(
history_data: Dict[str, Any], # 改为更灵活的字典类型 history_data: Dict[str, Any], # 改为更灵活的字典类型
db: DatabaseManager = Depends(get_database), db: DatabaseManager = Depends(get_database),
...@@ -195,7 +203,7 @@ async def save_monthly_history( ...@@ -195,7 +203,7 @@ async def save_monthly_history(
raise HTTPException(status_code=500, detail=f"保存历史记录失败: {str(e)}") raise HTTPException(status_code=500, detail=f"保存历史记录失败: {str(e)}")
@router.delete("/", response_model=BaseResponse, summary="清空所有历史记录") @router.delete("", response_model=BaseResponse, summary="清空所有历史记录")
async def clear_all_history( async def clear_all_history(
db: DatabaseManager = Depends(get_database), db: DatabaseManager = Depends(get_database),
current_user: UserResponse = Depends(require_admin) current_user: UserResponse = Depends(require_admin)
......
...@@ -59,7 +59,7 @@ async def get_institution_with_images(institution_id: str, db: DatabaseManager): ...@@ -59,7 +59,7 @@ async def get_institution_with_images(institution_id: str, db: DatabaseManager):
) )
@router.get("/", response_model=List[InstitutionResponse], summary="获取机构列表") @router.get("", response_model=List[InstitutionResponse], summary="获取机构列表")
async def get_all_institutions( async def get_all_institutions(
db: DatabaseManager = Depends(get_database), db: DatabaseManager = Depends(get_database),
current_user: UserResponse = Depends(get_current_active_user) current_user: UserResponse = Depends(get_current_active_user)
...@@ -141,7 +141,7 @@ async def get_institutions_by_owner( ...@@ -141,7 +141,7 @@ async def get_institutions_by_owner(
raise HTTPException(status_code=500, detail="获取机构失败") raise HTTPException(status_code=500, detail="获取机构失败")
@router.post("/", response_model=InstitutionResponse, summary="创建机构") @router.post("", response_model=InstitutionResponse, summary="创建机构")
async def create_institution( async def create_institution(
institution_data: InstitutionCreate, institution_data: InstitutionCreate,
db: DatabaseManager = Depends(get_database), db: DatabaseManager = Depends(get_database),
......
...@@ -14,7 +14,7 @@ from dependencies import get_current_active_user, require_admin ...@@ -14,7 +14,7 @@ from dependencies import get_current_active_user, require_admin
router = APIRouter() router = APIRouter()
@router.get("/", response_model=Dict[str, Any], summary="获取所有系统配置") @router.get("", response_model=Dict[str, Any], summary="获取所有系统配置")
async def get_all_config( async def get_all_config(
db: DatabaseManager = Depends(get_database), db: DatabaseManager = Depends(get_database),
current_user: UserResponse = Depends(get_current_active_user) current_user: UserResponse = Depends(get_current_active_user)
...@@ -79,7 +79,7 @@ async def get_config_by_key(config_key: str, db: DatabaseManager = Depends(get_d ...@@ -79,7 +79,7 @@ async def get_config_by_key(config_key: str, db: DatabaseManager = Depends(get_d
raise HTTPException(status_code=500, detail="获取配置项失败") raise HTTPException(status_code=500, detail="获取配置项失败")
@router.post("/", response_model=BaseResponse, summary="创建或更新配置项") @router.post("", response_model=BaseResponse, summary="创建或更新配置项")
async def set_config( async def set_config(
config_item: SystemConfigItem, config_item: SystemConfigItem,
db: DatabaseManager = Depends(get_database), db: DatabaseManager = Depends(get_database),
......
...@@ -22,7 +22,7 @@ from config import settings ...@@ -22,7 +22,7 @@ from config import settings
router = APIRouter() router = APIRouter()
@router.get("/", response_model=List[UserResponse], summary="获取所有用户") @router.get("", response_model=List[UserResponse], summary="获取所有用户")
async def get_all_users( async def get_all_users(
db: DatabaseManager = Depends(get_database), db: DatabaseManager = Depends(get_database),
current_user: UserResponse = Depends(require_admin) current_user: UserResponse = Depends(require_admin)
...@@ -85,7 +85,7 @@ async def get_user_by_id( ...@@ -85,7 +85,7 @@ async def get_user_by_id(
raise HTTPException(status_code=500, detail="获取用户失败") raise HTTPException(status_code=500, detail="获取用户失败")
@router.post("/", response_model=UserResponse, summary="创建用户") @router.post("", response_model=UserResponse, summary="创建用户")
async def create_user( async def create_user(
user_data: UserCreate, user_data: UserCreate,
db: DatabaseManager = Depends(get_database), db: DatabaseManager = Depends(get_database),
......
#!/usr/bin/env python3
"""
数据库表结构更新脚本
为 monthly_history 表添加 institutions_data 字段
"""
import asyncio
import asyncpg
from loguru import logger
async def update_database():
"""更新数据库表结构"""
try:
# 连接数据库
conn = await asyncpg.connect(
host="localhost",
port=5432,
user="performance_user",
password="performance_pass",
database="performance_db"
)
logger.info("✅ 数据库连接成功")
# 检查字段是否已存在
check_query = """
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'monthly_history'
AND column_name = 'institutions_data'
"""
result = await conn.fetch(check_query)
if result:
logger.info("✅ institutions_data 字段已存在,无需更新")
else:
# 添加字段
alter_query = """
ALTER TABLE monthly_history
ADD COLUMN institutions_data JSONB
"""
await conn.execute(alter_query)
logger.info("✅ 成功添加 institutions_data 字段")
# 添加注释
comment_query = """
COMMENT ON COLUMN monthly_history.institutions_data
IS '机构图片数据,包含完整的机构和图片信息'
"""
await conn.execute(comment_query)
logger.info("✅ 成功添加字段注释")
# 验证更新结果
verify_query = """
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_name = 'monthly_history'
AND column_name = 'institutions_data'
"""
result = await conn.fetch(verify_query)
if result:
row = result[0]
logger.info(f"✅ 字段验证成功: {row['column_name']} ({row['data_type']}, nullable: {row['is_nullable']})")
else:
logger.error("❌ 字段验证失败")
await conn.close()
logger.info("✅ 数据库连接已关闭")
except Exception as e:
logger.error(f"❌ 数据库更新失败: {e}")
raise
if __name__ == "__main__":
asyncio.run(update_database())
# 系统开发规则文档 (Cursor Rules)
## 项目概述
开发一个基于Web的记分管理系统,支持多用户登录、机构管理、图片上传、得分计算等功能。
## 技术栈要求
- 前端框架:Vue.js 3 + Composition API
- 状态管理:Pinia
- 路由管理:Vue Router
- UI框架:Element Plus
- 数据持久化:localStorage
- 构建工具:Vite
## 代码结构规范
```
src/
├── assets/ # 静态资源
├── components/ # 公共组件
├── views/ # 页面组件
│ ├── auth/ # 认证相关页面
│ ├── user/ # 用户操作页面
│ └── admin/ # 管理员页面
├── store/ # 状态管理
├── router/ # 路由配置
├── utils/ # 工具函数
└── styles/ # 样式文件
```
## 功能模块实现规则
### 1. 用户认证模块
#### 登录功能
```javascript
// 实现规则
1. 手机号作为用户名登录
2. 管理员可重置用户密码
3. 密码存储需加密处理
4. 登录状态持久化保存
```
#### 用户权限控制
```javascript
// 权限级别
- 管理员:拥有所有权限
- 普通用户:仅能操作自己负责的机构
```
### 2. 用户操作界面
#### 机构搜索筛选
```javascript
// 实现规则
1. 支持按机构名称模糊搜索
2. 支持按上传状态筛选
3. 无匹配机构时显示提示信息
4. 搜索结果实时更新
```
#### 图片上传功能
```javascript
// 实现规则
1. 每个机构最多上传10张图片
2. 支持图片预览功能
3. 上传记录按时间倒序排列
4. 点击图片可查看大图
5. 支持图片删除操作
```
### 3. 管理员功能模块
#### 用户管理
```javascript
// 实现规则
1. 添加用户时需设置初始密码
2. 删除用户前必须转移其负责机构
3. 用户列表显示负责机构数量
4. 支持批量操作
```
#### 机构管理
```javascript
// 实现规则
1. 单个/批量添加机构
2. 批量删除机构功能
3. 机构调配需选择源用户和目标用户
4. 公池机构可分配给任意用户
```
### 4. 得分计算系统
#### 互动得分计算
```javascript
// 计算逻辑
1. 每个机构:
- 0张图片 = 0分
- 1张图片 = 0.5分
- 2张及以上图片 = 1分
2. 用户总互动得分 = 所有负责机构得分之和
```
#### 绩效得分计算
```javascript
// 计算公式
绩效得分 = (互动得分 ÷ 负责机构数) × 10
注意:负责机构数为0时,绩效得分为0
```
## 数据结构规范
### 用户数据结构
```javascript
{
id: 'unique_id',
phone: '手机号',
password: '加密密码',
name: '用户姓名',
role: 'admin/user',
institutions: ['机构ID数组']
}
```
### 机构数据结构
```javascript
{
id: 'unique_id',
name: '机构名称',
ownerId: '负责人ID',
images: [
{
id: '图片ID',
url: '图片URL',
uploadTime: '上传时间'
}
]
}
```
### 系统配置数据
```javascript
{
defaultUsers: [
{ name: '陈锐屏', institutions: ['A', 'B', 'C', 'D', 'E'] },
{ name: '张田田', institutions: ['a', 'b', 'c', 'd', 'e'] },
{ name: '余芳飞', institutions: ['①', '②', '③', '④', '⑤'] }
]
}
```
## localStorage存储规范
### 存储键名定义
```javascript
const STORAGE_KEYS = {
USERS: 'score_system_users',
INSTITUTIONS: 'score_system_institutions',
CURRENT_USER: 'score_system_current_user',
SYSTEM_CONFIG: 'score_system_config'
}
```
### 数据持久化规则
```javascript
1. 所有数据变更实时同步到localStorage
2. 页面加载时从localStorage恢复数据
3. 提供数据初始化功能
4. 支持数据导出/导入功能
```
## 界面设计规范
### 页面布局要求
```css
/* 响应式设计 */
1. 支持移动端访问
2. 主要操作区域清晰可见
3. 得分统计区域固定显示
4. 操作按钮醒目易用
```
### UI组件规范
```javascript
// 使用Element Plus组件
1. 表格:展示机构列表和用户列表
2. 表单:用户登录和数据录入
3. 对话框:确认操作和信息提示
4. 图片预览:图片查看功能
5. 进度条:得分可视化展示
```
## 错误处理规范
### 异常情况处理
```javascript
1. 网络异常:显示友好提示
2. 数据异常:提供恢复机制
3. 权限异常:跳转到登录页面
4. 操作异常:显示错误原因
```
## 性能优化规则
### 前端性能优化
```javascript
1. 图片懒加载
2. 数据分页加载
3. 组件按需加载
4. 防抖节流处理
```
## 安全规范
### 数据安全
```javascript
1. 密码加密存储
2. 敏感操作二次确认
3. 用户权限验证
4. 输入数据校验
```
## 测试要求
### 功能测试覆盖
```javascript
1. 用户登录流程
2. 图片上传下载
3. 得分计算准确性
4. 数据持久化验证
5. 权限控制验证
```
### 兼容性测试
```javascript
1. 主流浏览器支持
2. 移动端适配测试
3. 不同分辨率适配
```
## 开发约定
### 代码风格
```javascript
1. 使用ESLint代码检查
2. 遵循Vue.js风格指南
3. 函数命名语义化
4. 注释完整清晰
```
### 版本管理
```bash
# Git提交规范
feat: 新功能开发
fix: bug修复
style: 代码样式调整
refactor: 代码重构
test: 测试相关
docs: 文档更新
```
@echo off
chcp 65001 >nul
echo ================================
echo 绩效计分系统 Docker 部署脚本
echo ================================
echo.
echo [1/6] 检查Docker环境...
docker --version >nul 2>&1
if %errorlevel% neq 0 (
echo ❌ Docker未安装或未启动,请先安装Docker Desktop
pause
exit /b 1
)
docker-compose --version >nul 2>&1
if %errorlevel% neq 0 (
echo ❌ Docker Compose未安装
pause
exit /b 1
)
echo ✅ Docker环境检查通过
echo.
echo [2/6] 停止现有容器...
docker-compose down
echo.
echo [3/6] 清理旧镜像(可选)...
set /p cleanup="是否清理旧镜像?(y/N): "
if /i "%cleanup%"=="y" (
docker system prune -f
echo ✅ 清理完成
)
echo.
echo [4/6] 构建应用镜像...
docker-compose build --no-cache
if %errorlevel% neq 0 (
echo ❌ 镜像构建失败
pause
exit /b 1
)
echo ✅ 镜像构建完成
echo.
echo [5/6] 启动服务...
docker-compose up -d
if %errorlevel% neq 0 (
echo ❌ 服务启动失败
pause
exit /b 1
)
echo ✅ 服务启动完成
echo.
echo [6/6] 检查服务状态...
timeout /t 10 /nobreak >nul
docker-compose ps
echo.
echo ================================
echo 🎉 部署完成!
echo ================================
echo.
echo 📋 服务信息:
echo - 主应用: http://localhost:8080
echo - API接口: http://localhost:4001
echo - 数据库: localhost:5432
echo - Redis: localhost:6379
echo.
echo 📊 监控命令:
echo - 查看日志: docker-compose logs -f
echo - 查看状态: docker-compose ps
echo - 停止服务: docker-compose down
echo.
echo 🔧 管理命令:
echo - 重启服务: docker-compose restart
echo - 更新服务: docker-compose pull && docker-compose up -d
echo.
echo 正在检查服务健康状态...
timeout /t 5 /nobreak >nul
curl -s http://localhost:8080/health >nul 2>&1
if %errorlevel% equ 0 (
echo ✅ 应用服务正常
) else (
echo ⚠️ 应用服务可能还在启动中,请稍后检查
)
echo.
echo 按任意键打开应用...
pause >nul
start http://localhost:8080
@echo off
setlocal ENABLEDELAYEDEXPANSION
cd /d "%~dp0"
echo ========================================
echo 绩效计分系统 8.8 版本 - Docker 部署
echo ========================================
set CONTAINER_NAME=scoring-system-8.8
set IMAGE_NAME=scoring-system:8.8
set PORT=4001
echo [1/4] 检查 Docker 环境...
docker --version >nul 2>&1
if errorlevel 1 (
echo ❌ Docker 未安装或未启动
pause
exit /b 1
)
echo [2/4] 停止并移除旧容器(如果存在)...
docker stop %CONTAINER_NAME% >nul 2>&1
docker rm %CONTAINER_NAME% >nul 2>&1
echo [3/4] 构建最新镜像...
docker build -t %IMAGE_NAME% .
if errorlevel 1 (
echo ❌ 镜像构建失败
pause
exit /b 1
)
echo [4/4] 启动容器...
docker run -d -p %PORT%:80 --name %CONTAINER_NAME% %IMAGE_NAME%
if errorlevel 1 (
echo ❌ 容器启动失败
pause
exit /b 1
)
echo.
echo ✅ 部署成功!
echo.
echo 🌐 访问地址: http://localhost:%PORT%/
echo 📊 容器状态: docker ps
echo 📋 查看日志: docker logs %CONTAINER_NAME%
echo 🛑 停止服务: docker stop %CONTAINER_NAME%
echo.
echo 默认登录账号:
echo - 管理员: admin / admin123
echo - 张田田: 13800138002 / 123456
echo - 陈锐屏: 13800138001 / 123456
echo - 余芳飞: 13800138003 / 123456
echo.
pause
@echo off
setlocal ENABLEDELAYEDEXPANSION
cd /d "%~dp0"
set CONTAINER_NAME=scoring-system-8.8
set IMAGE_NAME=scoring-system:8.8
:menu
echo.
echo ========================================
echo 绩效计分系统 8.8 版本 - Docker 管理
echo ========================================
echo.
echo 1. 查看容器状态
echo 2. 查看容器日志
echo 3. 重启容器
echo 4. 停止容器
echo 5. 启动容器
echo 6. 删除容器
echo 7. 重新构建并部署
echo 8. 打开浏览器访问
echo 0. 退出
echo.
set /p choice=请选择操作 (0-8):
if "%choice%"=="1" goto status
if "%choice%"=="2" goto logs
if "%choice%"=="3" goto restart
if "%choice%"=="4" goto stop
if "%choice%"=="5" goto start
if "%choice%"=="6" goto remove
if "%choice%"=="7" goto rebuild
if "%choice%"=="8" goto open
if "%choice%"=="0" goto exit
echo 无效选择,请重试
goto menu
:status
echo.
echo 容器状态:
docker ps -a --filter name=%CONTAINER_NAME%
goto menu
:logs
echo.
echo 容器日志 (最近50行):
docker logs --tail 50 %CONTAINER_NAME%
goto menu
:restart
echo.
echo 重启容器...
docker restart %CONTAINER_NAME%
echo 重启完成
goto menu
:stop
echo.
echo 停止容器...
docker stop %CONTAINER_NAME%
echo 停止完成
goto menu
:start
echo.
echo 启动容器...
docker start %CONTAINER_NAME%
echo 启动完成
goto menu
:remove
echo.
echo 删除容器...
docker stop %CONTAINER_NAME% >nul 2>&1
docker rm %CONTAINER_NAME%
echo 删除完成
goto menu
:rebuild
echo.
echo 重新构建并部署...
docker stop %CONTAINER_NAME% >nul 2>&1
docker rm %CONTAINER_NAME% >nul 2>&1
docker build -t %IMAGE_NAME% .
docker run -d -p 4001:80 --name %CONTAINER_NAME% %IMAGE_NAME%
echo 重新部署完成
goto menu
:open
echo.
echo 打开浏览器...
start http://localhost:4001/
goto menu
:exit
echo 退出管理工具
exit /b 0
# 文档目录
此目录包含项目相关的文档文件。
# 绩效计分系统 - 完整使用指南 ++ /dev/null
# 绩效计分系统 - 完整使用指南
## 🎯 系统概述
绩效计分系统是一个基于Web的现代化应用,专为机构图片上传和绩效评分管理而设计。系统支持多用户角色、实时得分计算、数据统计分析等功能。
## 🚀 快速开始
### 环境要求
- Node.js >= 16.0.0
- 现代浏览器(Chrome、Firefox、Edge等)
### 启动系统
1. **开发环境启动**
```bash
npm run dev
```
或双击 `启动开发服务器.bat`
2. **生产环境启动**
```bash
npm run build
npm run preview
```
或双击 `启动生产环境.bat`
3. **访问系统**
- 开发环境:http://localhost:4001
- 生产环境:http://localhost:4001
## 👤 用户角色
### 管理员 (admin)
- **默认账号**:admin / admin123
- **权限**:系统完全控制权限
- **功能**:用户管理、机构管理、数据统计、系统配置
### 普通用户 (user)
- **账号**:由管理员创建
- **权限**:仅能访问分配的机构
- **功能**:图片上传、查看个人统计
## 🔐 登录系统
1. 打开浏览器访问系统地址
2. 在登录页面输入用户名和密码
3. 点击"登录"按钮
4. 系统会根据用户角色跳转到相应界面
## 👨‍💼 管理员功能详解
### 1. 数据统计
- **总体统计**:用户数、机构数、图片数
- **用户排名**:按绩效分数排序
- **上传统计**:图片上传情况分析
- **实时更新**:数据自动刷新
### 2. 用户管理
- **添加用户**:创建新用户账号
- **编辑用户**:修改用户信息
- **重置密码**:重置用户密码为123456
- **删除用户**:删除用户及相关数据
### 3. 机构管理
- **添加机构**:创建新机构
- **批量导入**:Excel批量导入机构
- **机构转移**:转移机构所有权
- **删除机构**:删除机构及图片数据
### 4. 数据管理
- **数据备份**:导出系统数据
- **数据恢复**:导入备份数据
- **月度重置**:清空图片数据,保存历史统计
### 5. 历史统计
- **月度数据**:查看历史月份统计
- **数据导出**:导出历史数据
- **数据删除**:删除指定月份数据
## 👤 用户功能详解
### 1. 机构查看
- **机构列表**:查看分配的机构
- **机构详情**:查看机构基本信息
- **图片统计**:查看已上传图片数量
### 2. 图片上传
- **选择机构**:选择要上传图片的机构
- **上传图片**:支持多种图片格式
- **查看图片**:查看已上传的图片
- **删除图片**:删除不需要的图片
### 3. 个人统计
- **绩效分数**:查看个人绩效评分
- **互动分数**:查看互动活跃度
- **上传统计**:查看上传图片统计
## 📊 评分规则
### 互动分数计算
- **基础分**:每个机构10分
- **上传奖励**:每上传1张图片+2分
- **完成奖励**:机构图片数≥5张时+10分
### 绩效分数计算
- **上传率权重**:40%
- **平均图片数权重**:35%
- **互动分数权重**:25%
## 📁 数据导出功能
### 支持格式
- **CSV格式**:表格数据导出
- **ZIP格式**:图片打包下载
### 导出内容
- **用户数据**:用户信息和统计数据
- **历史数据**:月度统计数据
- **图片数据**:机构图片文件
## 🔄 月度重置功能
### 重置内容
1. **保存统计**:当前月份数据保存到历史记录
2. **清空图片**:删除所有机构的图片数据
3. **重置分数**:用户分数重新计算
4. **更新时间**:记录重置时间
### 注意事项
- ⚠️ **不可逆操作**:重置后无法恢复
- 📅 **建议时机**:每月初执行
- 💾 **数据备份**:重置前建议备份数据
## 🛠️ 常见问题
### Q1: 忘记密码怎么办?
**A**: 联系管理员重置密码,重置后密码为123456
### Q2: 图片上传失败?
**A**: 检查图片格式和大小,确保网络连接正常
### Q3: 数据丢失怎么办?
**A**: 使用数据备份功能恢复,建议定期备份
### Q4: 系统运行缓慢?
**A**: 清理浏览器缓存,检查网络连接
### Q5: 无法访问某些功能?
**A**: 检查用户权限,确认是否有相应操作权限
## 📞 技术支持
### 故障排查
1. **检查浏览器控制台**:查看错误信息
2. **清理浏览器缓存**:解决显示问题
3. **重启系统**:解决临时故障
4. **检查网络连接**:确保网络正常
### 联系方式
- 查看系统日志获取详细错误信息
- 参考项目文档和README文件
## 📋 最佳实践
### 管理员建议
1. **定期备份**:每周备份系统数据
2. **用户培训**:为新用户提供使用培训
3. **权限管理**:合理分配用户权限
4. **数据监控**:定期检查数据完整性
### 用户建议
1. **及时上传**:按时上传机构图片
2. **图片质量**:确保图片清晰可用
3. **定期查看**:关注个人绩效数据
4. **问题反馈**:及时反馈使用问题
---
**绩效计分系统** - 让绩效管理更简单、更高效!
# 绩效计分系统 - 部署指南 ++ /dev/null
# 绩效计分系统 - 部署指南
## 📋 系统要求
### 最低要求
- **操作系统**: Windows 7/8/10/11, macOS 10.14+, Ubuntu 18.04+
- **Node.js**: 16.0 或更高版本
- **内存**: 至少 2GB RAM
- **硬盘**: 至少 500MB 可用空间
- **浏览器**: Chrome、Firefox、Edge(推荐Chrome)
### 推荐配置
- **操作系统**: Windows 10/11, macOS 12+, Ubuntu 20.04+
- **Node.js**: 18.0 或更高版本
- **内存**: 4GB RAM 或更多
- **硬盘**: 1GB 可用空间
- **网络**: 稳定的网络连接
## 🚀 快速部署
### 方案一:开发环境部署
适用于:开发、测试、演示
```bash
# 1. 安装依赖
npm install
# 2. 启动开发服务器
npm run dev
# 3. 访问系统
# 浏览器打开 http://localhost:4001
```
**Windows用户可直接双击**`启动开发服务器.bat`
### 方案二:生产环境部署
适用于:正式使用、生产环境
```bash
# 1. 安装依赖
npm install
# 2. 构建项目
npm run build
# 3. 启动生产服务器
npm run preview
```
**Windows用户可直接双击**`启动生产环境.bat`
## 🐳 Docker部署
### 使用Docker Compose(推荐)
```bash
# 1. 构建并启动
docker-compose up -d
# 2. 查看状态
docker-compose ps
# 3. 停止服务
docker-compose down
```
### 手动Docker部署
```bash
# 1. 构建镜像
docker build -t score-system .
# 2. 运行容器
docker run -d -p 4001:4001 --name score-system score-system
# 3. 查看日志
docker logs score-system
```
## ⚙️ 配置说明
### 端口配置
默认端口:4001
修改端口:编辑 `vite.config.js`
```javascript
export default defineConfig({
server: {
port: 4001, // 修改为其他端口
host: '0.0.0.0'
}
})
```
### 环境变量
创建 `.env` 文件:
```env
# 端口配置
VITE_PORT=4001
# API地址(如果有后端API)
VITE_API_URL=http://localhost:3000
# 应用标题
VITE_APP_TITLE=绩效计分系统
```
## 🔧 高级配置
### Nginx反向代理
创建 `/etc/nginx/sites-available/score-system`
```nginx
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:4001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
```
### SSL配置
使用Let's Encrypt:
```bash
# 安装certbot
sudo apt install certbot python3-certbot-nginx
# 获取SSL证书
sudo certbot --nginx -d your-domain.com
# 自动续期
sudo crontab -e
# 添加:0 12 * * * /usr/bin/certbot renew --quiet
```
## 🛠️ 故障排查
### 常见问题
1. **端口被占用**
```bash
# 查看端口占用
netstat -ano | findstr :4001
# 杀死进程
taskkill /PID <PID> /F
```
2. **Node.js版本过低**
```bash
# 检查版本
node --version
# 升级Node.js
# 访问 https://nodejs.org 下载最新版本
```
3. **依赖安装失败**
```bash
# 清理缓存
npm cache clean --force
# 删除node_modules重新安装
rm -rf node_modules package-lock.json
npm install
```
4. **内存不足**
```bash
# 增加Node.js内存限制
export NODE_OPTIONS="--max-old-space-size=4096"
npm run build
```
### 日志查看
- **开发环境**:控制台直接显示
- **生产环境**:检查 `logs/` 目录
- **Docker**`docker logs <container-name>`
## 📊 性能优化
### 构建优化
```javascript
// vite.config.js
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router', 'pinia'],
ui: ['element-plus']
}
}
},
chunkSizeWarningLimit: 1000
}
})
```
### 缓存配置
```nginx
# Nginx缓存配置
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
```
## 🔒 安全配置
### 基本安全措施
1. **更改默认密码**
- 首次登录后立即更改admin密码
2. **HTTPS配置**
- 生产环境必须使用HTTPS
3. **防火墙设置**
```bash
# Ubuntu防火墙
sudo ufw allow 4001
sudo ufw enable
```
4. **定期备份**
- 设置自动备份计划
- 备份数据到安全位置
## 📋 部署检查清单
### 部署前检查
- [ ] Node.js版本 >= 16.0
- [ ] 端口4001可用
- [ ] 网络连接正常
- [ ] 磁盘空间充足
### 部署后验证
- [ ] 系统可正常访问
- [ ] 登录功能正常
- [ ] 数据上传功能正常
- [ ] 导出功能正常
- [ ] 响应速度正常
### 生产环境检查
- [ ] HTTPS配置完成
- [ ] 防火墙配置正确
- [ ] 备份策略已设置
- [ ] 监控系统已配置
- [ ] 日志轮转已配置
## 📞 技术支持
### 获取帮助
1. 查看项目README.md
2. 检查docs目录下的文档
3. 查看系统日志文件
4. 检查浏览器控制台错误
### 报告问题
请提供以下信息:
- 操作系统和版本
- Node.js版本
- 浏览器类型和版本
- 错误信息截图
- 操作步骤描述
---
**绩效计分系统** - 专业的部署解决方案!
...@@ -7,9 +7,9 @@ server { ...@@ -7,9 +7,9 @@ server {
root /usr/share/nginx/html; root /usr/share/nginx/html;
index index.html; index index.html;
# API 代理到后端服务(仅当使用相对路径 /api 时) # API 代理到后端服务
location /api/ { location /api/ {
proxy_pass http://api:8000/; proxy_pass http://api:8000;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
......
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
# 性能优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 100;
types_hash_max_size 2048;
server_tokens off;
# 缓冲区设置
client_body_buffer_size 128k;
client_max_body_size 10m;
client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
output_buffers 1 32k;
postpone_output 1460;
# Gzip压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
# 限流配置
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
# 上游服务器配置
upstream backend {
least_conn;
server performance-system:80 max_fails=3 fail_timeout=30s;
keepalive 32;
}
# HTTP重定向到HTTPS
server {
listen 80;
server_name _;
return 301 https://$host$request_uri;
}
# HTTPS服务器
server {
listen 443 ssl http2;
server_name localhost;
# SSL配置
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# 现代SSL配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;
# 安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
# 静态文件缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary "Accept-Encoding";
}
# API限流
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# 登录限流
location /api/login {
limit_req zone=login burst=5 nodelay;
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# WebSocket代理
location /socket.io/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 7d;
proxy_send_timeout 7d;
proxy_read_timeout 7d;
}
# 主应用
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# 健康检查
location /health {
access_log off;
proxy_pass http://backend/health;
}
}
}
# 脚本目录
此目录包含项目的启动和部署脚本。
@echo off
chcp 65001 >nul
echo.
echo ==========================================
echo 绩效计分系统 - 清理缓存
echo ==========================================
echo.
echo [1/4] 清理浏览器缓存提示...
echo 请手动清理浏览器缓存:
echo - Chrome: Ctrl+Shift+Delete
echo - Firefox: Ctrl+Shift+Delete
echo - Edge: Ctrl+Shift+Delete
echo.
echo [2/4] 清理Vite缓存...
if exist "node_modules\.vite" (
rmdir /s /q "node_modules\.vite"
echo ✅ Vite缓存已清理
) else (
echo ℹ️ Vite缓存目录不存在
)
echo.
echo [3/4] 清理dist目录...
if exist "dist" (
rmdir /s /q "dist"
echo ✅ dist目录已清理
) else (
echo ℹ️ dist目录不存在
)
echo.
echo [4/4] 重新构建项目...
echo 正在重新安装依赖并构建...
call npm install
call npm run build
echo.
echo ✅ 缓存清理完成!
echo 💡 建议:
echo 1. 重启开发服务器
echo 2. 强制刷新浏览器 (Ctrl+F5)
echo 3. 检查浏览器开发者工具中的网络选项卡,确保禁用缓存
echo.
pause
# 绩效计分系统 - PowerShell缓存清理脚本
Write-Host ""
Write-Host "==========================================" -ForegroundColor Cyan
Write-Host " 绩效计分系统 - 清理缓存" -ForegroundColor Cyan
Write-Host "==========================================" -ForegroundColor Cyan
Write-Host ""
# 1. 清理Vite缓存
Write-Host "[1/4] 清理Vite缓存..." -ForegroundColor Yellow
if (Test-Path "node_modules\.vite") {
Remove-Item -Recurse -Force "node_modules\.vite"
Write-Host "✅ Vite缓存已清理" -ForegroundColor Green
} else {
Write-Host "ℹ️ Vite缓存目录不存在" -ForegroundColor Yellow
}
Write-Host ""
# 2. 清理dist目录
Write-Host "[2/4] 清理dist目录..." -ForegroundColor Yellow
if (Test-Path "dist") {
Remove-Item -Recurse -Force "dist"
Write-Host "✅ dist目录已清理" -ForegroundColor Green
} else {
Write-Host "ℹ️ dist目录不存在" -ForegroundColor Yellow
}
Write-Host ""
# 3. 清理npm缓存
Write-Host "[3/4] 清理npm缓存..." -ForegroundColor Yellow
try {
npm cache clean --force
Write-Host "✅ npm缓存已清理" -ForegroundColor Green
} catch {
Write-Host "⚠️ npm缓存清理失败" -ForegroundColor Red
}
Write-Host ""
# 4. 重新安装依赖
Write-Host "[4/4] 重新安装依赖..." -ForegroundColor Yellow
try {
npm install
Write-Host "✅ 依赖安装完成" -ForegroundColor Green
} catch {
Write-Host "❌ 依赖安装失败" -ForegroundColor Red
}
Write-Host ""
Write-Host "✅ 缓存清理完成!" -ForegroundColor Green
Write-Host ""
Write-Host "💡 接下来请:" -ForegroundColor Cyan
Write-Host "1. 启动开发服务器: npm run dev" -ForegroundColor White
Write-Host "2. 强制刷新浏览器: Ctrl+F5" -ForegroundColor White
Write-Host "3. 检查浏览器开发者工具,确保禁用缓存" -ForegroundColor White
Write-Host ""
# 询问是否立即启动开发服务器
$response = Read-Host "是否立即启动开发服务器?(y/n)"
if ($response -eq "y" -or $response -eq "Y" -or $response -eq "yes") {
Write-Host ""
Write-Host "🚀 正在启动开发服务器..." -ForegroundColor Green
npm run dev
}
Write-Host ""
Write-Host "按任意键退出..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
# 修复localhost访问问题的脚本
Write-Host ""
Write-Host "==========================================" -ForegroundColor Cyan
Write-Host " 修复localhost访问问题" -ForegroundColor Cyan
Write-Host "==========================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "[1/4] 清理DNS缓存..." -ForegroundColor Yellow
try {
ipconfig /flushdns
Write-Host "✅ DNS缓存已清理" -ForegroundColor Green
} catch {
Write-Host "⚠️ DNS缓存清理失败" -ForegroundColor Yellow
}
Write-Host ""
Write-Host "[2/4] 检查hosts文件..." -ForegroundColor Yellow
$hostsPath = "$env:SystemRoot\System32\drivers\etc\hosts"
$hostsContent = Get-Content $hostsPath -ErrorAction SilentlyContinue
$localhostEntry = $hostsContent | Where-Object { $_ -match "127\.0\.0\.1\s+localhost" }
if ($localhostEntry) {
Write-Host "✅ localhost映射正常" -ForegroundColor Green
} else {
Write-Host "⚠️ localhost映射可能有问题" -ForegroundColor Yellow
Write-Host "建议检查hosts文件: $hostsPath" -ForegroundColor White
}
Write-Host ""
Write-Host "[3/4] 清理浏览器缓存..." -ForegroundColor Yellow
Write-Host "请手动执行以下操作:" -ForegroundColor White
Write-Host "1. 完全关闭浏览器" -ForegroundColor White
Write-Host "2. 重新打开浏览器" -ForegroundColor White
Write-Host "3. 按 Ctrl+Shift+Delete 清理缓存" -ForegroundColor White
Write-Host "4. 或使用无痕模式访问" -ForegroundColor White
Write-Host ""
Write-Host "[4/4] 测试连接..." -ForegroundColor Yellow
$urls = @(
"http://localhost:4001/",
"http://127.0.0.1:4001/",
"http://192.168.100.70:4001/"
)
foreach ($url in $urls) {
try {
$response = Invoke-WebRequest -Uri $url -Method Head -TimeoutSec 5 -ErrorAction Stop
Write-Host "✅ $url - 连接正常 (状态码: $($response.StatusCode))" -ForegroundColor Green
} catch {
Write-Host "❌ $url - 连接失败" -ForegroundColor Red
}
}
Write-Host ""
Write-Host "✅ 修复完成!" -ForegroundColor Green
Write-Host ""
Write-Host "💡 如果localhost仍有问题,请尝试:" -ForegroundColor Cyan
Write-Host "1. 使用 http://127.0.0.1:4001/ 代替" -ForegroundColor White
Write-Host "2. 使用 http://192.168.100.70:4001/ (已确认工作)" -ForegroundColor White
Write-Host "3. 重启计算机以清理所有缓存" -ForegroundColor White
Write-Host ""
Write-Host "按任意键退出..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
# 绩效计分系统 - 强制刷新脚本
Write-Host ""
Write-Host "==========================================" -ForegroundColor Cyan
Write-Host " 绩效计分系统 - 强制刷新" -ForegroundColor Cyan
Write-Host "==========================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "🔍 检测到localhost缓存问题!" -ForegroundColor Yellow
Write-Host ""
# 1. 停止开发服务器
Write-Host "[1/6] 停止开发服务器..." -ForegroundColor Yellow
try {
# 查找并终止占用4001端口的进程
$processes = Get-NetTCPConnection -LocalPort 4001 -ErrorAction SilentlyContinue | Select-Object -ExpandProperty OwningProcess
if ($processes) {
foreach ($pid in $processes) {
Stop-Process -Id $pid -Force -ErrorAction SilentlyContinue
Write-Host "✅ 已停止进程 PID: $pid" -ForegroundColor Green
}
} else {
Write-Host "ℹ️ 没有发现占用4001端口的进程" -ForegroundColor Yellow
}
} catch {
Write-Host "⚠️ 停止进程时出现错误,继续执行..." -ForegroundColor Yellow
}
Start-Sleep -Seconds 2
# 2. 清理所有缓存
Write-Host ""
Write-Host "[2/6] 清理项目缓存..." -ForegroundColor Yellow
# 清理Vite缓存
if (Test-Path "node_modules\.vite") {
Remove-Item -Recurse -Force "node_modules\.vite"
Write-Host "✅ Vite缓存已清理" -ForegroundColor Green
}
# 清理dist目录
if (Test-Path "dist") {
Remove-Item -Recurse -Force "dist"
Write-Host "✅ dist目录已清理" -ForegroundColor Green
}
# 清理npm缓存
npm cache clean --force 2>$null
Write-Host "✅ npm缓存已清理" -ForegroundColor Green
# 3. 修改Vite配置以禁用缓存
Write-Host ""
Write-Host "[3/6] 临时禁用Vite缓存..." -ForegroundColor Yellow
$viteConfig = @"
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': '/src'
}
},
server: {
port: 4001,
host: '0.0.0.0',
hmr: true,
force: true
},
build: {
rollupOptions: {
output: {
manualChunks: undefined
}
}
},
// 强制禁用缓存
optimizeDeps: {
force: true
},
// 添加时间戳避免缓存
define: {
__BUILD_TIME__: JSON.stringify(new Date().getTime())
}
})
"@
$viteConfig | Out-File -FilePath "vite.config.js" -Encoding UTF8
Write-Host "✅ Vite配置已更新" -ForegroundColor Green
# 4. 重新安装依赖
Write-Host ""
Write-Host "[4/6] 重新安装依赖..." -ForegroundColor Yellow
npm install --force
Write-Host "✅ 依赖重新安装完成" -ForegroundColor Green
# 5. 启动开发服务器
Write-Host ""
Write-Host "[5/6] 启动开发服务器..." -ForegroundColor Yellow
Write-Host "🚀 正在启动,请稍候..." -ForegroundColor Green
# 在后台启动开发服务器
Start-Process -FilePath "npm" -ArgumentList "run", "dev" -WindowStyle Hidden
# 等待服务器启动
Write-Host "⏳ 等待服务器启动..." -ForegroundColor Yellow
Start-Sleep -Seconds 8
# 6. 打开浏览器并清理缓存
Write-Host ""
Write-Host "[6/6] 打开浏览器..." -ForegroundColor Yellow
Write-Host ""
Write-Host "🌐 正在打开浏览器..." -ForegroundColor Green
Write-Host "📍 地址: http://localhost:4001/" -ForegroundColor Cyan
Write-Host ""
# 打开浏览器
Start-Process "http://localhost:4001/"
Write-Host "⚠️ 重要提醒:" -ForegroundColor Red
Write-Host ""
Write-Host "在浏览器中请立即执行以下操作:" -ForegroundColor Yellow
Write-Host "1. 按 F12 打开开发者工具" -ForegroundColor White
Write-Host "2. 右键点击刷新按钮" -ForegroundColor White
Write-Host "3. 选择 '清空缓存并硬性重新加载'" -ForegroundColor White
Write-Host "4. 或者按 Ctrl+Shift+R 强制刷新" -ForegroundColor White
Write-Host ""
Write-Host "如果仍有问题,请:" -ForegroundColor Yellow
Write-Host "- 按 Ctrl+Shift+Delete 清理浏览器缓存" -ForegroundColor White
Write-Host "- 在开发者工具 Network 标签页勾选 'Disable cache'" -ForegroundColor White
Write-Host "- 尝试无痕模式访问" -ForegroundColor White
Write-Host ""
Write-Host "✅ 强制刷新完成!" -ForegroundColor Green
Write-Host ""
Write-Host "按任意键退出..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
@echo off
chcp 65001 >nul
echo.
echo ==========================================
echo 绩效计分系统 - 开发环境启动
echo ==========================================
echo.
echo [1/3] 检查Node.js环境...
node --version >nul 2>&1
if errorlevel 1 (
echo ❌ 未检测到Node.js,请先安装Node.js
echo 📥 下载地址:https://nodejs.org
pause
exit /b 1
)
echo ✅ Node.js环境检查通过
echo.
echo [2/3] 安装依赖包...
call npm install
if errorlevel 1 (
echo ❌ 依赖安装失败
pause
exit /b 1
)
echo ✅ 依赖安装完成
echo.
echo [3/3] 启动开发服务器...
echo 🚀 正在启动开发服务器...
echo 📱 启动完成后将自动打开浏览器
echo 🌐 访问地址:http://localhost:4001
echo.
echo ⚠️ 按 Ctrl+C 可停止服务器
echo.
call npm run dev
pause
@echo off
chcp 65001 >nul
echo.
echo ==========================================
echo 绩效计分系统 - 生产环境启动
echo ==========================================
echo.
echo [1/4] 检查Node.js环境...
node --version >nul 2>&1
if errorlevel 1 (
echo ❌ 未检测到Node.js,请先安装Node.js
echo 📥 下载地址:https://nodejs.org
pause
exit /b 1
)
echo ✅ Node.js环境检查通过
echo.
echo [2/4] 安装依赖包...
call npm install
if errorlevel 1 (
echo ❌ 依赖安装失败
pause
exit /b 1
)
echo ✅ 依赖安装完成
echo.
echo [3/4] 构建生产版本...
call npm run build
if errorlevel 1 (
echo ❌ 构建失败
pause
exit /b 1
)
echo ✅ 构建完成
echo.
echo [4/4] 启动生产服务器...
echo 🚀 正在启动生产服务器...
echo 🌐 访问地址:http://localhost:4001
echo.
echo ⚠️ 按 Ctrl+C 可停止服务器
echo.
call npm run preview
pause
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
* 替换原有的 localStorage 存储机制 * 替换原有的 localStorage 存储机制
*/ */
// API 基础配置 - 使用相对路径,通过Vite代理访问后端 // API 基础配置 - 直接使用后端API地址
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || '' const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
/** /**
* HTTP 请求封装类 * HTTP 请求封装类
...@@ -402,7 +402,7 @@ export const configApi = { ...@@ -402,7 +402,7 @@ export const configApi = {
// 设置配置项 // 设置配置项
async set(configKey, configValue, description = '') { async set(configKey, configValue, description = '') {
return apiClient.post('/api/config', { return apiClient.post('/api/config/', {
config_key: configKey, config_key: configKey,
config_value: configValue, config_value: configValue,
description description
......
@echo off
chcp 65001 >nul
echo ========================================
echo 绩效计分系统 - 数据库启动脚本
echo ========================================
echo.
REM 检查 Docker 是否安装
where docker >nul 2>&1
if errorlevel 1 (
echo ❌ 未检测到 Docker,请先安装 Docker Desktop
pause
exit /b 1
)
REM 检查 Docker 是否运行
docker info >nul 2>&1
if errorlevel 1 (
echo ❌ Docker 未运行,请启动 Docker Desktop
pause
exit /b 1
)
echo ✅ Docker 环境检查通过
echo.
echo 🚀 启动 PostgreSQL 数据库...
docker compose up -d postgres
if errorlevel 1 (
echo ❌ 数据库启动失败
pause
exit /b 1
)
echo.
echo ⏳ 等待数据库初始化完成...
timeout /t 10 /nobreak >nul
REM 检查数据库健康状态
echo 🔍 检查数据库连接状态...
docker compose exec postgres pg_isready -U performance_user -d performance_db >nul 2>&1
if errorlevel 1 (
echo ⚠️ 数据库可能还在初始化中,请稍后检查
) else (
echo ✅ 数据库连接正常
)
echo.
echo ========================================
echo 🎉 数据库启动完成!
echo ========================================
echo.
echo 📋 数据库信息:
echo - 主机: localhost
echo - 端口: 5432
echo - 数据库: performance_db
echo - 用户: performance_user
echo - 密码: performance_pass
echo.
echo 🔧 管理命令:
echo - 查看日志: docker compose logs postgres
echo - 停止数据库: docker compose stop postgres
echo - 连接数据库: docker compose exec postgres psql -U performance_user -d performance_db
echo.
pause
@echo off
chcp 65001 >nul
echo ========================================
echo 绩效计分系统 v8.6 - 开发服务器
echo ========================================
echo.
REM 检查Node.js是否安装
node --version >nul 2>&1
if errorlevel 1 (
echo ❌ 错误: 未找到Node.js,请先安装Node.js
echo 请访问 https://nodejs.org/ 下载安装
pause
exit /b 1
)
echo ✅ Node.js 环境检查通过
node --version
REM 检查npm是否可用
npm --version >nul 2>&1
if errorlevel 1 (
echo ❌ 错误: 未找到npm,请检查Node.js安装
pause
exit /b 1
)
echo ✅ npm 环境检查通过
npm --version
echo.
REM 检查node_modules是否存在
if not exist "node_modules" (
echo 📦 正在安装项目依赖...
echo 这可能需要几分钟时间,请耐心等待...
npm install
if errorlevel 1 (
echo ❌ 依赖安装失败,请检查网络连接
pause
exit /b 1
)
echo ✅ 依赖安装完成
)
echo.
echo 🚀 启动绩效计分系统 v8.6 开发服务器...
echo.
echo 📍 服务器地址: http://localhost:8080
echo 🏠 主系统: http://localhost:8080
echo 🔍 诊断页面: http://localhost:8080/public/diagnose.html
echo.
echo 默认登录账号:
echo - 管理员: admin / admin123
echo - 陈锐屏: 13800138001 / 123456
echo - 张田田: 13800138002 / 123456
echo - 余芳飞: 13800138003 / 123456
echo.
echo 按 Ctrl+C 停止服务器
echo ========================================
echo.
REM 尝试启动vite开发服务器,使用不同端口避免权限问题
echo 正在启动vite开发服务器...
npx vite --port 8080 --host 127.0.0.1
REM 如果vite失败,使用简单HTTP服务器
if errorlevel 1 (
echo.
echo ⚠️ vite启动失败,使用备用HTTP服务器...
node basic-server.js
)
pause
@echo off
setlocal ENABLEDELAYEDEXPANSION
chcp 65001 >nul
cd /d "%~dp0"
echo ========================================
echo 绩效计分系统 8.8 - Docker 启动
echo ========================================
REM 1) 检查 Docker 可用
where docker >nul 2>&1
if errorlevel 1 (
echo ❌ 未检测到 Docker,请先安装 Docker Desktop 并启动后重试
pause
exit /b 1
)
REM 2) 检查 Docker Engine 是否运行
for /f "tokens=2 delims=:" %%a in ('docker info 2^>^&1 ^| findstr /C:"Server Version"') do set DOCKER_RUNNING=1
if not defined DOCKER_RUNNING (
echo ❌ 检测到 Docker Engine 未运行,请先启动 Docker Desktop
pause
exit /b 1
)
REM 3) 构建镜像并启动容器(使用 compose)
echo 🏗️ 正在构建镜像...
docker compose build
if errorlevel 1 (
echo ❌ 构建失败
pause
exit /b 1
)
echo 🚀 正在启动容器...
docker compose up -d
if errorlevel 1 (
echo ❌ 启动失败
pause
exit /b 1
)
echo ✅ 启动完成,请访问: http://localhost:8080/
echo 如需停止: docker compose down
pause
@echo off
setlocal ENABLEDELAYEDEXPANSION
set PORT=8080
cd /d "%~dp0"
echo ========================================
echo Start static server (port %PORT%)
echo ========================================
REM [1/3] Free port using PowerShell only
powershell -NoProfile -ExecutionPolicy Bypass -Command "$port=%PORT%; try { $cons=Get-NetTCPConnection -LocalPort $port -ErrorAction SilentlyContinue; if ($cons) { ($cons | Select-Object -ExpandProperty OwningProcess -Unique) | ForEach-Object { try { Stop-Process -Id $_ -Force -ErrorAction SilentlyContinue } catch {} } } } catch {}"
REM Small wait
powershell -NoProfile -ExecutionPolicy Bypass -Command "Start-Sleep -Seconds 1"
REM [2/3] Check Node.js using PowerShell
powershell -NoProfile -ExecutionPolicy Bypass -Command "if (-not (Get-Command node -ErrorAction SilentlyContinue)) { Write-Host 'Node.js not found. Please install from https://nodejs.org/'; exit 1 }"
if errorlevel 1 (
pause
exit /b 1
)
REM [3/3] Start server (with SPA fallback)
echo Starting server: http://localhost:%PORT%/
powershell -NoProfile -ExecutionPolicy Bypass -Command "node serve-dist.js"
echo Server stopped.
pause
@echo off
chcp 65001 >nul
echo ========================================
echo 绩效计分系统 - 完整启动脚本
echo ========================================
echo.
REM 检查 Docker 是否安装
where docker >nul 2>&1
if errorlevel 1 (
echo ❌ 未检测到 Docker,请先安装 Docker Desktop
pause
exit /b 1
)
REM 检查 Docker 是否运行
docker info >nul 2>&1
if errorlevel 1 (
echo ❌ Docker 未运行,请启动 Docker Desktop
pause
exit /b 1
)
echo ✅ Docker 环境检查通过
echo.
echo 🚀 启动完整系统...
echo.
echo 📊 1. 启动 PostgreSQL 数据库...
docker compose up -d postgres
if errorlevel 1 (
echo ❌ 数据库启动失败
pause
exit /b 1
)
echo ⏳ 等待数据库初始化完成...
timeout /t 15 /nobreak >nul
echo 🔍 检查数据库连接状态...
docker compose exec postgres pg_isready -U performance_user -d performance_db >nul 2>&1
if errorlevel 1 (
echo ⚠️ 数据库可能还在初始化中,继续启动其他服务...
) else (
echo ✅ 数据库连接正常
)
echo.
echo 🔧 2. 启动 FastAPI 后端服务...
docker compose up -d api
if errorlevel 1 (
echo ❌ 后端服务启动失败
pause
exit /b 1
)
echo ⏳ 等待后端服务启动...
timeout /t 10 /nobreak >nul
echo.
echo 🌐 3. 启动前端应用...
docker compose up -d frontend
if errorlevel 1 (
echo ❌ 前端应用启动失败
pause
exit /b 1
)
echo.
echo ========================================
echo 🎉 系统启动完成!
echo ========================================
echo.
echo 📋 服务信息:
echo - 前端应用: http://localhost:4001
echo - 后端API: http://localhost:8000
echo - API文档: http://localhost:8000/docs
echo - 数据库: localhost:5432
echo.
echo 🔧 管理命令:
echo - 查看日志: docker compose logs -f
echo - 停止系统: docker compose down
echo - 重启系统: docker compose restart
echo.
echo 📖 默认登录信息:
echo - 用户名: admin
echo - 密码: admin123
echo.
REM 等待5秒后自动打开浏览器
echo 🌐 5秒后自动打开浏览器...
timeout /t 5 /nobreak >nul
start http://localhost:4001
pause
# 绩效计分系统启动脚本
# 用于启动前端开发服务器
Write-Host "=== 绩效计分系统启动脚本 ===" -ForegroundColor Green
# 检查Node.js是否安装
try {
$nodeVersion = node --version
Write-Host "Node.js版本: $nodeVersion" -ForegroundColor Green
} catch {
Write-Host "错误: 未找到Node.js,请先安装Node.js" -ForegroundColor Red
exit 1
}
# 检查npm是否安装
try {
$npmVersion = npm --version
Write-Host "npm版本: $npmVersion" -ForegroundColor Green
} catch {
Write-Host "错误: 未找到npm" -ForegroundColor Red
exit 1
}
# 停止可能正在运行的进程
Write-Host "停止现有进程..." -ForegroundColor Yellow
Get-Process -Name "node" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
# 等待进程完全停止
Start-Sleep -Seconds 2
# 检查端口是否被占用
$port5173 = Get-NetTCPConnection -LocalPort 5173 -ErrorAction SilentlyContinue
$port4001 = Get-NetTCPConnection -LocalPort 4001 -ErrorAction SilentlyContinue
if ($port5173) {
Write-Host "警告: 端口5173仍被占用" -ForegroundColor Yellow
}
if ($port4001) {
Write-Host "警告: 端口4001仍被占用" -ForegroundColor Yellow
}
# 安装依赖(如果需要)
if (-not (Test-Path "node_modules")) {
Write-Host "安装依赖..." -ForegroundColor Yellow
npm install
if ($LASTEXITCODE -ne 0) {
Write-Host "错误: 依赖安装失败" -ForegroundColor Red
exit 1
}
}
Write-Host "启动前端服务器..." -ForegroundColor Yellow
$frontendJob = Start-Job -ScriptBlock {
Set-Location $using:PWD
npx vite --host 0.0.0.0 --port 5173
}
# 等待前端服务器启动
Start-Sleep -Seconds 5
# 检查服务状态
Write-Host "检查服务状态..." -ForegroundColor Yellow
try {
$frontendResponse = Invoke-WebRequest -Uri "http://localhost:5173" -Method HEAD -TimeoutSec 5 -ErrorAction Stop
Write-Host "✓ 前端服务器运行正常 (http://localhost:5173)" -ForegroundColor Green
} catch {
Write-Host "✗ 前端服务器启动失败" -ForegroundColor Red
}
Write-Host ""
Write-Host "=== 系统启动完成 ===" -ForegroundColor Green
Write-Host "前端应用: http://localhost:5173" -ForegroundColor Cyan
Write-Host "状态检查: http://localhost:5173/status.html" -ForegroundColor Cyan
Write-Host "同步测试: http://localhost:5173/sync-test.html" -ForegroundColor Cyan
Write-Host ""
Write-Host "按 Ctrl+C 停止所有服务" -ForegroundColor Yellow
# 监控服务状态
try {
while ($true) {
Start-Sleep -Seconds 30
# 检查作业状态
if ($frontendJob.State -eq "Failed" -or $frontendJob.State -eq "Stopped") {
Write-Host "前端服务器已停止,重新启动..." -ForegroundColor Yellow
$frontendJob = Start-Job -ScriptBlock {
Set-Location $using:PWD
npx vite --host 0.0.0.0 --port 5173
}
}
}
} finally {
Write-Host "停止所有服务..." -ForegroundColor Yellow
Stop-Job $frontendJob -ErrorAction SilentlyContinue
Remove-Job $frontendJob -ErrorAction SilentlyContinue
Get-Process -Name "node" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
Write-Host "所有服务已停止" -ForegroundColor Green
}
...@@ -12,20 +12,7 @@ export default defineConfig({ ...@@ -12,20 +12,7 @@ export default defineConfig({
server: { server: {
port: 5173, port: 5173,
host: '0.0.0.0', host: '0.0.0.0',
hmr: true, hmr: true
proxy: {
// 代理 API 请求到后端服务
'/api': {
target: 'http://localhost:8000',
changeOrigin: true,
secure: false
},
'/health': {
target: 'http://localhost:8000',
changeOrigin: true,
secure: false
}
}
}, },
build: { build: {
rollupOptions: { rollupOptions: {
......
@echo off ++ /dev/null
@echo off
chcp 65001 >nul
:start
cls
echo ==========================================
echo 绩效计分系统 - 一键启动
echo ==========================================
echo.
echo 请选择启动模式:
echo.
echo [1] 开发环境 (推荐用于开发和测试)
echo - 启动快速,支持热重载
echo - 便于调试和开发
echo.
echo [2] 生产环境 (推荐用于正式使用)
echo - 性能优化,适合生产使用
echo - 需要构建时间较长
echo.
echo [3] 清理缓存并重启 (解决显示问题)
echo - 清理所有缓存文件
echo - 重新构建项目
echo.
echo [4] 查看使用说明
echo.
echo [5] 退出
echo.
set /p choice=请输入选择 (1-5):
if "%choice%"=="1" (
echo.
echo 🚀 启动开发环境...
call scripts\start-dev.bat
goto :start
) else if "%choice%"=="2" (
echo.
echo 🚀 启动生产环境...
call scripts\start-prod.bat
goto :start
) else if "%choice%"=="3" (
echo.
echo 🧹 清理缓存并重启...
call scripts\clear-cache.bat
goto :start
) else if "%choice%"=="4" (
echo.
echo 📖 打开使用说明...
if exist "docs\使用指南.md" (
start docs\使用指南.md
) else if exist "Node.js安装指南.md" (
start "Node.js安装指南.md"
) else (
echo ❌ 使用指南文件不存在
)
pause
goto :start
) else if "%choice%"=="5" (
echo.
echo 👋 再见!
exit /b 0
) else (
echo.
echo ❌ 无效选择,请重新输入
pause
goto :start
)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment