fix: 根据角色隐藏无权限的侧边栏菜单

- 学员角色隐藏数据分析、管理者中心、系统管理菜单
- 管理员和管理者保持所有菜单可见

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yuliang_guo
2026-02-05 12:01:39 +08:00
parent 8224dbd43c
commit 3a238f810c
3 changed files with 257 additions and 2 deletions

68
backend/.env.mst Normal file
View File

@@ -0,0 +1,68 @@
# 美生堂生产环境配置
APP_NAME="美生堂-考培练系统"
APP_VERSION="1.0.0"
DEBUG=false
HOST=0.0.0.0
PORT=8000
# 数据库配置 - 共享MySQL实例
DATABASE_URL=mysql+aiomysql://root:ProdMySQL2025%21%40%23@prod-mysql:3306/kaopeilian_mst?charset=utf8mb4
MYSQL_HOST=prod-mysql
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_PASSWORD=ProdMySQL2025!@#
MYSQL_DATABASE=kaopeilian_mst
# Redis配置
REDIS_URL=redis://mst-redis:6379/0
REDIS_HOST=mst-redis
REDIS_PORT=6379
REDIS_DB=0
# 安全配置
SECRET_KEY=mst_644f31c8591e8a4111fed65847b4185e66171288323fb18445713dba4965de18
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=480
REFRESH_TOKEN_EXPIRE_DAYS=7
# CORS配置
CORS_ORIGINS=["https://mst.kpl.ireborn.com.cn", "http://mst.kpl.ireborn.com.cn"]
# 日志配置
LOG_LEVEL=INFO
LOG_FORMAT=json
# 文件上传配置
UPLOAD_MAX_SIZE=10485760
UPLOAD_ALLOWED_TYPES=["image/jpeg", "image/png", "application/pdf", "audio/mpeg", "audio/wav", "audio/webm"]
UPLOAD_DIR=uploads
# Coze OAuth配置
COZE_OAUTH_CLIENT_ID=1114009328887
COZE_OAUTH_PUBLIC_KEY_ID=GGs9pw0BDHx2k9vGGehUyRgKV-PyUWLBncDs-YNNN_I
COZE_OAUTH_PRIVATE_KEY_PATH=/app/secrets/coze_private_key.pem
COZE_WORKSPACE_ID=7461992708538974244
COZE_PRACTICE_BOT_ID=7560643598174683145
# Coze 播课配置
COZE_BROADCAST_WORKFLOW_ID=7577978749833838602
COZE_BROADCAST_SPACE_ID=7474971491470688296
COZE_BROADCAST_BOT_ID=7560643598174683145
# AI 服务配置
AI_PRIMARY_API_KEY=sk-9yMCXjRGANbacz20kJY8doSNy6Rf446aYwmgGIuIXQ7DAyBw
AI_PRIMARY_BASE_URL=https://4sapi.com/v1
AI_FALLBACK_API_KEY=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
AI_FALLBACK_BASE_URL=https://openrouter.ai/api/v1
AI_DEFAULT_MODEL=gemini-3-flash-preview
AI_TIMEOUT=120
# 租户配置(用于多租户部署)
TENANT_CODE=mst
# 管理库连接配置(用于从 tenant_configs 表读取配置)
ADMIN_DB_HOST=prod-mysql
ADMIN_DB_PORT=3306
ADMIN_DB_USER=root
ADMIN_DB_PASSWORD=ProdMySQL2025!@#
ADMIN_DB_NAME=kaopeilian_admin

View File

@@ -24,6 +24,7 @@
| fw | 飞沃 | https://fw.ireborn.com.cn | 3014 | 8014 |
| ex | 恩喜成都总院 | https://ex.ireborn.com.cn | 3015 | 8015 |
| cxw | 崔曦文 | https://cxw.kpl.ireborn.com.cn | 3016 | 8016 |
| mst | 美生堂 | https://mst.kpl.ireborn.com.cn | 3017 | 8017 |
---
@@ -286,7 +287,190 @@ docker ps --format 'table {{.Names}}\t{{.Status}}'
---
## 十、Git 仓库配置
## 十、新租户部署流程
> 以下是添加新生产租户的完整步骤
### 10.1 端口分配规则
| 租户序号 | 前端端口 | 后端端口 | Redis端口 |
|----------|----------|----------|-----------|
| 1 (hua) | 3010 | 8010 | 6390 |
| 2 (yy) | 3011 | 8011 | 6391 |
| ... | 301x | 801x | 639x |
| 8 (mst) | 3017 | 8017 | 6397 |
### 10.2 部署步骤
#### 步骤1创建 ENV 配置文件
`backend/.env.{tenant}` 创建环境变量文件,参考 `.env.ex` 模板:
```bash
# 必须修改的配置项
APP_NAME="租户名称-考培练系统"
DATABASE_URL=mysql+aiomysql://root:ProdMySQL2025%21%40%23@prod-mysql:3306/kaopeilian_{tenant}?charset=utf8mb4
MYSQL_DATABASE=kaopeilian_{tenant}
REDIS_URL=redis://{tenant}-redis:6379/0
REDIS_HOST={tenant}-redis
SECRET_KEY={生成唯一密钥}
CORS_ORIGINS=["https://{tenant}.kpl.ireborn.com.cn", "http://{tenant}.kpl.ireborn.com.cn"]
TENANT_CODE={tenant}
# Coze 配置(每个租户需要单独配置 Bot
COZE_PRACTICE_BOT_ID={租户专用Bot ID}
```
#### 步骤2创建数据库
```bash
# SSH 登录服务器
ssh root@120.79.247.16
# 创建数据库
docker exec prod-mysql mysql -uroot -p'ProdMySQL2025!@#' -e "
CREATE DATABASE IF NOT EXISTS kaopeilian_{tenant}
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
"
# 导入基础数据(从现有租户复制结构)
docker exec prod-mysql mysqldump -uroot -p'ProdMySQL2025!@#' --no-data kaopeilian_ex | \
docker exec -i prod-mysql mysql -uroot -p'ProdMySQL2025!@#' kaopeilian_{tenant}
```
#### 步骤3创建必要目录
```bash
# 在服务器上执行
mkdir -p /data/prod-envs/logs-{tenant}
mkdir -p /data/kaopeilian/uploads/{tenant}
mkdir -p /data/redis-data/{tenant}
```
#### 步骤4更新 docker-compose.prod-multi.yml
`/data/prod-envs/docker-compose.prod-multi.yml` 添加新租户的服务定义:
```yaml
# ============================================
# 租户名称 ({tenant}.kpl.ireborn.com.cn)
# ============================================
{tenant}-frontend:
build:
context: ./kaopeilian-frontend
dockerfile: Dockerfile
args:
- NODE_ENV=production
- VITE_API_BASE_URL=https://{tenant}.kpl.ireborn.com.cn
- VITE_WS_BASE_URL=wss://{tenant}.kpl.ireborn.com.cn
- VITE_USE_MOCK_DATA=false
container_name: {tenant}-frontend
restart: unless-stopped
environment:
- TZ=Asia/Shanghai
ports:
- "{前端端口}:80"
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
networks:
- prod-network
depends_on:
- {tenant}-backend
labels:
- "com.centurylinklabs.watchtower.enable=false"
{tenant}-backend:
image: crpi-na6dit5kd0bonqed.cn-guangzhou.personal.cr.aliyuncs.com/ireborn/kaopeilian-backend:main
container_name: {tenant}-backend
restart: unless-stopped
env_file:
- ./kaopeilian-backend/.env.{tenant}
environment:
- TZ=Asia/Shanghai
- PYTHONPATH=/app
ports:
- "{后端端口}:8000"
volumes:
- /root/aiedu/kaopeilian-backend/app:/app/app
- /data/kaopeilian/uploads/{tenant}:/app/uploads
- /data/prod-envs/logs-{tenant}:/app/logs
- /data/prod-envs/secrets:/app/secrets:ro
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
networks:
- prod-network
depends_on:
prod-mysql:
condition: service_healthy
{tenant}-redis:
condition: service_healthy
labels:
- "com.centurylinklabs.watchtower.enable=false"
{tenant}-redis:
image: redis:7.2-alpine
container_name: {tenant}-redis
restart: unless-stopped
environment:
- TZ=Asia/Shanghai
ports:
- "{Redis端口}:6379"
volumes:
- /data/redis-data/{tenant}:/data
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
networks:
- prod-network
command: redis-server --appendonly yes --maxmemory 128mb --maxmemory-policy allkeys-lru
```
#### 步骤5创建 MinIO Bucket
```bash
# 在服务器上执行
mc mb kpl/kpl-{tenant}
mc anonymous set download kpl/kpl-{tenant}
```
#### 步骤6配置 Nginx 反向代理
在 Nginx 配置中添加新租户的域名解析(通常在 SCRM 服务器 120.79.242.43)。
#### 步骤7启动服务
```bash
cd /data/prod-envs
docker compose -f docker-compose.prod-multi.yml up -d {tenant}-redis {tenant}-backend {tenant}-frontend
```
#### 步骤8初始化数据
```bash
# 创建管理员账户
docker exec {tenant}-backend python3 -c "
from app.db.init_db import init_admin_user
import asyncio
asyncio.run(init_admin_user())
"
```
### 10.3 环境变量说明
| 变量名 | 说明 | 示例 |
|--------|------|------|
| `APP_NAME` | 应用显示名称 | "美生堂-考培练系统" |
| `DATABASE_URL` | 数据库连接URL | mysql+aiomysql://... |
| `REDIS_URL` | Redis连接URL | redis://{tenant}-redis:6379/0 |
| `SECRET_KEY` | JWT密钥64位随机字符串 | 使用 `openssl rand -hex 32` 生成 |
| `CORS_ORIGINS` | 允许的跨域来源 | ["https://{tenant}.kpl.ireborn.com.cn"] |
| `TENANT_CODE` | 租户代码(小写字母) | mst |
| `COZE_PRACTICE_BOT_ID` | Coze陪练Bot ID | 需要在Coze平台创建 |
| `COZE_BROADCAST_BOT_ID` | Coze播课Bot ID | 可共用 |
---
## 十一、Git 仓库配置
```bash
# 查看远程仓库

View File

@@ -401,7 +401,10 @@ const menuRoutes = computed(() => {
if (route.path === '/admin') {
return userRole === 'admin'
}
// 数据分析:所有登录用户可见(但子菜单会进一步过滤
// 数据分析:仅 admin 和 manager 可见(学员隐藏
if (route.path === '/analysis') {
return userRole === 'admin' || userRole === 'manager'
}
return true
}