去除密码验证

This commit is contained in:
xiao12feng8 2026-02-01 10:03:21 +08:00
parent 19bd5910ad
commit 4286338fa0
18 changed files with 4560 additions and 266 deletions

23
.env
View File

@ -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=

View File

@ -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}")

View File

@ -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}")

View File

@ -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()

View File

@ -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
View 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. 如果需要创建测试用户,可以在数据库中手动添加")

View File

@ -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}")

View File

@ -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()

View File

@ -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>

View File

@ -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}")

View File

@ -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>
@ -165,7 +185,102 @@
</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;

View File

@ -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({
@ -484,6 +514,21 @@
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;
padding: 20rpx 30rpx;

13
xunifriend_RaeeC/.env Normal file
View 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

View File

@ -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'));
}
}
//如果已经有账号则直接登录

View File

@ -0,0 +1,2 @@
<?php
phpinfo();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
1. 将密码校验删除,因为无法生成模型,用最简单的方法来尝试这些内容。