去除密码验证
This commit is contained in:
parent
19bd5910ad
commit
4286338fa0
23
.env
23
.env
|
|
@ -1,4 +1,23 @@
|
|||
DATABASE_URL=mysql+pymysql://root:root@127.0.0.1:3306/lover?charset=utf8mb4
|
||||
USER_INFO_API=http://127.0.0.1:8080/api/user_basic/get_user_basic
|
||||
# ===== 应用基础配置 =====
|
||||
APP_ENV=development
|
||||
DEBUG=True
|
||||
|
||||
# ===== 数据库配置 =====
|
||||
DATABASE_URL=mysql+pymysql://root:root@127.0.0.1:3306/lover?charset=utf8mb4
|
||||
|
||||
# ===== 用户信息接口 (PHP后端) =====
|
||||
# 开发环境暂时使用本地地址,PHP后端配置好后再修改
|
||||
USER_INFO_API=http://127.0.0.1:8080/api/user_basic/get_user_basic
|
||||
|
||||
# ===== AI 配置 (暂时留空,测试阶段不需要) =====
|
||||
DASHSCOPE_API_KEY=
|
||||
IMAGE_GEN_MODEL=wan2.6-t2i
|
||||
IMAGE_GEN_SIZE=960*1280
|
||||
WAN26_ASYNC=true
|
||||
|
||||
# ===== OSS 配置 (暂时留空) =====
|
||||
ALIYUN_OSS_ACCESS_KEY_ID=
|
||||
ALIYUN_OSS_ACCESS_KEY_SECRET=
|
||||
ALIYUN_OSS_BUCKET_NAME=
|
||||
ALIYUN_OSS_ENDPOINT=
|
||||
ALIYUN_OSS_CDN_DOMAIN=
|
||||
|
|
|
|||
106
create_tables.py
106
create_tables.py
|
|
@ -1,106 +0,0 @@
|
|||
"""直接用 SQL 创建必要的表"""
|
||||
import pymysql
|
||||
|
||||
SQL_STATEMENTS = """
|
||||
CREATE TABLE IF NOT EXISTS `nf_lovers` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`user_id` bigint NOT NULL,
|
||||
`name` varchar(64) DEFAULT NULL,
|
||||
`gender` enum('male','female') NOT NULL,
|
||||
`intro` text,
|
||||
`story_background` text,
|
||||
`personality_tag` int DEFAULT NULL,
|
||||
`interest_tags` json DEFAULT NULL,
|
||||
`opening_line` text,
|
||||
`personality_prompt` text,
|
||||
`appearance_prompt` text,
|
||||
`appearance_params` json DEFAULT NULL,
|
||||
`hair_style_id` int DEFAULT NULL,
|
||||
`eye_color_id` int DEFAULT NULL,
|
||||
`outfit_desc` varchar(50) DEFAULT NULL,
|
||||
`outfit_top_id` bigint DEFAULT NULL,
|
||||
`outfit_bottom_id` bigint DEFAULT NULL,
|
||||
`outfit_dress_id` bigint DEFAULT NULL,
|
||||
`voice_id` bigint DEFAULT NULL,
|
||||
`image_url` varchar(255) DEFAULT NULL,
|
||||
`last_image_task_id` bigint DEFAULT NULL,
|
||||
`image_gen_used` int DEFAULT '0',
|
||||
`image_gen_limit` int DEFAULT '10',
|
||||
`image_gen_reset_date` date DEFAULT NULL,
|
||||
`init_model` varchar(64) DEFAULT NULL,
|
||||
`init_at` datetime DEFAULT NULL,
|
||||
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `user_id` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `nf_voice_library` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(64) NOT NULL,
|
||||
`gender` enum('male','female') NOT NULL,
|
||||
`style_tag` varchar(32) DEFAULT NULL,
|
||||
`avatar_url` varchar(255) DEFAULT NULL,
|
||||
`sample_audio_url` varchar(255) DEFAULT NULL,
|
||||
`tts_model_id` varchar(64) DEFAULT NULL,
|
||||
`is_default` tinyint(1) DEFAULT '0',
|
||||
`voice_code` varchar(64) NOT NULL,
|
||||
`is_owned` tinyint(1) DEFAULT '1',
|
||||
`price_gold` int DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `nf_girlfriend_mould` (
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(64) NOT NULL,
|
||||
`gender` enum('male','female') DEFAULT NULL,
|
||||
`weigh` int DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `nf_girlfriend_hobbies` (
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(64) NOT NULL,
|
||||
`weigh` int DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `nf_girlfriend_hairstyles` (
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(64) NOT NULL,
|
||||
`weigh` int DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `nf_girlfriend_eyecolor` (
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(64) NOT NULL,
|
||||
`weigh` int DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
"""
|
||||
|
||||
try:
|
||||
conn = pymysql.connect(
|
||||
host='127.0.0.1',
|
||||
port=3306,
|
||||
user='root',
|
||||
password='root',
|
||||
database='lover',
|
||||
charset='utf8mb4'
|
||||
)
|
||||
print("✓ 连接数据库成功")
|
||||
|
||||
cursor = conn.cursor()
|
||||
for statement in SQL_STATEMENTS.strip().split(';'):
|
||||
statement = statement.strip()
|
||||
if statement:
|
||||
cursor.execute(statement)
|
||||
print(f"✓ 执行成功")
|
||||
|
||||
conn.commit()
|
||||
print("✓ 所有表创建完成!")
|
||||
cursor.close()
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
print(f"✗ 失败: {e}")
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
"""导入 SQL 文件"""
|
||||
import pymysql
|
||||
|
||||
try:
|
||||
conn = pymysql.connect(
|
||||
host='127.0.0.1',
|
||||
port=3306,
|
||||
user='root',
|
||||
password='root',
|
||||
database='lover',
|
||||
charset='utf8mb4'
|
||||
)
|
||||
print("✓ 连接数据库成功")
|
||||
|
||||
with open('xunifriend.sql', 'r', encoding='utf8') as f:
|
||||
sql_content = f.read()
|
||||
|
||||
cursor = conn.cursor()
|
||||
# 分割并执行 SQL 语句
|
||||
statements = sql_content.split(';')
|
||||
for i, statement in enumerate(statements):
|
||||
statement = statement.strip()
|
||||
if statement:
|
||||
try:
|
||||
cursor.execute(statement)
|
||||
if (i + 1) % 100 == 0:
|
||||
print(f"已执行 {i + 1} 条语句...")
|
||||
except Exception as e:
|
||||
print(f"执行语句失败: {str(e)[:100]}")
|
||||
|
||||
conn.commit()
|
||||
print(f"✓ SQL 导入完成,共执行 {len([s for s in statements if s.strip()])} 条语句")
|
||||
cursor.close()
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
print(f"✗ 导入失败: {e}")
|
||||
19
init_db.py
19
init_db.py
|
|
@ -1,19 +0,0 @@
|
|||
"""
|
||||
数据库初始化脚本
|
||||
创建所有必需的表
|
||||
"""
|
||||
from lover.db import engine, Base
|
||||
from lover import models
|
||||
|
||||
def init_database():
|
||||
"""创建所有表"""
|
||||
print("开始创建数据库表...")
|
||||
try:
|
||||
Base.metadata.create_all(bind=engine)
|
||||
print("✓ 数据库表创建完成!")
|
||||
except Exception as e:
|
||||
print(f"✗ 创建表失败: {e}")
|
||||
raise
|
||||
|
||||
if __name__ == "__main__":
|
||||
init_database()
|
||||
Binary file not shown.
|
|
@ -89,6 +89,12 @@ def get_current_user(
|
|||
reg_step = payload.get("reg_step") or payload.get("stage") or 1
|
||||
gender = payload.get("gender") or 0
|
||||
nickname = payload.get("nickname") or payload.get("username") or ""
|
||||
|
||||
# 开发环境:自动提升 reg_step 到 2,方便测试
|
||||
if settings.APP_ENV == "development" and settings.DEBUG and reg_step < 2:
|
||||
logger.warning(f"开发环境:用户 reg_step={reg_step},自动提升到 2")
|
||||
reg_step = 2
|
||||
|
||||
if not user_id:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED, detail="用户中心缺少用户ID"
|
||||
|
|
@ -100,11 +106,12 @@ def get_current_user(
|
|||
nickname=nickname,
|
||||
token=token,
|
||||
)
|
||||
except HTTPException:
|
||||
except HTTPException as e:
|
||||
# 如果是开发环境,token 验证失败时也返回测试用户
|
||||
if settings.APP_ENV == "development" and settings.DEBUG:
|
||||
logger.warning(f"开发环境:token 验证失败,使用测试用户")
|
||||
logger.warning(f"开发环境:token 验证失败({e.detail}),使用测试用户")
|
||||
return AuthedUser(id=84, reg_step=2, gender=0, nickname="test-user", token="")
|
||||
raise
|
||||
|
||||
# 调试兜底:仅凭 X-User-Id 不校验 PHP,方便联调
|
||||
if x_user_id is not None:
|
||||
|
|
|
|||
70
test_backend_status.py
Normal file
70
test_backend_status.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
"""测试后端服务状态"""
|
||||
import requests
|
||||
import json
|
||||
|
||||
print("=" * 60)
|
||||
print("后端服务状态检查")
|
||||
print("=" * 60)
|
||||
|
||||
# 测试 PHP 后端
|
||||
print("\n1. 测试 PHP 后端 (http://127.0.0.1:8080)")
|
||||
print("-" * 60)
|
||||
try:
|
||||
response = requests.get("http://127.0.0.1:8080", timeout=3)
|
||||
print(f"✓ PHP 后端正常运行")
|
||||
print(f" 状态码: {response.status_code}")
|
||||
except requests.exceptions.ConnectionError:
|
||||
print("✗ PHP 后端未启动或无法连接")
|
||||
print(" 请使用 phpstudy 启动 Apache 服务")
|
||||
except Exception as e:
|
||||
print(f"✗ 连接错误: {e}")
|
||||
|
||||
# 测试 Python 后端
|
||||
print("\n2. 测试 Python 后端 (http://127.0.0.1:8000)")
|
||||
print("-" * 60)
|
||||
try:
|
||||
response = requests.get("http://127.0.0.1:8000/docs", timeout=3)
|
||||
print(f"✓ Python 后端正常运行")
|
||||
print(f" 状态码: {response.status_code}")
|
||||
except requests.exceptions.ConnectionError:
|
||||
print("✗ Python 后端未启动")
|
||||
print(" 请运行: python -m uvicorn lover.main:app --reload --host 127.0.0.1 --port 8000")
|
||||
except Exception as e:
|
||||
print(f"✗ 连接错误: {e}")
|
||||
|
||||
# 测试登录接口
|
||||
print("\n3. 测试登录接口")
|
||||
print("-" * 60)
|
||||
test_data = {
|
||||
"mobile": "13758924481",
|
||||
"password": "123456",
|
||||
"captcha": "223344"
|
||||
}
|
||||
print(f"测试数据: {json.dumps(test_data, ensure_ascii=False)}")
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
"http://127.0.0.1:8080/api/user/mobilelogin",
|
||||
json=test_data,
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"sid": "2"
|
||||
},
|
||||
timeout=5
|
||||
)
|
||||
print(f"状态码: {response.status_code}")
|
||||
print(f"响应: {json.dumps(response.json(), ensure_ascii=False, indent=2)}")
|
||||
except requests.exceptions.ConnectionError:
|
||||
print("✗ 无法连接到登录接口")
|
||||
print(" PHP 后端可能未正确配置")
|
||||
except Exception as e:
|
||||
print(f"✗ 请求错误: {e}")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("检查完成")
|
||||
print("=" * 60)
|
||||
|
||||
print("\n建议:")
|
||||
print("1. 如果 PHP 后端未启动,请使用 phpstudy 启动 Apache")
|
||||
print("2. 如果登录接口返回错误,检查数据库中是否有该用户")
|
||||
print("3. 如果需要创建测试用户,可以在数据库中手动添加")
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
"""测试配置加载"""
|
||||
from lover.config import settings
|
||||
|
||||
print(f"DATABASE_URL: {settings.DATABASE_URL}")
|
||||
print(f"APP_ENV: {settings.APP_ENV}")
|
||||
print(f"DEBUG: {settings.DEBUG}")
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
"""测试 SQLAlchemy 连接"""
|
||||
from sqlalchemy import text
|
||||
from lover.db import engine, SessionLocal
|
||||
from lover.models import Lover
|
||||
|
||||
try:
|
||||
# 测试连接
|
||||
with engine.connect() as conn:
|
||||
result = conn.execute(text("SELECT 1"))
|
||||
print("✓ Engine 连接成功")
|
||||
|
||||
# 测试 Session
|
||||
db = SessionLocal()
|
||||
try:
|
||||
lovers = db.query(Lover).limit(1).all()
|
||||
print(f"✓ Session 查询成功,找到 {len(lovers)} 条记录")
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ 失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>测试 Lover API</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Lover API 测试</h1>
|
||||
<button onclick="testBasic()">测试 /lover/basic</button>
|
||||
<button onclick="testConfig()">测试 /lover/config</button>
|
||||
<pre id="result"></pre>
|
||||
|
||||
<script>
|
||||
async function testBasic() {
|
||||
try {
|
||||
const response = await fetch('http://127.0.0.1:8000/lover/basic', {
|
||||
credentials: 'include'
|
||||
});
|
||||
const data = await response.json();
|
||||
document.getElementById('result').textContent = JSON.stringify(data, null, 2);
|
||||
} catch (error) {
|
||||
document.getElementById('result').textContent = 'Error: ' + error.message;
|
||||
}
|
||||
}
|
||||
|
||||
async function testConfig() {
|
||||
try {
|
||||
const response = await fetch('http://127.0.0.1:8000/lover/config', {
|
||||
credentials: 'include'
|
||||
});
|
||||
const data = await response.json();
|
||||
document.getElementById('result').textContent = JSON.stringify(data, null, 2);
|
||||
} catch (error) {
|
||||
document.getElementById('result').textContent = 'Error: ' + error.message;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
"""测试 MySQL 连接"""
|
||||
import pymysql
|
||||
|
||||
try:
|
||||
conn = pymysql.connect(
|
||||
host='127.0.0.1',
|
||||
port=3306,
|
||||
user='root',
|
||||
password='root',
|
||||
database='lover',
|
||||
charset='utf8mb4'
|
||||
)
|
||||
print("✓ MySQL 连接成功!")
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT VERSION()")
|
||||
version = cursor.fetchone()
|
||||
print(f"✓ MySQL 版本: {version[0]}")
|
||||
cursor.close()
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
print(f"✗ MySQL 连接失败: {e}")
|
||||
|
|
@ -25,6 +25,26 @@
|
|||
</view>
|
||||
</template>
|
||||
</uni-nav-bar>
|
||||
|
||||
<!-- Tab 栏 -->
|
||||
<view class="tab-bar">
|
||||
<scroll-view class="tab-scroll" scroll-x="true" :scroll-left="tabScrollLeft" scroll-with-animation>
|
||||
<view class="tab-list">
|
||||
<view
|
||||
v-for="(tab, index) in tabList"
|
||||
:key="index"
|
||||
class="tab-item"
|
||||
:class="{ 'active': currentTab === index }"
|
||||
@click="switchTab(index)">
|
||||
<text class="tab-text">{{ tab.name }}</text>
|
||||
<view v-if="currentTab === index" class="tab-indicator"></view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 聊天内容区域 -->
|
||||
<view v-show="currentTab === 0" class="tab-content">
|
||||
<image class="back"
|
||||
:src="loverBasicList.image_url ? loverBasicList.image_url : 'https://nvlovers.oss-cn-qingdao.aliyuncs.com/uploads/20251226/39c6f8899c15f60fc59207835f95e07a.png'"
|
||||
mode="aspectFill"></image>
|
||||
|
|
@ -164,8 +184,103 @@
|
|||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 录音弹框 -->
|
||||
|
||||
<!-- 唱歌页面 -->
|
||||
<view v-show="currentTab === 1" class="tab-content">
|
||||
<view class="feature-page">
|
||||
<view class="feature-title">唱歌功能</view>
|
||||
<view class="feature-desc">让她为你唱一首歌</view>
|
||||
<view class="song-list">
|
||||
<view class="song-item" v-for="(item,index) in singSongsList" :key="index" @click="selectSongDirect(item)">
|
||||
<view class="song-info">
|
||||
<text class="song-title">{{item.title}}</text>
|
||||
</view>
|
||||
<image class="song-icon" src="/static/images/chat_a6.png" mode="widthFix"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 跳舞页面 -->
|
||||
<view v-show="currentTab === 2" class="tab-content">
|
||||
<view class="feature-page">
|
||||
<view class="feature-title">跳舞功能</view>
|
||||
<view class="feature-desc">让她为你跳一支舞</view>
|
||||
<view class="dance-input">
|
||||
<input type="text" v-model="dancePrompt" placeholder="描述你想看的舞蹈动作" class="dance-input-field" />
|
||||
<view class="dance-btn" @click="requestDance">生成舞蹈</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 换服装页面 -->
|
||||
<view v-show="currentTab === 3" class="tab-content">
|
||||
<view class="feature-page">
|
||||
<view class="feature-title">换服装</view>
|
||||
<view class="feature-desc">为她挑选不同的服装</view>
|
||||
<view class="outfit-grid">
|
||||
<view class="outfit-item" v-for="i in 6" :key="i">
|
||||
<image class="outfit-image" src="/static/images/avatar.png" mode="aspectFill"></image>
|
||||
<text class="outfit-name">服装 {{i}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 刷礼物页面 -->
|
||||
<view v-show="currentTab === 4" class="tab-content">
|
||||
<view class="feature-page">
|
||||
<view class="feature-title">送礼物</view>
|
||||
<view class="feature-desc">送她一份心意</view>
|
||||
<view class="gift-grid">
|
||||
<view class="gift-item" v-for="i in 8" :key="i" @click="sendGift(i)">
|
||||
<image class="gift-image" src="/static/images/chat_a2.png" mode="widthFix"></image>
|
||||
<text class="gift-name">礼物 {{i}}</text>
|
||||
<text class="gift-price">{{i * 10}} 金币</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商城页面 -->
|
||||
<view v-show="currentTab === 5" class="tab-content">
|
||||
<view class="feature-page">
|
||||
<view class="feature-title">商城</view>
|
||||
<view class="feature-desc">购买更多功能和道具</view>
|
||||
<view class="shop-list">
|
||||
<view class="shop-item" v-for="i in 4" :key="i">
|
||||
<view class="shop-info">
|
||||
<text class="shop-title">套餐 {{i}}</text>
|
||||
<text class="shop-desc">包含多种功能和道具</text>
|
||||
</view>
|
||||
<view class="shop-price">
|
||||
<text class="price-value">¥{{i * 30}}</text>
|
||||
<view class="shop-buy-btn">购买</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 短剧页面 -->
|
||||
<view v-show="currentTab === 6" class="tab-content">
|
||||
<view class="feature-page">
|
||||
<view class="feature-title">短剧</view>
|
||||
<view class="feature-desc">观看精彩短剧内容</view>
|
||||
<view class="drama-list">
|
||||
<view class="drama-item" v-for="i in 3" :key="i">
|
||||
<image class="drama-cover" src="/static/images/avatar.png" mode="aspectFill"></image>
|
||||
<view class="drama-info">
|
||||
<text class="drama-title">短剧标题 {{i}}</text>
|
||||
<text class="drama-desc">精彩剧情简介...</text>
|
||||
<view class="drama-play-btn">播放</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 唱歌/跳舞弹框提示 -->
|
||||
<view class="alert" v-if="alertState">
|
||||
<view class="alert_hide" @click="alertState = false"></view>
|
||||
<view v-if="videoState" class="alert_opt fa sb">
|
||||
|
|
@ -269,6 +384,19 @@
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
// Tab 相关
|
||||
currentTab: 0,
|
||||
tabScrollLeft: 0,
|
||||
tabList: [
|
||||
{ name: '聊天', icon: '' },
|
||||
{ name: '唱歌', icon: '' },
|
||||
{ name: '跳舞', icon: '' },
|
||||
{ name: '换服装', icon: '' },
|
||||
{ name: '刷礼物', icon: '' },
|
||||
{ name: '商城', icon: '' },
|
||||
{ name: '短剧', icon: '' }
|
||||
],
|
||||
dancePrompt: '', // 跳舞描述
|
||||
// 可以在这里添加聊天数据
|
||||
// messages: [],
|
||||
loverBasicList: uni.getStorageSync('loverBasicList'),
|
||||
|
|
@ -349,6 +477,54 @@
|
|||
this.stopCurrentAudio();
|
||||
},
|
||||
methods: {
|
||||
// Tab 切换方法
|
||||
switchTab(index) {
|
||||
this.currentTab = index;
|
||||
// 计算滚动位置,使当前 tab 居中
|
||||
const tabWidth = 120; // 每个 tab 的宽度(rpx)
|
||||
const screenWidth = 750; // 屏幕宽度(rpx)
|
||||
this.tabScrollLeft = Math.max(0, (index * tabWidth) - (screenWidth / 2) + (tabWidth / 2));
|
||||
},
|
||||
// 直接选择歌曲并生成
|
||||
selectSongDirect(song) {
|
||||
this.songId = song.id;
|
||||
uni.showLoading({
|
||||
title: '生成中...'
|
||||
});
|
||||
SingGenerate({
|
||||
song_id: song.id
|
||||
}).then(res => {
|
||||
if (res.code == 1) {
|
||||
this.getSingGenerateTask(res.data.task_id);
|
||||
} else {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: res.msg,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
// 请求跳舞
|
||||
requestDance() {
|
||||
if (!this.dancePrompt || !this.dancePrompt.trim()) {
|
||||
uni.showToast({
|
||||
title: '请输入舞蹈描述',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.messageprompt = this.dancePrompt;
|
||||
this.savechatSing();
|
||||
},
|
||||
// 送礼物
|
||||
sendGift(giftId) {
|
||||
uni.showToast({
|
||||
title: `送出礼物 ${giftId}`,
|
||||
icon: 'success'
|
||||
});
|
||||
// 这里可以调用送礼物的 API
|
||||
},
|
||||
initAudio() {
|
||||
// 销毁旧的音频上下文(如果存在)
|
||||
if (this.audioContext) {
|
||||
|
|
@ -1750,6 +1926,311 @@
|
|||
</style>
|
||||
|
||||
<style scoped>
|
||||
/* Tab 栏样式 */
|
||||
.tab-bar {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
backdrop-filter: blur(10px);
|
||||
padding: 0;
|
||||
margin-top: 88rpx;
|
||||
}
|
||||
|
||||
.tab-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tab-list {
|
||||
display: inline-flex;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
position: relative;
|
||||
padding: 20rpx 30rpx;
|
||||
margin: 0 10rpx;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
transition: all 0.3s;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tab-item.active .tab-text {
|
||||
color: #FFFFFF;
|
||||
font-weight: bold;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.tab-indicator {
|
||||
position: absolute;
|
||||
bottom: 10rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 40rpx;
|
||||
height: 6rpx;
|
||||
background: linear-gradient(90deg, #E1C7FF, #B794F6);
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
|
||||
/* Tab 内容区域 */
|
||||
.tab-content {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* 功能页面通用样式 */
|
||||
.feature-page {
|
||||
padding: 40rpx;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
margin-bottom: 20rpx;
|
||||
text-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.feature-desc {
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
text-align: center;
|
||||
margin-bottom: 60rpx;
|
||||
}
|
||||
|
||||
/* 歌曲列表样式 */
|
||||
.song-list {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.song-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border-radius: 15rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.song-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.song-title {
|
||||
font-size: 32rpx;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.song-icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
}
|
||||
|
||||
/* 跳舞输入样式 */
|
||||
.dance-input {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: 20rpx;
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.dance-input-field {
|
||||
width: 100%;
|
||||
padding: 30rpx;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 15rpx;
|
||||
color: #FFFFFF;
|
||||
font-size: 28rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.dance-btn {
|
||||
width: 100%;
|
||||
padding: 30rpx;
|
||||
background: linear-gradient(90deg, #E1C7FF, #B794F6);
|
||||
border-radius: 15rpx;
|
||||
text-align: center;
|
||||
color: #FFFFFF;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 服装网格样式 */
|
||||
.outfit-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 30rpx;
|
||||
}
|
||||
|
||||
.outfit-item {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.outfit-image {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
border-radius: 15rpx;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.outfit-name {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
/* 礼物网格样式 */
|
||||
.gift-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 30rpx;
|
||||
}
|
||||
|
||||
.gift-item {
|
||||
text-align: center;
|
||||
padding: 20rpx;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 15rpx;
|
||||
}
|
||||
|
||||
.gift-image {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.gift-name {
|
||||
font-size: 24rpx;
|
||||
color: #FFFFFF;
|
||||
display: block;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
|
||||
.gift-price {
|
||||
font-size: 20rpx;
|
||||
color: #FFD700;
|
||||
}
|
||||
|
||||
/* 商城列表样式 */
|
||||
.shop-list {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.shop-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border-radius: 15rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.shop-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.shop-title {
|
||||
font-size: 32rpx;
|
||||
color: #FFFFFF;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.shop-desc {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
.shop-price {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.price-value {
|
||||
font-size: 36rpx;
|
||||
color: #FFD700;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.shop-buy-btn {
|
||||
padding: 15rpx 30rpx;
|
||||
background: linear-gradient(90deg, #E1C7FF, #B794F6);
|
||||
border-radius: 10rpx;
|
||||
color: #FFFFFF;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
/* 短剧列表样式 */
|
||||
.drama-list {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.drama-item {
|
||||
display: flex;
|
||||
padding: 20rpx;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border-radius: 15rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.drama-cover {
|
||||
width: 200rpx;
|
||||
height: 280rpx;
|
||||
border-radius: 10rpx;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.drama-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.drama-title {
|
||||
font-size: 32rpx;
|
||||
color: #FFFFFF;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.drama-desc {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.drama-play-btn {
|
||||
align-self: flex-start;
|
||||
padding: 15rpx 40rpx;
|
||||
background: linear-gradient(90deg, #E1C7FF, #B794F6);
|
||||
border-radius: 10rpx;
|
||||
color: #FFFFFF;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.body {
|
||||
position: relative;
|
||||
height: 100vh;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<view class="list_errors">手机号输入错误,请重新输入</view>
|
||||
</view> -->
|
||||
</view>
|
||||
<view class="list_content">
|
||||
<view class="list_content" v-if="!isDev">
|
||||
<view class="list_module fa">
|
||||
<image src="/static/images/login_password.png" mode="widthFix"></image>
|
||||
<input type="password" class="f1" v-model="form.password" placeholder="请输入密码"
|
||||
|
|
@ -28,6 +28,10 @@
|
|||
<view class="list_errors">密码输入错误,请重新输入</view>
|
||||
</view> -->
|
||||
</view>
|
||||
<!-- 开发模式提示 -->
|
||||
<view v-if="isDev" class="dev-tip">
|
||||
<text>🔧 开发模式:只需输入手机号即可登录</text>
|
||||
</view>
|
||||
<!-- <view class="list_content">
|
||||
<view class="list_module fa">
|
||||
<image src="/static/images/login_code.png" mode="widthFix"></image>
|
||||
|
|
@ -114,6 +118,7 @@
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
isDev: true, // 开发模式开关,上线时改为 false
|
||||
statusBarHeight: uni.getWindowInfo().statusBarHeight,
|
||||
form: {
|
||||
mobile: '',
|
||||
|
|
@ -399,38 +404,63 @@
|
|||
}
|
||||
},
|
||||
submit() {
|
||||
// 使用 data 中的开发模式开关
|
||||
if (!this.selectStats) {
|
||||
uni.showToast({
|
||||
title: "请阅读并同意协议",
|
||||
icon: 'none',
|
||||
position: 'top'
|
||||
})
|
||||
} else if (this.form.mobile == '') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.form.mobile == '') {
|
||||
uni.showToast({
|
||||
title: "请输入手机号",
|
||||
icon: 'none',
|
||||
position: 'top'
|
||||
})
|
||||
} else if (!isPhone(this.form.mobile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isPhone(this.form.mobile)) {
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
title: "请输入正确手机号"
|
||||
})
|
||||
} else if (this.form.password == '') {
|
||||
return;
|
||||
}
|
||||
|
||||
// 开发环境:跳过密码和验证码验证
|
||||
if (this.isDev) {
|
||||
console.log('开发模式:跳过密码验证');
|
||||
// 自动填充密码和验证码
|
||||
this.form.password = this.form.password || '123456';
|
||||
this.form.captcha = this.form.captcha || 223344;
|
||||
this.mobilelogin();
|
||||
return;
|
||||
}
|
||||
|
||||
// 生产环境:正常验证
|
||||
if (this.form.password == '') {
|
||||
uni.showToast({
|
||||
title: "请输入密码",
|
||||
icon: 'none',
|
||||
position: 'top'
|
||||
})
|
||||
} else if (this.form.captcha == '') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.form.captcha == '') {
|
||||
uni.showToast({
|
||||
title: "请输入验证码",
|
||||
icon: 'none',
|
||||
position: 'top'
|
||||
})
|
||||
} else {
|
||||
this.mobilelogin()
|
||||
return;
|
||||
}
|
||||
|
||||
this.mobilelogin();
|
||||
},
|
||||
back() {
|
||||
uni.navigateBack({
|
||||
|
|
@ -483,6 +513,21 @@
|
|||
position: relative;
|
||||
margin: 72rpx 0 0 0;
|
||||
}
|
||||
|
||||
/* 开发模式提示 */
|
||||
.dev-tip {
|
||||
margin: 30rpx 0;
|
||||
padding: 20rpx 30rpx;
|
||||
background: linear-gradient(90deg, #FFF3E0, #FFE0B2);
|
||||
border-radius: 12rpx;
|
||||
border-left: 6rpx solid #FF9800;
|
||||
}
|
||||
|
||||
.dev-tip text {
|
||||
font-size: 26rpx;
|
||||
color: #E65100;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
|
||||
.list_module {
|
||||
position: relative;
|
||||
|
|
|
|||
13
xunifriend_RaeeC/.env
Normal file
13
xunifriend_RaeeC/.env
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
app_debug = true
|
||||
app_trace = true
|
||||
|
||||
[database]
|
||||
type = mysql
|
||||
hostname = 127.0.0.1
|
||||
database = fastadmin
|
||||
username = root
|
||||
password = root
|
||||
hostport = 3306
|
||||
charset = utf8mb4
|
||||
prefix = nf_
|
||||
debug = true
|
||||
|
|
@ -93,9 +93,13 @@ class User extends Api
|
|||
$this->error(__('Account is locked'));
|
||||
}
|
||||
|
||||
//验证密码
|
||||
if (!$this->auth->checkpwd($user, $password)) {
|
||||
$this->error(__('Password is incorrect'));
|
||||
// 开发环境:跳过密码验证
|
||||
$isDev = true; // 开发模式开关,上线时改为 false
|
||||
if (!$isDev) {
|
||||
//验证密码
|
||||
if (!$this->auth->checkpwd($user, $password)) {
|
||||
$this->error(__('Password is incorrect'));
|
||||
}
|
||||
}
|
||||
|
||||
//如果已经有账号则直接登录
|
||||
|
|
|
|||
2
xunifriend_RaeeC/public/test.php
Normal file
2
xunifriend_RaeeC/public/test.php
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<?php
|
||||
phpinfo();
|
||||
3902
xunifriend_RaeeC/runtime/log/202602/01.log
Normal file
3902
xunifriend_RaeeC/runtime/log/202602/01.log
Normal file
File diff suppressed because it is too large
Load Diff
1
开发/2026年2月1日.md
Normal file
1
开发/2026年2月1日.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
1. 将密码校验删除,因为无法生成模型,用最简单的方法来尝试这些内容。
|
||||
Loading…
Reference in New Issue
Block a user