初始化代码

This commit is contained in:
MerCry 2026-02-08 16:22:43 +08:00
parent a197c7e09b
commit 17d374a3f0
232 changed files with 4229 additions and 24 deletions

41
.dockerignore Normal file
View File

@ -0,0 +1,41 @@
# Git
.git
.gitignore
# IDE
.idea
.vscode
*.iml
*.ipr
*.iws
# Maven
target/
!ruoyi-admin/target/*.jar
# Logs
logs/
*.log
# Temp files
*.tmp
*.bak
*.swp
*~
# OS
.DS_Store
Thumbs.db
# Docker
Dockerfile*
docker-compose*
.dockerignore
# Documentation
*.md
doc/
# Frontend build (will be built in container)
ruoyi-ui/node_modules/
ruoyi-ui/dist/

353
DOCKER_DEPLOY.md Normal file
View File

@ -0,0 +1,353 @@
# 若依项目 Docker 部署指南
## 概述
本文档说明如何使用 Docker 和 Docker Compose 部署若依项目,并通过子路径 `/ashai-wecom-test` 访问。
## 前提条件
- Docker 已安装(版本 20.10+
- Docker Compose 已安装(版本 1.29+
- 服务器 80 端口已被占用,需要使用其他端口(如 8081
## 项目结构
```
wecom-dashboards/
├── Dockerfile.backend # 后端 Dockerfile
├── docker-compose.yml # Docker Compose 编排文件
├── ruoyi-ui/
│ ├── Dockerfile # 前端 Dockerfile
│ └── nginx.conf # Nginx 配置文件
├── ruoyi-admin/
│ └── src/main/resources/
│ ├── application.yml # 后端主配置
│ └── application-prod.yml # 生产环境配置
└── sql/ # 数据库初始化脚本
```
## 配置说明
### 1. 前端配置
前端已配置为使用子路径 `/ashai-wecom-test`
- **vue.config.js**: `publicPath` 设置为 `/ashai-wecom-test`
- **.env.production**: `VUE_APP_BASE_API` 设置为 `/prod-api`
- **nginx.conf**: 配置了子路径访问和 API 代理
### 2. 后端配置
后端配置支持环境变量注入:
- **数据库连接**: 通过环境变量 `SPRING_DATASOURCE_URL`、`SPRING_DATASOURCE_USERNAME`、`SPRING_DATASOURCE_PASSWORD`
- **Redis 连接**: 通过环境变量 `SPRING_REDIS_HOST`、`SPRING_REDIS_PORT`
- **上传路径**: 使用 Docker 卷挂载 `/home/ruoyi/uploadPath`
### 3. Docker Compose 配置
包含以下服务:
- **mysql**: MySQL 5.7 数据库
- **redis**: Redis 6 缓存
- **backend**: Spring Boot 后端服务
- **frontend**: Nginx 前端服务
## 部署步骤
### 步骤 1: 准备数据库脚本
确保 `sql/` 目录下有数据库初始化脚本:
```bash
cd Ruoyi-Vue-2/wecom-dashboards
ls sql/
# 应该包含: ry_20250522.sql, quartz.sql, schema.sql 等
```
### 步骤 2: 修改配置(可选)
如果需要修改数据库密码或其他配置,编辑 `docker-compose.yml`
```yaml
services:
mysql:
environment:
MYSQL_ROOT_PASSWORD: your_password # 修改数据库密码
backend:
environment:
SPRING_DATASOURCE_PASSWORD: your_password # 同步修改
```
### 步骤 3: 构建和启动服务
```bash
# 进入项目目录
cd Ruoyi-Vue-2/wecom-dashboards
# 构建并启动所有服务
docker-compose up -d --build
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f
```
### 步骤 4: 等待服务启动
首次启动需要等待:
1. MySQL 初始化数据库(约 1-2 分钟)
2. 后端服务启动(约 30 秒)
3. 前端服务启动(约 10 秒)
查看后端日志确认启动成功:
```bash
docker-compose logs -f backend
# 看到 "Started RuoYiApplication" 表示启动成功
```
### 步骤 5: 访问应用
前端服务运行在 8081 端口,通过以下 URL 访问:
```
http://your-server-ip:8081/ashai-wecom-test
```
默认登录账号:
- 用户名: `admin`
- 密码: `admin123`
## 集成到现有 Nginx
如果你的服务器 80 端口已经有 Nginx 在运行,可以通过反向代理将请求转发到容器:
### 方案 1: Nginx 反向代理(推荐)
在你现有的 Nginx 配置中添加:
```nginx
# /etc/nginx/conf.d/ruoyi.conf 或在主配置文件中添加
server {
listen 80;
server_name your-domain.com; # 替换为你的域名
# 其他现有配置...
# 若依项目代理
location /ashai-wecom-test {
proxy_pass http://localhost:8081/ashai-wecom-test;
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 600;
proxy_read_timeout 600;
}
}
```
重启 Nginx
```bash
nginx -t # 测试配置
nginx -s reload # 重新加载配置
```
现在可以通过以下 URL 访问:
```
http://your-domain.com/ashai-wecom-test
```
### 方案 2: 修改 Docker Compose 端口映射
如果不想使用反向代理,可以修改 `docker-compose.yml` 中的端口映射:
```yaml
services:
frontend:
ports:
- "8081:80" # 改为其他未占用的端口
```
## 常用命令
```bash
# 启动服务
docker-compose up -d
# 停止服务
docker-compose down
# 重启服务
docker-compose restart
# 查看日志
docker-compose logs -f [service_name]
# 进入容器
docker-compose exec backend bash
docker-compose exec frontend sh
# 重新构建并启动
docker-compose up -d --build
# 清理所有数据(包括数据库)
docker-compose down -v
```
## 数据持久化
Docker Compose 配置了以下数据卷:
- `mysql-data`: MySQL 数据库文件
- `redis-data`: Redis 持久化数据
- `upload-data`: 文件上传目录
数据会持久化保存,即使容器重启也不会丢失。
## 备份和恢复
### 备份数据库
```bash
docker-compose exec mysql mysqldump -uroot -ppassword ruoyi > backup.sql
```
### 恢复数据库
```bash
docker-compose exec -T mysql mysql -uroot -ppassword ruoyi < backup.sql
```
### 备份上传文件
```bash
docker cp ruoyi-backend:/home/ruoyi/uploadPath ./uploadPath_backup
```
## 故障排查
### 1. 前端无法访问
检查前端容器日志:
```bash
docker-compose logs frontend
```
确认 Nginx 配置正确:
```bash
docker-compose exec frontend cat /etc/nginx/conf.d/default.conf
```
### 2. 后端无法连接数据库
检查后端日志:
```bash
docker-compose logs backend
```
确认 MySQL 已启动:
```bash
docker-compose ps mysql
```
进入 MySQL 容器检查:
```bash
docker-compose exec mysql mysql -uroot -ppassword -e "SHOW DATABASES;"
```
### 3. API 请求失败
检查 Nginx 代理配置:
```bash
docker-compose exec frontend cat /etc/nginx/conf.d/default.conf
```
确认后端服务可访问:
```bash
curl http://localhost:8080/
```
### 4. 前端静态资源 404
确认前端构建时 `publicPath` 配置正确:
```bash
# 检查 vue.config.js
cat ruoyi-ui/vue.config.js | grep publicPath
```
确认 Nginx 中的文件路径:
```bash
docker-compose exec frontend ls -la /usr/share/nginx/html/ashai-wecom-test
```
## 性能优化
### 1. 调整 JVM 参数
修改 `Dockerfile.backend`,在 `ENTRYPOINT` 中添加 JVM 参数:
```dockerfile
ENTRYPOINT ["java", "-Xms512m", "-Xmx1024m", "-jar", "app.jar"]
```
### 2. 启用 Nginx Gzip
前端 Dockerfile 已配置 gzip 压缩,确保 Nginx 配置中启用:
```nginx
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
```
### 3. 调整数据库连接池
修改 `application-prod.yml` 中的 Druid 配置。
## 安全建议
1. **修改默认密码**: 修改 MySQL root 密码和应用管理员密码
2. **配置 Redis 密码**: 在生产环境中为 Redis 设置密码
3. **使用 HTTPS**: 配置 SSL 证书,使用 HTTPS 访问
4. **限制端口访问**: 使用防火墙限制数据库和 Redis 端口的外部访问
5. **定期备份**: 设置定时任务定期备份数据库和文件
## 更新部署
当代码更新后,重新部署:
```bash
# 拉取最新代码
git pull
# 重新构建并启动
docker-compose up -d --build
# 查看日志确认启动成功
docker-compose logs -f
```
## 联系支持
如有问题,请查看:
- 若依官方文档: http://doc.ruoyi.vip
- Docker 官方文档: https://docs.docker.com
- 项目 README: ./README.md

35
Dockerfile.backend Normal file
View File

@ -0,0 +1,35 @@
# 后端 Dockerfile
FROM maven:3.8.5-openjdk-8 AS build
# 设置工作目录
WORKDIR /app
# 复制 pom.xml 和源代码
COPY pom.xml .
COPY ruoyi-admin ./ruoyi-admin
COPY ruoyi-common ./ruoyi-common
COPY ruoyi-framework ./ruoyi-framework
COPY ruoyi-generator ./ruoyi-generator
COPY ruoyi-quartz ./ruoyi-quartz
COPY ruoyi-system ./ruoyi-system
COPY excel-handle ./excel-handle
# 构建项目
RUN mvn clean package -DskipTests
# 运行阶段
FROM openjdk:8-jre-slim
WORKDIR /app
# 复制构建好的 jar 包
COPY --from=build /app/ruoyi-admin/target/*.jar app.jar
# 创建上传目录
RUN mkdir -p /home/ruoyi/uploadPath
# 暴露端口
EXPOSE 8080
# 启动应用
ENTRYPOINT ["java", "-jar", "app.jar"]

180
deploy/CONFIG-FILE.md Normal file
View File

@ -0,0 +1,180 @@
# 配置文件说明
## 外部配置文件方案
为了解决 Druid 配置无法通过环境变量覆盖的问题,我们使用外部配置文件方案。
## 文件结构
```
deploy/backend/
├── Dockerfile
├── entrypoint.sh
├── application-druid.yml # 外部配置文件
└── ruoyi-admin.jar # 你的 jar 包
```
## 配置文件说明
### application-druid.yml
这个文件会覆盖 jar 包内的 `application-druid.yml` 配置。
**重要配置项**
```yaml
spring:
datasource:
druid:
master:
url: jdbc:mysql://host.docker.internal:3316/ry-vue?...
username: root
password: jiong1114 # 修改为你的密码
redis:
host: host.docker.internal
port: 6379
password: # 如果有密码,填写这里
```
### 修改配置
如果需要修改数据库连接信息,编辑 [application-druid.yml](backend/application-druid.yml)
1. **数据库地址**: 修改 `master.url`
2. **数据库用户名**: 修改 `master.username`
3. **数据库密码**: 修改 `master.password`
4. **Redis 地址**: 修改 `redis.host`
5. **Redis 密码**: 修改 `redis.password`
## 工作原理
Spring Boot 会按以下顺序加载配置(后面的会覆盖前面的):
1. jar 包内的 `application.yml`
2. jar 包内的 `application-druid.yml`
3. jar 包外的 `application.yml`(如果存在)
4. jar 包外的 `application-druid.yml` ✅ **我们使用这个**
## 重新部署
修改配置后,需要重新构建镜像:
```bash
# 停止并删除旧容器
docker stop wecom-backend
docker rm wecom-backend
# 重新构建并启动
cd deploy
docker compose up -d --build backend
# 查看日志
docker compose logs -f backend
```
## 不需要重新构建的方案
如果你想修改配置而不重新构建镜像,可以使用卷挂载:
### 修改 docker-compose.yml
```yaml
services:
backend:
volumes:
- upload_data:/home/ruoyi/uploadPath
- ./backend/application-druid.yml:/app/application-druid.yml # 挂载配置文件
```
这样修改 `backend/application-druid.yml` 后,只需重启容器:
```bash
docker compose restart backend
```
## 验证配置
### 1. 检查配置文件是否被复制
```bash
docker exec -it wecom-backend cat /app/application-druid.yml
```
### 2. 查看启动日志
```bash
docker compose logs backend | grep -i "datasource\|redis"
```
### 3. 测试数据库连接
```bash
# 进入容器
docker exec -it wecom-backend sh
# 测试 MySQL 连接(需要安装 telnet 或 nc
nc -zv host.docker.internal 3316
# 测试 Redis 连接
nc -zv host.docker.internal 6379
```
## 常见问题
### 1. 配置文件没有生效
确认配置文件在正确的位置:
```bash
docker exec -it wecom-backend ls -la /app/
```
应该看到 `application-druid.yml` 文件。
### 2. 数据库名称不匹配
确保 MySQL 中存在对应的数据库:
```bash
docker exec -it mysql-jijin-test mysql -uroot -pjiong1114 -e "SHOW DATABASES;"
```
如果没有 `ry-vue` 数据库,创建它:
```bash
docker exec -it mysql-jijin-test mysql -uroot -pjiong1114 -e "CREATE DATABASE IF NOT EXISTS \`ry-vue\` DEFAULT CHARACTER SET utf8mb4;"
```
### 3. 仍然报配置错误
检查 jar 包的 Spring Boot 版本和配置加载方式。某些版本可能需要使用 `--spring.config.location` 参数:
修改 `entrypoint.sh`
```bash
#!/bin/sh
exec java -Dspring.profiles.active=prod \
--spring.config.location=classpath:/,file:/app/ \
-jar app.jar
```
## 完整的部署流程
```bash
# 1. 准备文件
deploy/backend/
├── ruoyi-admin.jar # 你的 jar 包
├── application-druid.yml # 已创建
├── entrypoint.sh # 已创建
└── Dockerfile # 已创建
# 2. 修改配置(如果需要)
vim deploy/backend/application-druid.yml
# 3. 构建并启动
cd deploy
docker compose up -d --build backend
# 4. 查看日志
docker compose logs -f backend
# 5. 验证启动成功
# 看到 "Started RuoYiApplication" 表示成功
```

266
deploy/CONFIG.md Normal file
View File

@ -0,0 +1,266 @@
# 使用现有 MySQL 和 Redis 容器的配置说明
## 📋 当前配置
你的现有容器:
- **MySQL**: `mysql-jijin-test` (端口 3316)
- **Redis**: `redis` (端口 6379)
## 🔧 配置步骤
### 1. 修改 docker-compose.yml
已经配置为使用 `host.docker.internal` 连接宿主机的容器。
关键配置:
```yaml
environment:
# MySQL 连接(注意端口是 3316
- SPRING_DATASOURCE_URL=jdbc:mysql://host.docker.internal:3316/ry-vue?...
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=password # 修改为你的密码
# Redis 连接
- SPRING_REDIS_HOST=host.docker.internal
- SPRING_REDIS_PORT=6379
- SPRING_REDIS_PASSWORD= # 如果有密码,填写这里
extra_hosts:
- "host.docker.internal:host-gateway" # 允许容器访问宿主机
```
### 2. 修改数据库配置
**重要**:请根据你的实际情况修改以下配置:
#### 数据库名称
默认使用 `ry-vue`,如果你的数据库名称不同,修改:
```yaml
SPRING_DATASOURCE_URL=jdbc:mysql://host.docker.internal:3316/你的数据库名?...
```
#### 数据库密码
修改为你的 MySQL root 密码:
```yaml
SPRING_DATASOURCE_PASSWORD=你的密码
```
#### Redis 密码
如果你的 Redis 设置了密码,修改:
```yaml
SPRING_REDIS_PASSWORD=你的redis密码
```
### 3. 准备数据库
在你的 MySQL 容器中创建数据库并导入数据:
```bash
# 方式 1: 进入 MySQL 容器
docker exec -it mysql-jijin-test mysql -uroot -p
# 创建数据库
CREATE DATABASE IF NOT EXISTS `ry-vue` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
# 退出
exit
# 方式 2: 导入 SQL 文件
docker exec -i mysql-jijin-test mysql -uroot -p你的密码 ry-vue < /path/to/your.sql
```
### 4. 启动服务
```bash
cd deploy
docker-compose up -d
```
## 🔍 验证连接
### 检查后端日志
```bash
docker-compose logs -f backend
```
如果看到类似以下内容,说明连接成功:
```
Started RuoYiApplication in X seconds
```
### 测试数据库连接
```bash
# 进入后端容器
docker exec -it wecom-backend sh
# 测试 MySQL 连接
wget -O- http://host.docker.internal:3316 2>&1 | grep -i mysql
# 测试 Redis 连接
ping host.docker.internal
```
## 🐛 常见问题
### 1. 无法连接到 host.docker.internal
**Windows/Mac**: `host.docker.internal` 自动可用
**Linux**: 需要手动添加,已在 docker-compose.yml 中配置:
```yaml
extra_hosts:
- "host.docker.internal:host-gateway"
```
### 2. 数据库连接被拒绝
检查 MySQL 容器是否允许远程连接:
```bash
# 进入 MySQL 容器
docker exec -it mysql-jijin-test mysql -uroot -p
# 检查用户权限
SELECT host, user FROM mysql.user WHERE user='root';
# 如果 host 只有 localhost需要授权
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '你的密码';
FLUSH PRIVILEGES;
```
### 3. 端口连接错误
确认你的 MySQL 端口是 3316
```bash
docker ps | grep mysql
```
如果端口不同,修改 docker-compose.yml 中的端口号。
### 4. Redis 连接失败
检查 Redis 是否允许远程连接:
```bash
# 查看 Redis 配置
docker exec -it redis redis-cli CONFIG GET bind
# 如果绑定了 127.0.0.1,需要修改为 0.0.0.0
docker exec -it redis redis-cli CONFIG SET bind "0.0.0.0"
```
## 🔄 替代方案:使用 Docker 网络
如果 `host.docker.internal` 不工作,可以让新容器加入现有容器的网络:
### 1. 查看现有容器的网络
```bash
docker inspect mysql-jijin-test | grep NetworkMode
docker inspect redis | grep NetworkMode
```
### 2. 修改 docker-compose.yml
假设现有容器在 `bridge` 网络:
```yaml
services:
backend:
# ... 其他配置
environment:
# 直接使用容器名连接
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql-jijin-test:3306/ry-vue?...
- SPRING_REDIS_HOST=redis
networks:
- default
networks:
default:
external: true
name: bridge # 或者你的网络名称
```
### 3. 或者创建自定义网络
```bash
# 创建网络
docker network create my-network
# 将现有容器连接到网络
docker network connect my-network mysql-jijin-test
docker network connect my-network redis
# 修改 docker-compose.yml
networks:
wecom-network:
external: true
name: my-network
```
## 📝 完整配置示例
### docker-compose.yml使用 host.docker.internal
```yaml
version: '3.8'
services:
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: wecom-backend
restart: always
ports:
- "8080:8080"
volumes:
- upload_data:/home/ruoyi/uploadPath
environment:
- SPRING_PROFILES_ACTIVE=prod
- TZ=Asia/Shanghai
- SPRING_DATASOURCE_URL=jdbc:mysql://host.docker.internal:3316/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=your_password
- SPRING_REDIS_HOST=host.docker.internal
- SPRING_REDIS_PORT=6379
- SPRING_REDIS_PASSWORD=
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- wecom-network
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: wecom-frontend
restart: always
ports:
- "8081:80"
depends_on:
- backend
networks:
- wecom-network
volumes:
upload_data:
driver: local
networks:
wecom-network:
driver: bridge
```
## 🎯 快速检查清单
- [ ] 修改了 MySQL 密码配置
- [ ] 修改了数据库名称(如果不是 ry-vue
- [ ] 修改了 Redis 密码(如果有)
- [ ] 确认 MySQL 端口是 3316
- [ ] 确认 Redis 端口是 6379
- [ ] 在 MySQL 中创建了数据库
- [ ] 导入了数据库初始化脚本
- [ ] MySQL 允许远程连接
- [ ] Redis 允许远程连接
完成以上检查后,运行 `docker-compose up -d` 即可启动服务。

View File

@ -0,0 +1,85 @@
# Docker 镜像问题说明
## 问题原因
`openjdk:8-jre-alpine` 镜像已被弃用,无法从 Docker Hub 拉取。
## 解决方案
已将 Dockerfile 中的基础镜像更改为 `eclipse-temurin:8-jre-alpine`
### Eclipse Temurin 是什么?
- Eclipse Temurin 是 OpenJDK 的官方继任者
- 由 Eclipse Adoptium 项目维护
- 完全兼容 OpenJDK
- 持续更新和维护
## 其他可用的 Java 8 镜像
如果 `eclipse-temurin:8-jre-alpine` 也无法拉取,可以尝试以下替代方案:
### 1. Amazon Corretto推荐
```dockerfile
FROM amazoncorretto:8-alpine-jre
```
### 2. Eclipse Temurin非 Alpine
```dockerfile
FROM eclipse-temurin:8-jre
```
注意:体积较大(约 200MB vs 85MB
### 3. Azul Zulu
```dockerfile
FROM azul/zulu-openjdk-alpine:8-jre
```
### 4. 使用国内镜像加速
如果网络问题导致拉取失败,可以配置 Docker 镜像加速器:
#### 阿里云镜像加速
```json
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://registry.docker-cn.com",
"https://docker.mirrors.ustc.edu.cn"
]
}
```
配置位置:
- **Windows**: Docker Desktop -> Settings -> Docker Engine
- **Linux**: `/etc/docker/daemon.json`
配置后重启 Docker
```bash
# Linux
sudo systemctl restart docker
# Windows
重启 Docker Desktop
```
## 当前配置
已修改 [backend/Dockerfile](backend/Dockerfile) 使用:
```dockerfile
FROM eclipse-temurin:8-jre-alpine
```
现在可以重新尝试构建:
```bash
docker compose up -d
```
## 如果仍然失败
1. 检查网络连接
2. 配置镜像加速器
3. 或者使用非 Alpine 版本(体积更大但更稳定):
```dockerfile
FROM eclipse-temurin:8-jre
```

204
deploy/NO-COMPOSE.md Normal file
View File

@ -0,0 +1,204 @@
# 不使用 docker-compose 的部署方案
如果你没有安装 docker-compose可以使用以下两种方式
## 方式 1: 使用 Docker Compose V2推荐
Docker Desktop 和新版 Docker 已经内置了 Compose V2命令是 `docker compose`(注意是空格,不是连字符)。
### 测试是否可用
```bash
docker compose version
```
如果可用,只需将所有 `docker-compose` 命令改为 `docker compose`
```bash
# 启动服务
docker compose up -d
# 查看日志
docker compose logs -f
# 停止服务
docker compose down
```
## 方式 2: 使用纯 Docker 命令
如果 `docker compose` 也不可用,可以使用纯 Docker 命令手动启动容器。
### 1. 创建网络
```bash
docker network create wecom-network
```
### 2. 构建镜像
#### 构建后端镜像
```bash
cd deploy/backend
docker build -t wecom-backend:latest .
cd ../..
```
#### 构建前端镜像
```bash
cd deploy/frontend
docker build -t wecom-frontend:latest .
cd ../..
```
### 3. 启动容器
#### 启动后端容器
```bash
docker run -d \
--name wecom-backend \
--restart always \
--network wecom-network \
-p 8080:8080 \
-v wecom-upload-data:/home/ruoyi/uploadPath \
-e SPRING_PROFILES_ACTIVE=prod \
-e TZ=Asia/Shanghai \
-e SPRING_DATASOURCE_URL="jdbc:mysql://host.docker.internal:3316/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8" \
-e SPRING_DATASOURCE_USERNAME=root \
-e SPRING_DATASOURCE_PASSWORD=你的MySQL密码 \
-e SPRING_REDIS_HOST=host.docker.internal \
-e SPRING_REDIS_PORT=6379 \
-e SPRING_REDIS_PASSWORD= \
--add-host host.docker.internal:host-gateway \
wecom-backend:latest
```
#### 启动前端容器
```bash
docker run -d \
--name wecom-frontend \
--restart always \
--network wecom-network \
-p 8081:80 \
wecom-frontend:latest
```
### 4. 常用管理命令
```bash
# 查看运行中的容器
docker ps
# 查看所有容器(包括停止的)
docker ps -a
# 查看后端日志
docker logs -f wecom-backend
# 查看前端日志
docker logs -f wecom-frontend
# 停止容器
docker stop wecom-backend wecom-frontend
# 启动容器
docker start wecom-backend wecom-frontend
# 重启容器
docker restart wecom-backend wecom-frontend
# 删除容器
docker rm -f wecom-backend wecom-frontend
# 删除网络
docker network rm wecom-network
# 删除数据卷
docker volume rm wecom-upload-data
```
### 5. 更新部署
#### 更新后端
```bash
# 停止并删除旧容器
docker stop wecom-backend
docker rm wecom-backend
# 重新构建镜像
cd deploy/backend
docker build -t wecom-backend:latest .
cd ../..
# 启动新容器(使用上面的 docker run 命令)
docker run -d \
--name wecom-backend \
--restart always \
--network wecom-network \
-p 8080:8080 \
-v wecom-upload-data:/home/ruoyi/uploadPath \
-e SPRING_PROFILES_ACTIVE=prod \
-e TZ=Asia/Shanghai \
-e SPRING_DATASOURCE_URL="jdbc:mysql://host.docker.internal:3316/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8" \
-e SPRING_DATASOURCE_USERNAME=root \
-e SPRING_DATASOURCE_PASSWORD=你的MySQL密码 \
-e SPRING_REDIS_HOST=host.docker.internal \
-e SPRING_REDIS_PORT=6379 \
-e SPRING_REDIS_PASSWORD= \
--add-host host.docker.internal:host-gateway \
wecom-backend:latest
```
#### 更新前端
```bash
# 停止并删除旧容器
docker stop wecom-frontend
docker rm wecom-frontend
# 重新构建镜像
cd deploy/frontend
docker build -t wecom-frontend:latest .
cd ../..
# 启动新容器
docker run -d \
--name wecom-frontend \
--restart always \
--network wecom-network \
-p 8081:80 \
wecom-frontend:latest
```
## 方式 3: 使用部署脚本(最简单)
我可以为你创建一个 Shell 脚本,自动执行所有 Docker 命令。
### Windows (PowerShell)
创建 `deploy.ps1` 脚本
### Linux/Mac (Bash)
创建 `deploy.sh` 脚本
需要我创建这些脚本吗?
## 🔍 检查 Docker Compose 可用性
```bash
# 检查 docker-compose旧版
docker-compose --version
# 检查 docker compose新版
docker compose version
# 检查 Docker 版本
docker --version
```
## 📝 推荐方案
1. **最推荐**: 使用 `docker compose`Docker Compose V2
2. **次推荐**: 使用部署脚本(我可以帮你创建)
3. **备选**: 手动执行 docker 命令
你想使用哪种方式?我可以帮你:
- 测试 `docker compose` 是否可用
- 创建自动化部署脚本
- 提供完整的手动命令清单

181
deploy/PORT-CONFIG.md Normal file
View File

@ -0,0 +1,181 @@
# 端口配置说明
## 当前端口配置
### 后端服务
- **容器内端口**: 8888
- **宿主机端口**: 8888
- **访问地址**: `http://your-server-ip:8888`
### 前端服务
- **容器内端口**: 80
- **宿主机端口**: 8889
- **访问地址**: `http://your-server-ip:8889/ashai-wecom-test`
## 配置文件位置
### 1. 后端端口配置
**文件**: [backend/application-druid.yml](backend/application-druid.yml)
```yaml
server:
port: 8888
```
### 2. Docker 端口映射
**文件**: [docker-compose.yml](docker-compose.yml)
```yaml
services:
backend:
ports:
- "8888:8888" # 宿主机:容器
frontend:
ports:
- "8889:80" # 宿主机:容器
```
### 3. Dockerfile 暴露端口
**文件**: [backend/Dockerfile](backend/Dockerfile)
```dockerfile
EXPOSE 8888
```
## 修改端口
如果需要修改端口,需要同时修改以上三个地方:
### 示例:改为 9000 端口
1. **修改 application-druid.yml**:
```yaml
server:
port: 9000
```
2. **修改 docker-compose.yml**:
```yaml
ports:
- "9000:9000"
```
3. **修改 Dockerfile**:
```dockerfile
EXPOSE 9000
```
4. **修改 healthcheck**:
```yaml
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:9000/"]
```
## 重新部署
修改端口后需要重新构建:
```bash
# 停止并删除旧容器
docker stop wecom-backend wecom-frontend
docker rm wecom-backend wecom-frontend
# 重新构建并启动
cd deploy
docker compose up -d --build
# 查看日志
docker compose logs -f
```
## 验证端口
### 检查容器端口
```bash
docker ps
```
应该看到类似:
```
CONTAINER ID IMAGE PORTS
xxx deploy-backend 0.0.0.0:8888->8888/tcp
xxx deploy-frontend 0.0.0.0:8889->80/tcp
```
### 测试后端访问
```bash
curl http://localhost:8888
```
### 测试前端访问
```bash
curl http://localhost:8889/ashai-wecom-test
```
## 常见问题
### 1. 端口被占用
如果启动时报错端口被占用:
```bash
# 查看端口占用
netstat -tulpn | grep 8888
# 或使用 lsofMac/Linux
lsof -i :8888
# Windows
netstat -ano | findstr 8888
```
解决方案:
- 停止占用端口的程序
- 或修改为其他未占用的端口
### 2. 容器内外端口不一致
如果宿主机 8080 被占用,可以只修改宿主机端口:
```yaml
ports:
- "9000:8888" # 宿主机 9000 映射到容器 8888
```
这样:
- 容器内应用仍运行在 8888
- 外部通过 9000 访问
### 3. 前端无法连接后端
确保前端 Nginx 配置中的后端地址正确:
**文件**: [frontend/nginx.conf](frontend/nginx.conf)
```nginx
location /ashai-wecom-test/prod-api/ {
proxy_pass http://backend:8888/; # 使用容器名和容器内端口
...
}
```
注意:
- 容器间通信使用**容器名**和**容器内端口**
- 不是宿主机端口
## 完整的访问流程
```
用户浏览器
http://server-ip:8889/ashai-wecom-test
宿主机 8889 端口
前端容器 80 端口 (Nginx)
API 请求: /ashai-wecom-test/prod-api/*
Nginx 代理到: http://backend:8888/
后端容器 8888 端口 (Spring Boot)
返回数据
```

293
deploy/README.md Normal file
View File

@ -0,0 +1,293 @@
# 简化版 Docker 部署指南
这是一个简化的 Docker 部署方案,直接使用已经打包好的 jar 包和 dist 文件,无需在容器内重新构建。
## 📁 目录结构
```
deploy/
├── docker-compose.yml # Docker Compose 配置文件
├── backend/ # 后端部署目录
│ ├── Dockerfile # 后端 Dockerfile
│ └── ruoyi-admin.jar # 【需要放置】后端 jar 包
├── frontend/ # 前端部署目录
│ ├── Dockerfile # 前端 Dockerfile
│ ├── nginx.conf # Nginx 配置文件
│ └── dist/ # 【需要放置】前端打包文件
└── sql/ # 【可选】数据库初始化脚本
└── ry_20xx.sql
```
## 🚀 快速部署步骤
### 1. 准备文件
将以下文件上传到服务器的 `deploy` 目录:
```bash
# 1. 将后端 jar 包放到 backend 目录
deploy/backend/ruoyi-admin.jar
# 2. 将前端 dist 文件夹放到 frontend 目录
deploy/frontend/dist/
# 3. (可选)将数据库初始化脚本放到 sql 目录
deploy/sql/ry_20xx.sql
```
### 2. 修改配置
编辑 `docker-compose.yml`,根据需要修改以下配置:
```yaml
# MySQL 配置
environment:
MYSQL_ROOT_PASSWORD: password # 修改为你的密码
MYSQL_DATABASE: ry-vue # 数据库名称
# 端口配置(如果端口冲突,可以修改)
ports:
- "3306:3306" # MySQL
- "6379:6379" # Redis
- "8080:8080" # 后端
- "8081:80" # 前端
```
### 3. 启动服务
```bash
# 进入 deploy 目录
cd deploy
# 启动所有服务
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f
```
### 4. 访问应用
- **前端地址**: `http://your-server-ip:8081/ashai-wecom-test`
- **后端 API**: `http://your-server-ip:8080`
- **默认账号**: admin / admin123
## 📝 常用命令
```bash
# 启动所有服务
docker-compose up -d
# 停止所有服务
docker-compose down
# 重启某个服务
docker-compose restart backend
docker-compose restart frontend
# 查看服务日志
docker-compose logs -f backend
docker-compose logs -f frontend
# 查看服务状态
docker-compose ps
# 进入容器
docker exec -it wecom-backend sh
docker exec -it wecom-frontend sh
# 重新构建并启动
docker-compose up -d --build
# 停止并删除所有容器、网络、数据卷
docker-compose down -v
```
## 🔄 更新部署
### 更新后端
```bash
# 1. 停止后端服务
docker-compose stop backend
# 2. 替换 jar 包
cp new-ruoyi-admin.jar backend/ruoyi-admin.jar
# 3. 重新构建并启动
docker-compose up -d --build backend
```
### 更新前端
```bash
# 1. 停止前端服务
docker-compose stop frontend
# 2. 替换 dist 文件
rm -rf frontend/dist
cp -r new-dist frontend/dist
# 3. 重新构建并启动
docker-compose up -d --build frontend
```
## 🔧 配置说明
### 后端配置
后端使用 `--spring.profiles.active=prod` 启动,确保你的 jar 包中包含正确的生产环境配置:
- 数据库连接:`jdbc:mysql://mysql:3306/ry-vue`
- Redis 连接:`redis://redis:6379`
如果需要修改配置,可以通过环境变量或重新打包 jar。
### 前端配置
前端通过 Nginx 提供服务,配置文件在 [frontend/nginx.conf](frontend/nginx.conf)
- 访问路径:`/ashai-wecom-test`
- API 代理:`/ashai-wecom-test/prod-api/` → `http://backend:8080/`
### 数据库初始化
首次启动时,如果 `sql` 目录中有 `.sql` 文件MySQL 会自动执行这些脚本。
如果需要手动导入:
```bash
# 复制 SQL 文件到容器
docker cp ry_20xx.sql wecom-mysql:/tmp/
# 进入 MySQL 容器
docker exec -it wecom-mysql bash
# 导入数据库
mysql -uroot -ppassword ry-vue < /tmp/ry_20xx.sql
```
## 🌐 集成到现有 Nginx80 端口)
如果服务器 80 端口已有 Nginx可以添加反向代理配置
```nginx
# 在你的 Nginx 配置中添加
location /ashai-wecom-test {
proxy_pass http://localhost:8081/ashai-wecom-test;
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;
}
```
然后重启 Nginx
```bash
nginx -t
nginx -s reload
```
## 🐛 故障排查
### 1. 后端无法连接数据库
```bash
# 检查 MySQL 是否启动
docker-compose ps mysql
# 查看 MySQL 日志
docker-compose logs mysql
# 检查网络连接
docker exec -it wecom-backend ping mysql
```
### 2. 前端无法访问后端 API
```bash
# 检查后端是否启动
docker-compose ps backend
# 查看后端日志
docker-compose logs backend
# 测试后端接口
curl http://localhost:8080/
```
### 3. 前端页面 404
```bash
# 检查 dist 文件是否正确放置
docker exec -it wecom-frontend ls -la /usr/share/nginx/html/ashai-wecom-test
# 查看 Nginx 日志
docker-compose logs frontend
# 检查 Nginx 配置
docker exec -it wecom-frontend cat /etc/nginx/conf.d/default.conf
```
### 4. 端口被占用
```bash
# 查看端口占用
netstat -tulpn | grep 8080
netstat -tulpn | grep 8081
# 修改 docker-compose.yml 中的端口映射
ports:
- "8082:8080" # 改为其他端口
```
### 5. 容器启动失败
```bash
# 查看详细日志
docker-compose logs -f
# 检查容器状态
docker-compose ps
# 重新构建
docker-compose down
docker-compose up -d --build
```
## 📊 数据持久化
所有数据都通过 Docker 卷持久化:
- `mysql_data`: MySQL 数据
- `redis_data`: Redis 数据
- `upload_data`: 文件上传目录
即使删除容器,数据也不会丢失。如需完全清理:
```bash
docker-compose down -v
```
## 🔒 安全建议
1. **修改默认密码**:修改 MySQL root 密码和应用管理员密码
2. **限制端口访问**:使用防火墙限制数据库端口的外部访问
3. **使用 HTTPS**:在生产环境配置 SSL 证书
4. **定期备份**:定期备份数据库和上传文件
## 📈 性能优化
1. **调整 JVM 参数**:在 [backend/Dockerfile](backend/Dockerfile) 中添加 JVM 参数
2. **配置 Nginx 缓存**:已在 [frontend/nginx.conf](frontend/nginx.conf) 中配置
3. **数据库优化**:根据实际情况调整 MySQL 配置
## 💡 提示
- 首次启动可能需要等待 1-2 分钟,等待数据库初始化
- 确保服务器有足够的内存(建议至少 2GB
- 生产环境建议使用外部数据库,而不是容器内的数据库

184
deploy/TROUBLESHOOTING.md Normal file
View File

@ -0,0 +1,184 @@
# 后端启动配置问题修复
## 问题描述
后端启动时报错:
```
Could not resolve placeholder 'spring.datasource.druid.initialSize'
```
## 原因分析
若依项目使用了 Druid 数据源,配置在 `application-druid.yml` 中。环境变量无法直接覆盖 Druid 的嵌套配置属性。
## 解决方案
### 1. 创建启动脚本
已创建 [entrypoint.sh](backend/entrypoint.sh),使用 Java 系统属性覆盖配置:
```bash
#!/bin/sh
exec java \
-Dspring.profiles.active=prod \
-Dspring.datasource.druid.master.url="${SPRING_DATASOURCE_URL}" \
-Dspring.datasource.druid.master.username="${SPRING_DATASOURCE_USERNAME}" \
-Dspring.datasource.druid.master.password="${SPRING_DATASOURCE_PASSWORD}" \
-Dspring.redis.host="${SPRING_REDIS_HOST}" \
-Dspring.redis.port="${SPRING_REDIS_PORT}" \
-jar app.jar
```
### 2. 修改 Dockerfile
已修改 [backend/Dockerfile](backend/Dockerfile),使用启动脚本:
```dockerfile
# 复制启动脚本
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
# 启动应用
ENTRYPOINT ["/entrypoint.sh"]
```
## 重新部署
### 1. 停止并删除旧容器
```bash
docker stop wecom-backend
docker rm wecom-backend
```
### 2. 重新构建并启动
```bash
cd deploy
docker compose up -d --build backend
```
### 3. 查看日志
```bash
docker compose logs -f backend
```
## 验证启动成功
查看日志中是否有以下内容:
```
Started RuoYiApplication in X seconds
```
## 其他可能的问题
### 1. 数据库连接失败
检查 MySQL 容器是否允许远程连接:
```bash
docker exec -it mysql-jijin-test mysql -uroot -p
# 授权远程访问
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'jiong1114';
FLUSH PRIVILEGES;
```
### 2. 数据库不存在
创建数据库:
```bash
docker exec -it mysql-jijin-test mysql -uroot -pjiong1114
CREATE DATABASE IF NOT EXISTS `ry-vue` DEFAULT CHARACTER SET utf8mb4;
```
### 3. Redis 连接失败
检查 Redis 是否允许远程连接:
```bash
docker exec -it redis redis-cli CONFIG GET bind
# 如果绑定了 127.0.0.1,需要修改
docker exec -it redis redis-cli CONFIG SET bind "0.0.0.0"
```
### 4. 端口配置不匹配
注意 docker-compose.yml 中配置的是 8888 端口:
```yaml
ports:
- "8888:8888" # 宿主机:容器
```
但 Dockerfile 暴露的是 8080 端口。需要修改其中一个保持一致。
#### 方案 A: 修改 docker-compose.yml推荐
```yaml
ports:
- "8888:8080" # 宿主机 8888 映射到容器 8080
```
#### 方案 B: 修改应用端口
在 docker-compose.yml 中添加环境变量:
```yaml
environment:
- SERVER_PORT=8888
```
## 完整的 docker-compose.yml 配置
```yaml
version: '3.8'
services:
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: wecom-backend
restart: always
ports:
- "8888:8080" # 宿主机 8888 映射到容器 8080
volumes:
- upload_data:/home/ruoyi/uploadPath
environment:
- SPRING_PROFILES_ACTIVE=prod
- TZ=Asia/Shanghai
- SPRING_DATASOURCE_URL=jdbc:mysql://host.docker.internal:3316/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=jiong1114
- SPRING_REDIS_HOST=host.docker.internal
- SPRING_REDIS_PORT=6379
- SPRING_REDIS_PASSWORD=
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- wecom-network
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/"]
interval: 30s
timeout: 10s
retries: 3
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: wecom-frontend
restart: always
ports:
- "8889:80"
depends_on:
- backend
networks:
- wecom-network
volumes:
upload_data:
driver: local
networks:
wecom-network:
driver: bridge
```
注意 healthcheck 中使用的是容器内部端口 8080。

30
deploy/backend/Dockerfile Normal file
View File

@ -0,0 +1,30 @@
# 简化版后端 Dockerfile - 直接使用已打包的 jar 文件
# 使用 Eclipse TemurinOpenJDK 的官方替代品)
FROM eclipse-temurin:8-jre-alpine
# 设置工作目录
WORKDIR /app
# 复制 jar 包到容器
# 使用时将 jar 包放在与 Dockerfile 同级目录
COPY *.jar app.jar
# 复制外部配置文件(会覆盖 jar 包内的配置)
COPY application-druid.yml /app/application-druid.yml
# 复制启动脚本
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
# 创建上传文件目录
RUN mkdir -p /home/ruoyi/uploadPath
# 暴露端口
EXPOSE 8888
# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 启动应用
ENTRYPOINT ["/entrypoint.sh"]

View File

@ -0,0 +1,79 @@
# 数据源配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
# 主库数据源
master:
url: jdbc:mysql://host.docker.internal:3316/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: jiong1114
# 从库数据源
slave:
# 从数据源开关/默认关闭
enabled: false
url:
username:
password:
# 初始连接数
initialSize: 5
# 最小连接池数量
minIdle: 10
# 最大连接池数量
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置连接超时时间
connectTimeout: 30000
# 配置网络超时时间
socketTimeout: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow:
url-pattern: /druid/*
# 控制台管理用户名和密码
login-username: ruoyi
login-password: 123456
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
# Redis 配置
redis:
host: host.docker.internal
port: 6379
password:
database: 0
timeout: 10s
lettuce:
pool:
min-idle: 0
max-idle: 8
max-active: 8
max-wait: -1ms
# 服务器端口配置
server:
port: 8888

View File

@ -0,0 +1,5 @@
#!/bin/sh
# 启动 Spring Boot 应用
# 外部配置文件 application-druid.yml 会自动被加载并覆盖 jar 包内的配置
exec java -Dspring.profiles.active=prod -jar app.jar

58
deploy/docker-compose.yml Normal file
View File

@ -0,0 +1,58 @@
version: '3.8'
services:
# 后端服务
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: wecom-backend
restart: always
ports:
- "8888:8888"
volumes:
- upload_data:/home/ruoyi/uploadPath
environment:
- SPRING_PROFILES_ACTIVE=prod
- TZ=Asia/Shanghai
# 数据库连接配置(连接到宿主机的 MySQL 容器)
- SPRING_DATASOURCE_URL=jdbc:mysql://host.docker.internal:3316/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=jiong1114
# Redis 连接配置(连接到宿主机的 Redis 容器)
- SPRING_REDIS_HOST=host.docker.internal
- SPRING_REDIS_PORT=6379
- SPRING_REDIS_PASSWORD=
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- wecom-network
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8888/"]
interval: 30s
timeout: 10s
retries: 3
# 前端服务
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: wecom-frontend
restart: always
ports:
- "8889:80"
depends_on:
- backend
networks:
- wecom-network
# 数据卷
volumes:
upload_data:
driver: local
# 网络
networks:
wecom-network:
driver: bridge

View File

@ -0,0 +1,15 @@
# 简化版前端 Dockerfile - 直接使用已打包的 dist 文件
FROM nginx:alpine
# 复制 dist 文件到 Nginx 的子路径目录
# 使用时将 dist 目录放在与 Dockerfile 同级目录
COPY dist /usr/share/nginx/html/ashai-wecom-test
# 复制 Nginx 配置文件
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 暴露端口
EXPOSE 80
# 启动 Nginx
CMD ["nginx", "-g", "daemon off;"]

View File

@ -0,0 +1,83 @@
server {
listen 80;
server_name localhost;
# Gzip 压缩配置
gzip on;
gzip_min_length 1k;
gzip_comp_level 6;
gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
# API 代理到后端(不带项目路径前缀)
location /prod-api/ {
proxy_pass http://backend:8888/;
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 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
# 支持 WebSocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# 前端静态文件路径(带项目路径前缀)
location /ashai-wecom-test {
alias /usr/share/nginx/html/ashai-wecom-test;
try_files $uri $uri/ /ashai-wecom-test/index.html;
index index.html;
# 静态资源缓存配置
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 7d;
add_header Cache-Control "public, immutable";
}
}
# API 代理到后端(带项目路径前缀)
location /ashai-wecom-test/prod-api/ {
proxy_pass http://backend:8888/;
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 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
# 支持 WebSocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# 根路径重定向到项目路径
location = / {
return 301 /ashai-wecom-test/;
}
# 其他所有路径都尝试从项目目录加载(支持 Vue Router History 模式)
location / {
root /usr/share/nginx/html/ashai-wecom-test;
try_files $uri $uri/ /index.html;
index index.html;
# 静态资源缓存配置
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 7d;
add_header Cache-Control "public, immutable";
}
}
# 错误页面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

79
docker-compose.yml Normal file
View File

@ -0,0 +1,79 @@
version: '3.8'
services:
# MySQL 数据库
mysql:
image: mysql:5.7
container_name: ruoyi-mysql
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: ruoyi
TZ: Asia/Shanghai
ports:
- "3306:3306"
volumes:
- mysql-data:/var/lib/mysql
- ./sql:/docker-entrypoint-initdb.d
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
networks:
- ruoyi-network
restart: unless-stopped
# Redis 缓存
redis:
image: redis:6-alpine
container_name: ruoyi-redis
ports:
- "6379:6379"
volumes:
- redis-data:/data
networks:
- ruoyi-network
restart: unless-stopped
# 后端服务
backend:
build:
context: .
dockerfile: Dockerfile.backend
container_name: ruoyi-backend
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/ruoyi?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: password
SPRING_REDIS_HOST: redis
SPRING_REDIS_PORT: 6379
SERVER_SERVLET_CONTEXT_PATH: /
ports:
- "8080:8080"
volumes:
- upload-data:/home/ruoyi/uploadPath
depends_on:
- mysql
- redis
networks:
- ruoyi-network
restart: unless-stopped
# 前端 Nginx
frontend:
build:
context: ./ruoyi-ui
dockerfile: Dockerfile
container_name: ruoyi-frontend
ports:
- "8081:80"
depends_on:
- backend
networks:
- ruoyi-network
restart: unless-stopped
networks:
ruoyi-network:
driver: bridge
volumes:
mysql-data:
redis-data:
upload-data:

View File

@ -3,6 +3,7 @@ package com.ruoyi.excel.wecom.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.Excel;
import java.io.Serializable;
import java.util.Date;
@ -16,55 +17,68 @@ public class CustomerStatisticsDataVO implements Serializable {
private static final long serialVersionUID = 1L;
@ExcelProperty("统计日期")
@Excel(name ="统计日期")
@DateTimeFormat("yyyy-MM-dd")
@ColumnWidth(20)
private Date curDate;
@ExcelProperty("重要指标")
@Excel(name ="重要指标")
@ColumnWidth(30)
private String indicatorName;
@ExcelProperty("N组")
@Excel(name ="N组(投放)")
@ColumnWidth(15)
private String nGroup;
@ExcelProperty("O组(公司孵化)")
@Excel(name ="O组(公司孵化)")
@ColumnWidth(20)
private String oGroup;
@ExcelProperty("P组(商务)")
@Excel(name ="P组(商务)")
@ColumnWidth(15)
private String pGroup;
@ExcelProperty("W组(A1组)")
@Excel(name ="W组(A1组)")
@ColumnWidth(15)
private String wGroup;
@ExcelProperty("X组(B1组)")
@Excel(name ="X组(B1组)")
@ColumnWidth(15)
private String xGroup;
@ExcelProperty("Y组(C1组)")
@Excel(name ="Y组(C1组)")
@ColumnWidth(15)
private String yGroup;
@ExcelProperty("Z组(D1组)")
@Excel(name ="Z组(D1组)")
@ColumnWidth(15)
private String zGroup;
@ExcelProperty("AA组(E1组)")
@Excel(name ="AA组(E1组)")
@ColumnWidth(15)
private String aaGroup;
@ExcelProperty("AC组(自然流)")
@Excel(name ="AC组(自然流)")
@ColumnWidth(20)
private String acGroup;
@ExcelProperty("AD组(F1组)")
@Excel(name ="AD组(F1组)")
@ColumnWidth(15)
private String adGroup;
@ExcelProperty("AE组(G1组)")
@Excel(name ="AE组(G1组)")
@ColumnWidth(15)
private String aeGroup;

View File

@ -3,6 +3,7 @@ package com.ruoyi.excel.wecom.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.common.annotation.Excel;
import lombok.Data;
import java.io.Serializable;
@ -18,28 +19,34 @@ public class DepartmentStatisticsDataVO implements Serializable {
private static final long serialVersionUID = 1L;
@ExcelProperty("统计日期")
@Excel(name ="统计日期")
@DateTimeFormat("yyyy-MM-dd")
@ColumnWidth(15)
private Date statDate;
@ExcelProperty("部门路径")
@Excel(name ="部门路径")
@ColumnWidth(40)
private String departmentPath;
@ExcelProperty("当日总承接数")
@Excel(name ="当日总承接数")
@ColumnWidth(15)
private Integer dailyTotalAccepted;
@ExcelProperty("当日总成单数")
@Excel(name ="当日总成单数")
@ColumnWidth(15)
private Integer dailyTotalOrders;
@ExcelProperty("当日转化率")
@Excel(name ="当日转化率")
@ColumnWidth(15)
private BigDecimal dailyConversionRate;
@ExcelProperty("排序号")
@Excel(name ="排序号")
@ColumnWidth(10)
private Integer sortNo;
}

View File

@ -95,7 +95,8 @@
<select id="getSummary" resultType="java.util.Map">
select sum(daily_total_orders) as totalOrders,
sum(ifnull(daily_total_accepted,0)+ifnull(manager_accepted,0)) as totalIns from department_statistics_data
sum(ifnull(daily_total_accepted,0)+ifnull(manager_accepted,0)) as totalIns
from department_statistics_data
<where>
<if test="startDate != null">
AND stat_date &gt;= #{startDate}

View File

@ -55,7 +55,7 @@ public class CustomerStatisticsDataController extends BaseController {
@RequestParam(value = "indicatorName", required = false) String indicatorName) {
List<CustomerStatisticsDataVO> list = customerStatisticsDataService.selectCustomerStatisticsDataVOList(startDate, endDate, indicatorName);
ExcelUtil<CustomerStatisticsDataVO> util = new ExcelUtil<>(CustomerStatisticsDataVO.class);
util.exportExcel(response, list, "客户统计数据");
util.exportExcel(response, list, "流量看板数据");
}
/**

View File

@ -16,6 +16,7 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Map;
@ -78,7 +79,21 @@ public class DepartmentStatisticsDataController extends BaseController {
@RequestParam(value = "startDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
@RequestParam(value = "endDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate,
@RequestParam(value = "departmentPath", required = false) String departmentPath) {
Map<String, BigDecimal> map = departmentStatisticsDataService.getSummary(startDate, endDate, departmentPath);
BigDecimal totalOrders = map.get("totalOrders");
BigDecimal totalIns = map.get("totalIns");
if(totalOrders == null) {
totalOrders = BigDecimal.ZERO;
}
if(totalIns == null) {
totalIns = BigDecimal.ZERO;
}
if(totalIns.equals(BigDecimal.ZERO)) {
map.put("penetrationRate",null);
} else {
map.put("penetrationRate",totalOrders.multiply(new BigDecimal(100)).divide(totalIns).setScale(2, RoundingMode.HALF_UP));
}
return success(map);
}
}

View File

@ -6,7 +6,7 @@ spring:
druid:
# 主库数据源
master:
url: jdbc:mysql://localhost:3306/excel-handle?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:mysql://host.docker.internal:3316/excel-handle?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: jiong1114
# 从库数据源

View File

@ -0,0 +1,61 @@
# 数据源配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
# 主库数据源
master:
url: jdbc:mysql://host.docker.internal:3316/excel-handle?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: jiong1114
# 从库数据源
slave:
# 从数据源开关/默认关闭
enabled: false
url:
username:
password:
# 初始连接数
initialSize: 5
# 最小连接池数量
minIdle: 10
# 最大连接池数量
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置连接超时时间
connectTimeout: 30000
# 配置网络超时时间
socketTimeout: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow:
url-pattern: /druid/*
# 控制台管理用户名和密码
login-username: ruoyi
login-password: 123456
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true

View File

@ -7,7 +7,7 @@ ruoyi:
# 版权年份
copyrightYear: 2026
# 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath
profile: D:/ruoyi/uploadPath
profile: /home/ruoyi/uploadPath
# 获取ip地址开关
addressEnabled: false
# 验证码类型 math 数字计算 char 字符验证
@ -16,7 +16,7 @@ ruoyi:
# 开发环境配置
server:
# 服务器的HTTP端口默认为8080
port: 8080
port: 8888
servlet:
# 应用的访问路径
context-path: /
@ -34,10 +34,10 @@ server:
# 日志配置
logging:
level:
com.ruoyi: warn
org.springframework: warn
com.ruoyi: info
org.springframework: info
# 添加 MyBatis-Plus SQL 日志
com.ruoyi.**.mapper: debug
com.ruoyi.**.mapper: info
# 用户配置
user:
password:
@ -53,7 +53,7 @@ spring:
# 国际化资源文件路径
basename: i18n/messages
profiles:
active: druid
active: local
# 文件上传
servlet:
multipart:
@ -69,7 +69,7 @@ spring:
# redis 配置
redis:
# 地址
host: localhost
host: host.docker.internal
# 端口默认为6379
port: 6379
# 数据库索引

View File

@ -74,12 +74,12 @@
<!-- 系统模块日志级别控制 -->
<logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<logger name="org.springframework" level="info" />
<!-- MyBatis-Plus SQL日志 - 打印所有Mapper的SQL -->
<logger name="com.ruoyi.system.mapper" level="debug" />
<logger name="com.ruoyi.generator.mapper" level="debug" />
<logger name="com.ruoyi.quartz.mapper" level="debug" />
<logger name="com.ruoyi.excel.wecom.mapper" level="debug" />
<logger name="com.ruoyi.system.mapper" level="info" />
<logger name="com.ruoyi.generator.mapper" level="info" />
<logger name="com.ruoyi.quartz.mapper" level="info" />
<logger name="com.ruoyi.excel.wecom.mapper" level="info" />
<root level="info">
<appender-ref ref="console" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -0,0 +1,2 @@
User-agent: *
Disallow: /

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.login[data-v-5153eeb9]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:100%;background-image:url(../../static/img/login-background.f9f49138.jpg);background-size:cover}.title[data-v-5153eeb9]{margin:0 auto 30px auto;text-align:center;color:#707070}.login-form[data-v-5153eeb9]{border-radius:6px;background:#fff;width:400px;padding:25px 25px 5px 25px;z-index:1}.login-form .el-input[data-v-5153eeb9],.login-form .el-input input[data-v-5153eeb9]{height:38px}.login-form .input-icon[data-v-5153eeb9]{height:39px;width:14px;margin-left:2px}.login-tip[data-v-5153eeb9]{font-size:13px;text-align:center;color:#bfbfbf}.login-code[data-v-5153eeb9]{width:33%;height:38px;float:right}.login-code img[data-v-5153eeb9]{cursor:pointer;vertical-align:middle}.el-login-footer[data-v-5153eeb9]{height:40px;line-height:40px;position:fixed;bottom:0;width:100%;text-align:center;color:#fff;font-family:Arial;font-size:12px;letter-spacing:1px}.login-code-img[data-v-5153eeb9]{height:38px}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.register[data-v-68eda314]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:100%;background-image:url(../../static/img/login-background.f9f49138.jpg);background-size:cover}.title[data-v-68eda314]{margin:0 auto 30px auto;text-align:center;color:#707070}.register-form[data-v-68eda314]{border-radius:6px;background:#fff;width:400px;padding:25px 25px 5px 25px}.register-form .el-input[data-v-68eda314],.register-form .el-input input[data-v-68eda314]{height:38px}.register-form .input-icon[data-v-68eda314]{height:39px;width:14px;margin-left:2px}.register-tip[data-v-68eda314]{font-size:13px;text-align:center;color:#bfbfbf}.register-code[data-v-68eda314]{width:33%;height:38px;float:right}.register-code img[data-v-68eda314]{cursor:pointer;vertical-align:middle}.el-register-footer[data-v-68eda314]{height:40px;line-height:40px;position:fixed;bottom:0;width:100%;text-align:center;color:#fff;font-family:Arial;font-size:12px;letter-spacing:1px}.register-code-img[data-v-68eda314]{height:38px}

View File

@ -0,0 +1 @@
.pop_btn[data-v-1e48b3cd]{text-align:center;margin-top:20px}.popup-main[data-v-1e48b3cd]{position:relative;margin:10px auto;background:#fff;border-radius:5px;font-size:12px;overflow:hidden}.popup-title[data-v-1e48b3cd]{overflow:hidden;line-height:34px;padding-top:6px;background:#f2f2f2}.popup-result[data-v-1e48b3cd]{-webkit-box-sizing:border-box;box-sizing:border-box;line-height:24px;margin:25px auto;padding:15px 10px 10px;border:1px solid #ccc;position:relative}.popup-result .title[data-v-1e48b3cd]{position:absolute;top:-28px;left:50%;width:140px;font-size:14px;margin-left:-70px;text-align:center;line-height:30px;background:#fff}.popup-result table[data-v-1e48b3cd]{text-align:center;width:100%;margin:0 auto}.popup-result table span[data-v-1e48b3cd]{display:block;width:100%;font-family:arial;line-height:30px;height:30px;white-space:nowrap;overflow:hidden;border:1px solid #e8e8e8}.popup-result-scroll[data-v-1e48b3cd]{font-size:12px;line-height:24px;height:10em;overflow-y:auto}

View File

@ -0,0 +1 @@
.icon-body[data-v-480c2f7f]{width:100%;padding:10px}.icon-body .icon-search[data-v-480c2f7f]{position:relative;margin-bottom:5px}.icon-body .icon-list[data-v-480c2f7f]{height:200px;overflow:auto}.icon-body .icon-list .list-container[data-v-480c2f7f]{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap}.icon-body .icon-list .list-container .icon-item-wrapper[data-v-480c2f7f]{width:33.33333%;height:25px;line-height:25px;cursor:pointer;display:-webkit-box;display:-ms-flexbox;display:flex}.icon-body .icon-list .list-container .icon-item-wrapper .icon-item[data-v-480c2f7f]{display:-webkit-box;display:-ms-flexbox;display:flex;max-width:100%;height:100%;padding:0 5px}.icon-body .icon-list .list-container .icon-item-wrapper .icon-item[data-v-480c2f7f]:hover{background:#ececec;border-radius:5px}.icon-body .icon-list .list-container .icon-item-wrapper .icon-item .icon[data-v-480c2f7f]{-ms-flex-negative:0;flex-shrink:0}.icon-body .icon-list .list-container .icon-item-wrapper .icon-item span[data-v-480c2f7f]{display:inline-block;vertical-align:-.15em;fill:currentColor;padding-left:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.icon-body .icon-list .list-container .icon-item-wrapper .icon-item.active[data-v-480c2f7f]{background:#ececec;border-radius:5px}

View File

@ -0,0 +1 @@
.icon-ul[data-v-2fa68d6e]{margin:0;padding:0;font-size:0}.icon-ul li[data-v-2fa68d6e]{list-style-type:none;text-align:center;font-size:14px;display:inline-block;width:16.66%;-webkit-box-sizing:border-box;box-sizing:border-box;height:108px;padding:15px 6px 6px 6px;cursor:pointer;overflow:hidden}.icon-ul li[data-v-2fa68d6e]:hover{background:#f2f2f2}.icon-ul li.active-item[data-v-2fa68d6e]{background:#e1f3fb;color:#7a6df0}.icon-ul li>i[data-v-2fa68d6e]{font-size:30px;line-height:50px}.icon-dialog[data-v-2fa68d6e] .el-dialog{border-radius:8px;margin-bottom:0;margin-top:4vh!important;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-height:92vh;overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box}.icon-dialog[data-v-2fa68d6e] .el-dialog .el-dialog__header{padding-top:14px}.icon-dialog[data-v-2fa68d6e] .el-dialog .el-dialog__body{margin:0 20px 20px 20px;padding:0;overflow:auto}.right-board[data-v-78f2d993]{width:350px;position:absolute;right:0;top:0;padding-top:3px}.right-board .field-box[data-v-78f2d993]{position:relative;height:calc(100vh - 42px);-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden}.right-board .el-scrollbar[data-v-78f2d993]{height:100%}.select-item[data-v-78f2d993]{display:-webkit-box;display:-ms-flexbox;display:flex;border:1px dashed #fff;-webkit-box-sizing:border-box;box-sizing:border-box}.select-item .close-btn[data-v-78f2d993]{cursor:pointer;color:#f56c6c}.select-item .el-input+.el-input[data-v-78f2d993]{margin-left:4px}.select-item+.select-item[data-v-78f2d993]{margin-top:4px}.select-item.sortable-chosen[data-v-78f2d993]{border:1px dashed #409eff}.select-line-icon[data-v-78f2d993]{line-height:32px;font-size:22px;padding:0 4px;color:#777}.option-drag[data-v-78f2d993]{cursor:move}.time-range .el-date-editor[data-v-78f2d993]{width:227px}.time-range[data-v-78f2d993] .el-icon-time{display:none}.document-link[data-v-78f2d993]{position:absolute;display:block;width:26px;height:26px;top:0;left:0;cursor:pointer;background:#409eff;z-index:1;border-radius:0 0 6px 0;text-align:center;line-height:26px;color:#fff;font-size:18px}.node-label[data-v-78f2d993]{font-size:14px}.node-icon[data-v-78f2d993]{color:#bebfc3}

View File

@ -0,0 +1 @@
.user-info-head[data-v-026db168]{position:relative;display:inline-block;height:120px}.user-info-head[data-v-026db168]:hover:after{content:"+";position:absolute;left:0;right:0;top:0;bottom:0;color:#eee;background:rgba(0,0,0,.5);font-size:24px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;cursor:pointer;line-height:110px;border-radius:50%}

View File

@ -0,0 +1 @@
.wscn-http404-container[data-v-279ea4b2]{-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;top:40%;left:50%}.wscn-http404[data-v-279ea4b2]{position:relative;width:1200px;padding:0 50px;overflow:hidden}.wscn-http404 .pic-404[data-v-279ea4b2]{position:relative;float:left;width:600px;overflow:hidden}.wscn-http404 .pic-404__parent[data-v-279ea4b2]{width:100%}.wscn-http404 .pic-404__child[data-v-279ea4b2]{position:absolute}.wscn-http404 .pic-404__child.left[data-v-279ea4b2]{width:80px;top:17px;left:220px;opacity:0;-webkit-animation-name:cloudLeft-data-v-279ea4b2;animation-name:cloudLeft-data-v-279ea4b2;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1s;animation-delay:1s}.wscn-http404 .pic-404__child.mid[data-v-279ea4b2]{width:46px;top:10px;left:420px;opacity:0;-webkit-animation-name:cloudMid-data-v-279ea4b2;animation-name:cloudMid-data-v-279ea4b2;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1.2s;animation-delay:1.2s}.wscn-http404 .pic-404__child.right[data-v-279ea4b2]{width:62px;top:100px;left:500px;opacity:0;-webkit-animation-name:cloudRight-data-v-279ea4b2;animation-name:cloudRight-data-v-279ea4b2;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1s;animation-delay:1s}@-webkit-keyframes cloudLeft-data-v-279ea4b2{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@keyframes cloudLeft-data-v-279ea4b2{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@-webkit-keyframes cloudMid-data-v-279ea4b2{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@keyframes cloudMid-data-v-279ea4b2{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@-webkit-keyframes cloudRight-data-v-279ea4b2{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}@keyframes cloudRight-data-v-279ea4b2{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}.wscn-http404 .bullshit[data-v-279ea4b2]{position:relative;float:left;width:300px;padding:30px 0;overflow:hidden}.wscn-http404 .bullshit__oops[data-v-279ea4b2]{font-size:32px;line-height:40px;color:#1482f0;margin-bottom:20px;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__headline[data-v-279ea4b2],.wscn-http404 .bullshit__oops[data-v-279ea4b2]{font-weight:700;opacity:0;-webkit-animation-name:slideUp-data-v-279ea4b2;animation-name:slideUp-data-v-279ea4b2;-webkit-animation-duration:.5s;animation-duration:.5s}.wscn-http404 .bullshit__headline[data-v-279ea4b2]{font-size:20px;line-height:24px;color:#222;margin-bottom:10px;-webkit-animation-delay:.1s;animation-delay:.1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__info[data-v-279ea4b2]{font-size:13px;line-height:21px;color:grey;margin-bottom:30px;-webkit-animation-delay:.2s;animation-delay:.2s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__info[data-v-279ea4b2],.wscn-http404 .bullshit__return-home[data-v-279ea4b2]{opacity:0;-webkit-animation-name:slideUp-data-v-279ea4b2;animation-name:slideUp-data-v-279ea4b2;-webkit-animation-duration:.5s;animation-duration:.5s}.wscn-http404 .bullshit__return-home[data-v-279ea4b2]{display:block;float:left;width:110px;height:36px;background:#1482f0;border-radius:100px;text-align:center;color:#fff;font-size:14px;line-height:36px;cursor:pointer;-webkit-animation-delay:.3s;animation-delay:.3s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@-webkit-keyframes slideUp-data-v-279ea4b2{0%{-webkit-transform:translateY(60px);transform:translateY(60px);opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}@keyframes slideUp-data-v-279ea4b2{0%{-webkit-transform:translateY(60px);transform:translateY(60px);opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}

View File

@ -0,0 +1 @@
.panel-group[data-v-0ac8ac4e]{margin-top:18px}.panel-group .card-panel-col[data-v-0ac8ac4e]{margin-bottom:32px}.panel-group .card-panel[data-v-0ac8ac4e]{height:108px;cursor:pointer;font-size:12px;position:relative;overflow:hidden;color:#666;background:#fff;-webkit-box-shadow:4px 4px 40px rgba(0,0,0,.05);box-shadow:4px 4px 40px rgba(0,0,0,.05);border-color:rgba(0,0,0,.05)}.panel-group .card-panel:hover .card-panel-icon-wrapper[data-v-0ac8ac4e]{color:#fff}.panel-group .card-panel:hover .icon-people[data-v-0ac8ac4e]{background:#40c9c6}.panel-group .card-panel:hover .icon-message[data-v-0ac8ac4e]{background:#36a3f7}.panel-group .card-panel:hover .icon-money[data-v-0ac8ac4e]{background:#f4516c}.panel-group .card-panel:hover .icon-shopping[data-v-0ac8ac4e]{background:#34bfa3}.panel-group .card-panel .icon-people[data-v-0ac8ac4e]{color:#40c9c6}.panel-group .card-panel .icon-message[data-v-0ac8ac4e]{color:#36a3f7}.panel-group .card-panel .icon-money[data-v-0ac8ac4e]{color:#f4516c}.panel-group .card-panel .icon-shopping[data-v-0ac8ac4e]{color:#34bfa3}.panel-group .card-panel .card-panel-icon-wrapper[data-v-0ac8ac4e]{float:left;margin:14px 0 0 14px;padding:16px;-webkit-transition:all .38s ease-out;transition:all .38s ease-out;border-radius:6px}.panel-group .card-panel .card-panel-icon[data-v-0ac8ac4e]{float:left;font-size:48px}.panel-group .card-panel .card-panel-description[data-v-0ac8ac4e]{float:right;font-weight:700;margin:26px;margin-left:0}.panel-group .card-panel .card-panel-description .card-panel-text[data-v-0ac8ac4e]{line-height:18px;color:rgba(0,0,0,.45);font-size:16px;margin-bottom:12px}.panel-group .card-panel .card-panel-description .card-panel-num[data-v-0ac8ac4e]{font-size:20px}@media (max-width:550px){.card-panel-description[data-v-0ac8ac4e]{display:none}.card-panel-icon-wrapper[data-v-0ac8ac4e]{float:none!important;width:100%;height:100%;margin:0!important}.card-panel-icon-wrapper .svg-icon[data-v-0ac8ac4e]{display:block;margin:14px auto!important;float:none!important}}

View File

@ -0,0 +1 @@
.hljs{display:block;background:#fff;padding:.5em;color:#333;overflow-x:auto}.hljs-comment,.hljs-meta{color:#969896}.hljs-emphasis,.hljs-quote,.hljs-strong,.hljs-template-variable,.hljs-variable{color:#df5000}.hljs-keyword,.hljs-selector-tag,.hljs-type{color:#d73a49}.hljs-attribute,.hljs-bullet,.hljs-literal,.hljs-symbol{color:#0086b3}.hljs-name,.hljs-section{color:#63a35c}.hljs-tag{color:#333}.hljs-attr,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-selector-pseudo,.hljs-title{color:#6f42c1}.hljs-addition{color:#55a532;background-color:#eaffea}.hljs-deletion{color:#bd2c00;background-color:#ffecec}.hljs-link{text-decoration:underline}.hljs-number{color:#005cc5}.hljs-string{color:#032f62}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.icon-ul[data-v-2fa68d6e]{margin:0;padding:0;font-size:0}.icon-ul li[data-v-2fa68d6e]{list-style-type:none;text-align:center;font-size:14px;display:inline-block;width:16.66%;-webkit-box-sizing:border-box;box-sizing:border-box;height:108px;padding:15px 6px 6px 6px;cursor:pointer;overflow:hidden}.icon-ul li[data-v-2fa68d6e]:hover{background:#f2f2f2}.icon-ul li.active-item[data-v-2fa68d6e]{background:#e1f3fb;color:#7a6df0}.icon-ul li>i[data-v-2fa68d6e]{font-size:30px;line-height:50px}.icon-dialog[data-v-2fa68d6e] .el-dialog{border-radius:8px;margin-bottom:0;margin-top:4vh!important;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-height:92vh;overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box}.icon-dialog[data-v-2fa68d6e] .el-dialog .el-dialog__header{padding-top:14px}.icon-dialog[data-v-2fa68d6e] .el-dialog .el-dialog__body{margin:0 20px 20px 20px;padding:0;overflow:auto}

View File

@ -0,0 +1 @@
.user-info-head[data-v-026db168]{position:relative;display:inline-block;height:120px}.user-info-head[data-v-026db168]:hover:after{content:"+";position:absolute;left:0;right:0;top:0;bottom:0;color:#eee;background:rgba(0,0,0,.5);font-size:24px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;cursor:pointer;line-height:110px;border-radius:50%}

View File

@ -0,0 +1 @@
.panel-group[data-v-0ac8ac4e]{margin-top:18px}.panel-group .card-panel-col[data-v-0ac8ac4e]{margin-bottom:32px}.panel-group .card-panel[data-v-0ac8ac4e]{height:108px;cursor:pointer;font-size:12px;position:relative;overflow:hidden;color:#666;background:#fff;-webkit-box-shadow:4px 4px 40px rgba(0,0,0,.05);box-shadow:4px 4px 40px rgba(0,0,0,.05);border-color:rgba(0,0,0,.05)}.panel-group .card-panel:hover .card-panel-icon-wrapper[data-v-0ac8ac4e]{color:#fff}.panel-group .card-panel:hover .icon-people[data-v-0ac8ac4e]{background:#40c9c6}.panel-group .card-panel:hover .icon-message[data-v-0ac8ac4e]{background:#36a3f7}.panel-group .card-panel:hover .icon-money[data-v-0ac8ac4e]{background:#f4516c}.panel-group .card-panel:hover .icon-shopping[data-v-0ac8ac4e]{background:#34bfa3}.panel-group .card-panel .icon-people[data-v-0ac8ac4e]{color:#40c9c6}.panel-group .card-panel .icon-message[data-v-0ac8ac4e]{color:#36a3f7}.panel-group .card-panel .icon-money[data-v-0ac8ac4e]{color:#f4516c}.panel-group .card-panel .icon-shopping[data-v-0ac8ac4e]{color:#34bfa3}.panel-group .card-panel .card-panel-icon-wrapper[data-v-0ac8ac4e]{float:left;margin:14px 0 0 14px;padding:16px;-webkit-transition:all .38s ease-out;transition:all .38s ease-out;border-radius:6px}.panel-group .card-panel .card-panel-icon[data-v-0ac8ac4e]{float:left;font-size:48px}.panel-group .card-panel .card-panel-description[data-v-0ac8ac4e]{float:right;font-weight:700;margin:26px;margin-left:0}.panel-group .card-panel .card-panel-description .card-panel-text[data-v-0ac8ac4e]{line-height:18px;color:rgba(0,0,0,.45);font-size:16px;margin-bottom:12px}.panel-group .card-panel .card-panel-description .card-panel-num[data-v-0ac8ac4e]{font-size:20px}@media (max-width:550px){.card-panel-description[data-v-0ac8ac4e]{display:none}.card-panel-icon-wrapper[data-v-0ac8ac4e]{float:none!important;width:100%;height:100%;margin:0!important}.card-panel-icon-wrapper .svg-icon[data-v-0ac8ac4e]{display:block;margin:14px auto!important;float:none!important}}.dashboard-editor-container[data-v-70cc8e61]{padding:32px;background-color:#f0f2f5;position:relative}.dashboard-editor-container .chart-wrapper[data-v-70cc8e61]{background:#fff;padding:16px 16px 0;margin-bottom:32px}@media (max-width:1024px){.chart-wrapper[data-v-70cc8e61]{padding:8px}}

View File

@ -0,0 +1 @@
.splitpanes{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;height:100%}.splitpanes--vertical{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.splitpanes--horizontal{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.splitpanes--dragging *{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.splitpanes__pane{width:100%;height:100%;overflow:hidden}.splitpanes--vertical .splitpanes__pane{-webkit-transition:width .2s ease-out;transition:width .2s ease-out}.splitpanes--horizontal .splitpanes__pane{-webkit-transition:height .2s ease-out;transition:height .2s ease-out}.splitpanes--dragging .splitpanes__pane{-webkit-transition:none;transition:none}.splitpanes__splitter{-ms-touch-action:none;touch-action:none}.splitpanes--vertical>.splitpanes__splitter{min-width:1px;cursor:col-resize}.splitpanes--horizontal>.splitpanes__splitter{min-height:1px;cursor:row-resize}.splitpanes.default-theme .splitpanes__pane{background-color:#f2f2f2}.splitpanes.default-theme .splitpanes__splitter{background-color:#fff;-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;-ms-flex-negative:0;flex-shrink:0}.splitpanes.default-theme .splitpanes__splitter:after,.splitpanes.default-theme .splitpanes__splitter:before{content:"";position:absolute;top:50%;left:50%;background-color:rgba(0,0,0,.14901960784313725);-webkit-transition:background-color .3s;transition:background-color .3s}.splitpanes.default-theme .splitpanes__splitter:hover:after,.splitpanes.default-theme .splitpanes__splitter:hover:before{background-color:rgba(0,0,0,.25098039215686274)}.splitpanes.default-theme .splitpanes__splitter:first-child{cursor:auto}.default-theme.splitpanes .splitpanes .splitpanes__splitter{z-index:1}.default-theme.splitpanes--vertical>.splitpanes__splitter,.default-theme .splitpanes--vertical>.splitpanes__splitter{width:7px;border-left:1px solid #eee;margin-left:-1px}.default-theme.splitpanes--vertical>.splitpanes__splitter:after,.default-theme .splitpanes--vertical>.splitpanes__splitter:after,.default-theme.splitpanes--vertical>.splitpanes__splitter:before,.default-theme .splitpanes--vertical>.splitpanes__splitter:before{-webkit-transform:translateY(-50%);transform:translateY(-50%);width:1px;height:30px}.default-theme.splitpanes--vertical>.splitpanes__splitter:before,.default-theme .splitpanes--vertical>.splitpanes__splitter:before{margin-left:-2px}.default-theme.splitpanes--vertical>.splitpanes__splitter:after,.default-theme .splitpanes--vertical>.splitpanes__splitter:after{margin-left:1px}.default-theme.splitpanes--horizontal>.splitpanes__splitter,.default-theme .splitpanes--horizontal>.splitpanes__splitter{height:7px;border-top:1px solid #eee;margin-top:-1px}.default-theme.splitpanes--horizontal>.splitpanes__splitter:after,.default-theme .splitpanes--horizontal>.splitpanes__splitter:after,.default-theme.splitpanes--horizontal>.splitpanes__splitter:before,.default-theme .splitpanes--horizontal>.splitpanes__splitter:before{-webkit-transform:translateX(-50%);transform:translate(-50%);width:30px;height:1px}.default-theme.splitpanes--horizontal>.splitpanes__splitter:before,.default-theme .splitpanes--horizontal>.splitpanes__splitter:before{margin-top:-2px}.default-theme.splitpanes--horizontal>.splitpanes__splitter:after,.default-theme .splitpanes--horizontal>.splitpanes__splitter:after{margin-top:1px}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.errPage-container[data-v-f2e02586]{width:800px;max-width:100%;margin:100px auto}.errPage-container .pan-back-btn[data-v-f2e02586]{background:#008489;color:#fff;border:none!important}.errPage-container .pan-gif[data-v-f2e02586]{margin:0 auto;display:block}.errPage-container .pan-img[data-v-f2e02586]{display:block;margin:0 auto;width:100%}.errPage-container .text-jumbo[data-v-f2e02586]{font-size:60px;font-weight:700;color:#484848}.errPage-container .list-unstyled[data-v-f2e02586]{font-size:14px}.errPage-container .list-unstyled li[data-v-f2e02586]{padding-bottom:5px}.errPage-container .list-unstyled a[data-v-f2e02586]{color:#008489;text-decoration:none}.errPage-container .list-unstyled a[data-v-f2e02586]:hover{text-decoration:underline}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1">
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
<rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect>
<filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4">
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
</filter>
</defs>
<g id="配置面板" width="48" height="40" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="setting-copy-2" width="48" height="40" transform="translate(-1190.000000, -136.000000)">
<g id="Group-8" width="48" height="40" transform="translate(1167.000000, 0.000000)">
<g id="Group-5-Copy-5" filter="url(#filter-1)" transform="translate(25.000000, 137.000000)">
<mask id="mask-3" fill="white">
<use xlink:href="#path-2"></use>
</mask>
<g id="Rectangle-18">
<use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use>
<use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use>
</g>
<rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect>
<rect id="Rectangle-18" fill="#303648" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1">
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
<rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect>
<filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4">
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
</filter>
</defs>
<g id="配置面板" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="setting-copy-2" transform="translate(-1254.000000, -136.000000)">
<g id="Group-8" transform="translate(1167.000000, 0.000000)">
<g id="Group-5" filter="url(#filter-1)" transform="translate(89.000000, 137.000000)">
<mask id="mask-3" fill="white">
<use xlink:href="#path-2"></use>
</mask>
<g id="Rectangle-18">
<use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use>
<use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use>
</g>
<rect id="Rectangle-18" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect>
<rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-005cb0c7"],{"4b72":function(e,t,n){"use strict";n.d(t,"g",(function(){return o})),n.d(t,"f",(function(){return r})),n.d(t,"d",(function(){return l})),n.d(t,"j",(function(){return i})),n.d(t,"e",(function(){return u})),n.d(t,"a",(function(){return s})),n.d(t,"h",(function(){return c})),n.d(t,"b",(function(){return m})),n.d(t,"c",(function(){return b})),n.d(t,"i",(function(){return d}));var a=n("b775");function o(e){return Object(a["a"])({url:"/tool/gen/list",method:"get",params:e})}function r(e){return Object(a["a"])({url:"/tool/gen/db/list",method:"get",params:e})}function l(e){return Object(a["a"])({url:"/tool/gen/"+e,method:"get"})}function i(e){return Object(a["a"])({url:"/tool/gen",method:"put",data:e})}function u(e){return Object(a["a"])({url:"/tool/gen/importTable",method:"post",params:e})}function s(e){return Object(a["a"])({url:"/tool/gen/createTable",method:"post",params:e})}function c(e){return Object(a["a"])({url:"/tool/gen/preview/"+e,method:"get"})}function m(e){return Object(a["a"])({url:"/tool/gen/"+e,method:"delete"})}function b(e){return Object(a["a"])({url:"/tool/gen/genCode/"+e,method:"get"})}function d(e){return Object(a["a"])({url:"/tool/gen/synchDb/"+e,method:"get"})}},"6f72":function(e,t,n){"use strict";n.r(t);var a=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("el-dialog",{attrs:{title:"导入表",visible:e.visible,width:"800px",top:"5vh","append-to-body":""},on:{"update:visible":function(t){e.visible=t}}},[n("el-form",{ref:"queryForm",attrs:{model:e.queryParams,size:"small",inline:!0}},[n("el-form-item",{attrs:{label:"表名称",prop:"tableName"}},[n("el-input",{attrs:{placeholder:"请输入表名称",clearable:""},nativeOn:{keyup:function(t){return!t.type.indexOf("key")&&e._k(t.keyCode,"enter",13,t.key,"Enter")?null:e.handleQuery(t)}},model:{value:e.queryParams.tableName,callback:function(t){e.$set(e.queryParams,"tableName",t)},expression:"queryParams.tableName"}})],1),n("el-form-item",{attrs:{label:"表描述",prop:"tableComment"}},[n("el-input",{attrs:{placeholder:"请输入表描述",clearable:""},nativeOn:{keyup:function(t){return!t.type.indexOf("key")&&e._k(t.keyCode,"enter",13,t.key,"Enter")?null:e.handleQuery(t)}},model:{value:e.queryParams.tableComment,callback:function(t){e.$set(e.queryParams,"tableComment",t)},expression:"queryParams.tableComment"}})],1),n("el-form-item",[n("el-button",{attrs:{type:"primary",icon:"el-icon-search",size:"mini"},on:{click:e.handleQuery}},[e._v("搜索")]),n("el-button",{attrs:{icon:"el-icon-refresh",size:"mini"},on:{click:e.resetQuery}},[e._v("重置")])],1)],1),n("el-row",[n("el-table",{ref:"table",attrs:{data:e.dbTableList,height:"260px"},on:{"row-click":e.clickRow,"selection-change":e.handleSelectionChange}},[n("el-table-column",{attrs:{type:"selection",width:"55"}}),n("el-table-column",{attrs:{prop:"tableName",label:"表名称","show-overflow-tooltip":!0}}),n("el-table-column",{attrs:{prop:"tableComment",label:"表描述","show-overflow-tooltip":!0}}),n("el-table-column",{attrs:{prop:"createTime",label:"创建时间"}}),n("el-table-column",{attrs:{prop:"updateTime",label:"更新时间"}})],1),n("pagination",{directives:[{name:"show",rawName:"v-show",value:e.total>0,expression:"total>0"}],attrs:{total:e.total,page:e.queryParams.pageNum,limit:e.queryParams.pageSize},on:{"update:page":function(t){return e.$set(e.queryParams,"pageNum",t)},"update:limit":function(t){return e.$set(e.queryParams,"pageSize",t)},pagination:e.getList}})],1),n("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[n("el-button",{attrs:{type:"primary"},on:{click:e.handleImportTable}},[e._v("确 定")]),n("el-button",{on:{click:function(t){e.visible=!1}}},[e._v("取 消")])],1)],1)},o=[],r=(n("a15b"),n("d81d"),n("d3b7"),n("0643"),n("a573"),n("4b72")),l={data:function(){return{visible:!1,tables:[],total:0,dbTableList:[],queryParams:{pageNum:1,pageSize:10,tableName:void 0,tableComment:void 0}}},methods:{show:function(){this.getList(),this.visible=!0},clickRow:function(e){this.$refs.table.toggleRowSelection(e)},handleSelectionChange:function(e){this.tables=e.map((function(e){return e.tableName}))},getList:function(){var e=this;Object(r["f"])(this.queryParams).then((function(t){200===t.code&&(e.dbTableList=t.rows,e.total=t.total)}))},handleQuery:function(){this.queryParams.pageNum=1,this.getList()},resetQuery:function(){this.resetForm("queryForm"),this.handleQuery()},handleImportTable:function(){var e=this,t=this.tables.join(",");""!=t?Object(r["e"])({tables:t}).then((function(t){e.$modal.msgSuccess(t.msg),200===t.code&&(e.visible=!1,e.$emit("ok"))})):this.$modal.msgError("请选择要导入的表")}}},i=l,u=n("2877"),s=Object(u["a"])(i,a,o,!1,null,null,null);t["default"]=s.exports}}]);

View File

@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-0238e9b0"],{"4b72":function(t,e,n){"use strict";n.d(e,"g",(function(){return r})),n.d(e,"f",(function(){return u})),n.d(e,"d",(function(){return i})),n.d(e,"j",(function(){return c})),n.d(e,"e",(function(){return l})),n.d(e,"a",(function(){return a})),n.d(e,"h",(function(){return s})),n.d(e,"b",(function(){return d})),n.d(e,"c",(function(){return b})),n.d(e,"i",(function(){return f}));var o=n("b775");function r(t){return Object(o["a"])({url:"/tool/gen/list",method:"get",params:t})}function u(t){return Object(o["a"])({url:"/tool/gen/db/list",method:"get",params:t})}function i(t){return Object(o["a"])({url:"/tool/gen/"+t,method:"get"})}function c(t){return Object(o["a"])({url:"/tool/gen",method:"put",data:t})}function l(t){return Object(o["a"])({url:"/tool/gen/importTable",method:"post",params:t})}function a(t){return Object(o["a"])({url:"/tool/gen/createTable",method:"post",params:t})}function s(t){return Object(o["a"])({url:"/tool/gen/preview/"+t,method:"get"})}function d(t){return Object(o["a"])({url:"/tool/gen/"+t,method:"delete"})}function b(t){return Object(o["a"])({url:"/tool/gen/genCode/"+t,method:"get"})}function f(t){return Object(o["a"])({url:"/tool/gen/synchDb/"+t,method:"get"})}},"7d85":function(t,e,n){"use strict";n.r(e);var o=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("el-dialog",{attrs:{title:"创建表",visible:t.visible,width:"800px",top:"5vh","append-to-body":""},on:{"update:visible":function(e){t.visible=e}}},[n("span",[t._v("创建表语句(支持多个建表语句)")]),n("el-input",{attrs:{type:"textarea",rows:10,placeholder:"请输入文本"},model:{value:t.content,callback:function(e){t.content=e},expression:"content"}}),n("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[n("el-button",{attrs:{type:"primary"},on:{click:t.handleCreateTable}},[t._v("确 定")]),n("el-button",{on:{click:function(e){t.visible=!1}}},[t._v("取 消")])],1)],1)},r=[],u=n("4b72"),i={data:function(){return{visible:!1,content:""}},methods:{show:function(){this.visible=!0},handleCreateTable:function(){var t=this;""!==this.content?Object(u["a"])({sql:this.content}).then((function(e){t.$modal.msgSuccess(e.msg),200===e.code&&(t.visible=!1,t.$emit("ok"))})):this.$modal.msgError("请输入建表语句")}}},c=i,l=n("2877"),a=Object(l["a"])(c,o,r,!1,null,null,null);e["default"]=a.exports}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-12624f69"],{"1e4b":function(s,t,a){"use strict";a.r(t);var e=function(){var s=this,t=s.$createElement,a=s._self._c||t;return a("div",{staticClass:"dashboard-container"},[a("div",{staticClass:"welcome-section"},[a("el-card",{staticClass:"welcome-card",attrs:{shadow:"hover"}},[a("div",{staticClass:"welcome-content"},[a("div",{staticClass:"welcome-text"},[a("h1",{staticClass:"company-name"},[s._v("超脑智子测试版")]),a("p",{staticClass:"company-slogan"},[s._v("用人工智能科技为各行业提供解决方案")]),a("p",{staticClass:"company-desc"},[s._v("集互联网零售、人工智能和信息咨询于一体的互联网公司")])]),a("div",{staticClass:"welcome-icon"},[a("i",{staticClass:"el-icon-s-platform"})])])])],1),a("el-row",{staticClass:"business-section",attrs:{gutter:20}},[a("el-col",{attrs:{xs:24,sm:12,md:8}},[a("el-card",{staticClass:"business-card retail",attrs:{shadow:"hover"}},[a("div",{staticClass:"card-icon"},[a("i",{staticClass:"el-icon-shopping-cart-full"})]),a("div",{staticClass:"card-content"},[a("h3",[s._v("互联网销售")]),a("p",[s._v("严选品牌,甄选好物")]),a("el-tag",{attrs:{size:"small",type:"success"}},[s._v("零售业务")])],1)])],1),a("el-col",{attrs:{xs:24,sm:12,md:8}},[a("el-card",{staticClass:"business-card ai",attrs:{shadow:"hover"}},[a("div",{staticClass:"card-icon"},[a("i",{staticClass:"el-icon-cpu"})]),a("div",{staticClass:"card-content"},[a("h3",[s._v("人工智能")]),a("p",[s._v("自研智能科技模型,赋能增效")]),a("el-tag",{attrs:{size:"small",type:"primary"}},[s._v("核心技术")])],1)])],1),a("el-col",{attrs:{xs:24,sm:12,md:8}},[a("el-card",{staticClass:"business-card consult",attrs:{shadow:"hover"}},[a("div",{staticClass:"card-icon"},[a("i",{staticClass:"el-icon-data-analysis"})]),a("div",{staticClass:"card-content"},[a("h3",[s._v("企业咨询")]),a("p",[s._v("AI与大数据融合提供专业解决方案")]),a("el-tag",{attrs:{size:"small",type:"warning"}},[s._v("咨询服务")])],1)])],1)],1),a("el-row",{staticClass:"feature-section",attrs:{gutter:20}},[a("el-col",{attrs:{xs:24,md:12}},[a("el-card",{staticClass:"feature-card",attrs:{shadow:"never"}},[a("div",{staticClass:"card-header",attrs:{slot:"header"},slot:"header"},[a("i",{staticClass:"el-icon-medal"}),a("span",[s._v("严选标准")])]),a("div",{staticClass:"feature-list"},[a("div",{staticClass:"feature-item"},[a("i",{staticClass:"el-icon-check"}),a("span",[s._v("好商品 - 精选优质供应商")])]),a("div",{staticClass:"feature-item"},[a("i",{staticClass:"el-icon-check"}),a("span",[s._v("好品质 - 严格质量把控")])]),a("div",{staticClass:"feature-item"},[a("i",{staticClass:"el-icon-check"}),a("span",[s._v("好价格 - 极具竞争力价格")])]),a("div",{staticClass:"feature-item"},[a("i",{staticClass:"el-icon-check"}),a("span",[s._v("好服务 - 完善售后体系")])])])])],1),a("el-col",{attrs:{xs:24,md:12}},[a("el-card",{staticClass:"feature-card",attrs:{shadow:"never"}},[a("div",{staticClass:"card-header",attrs:{slot:"header"},slot:"header"},[a("i",{staticClass:"el-icon-magic-stick"}),a("span",[s._v("科技赋能")])]),a("div",{staticClass:"tech-content"},[a("div",{staticClass:"tech-highlight"},[a("div",{staticClass:"tech-number"},[s._v("AI+")]),a("div",{staticClass:"tech-desc"},[a("p",[s._v("智能科技+大数据赋能增效")]),a("p",{staticClass:"sub-text"},[s._v("更高效,更懂你")])])])])])],1)],1),a("el-card",{staticClass:"process-card",attrs:{shadow:"never"}},[a("div",{attrs:{slot:"header"},slot:"header"},[a("i",{staticClass:"el-icon-s-operation"}),a("span",[s._v("供应链选及招商流程")])]),a("el-steps",{attrs:{active:4,"align-center":"","finish-status":"success"}},[a("el-step",{attrs:{title:"商家入驻",description:"商家注册入驻,资质和商品提报"}}),a("el-step",{attrs:{title:"资质初审",description:"审核资质及商品信息"}}),a("el-step",{attrs:{title:"结果反馈",description:"3个工作日内反馈结果"}}),a("el-step",{attrs:{title:"洽谈推广",description:"详细洽谈并安排推广"}})],1)],1)],1)},c=[],i={name:"Dashboard",data:function(){return{}}},l=i,r=(a("67b9"),a("2877")),n=Object(r["a"])(l,e,c,!1,null,"949410e8",null);t["default"]=n.exports},"67b9":function(s,t,a){"use strict";a("a429")},a429:function(s,t,a){}}]);

Some files were not shown because too many files have changed in this diff Show More