template
This commit is contained in:
202
web/group-site/README.md
Normal file
202
web/group-site/README.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# 科研课题组展示网站
|
||||
|
||||
## 📍 访问地址
|
||||
|
||||
```
|
||||
https://amiap.hzau.edu.cn/group/
|
||||
```
|
||||
|
||||
## 🎨 Vue 项目配置(重要!)
|
||||
|
||||
### 1. Vue Router 配置
|
||||
|
||||
```javascript
|
||||
// router/index.js
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
|
||||
const router = createRouter({
|
||||
// ⚠️ 重要:base 设置为 /group/
|
||||
history: createWebHistory('/group/'),
|
||||
routes: [
|
||||
{
|
||||
path: '/', // 实际访问: https://amiap.hzau.edu.cn/group/
|
||||
name: 'Home',
|
||||
component: () => import('@/views/Home.vue')
|
||||
},
|
||||
{
|
||||
path: '/members', // 实际访问: https://amiap.hzau.edu.cn/group/members
|
||||
name: 'Members',
|
||||
component: () => import('@/views/Members.vue')
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
export default router
|
||||
```
|
||||
|
||||
### 2. Vite 配置
|
||||
|
||||
```javascript
|
||||
// vite.config.js
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
// ⚠️ 重要:base 设置为 /group/
|
||||
base: '/group/',
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
assetsDir: 'assets'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 3. Vue CLI 配置(如果使用 Vue CLI)
|
||||
|
||||
```javascript
|
||||
// vue.config.js
|
||||
module.exports = {
|
||||
publicPath: process.env.NODE_ENV === 'production' ? '/group/' : '/',
|
||||
outputDir: 'dist'
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 部署步骤
|
||||
|
||||
### 1. 构建 Vue 项目
|
||||
|
||||
```bash
|
||||
# 在你的 Vue 项目根目录
|
||||
cd your-vue-project
|
||||
|
||||
# 确保已配置 base: '/group/'
|
||||
# 然后构建
|
||||
npm run build
|
||||
|
||||
# 或
|
||||
pnpm build
|
||||
```
|
||||
|
||||
### 2. 复制构建产物
|
||||
|
||||
```bash
|
||||
# 复制 dist 目录到部署位置
|
||||
cp -r dist /vol1/1000/docker_server/traefik/web/group-site/
|
||||
```
|
||||
|
||||
### 3. 启动服务
|
||||
|
||||
```bash
|
||||
cd /vol1/1000/docker_server/traefik/web/group-site
|
||||
|
||||
# 启动
|
||||
docker compose up -d
|
||||
|
||||
# 查看日志
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
### 4. 访问网站
|
||||
|
||||
```
|
||||
https://amiap.hzau.edu.cn/group/
|
||||
```
|
||||
|
||||
## 📊 完整路由规划
|
||||
|
||||
```
|
||||
https://amiap.hzau.edu.cn/
|
||||
├── / → MinIO S3 API + 控制台(根路径)
|
||||
│ ├── /stub/ → S3 bucket 访问
|
||||
│ ├── /api/v1/ → MinIO Console API
|
||||
│ └── /static/ → MinIO Console 静态资源
|
||||
│
|
||||
├── /group/ → 科研课题组网站(你的 Vue 项目)
|
||||
│ ├── /group/ → 首页
|
||||
│ ├── /group/members → 成员介绍
|
||||
│ ├── /group/research → 研究方向
|
||||
│ └── /group/... → 其他页面
|
||||
│
|
||||
├── /supa/ → Supabase API
|
||||
└── /ABM/ → ABM 数据库
|
||||
```
|
||||
|
||||
## 🔧 开发调试
|
||||
|
||||
### 本地开发
|
||||
|
||||
```bash
|
||||
# 在 Vue 项目中本地运行
|
||||
npm run dev
|
||||
|
||||
# Vite 会自动处理 /group/ base path
|
||||
# 访问: http://localhost:5173/group/
|
||||
```
|
||||
|
||||
### 生产环境测试
|
||||
|
||||
```bash
|
||||
# 构建生产版本
|
||||
npm run build
|
||||
|
||||
# 预览
|
||||
npm run preview
|
||||
# 访问: http://localhost:4173/group/
|
||||
```
|
||||
|
||||
## <20><> 示例项目结构
|
||||
|
||||
```javascript
|
||||
// App.vue
|
||||
<template>
|
||||
<div id="app">
|
||||
<nav>
|
||||
<\!-- 路由链接会自动加上 /group/ 前缀 -->
|
||||
<router-link to="/">首页</router-link>
|
||||
<router-link to="/members">团队成员</router-link>
|
||||
<router-link to="/research">研究方向</router-link>
|
||||
</nav>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
// 图片引用示例
|
||||
<template>
|
||||
<img src="@/assets/logo.png" alt="Logo">
|
||||
<\!-- Vite 会自动处理为: /group/assets/logo-xxx.png -->
|
||||
</template>
|
||||
```
|
||||
|
||||
## ⚠️ 常见问题
|
||||
|
||||
### Q: 刷新页面出现 404
|
||||
A: 已在 nginx.conf 中配置 `try_files`,支持 Vue Router History 模式
|
||||
|
||||
### Q: 静态资源加载失败
|
||||
A: 确保 Vite/Vue CLI 配置了正确的 `base: '/group/'`
|
||||
|
||||
### Q: 路由跳转到根路径
|
||||
A: 检查 Vue Router 的 `history: createWebHistory('/group/')`
|
||||
|
||||
### Q: API 请求路径错误
|
||||
A: 使用绝对路径或相对路径,例如:
|
||||
```javascript
|
||||
// 调用 Supabase API
|
||||
fetch('https://amiap.hzau.edu.cn/supa/rest/v1/...')
|
||||
|
||||
// 或使用环境变量
|
||||
const API_BASE = import.meta.env.VITE_API_URL
|
||||
```
|
||||
|
||||
## 🔗 相关资源
|
||||
|
||||
- [Vue Router Base 配置](https://router.vuejs.org/guide/essentials/history-mode.html#html5-mode)
|
||||
- [Vite Base 配置](https://vitejs.dev/config/shared-options.html#base)
|
||||
- [主项目文档](../../README.md)
|
||||
|
||||
---
|
||||
|
||||
**部署路径**: `/group/`
|
||||
**优先级**: 80(高于 MinIO S3 的 50)
|
||||
**维护者**: Lab Admin
|
||||
203
web/group-site/dist/index.html
vendored
Executable file
203
web/group-site/dist/index.html
vendored
Executable file
@@ -0,0 +1,203 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>实验室服务导航 - HZAU Lab</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.container {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||||
padding: 3rem;
|
||||
max-width: 800px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 2.5rem;
|
||||
color: #2d3748;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.header p {
|
||||
color: #718096;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.services {
|
||||
display: grid;
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.service-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 1.5rem;
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.07);
|
||||
transition: all 0.3s ease;
|
||||
text-decoration: none;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
.service-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.service-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 2rem;
|
||||
margin-right: 1.5rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.icon-minio { background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%); }
|
||||
.icon-supabase { background: linear-gradient(135deg, #3ecf8e 0%, #2eb77a 100%); }
|
||||
.icon-abm { background: linear-gradient(135deg, #4facfe 0%, #00a8ff 100%); }
|
||||
|
||||
.service-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.service-info h3 {
|
||||
font-size: 1.3rem;
|
||||
color: #2d3748;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
.service-info p {
|
||||
color: #718096;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.service-badge {
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.badge-internal {
|
||||
background: #fef5e7;
|
||||
color: #d68910;
|
||||
}
|
||||
|
||||
.badge-public {
|
||||
background: #eaf7f0;
|
||||
color: #27ae60;
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
padding-top: 2rem;
|
||||
border-top: 1px solid #e2e8f0;
|
||||
color: #a0aec0;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.footer strong {
|
||||
color: #667eea;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.container {
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.service-card {
|
||||
padding: 1.25rem;
|
||||
}
|
||||
|
||||
.service-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: 1.5rem;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>🔬 实验室服务导航</h1>
|
||||
<p>华中农业大学 · Lab Services Portal</p>
|
||||
</div>
|
||||
|
||||
<div class="services">
|
||||
<!-- MinIO 对象存储 -->
|
||||
<a href="http://100.64.0.2:9001" class="service-card" target="_blank">
|
||||
<div class="service-icon icon-minio">📦</div>
|
||||
<div class="service-info">
|
||||
<h3>MinIO 对象存储</h3>
|
||||
<p>S3 兼容对象存储管理控制台</p>
|
||||
</div>
|
||||
<span class="service-badge badge-internal">内网访问</span>
|
||||
</a>
|
||||
|
||||
<!-- Supabase Dashboard -->
|
||||
<a href="http://100.64.0.2:18000" class="service-card" target="_blank">
|
||||
<div class="service-icon icon-supabase">🗄️</div>
|
||||
<div class="service-info">
|
||||
<h3>Supabase Dashboard</h3>
|
||||
<p>数据库管理和 API 配置面板</p>
|
||||
</div>
|
||||
<span class="service-badge badge-internal">内网访问</span>
|
||||
</a>
|
||||
|
||||
<!-- ABM 数据库 -->
|
||||
<a href="https://amiap.hzau.edu.cn/ABM/" class="service-card" target="_blank">
|
||||
<div class="service-icon icon-abm">🌐</div>
|
||||
<div class="service-info">
|
||||
<h3>ABM 数据库</h3>
|
||||
<p>WebSocket 实时数据服务</p>
|
||||
</div>
|
||||
<span class="service-badge badge-public">公网访问</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p>⚠️ 这是临时导航页面</p>
|
||||
<p style="margin-top: 0.5rem;">
|
||||
后续将替换为 <strong>Vue 课题组网站</strong>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
39
web/group-site/docker-compose.yml
Normal file
39
web/group-site/docker-compose.yml
Normal file
@@ -0,0 +1,39 @@
|
||||
# Vue 科研课题组展示网站
|
||||
# 部署路径:https://amiap.hzau.edu.cn/group/
|
||||
|
||||
services:
|
||||
group-site:
|
||||
image: nginx:alpine
|
||||
container_name: group-site
|
||||
volumes:
|
||||
# Vue 构建产物
|
||||
- ./dist:/usr/share/nginx/html:ro
|
||||
# Nginx 配置
|
||||
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
networks:
|
||||
- frontend
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
|
||||
# ======================================
|
||||
# 课题组网站路由 - /group/ 子路径
|
||||
# ======================================
|
||||
- "traefik.http.routers.group-site.rule=Host(`amiap.hzau.edu.cn`) && PathPrefix(`/group`)"
|
||||
- "traefik.http.routers.group-site.priority=80" # 高于 MinIO S3 (50)
|
||||
- "traefik.http.routers.group-site.entrypoints=websecure"
|
||||
- "traefik.http.routers.group-site.tls.certresolver=myresolver"
|
||||
|
||||
# StripPrefix 中间件 - 去除 /group 前缀
|
||||
- "traefik.http.middlewares.group-stripprefix.stripprefix.prefixes=/group"
|
||||
|
||||
# 压缩中间件
|
||||
- "traefik.http.middlewares.group-compress.compress=true"
|
||||
|
||||
# 应用中间件
|
||||
- "traefik.http.routers.group-site.middlewares=group-stripprefix,group-compress"
|
||||
|
||||
- "traefik.http.services.group-site-svc.loadbalancer.server.port=80"
|
||||
|
||||
networks:
|
||||
frontend:
|
||||
external: true
|
||||
30
web/group-site/nginx.conf
Normal file
30
web/group-site/nginx.conf
Normal file
@@ -0,0 +1,30 @@
|
||||
# Nginx 配置 - Vue Router History 模式 + 子路径
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
# Gzip 压缩
|
||||
gzip on;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
|
||||
gzip_min_length 1000;
|
||||
|
||||
# Vue Router history 模式支持
|
||||
# 重要:因为 Traefik 已经去除了 /group 前缀,这里直接处理根路径
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# 静态资源缓存
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# 安全头
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
}
|
||||
Reference in New Issue
Block a user