diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f759c2d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,58 @@ +# 依赖目录 +node_modules +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# 构建输出 +dist +build + +# 开发环境配置 +.env.local +.env.*.local + +# IDE配置 +.vscode +.idea +*.swp +*.swo +*~ + +# 操作系统文件 +.DS_Store +Thumbs.db + +# Git +.git +.gitignore + +# Docker相关 +Dockerfile* +docker-compose* +.dockerignore + +# 测试相关 +coverage +.nyc_output +tests + +# 文档 +README*.md +IFLOW.md + +# 日志文件 +logs +*.log + +# 临时文件 +tmp +temp + +# 缓存 +.cache +.parcel-cache + +# 其他 +*.tgz +*.tar.gz \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b352fad --- /dev/null +++ b/Dockerfile @@ -0,0 +1,55 @@ +# 多段构建 - 第一阶段:构建应用 +FROM node:16-alpine AS builder + +# 设置工作目录 +WORKDIR /app + +# 复制package文件 +COPY package*.json ./ + +# 安装依赖 +RUN npm ci --only=production + +# 复制源代码 +COPY . . + +# 构建应用 +RUN npm run build:prod + +# 多段构建 - 第二阶段:Nginx部署 +FROM nginx:alpine AS final + +# 安装必要的工具 +RUN apk add --no-cache curl + +# 复制自定义nginx配置 +COPY nginx.conf /etc/nginx/nginx.conf + +# 从构建阶段复制构建产物 +COPY --from=builder /app/dist /usr/share/nginx/html + +# 复制SSL证书(如果有的话) +# COPY ssl/ /etc/nginx/ssl/ + +# 设置权限 +RUN chown -R nginx:nginx /usr/share/nginx/html && \ + chown -R nginx:nginx /var/cache/nginx && \ + chown -R nginx:nginx /var/log/nginx && \ + chown -R nginx:nginx /etc/nginx/conf.d + +# 创建nginx运行时需要的目录 +RUN touch /var/run/nginx.pid && \ + chown -R nginx:nginx /var/run/nginx.pid + +# 切换到非root用户 +USER nginx + +# 暴露端口 +EXPOSE 80 + +# 健康检查 +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD curl -f http://localhost/ || exit 1 + +# 启动nginx +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/IFLOW.md b/IFLOW.md new file mode 100644 index 0000000..d2bf499 --- /dev/null +++ b/IFLOW.md @@ -0,0 +1,152 @@ +# 企业数字档案管理系统 + +## 项目概述 + +企业数字档案管理系统是基于Vue.js前端框架开发的企业级档案管理应用,对标《GBT 39784-2021电子档案管理系统通用功能要求》。本项目是feat-ezyc分支,专门针对鄂州烟草项目定制开发。 + +### 技术栈 +- **前端框架**: Vue 2.6.10 +- **UI组件库**: Element UI 2.15.6, Ant Design Vue 1.7.8 +- **状态管理**: Vuex 3.1.0 +- **路由管理**: Vue Router 3.0.2 +- **构建工具**: Vue CLI 4.4.4 +- **HTTP客户端**: Axios 0.26.0 +- **图表库**: ECharts 4.2.1 +- **工作流**: BPMN.js 8.7.1 +- **测试框架**: Jest + +### 项目架构 +- 基于vue-element-admin模板进行开发 +- 采用模块化路由设计,主要功能模块包括: + - 档案管理 (archives-management) + - 档案利用 (archiveUtilize) + - 智能库房 (intelligent-warehouse) + - 数据管理 (dataManagement) + - 系统管理 (system-management) + - 预归档 (preFiling) + - 监督管理 (supervise-management) + - 权限管理 (authority-management) + - 管辖范围 (jurisdiction) + - 文件收集 (fileCollection) + +## 构建和运行 + +### 环境要求 +- Node.js >= 8.9 +- npm >= 3.0.0 + +### 开发环境运行 +```bash +# 安装依赖 +npm install + +# 启动开发服务器 +npm run dev +``` + +开发服务器默认端口由环境变量`VUE_APP_PROXY_PORT`决定,代理API请求到`http://127.0.0.1:9081` + +### 生产环境构建 +```bash +# 构建生产环境版本 +npm run build:prod + +# 构建测试环境版本 +npm run build:stage +``` + +### 代码质量检查 +```bash +# ESLint代码检查 +npm run lint + +# 运行单元测试 +npm run test:unit + +# CI环境检查(lint + test) +npm run test:ci +``` + +### 其他实用命令 +```bash +# 预览构建结果 +npm run preview + +# 生成新组件/页面/存储模块 +npm run new + +# 优化SVG图标 +npm run svgo +``` + +## 开发规范 + +### 代码风格 +- 使用ESLint进行代码规范检查 +- 采用Vue.js官方推荐的风格指南 +- 使用Plop模板生成器创建新组件,保持代码结构一致 + +### 目录结构规范 +``` +src/ +├── api/ # API接口定义 +├── assets/ # 静态资源 +├── components/ # 公共组件 +├── directive/ # 自定义指令 +├── filters/ # 全局过滤器 +├── icons/ # SVG图标 +├── layout/ # 布局组件 +├── router/ # 路由配置 +├── store/ # Vuex状态管理 +├── styles/ # 全局样式 +├── utils/ # 工具函数 +└── views/ # 页面组件 +``` + +### 组件开发规范 +- 使用Vue单文件组件(.vue)格式 +- 组件命名采用PascalCase +- 公共组件放置在`src/components`目录 +- 页面级组件放置在`src/views`对应功能模块目录 + +### Git提交规范 +- 使用lint-staged进行提交前代码检查 +- 通过husky配置pre-commit钩子自动执行代码格式化 + +## 项目特性 + +- 支持响应式设计,适配不同屏幕尺寸 +- 集成多种文件预览功能(PDF、图片等) +- 支持工作流审批流程 +- 实现了3D库房展示功能 +- 集成了丰富的图表展示组件 +- 支持批量操作和数据导入导出 +- 实现了细粒度的权限控制系统 + +## 部署说明 + +### 环境配置 +项目支持多环境配置,通过`.env`文件管理: +- `.env.development` - 开发环境配置 +- `.env.staging` - 测试环境配置 +- `.env.production` - 生产环境配置 + +### 静态资源处理 +- 生产环境静态资源输出到`dist/static`目录 +- 支持CDN部署,通过`publicPath`配置 +- 图片资源支持懒加载和压缩优化 + +### 代理配置 +开发环境API代理配置在`vue.config.js`中: +```javascript +proxy: { + "/api": { + target: "http://127.0.0.1:9081", + changeOrigin: true, + ws: true, + pathRewrite: { + "^/apis": "", + }, + }, +} +``` \ No newline at end of file diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..cf56ac4 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,235 @@ +#!/bin/bash + +# 部署脚本 - 数字档案管理系统前端 + +set -e + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# 配置变量 +PROJECT_NAME="digital-archive" +DEPLOY_DIR="${1:-/opt/${PROJECT_NAME}}" # 第一个参数作为部署目录,默认为/opt/digital-archive +FRONTEND_DIR="${DEPLOY_DIR}/frontend" +BACKUP_DIR="${DEPLOY_DIR}/backup" +TIMESTAMP=$(date +%Y%m%d_%H%M%S) + +# 日志函数 +log_info() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +log_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# 检查Docker和Docker Compose +check_dependencies() { + log_info "检查依赖..." + + if ! command -v docker &> /dev/null; then + log_error "Docker 未安装或不在PATH中" + exit 1 + fi + + if ! command -v docker-compose &> /dev/null; then + log_error "Docker Compose 未安装或不在PATH中" + exit 1 + fi + + log_info "依赖检查完成" +} + +# 检查proxy网络是否存在 +check_network() { + log_info "检查proxy网络..." + + if ! docker network ls | grep -q "proxy"; then + log_error "proxy网络不存在,请先创建proxy网络:" + log_error "docker network create proxy" + exit 1 + fi + + log_info "proxy网络检查完成" +} + +# 检查后端服务是否运行 +check_backend() { + log_info "检查后端服务..." + + if ! docker ps | grep -q "digital-archive-app"; then + log_warn "后端服务digital-archive-app未运行,请确保后端服务已启动" + else + log_info "后端服务运行正常" + fi +} + +# 创建部署目录 +create_directories() { + log_info "创建部署目录..." + + sudo mkdir -p "${DEPLOY_DIR}" + sudo mkdir -p "${FRONTEND_DIR}" + sudo mkdir -p "${BACKUP_DIR}" + + log_info "目录创建完成" +} + +# 备份当前版本 +backup_current() { + log_info "备份当前版本..." + + if [ -d "${FRONTEND_DIR}" ] && [ "$(ls -A ${FRONTEND_DIR})" ]; then + sudo mv "${FRONTEND_DIR}" "${BACKUP_DIR}/frontend_${TIMESTAMP}" + log_info "当前版本已备份到: ${BACKUP_DIR}/frontend_${TIMESTAMP}" + fi +} + +# 复制文件到部署目录 +copy_files() { + log_info "复制文件到部署目录..." + + # 创建新的前端目录 + sudo mkdir -p "${FRONTEND_DIR}" + + # 复制必要文件 + sudo cp docker-compose.yml "${FRONTEND_DIR}/" + sudo cp Dockerfile "${FRONTEND_DIR}/" + sudo cp nginx.conf "${FRONTEND_DIR}/" + sudo cp .dockerignore "${FRONTEND_DIR}/" + sudo cp -r src "${FRONTEND_DIR}/" + sudo cp package*.json "${FRONTEND_DIR}/" + sudo cp vue.config.js "${FRONTEND_DIR}/" + sudo cp babel.config.js "${FRONTEND_DIR}/" + sudo cp jsconfig.json "${FRONTEND_DIR}/" + + # 设置权限 + sudo chown -R $USER:$USER "${FRONTEND_DIR}" + + log_info "文件复制完成" +} + +# 构建和启动服务 +build_and_start() { + log_info "构建和启动前端服务..." + + cd "${FRONTEND_DIR}" + + # 停止现有服务 + docker-compose down || true + + # 构建镜像 + docker-compose build --no-cache + + # 启动服务 + docker-compose up -d + + log_info "前端服务启动完成" +} + +# 验证部署 +verify_deployment() { + log_info "验证部署..." + + # 等待服务启动 + sleep 10 + + # 检查容器状态 + if docker-compose ps | grep -q "Up"; then + log_info "前端服务运行正常" + else + log_error "前端服务启动失败" + docker-compose logs + exit 1 + fi + + # 健康检查 + log_info "执行健康检查..." + if curl -f http://localhost/health > /dev/null 2>&1; then + log_info "健康检查通过" + else + log_warn "健康检查失败,但服务可能仍在启动中" + fi +} + +# 清理旧镜像 +cleanup() { + log_info "清理旧镜像..." + + # 删除悬空镜像 + docker image prune -f + + # 删除旧版本镜像(保留最近3个版本) + OLD_IMAGES=$(docker images digital-archive-frontend --format "table {{.Repository}}:{{.Tag}}" | tail -n +2 | tail -n +4) + if [ ! -z "$OLD_IMAGES" ]; then + echo "$OLD_IMAGES" | xargs docker rmi -f || true + fi + + log_info "清理完成" +} + +# 显示部署信息 +show_info() { + log_info "部署完成!" + echo "" + echo "部署信息:" + echo " 部署目录: ${FRONTEND_DIR}" + echo " 访问地址: http://localhost" + echo " 容器名称: digital-archive-frontend" + echo " 备份位置: ${BACKUP_DIR}" + echo "" + echo "常用命令:" + echo " 查看日志: cd ${FRONTEND_DIR} && docker-compose logs -f" + echo " 重启服务: cd ${FRONTEND_DIR} && docker-compose restart" + echo " 停止服务: cd ${FRONTEND_DIR} && docker-compose down" + echo "" +} + +# 显示使用帮助 +show_help() { + echo "用法: $0 [部署目录]" + echo "" + echo "参数:" + echo " 部署目录 指定部署目录路径(可选,默认为/opt/digital-archive)" + echo "" + echo "示例:" + echo " $0 # 使用默认目录 /opt/digital-archive" + echo " $0 /root/xxx # 使用指定目录 /root/xxx" + echo " $0 ./deploy # 使用当前目录下的deploy子目录" + echo "" +} + +# 主函数 +main() { + # 检查帮助参数 + if [[ "$1" == "-h" || "$1" == "--help" ]]; then + show_help + exit 0 + fi + + log_info "开始部署数字档案管理系统前端..." + log_info "部署目录: ${DEPLOY_DIR}" + + check_dependencies + check_network + check_backend + create_directories + backup_current + copy_files + build_and_start + verify_deployment + cleanup + show_info + + log_info "部署完成!" +} + +# 执行主函数 +main "$@" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..09dc33a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,30 @@ +version: '3.8' + +services: + # 前端服务 + digital-archive-frontend: + build: + context: . + dockerfile: Dockerfile + container_name: digital-archive-frontend + ports: + - "80:80" + networks: + - proxy + restart: unless-stopped + environment: + - NGINX_HOST=localhost + - NGINX_PORT=80 + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + - ./ssl:/etc/nginx/ssl:ro + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + +networks: + proxy: + external: true \ No newline at end of file diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..d39d484 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,106 @@ +user nginx; +worker_processes auto; +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; + +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; + + # 性能优化 + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + client_max_body_size 100M; + + # 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; + + # 服务器配置 + server { + listen 80; + server_name localhost; + root /usr/share/nginx/html; + index index.html; + + # 安全头 + 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"; + try_files $uri =404; + } + + # API代理到后端服务 + location /api/ { + proxy_pass http://digital-archive-app:9081/; + 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_read_timeout 300s; + proxy_connect_timeout 75s; + } + + # Vue路由支持 + location / { + try_files $uri $uri/ /index.html; + add_header Cache-Control "no-cache, no-store, must-revalidate"; + add_header Pragma "no-cache"; + add_header Expires "0"; + } + + # 错误页面 + error_page 404 /index.html; + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + + # 健康检查端点 + location /health { + access_log off; + return 200 "healthy\n"; + add_header Content-Type text/plain; + } + } +} \ No newline at end of file