Compare commits

...

3 Commits

Author SHA1 Message Date
xiao12feng8
389d291397 部署: 部署到服务器测试 2026-02-05 11:28:34 +08:00
xiao12feng8
345ba0f86d 项目:启动和配置指南 2026-02-05 10:06:07 +08:00
xiao12feng8
9190872fcb 样式:调整好 2026-02-05 09:35:22 +08:00
83 changed files with 2764 additions and 1767 deletions

View File

@ -1,199 +0,0 @@
# PHP 服务连接问题解决方案
## 问题描述
Python 后端无法连接到 PHP 服务,报错:
```
HTTPConnectionPool(host='192.168.1.164', port=30100): Read timed out
```
## 已完成的修复
### 1. 配置修正
- ✅ 修改 `lover/deps.py`:移除硬编码 IP从配置读取
- ✅ 修改 `lover/config.py`:默认地址改为 `127.0.0.1:30100`
- ✅ 修改 `.env`:端口从 `8080` 改为 `30100`
- ✅ 减少超时时间:从 5 秒改为 3 秒
- ✅ 改进错误处理:区分超时和连接错误
### 2. 启动脚本优化
- ✅ 使用 `router.php` 而不是 `-t .`
- ✅ 添加端口清理逻辑,自动终止占用端口的旧进程
- ✅ 添加等待时间,确保服务完全启动
### 3. 测试工具
创建了 `xunifriend_RaeeC/public/test_api.php` 用于测试:
- `/test_api.php` - 测试 PHP 服务器基本响应
- `/test_db` - 测试数据库连接
## 当前问题分析
### PHP 服务器状态
```
端口 30100 已被监听(进程 31592, 16636
但是请求超时,无法获得响应
```
### 可能的原因
1. **数据库连接问题**
- PHP 应用可能在启动时尝试连接数据库
- 如果数据库连接失败或慢,会导致请求超时
- 检查 `xunifriend_RaeeC/application/database.php` 配置
2. **PHP 内置服务器限制**
- PHP 内置服务器是单线程的
- 如果有请求阻塞,后续请求会超时
- 建议使用 Apache 或 Nginx + PHP-FPM
3. **应用初始化问题**
- ThinkPHP 框架初始化可能有问题
- 检查 `xunifriend_RaeeC/application/admin/command/Install/install.lock` 是否存在
4. **路由配置问题**
- API 路由可能未正确配置
- 检查 `xunifriend_RaeeC/application/route.php`
## 解决步骤
### 步骤 1: 测试 PHP 服务器基本功能
```cmd
# 在浏览器或命令行测试
curl http://127.0.0.1:30100/test_api.php
```
预期响应:
```json
{
"code": 1,
"msg": "PHP 服务器运行正常",
"time": 1738665600,
"data": {
"php_version": "8.0.0",
"server_time": "2026-02-04 19:00:00"
}
}
```
### 步骤 2: 测试数据库连接
```cmd
curl http://127.0.0.1:30100/test_db
```
如果数据库连接失败,检查:
- MySQL 是否运行
- `xunifriend_RaeeC/application/database.php` 配置是否正确
- 数据库用户名密码是否正确
### 步骤 3: 测试实际 API
```cmd
# 使用有效的 token 测试
curl -H "token: YOUR_TOKEN_HERE" http://127.0.0.1:30100/api/user_basic/get_user_basic
```
### 步骤 4: 检查 PHP 错误日志
PHP 内置服务器的错误会显示在启动窗口中,查看是否有:
- 数据库连接错误
- 文件权限错误
- PHP 语法错误
- 缺少扩展
## 临时解决方案
### 方案 1: 使用开发环境兜底(已实现)
Python 后端在开发环境下,如果 PHP 连接失败,会自动使用测试用户:
```python
# 在 lover/deps.py 中
if settings.APP_ENV == "development" and settings.DEBUG:
logger.warning(f"开发环境token 验证失败({e.detail}),使用测试用户")
return AuthedUser(id=70, reg_step=2, gender=0, nickname="test-user", token="")
```
### 方案 2: 直接使用数据库认证
修改 Python 后端,不依赖 PHP API直接查询数据库
```python
# 在 lover/deps.py 中添加
def _fetch_user_from_db(token: str) -> Optional[dict]:
"""直接从数据库获取用户信息"""
from lover.db import get_db
db = next(get_db())
user = db.execute(
"SELECT * FROM fa_user WHERE token = :token",
{"token": token}
).fetchone()
return dict(user) if user else None
```
### 方案 3: 重启 PHP 服务
```cmd
# 使用更新后的启动脚本,会自动清理旧进程
启动项目.bat
```
## 长期解决方案
### 推荐:使用 Nginx + PHP-FPM
PHP 内置服务器不适合生产环境,建议:
1. 安装 Nginx
2. 配置 PHP-FPM
3. 配置 Nginx 反向代理
配置示例:
```nginx
server {
listen 30100;
server_name localhost;
root C:/Users/Administrator/Desktop/Project/AI_GirlFriend/xunifriend_RaeeC/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
```
## 调试命令
### 查看端口占用
```cmd
netstat -ano | findstr :30100
```
### 终止进程
```cmd
taskkill /F /PID <进程ID>
```
### 测试 PHP 配置
```cmd
D:\2_part\php-8.0.0-Win32-vs16-x64\php.exe -v
D:\2_part\php-8.0.0-Win32-vs16-x64\php.exe -m # 查看已安装的扩展
```
### 手动启动 PHP 服务器(用于调试)
```cmd
cd xunifriend_RaeeC\public
D:\2_part\php-8.0.0-Win32-vs16-x64\php.exe -S 0.0.0.0:30100 router.php
```
## 下一步行动
1. **立即测试**:运行 `curl http://127.0.0.1:30100/test_api.php`
2. **检查数据库**:确认 MySQL 正在运行
3. **查看日志**:检查 PHP 启动窗口的错误信息
4. **重启服务**:使用更新后的 `启动项目.bat`
## 文件修改记录
- `lover/deps.py` - 改进错误处理和超时设置
- `lover/config.py` - 修正默认地址
- `.env` - 修正端口配置
- `启动项目.bat` - 添加端口清理和 router.php
- `xunifriend_RaeeC/public/test_api.php` - 新增测试脚本

View File

@ -1,161 +0,0 @@
@echo off
chcp 65001 >nul
title PHP 开发服务器
:MENU
cls
echo ========================================
echo PHP 开发服务器启动脚本 (高级版)
echo ========================================
echo.
echo 请选择启动模式:
echo.
echo [1] 快速启动 (端口 8080)
echo [2] 自定义端口
echo [3] 查看 PHP 信息
echo [4] 退出
echo.
echo ========================================
set /p choice=请输入选项 (1-4):
if "%choice%"=="1" goto QUICK_START
if "%choice%"=="2" goto CUSTOM_PORT
if "%choice%"=="3" goto PHP_INFO
if "%choice%"=="4" goto END
echo [错误] 无效选项,请重新选择
timeout /t 2 >nul
goto MENU
:QUICK_START
set PORT=8080
goto START_SERVER
:CUSTOM_PORT
echo.
set /p PORT=请输入端口号 (例如: 8080):
if "%PORT%"=="" (
echo [错误] 端口号不能为空
timeout /t 2 >nul
goto MENU
)
goto START_SERVER
:START_SERVER
cls
echo ========================================
echo 正在启动 PHP 开发服务器...
echo ========================================
echo.
REM 设置 PHP 路径
set PHP_PATH=D:\2_part\php-8.0.0-Win32-vs16-x64\php.exe
REM 检查 PHP 是否存在
if not exist "%PHP_PATH%" (
echo [错误] PHP 未找到: %PHP_PATH%
echo.
echo 请修改脚本中的 PHP_PATH 变量
pause
goto MENU
)
REM 显示 PHP 版本
echo [信息] PHP 版本:
"%PHP_PATH%" -v | findstr /C:"PHP"
echo.
REM 设置项目根目录
set PROJECT_ROOT=%~dp0xunifriend_RaeeC\public
REM 检查项目目录是否存在
if not exist "%PROJECT_ROOT%" (
echo [错误] 项目目录未找到: %PROJECT_ROOT%
pause
goto MENU
)
REM 获取本机 IP 地址
for /f "tokens=2 delims=:" %%a in ('ipconfig ^| findstr /C:"IPv4"') do (
set LOCAL_IP=%%a
goto :IP_FOUND
)
:IP_FOUND
set LOCAL_IP=%LOCAL_IP: =%
REM 设置服务器参数
set HOST=0.0.0.0
echo [信息] 项目目录: %PROJECT_ROOT%
echo [信息] 服务器端口: %PORT%
echo.
echo ========================================
echo 访问地址:
echo ========================================
echo.
echo [本地访问]
echo http://127.0.0.1:%PORT%
echo http://localhost:%PORT%
echo.
echo [局域网访问]
echo http://%LOCAL_IP%:%PORT%
echo.
echo [管理后台]
echo http://127.0.0.1:%PORT%/admin
echo.
echo ========================================
echo.
echo [提示] 按 Ctrl+C 停止服务器
echo.
REM 询问是否打开浏览器
set /p OPEN_BROWSER=是否自动打开浏览器? (Y/N):
if /i "%OPEN_BROWSER%"=="Y" (
echo [信息] 正在打开浏览器...
start http://127.0.0.1:%PORT%
)
echo.
echo [信息] 服务器启动中...
echo ========================================
echo.
REM 启动 PHP 内置服务器
cd /d "%PROJECT_ROOT%"
"%PHP_PATH%" -S %HOST%:%PORT% -t .
pause
goto MENU
:PHP_INFO
cls
echo ========================================
echo PHP 信息
echo ========================================
echo.
set PHP_PATH=D:\2_part\php-8.0.0-Win32-vs16-x64\php.exe
if not exist "%PHP_PATH%" (
echo [错误] PHP 未找到: %PHP_PATH%
pause
goto MENU
)
echo [PHP 版本]
"%PHP_PATH%" -v
echo.
echo [PHP 配置文件]
"%PHP_PATH%" --ini
echo.
echo [已加载的扩展]
"%PHP_PATH%" -m
echo.
pause
goto MENU
:END
echo.
echo 感谢使用!
timeout /t 1 >nul
exit

View File

@ -209,8 +209,12 @@
})
},
connectWebSocket() {
// baseURLPy WebSocket URL
let wsUrl = baseURLPy.replace('http://', 'ws://').replace('https://', 'wss://') + '/voice/call'
console.log('WebSocket URL:', wsUrl)
this.socketTask = uni.connectSocket({
url: 'wss://lovers.shandonghuixing.com/voice/call',
url: wsUrl,
header: {
"content-type": "application/json",
'Authorization': 'Bearer ' + uni.getStorageSync("token") || ""

View File

@ -143,25 +143,28 @@
<image class="home-header-icon" src="/static/images/replacement_switch.png" mode="aspectFit"></image>
<text class="home-header-text">装扮设置</text>
</view>
<view class="home-header-spacer"></view>
<view class="home-header-btn" @click="todynamics">
<image class="home-header-icon" src="/static/images/dynamics_logo.png" mode="aspectFit"></image>
<text class="home-header-text">朋友圈</text>
</view>
<view class="home-header-btn" @click="todiary">
<image class="home-header-icon" src="/static/images/diary_a1.png" mode="aspectFit"></image>
<text class="home-header-text">日记</text>
</view>
<view class="home-header-btn" @click="tophone">
<image class="home-header-icon" src="/static/images/index_phone.png" mode="aspectFit"></image>
<text class="home-header-text">语音通话</text>
</view>
<view class="home-header-btn" @click="tovoicecall">
<image class="home-header-icon" src="/static/images/index_phone.png" mode="aspectFit"></image>
<text class="home-header-text">视频通话</text>
</view>
<view class="home-header-btn" @click="tointimacy">
<image class="home-header-icon" src="/static/images/index_intimate.png" mode="aspectFit"></image>
<text class="home-header-text">邀请入驻</text>
</view>
</view>
<!-- 选择互动对象 -->
<view class="home-title">
<text class="home-title-icon"></text>
<text class="home-title-text">选择一位互动对象</text>
<text class="home-title-icon"></text>
<text class="home-title-more" @click="toreplacement">搜索更多</text>
</view>
<!-- 主卡片区域 -->
<view class="home-card">
<view class="home-card-inner">
@ -2059,21 +2062,23 @@
});
},
tophone() {
// if (this.getBobbiesList.level >= 2) {
// uni.navigateTo({
// url: '/pages/chat/phone'
// });
// } else {
// uni.showToast({
// title: 'Lv.2',
// icon: 'none',
// position: 'top'
// });
// }
console.log('tophone 方法被调用');
uni.navigateTo({
url: '/pages/chat/phone'
});
},
todiary() {
console.log('todiary 方法被调用');
uni.navigateTo({
url: '/pages/chat/diary'
});
},
tovoicecall() {
console.log('tovoicecall 方法被调用');
uni.navigateTo({
url: '/pages/chat/voiceCall'
});
},
togift() {
uni.navigateTo({
url: '/pages/index/gift'
@ -2226,12 +2231,30 @@
OutfitList({}).then(res => {
if (res && res.code == 1 && res.data) {
this.homeLooksList = res.data.looks || [];
//
if (this.homeLooksList.length > 0) {
// 使
const currentLook = this.homeLooksList.find(look => look.is_current);
if (currentLook) {
// 使
this.selectedLookId = currentLook.id;
this.currentLookImageUrl = currentLook.image_url;
this.chatLoverAvatar = currentLook.image_url;
//
if (this.loverBasicList) {
this.loverBasicList.image_url = currentLook.image_url;
}
} else if (this.homeLooksList.length > 0) {
//
this.selectedLookId = this.homeLooksList[0].id;
this.currentLookImageUrl = this.homeLooksList[0].image_url;
//
this.chatLoverAvatar = this.homeLooksList[0].image_url;
//
if (this.loverBasicList) {
this.loverBasicList.image_url = this.homeLooksList[0].image_url;
}
}
}
}).catch(err => {
@ -2243,6 +2266,12 @@
switchLook(look) {
if (!look || !look.id) return;
//
this.selectedLookId = look.id;
if (this.loverBasicList) {
this.loverBasicList.image_url = look.image_url;
}
// API
uni.request({
url: baseURLPy + '/outfit/looks/use/' + look.id,
@ -2252,21 +2281,16 @@
},
success: (res) => {
if (res.data && res.data.code === 1) {
this.selectedLookId = look.id;
this.currentLookImageUrl = look.image_url;
//
this.chatLoverAvatar = look.image_url;
//
this.loverBasic();
uni.showToast({
title: '形象切换成功',
icon: 'success',
duration: 1500
});
//
} else {
//
this.loverBasic();
uni.showToast({
title: res.data.msg || '切换失败',
icon: 'none',
@ -2276,6 +2300,8 @@
},
fail: (err) => {
console.error('切换形象失败:', err);
//
this.loverBasic();
uni.showToast({
title: '切换失败,请重试',
icon: 'none',
@ -5110,21 +5136,33 @@
.home-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 0;
margin-bottom: 20rpx;
overflow-x: auto;
overflow-y: hidden;
gap: 15rpx;
/* 隐藏滚动条 */
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE 10+ */
}
.home-header::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
.home-header-btn {
display: flex;
flex-direction: column;
align-items: center;
gap: 8rpx;
padding: 10rpx 15rpx;
justify-content: center;
gap: 6rpx;
padding: 12rpx 16rpx;
background: rgba(255, 255, 255, 0.8);
border-radius: 16rpx;
transition: all 0.3s ease;
box-shadow: 0 2rpx 8rpx rgba(159, 71, 255, 0.1);
min-width: 100rpx;
flex-shrink: 0;
}
.home-header-btn:active {
@ -5133,17 +5171,16 @@
}
.home-header-icon {
width: 40rpx;
height: 40rpx;
width: 44rpx;
height: 44rpx;
object-fit: contain;
}
.home-header-text {
font-size: 22rpx;
color: #666;
}
.home-header-spacer {
flex: 1;
white-space: nowrap;
text-align: center;
}
/* 选择互动对象标题 */

View File

@ -1,6 +1,8 @@
// Windows 本地开发 - 混合架构
export const baseURL = 'http://192.168.1.164:30100' // PHP 处理用户管理和界面
export const baseURLPy = 'http://192.168.1.164:30101' // FastAPI 处理 AI 功能
// export const baseURL = 'http://192.168.1.164:30100' // PHP 处理用户管理和界面
export const baseURL = 'http://1.15.149.240:30100' // PHP 处理用户管理和界面
// export const baseURLPy = 'http://192.168.1.164:30101' // FastAPI 处理 AI 功能
export const baseURLPy = 'http://1.15.149.240:30101' // FastAPI 处理 AI 功能
// 远程服务器 - 需要时取消注释
// export const baseURL = 'http://1.15.149.240:30100'

View File

@ -1,263 +0,0 @@
@echo off
chcp 65001 >nul
title AI 女友项目 - 启动服务 (改进版)
REM ==========================================
REM 配置区域
REM ==========================================
set PHP_PATH=D:\2_part\php-8.0.0-Win32-vs16-x64\php.exe
set PHP_PORT=30100
set PYTHON_PORT=30101
REM ==========================================
REM 检查 MySQL 是否运行
REM ==========================================
cls
echo.
echo ╔════════════════════════════════════╗
echo ║ AI 女友项目 - 启动服务 ║
echo ╚════════════════════════════════════╝
echo.
echo [检查] 正在检查 MySQL 服务...
netstat -ano | findstr :3306 >nul 2>&1
if errorlevel 1 (
echo [警告] MySQL 服务未运行(端口 3306 未监听)
echo.
echo 请先启动 MySQL 服务,否则 PHP 应用可能无法正常工作
echo.
set /p CONTINUE=是否继续启动?(Y/N):
if /i not "!CONTINUE!"=="Y" (
echo.
echo 已取消启动
pause
exit /b 1
)
) else (
echo [成功] MySQL 服务正在运行
)
echo.
REM ==========================================
REM 清理旧的服务进程
REM ==========================================
echo [清理] 正在检查并清理旧的服务进程...
echo.
REM 查找占用 30100 端口的进程并终止
echo [清理] 检查端口 30100...
for /f "tokens=5" %%a in ('netstat -ano ^| findstr :30100 2^>nul') do (
echo [清理] 终止进程 PID: %%a
taskkill /F /PID %%a >nul 2>&1
)
REM 查找占用 30101 端口的进程并终止
echo [清理] 检查端口 30101...
for /f "tokens=5" %%a in ('netstat -ano ^| findstr :30101 2^>nul') do (
echo [清理] 终止进程 PID: %%a
taskkill /F /PID %%a >nul 2>&1
)
echo.
echo [成功] 端口清理完成
echo.
REM 等待端口完全释放
echo [等待] 等待端口释放3秒...
timeout /t 3 >nul
echo.
REM ==========================================
REM 检查 PHP
REM ==========================================
echo [检查] 正在检查 PHP...
if not exist "%PHP_PATH%" (
echo [错误] PHP 未找到: %PHP_PATH%
echo.
echo 请修改脚本中的 PHP_PATH 变量
echo.
pause
exit /b 1
)
"%PHP_PATH%" -v >nul 2>&1
if errorlevel 1 (
echo [错误] PHP 无法运行
pause
exit /b 1
)
echo [成功] PHP 已就绪
echo.
REM ==========================================
REM 检查 Python
REM ==========================================
echo [检查] 正在检查 Python...
python --version >nul 2>&1
if errorlevel 1 (
echo [错误] Python 未找到或未添加到 PATH
echo.
pause
exit /b 1
)
echo [成功] Python 已就绪
echo.
REM ==========================================
REM 检查项目目录
REM ==========================================
echo [检查] 正在检查项目目录...
if not exist "%~dp0xunifriend_RaeeC\public" (
echo [错误] PHP 项目目录未找到
pause
exit /b 1
)
if not exist "%~dp0lover" (
echo [错误] Python 项目目录未找到
pause
exit /b 1
)
echo [成功] 项目目录已就绪
echo.
REM ==========================================
REM 获取本机 IP
REM ==========================================
for /f "tokens=2 delims=:" %%a in ('ipconfig ^| findstr /C:"IPv4"') do (
set LOCAL_IP=%%a
goto :IP_FOUND
)
:IP_FOUND
set LOCAL_IP=%LOCAL_IP: =%
REM ==========================================
REM 显示启动信息
REM ==========================================
cls
echo.
echo ╔════════════════════════════════════╗
echo ║ AI 女友项目 - 启动服务 ║
echo ╚════════════════════════════════════╝
echo.
echo 准备启动以下服务:
echo.
echo [PHP 服务器]
echo → 端口: %PHP_PORT%
echo → 本地: http://127.0.0.1:%PHP_PORT%
echo → 测试: http://127.0.0.1:%PHP_PORT%/test_api.php
echo → 局域网: http://%LOCAL_IP%:%PHP_PORT%
echo.
echo [Python 后端]
echo → 端口: %PYTHON_PORT%
echo → 本地: http://127.0.0.1:%PYTHON_PORT%
echo → 局域网: http://%LOCAL_IP%:%PYTHON_PORT%
echo.
echo ────────────────────────────────────
echo.
echo 按任意键开始启动...
pause >nul
REM ==========================================
REM 启动 PHP 服务器(使用 router.php
REM ==========================================
cls
echo.
echo [1/2] 启动 PHP 服务器...
echo.
start "PHP 服务器 - 端口 %PHP_PORT%" cmd /k "title PHP 服务器 - 端口 %PHP_PORT% && cd /d "%~dp0xunifriend_RaeeC\public" && echo [PHP 服务器] 正在启动... && echo [PHP 服务器] 端口: %PHP_PORT% && echo [PHP 服务器] 访问: http://127.0.0.1:%PHP_PORT% && echo [PHP 服务器] 测试: http://127.0.0.1:%PHP_PORT%/test_api.php && echo. && "%PHP_PATH%" -S 0.0.0.0:%PHP_PORT% router.php"
echo [成功] PHP 服务器已启动
echo.
REM 等待 5 秒让 PHP 完全启动
echo 等待 PHP 服务器启动5秒...
timeout /t 5 >nul
REM ==========================================
REM 测试 PHP 服务器
REM ==========================================
echo.
echo [测试] 正在测试 PHP 服务器...
echo.
powershell -Command "try { $response = Invoke-WebRequest -Uri 'http://127.0.0.1:%PHP_PORT%/test_api.php' -TimeoutSec 5; if ($response.StatusCode -eq 200) { Write-Host '[成功] PHP 服务器响应正常' -ForegroundColor Green } else { Write-Host '[警告] PHP 服务器响应异常' -ForegroundColor Yellow } } catch { Write-Host '[错误] PHP 服务器无响应' -ForegroundColor Red; Write-Host $_.Exception.Message -ForegroundColor Red }"
echo.
set /p CONTINUE_PYTHON=PHP 服务器已启动,是否继续启动 Python 后端?(Y/N):
if /i not "%CONTINUE_PYTHON%"=="Y" (
echo.
echo 已取消 Python 后端启动
echo.
echo 按任意键退出...
pause >nul
exit /b 0
)
REM ==========================================
REM 启动 Python 后端
REM ==========================================
echo.
echo [2/2] 启动 Python 后端...
echo.
start "Python 后端 - 端口 %PYTHON_PORT%" cmd /k "title Python 后端 - 端口 %PYTHON_PORT% && cd /d "%~dp0" && echo [Python 后端] 正在启动... && echo [Python 后端] 端口: %PYTHON_PORT% && echo [Python 后端] 访问: http://127.0.0.1:%PYTHON_PORT% && echo [Python 后端] API 文档: http://127.0.0.1:%PYTHON_PORT%/docs && echo. && python -m uvicorn lover.main:app --host 0.0.0.0 --port %PYTHON_PORT% --reload"
echo [成功] Python 后端已启动
echo.
REM 等待 3 秒让 Python 完全启动
echo 等待 Python 后端启动3秒...
timeout /t 3 >nul
REM ==========================================
REM 显示完成信息
REM ==========================================
cls
echo.
echo ╔════════════════════════════════════╗
echo ║ 启动成功! ║
echo ╚════════════════════════════════════╝
echo.
echo [PHP 服务器] ✓ 已启动
echo → http://127.0.0.1:%PHP_PORT%
echo → http://127.0.0.1:%PHP_PORT%/test_api.php (测试)
echo → http://127.0.0.1:%PHP_PORT%/admin
echo → http://%LOCAL_IP%:%PHP_PORT%
echo.
echo [Python 后端] ✓ 已启动
echo → http://127.0.0.1:%PYTHON_PORT%
echo → http://127.0.0.1:%PYTHON_PORT%/docs
echo → http://%LOCAL_IP%:%PYTHON_PORT%
echo.
echo ────────────────────────────────────
echo.
echo 提示:
echo • 两个服务已在独立窗口中启动
echo • 可以在窗口中查看运行日志
echo • 关闭对应窗口可停止服务
echo • 如果 PHP API 超时,请检查 MySQL 是否运行
echo.
echo 按任意键打开浏览器测试...
pause >nul
REM ==========================================
REM 打开浏览器测试
REM ==========================================
start http://127.0.0.1:%PHP_PORT%/test_api.php
timeout /t 1 >nul
start http://127.0.0.1:%PYTHON_PORT%/docs
echo.
echo 浏览器已打开!
echo.
echo 按任意键退出(不影响服务运行)...
pause >nul
exit

View File

@ -0,0 +1,277 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
图片迁移到新 OSS 存储桶
集成配置和上传功能
"""
import os
import re
import oss2
from pathlib import Path
# 本地图片目录
GIFT_DIR = 'public/images/gifts'
OUTFIT_DIR = 'public/images/outfits'
# OSS 上传路径(保持与数据库一致)
OSS_GIFT_PREFIX = 'uploads/gifts/'
OSS_OUTFIT_PREFIX = 'uploads/outfit/'
class OSSMigrator:
def __init__(self):
self.config = {}
self.bucket = None
def get_input(self, prompt, default=None):
"""获取用户输入"""
if default:
prompt = f"{prompt} [{default}]: "
else:
prompt = f"{prompt}: "
value = input(prompt).strip()
return value if value else default
def validate_endpoint(self, endpoint):
"""验证 Endpoint 格式"""
endpoint = endpoint.replace('https://', '').replace('http://', '')
return endpoint
def configure(self):
"""配置新 OSS 信息"""
print("=" * 60)
print("配置新的 OSS 存储桶")
print("=" * 60)
print("\n请输入新的 OSS 配置信息:\n")
# 获取配置信息
self.config['access_key_id'] = self.get_input("Access Key ID")
if not self.config['access_key_id']:
print("✗ Access Key ID 不能为空")
return False
self.config['access_key_secret'] = self.get_input("Access Key Secret")
if not self.config['access_key_secret']:
print("✗ Access Key Secret 不能为空")
return False
self.config['bucket_name'] = self.get_input("Bucket 名称")
if not self.config['bucket_name']:
print("✗ Bucket 名称不能为空")
return False
self.config['endpoint'] = self.get_input("Endpoint", "oss-cn-hangzhou.aliyuncs.com")
self.config['endpoint'] = self.validate_endpoint(self.config['endpoint'])
# 显示配置摘要
print("\n" + "=" * 60)
print("配置摘要")
print("=" * 60)
print(f"Access Key ID: {self.config['access_key_id'][:8]}...")
print(f"Access Key Secret: {self.config['access_key_secret'][:8]}...")
print(f"Bucket 名称: {self.config['bucket_name']}")
print(f"Endpoint: {self.config['endpoint']}")
print(f"CDN 域名: https://{self.config['bucket_name']}.{self.config['endpoint']}")
# 确认
confirm = self.get_input("\n确认配置?(y/n)", "y")
if confirm.lower() != 'y':
print("已取消")
return False
return True
def init_oss_bucket(self):
"""初始化 OSS 连接"""
try:
auth = oss2.Auth(self.config['access_key_id'], self.config['access_key_secret'])
self.bucket = oss2.Bucket(auth, self.config['endpoint'], self.config['bucket_name'])
return True
except Exception as e:
print(f"✗ 初始化 OSS 失败: {e}")
return False
def test_oss_connection(self):
"""测试 OSS 连接"""
try:
for obj in oss2.ObjectIterator(self.bucket, max_keys=1):
pass
return True
except Exception as e:
print(f"✗ OSS 连接失败: {e}")
return False
def upload_file(self, local_path, oss_path):
"""上传单个文件到 OSS"""
try:
result = self.bucket.put_object_from_file(oss_path, local_path)
if result.status == 200:
return True
else:
print(f" ✗ 上传失败 (状态码: {result.status})")
return False
except Exception as e:
print(f" ✗ 上传错误: {e}")
return False
def upload_gifts(self):
"""上传礼物图片"""
print(f"\n📦 上传礼物图片")
print(f"本地目录: {GIFT_DIR}")
print(f"OSS 路径: {OSS_GIFT_PREFIX}")
if not os.path.exists(GIFT_DIR):
print(f"✗ 目录不存在: {GIFT_DIR}")
return
files = [f for f in os.listdir(GIFT_DIR) if f.endswith(('.png', '.jpg', '.jpeg', '.gif'))]
print(f"找到 {len(files)} 个文件")
success = 0
failed = 0
skipped = 0
for filename in files:
local_path = os.path.join(GIFT_DIR, filename)
oss_path = OSS_GIFT_PREFIX + filename
# 检查文件是否已存在
try:
self.bucket.head_object(oss_path)
print(f" ○ 已存在: {filename}")
skipped += 1
continue
except oss2.exceptions.NoSuchKey:
pass
print(f" ↑ 上传: {filename}")
if self.upload_file(local_path, oss_path):
success += 1
print(f" ✓ 成功")
else:
failed += 1
print(f"\n礼物上传完成: 成功 {success}, 失败 {failed}, 跳过 {skipped}")
def upload_outfits(self):
"""上传服装图片"""
print(f"\n👔 上传服装图片")
print(f"本地目录: {OUTFIT_DIR}")
print(f"OSS 路径: {OSS_OUTFIT_PREFIX}")
if not os.path.exists(OUTFIT_DIR):
print(f"✗ 目录不存在: {OUTFIT_DIR}")
return
files = [f for f in os.listdir(OUTFIT_DIR) if f.endswith(('.png', '.jpg', '.jpeg', '.gif'))]
print(f"找到 {len(files)} 个文件")
success = 0
failed = 0
skipped = 0
# 服装图片需要按类型分类上传
outfit_types = {
'top': ['tshirt', 'shirt', 'sleeve', 'strap', 'shoulder', 'crop', 'cardigan', 'jacket', 'sweatshirt'],
'bottom': ['jeans', 'skirt', 'shorts', 'pants', 'sweatpants'],
'dress': ['dress', 'uniform', 'hanfu', 'lolita']
}
for filename in files:
local_path = os.path.join(OUTFIT_DIR, filename)
# 判断服装类型
outfit_type = 'dress'
for type_name, keywords in outfit_types.items():
if any(keyword in filename.lower() for keyword in keywords):
outfit_type = type_name
break
oss_path = f"{OSS_OUTFIT_PREFIX}{outfit_type}/{filename}"
# 检查文件是否已存在
try:
self.bucket.head_object(oss_path)
print(f" ○ 已存在: {filename} ({outfit_type})")
skipped += 1
continue
except oss2.exceptions.NoSuchKey:
pass
print(f" ↑ 上传: {filename} -> {outfit_type}/")
if self.upload_file(local_path, oss_path):
success += 1
print(f" ✓ 成功")
else:
failed += 1
print(f"\n服装上传完成: 成功 {success}, 失败 {failed}, 跳过 {skipped}")
def generate_env_config(self):
"""生成 .env 配置内容"""
endpoint_with_https = f"https://{self.config['endpoint']}"
cdn_domain = f"https://{self.config['bucket_name']}.{self.config['endpoint']}"
env_content = f"""
# ===== 新的 OSS 配置 =====
ALIYUN_OSS_ACCESS_KEY_ID={self.config['access_key_id']}
ALIYUN_OSS_ACCESS_KEY_SECRET={self.config['access_key_secret']}
ALIYUN_OSS_BUCKET_NAME={self.config['bucket_name']}
ALIYUN_OSS_ENDPOINT={endpoint_with_https}
ALIYUN_OSS_CDN_DOMAIN={cdn_domain}
"""
return env_content
def run(self):
"""运行迁移流程"""
print("=" * 60)
print("图片迁移到新 OSS 存储桶")
print("=" * 60)
# 步骤1: 配置
if not self.configure():
return
# 步骤2: 初始化 OSS
print("\n正在连接 OSS...")
if not self.init_oss_bucket():
return
# 步骤3: 测试连接
if not self.test_oss_connection():
print("\n✗ 无法连接到 OSS请检查配置")
return
print("✓ OSS 连接成功")
# 步骤4: 上传礼物图片
self.upload_gifts()
# 步骤5: 上传服装图片
self.upload_outfits()
# 步骤6: 显示后续操作
print("\n" + "=" * 60)
print("✓ 上传完成!")
print("=" * 60)
print("\n下一步操作:")
print("\n1. 将以下内容添加到 .env 文件:")
print(self.generate_env_config())
print("\n2. 重启服务:")
print(" 开发\\1-启动项目.bat")
print("\n数据库无需修改,图片路径保持不变!")
def main():
try:
migrator = OSSMigrator()
migrator.run()
except KeyboardInterrupt:
print("\n\n用户中断操作")
except Exception as e:
print(f"\n✗ 发生错误: {e}")
import traceback
traceback.print_exc()
if __name__ == '__main__':
main()

View File

@ -0,0 +1,78 @@
# 项目启动配置清单
## 📁 相关文档
- `0-项目启动配置清单.md` - 本文档,配置说明
- `1-启动项目.bat` - 启动脚本
- `2-迁移图片到新OSS.md` - 图片迁移说明
- `3-迁移图片到新OSS.bat` - 图片迁移工具
## 📋 需要的服务和密钥
### 1. 阿里云 DashScope必需
**用途:** AI 大模型服务(对话、语音、图像、视频)
**需要申请:**
- DashScope API Key
**申请地址:**
- https://dashscope.aliyun.com/
**配置位置:**
```env
DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxx
```
**使用的模型:**
- `qwen-plus` - 对话模型
- `cosyvoice-v2` - 语音合成TTS
- `paraformer-realtime-v2` - 语音识别ASR
- `wan2.6-t2i` - 图像生成
- `wan2.6-i2v-flash` - 视频生成
- `qwen3-vl-flash` - 视觉理解
---
### 2. 阿里云 OSS必需
**用途:** 存储图片、音频、视频文件
**需要申请:**
- OSS Access Key ID
- OSS Access Key Secret
- OSS Bucket存储桶
**申请地址:**
- https://oss.console.aliyun.com/
**配置位置:**
```env
ALIYUN_OSS_ACCESS_KEY_ID=LTAI5xxxxxxxxxxxxx
ALIYUN_OSS_ACCESS_KEY_SECRET=xxxxxxxxxxxxxxxx
ALIYUN_OSS_BUCKET_NAME=你的bucket名称
ALIYUN_OSS_ENDPOINT=https://oss-cn-hangzhou.aliyuncs.com
ALIYUN_OSS_CDN_DOMAIN=https://你的bucket名称.oss-cn-hangzhou.aliyuncs.com
```
**OSS 配置步骤:**
1. 创建 Bucket选择杭州区域
2. 设置读写权限为"公共读"
3. 获取 Access Key ID 和 Secret
4. 填入配置文件
---
### 3. MySQL 数据库
**用途:** 存储用户数据、聊天记录等
**配置位置:**
```env
DATABASE_URL=mysql+pymysql://root:root@127.0.0.1:3306/fastadmin?charset=utf8mb4
```
**数据库信息:**
- 数据库名:`fastadmin`
- 用户名:`root`
- 密码:`root`
- 端口:`3306`

View File

@ -1,16 +0,0 @@
# 主要功能
1. 将密码校验删除,因为无法生成模型,用最简单的方法来尝试这些内容。
- [x] 增加tab栏但是还没有加上对应的功能
3. 增加聊天背景选择功能,会员可以自定义背景
4. 增加恋人消息编辑功能,更新**数据库**,加上一些编辑消息、编辑时间相关字段。用户编辑消息之后恋人不回答,只会更新记忆和摘要的数据库,下一次回答的时候会重新引用这个更新后的记忆。
5. 恋人消息回复增加思考中...
- [x] 恋人消息回复和消息编辑都需要测试
6. 将Hbuilder的AppId更换成自己的原本的保留(__UNI__1F3C178)。还是无法正常编译将下面的插件注释掉不用Agora-RTC音视频插件和AudioRecode录音插件。
- [x] 克隆音色API填写然后给你测试
7. 二维码推广功能创建邀请码邀请新用户但是没有二维码生成API
上线需调整
1. oss存储桶用来存放播放的音色
2. DashCope阿里云模型apisk-xxx 并启用下面模型
- qwen-plusAI对话聊天
- cosyvoice-v2音色克隆

View File

@ -1,114 +0,0 @@
-- ============================================
-- 换装种类数据填充(流行服装风格)
-- 表名: nf_outfit_items
-- 字段说明:
-- name: 服装名称
-- category: 分类top=上装, bottom=下装, dress=连衣裙/连体服)
-- gender: 适用性别male=男, female=女, unisex=通用)
-- image_url: 服装图片路径(需要上传图片后更新)
-- is_free: 是否免费1=免费, 0=收费)
-- price_gold: 金币价格(收费时)
-- is_vip_only: 是否仅VIP可见/可用1=是, 0=否)
-- status: 状态1=上架, 0=下架)
-- weigh: 排序权重(数字越大越靠前)
-- ============================================
-- ========== 上装 (top) - 女性 ==========
INSERT INTO `nf_outfit_items` (`name`, `category`, `gender`, `image_url`, `is_free`, `price_gold`, `is_vip_only`, `status`, `weigh`, `createtime`, `updatetime`) VALUES
-- 免费基础款
('白色T恤', 'top', 'female', '/uploads/outfit/top/white_tshirt.jpg', 1, 0, 0, '1', 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('粉色短袖', 'top', 'female', '/uploads/outfit/top/pink_short_sleeve.jpg', 1, 0, 0, '1', 99, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('蓝色衬衫', 'top', 'female', '/uploads/outfit/top/blue_shirt.jpg', 1, 0, 0, '1', 98, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('灰色卫衣', 'top', 'female', '/uploads/outfit/top/gray_sweatshirt.jpg', 1, 0, 0, '1', 97, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- 收费款
('蕾丝吊带上衣', 'top', 'female', '/uploads/outfit/top/lace_strap.jpg', 0, 100, 0, '1', 96, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('一字领露肩上衣', 'top', 'female', '/uploads/outfit/top/off_shoulder.jpg', 0, 80, 0, '1', 95, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('露脐短袖', 'top', 'female', '/uploads/outfit/top/crop_top.jpg', 0, 60, 0, '1', 94, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('雪纺衬衫', 'top', 'female', '/uploads/outfit/top/chiffon_shirt.jpg', 0, 70, 0, '1', 93, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('针织开衫', 'top', 'female', '/uploads/outfit/top/knit_cardigan.jpg', 0, 90, 0, '1', 92, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('小香风外套', 'top', 'female', '/uploads/outfit/top/tweed_jacket.jpg', 0, 150, 0, '1', 91, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- VIP专属
('真丝衬衫', 'top', 'female', '/uploads/outfit/top/silk_shirt.jpg', 0, 200, 1, '1', 90, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- ========== 下装 (bottom) - 女性 ==========
INSERT INTO `nf_outfit_items` (`name`, `category`, `gender`, `image_url`, `is_free`, `price_gold`, `is_vip_only`, `status`, `weigh`, `createtime`, `updatetime`) VALUES
-- 免费基础款
('蓝色牛仔裤', 'bottom', 'female', '/uploads/outfit/bottom/blue_jeans.jpg', 1, 0, 0, '1', 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('黑色短裙', 'bottom', 'female', '/uploads/outfit/bottom/black_skirt.jpg', 1, 0, 0, '1', 99, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('白色短裤', 'bottom', 'female', '/uploads/outfit/bottom/white_shorts.jpg', 1, 0, 0, '1', 98, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('灰色运动裤', 'bottom', 'female', '/uploads/outfit/bottom/gray_sweatpants.jpg', 1, 0, 0, '1', 97, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- 收费款
('A字半身裙', 'bottom', 'female', '/uploads/outfit/bottom/a_line_skirt.jpg', 0, 80, 0, '1', 96, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('高腰阔腿裤', 'bottom', 'female', '/uploads/outfit/bottom/high_waist_pants.jpg', 0, 100, 0, '1', 95, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('百褶短裙', 'bottom', 'female', '/uploads/outfit/bottom/pleated_skirt.jpg', 0, 70, 0, '1', 94, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('包臀裙', 'bottom', 'female', '/uploads/outfit/bottom/pencil_skirt.jpg', 0, 90, 0, '1', 93, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('破洞牛仔裤', 'bottom', 'female', '/uploads/outfit/bottom/ripped_jeans.jpg', 0, 60, 0, '1', 92, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('西装裤', 'bottom', 'female', '/uploads/outfit/bottom/suit_pants.jpg', 0, 120, 0, '1', 91, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- VIP专属
('真丝长裙', 'bottom', 'female', '/uploads/outfit/bottom/silk_long_skirt.jpg', 0, 250, 1, '1', 90, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('定制礼服下装', 'bottom', 'female', '/uploads/outfit/bottom/custom_dress_bottom.jpg', 0, 350, 1, '1', 89, UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- ========== 连衣裙/连体服 (dress) - 女性 ==========
INSERT INTO `nf_outfit_items` (`name`, `category`, `gender`, `image_url`, `is_free`, `price_gold`, `is_vip_only`, `status`, `weigh`, `createtime`, `updatetime`) VALUES
-- 免费基础款
('白色连衣裙', 'dress', 'female', '/uploads/outfit/dress/white_dress.jpg', 1, 0, 0, '1', 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('碎花连衣裙', 'dress', 'female', '/uploads/outfit/dress/floral_dress.jpg', 1, 0, 0, '1', 99, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('黑色小礼服', 'dress', 'female', '/uploads/outfit/dress/black_dress.jpg', 1, 0, 0, '1', 98, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- 日常风格
('法式复古连衣裙', 'dress', 'female', '/uploads/outfit/dress/french_vintage.jpg', 0, 150, 0, '1', 97, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('甜美公主裙', 'dress', 'female', '/uploads/outfit/dress/princess_dress.jpg', 0, 180, 0, '1', 96, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('优雅长裙', 'dress', 'female', '/uploads/outfit/dress/elegant_long_dress.jpg', 0, 200, 0, '1', 95, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('吊带连衣裙', 'dress', 'female', '/uploads/outfit/dress/strapless_dress.jpg', 0, 120, 0, '1', 94, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('雪纺连衣裙', 'dress', 'female', '/uploads/outfit/dress/chiffon_dress.jpg', 0, 160, 0, '1', 93, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- 主题风格
('JK制服', 'dress', 'female', '/uploads/outfit/dress/jk_uniform.jpg', 0, 200, 0, '1', 92, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('汉服', 'dress', 'female', '/uploads/outfit/dress/hanfu.jpg', 0, 300, 0, '1', 91, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('洛丽塔', 'dress', 'female', '/uploads/outfit/dress/lolita.jpg', 0, 350, 0, '1', 90, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('和服', 'dress', 'female', '/uploads/outfit/dress/kimono.jpg', 0, 280, 0, '1', 89, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('魔法少女装', 'dress', 'female', '/uploads/outfit/dress/magical_girl.jpg', 0, 250, 0, '1', 88, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- 季节限定
('夏日比基尼', 'dress', 'female', '/uploads/outfit/dress/summer_bikini.jpg', 0, 150, 0, '1', 87, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('冬季毛衣裙', 'dress', 'female', '/uploads/outfit/dress/winter_sweater_dress.jpg', 0, 180, 0, '1', 86, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('圣诞装', 'dress', 'female', '/uploads/outfit/dress/christmas_dress.jpg', 0, 200, 0, '1', 85, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- VIP专属
('定制晚礼服', 'dress', 'female', '/uploads/outfit/dress/custom_evening_dress.jpg', 0, 500, 1, '1', 84, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('高级定制婚纱', 'dress', 'female', '/uploads/outfit/dress/custom_wedding_dress.jpg', 0, 1000, 1, '1', 83, UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- ========== 上装 (top) - 男性 ==========
INSERT INTO `nf_outfit_items` (`name`, `category`, `gender`, `image_url`, `is_free`, `price_gold`, `is_vip_only`, `status`, `weigh`, `createtime`, `updatetime`) VALUES
-- 免费基础款
('白色T恤', 'top', 'male', '/uploads/outfit/top/male_white_tshirt.jpg', 1, 0, 0, '1', 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('蓝色衬衫', 'top', 'male', '/uploads/outfit/top/male_blue_shirt.jpg', 1, 0, 0, '1', 99, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('黑色卫衣', 'top', 'male', '/uploads/outfit/top/male_black_sweatshirt.jpg', 1, 0, 0, '1', 98, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- 收费款
('休闲Polo衫', 'top', 'male', '/uploads/outfit/top/polo_shirt.jpg', 0, 80, 0, '1', 97, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('商务衬衫', 'top', 'male', '/uploads/outfit/top/business_shirt.jpg', 0, 100, 0, '1', 96, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('运动背心', 'top', 'male', '/uploads/outfit/top/sports_tank.jpg', 0, 60, 0, '1', 95, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('牛仔外套', 'top', 'male', '/uploads/outfit/top/denim_jacket.jpg', 0, 120, 0, '1', 94, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('西装外套', 'top', 'male', '/uploads/outfit/top/suit_jacket.jpg', 0, 200, 0, '1', 93, UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- ========== 下装 (bottom) - 男性 ==========
INSERT INTO `nf_outfit_items` (`name`, `category`, `gender`, `image_url`, `is_free`, `price_gold`, `is_vip_only`, `status`, `weigh`, `createtime`, `updatetime`) VALUES
-- 免费基础款
('蓝色牛仔裤', 'bottom', 'male', '/uploads/outfit/bottom/male_blue_jeans.jpg', 1, 0, 0, '1', 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('黑色休闲裤', 'bottom', 'male', '/uploads/outfit/bottom/male_black_pants.jpg', 1, 0, 0, '1', 99, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- 收费款
('运动短裤', 'bottom', 'male', '/uploads/outfit/bottom/sports_shorts.jpg', 0, 50, 0, '1', 98, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('卡其裤', 'bottom', 'male', '/uploads/outfit/bottom/khaki_pants.jpg', 0, 80, 0, '1', 97, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('西装裤', 'bottom', 'male', '/uploads/outfit/bottom/suit_pants_male.jpg', 0, 150, 0, '1', 96, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('工装裤', 'bottom', 'male', '/uploads/outfit/bottom/cargo_pants.jpg', 0, 100, 0, '1', 95, UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- ========== 通用款 (unisex) ==========
INSERT INTO `nf_outfit_items` (`name`, `category`, `gender`, `image_url`, `is_free`, `price_gold`, `is_vip_only`, `status`, `weigh`, `createtime`, `updatetime`) VALUES
('基础T恤', 'top', 'unisex', '/uploads/outfit/top/basic_tshirt.jpg', 1, 0, 0, '1', 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('运动裤', 'bottom', 'unisex', '/uploads/outfit/bottom/sweatpants.jpg', 1, 0, 0, '1', 99, UNIX_TIMESTAMP(), UNIX_TIMESTAMP());

View File

@ -1,115 +0,0 @@
-- ============================================
-- 换装种类数据填充(流行服装风格)
-- 表名: nf_outfit_items
-- 字段说明:
-- name: 服装名称
-- category: 分类top=上装, bottom=下装, dress=连衣裙/连体服)
-- gender: 适用性别male=男, female=女, unisex=通用)
-- image_url: 服装图片路径(需要上传图片后更新)
-- is_free: 是否免费1=免费, 0=收费)
-- price_gold: 金币价格(收费时)
-- is_vip_only: 是否仅VIP可见/可用1=是, 0=否)
-- status: 状态1=上架, 0=下架)
-- weigh: 排序权重(数字越大越靠前)
-- ============================================
-- ========== 上装 (top) - 女性 ==========
INSERT INTO `nf_outfit_items` (`name`, `category`, `gender`, `image_url`, `is_free`, `price_gold`, `is_vip_only`, `status`, `weigh`, `createtime`, `updatetime`) VALUES
-- 免费基础款
('白色T恤', 'top', 'female', '/uploads/outfit/top/white_tshirt.jpg', 1, 0, 0, '1', 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('粉色短袖', 'top', 'female', '/uploads/outfit/top/pink_short_sleeve.jpg', 1, 0, 0, '1', 99, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('蓝色衬衫', 'top', 'female', '/uploads/outfit/top/blue_shirt.jpg', 1, 0, 0, '1', 98, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('灰色卫衣', 'top', 'female', '/uploads/outfit/top/gray_sweatshirt.jpg', 1, 0, 0, '1', 97, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- 收费款
('蕾丝吊带上衣', 'top', 'female', '/uploads/outfit/top/lace_strap.jpg', 0, 100, 0, '1', 96, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('一字领露肩上衣', 'top', 'female', '/uploads/outfit/top/off_shoulder.jpg', 0, 80, 0, '1', 95, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('露脐短袖', 'top', 'female', '/uploads/outfit/top/crop_top.jpg', 0, 60, 0, '1', 94, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('雪纺衬衫', 'top', 'female', '/uploads/outfit/top/chiffon_shirt.jpg', 0, 70, 0, '1', 93, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('针织开衫', 'top', 'female', '/uploads/outfit/top/knit_cardigan.jpg', 0, 90, 0, '1', 92, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('小香风外套', 'top', 'female', '/uploads/outfit/top/tweed_jacket.jpg', 0, 150, 0, '1', 91, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- VIP专属
('真丝衬衫', 'top', 'female', '/uploads/outfit/top/silk_shirt.jpg', 0, 200, 1, '1', 90, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('定制礼服上衣', 'top', 'female', '/uploads/outfit/top/custom_dress_top.jpg', 0, 300, 1, '1', 89, UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- ========== 下装 (bottom) - 女性 ==========
INSERT INTO `nf_outfit_items` (`name`, `category`, `gender`, `image_url`, `is_free`, `price_gold`, `is_vip_only`, `status`, `weigh`, `createtime`, `updatetime`) VALUES
-- 免费基础款
('蓝色牛仔裤', 'bottom', 'female', '/uploads/outfit/bottom/blue_jeans.jpg', 1, 0, 0, '1', 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('黑色短裙', 'bottom', 'female', '/uploads/outfit/bottom/black_skirt.jpg', 1, 0, 0, '1', 99, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('白色短裤', 'bottom', 'female', '/uploads/outfit/bottom/white_shorts.jpg', 1, 0, 0, '1', 98, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('灰色运动裤', 'bottom', 'female', '/uploads/outfit/bottom/gray_sweatpants.jpg', 1, 0, 0, '1', 97, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- 收费款
('A字半身裙', 'bottom', 'female', '/uploads/outfit/bottom/a_line_skirt.jpg', 0, 80, 0, '1', 96, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('高腰阔腿裤', 'bottom', 'female', '/uploads/outfit/bottom/high_waist_pants.jpg', 0, 100, 0, '1', 95, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('百褶短裙', 'bottom', 'female', '/uploads/outfit/bottom/pleated_skirt.jpg', 0, 70, 0, '1', 94, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('包臀裙', 'bottom', 'female', '/uploads/outfit/bottom/pencil_skirt.jpg', 0, 90, 0, '1', 93, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('破洞牛仔裤', 'bottom', 'female', '/uploads/outfit/bottom/ripped_jeans.jpg', 0, 60, 0, '1', 92, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('西装裤', 'bottom', 'female', '/uploads/outfit/bottom/suit_pants.jpg', 0, 120, 0, '1', 91, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- VIP专属
('真丝长裙', 'bottom', 'female', '/uploads/outfit/bottom/silk_long_skirt.jpg', 0, 250, 1, '1', 90, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('定制礼服下装', 'bottom', 'female', '/uploads/outfit/bottom/custom_dress_bottom.jpg', 0, 350, 1, '1', 89, UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- ========== 连衣裙/连体服 (dress) - 女性 ==========
INSERT INTO `nf_outfit_items` (`name`, `category`, `gender`, `image_url`, `is_free`, `price_gold`, `is_vip_only`, `status`, `weigh`, `createtime`, `updatetime`) VALUES
-- 免费基础款
('白色连衣裙', 'dress', 'female', '/uploads/outfit/dress/white_dress.jpg', 1, 0, 0, '1', 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('碎花连衣裙', 'dress', 'female', '/uploads/outfit/dress/floral_dress.jpg', 1, 0, 0, '1', 99, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('黑色小礼服', 'dress', 'female', '/uploads/outfit/dress/black_dress.jpg', 1, 0, 0, '1', 98, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- 日常风格
('法式复古连衣裙', 'dress', 'female', '/uploads/outfit/dress/french_vintage.jpg', 0, 150, 0, '1', 97, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('甜美公主裙', 'dress', 'female', '/uploads/outfit/dress/princess_dress.jpg', 0, 180, 0, '1', 96, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('优雅长裙', 'dress', 'female', '/uploads/outfit/dress/elegant_long_dress.jpg', 0, 200, 0, '1', 95, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('吊带连衣裙', 'dress', 'female', '/uploads/outfit/dress/strapless_dress.jpg', 0, 120, 0, '1', 94, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('雪纺连衣裙', 'dress', 'female', '/uploads/outfit/dress/chiffon_dress.jpg', 0, 160, 0, '1', 93, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- 主题风格
('JK制服', 'dress', 'female', '/uploads/outfit/dress/jk_uniform.jpg', 0, 200, 0, '1', 92, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('汉服', 'dress', 'female', '/uploads/outfit/dress/hanfu.jpg', 0, 300, 0, '1', 91, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('洛丽塔', 'dress', 'female', '/uploads/outfit/dress/lolita.jpg', 0, 350, 0, '1', 90, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('和服', 'dress', 'female', '/uploads/outfit/dress/kimono.jpg', 0, 280, 0, '1', 89, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('魔法少女装', 'dress', 'female', '/uploads/outfit/dress/magical_girl.jpg', 0, 250, 0, '1', 88, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- 季节限定
('夏日比基尼', 'dress', 'female', '/uploads/outfit/dress/summer_bikini.jpg', 0, 150, 0, '1', 87, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('冬季毛衣裙', 'dress', 'female', '/uploads/outfit/dress/winter_sweater_dress.jpg', 0, 180, 0, '1', 86, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('圣诞装', 'dress', 'female', '/uploads/outfit/dress/christmas_dress.jpg', 0, 200, 0, '1', 85, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- VIP专属
('定制晚礼服', 'dress', 'female', '/uploads/outfit/dress/custom_evening_dress.jpg', 0, 500, 1, '1', 84, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('高级定制婚纱', 'dress', 'female', '/uploads/outfit/dress/custom_wedding_dress.jpg', 0, 1000, 1, '1', 83, UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- ========== 上装 (top) - 男性 ==========
INSERT INTO `nf_outfit_items` (`name`, `category`, `gender`, `image_url`, `is_free`, `price_gold`, `is_vip_only`, `status`, `weigh`, `createtime`, `updatetime`) VALUES
-- 免费基础款
('白色T恤', 'top', 'male', '/uploads/outfit/top/male_white_tshirt.jpg', 1, 0, 0, '1', 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('蓝色衬衫', 'top', 'male', '/uploads/outfit/top/male_blue_shirt.jpg', 1, 0, 0, '1', 99, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('黑色卫衣', 'top', 'male', '/uploads/outfit/top/male_black_sweatshirt.jpg', 1, 0, 0, '1', 98, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- 收费款
('休闲Polo衫', 'top', 'male', '/uploads/outfit/top/polo_shirt.jpg', 0, 80, 0, '1', 97, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('商务衬衫', 'top', 'male', '/uploads/outfit/top/business_shirt.jpg', 0, 100, 0, '1', 96, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('运动背心', 'top', 'male', '/uploads/outfit/top/sports_tank.jpg', 0, 60, 0, '1', 95, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('牛仔外套', 'top', 'male', '/uploads/outfit/top/denim_jacket.jpg', 0, 120, 0, '1', 94, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('西装外套', 'top', 'male', '/uploads/outfit/top/suit_jacket.jpg', 0, 200, 0, '1', 93, UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- ========== 下装 (bottom) - 男性 ==========
INSERT INTO `nf_outfit_items` (`name`, `category`, `gender`, `image_url`, `is_free`, `price_gold`, `is_vip_only`, `status`, `weigh`, `createtime`, `updatetime`) VALUES
-- 免费基础款
('蓝色牛仔裤', 'bottom', 'male', '/uploads/outfit/bottom/male_blue_jeans.jpg', 1, 0, 0, '1', 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('黑色休闲裤', 'bottom', 'male', '/uploads/outfit/bottom/male_black_pants.jpg', 1, 0, 0, '1', 99, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
-- 收费款
('运动短裤', 'bottom', 'male', '/uploads/outfit/bottom/sports_shorts.jpg', 0, 50, 0, '1', 98, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('卡其裤', 'bottom', 'male', '/uploads/outfit/bottom/khaki_pants.jpg', 0, 80, 0, '1', 97, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('西装裤', 'bottom', 'male', '/uploads/outfit/bottom/suit_pants_male.jpg', 0, 150, 0, '1', 96, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('工装裤', 'bottom', 'male', '/uploads/outfit/bottom/cargo_pants.jpg', 0, 100, 0, '1', 95, UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- ========== 通用款 (unisex) ==========
INSERT INTO `nf_outfit_items` (`name`, `category`, `gender`, `image_url`, `is_free`, `price_gold`, `is_vip_only`, `status`, `weigh`, `createtime`, `updatetime`) VALUES
('基础T恤', 'top', 'unisex', '/uploads/outfit/top/basic_tshirt.jpg', 1, 0, 0, '1', 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('运动裤', 'bottom', 'unisex', '/uploads/outfit/bottom/sweatpants.jpg', 1, 0, 0, '1', 99, UNIX_TIMESTAMP(), UNIX_TIMESTAMP());

View File

@ -1,59 +0,0 @@
-- ============================================
-- 礼物种类数据填充(流行虚拟礼物)
-- 表名: nf_gifts
-- 字段说明:
-- name: 礼物名称
-- title: 礼物标题/描述
-- price: 礼物价格(金币)
-- intimacy_value: 亲密度增加值
-- image: 礼物图片路径(需要上传图片后更新)
-- weigh: 排序权重(数字越大越靠前)
-- status: 状态1=上架0=下架)
-- ============================================
-- 经济类礼物10-50金币
INSERT INTO `nf_gifts` (`name`, `title`, `price`, `intimacy_value`, `image`, `weigh`, `status`, `createtime`, `updatetime`) VALUES
('玫瑰花', '送她一朵玫瑰花,表达你的爱意', 10.00, 10, '/uploads/gifts/rose.png', 100, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('棒棒糖', '甜甜的棒棒糖,甜到心里', 10.00, 10, '/uploads/gifts/lollipop.png', 99, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('咖啡', '一杯香浓咖啡,温暖她的心', 15.00, 15, '/uploads/gifts/coffee.png', 98, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('冰淇淋', '夏日清凉,甜蜜相伴', 15.00, 15, '/uploads/gifts/icecream.png', 97, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('小蛋糕', '精致小蛋糕,甜蜜时光', 20.00, 20, '/uploads/gifts/cake.png', 96, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('巧克力', '浓情巧克力,爱意满满', 20.00, 20, '/uploads/gifts/chocolate.png', 95, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('奶茶', '香醇奶茶,温暖陪伴', 25.00, 25, '/uploads/gifts/milktea.png', 94, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('小星星', '闪闪小星星,照亮她的心', 30.00, 30, '/uploads/gifts/star.png', 93, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('爱心气球', '浪漫爱心气球,传递爱意', 35.00, 35, '/uploads/gifts/heart_balloon.png', 92, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('小礼物盒', '神秘礼物盒,惊喜不断', 40.00, 40, '/uploads/gifts/gift_box.png', 91, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('彩虹', '美丽彩虹,带来好运', 50.00, 50, '/uploads/gifts/rainbow.png', 90, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- 中档礼物50-200金币
INSERT INTO `nf_gifts` (`name`, `title`, `price`, `intimacy_value`, `image`, `weigh`, `status`, `createtime`, `updatetime`) VALUES
('香槟', '庆祝时刻,香槟相伴', 50.00, 50, '/uploads/gifts/champagne.png', 89, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('钻石', '璀璨钻石,永恒的爱', 80.00, 80, '/uploads/gifts/diamond.png', 88, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('王冠', '女王王冠,尊贵象征', 100.00, 100, '/uploads/gifts/crown.png', 87, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('爱心', '大爱心,满满爱意', 100.00, 100, '/uploads/gifts/big_heart.png', 86, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('月亮', '皎洁月亮,浪漫夜晚', 120.00, 120, '/uploads/gifts/moon.png', 85, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('烟花', '绚丽烟花,浪漫绽放', 150.00, 150, '/uploads/gifts/fireworks.png', 84, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('水晶球', '魔法水晶球,许愿成真', 150.00, 150, '/uploads/gifts/crystal_ball.png', 83, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('玫瑰花束', '99朵玫瑰长长久久', 180.00, 180, '/uploads/gifts/rose_bouquet.png', 82, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('星星项链', '闪亮星星项链,点缀美丽', 200.00, 200, '/uploads/gifts/star_necklace.png', 81, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- 高级礼物200-500金币
INSERT INTO `nf_gifts` (`name`, `title`, `price`, `intimacy_value`, `image`, `weigh`, `status`, `createtime`, `updatetime`) VALUES
('跑车', '豪华跑车,速度与激情', 300.00, 300, '/uploads/gifts/sports_car.png', 80, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('飞机', '私人飞机,自由翱翔', 400.00, 400, '/uploads/gifts/airplane.png', 79, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('游艇', '豪华游艇,海上浪漫', 450.00, 450, '/uploads/gifts/yacht.png', 78, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('城堡', '梦幻城堡,公主的梦', 500.00, 500, '/uploads/gifts/castle.png', 77, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- 特殊礼物500+金币)
INSERT INTO `nf_gifts` (`name`, `title`, `price`, `intimacy_value`, `image`, `weigh`, `status`, `createtime`, `updatetime`) VALUES
('宇宙飞船', '探索宇宙,无限可能', 600.00, 600, '/uploads/gifts/spaceship.png', 76, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('时光机', '穿越时空,回到过去', 800.00, 800, '/uploads/gifts/time_machine.png', 75, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('魔法棒', '神奇魔法棒,实现愿望', 1000.00, 1000, '/uploads/gifts/magic_wand.png', 74, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('永恒之心', '永恒之心,永不分离', 1314.00, 1314, '/uploads/gifts/eternal_heart.png', 73, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- 节日限定礼物
INSERT INTO `nf_gifts` (`name`, `title`, `price`, `intimacy_value`, `image`, `weigh`, `status`, `createtime`, `updatetime`) VALUES
('圣诞树', '圣诞树,节日氛围', 200.00, 200, '/uploads/gifts/christmas_tree.png', 72, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('情人节巧克力', '情人节限定,甜蜜加倍', 520.00, 520, '/uploads/gifts/valentine_chocolate.png', 71, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('生日蛋糕', '生日蛋糕,生日快乐', 188.00, 188, '/uploads/gifts/birthday_cake.png', 70, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('万圣节南瓜', '万圣节南瓜,神秘有趣', 150.00, 150, '/uploads/gifts/halloween_pumpkin.png', 69, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP());

View File

@ -1,59 +0,0 @@
-- ============================================
-- 礼物种类数据填充(流行虚拟礼物)
-- 表名: nf_gifts
-- 字段说明:
-- name: 礼物名称
-- title: 礼物标题/描述
-- price: 礼物价格(金币)
-- intimacy_value: 亲密度增加值
-- image: 礼物图片路径(需要上传图片后更新)
-- weigh: 排序权重(数字越大越靠前)
-- status: 状态1=上架0=下架)
-- ============================================
-- 经济类礼物10-50金币
INSERT INTO `nf_gifts` (`name`, `title`, `price`, `intimacy_value`, `image`, `weigh`, `status`, `createtime`, `updatetime`) VALUES
('玫瑰花', '送她一朵玫瑰花,表达你的爱意', 10.00, 10, '/uploads/gifts/rose.png', 100, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('棒棒糖', '甜甜的棒棒糖,甜到心里', 10.00, 10, '/uploads/gifts/lollipop.png', 99, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('咖啡', '一杯香浓咖啡,温暖她的心', 15.00, 15, '/uploads/gifts/coffee.png', 98, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('冰淇淋', '夏日清凉,甜蜜相伴', 15.00, 15, '/uploads/gifts/icecream.png', 97, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('小蛋糕', '精致小蛋糕,甜蜜时光', 20.00, 20, '/uploads/gifts/cake.png', 96, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('巧克力', '浓情巧克力,爱意满满', 20.00, 20, '/uploads/gifts/chocolate.png', 95, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('奶茶', '香醇奶茶,温暖陪伴', 25.00, 25, '/uploads/gifts/milktea.png', 94, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('小星星', '闪闪小星星,照亮她的心', 30.00, 30, '/uploads/gifts/star.png', 93, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('爱心气球', '浪漫爱心气球,传递爱意', 35.00, 35, '/uploads/gifts/heart_balloon.png', 92, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('小礼物盒', '神秘礼物盒,惊喜不断', 40.00, 40, '/uploads/gifts/gift_box.png', 91, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('彩虹', '美丽彩虹,带来好运', 50.00, 50, '/uploads/gifts/rainbow.png', 90, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- 中档礼物50-200金币
INSERT INTO `nf_gifts` (`name`, `title`, `price`, `intimacy_value`, `image`, `weigh`, `status`, `createtime`, `updatetime`) VALUES
('香槟', '庆祝时刻,香槟相伴', 50.00, 50, '/uploads/gifts/champagne.png', 89, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('钻石', '璀璨钻石,永恒的爱', 80.00, 80, '/uploads/gifts/diamond.png', 88, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('王冠', '女王王冠,尊贵象征', 100.00, 100, '/uploads/gifts/crown.png', 87, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('爱心', '大爱心,满满爱意', 100.00, 100, '/uploads/gifts/big_heart.png', 86, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('月亮', '皎洁月亮,浪漫夜晚', 120.00, 120, '/uploads/gifts/moon.png', 85, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('烟花', '绚丽烟花,浪漫绽放', 150.00, 150, '/uploads/gifts/fireworks.png', 84, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('水晶球', '魔法水晶球,许愿成真', 150.00, 150, '/uploads/gifts/crystal_ball.png', 83, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('玫瑰花束', '99朵玫瑰长长久久', 180.00, 180, '/uploads/gifts/rose_bouquet.png', 82, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('星星项链', '闪亮星星项链,点缀美丽', 200.00, 200, '/uploads/gifts/star_necklace.png', 81, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- 高级礼物200-500金币
INSERT INTO `nf_gifts` (`name`, `title`, `price`, `intimacy_value`, `image`, `weigh`, `status`, `createtime`, `updatetime`) VALUES
('跑车', '豪华跑车,速度与激情', 300.00, 300, '/uploads/gifts/sports_car.png', 80, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('飞机', '私人飞机,自由翱翔', 400.00, 400, '/uploads/gifts/airplane.png', 79, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('游艇', '豪华游艇,海上浪漫', 450.00, 450, '/uploads/gifts/yacht.png', 78, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('城堡', '梦幻城堡,公主的梦', 500.00, 500, '/uploads/gifts/castle.png', 77, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- 特殊礼物500+金币)
INSERT INTO `nf_gifts` (`name`, `title`, `price`, `intimacy_value`, `image`, `weigh`, `status`, `createtime`, `updatetime`) VALUES
('宇宙飞船', '探索宇宙,无限可能', 600.00, 600, '/uploads/gifts/spaceship.png', 76, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('时光机', '穿越时空,回到过去', 800.00, 800, '/uploads/gifts/time_machine.png', 75, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('魔法棒', '神奇魔法棒,实现愿望', 1000.00, 1000, '/uploads/gifts/magic_wand.png', 74, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('永恒之心', '永恒之心,永不分离', 1314.00, 1314, '/uploads/gifts/eternal_heart.png', 73, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
-- 节日限定礼物
INSERT INTO `nf_gifts` (`name`, `title`, `price`, `intimacy_value`, `image`, `weigh`, `status`, `createtime`, `updatetime`) VALUES
('圣诞树', '圣诞树,节日氛围', 200.00, 200, '/uploads/gifts/christmas_tree.png', 72, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('情人节巧克力', '情人节限定,甜蜜加倍', 520.00, 520, '/uploads/gifts/valentine_chocolate.png', 71, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('生日蛋糕', '生日蛋糕,生日快乐', 188.00, 188, '/uploads/gifts/birthday_cake.png', 70, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
('万圣节南瓜', '万圣节南瓜,神秘有趣', 150.00, 150, '/uploads/gifts/halloween_pumpkin.png', 69, '1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP());

View File

@ -1,75 +0,0 @@
-- ============================================
-- 音色种类数据填充流行AI语音合成音色
-- 表名: nf_voice_library
-- 字段说明:
-- name: 音色名称
-- gender: 性别male=男, female=女)
-- style_tag: 风格标签
-- avatar_url: 音色头像URL
-- sample_audio_url: 试听音频URL
-- tts_model_id: TTS模型ID根据实际使用的TTS服务填写
-- voice_code: 语音合成参数根据实际TTS服务填写
-- is_default: 是否默认1=是, 0=否)
-- is_owned: 是否已拥有1=是, 0=否)
-- price_gold: 解锁所需金币0=免费)
-- ============================================
-- ========== 女性音色 ==========
INSERT INTO `nf_voice_library` (`name`, `gender`, `style_tag`, `avatar_url`, `sample_audio_url`, `tts_model_id`, `voice_code`, `is_default`, `is_owned`, `price_gold`, `createtime`, `updatetime`, `deletetime`) VALUES
-- 免费基础音色
('温柔甜美', 'female', '温柔甜美', '/uploads/voice/avatar/sweet.jpg', '/uploads/voice/sample/sweet.mp3', 'cosyvoice-v2', 'sweet_voice', 1, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('清纯可爱', 'female', '清纯可爱', '/uploads/voice/avatar/cute.jpg', '/uploads/voice/sample/cute.mp3', 'cosyvoice-v2', 'cute_voice', 0, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('活泼开朗', 'female', '活泼开朗', '/uploads/voice/avatar/cheerful.jpg', '/uploads/voice/sample/cheerful.mp3', 'cosyvoice-v2', 'cheerful_voice', 0, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
-- 收费音色 - 日常风格
('成熟御姐', 'female', '成熟御姐', '/uploads/voice/avatar/mature.jpg', '/uploads/voice/sample/mature.mp3', 'cosyvoice-v2', 'mature_voice', 0, 0, 50, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('知性优雅', 'female', '知性优雅', '/uploads/voice/avatar/elegant.jpg', '/uploads/voice/sample/elegant.mp3', 'cosyvoice-v2', 'elegant_voice', 0, 0, 80, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('温柔邻家', 'female', '温柔邻家', '/uploads/voice/avatar/neighbor.jpg', '/uploads/voice/sample/neighbor.mp3', 'cosyvoice-v2', 'neighbor_voice', 0, 0, 60, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('元气少女', 'female', '元气少女', '/uploads/voice/avatar/energetic.jpg', '/uploads/voice/sample/energetic.mp3', 'cosyvoice-v2', 'energetic_voice', 0, 0, 70, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('清冷女神', 'female', '清冷女神', '/uploads/voice/avatar/cool.jpg', '/uploads/voice/sample/cool.mp3', 'cosyvoice-v2', 'cool_voice', 0, 0, 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
-- 收费音色 - 特殊风格
('萝莉音', 'female', '萝莉音', '/uploads/voice/avatar/loli.jpg', '/uploads/voice/sample/loli.mp3', 'cosyvoice-v2', 'loli_voice', 0, 0, 120, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('御姐音', 'female', '御姐音', '/uploads/voice/avatar/onee.jpg', '/uploads/voice/sample/onee.mp3', 'cosyvoice-v2', 'onee_voice', 0, 0, 120, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('软萌音', 'female', '软萌音', '/uploads/voice/avatar/soft.jpg', '/uploads/voice/sample/soft.mp3', 'cosyvoice-v2', 'soft_voice', 0, 0, 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('磁性低音', 'female', '磁性低音', '/uploads/voice/avatar/magnetic.jpg', '/uploads/voice/sample/magnetic.mp3', 'cosyvoice-v2', 'magnetic_voice', 0, 0, 150, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('空灵仙音', 'female', '空灵仙音', '/uploads/voice/avatar/ethereal.jpg', '/uploads/voice/sample/ethereal.mp3', 'cosyvoice-v2', 'ethereal_voice', 0, 0, 200, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
-- 收费音色 - 角色风格
('古风女声', 'female', '古风女声', '/uploads/voice/avatar/ancient.jpg', '/uploads/voice/sample/ancient.mp3', 'cosyvoice-v2', 'ancient_voice', 0, 0, 180, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('日系少女', 'female', '日系少女', '/uploads/voice/avatar/japanese.jpg', '/uploads/voice/sample/japanese.mp3', 'cosyvoice-v2', 'japanese_voice', 0, 0, 150, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('韩系甜美', 'female', '韩系甜美', '/uploads/voice/avatar/korean.jpg', '/uploads/voice/sample/korean.mp3', 'cosyvoice-v2', 'korean_voice', 0, 0, 150, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('欧美性感', 'female', '欧美性感', '/uploads/voice/avatar/sexy.jpg', '/uploads/voice/sample/sexy.mp3', 'cosyvoice-v2', 'sexy_voice', 0, 0, 200, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
-- VIP专属音色
('定制专属音色', 'female', '定制专属', '/uploads/voice/avatar/custom.jpg', '/uploads/voice/sample/custom.mp3', 'cosyvoice-v2', 'custom_voice', 0, 0, 500, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('AI歌手音色', 'female', 'AI歌手', '/uploads/voice/avatar/singer.jpg', '/uploads/voice/sample/singer.mp3', 'cosyvoice-v2', 'singer_voice', 0, 0, 300, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL);
-- ========== 男性音色 ==========
INSERT INTO `nf_voice_library` (`name`, `gender`, `style_tag`, `avatar_url`, `sample_audio_url`, `tts_model_id`, `voice_code`, `is_default`, `is_owned`, `price_gold`, `createtime`, `updatetime`, `deletetime`) VALUES
-- 免费基础音色
('阳光少年', 'male', '阳光少年', '/uploads/voice/avatar/male_sunny.jpg', '/uploads/voice/sample/male_sunny.mp3', 'cosyvoice-v2', 'sunny_voice', 1, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('温暖大叔', 'male', '温暖大叔', '/uploads/voice/avatar/male_warm.jpg', '/uploads/voice/sample/male_warm.mp3', 'cosyvoice-v2', 'warm_voice', 0, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('干净清爽', 'male', '干净清爽', '/uploads/voice/avatar/male_clean.jpg', '/uploads/voice/sample/male_clean.mp3', 'cosyvoice-v2', 'clean_voice', 0, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
-- 收费音色 - 日常风格
('成熟稳重', 'male', '成熟稳重', '/uploads/voice/avatar/male_mature.jpg', '/uploads/voice/sample/male_mature.mp3', 'cosyvoice-v2', 'mature_male_voice', 0, 0, 50, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('磁性低音', 'male', '磁性低音', '/uploads/voice/avatar/male_magnetic.jpg', '/uploads/voice/sample/male_magnetic.mp3', 'cosyvoice-v2', 'magnetic_male_voice', 0, 0, 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('温柔暖男', 'male', '温柔暖男', '/uploads/voice/avatar/male_gentle.jpg', '/uploads/voice/sample/male_gentle.mp3', 'cosyvoice-v2', 'gentle_male_voice', 0, 0, 80, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('活力青年', 'male', '活力青年', '/uploads/voice/avatar/male_vigorous.jpg', '/uploads/voice/sample/male_vigorous.mp3', 'cosyvoice-v2', 'vigorous_male_voice', 0, 0, 70, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('睿智精英', 'male', '睿智精英', '/uploads/voice/avatar/male_wise.jpg', '/uploads/voice/sample/male_wise.mp3', 'cosyvoice-v2', 'wise_male_voice', 0, 0, 120, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
-- 收费音色 - 特殊风格
('少年音', 'male', '少年音', '/uploads/voice/avatar/male_boy.jpg', '/uploads/voice/sample/male_boy.mp3', 'cosyvoice-v2', 'boy_voice', 0, 0, 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('大叔音', 'male', '大叔音', '/uploads/voice/avatar/male_uncle.jpg', '/uploads/voice/sample/male_uncle.mp3', 'cosyvoice-v2', 'uncle_voice', 0, 0, 120, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('沙哑磁性', 'male', '沙哑磁性', '/uploads/voice/avatar/male_husky.jpg', '/uploads/voice/sample/male_husky.mp3', 'cosyvoice-v2', 'husky_voice', 0, 0, 150, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('清亮高音', 'male', '清亮高音', '/uploads/voice/avatar/male_clear.jpg', '/uploads/voice/sample/male_clear.mp3', 'cosyvoice-v2', 'clear_male_voice', 0, 0, 100, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
-- 收费音色 - 角色风格
('古风男声', 'male', '古风男声', '/uploads/voice/avatar/male_ancient.jpg', '/uploads/voice/sample/male_ancient.mp3', 'cosyvoice-v2', 'ancient_male_voice', 0, 0, 180, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('日系少年', 'male', '日系少年', '/uploads/voice/avatar/male_japanese.jpg', '/uploads/voice/sample/male_japanese.mp3', 'cosyvoice-v2', 'japanese_male_voice', 0, 0, 150, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('欧美硬汉', 'male', '欧美硬汉', '/uploads/voice/avatar/male_tough.jpg', '/uploads/voice/sample/male_tough.mp3', 'cosyvoice-v2', 'tough_voice', 0, 0, 200, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
-- VIP专属音色
('定制专属音色', 'male', '定制专属', '/uploads/voice/avatar/male_custom.jpg', '/uploads/voice/sample/male_custom.mp3', 'cosyvoice-v2', 'custom_male_voice', 0, 0, 500, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL),
('AI歌手音色', 'male', 'AI歌手', '/uploads/voice/avatar/male_singer.jpg', '/uploads/voice/sample/male_singer.mp3', 'cosyvoice-v2', 'singer_male_voice', 0, 0, 300, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), NULL);

View File

@ -1,19 +0,0 @@
- [ ] 礼物、换装、音色样式更改,但是还未更新数据库
1. Tab栏中各内容对齐
2. 短剧、商城、音乐库对接
3. UI完善对齐筑梦岛
4. 视频、语音、唱歌等功能调试成功
# 完成
- tab栏切换的聊天界面切换成功
- 发现vlp会员问题无法正常生成视频和语音
- 将php端口改为30100python改为30101
- 将xunifriend_Raees文件夹除node_modules文件夹都上传到30100站点
- 更改30100站点nginx配置并重载
- 将30100站点网站配置的运行改为public目录
- 将lover文件夹除__pycache__文件夹都上传到30101站点
cd /www/wwwroot/1.15.149.240_30101
source python/venv/bin/activate
python -m uvicorn python.main:app --host 127.0.0.1 --port 30101

View File

@ -1,230 +0,0 @@
# 第一版
server
{
listen 30100;
listen [::]:30100;
server_name 1.15.149.240_30100;
index index.php index.html index.htm default.php default.htm default.html;
root /www/wwwroot/1.15.149.240_30100/public;
#CERT-APPLY-CHECK--START
# 用于SSL证书申请时的文件验证相关配置 -- 请勿删除
include /www/server/panel/vhost/nginx/well-known/1.15.149.240_30100.conf;
#CERT-APPLY-CHECK--END
#SSL-START SSL相关配置请勿删除或修改下一行带注释的404规则
#error_page 404/404.html;
#SSL-END
#ERROR-PAGE-START 错误页配置,可以注释、删除或修改
error_page 404 /404.html;
#error_page 502 /502.html;
#ERROR-PAGE-END
#PHP-INFO-START PHP引用配置可以注释或修改
include enable-php-84.conf;
#PHP-INFO-END
#REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效
include /www/server/panel/vhost/rewrite/1.15.149.240_30100.conf;
#REWRITE-END
#禁止访问的文件或目录
location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md)
{
return 404;
}
#一键申请SSL证书验证目录相关设置
location ~ \.well-known{
allow all;
}
#禁止在证书验证目录放入敏感文件
if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) {
return 403;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
error_log /dev/null;
access_log /dev/null;
}
location ~ .*\.(js|css)?$
{
expires 12h;
error_log /dev/null;
access_log /dev/null;
}
access_log /www/wwwlogs/1.15.149.240_30100.log;
error_log /www/wwwlogs/1.15.149.240_30100.error.log;
}
# 第二版
server
{
listen 30100;
listen [::]:30100;
server_name 1.15.149.240_30100;
index index.php index.html index.htm default.php default.htm default.html;
root /www/wwwroot/1.15.149.240_30100/public;
#CERT-APPLY-CHECK--START
# 用于SSL证书申请时的文件验证相关配置 -- 请勿删除
include /www/server/panel/vhost/nginx/well-known/1.15.149.240_30100.conf;
#CERT-APPLY-CHECK--END
#SSL-START SSL相关配置请勿删除或修改下一行带注释的404规则
#error_page 404/404.html;
#SSL-END
#ERROR-PAGE-START 错误页配置,可以注释、删除或修改
error_page 404 /404.html;
#error_page 502 /502.html;
#ERROR-PAGE-END
#PHP-INFO-START PHP引用配置可以注释或修改
include enable-php-84.conf;
#PHP-INFO-END
#REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效
include /www/server/panel/vhost/rewrite/1.15.149.240_30100.conf;
#REWRITE-END
# ========== FastAPI 反代(/api -> 30101==========
location /api/ {
proxy_pass http://127.0.0.1:30101/;
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;
# WebSocket 支持(语音通话)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600;
proxy_send_timeout 3600;
}
#禁止访问的文件或目录
location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md)
{
return 404;
}
#一键申请SSL证书验证目录相关设置
location ~ \.well-known{
allow all;
}
#禁止在证书验证目录放入敏感文件
if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) {
return 403;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
error_log /dev/null;
access_log /dev/null;
}
location ~ .*\.(js|css)?$
{
expires 12h;
error_log /dev/null;
access_log /dev/null;
}
access_log /www/wwwlogs/1.15.149.240_30100.log;
error_log /www/wwwlogs/1.15.149.240_30100.error.log;
}
# 第三版
server
{
listen 30100;
listen [::]:30100;
server_name 1.15.149.240_30100;
index index.php index.html index.htm default.php default.htm default.html;
root /www/wwwroot/1.15.149.240_30100/public;
#CERT-APPLY-CHECK--START
# 用于SSL证书申请时的文件验证相关配置 -- 请勿删除
include /www/server/panel/vhost/nginx/well-known/1.15.149.240_30100.conf;
#CERT-APPLY-CHECK--END
#SSL-START SSL相关配置请勿删除或修改下一行带注释的404规则
#error_page 404/404.html;
#SSL-END
#ERROR-PAGE-START 错误页配置,可以注释、删除或修改
error_page 404 /404.html;
#error_page 502 /502.html;
#ERROR-PAGE-END
#PHP-INFO-START PHP引用配置可以注释或修改
location ~ [^/]\.php(/|$) {
try_files $uri =404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
include pathinfo.conf;
}
#PHP-INFO-END
#REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效
include /www/server/panel/vhost/rewrite/1.15.149.240_30100.conf;
#REWRITE-END
# ========== FastAPI 反代(/api -> 30101==========
location /api/ {
proxy_pass http://127.0.0.1:30101/;
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;
# WebSocket 支持(语音通话)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600;
proxy_send_timeout 3600;
}
#禁止访问的文件或目录
location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md)
{
return 404;
}
#一键申请SSL证书验证目录相关设置
location ~ \.well-known{
allow all;
}
#禁止在证书验证目录放入敏感文件
if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) {
return 403;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
error_log /dev/null;
access_log /dev/null;
}
location ~ .*\.(js|css)?$
{
expires 12h;
error_log /dev/null;
access_log /dev/null;
}
access_log /www/wwwlogs/1.15.149.240_30100.log;
error_log /www/wwwlogs/1.15.149.240_30100.error.log;
}

View File

@ -1,119 +0,0 @@
# 2026年2月3日开发日志
## 完成的任务
### 1. Tab 栏功能接入和界面美化
- 将所有 tab 栏的功能接上
- 优化界面美观度
### 2. 音乐库功能开发
- 实现用户上传音乐或粘贴音乐链接功能
- 所有用户可以看到共享的音乐
- 详细文档:[音乐库.sql](./音乐库.sql)
### 3. 邀请码功能修复
- **问题**:使用邀请码登录时用户没有成功获得 5 金币奖励
- **根本原因**:数据库字段类型错误
- `invited_by` 字段类型是 `int`,应该是 `varchar(10)`
- `invite_reward_total` 字段类型是 `int`,应该是 `decimal(10,2)`
- **解决方案**:创建一键修复脚本 `lover/migrations/fix_invite_complete.sql`
- **详细文档**
- [邀请码功能修复.md](./邀请码功能修复.md)
- [邀请码问题诊断.md](./邀请码问题诊断.md)
### 4. 登录无法进入系统问题修复
- **问题**:登录显示成功但一直无法进入系统,页面显示空白
- **根本原因**`getBobbiesList` 初始值为空字符串 `''`
- 页面使用 `v-show="getBobbiesList.reg_step == 1"` 判断显示
- 当 `getBobbiesList` 为空字符串时,`getBobbiesList.reg_step` 为 `undefined`
- 导致所有 `v-show` 条件都不满足,页面显示空白
- **解决方案**
- 将 `getBobbiesList` 初始值改为对象:`{ reg_step: 1, level: 0, intimacy: 0, next_level_intimacy: 100 }`
- 将 `loverBasicList` 初始值从空字符串改为 `null`
- 添加加载状态和错误处理
- **详细文档**[登录无法进入问题修复.md](./登录无法进入问题修复.md)
### 5. PHP 后端连接泄漏问题诊断
- **问题**Python 后端调用 PHP 后端接口超时5秒
```
HTTPConnectionPool(host='192.168.1.164', port=30100): Read timed out. (read timeout=5)
```
- **根本原因**PHP 内置开发服务器(`php -S`)连接泄漏
- 通过 `netstat -ano | findstr :30100` 发现 30+ 个 `CLOSE_WAIT` 连接
- `CLOSE_WAIT` 状态表示客户端已关闭连接但服务器端未关闭
- PHP 内置服务器在处理大量并发请求时容易出现连接泄漏
- **临时解决方案**:重启 PHP 服务
- 创建快速重启脚本:`restart_php_service.bat`
- 创建连接监控脚本:`monitor_php_connections.bat`(增强版)
- **长期解决方案**:使用 Nginx + PHP-FPM 代替 `php -S`
- **详细文档**[PHP连接泄漏问题修复.md](./PHP连接泄漏问题修复.md)
---
## 创建的工具脚本
### 服务管理脚本
- `start_all_services.bat` - 启动所有服务PHP + Python
- `stop_all_services.bat` - 停止所有服务
- `check_services.bat` - 检查服务状态
- `restart_php_service.bat` - 快速重启 PHP 服务(修复连接泄漏)
- `monitor_php_connections.bat` - 监控 PHP 连接状态(增强版)
### 数据库迁移脚本
- `lover/migrations/fix_invite_complete.sql` - 邀请码功能一键修复
- `lover/migrations/fix_invite_field_types.sql` - 修复邀请码字段类型
- `开发/2026年2月3日/音乐库.sql` - 音乐库数据库结构
---
## 待处理问题
### 1. PHP 连接泄漏(紧急)
- **当前状态**:已诊断,临时方案已就绪
- **下一步**
1. 执行 `restart_php_service.bat` 重启 PHP 服务
2. 验证登录功能是否恢复正常
3. 使用 `monitor_php_connections.bat` 持续监控
4. 长期考虑切换到 Nginx + PHP-FPM
### 2. 邀请码字段类型修复
- **当前状态**:修复脚本已创建
- **下一步**:执行 `lover/migrations/fix_invite_complete.sql`
---
## 技术要点
### PHP 连接泄漏诊断方法
```bash
# 检查连接状态
netstat -ano | findstr :30100
# 查看 CLOSE_WAIT 连接数
netstat -ano | findstr :30100 | findstr CLOSE_WAIT | find /c /v ""
```
### 判断标准
- **正常**CLOSE_WAIT < 10
- **注意**CLOSE_WAIT 10-20 个
- **警告**CLOSE_WAIT > 20 个(建议立即重启)
### 快速重启命令
```bash
# 停止所有 PHP 进程
taskkill /F /PID 23736
taskkill /F /PID 1416
# 启动新的 PHP 服务
cd xunifriend_RaeeC/public
php -S 192.168.1.164:30100
```
---
## 相关文档
- [邀请码功能修复.md](./邀请码功能修复.md)
- [邀请码问题诊断.md](./邀请码问题诊断.md)
- [登录无法进入问题修复.md](./登录无法进入问题修复.md)
- [PHP连接泄漏问题修复.md](./PHP连接泄漏问题修复.md)
- [音乐库.sql](./音乐库.sql)

View File

@ -1,34 +0,0 @@
-- 音乐库表
CREATE TABLE IF NOT EXISTS `nf_music_library` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` bigint(20) NOT NULL COMMENT '上传用户ID',
`title` varchar(255) NOT NULL COMMENT '歌曲标题',
`artist` varchar(255) DEFAULT NULL COMMENT '艺术家',
`music_url` varchar(500) NOT NULL COMMENT '音乐文件URL或链接',
`cover_url` varchar(500) DEFAULT NULL COMMENT '封面图URL',
`duration` int(11) DEFAULT NULL COMMENT '时长(秒)',
`upload_type` enum('file','link') NOT NULL DEFAULT 'link' COMMENT '上传类型file=文件上传link=链接',
`is_public` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否公开1=公开0=私有',
`play_count` int(11) NOT NULL DEFAULT 0 COMMENT '播放次数',
`like_count` int(11) NOT NULL DEFAULT 0 COMMENT '点赞次数',
`status` enum('pending','approved','rejected') NOT NULL DEFAULT 'approved' COMMENT '审核状态',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_status` (`status`),
KEY `idx_is_public` (`is_public`),
KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='音乐库表';
-- 用户音乐点赞表
CREATE TABLE IF NOT EXISTS `nf_music_likes` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`music_id` bigint(20) NOT NULL COMMENT '音乐ID',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_music` (`user_id`, `music_id`),
KEY `idx_music_id` (`music_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户音乐点赞表';

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 502 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 606 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 505 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 597 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 409 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

2322
数据库.sql Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,91 +0,0 @@
===========================================
添加打电话按钮 - 代码补丁
===========================================
文件xuniYou/pages/index/index.vue
位置:约第 302-318 行(聊天输入框区域)
===========================================
步骤 1找到以下代码
===========================================
<!-- 底部输入框 -->
<view class="chat-input-bar">
<input
class="chat-message-input"
v-model="chatInputText"
placeholder="输入消息..."
confirm-type="send"
:adjust-position="true"
:hold-keyboard="false"
@confirm="sendChatMessage"
@blur="onInputBlur"
/>
<view class="chat-send-btn" @click="sendChatMessage">
<text>发送</text>
</view>
</view>
===========================================
步骤 2替换为以下代码
===========================================
<!-- 底部输入框 -->
<view class="chat-input-bar">
<!-- 打电话按钮 -->
<view class="chat-phone-btn" @click="tophone">
<image class="chat-phone-icon" src="/static/images/phone_a1.png" mode="aspectFit"></image>
</view>
<input
class="chat-message-input"
v-model="chatInputText"
placeholder="输入消息..."
confirm-type="send"
:adjust-position="true"
:hold-keyboard="false"
@confirm="sendChatMessage"
@blur="onInputBlur"
/>
<view class="chat-send-btn" @click="sendChatMessage">
<text>发送</text>
</view>
</view>
===========================================
步骤 3添加样式
===========================================
在 <style> 部分(约第 4916 行附近)的 .chat-input-bar 样式后面添加:
/* 打电话按钮 */
.chat-phone-btn {
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 50%;
margin-right: 20rpx;
flex-shrink: 0;
}
.chat-phone-icon {
width: 40rpx;
height: 40rpx;
}
===========================================
完成!
===========================================
保存文件后,重新编译前端项目。
测试步骤:
1. 打开应用
2. 进入聊天页面
3. 应该能看到输入框左侧有一个紫色的圆形按钮
4. 点击按钮进入语音通话页面
===========================================

View File

@ -1,87 +0,0 @@
@echo off
chcp 65001 >nul
title 清理端口 30100 和 30101
echo.
echo ╔════════════════════════════════════╗
echo ║ 清理端口 30100 和 30101 ║
echo ╚════════════════════════════════════╝
echo.
REM ==========================================
REM 清理端口 30100
REM ==========================================
echo [清理] 正在检查端口 30100...
echo.
set FOUND_30100=0
for /f "tokens=5" %%a in ('netstat -ano ^| findstr :30100 2^>nul') do (
set FOUND_30100=1
echo [终止] 进程 PID: %%a
taskkill /F /PID %%a >nul 2>&1
if errorlevel 1 (
echo [警告] 无法终止进程 %%a
) else (
echo [成功] 已终止进程 %%a
)
)
if %FOUND_30100%==0 (
echo [信息] 端口 30100 未被占用
)
echo.
REM ==========================================
REM 清理端口 30101
REM ==========================================
echo [清理] 正在检查端口 30101...
echo.
set FOUND_30101=0
for /f "tokens=5" %%a in ('netstat -ano ^| findstr :30101 2^>nul') do (
set FOUND_30101=1
echo [终止] 进程 PID: %%a
taskkill /F /PID %%a >nul 2>&1
if errorlevel 1 (
echo [警告] 无法终止进程 %%a
) else (
echo [成功] 已终止进程 %%a
)
)
if %FOUND_30101%==0 (
echo [信息] 端口 30101 未被占用
)
echo.
echo ────────────────────────────────────
echo.
echo [完成] 端口清理完成!
echo.
REM 等待端口完全释放
echo [等待] 等待端口完全释放3秒...
timeout /t 3 >nul
echo.
echo [验证] 验证端口状态...
echo.
netstat -ano | findstr :30100
if errorlevel 1 (
echo [✓] 端口 30100 已释放
) else (
echo [✗] 端口 30100 仍被占用
)
netstat -ano | findstr :30101
if errorlevel 1 (
echo [✓] 端口 30101 已释放
) else (
echo [✗] 端口 30101 仍被占用
)
echo.
echo 按任意键退出...
pause >nul

View File

@ -1,82 +0,0 @@
@echo off
chcp 65001 >nul
title 诊断 PHP 服务器问题
echo.
echo ╔════════════════════════════════════╗
echo ║ 诊断 PHP 服务器问题 ║
echo ╚════════════════════════════════════╝
echo.
REM ==========================================
REM 1. 检查 MySQL 服务
REM ==========================================
echo [1/5] 检查 MySQL 服务...
echo.
netstat -ano | findstr :3306 >nul 2>&1
if errorlevel 1 (
echo [✗] MySQL 服务未运行(端口 3306 未监听)
echo.
echo 这可能是导致 PHP API 超时的原因!
echo 请启动 MySQL 服务后再试。
echo.
) else (
echo [✓] MySQL 服务正在运行
echo.
)
REM ==========================================
REM 2. 检查 PHP 服务器
REM ==========================================
echo [2/5] 检查 PHP 服务器...
echo.
netstat -ano | findstr :30100 >nul 2>&1
if errorlevel 1 (
echo [✗] PHP 服务器未运行(端口 30100 未监听)
echo.
) else (
echo [✓] PHP 服务器正在运行
echo.
)
REM ==========================================
REM 3. 测试 PHP 基本响应
REM ==========================================
echo [3/5] 测试 PHP 基本响应...
echo.
powershell -Command "try { $response = Invoke-WebRequest -Uri 'http://127.0.0.1:30100/test_api.php' -TimeoutSec 5; Write-Host '[✓] PHP 服务器响应正常' -ForegroundColor Green; Write-Host '响应内容:' -ForegroundColor Cyan; $response.Content } catch { Write-Host '[✗] PHP 服务器无响应' -ForegroundColor Red; Write-Host '错误:' $_.Exception.Message -ForegroundColor Red }"
echo.
REM ==========================================
REM 4. 测试 PHP 调试接口
REM ==========================================
echo [4/5] 测试 PHP 调试接口(包含数据库检查)...
echo.
powershell -Command "try { $response = Invoke-WebRequest -Uri 'http://127.0.0.1:30100/debug.php' -TimeoutSec 10; Write-Host '[✓] 调试接口响应正常' -ForegroundColor Green; Write-Host '响应内容:' -ForegroundColor Cyan; $response.Content } catch { Write-Host '[✗] 调试接口无响应' -ForegroundColor Red; Write-Host '错误:' $_.Exception.Message -ForegroundColor Red }"
echo.
REM ==========================================
REM 5. 测试实际 API
REM ==========================================
echo [5/5] 测试实际 API需要有效 token...
echo.
powershell -Command "try { $response = Invoke-WebRequest -Uri 'http://127.0.0.1:30100/api/user_basic/get_user_basic' -Headers @{'token'='test-token'} -TimeoutSec 10; Write-Host '[✓] API 响应正常' -ForegroundColor Green; Write-Host '响应内容:' -ForegroundColor Cyan; $response.Content } catch { Write-Host '[✗] API 无响应或返回错误' -ForegroundColor Yellow; Write-Host '错误:' $_.Exception.Message -ForegroundColor Yellow; Write-Host ''; Write-Host '这是正常的,因为使用了无效的 token' -ForegroundColor Gray }"
echo.
echo ════════════════════════════════════
echo.
echo 诊断完成!
echo.
echo 如果看到以下问题:
echo • MySQL 未运行 → 请启动 MySQL 服务
echo • PHP 服务器无响应 → 检查 PHP 启动窗口的错误信息
echo • 数据库连接失败 → 检查 xunifriend_RaeeC/.env 中的数据库配置
echo.
pause