Compare commits
10 Commits
881b77ddde
...
9320f02cf3
| Author | SHA1 | Date | |
|---|---|---|---|
| 9320f02cf3 | |||
| 55396cf82d | |||
| d20c51c9d9 | |||
| a7b98d0752 | |||
| f91c7c1971 | |||
| 6f825f0c5f | |||
| 361435cece | |||
| a9115c3b04 | |||
| 6a99895e66 | |||
| 529e923c2b |
67
Dockerfile
67
Dockerfile
@@ -1,58 +1,57 @@
|
||||
# 多段构建 - 第一阶段:构建应用
|
||||
FROM node:16-alpine AS builder
|
||||
# pnpm-lock.yaml 为 lockfileVersion 9,需要 pnpm v9(要求 Node >= 18)
|
||||
FROM node:18-alpine AS builder
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /app
|
||||
|
||||
# 复制package文件
|
||||
COPY package*.json ./
|
||||
# 可选:使用哪种包管理器构建(默认 pnpm;也可传 npm)
|
||||
ARG PKG_MANAGER=pnpm
|
||||
# 可选:镜像加速(例如 https://registry.npmmirror.com)
|
||||
ARG NPM_REGISTRY=https://registry.npmmirror.com
|
||||
|
||||
# 设置npmmirror镜像
|
||||
RUN npm config set registry https://registry.npmmirror.com
|
||||
ENV CI=true
|
||||
|
||||
# 安装所有依赖(包括开发依赖,构建需要)
|
||||
RUN npm ci
|
||||
# 先复制依赖清单,最大化缓存命中
|
||||
COPY package.json ./
|
||||
COPY package-lock.json* pnpm-lock.yaml* yarn.lock* ./
|
||||
|
||||
RUN if [ -n "$NPM_REGISTRY" ]; then npm config set registry "$NPM_REGISTRY"; fi
|
||||
|
||||
RUN set -eux; \
|
||||
if [ "$PKG_MANAGER" = "pnpm" ]; then \
|
||||
npm i -g pnpm@9; \
|
||||
if [ -n "$NPM_REGISTRY" ]; then pnpm config set registry "$NPM_REGISTRY"; fi; \
|
||||
pnpm i --frozen-lockfile; \
|
||||
elif [ "$PKG_MANAGER" = "npm" ]; then \
|
||||
npm ci --no-audit --fund=false; \
|
||||
else \
|
||||
echo "Unsupported PKG_MANAGER=$PKG_MANAGER (use pnpm or npm)"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
# 复制源代码
|
||||
COPY . .
|
||||
|
||||
# 构建应用
|
||||
RUN npm run build:prod
|
||||
RUN set -eux; \
|
||||
if [ "$PKG_MANAGER" = "pnpm" ]; then \
|
||||
pnpm run build:prod; \
|
||||
else \
|
||||
npm run build:prod; \
|
||||
fi
|
||||
|
||||
# 多段构建 - 第二阶段: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
|
||||
|
||||
# 健康检查
|
||||
# 健康检查:使用 nginx.conf 的 /health,避免额外安装 curl
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD curl -f http://localhost/ || exit 1
|
||||
CMD wget -qO- http://127.0.0.1/health >/dev/null || exit 1
|
||||
|
||||
# 启动nginx
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
|
||||
152
IFLOW.md
152
IFLOW.md
@@ -1,152 +0,0 @@
|
||||
# 企业数字档案管理系统
|
||||
|
||||
## 项目概述
|
||||
|
||||
企业数字档案管理系统是基于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": "",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
137
build-push-acr.sh
Executable file
137
build-push-acr.sh
Executable file
@@ -0,0 +1,137 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
load_env_file() {
|
||||
local file="$1"
|
||||
[[ -f "$file" ]] || return 0
|
||||
|
||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
line="${line#${line%%[![:space:]]*}}"
|
||||
line="${line%${line##*[![:space:]]}}"
|
||||
[[ -z "$line" ]] && continue
|
||||
[[ "$line" == \#* ]] && continue
|
||||
[[ "$line" != *=* ]] && continue
|
||||
|
||||
local key="${line%%=*}"
|
||||
local val="${line#*=}"
|
||||
key="${key#${key%%[![:space:]]*}}"
|
||||
key="${key%${key##*[![:space:]]}}"
|
||||
[[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] || continue
|
||||
|
||||
if [[ "$val" =~ ^\".*\"$ ]]; then
|
||||
val="${val:1:${#val}-2}"
|
||||
elif [[ "$val" =~ ^\'.*\'$ ]]; then
|
||||
val="${val:1:${#val}-2}"
|
||||
fi
|
||||
|
||||
if [[ -z "${!key:-}" ]]; then
|
||||
export "$key=$val"
|
||||
fi
|
||||
done < "$file"
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<'EOF' >&2
|
||||
Usage:
|
||||
bash build-push-acr.sh <acr_password>
|
||||
# or:
|
||||
ACR_PASSWORD=... ACR_USERNAME=... REPO_URL=... NAMESPACE=... REPO_NAME=... IMAGE_TAG=... bash build-push-acr.sh
|
||||
|
||||
Required:
|
||||
acr_password (positional arg #1) OR env ACR_PASSWORD
|
||||
|
||||
Optional:
|
||||
ENV_FILE env file to load (default: ../deploy/.env if exists)
|
||||
ACR_USERNAME default: aipper@qq.com
|
||||
REPO_URL registry host (ACR). Default: registry.cn-hangzhou.aliyuncs.com
|
||||
NAMESPACE ACR namespace. Default: aipper
|
||||
REPO_NAME repository name. Default: digital-archive-frontend
|
||||
IMAGE_TAG default: YYYYMMDDHHMM
|
||||
PKG_MANAGER pnpm|npm (build-arg)
|
||||
NPM_REGISTRY custom npm registry (build-arg)
|
||||
DRY_RUN=1 print computed image ref and exit
|
||||
|
||||
Compatibility:
|
||||
REPO_URL -> ACR_REGISTRY
|
||||
NAMESPACE -> ACR_NAMESPACE
|
||||
EOF
|
||||
}
|
||||
|
||||
if [[ -n "${ENV_FILE:-}" ]]; then
|
||||
load_env_file "$ENV_FILE"
|
||||
else
|
||||
load_env_file "$script_dir/../deploy/.env"
|
||||
fi
|
||||
|
||||
if [[ -z "${ACR_PASSWORD:-}" && -n "${1:-}" ]]; then
|
||||
export ACR_PASSWORD="$1"
|
||||
fi
|
||||
if [[ -z "${ACR_USERNAME:-}" && -n "${2:-}" ]]; then
|
||||
export ACR_USERNAME="$2"
|
||||
fi
|
||||
|
||||
if [[ -z "${ACR_REGISTRY:-}" && -n "${REPO_URL:-}" ]]; then
|
||||
export ACR_REGISTRY="$REPO_URL"
|
||||
fi
|
||||
if [[ -z "${ACR_NAMESPACE:-}" && -n "${NAMESPACE:-}" ]]; then
|
||||
export ACR_NAMESPACE="$NAMESPACE"
|
||||
fi
|
||||
|
||||
export REPO_URL="${REPO_URL:-${ACR_REGISTRY:-registry.cn-hangzhou.aliyuncs.com}}"
|
||||
export NAMESPACE="${NAMESPACE:-${ACR_NAMESPACE:-aipper}}"
|
||||
export REPO_NAME="${REPO_NAME:-${IMAGE_REPO:-digital-archive-frontend}}"
|
||||
export IMAGE_TAG="${IMAGE_TAG:-$(date +"%Y%m%d%H%M")}"
|
||||
|
||||
export ACR_REGISTRY="${ACR_REGISTRY:-$REPO_URL}"
|
||||
export ACR_NAMESPACE="${ACR_NAMESPACE:-$NAMESPACE}"
|
||||
export IMAGE_REPO="${IMAGE_REPO:-$REPO_NAME}"
|
||||
export ACR_USERNAME="${ACR_USERNAME:-aipper@qq.com}"
|
||||
|
||||
if [[ -z "${ACR_PASSWORD:-}" ]]; then
|
||||
echo "错误:请在运行脚本时传递密码,例如:bash build-push-acr.sh your-acr-password" >&2
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
image_repo="$IMAGE_REPO"
|
||||
image_tag="$IMAGE_TAG"
|
||||
|
||||
image_ref="${ACR_REGISTRY}/${ACR_NAMESPACE}/${image_repo}:${image_tag}"
|
||||
|
||||
if [[ "${DRY_RUN:-}" == "1" ]]; then
|
||||
echo "DRY_RUN=1"
|
||||
echo "IMAGE_REF=$image_ref"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
printf '%s' "$ACR_PASSWORD" | docker login "$ACR_REGISTRY" -u "$ACR_USERNAME" --password-stdin
|
||||
|
||||
build_args=()
|
||||
if [[ -n "${PKG_MANAGER:-}" ]]; then
|
||||
build_args+=(--build-arg "PKG_MANAGER=${PKG_MANAGER}")
|
||||
fi
|
||||
if [[ -n "${NPM_REGISTRY:-}" ]]; then
|
||||
build_args+=(--build-arg "NPM_REGISTRY=${NPM_REGISTRY}")
|
||||
fi
|
||||
|
||||
if docker buildx version >/dev/null 2>&1; then
|
||||
docker buildx build \
|
||||
-f "$script_dir/Dockerfile" \
|
||||
-t "$image_ref" \
|
||||
--load \
|
||||
"${build_args[@]}" \
|
||||
"$script_dir"
|
||||
else
|
||||
docker build \
|
||||
-f "$script_dir/Dockerfile" \
|
||||
-t "$image_ref" \
|
||||
"${build_args[@]}" \
|
||||
"$script_dir"
|
||||
fi
|
||||
|
||||
docker push "$image_ref"
|
||||
|
||||
echo "Pushed: $image_ref"
|
||||
echo "WEB_IMAGE=$image_ref"
|
||||
307
build.sh
307
build.sh
@@ -1,307 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 数字档案管理系统前端 - 多阶段构建脚本
|
||||
# 支持开发环境构建和生成Docker镜像
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 配置变量
|
||||
PROJECT_NAME="digital-archive-frontend"
|
||||
IMAGE_NAME="${PROJECT_NAME}"
|
||||
IMAGE_TAG="latest"
|
||||
BUILD_TYPE="${1:-prod}" # 构建类型:dev, prod, stage
|
||||
DOCKER_REGISTRY="" # Docker镜像仓库地址
|
||||
PUSH_IMAGE="${2:-false}" # 是否推送镜像
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
log_step() {
|
||||
echo -e "${BLUE}[STEP]${NC} $1"
|
||||
}
|
||||
|
||||
# 显示帮助信息
|
||||
show_help() {
|
||||
echo "用法: $0 [构建类型] [是否推送镜像]"
|
||||
echo ""
|
||||
echo "构建类型:"
|
||||
echo " dev 开发环境构建"
|
||||
echo " prod 生产环境构建(默认)"
|
||||
echo " stage 测试环境构建"
|
||||
echo ""
|
||||
echo "是否推送镜像:"
|
||||
echo " true 构建完成后推送镜像到仓库"
|
||||
echo " false 仅构建镜像,不推送(默认)"
|
||||
echo ""
|
||||
echo "环境变量:"
|
||||
echo " DOCKER_REGISTRY 设置Docker镜像仓库地址"
|
||||
echo ""
|
||||
echo "示例:"
|
||||
echo " $0 # 生产环境构建,不推送镜像"
|
||||
echo " $0 dev # 开发环境构建"
|
||||
echo " $0 prod true # 生产环境构建并推送镜像"
|
||||
echo " DOCKER_REGISTRY=registry.example.com $0 prod true # 推送到指定仓库"
|
||||
}
|
||||
|
||||
# 检查依赖
|
||||
check_dependencies() {
|
||||
log_step "检查构建依赖..."
|
||||
|
||||
# 检查Node.js
|
||||
if ! command -v node &> /dev/null; then
|
||||
log_error "Node.js 未安装"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查npm
|
||||
if ! command -v npm &> /dev/null; then
|
||||
log_error "npm 未安装"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查Docker
|
||||
if ! command -v docker &> /dev/null; then
|
||||
log_error "Docker 未安装"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "Node.js版本: $(node --version)"
|
||||
log_info "npm版本: $(npm --version)"
|
||||
log_info "Docker版本: $(docker --version)"
|
||||
}
|
||||
|
||||
# 清理构建缓存
|
||||
clean_build_cache() {
|
||||
log_step "清理构建缓存..."
|
||||
|
||||
# 清理npm缓存
|
||||
npm cache clean --force
|
||||
|
||||
# 清理Docker构建缓存
|
||||
docker builder prune -f
|
||||
|
||||
# 删除悬空镜像
|
||||
docker image prune -f
|
||||
|
||||
log_info "构建缓存清理完成"
|
||||
}
|
||||
|
||||
# 安装依赖
|
||||
install_dependencies() {
|
||||
log_step "安装项目依赖..."
|
||||
|
||||
# 设置npm镜像源
|
||||
npm config set registry https://registry.npmmirror.com
|
||||
|
||||
# 安装依赖
|
||||
if [[ "$BUILD_TYPE" == "dev" ]]; then
|
||||
npm ci --production=false
|
||||
else
|
||||
npm ci
|
||||
fi
|
||||
|
||||
log_info "依赖安装完成"
|
||||
}
|
||||
|
||||
# 执行代码检查
|
||||
run_code_checks() {
|
||||
log_step "执行代码质量检查..."
|
||||
|
||||
# ESLint检查
|
||||
log_info "运行ESLint检查..."
|
||||
if ! npm run lint; then
|
||||
log_warn "ESLint检查发现一些问题,请检查代码质量"
|
||||
fi
|
||||
|
||||
log_info "代码检查完成"
|
||||
}
|
||||
|
||||
# 构建前端应用
|
||||
build_frontend() {
|
||||
log_step "构建前端应用..."
|
||||
|
||||
case "$BUILD_TYPE" in
|
||||
"dev")
|
||||
log_info "开发环境构建..."
|
||||
npm run build:stage
|
||||
;;
|
||||
"prod")
|
||||
log_info "生产环境构建..."
|
||||
npm run build:prod
|
||||
;;
|
||||
"stage")
|
||||
log_info "测试环境构建..."
|
||||
npm run build:stage
|
||||
;;
|
||||
*)
|
||||
log_error "未知的构建类型: $BUILD_TYPE"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# 检查构建结果
|
||||
if [ ! -d "dist" ]; then
|
||||
log_error "构建失败,dist目录未生成"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "前端应用构建完成"
|
||||
}
|
||||
|
||||
# 构建Docker镜像
|
||||
build_docker_image() {
|
||||
log_step "构建Docker镜像..."
|
||||
|
||||
local full_image_name="${IMAGE_NAME}:${IMAGE_TAG}"
|
||||
|
||||
# 如果有镜像仓库地址,添加前缀
|
||||
if [ -n "$DOCKER_REGISTRY" ]; then
|
||||
full_image_name="${DOCKER_REGISTRY}/${full_image_name}"
|
||||
fi
|
||||
|
||||
log_info "构建镜像: $full_image_name"
|
||||
|
||||
# 构建Docker镜像
|
||||
docker build \
|
||||
--tag "$full_image_name" \
|
||||
--build-arg BUILD_TYPE="$BUILD_TYPE" \
|
||||
--no-cache \
|
||||
.
|
||||
|
||||
# 验证镜像构建
|
||||
if ! docker image inspect "$full_image_name" > /dev/null 2>&1; then
|
||||
log_error "Docker镜像构建失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "Docker镜像构建完成: $full_image_name"
|
||||
|
||||
# 显示镜像信息
|
||||
docker images | grep "$IMAGE_NAME"
|
||||
}
|
||||
|
||||
# 推送Docker镜像
|
||||
push_docker_image() {
|
||||
if [[ "$PUSH_IMAGE" != "true" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
log_step "推送Docker镜像..."
|
||||
|
||||
local full_image_name="${IMAGE_NAME}:${IMAGE_TAG}"
|
||||
|
||||
# 如果有镜像仓库地址,添加前缀
|
||||
if [ -n "$DOCKER_REGISTRY" ]; then
|
||||
full_image_name="${DOCKER_REGISTRY}/${full_image_name}"
|
||||
else
|
||||
log_error "未设置DOCKER_REGISTRY环境变量,无法推送镜像"
|
||||
return
|
||||
fi
|
||||
|
||||
# 登录Docker仓库(如果需要)
|
||||
if [[ "$DOCKER_REGISTRY" != "" ]]; then
|
||||
log_info "登录Docker仓库: $DOCKER_REGISTRY"
|
||||
# 这里可以根据需要添加登录逻辑
|
||||
# docker login $DOCKER_REGISTRY
|
||||
fi
|
||||
|
||||
# 推送镜像
|
||||
log_info "推送镜像: $full_image_name"
|
||||
docker push "$full_image_name"
|
||||
|
||||
log_info "镜像推送完成"
|
||||
}
|
||||
|
||||
# 生成部署信息文件
|
||||
generate_deploy_info() {
|
||||
log_step "生成部署信息..."
|
||||
|
||||
local deploy_info="deploy-info.json"
|
||||
|
||||
cat > "$deploy_info" << EOF
|
||||
{
|
||||
"project": "$PROJECT_NAME",
|
||||
"build_type": "$BUILD_TYPE",
|
||||
"image_name": "$IMAGE_NAME",
|
||||
"image_tag": "$IMAGE_TAG",
|
||||
"docker_registry": "$DOCKER_REGISTRY",
|
||||
"build_time": "$(date -Iseconds)",
|
||||
"git_commit": "$(git rev-parse HEAD 2>/dev/null || echo 'unknown')",
|
||||
"git_branch": "$(git branch --show-current 2>/dev/null || echo 'unknown')",
|
||||
"node_version": "$(node --version)",
|
||||
"npm_version": "$(npm --version)"
|
||||
}
|
||||
EOF
|
||||
|
||||
log_info "部署信息已生成: $deploy_info"
|
||||
}
|
||||
|
||||
# 显示构建摘要
|
||||
show_summary() {
|
||||
log_step "构建摘要"
|
||||
echo ""
|
||||
echo "项目名称: $PROJECT_NAME"
|
||||
echo "构建类型: $BUILD_TYPE"
|
||||
echo "镜像名称: $IMAGE_NAME:$IMAGE_TAG"
|
||||
|
||||
if [ -n "$DOCKER_REGISTRY" ]; then
|
||||
echo "镜像仓库: $DOCKER_REGISTRY"
|
||||
fi
|
||||
|
||||
echo "构建时间: $(date)"
|
||||
echo ""
|
||||
|
||||
if [[ "$PUSH_IMAGE" == "true" && -n "$DOCKER_REGISTRY" ]]; then
|
||||
echo "镜像已推送到: $DOCKER_REGISTRY/$IMAGE_NAME:$IMAGE_TAG"
|
||||
else
|
||||
echo "镜像已构建完成,可使用以下命令运行:"
|
||||
echo " docker run -d -p 80:80 $IMAGE_NAME:$IMAGE_TAG"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 主构建流程
|
||||
main() {
|
||||
# 检查帮助参数
|
||||
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
|
||||
show_help
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log_info "开始构建数字档案管理系统前端..."
|
||||
log_info "构建类型: $BUILD_TYPE"
|
||||
|
||||
check_dependencies
|
||||
clean_build_cache
|
||||
install_dependencies
|
||||
run_code_checks
|
||||
build_frontend
|
||||
build_docker_image
|
||||
push_docker_image
|
||||
generate_deploy_info
|
||||
show_summary
|
||||
|
||||
log_info "构建完成!"
|
||||
}
|
||||
|
||||
# 执行主函数
|
||||
main "$@"
|
||||
238
deploy.sh
238
deploy.sh
@@ -1,238 +0,0 @@
|
||||
#!/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
|
||||
|
||||
# 检查Docker Compose plugin
|
||||
if ! docker compose version &> /dev/null; then
|
||||
log_error "Docker Compose plugin 未安装"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "依赖检查完成"
|
||||
log_info "Docker版本: $(docker --version)"
|
||||
log_info "Docker Compose版本: $(docker compose version)"
|
||||
}
|
||||
|
||||
# 检查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 "$@"
|
||||
@@ -10,14 +10,8 @@ services:
|
||||
networks:
|
||||
- ${NETWORK_NAME:-proxy}
|
||||
restart: ${RESTART_POLICY:-unless-stopped}
|
||||
environment:
|
||||
- NGINX_HOST=${NGINX_HOST:-localhost}
|
||||
- NGINX_PORT=80
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
# - ./ssl:/etc/nginx/ssl:ro # 如果需要SSL证书,取消注释并配置证书文件
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost/"]
|
||||
test: ["CMD", "wget", "-qO-", "http://127.0.0.1/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
@@ -35,4 +29,4 @@ services:
|
||||
networks:
|
||||
proxy:
|
||||
external: ${EXTERNAL_NETWORK:-true}
|
||||
name: ${NETWORK_NAME:-proxy}
|
||||
name: ${NETWORK_NAME:-proxy}
|
||||
|
||||
@@ -98,7 +98,7 @@ http {
|
||||
|
||||
# point-strategy 路径转发到后端服务
|
||||
location /point-strategy/ {
|
||||
proxy_pass http://digital-archive-app:9081/;
|
||||
proxy_pass http://digital-archive-app:9081;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
|
||||
@@ -79,14 +79,19 @@
|
||||
"eslint": "6.7.2",
|
||||
"eslint-plugin-vue": "6.2.2",
|
||||
"html-webpack-plugin": "3.2.0",
|
||||
"js-base64": "^3.7.8",
|
||||
"lint-staged": "8.1.5",
|
||||
"loadsh": "^0.0.4",
|
||||
"lodash": "^4.17.21",
|
||||
"mockjs": "1.0.1-beta3",
|
||||
"moment": "^2.30.1",
|
||||
"plop": "2.3.0",
|
||||
"runjs": "4.3.2",
|
||||
"sass": "1.26.2",
|
||||
"sass-loader": "8.0.2",
|
||||
"script-ext-html-webpack-plugin": "2.1.3",
|
||||
"serve-static": "1.13.2",
|
||||
"svg-baker-runtime": "^1.4.7",
|
||||
"svg-sprite-loader": "4.1.3",
|
||||
"svgo": "1.2.0",
|
||||
"vue-template-compiler": "2.6.10"
|
||||
|
||||
34
pnpm-lock.yaml
generated
34
pnpm-lock.yaml
generated
@@ -44,6 +44,9 @@ importers:
|
||||
core-js:
|
||||
specifier: ^3.6.5
|
||||
version: 3.46.0
|
||||
crypto-js:
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0
|
||||
default-passive-events:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
@@ -189,12 +192,24 @@ importers:
|
||||
html-webpack-plugin:
|
||||
specifier: 3.2.0
|
||||
version: 3.2.0(webpack@4.47.0)
|
||||
js-base64:
|
||||
specifier: ^3.7.8
|
||||
version: 3.7.8
|
||||
lint-staged:
|
||||
specifier: 8.1.5
|
||||
version: 8.1.5
|
||||
loadsh:
|
||||
specifier: ^0.0.4
|
||||
version: 0.0.4
|
||||
lodash:
|
||||
specifier: ^4.17.21
|
||||
version: 4.17.21
|
||||
mockjs:
|
||||
specifier: 1.0.1-beta3
|
||||
version: 1.0.1-beta3
|
||||
moment:
|
||||
specifier: ^2.30.1
|
||||
version: 2.30.1
|
||||
plop:
|
||||
specifier: 2.3.0
|
||||
version: 2.3.0
|
||||
@@ -213,6 +228,9 @@ importers:
|
||||
serve-static:
|
||||
specifier: 1.13.2
|
||||
version: 1.13.2
|
||||
svg-baker-runtime:
|
||||
specifier: ^1.4.7
|
||||
version: 1.4.7
|
||||
svg-sprite-loader:
|
||||
specifier: 4.1.3
|
||||
version: 4.1.3(webpack@4.47.0)
|
||||
@@ -2433,6 +2451,9 @@ packages:
|
||||
resolution: {integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==}
|
||||
engines: {node: '>= 0.10'}
|
||||
|
||||
crypto-js@4.2.0:
|
||||
resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
|
||||
|
||||
css-color-names@0.0.4:
|
||||
resolution: {integrity: sha512-zj5D7X1U2h2zsXOAM8EyUREBnnts6H+Jm+d1M2DbiQQcUtnqgQsMrdo8JW9R80YFUmIdBZeMu5wvYM7hcgWP/Q==}
|
||||
|
||||
@@ -4370,6 +4391,9 @@ packages:
|
||||
js-base64@2.6.4:
|
||||
resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==}
|
||||
|
||||
js-base64@3.7.8:
|
||||
resolution: {integrity: sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==}
|
||||
|
||||
js-beautify@1.15.4:
|
||||
resolution: {integrity: sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==}
|
||||
engines: {node: '>=14'}
|
||||
@@ -4574,6 +4598,10 @@ packages:
|
||||
resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==}
|
||||
engines: {node: '>=8.9.0'}
|
||||
|
||||
loadsh@0.0.4:
|
||||
resolution: {integrity: sha512-U+wLL8InpfRalWrr+0SuhWgGt10M4OyAk6G8xCYo2rwpiHtxZkWiFpjei0vO463ghW8LPCdhqQxXlMy2qicAEw==}
|
||||
deprecated: This is a typosquat on the popular Lodash package. This is not maintained nor is the original Lodash package.
|
||||
|
||||
locate-path@2.0.0:
|
||||
resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -10368,6 +10396,8 @@ snapshots:
|
||||
randombytes: 2.1.0
|
||||
randomfill: 1.0.4
|
||||
|
||||
crypto-js@4.2.0: {}
|
||||
|
||||
css-color-names@0.0.4: {}
|
||||
|
||||
css-declaration-sorter@4.0.1:
|
||||
@@ -12807,6 +12837,8 @@ snapshots:
|
||||
|
||||
js-base64@2.6.4: {}
|
||||
|
||||
js-base64@3.7.8: {}
|
||||
|
||||
js-beautify@1.15.4:
|
||||
dependencies:
|
||||
config-chain: 1.1.13
|
||||
@@ -13113,6 +13145,8 @@ snapshots:
|
||||
emojis-list: 3.0.0
|
||||
json5: 2.2.3
|
||||
|
||||
loadsh@0.0.4: {}
|
||||
|
||||
locate-path@2.0.0:
|
||||
dependencies:
|
||||
p-locate: 2.0.0
|
||||
|
||||
@@ -691,7 +691,7 @@ export default {
|
||||
}, 200);
|
||||
}
|
||||
} else {
|
||||
let name = row.file_name_server.replace(".jpg", ".pdf");
|
||||
let name = row.file_name_server
|
||||
this.picUrl =
|
||||
process.env.NODE_ENV === "development"
|
||||
? "http://" +
|
||||
|
||||
@@ -196,7 +196,8 @@ import {getClassTreeByClassNameTwo} from "@/api/fondclass.js";
|
||||
initGetTree(){
|
||||
this.btnloading = true;
|
||||
let data = {
|
||||
className: "档案"
|
||||
className: "档案",
|
||||
onlyMapped: true
|
||||
};
|
||||
getClassTreeByClassNameTwo(data).then(res => {
|
||||
this.btnloading = false;
|
||||
|
||||
@@ -201,7 +201,8 @@ import {getClassTreeByFondId,saveFondClass,getClassTreeByClassNameTwo} from "@/a
|
||||
initGetTree(){
|
||||
this.btnloading = true;
|
||||
let data = {
|
||||
className: "档案"
|
||||
className: "档案",
|
||||
onlyMapped: true
|
||||
};
|
||||
getClassTreeByClassNameTwo(data).then(res => {
|
||||
this.btnloading = false;
|
||||
|
||||
@@ -272,7 +272,7 @@
|
||||
"roles",
|
||||
res.body.userRole.roles[0].roleName
|
||||
);
|
||||
//localStronge.setToken(res.body.token);
|
||||
localStronge.setToken(res.body.token);
|
||||
this.$router.push({
|
||||
path: "/"
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user