后端管理模块部署

This commit is contained in:
2025-10-30 16:55:22 +08:00
parent 093d07ab76
commit 8f2133f3af
16 changed files with 649 additions and 52 deletions
+63
View File
@@ -0,0 +1,63 @@
#!/bin/bash
# 部署脚本 - 将构建好的管理后台文件上传到服务器
# 使用方法: ./deploy.sh
SERVER_IP="101.200.208.45"
USERNAME="root"
REMOTE_PATH="/data/www/emotion-museum-admin"
echo "开始部署管理后台应用到服务器..."
# 检查是否安装了npm
if ! command -v npm &> /dev/null; then
echo "❌ 错误: 未找到npm命令,请先安装Node.js"
exit 1
fi
# 执行构建(无论dist目录是否存在,都必须构建)
echo "📦 开始构建管理后台项目..."
if npm run build; then
echo "✅ 管理后台项目构建成功"
else
echo "❌ 管理后台项目构建失败,请检查代码"
exit 1
fi
# 验证dist目录是否存在
if [ ! -d "dist" ]; then
echo "❌ 错误: 构建后dist目录仍不存在,请检查构建配置"
exit 1
fi
# 检查是否安装了scp命令
if ! command -v scp &> /dev/null; then
echo "❌ 错误: 未找到scp命令,请安装OpenSSH客户端"
exit 1
fi
echo "正在上传文件到服务器 $SERVER_IP..."
# 创建远程目录(如果不存在)
echo "📁 创建远程目录..."
ssh "${USERNAME}@${SERVER_IP}" "mkdir -p ${REMOTE_PATH}"
# 上传所有文件到服务器
echo "📤 上传文件到服务器..."
if scp dist/index.html "${USERNAME}@${SERVER_IP}:${REMOTE_PATH}/" && \
scp -r dist/assets "${USERNAME}@${SERVER_IP}:${REMOTE_PATH}/"; then
# 设置文件权限
echo "🔐 设置文件权限..."
ssh "${USERNAME}@${SERVER_IP}" "chmod -R 755 ${REMOTE_PATH}"
echo "✅ 管理后台部署完成!"
echo "📱 访问地址: http://$SERVER_IP/emotion-museum-admin/"
echo "🔧 管理后台功能: AI配置管理、用户管理、数据统计等"
else
echo "❌ 部署失败,请检查:"
echo "1. 服务器IP地址是否正确"
echo "2. SSH密钥是否配置正确"
echo "3. 服务器目录权限是否正确"
exit 1
fi
+2 -2
View File
@@ -77,13 +77,13 @@
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useRoute } from 'vue-router'
import { useAdminStore } from '@/stores/admin'
import { Fold, Expand } from '@element-plus/icons-vue'
import { menuConfig } from '@/config/menu'
const route = useRoute()
const router = useRouter()
// const router = useRouter()
const adminStore = useAdminStore()
const isCollapse = ref(false)
+2 -2
View File
@@ -72,12 +72,12 @@ const routes: RouteRecordRaw[] = [
]
const router = createRouter({
history: createWebHistory(),
history: createWebHistory('/emotion-museum-admin/'),
routes
})
// 路由守卫
router.beforeEach((to, from, next) => {
router.beforeEach((to, _from, next) => {
const token = localStorage.getItem('adminToken')
if (to.path === '/login') {
+6 -5
View File
@@ -13,12 +13,13 @@ export const useAdminStore = defineStore('admin', () => {
const login = async (loginForm: AdminLoginRequest) => {
try {
const res = await loginApi(loginForm)
token.value = res.data.accessToken
adminInfo.value = res.data.adminInfo
const authData = res.data as any
token.value = authData.accessToken
adminInfo.value = authData.adminInfo
localStorage.setItem('adminToken', res.data.accessToken)
localStorage.setItem('adminRefreshToken', res.data.refreshToken)
localStorage.setItem('adminInfo', JSON.stringify(res.data.adminInfo))
localStorage.setItem('adminToken', authData.accessToken)
localStorage.setItem('adminRefreshToken', authData.refreshToken)
localStorage.setItem('adminInfo', JSON.stringify(authData.adminInfo))
ElMessage.success('登录成功')
router.push('/')
+1 -1
View File
@@ -1,4 +1,4 @@
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import axios, { AxiosInstance, AxiosResponse } from 'axios'
import { ElMessage } from 'element-plus'
import router from '@/router'
+4 -4
View File
@@ -1,6 +1,6 @@
// 表单验证规则
export const validateAccount = (rule: any, value: string, callback: any) => {
export const validateAccount = (_rule: any, value: string, callback: any) => {
if (!value) {
callback(new Error('请输入账号'))
} else if (value.length < 3 || value.length > 50) {
@@ -10,7 +10,7 @@ export const validateAccount = (rule: any, value: string, callback: any) => {
}
}
export const validatePassword = (rule: any, value: string, callback: any) => {
export const validatePassword = (_rule: any, value: string, callback: any) => {
if (!value) {
callback(new Error('请输入密码'))
} else if (value.length < 6 || value.length > 20) {
@@ -20,7 +20,7 @@ export const validatePassword = (rule: any, value: string, callback: any) => {
}
}
export const validateEmail = (rule: any, value: string, callback: any) => {
export const validateEmail = (_rule: any, value: string, callback: any) => {
if (!value) {
callback()
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
@@ -30,7 +30,7 @@ export const validateEmail = (rule: any, value: string, callback: any) => {
}
}
export const validatePhone = (rule: any, value: string, callback: any) => {
export const validatePhone = (_rule: any, value: string, callback: any) => {
if (!value) {
callback()
} else if (!/^1[3-9]\d{9}$/.test(value)) {
-4
View File
@@ -45,10 +45,6 @@
</el-button>
</el-form-item>
</el-form>
<div class="login-footer">
<p>默认账号: admin / admin123</p>
</div>
</div>
</div>
</template>
+3 -2
View File
@@ -190,8 +190,9 @@ const fetchData = async () => {
size: pagination.size
}
const res = await getAdminPage(params)
tableData.value = res.data.records
pagination.total = res.data.total
const pageData = res.data as any
tableData.value = pageData.records
pagination.total = pageData.total
} catch (error) {
console.error('获取管理员列表失败:', error)
} finally {
@@ -1181,7 +1181,7 @@ const handleTestRequest = async () => {
}
// 检查是否为流式请求
const isStreamRequest = body.stream === true
const isStreamRequest = (body as any).stream === true
if (isStreamRequest) {
// 处理流式请求
+3 -2
View File
@@ -131,8 +131,9 @@ const fetchData = async () => {
size: pagination.size
}
const res = await getUserPage(params)
tableData.value = res.data.records
pagination.total = res.data.total
const pageData = res.data as any
tableData.value = pageData.records
pagination.total = pageData.total
} catch (error) {
console.error('获取用户列表失败:', error)
} finally {
+2 -1
View File
@@ -24,5 +24,6 @@ export default defineConfig({
assetsDir: 'assets',
sourcemap: false,
chunkSizeWarningLimit: 1500
}
},
base: '/emotion-museum-admin/'
})
+276
View File
@@ -0,0 +1,276 @@
# 情绪博物馆管理后台部署说明
## 📋 概述
本文档说明如何部署情绪博物馆管理后台到服务器 `101.200.208.45`
管理后台将部署到 `/data/www/emotion-museum-admin/` 目录,通过 `http://101.200.208.45/emotion-museum-admin/` 访问。
## 🚀 快速部署
### 1. 执行部署脚本
```bash
# 进入管理后台目录
cd web-admin
# 执行部署脚本
bash deploy.sh
```
### 2. 访问管理后台
部署完成后,可以通过以下地址访问:
- **管理后台**: http://101.200.208.45/emotion-museum-admin/
- **登录页面**: http://101.200.208.45/emotion-museum-admin/login
## 📊 部署流程详解
### 自动化部署流程
1. **环境检查**: 检查 Node.js 和 npm 是否安装
2. **项目构建**: 执行 `npm run build` 构建项目
3. **文件验证**: 验证 `dist` 目录是否生成
4. **文件上传**: 使用 SCP 上传文件到服务器
5. **权限设置**: 设置文件权限为 755
6. **部署验证**: 确认文件上传成功
### 构建配置
- **构建命令**: `npm run build`
- **输出目录**: `dist/`
- **基础路径**: `/emotion-museum-admin/`
- **路由模式**: HTML5 History 模式
## 🔧 配置说明
### Nginx 配置
管理后台的 Nginx 配置已添加到 `conf/emotion-museum.conf` 文件中:
```nginx
# 管理后台应用路径
location /emotion-museum-admin/ {
alias /data/www/emotion-museum-admin/;
autoindex off;
# 处理 Vue Router 的 history 模式
try_files $uri $uri/ /emotion-museum-admin/index.html;
# HTML 文件不缓存
location ~ \.html?$ {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# 静态资源缓存 1 年
location ~ \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
expires 1y;
}
}
# 处理不带末尾斜杠的请求
location = /emotion-museum-admin {
rewrite ^(.*)$ $1/ permanent;
}
```
### 路由配置
管理后台使用 Vue Router 的 History 模式,配置了基础路径:
```typescript
const router = createRouter({
history: createWebHistory('/emotion-museum-admin/'),
routes
})
```
### Vite 配置
构建配置中设置了正确的基础路径:
```typescript
export default defineConfig({
// ...其他配置
base: '/emotion-museum-admin/',
build: {
outDir: 'dist',
assetsDir: 'assets',
sourcemap: false,
chunkSizeWarningLimit: 1500
}
})
```
## ✅ 验证部署
### 1. 检查文件是否上传成功
```bash
# SSH 连接到服务器
ssh root@101.200.208.45
# 检查文件是否存在
ls -lh /data/www/emotion-museum-admin/
```
### 2. 检查 Nginx 配置
```bash
# 测试 Nginx 配置
nginx -t
# 重新加载 Nginx
nginx -s reload
```
### 3. 访问测试
在浏览器中访问以下地址:
- http://101.200.208.45/emotion-museum-admin/
- http://101.200.208.45/emotion-museum-admin/login
## 🔄 更新部署
### 代码更新后重新部署
```bash
# 1. 进入管理后台目录
cd web-admin
# 2. 拉取最新代码(如果使用 Git)
git pull
# 3. 安装依赖(如果有新依赖)
npm install
# 4. 执行部署
bash deploy.sh
```
### 仅更新前端资源
如果只是修改了前端代码,无需重启后端服务:
```bash
# 执行部署脚本即可
bash deploy.sh
```
## 🛠️ 故障排查
### 问题 1: 构建失败
**现象**: 执行 `npm run build` 失败
**解决方案**:
```bash
# 1. 清理依赖
rm -rf node_modules package-lock.json
# 2. 重新安装依赖
npm install
# 3. 重新构建
npm run build
```
### 问题 2: 上传失败
**现象**: SCP 上传文件失败
**解决方案**:
```bash
# 1. 检查 SSH 连接
ssh root@101.200.208.45 "echo 'SSH 连接成功'"
# 2. 检查目标目录权限
ssh root@101.200.208.45 "ls -ld /data/www/"
# 3. 手动创建目录
ssh root@101.200.208.45 "mkdir -p /data/www/emotion-museum-admin"
```
### 问题 3: 访问 404
**现象**: 访问管理后台返回 404
**解决方案**:
```bash
# 1. 检查文件是否存在
ssh root@101.200.208.45 "ls -lh /data/www/emotion-museum-admin/"
# 2. 检查 Nginx 配置
ssh root@101.200.208.45 "nginx -t"
# 3. 重新加载 Nginx
ssh root@101.200.208.45 "nginx -s reload"
```
### 问题 4: 路由不工作
**现象**: 直接访问子路由返回 404
**解决方案**:
1. 确认 Nginx 配置中的 `try_files` 指令正确
2. 确认路由配置中的 `base` 路径正确
3. 清除浏览器缓存
## 📱 功能说明
管理后台包含以下功能模块:
### 1. 仪表盘
- 系统概览
- 数据统计
- 快速操作
### 2. 管理员管理
- 管理员列表
- 添加/编辑管理员
- 权限管理
### 3. 用户管理
- 用户列表
- 用户详情
- 用户统计
### 4. AI配置管理
- AI配置列表
- 配置创建/编辑
- 接口测试
- 流式响应测试
## 🔐 安全说明
### 访问控制
- 管理后台需要登录才能访问
- 使用 JWT Token 进行身份验证
- 自动跳转到登录页面
### 文件权限
- 部署文件权限设置为 755
- 静态资源可公开访问
- 敏感配置文件受保护
## 📞 支持
如有问题,请检查:
1. **部署脚本**: `web-admin/deploy.sh`
2. **Nginx 配置**: `conf/emotion-museum.conf`
3. **路由配置**: `web-admin/src/router/index.ts`
4. **构建配置**: `web-admin/vite.config.ts`
---
**最后更新**: 2025-10-30
**版本**: 1.0
**状态**: ✅ 已完成