Compare commits
3 Commits
155c9f824c
...
389d291397
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
389d291397 | ||
|
|
345ba0f86d | ||
|
|
9190872fcb |
199
PHP服务连接问题解决方案.md
|
|
@ -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` - 新增测试脚本
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -209,8 +209,12 @@
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
connectWebSocket() {
|
connectWebSocket() {
|
||||||
|
// 根据 baseURLPy 构建 WebSocket URL
|
||||||
|
let wsUrl = baseURLPy.replace('http://', 'ws://').replace('https://', 'wss://') + '/voice/call'
|
||||||
|
console.log('WebSocket URL:', wsUrl)
|
||||||
|
|
||||||
this.socketTask = uni.connectSocket({
|
this.socketTask = uni.connectSocket({
|
||||||
url: 'wss://lovers.shandonghuixing.com/voice/call',
|
url: wsUrl,
|
||||||
header: {
|
header: {
|
||||||
"content-type": "application/json",
|
"content-type": "application/json",
|
||||||
'Authorization': 'Bearer ' + uni.getStorageSync("token") || ""
|
'Authorization': 'Bearer ' + uni.getStorageSync("token") || ""
|
||||||
|
|
|
||||||
|
|
@ -143,25 +143,28 @@
|
||||||
<image class="home-header-icon" src="/static/images/replacement_switch.png" mode="aspectFit"></image>
|
<image class="home-header-icon" src="/static/images/replacement_switch.png" mode="aspectFit"></image>
|
||||||
<text class="home-header-text">装扮设置</text>
|
<text class="home-header-text">装扮设置</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="home-header-spacer"></view>
|
|
||||||
<view class="home-header-btn" @click="todynamics">
|
<view class="home-header-btn" @click="todynamics">
|
||||||
<image class="home-header-icon" src="/static/images/dynamics_logo.png" mode="aspectFit"></image>
|
<image class="home-header-icon" src="/static/images/dynamics_logo.png" mode="aspectFit"></image>
|
||||||
<text class="home-header-text">朋友圈</text>
|
<text class="home-header-text">朋友圈</text>
|
||||||
</view>
|
</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">
|
<view class="home-header-btn" @click="tointimacy">
|
||||||
<image class="home-header-icon" src="/static/images/index_intimate.png" mode="aspectFit"></image>
|
<image class="home-header-icon" src="/static/images/index_intimate.png" mode="aspectFit"></image>
|
||||||
<text class="home-header-text">邀请入驻</text>
|
<text class="home-header-text">邀请入驻</text>
|
||||||
</view>
|
</view>
|
||||||
</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">
|
||||||
<view class="home-card-inner">
|
<view class="home-card-inner">
|
||||||
|
|
@ -2059,21 +2062,23 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
tophone() {
|
tophone() {
|
||||||
// if (this.getBobbiesList.level >= 2) {
|
console.log('tophone 方法被调用');
|
||||||
// uni.navigateTo({
|
|
||||||
// url: '/pages/chat/phone'
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// uni.showToast({
|
|
||||||
// title: '达到Lv.2才可以解锁电话',
|
|
||||||
// icon: 'none',
|
|
||||||
// position: 'top'
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages/chat/phone'
|
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() {
|
togift() {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages/index/gift'
|
url: '/pages/index/gift'
|
||||||
|
|
@ -2226,12 +2231,30 @@
|
||||||
OutfitList({}).then(res => {
|
OutfitList({}).then(res => {
|
||||||
if (res && res.code == 1 && res.data) {
|
if (res && res.code == 1 && res.data) {
|
||||||
this.homeLooksList = res.data.looks || [];
|
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.selectedLookId = this.homeLooksList[0].id;
|
||||||
this.currentLookImageUrl = this.homeLooksList[0].image_url;
|
this.currentLookImageUrl = this.homeLooksList[0].image_url;
|
||||||
// 同时更新聊天头像
|
|
||||||
this.chatLoverAvatar = 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 => {
|
}).catch(err => {
|
||||||
|
|
@ -2243,6 +2266,12 @@
|
||||||
switchLook(look) {
|
switchLook(look) {
|
||||||
if (!look || !look.id) return;
|
if (!look || !look.id) return;
|
||||||
|
|
||||||
|
// 立即更新本地显示,避免延迟
|
||||||
|
this.selectedLookId = look.id;
|
||||||
|
if (this.loverBasicList) {
|
||||||
|
this.loverBasicList.image_url = look.image_url;
|
||||||
|
}
|
||||||
|
|
||||||
// 调用后端 API 切换形象
|
// 调用后端 API 切换形象
|
||||||
uni.request({
|
uni.request({
|
||||||
url: baseURLPy + '/outfit/looks/use/' + look.id,
|
url: baseURLPy + '/outfit/looks/use/' + look.id,
|
||||||
|
|
@ -2252,21 +2281,16 @@
|
||||||
},
|
},
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
if (res.data && res.data.code === 1) {
|
if (res.data && res.data.code === 1) {
|
||||||
this.selectedLookId = look.id;
|
|
||||||
this.currentLookImageUrl = look.image_url;
|
|
||||||
|
|
||||||
// 更新聊天页面的头像
|
// 更新聊天页面的头像
|
||||||
this.chatLoverAvatar = look.image_url;
|
this.chatLoverAvatar = look.image_url;
|
||||||
|
|
||||||
// 更新女友基本信息(刷新图片)
|
// 更新女友基本信息(刷新图片)
|
||||||
this.loverBasic();
|
this.loverBasic();
|
||||||
|
|
||||||
uni.showToast({
|
// 移除成功提示,静默切换
|
||||||
title: '形象切换成功',
|
|
||||||
icon: 'success',
|
|
||||||
duration: 1500
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
|
// 如果失败,恢复原来的图片
|
||||||
|
this.loverBasic();
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: res.data.msg || '切换失败',
|
title: res.data.msg || '切换失败',
|
||||||
icon: 'none',
|
icon: 'none',
|
||||||
|
|
@ -2276,6 +2300,8 @@
|
||||||
},
|
},
|
||||||
fail: (err) => {
|
fail: (err) => {
|
||||||
console.error('切换形象失败:', err);
|
console.error('切换形象失败:', err);
|
||||||
|
// 如果失败,恢复原来的图片
|
||||||
|
this.loverBasic();
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '切换失败,请重试',
|
title: '切换失败,请重试',
|
||||||
icon: 'none',
|
icon: 'none',
|
||||||
|
|
@ -5110,21 +5136,33 @@
|
||||||
.home-header {
|
.home-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
padding: 20rpx 0;
|
padding: 20rpx 0;
|
||||||
margin-bottom: 20rpx;
|
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 {
|
.home-header-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8rpx;
|
justify-content: center;
|
||||||
padding: 10rpx 15rpx;
|
gap: 6rpx;
|
||||||
|
padding: 12rpx 16rpx;
|
||||||
background: rgba(255, 255, 255, 0.8);
|
background: rgba(255, 255, 255, 0.8);
|
||||||
border-radius: 16rpx;
|
border-radius: 16rpx;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
box-shadow: 0 2rpx 8rpx rgba(159, 71, 255, 0.1);
|
box-shadow: 0 2rpx 8rpx rgba(159, 71, 255, 0.1);
|
||||||
|
min-width: 100rpx;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-header-btn:active {
|
.home-header-btn:active {
|
||||||
|
|
@ -5133,17 +5171,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-header-icon {
|
.home-header-icon {
|
||||||
width: 40rpx;
|
width: 44rpx;
|
||||||
height: 40rpx;
|
height: 44rpx;
|
||||||
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-header-text {
|
.home-header-text {
|
||||||
font-size: 22rpx;
|
font-size: 22rpx;
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
white-space: nowrap;
|
||||||
|
text-align: center;
|
||||||
.home-header-spacer {
|
|
||||||
flex: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 选择互动对象标题 */
|
/* 选择互动对象标题 */
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// Windows 本地开发 - 混合架构
|
// Windows 本地开发 - 混合架构
|
||||||
export const baseURL = 'http://192.168.1.164:30100' // PHP 处理用户管理和界面
|
// 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://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'
|
// export const baseURL = 'http://1.15.149.240:30100'
|
||||||
|
|
|
||||||
263
启动项目_改进版.bat
|
|
@ -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
|
|
||||||
277
开发/0-礼物和服装图片上传到存储桶.py
Normal 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()
|
||||||
78
开发/0-项目启动配置清单.md
Normal 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`
|
||||||
|
|
@ -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阿里云模型api:sk-xxx 并启用下面模型
|
|
||||||
- qwen-plus:AI对话聊天
|
|
||||||
- cosyvoice-v2:音色克隆
|
|
||||||
|
|
@ -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());
|
|
||||||
|
|
@ -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());
|
|
||||||
|
|
@ -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());
|
|
||||||
|
|
@ -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());
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
- [ ] 礼物、换装、音色样式更改,但是还未更新数据库
|
|
||||||
1. Tab栏中各内容对齐
|
|
||||||
2. 短剧、商城、音乐库对接
|
|
||||||
3. UI完善:对齐筑梦岛
|
|
||||||
4. 视频、语音、唱歌等功能调试成功
|
|
||||||
|
|
||||||
# 完成
|
|
||||||
- tab栏切换的聊天界面切换成功
|
|
||||||
- 发现vlp会员问题,无法正常生成视频和语音
|
|
||||||
- 将php端口改为30100,python改为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
|
|
||||||
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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='用户音乐点赞表';
|
|
||||||
|
Before Width: | Height: | Size: 250 KiB |
|
Before Width: | Height: | Size: 247 KiB |
|
Before Width: | Height: | Size: 159 KiB |
|
Before Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 393 KiB |
|
Before Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 189 KiB |
|
Before Width: | Height: | Size: 195 KiB |
|
Before Width: | Height: | Size: 309 KiB |
|
Before Width: | Height: | Size: 502 KiB |
|
Before Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 139 KiB |
|
Before Width: | Height: | Size: 606 KiB |
|
Before Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 173 KiB |
|
Before Width: | Height: | Size: 505 KiB |
|
Before Width: | Height: | Size: 212 KiB |
|
Before Width: | Height: | Size: 354 KiB |
|
Before Width: | Height: | Size: 234 KiB |
|
Before Width: | Height: | Size: 249 KiB |
|
Before Width: | Height: | Size: 247 KiB |
|
Before Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 299 KiB |
|
Before Width: | Height: | Size: 226 KiB |
|
Before Width: | Height: | Size: 597 KiB |
|
Before Width: | Height: | Size: 290 KiB |
|
Before Width: | Height: | Size: 409 KiB |
|
Before Width: | Height: | Size: 269 KiB |
|
Before Width: | Height: | Size: 163 KiB |
|
Before Width: | Height: | Size: 252 KiB |
|
Before Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 218 KiB |
|
Before Width: | Height: | Size: 278 KiB |
|
Before Width: | Height: | Size: 101 KiB |
|
Before Width: | Height: | Size: 166 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 237 KiB |
|
Before Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 243 KiB |
|
Before Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 207 KiB |
|
Before Width: | Height: | Size: 168 KiB |
|
Before Width: | Height: | Size: 230 KiB |
|
Before Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 173 KiB |
|
Before Width: | Height: | Size: 212 KiB |
|
Before Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
|
@ -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. 点击按钮进入语音通话页面
|
|
||||||
|
|
||||||
===========================================
|
|
||||||
87
清理端口.bat
|
|
@ -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
|
|
||||||
82
诊断问题.bat
|
|
@ -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
|
|
||||||