功能:邀请有问题
This commit is contained in:
parent
57053f08ab
commit
8613e1560b
33
lover/migrations/add_invite_fields.sql
Normal file
33
lover/migrations/add_invite_fields.sql
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
-- 添加邀请码相关字段到 nf_user 表
|
||||||
|
-- 执行时间:2026-02-03
|
||||||
|
|
||||||
|
USE fastadmin;
|
||||||
|
|
||||||
|
-- 添加邀请码字段
|
||||||
|
ALTER TABLE `nf_user`
|
||||||
|
ADD COLUMN `invite_code` VARCHAR(10) DEFAULT NULL COMMENT '邀请码' AFTER `vip_endtime`,
|
||||||
|
ADD COLUMN `invited_by` VARCHAR(10) DEFAULT NULL COMMENT '被谁邀请(邀请码)' AFTER `invite_code`,
|
||||||
|
ADD COLUMN `invite_count` INT(11) DEFAULT 0 COMMENT '邀请人数' AFTER `invited_by`,
|
||||||
|
ADD COLUMN `invite_reward_total` DECIMAL(10,2) DEFAULT 0.00 COMMENT '邀请奖励总额' AFTER `invite_count`;
|
||||||
|
|
||||||
|
-- 添加唯一索引
|
||||||
|
ALTER TABLE `nf_user`
|
||||||
|
ADD UNIQUE INDEX `idx_invite_code` (`invite_code`);
|
||||||
|
|
||||||
|
-- 添加普通索引
|
||||||
|
ALTER TABLE `nf_user`
|
||||||
|
ADD INDEX `idx_invited_by` (`invited_by`);
|
||||||
|
|
||||||
|
-- 验证字段是否添加成功
|
||||||
|
SELECT
|
||||||
|
COLUMN_NAME,
|
||||||
|
COLUMN_TYPE,
|
||||||
|
IS_NULLABLE,
|
||||||
|
COLUMN_DEFAULT,
|
||||||
|
COLUMN_COMMENT
|
||||||
|
FROM
|
||||||
|
INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE
|
||||||
|
TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND COLUMN_NAME IN ('invite_code', 'invited_by', 'invite_count', 'invite_reward_total');
|
||||||
20
lover/migrations/check_invite_fields.sql
Normal file
20
lover/migrations/check_invite_fields.sql
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
-- 检查 nf_user 表中邀请码相关字段的情况
|
||||||
|
USE fastadmin;
|
||||||
|
|
||||||
|
-- 查看表结构
|
||||||
|
DESCRIBE nf_user;
|
||||||
|
|
||||||
|
-- 查看邀请码相关字段
|
||||||
|
SELECT
|
||||||
|
COLUMN_NAME,
|
||||||
|
COLUMN_TYPE,
|
||||||
|
IS_NULLABLE,
|
||||||
|
COLUMN_DEFAULT,
|
||||||
|
COLUMN_COMMENT
|
||||||
|
FROM
|
||||||
|
INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE
|
||||||
|
TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND COLUMN_NAME IN ('invite_code', 'invited_by', 'invite_count', 'invite_reward_total')
|
||||||
|
ORDER BY ORDINAL_POSITION;
|
||||||
107
lover/migrations/fix_invite_complete.sql
Normal file
107
lover/migrations/fix_invite_complete.sql
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
-- 邀请码功能完整修复脚本
|
||||||
|
-- 执行时间:2026-02-03
|
||||||
|
-- 说明:这个脚本会检查并修复所有邀请码相关的问题
|
||||||
|
|
||||||
|
USE fastadmin;
|
||||||
|
|
||||||
|
-- ========================================
|
||||||
|
-- 第 1 步:修复字段类型
|
||||||
|
-- ========================================
|
||||||
|
|
||||||
|
-- 修复 invited_by 字段类型(从 int 改为 varchar(10))
|
||||||
|
ALTER TABLE `nf_user`
|
||||||
|
MODIFY COLUMN `invited_by` VARCHAR(10) DEFAULT NULL COMMENT '被谁邀请(邀请码)';
|
||||||
|
|
||||||
|
-- 修复 invite_reward_total 字段类型(从 int 改为 decimal(10,2))
|
||||||
|
ALTER TABLE `nf_user`
|
||||||
|
MODIFY COLUMN `invite_reward_total` DECIMAL(10,2) DEFAULT 0.00 COMMENT '邀请奖励总额';
|
||||||
|
|
||||||
|
-- 确保 invite_code 字段正确
|
||||||
|
ALTER TABLE `nf_user`
|
||||||
|
MODIFY COLUMN `invite_code` VARCHAR(10) DEFAULT NULL COMMENT '邀请码';
|
||||||
|
|
||||||
|
-- 确保 invite_count 字段正确
|
||||||
|
ALTER TABLE `nf_user`
|
||||||
|
MODIFY COLUMN `invite_count` INT(11) DEFAULT 0 COMMENT '邀请人数';
|
||||||
|
|
||||||
|
SELECT '✅ 步骤 1:字段类型修复完成' AS '进度';
|
||||||
|
|
||||||
|
-- ========================================
|
||||||
|
-- 第 2 步:检查并添加索引
|
||||||
|
-- ========================================
|
||||||
|
|
||||||
|
-- 检查 invite_code 唯一索引
|
||||||
|
SET @index_exists = 0;
|
||||||
|
SELECT COUNT(*) INTO @index_exists
|
||||||
|
FROM INFORMATION_SCHEMA.STATISTICS
|
||||||
|
WHERE TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND INDEX_NAME = 'idx_invite_code';
|
||||||
|
|
||||||
|
SET @sql = IF(@index_exists = 0,
|
||||||
|
'ALTER TABLE `nf_user` ADD UNIQUE INDEX `idx_invite_code` (`invite_code`)',
|
||||||
|
'SELECT ''idx_invite_code 索引已存在'' AS message');
|
||||||
|
PREPARE stmt FROM @sql;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
-- 检查 invited_by 索引
|
||||||
|
SET @index_exists = 0;
|
||||||
|
SELECT COUNT(*) INTO @index_exists
|
||||||
|
FROM INFORMATION_SCHEMA.STATISTICS
|
||||||
|
WHERE TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND INDEX_NAME = 'idx_invited_by';
|
||||||
|
|
||||||
|
SET @sql = IF(@index_exists = 0,
|
||||||
|
'ALTER TABLE `nf_user` ADD INDEX `idx_invited_by` (`invited_by`)',
|
||||||
|
'SELECT ''idx_invited_by 索引已存在'' AS message');
|
||||||
|
PREPARE stmt FROM @sql;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
SELECT '✅ 步骤 2:索引检查完成' AS '进度';
|
||||||
|
|
||||||
|
-- ========================================
|
||||||
|
-- 第 3 步:验证修复结果
|
||||||
|
-- ========================================
|
||||||
|
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
SELECT '邀请码字段信息' AS '';
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
COLUMN_NAME AS '字段名',
|
||||||
|
COLUMN_TYPE AS '类型',
|
||||||
|
IS_NULLABLE AS '可空',
|
||||||
|
COLUMN_DEFAULT AS '默认值',
|
||||||
|
COLUMN_COMMENT AS '注释'
|
||||||
|
FROM
|
||||||
|
INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE
|
||||||
|
TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND COLUMN_NAME IN ('invite_code', 'invited_by', 'invite_count', 'invite_reward_total')
|
||||||
|
ORDER BY ORDINAL_POSITION;
|
||||||
|
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
SELECT '索引信息' AS '';
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
INDEX_NAME AS '索引名',
|
||||||
|
COLUMN_NAME AS '列名',
|
||||||
|
NON_UNIQUE AS '非唯一',
|
||||||
|
INDEX_TYPE AS '索引类型'
|
||||||
|
FROM
|
||||||
|
INFORMATION_SCHEMA.STATISTICS
|
||||||
|
WHERE
|
||||||
|
TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND INDEX_NAME IN ('idx_invite_code', 'idx_invited_by')
|
||||||
|
ORDER BY INDEX_NAME, SEQ_IN_INDEX;
|
||||||
|
|
||||||
|
SELECT '========================================' AS '';
|
||||||
|
SELECT '✅ 邀请码功能修复完成!' AS '状态';
|
||||||
|
SELECT '请重启 Python 服务以使更改生效' AS '提示';
|
||||||
|
SELECT '========================================' AS '';
|
||||||
56
lover/migrations/fix_invite_field_types.sql
Normal file
56
lover/migrations/fix_invite_field_types.sql
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
-- 修复邀请码字段类型错误
|
||||||
|
-- 执行时间:2026-02-03
|
||||||
|
-- 问题:invited_by 和 invite_reward_total 字段类型不正确
|
||||||
|
|
||||||
|
USE fastadmin;
|
||||||
|
|
||||||
|
-- 备份当前数据(可选,但建议)
|
||||||
|
-- CREATE TABLE nf_user_backup_20260203 AS SELECT * FROM nf_user;
|
||||||
|
|
||||||
|
-- 修复 invited_by 字段类型(从 int 改为 varchar(10))
|
||||||
|
ALTER TABLE `nf_user`
|
||||||
|
MODIFY COLUMN `invited_by` VARCHAR(10) DEFAULT NULL COMMENT '被谁邀请(邀请码)';
|
||||||
|
|
||||||
|
-- 修复 invite_reward_total 字段类型(从 int 改为 decimal(10,2))
|
||||||
|
ALTER TABLE `nf_user`
|
||||||
|
MODIFY COLUMN `invite_reward_total` DECIMAL(10,2) DEFAULT 0.00 COMMENT '邀请奖励总额';
|
||||||
|
|
||||||
|
-- 确保 invite_code 字段有注释
|
||||||
|
ALTER TABLE `nf_user`
|
||||||
|
MODIFY COLUMN `invite_code` VARCHAR(10) DEFAULT NULL COMMENT '邀请码';
|
||||||
|
|
||||||
|
-- 确保 invite_count 字段有注释
|
||||||
|
ALTER TABLE `nf_user`
|
||||||
|
MODIFY COLUMN `invite_count` INT(11) DEFAULT 0 COMMENT '邀请人数';
|
||||||
|
|
||||||
|
-- 验证修复结果
|
||||||
|
SELECT
|
||||||
|
COLUMN_NAME AS '字段名',
|
||||||
|
COLUMN_TYPE AS '类型',
|
||||||
|
IS_NULLABLE AS '可空',
|
||||||
|
COLUMN_DEFAULT AS '默认值',
|
||||||
|
COLUMN_COMMENT AS '注释'
|
||||||
|
FROM
|
||||||
|
INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE
|
||||||
|
TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND COLUMN_NAME IN ('invite_code', 'invited_by', 'invite_count', 'invite_reward_total')
|
||||||
|
ORDER BY ORDINAL_POSITION;
|
||||||
|
|
||||||
|
-- 显示修复后的索引信息
|
||||||
|
SELECT
|
||||||
|
INDEX_NAME AS '索引名',
|
||||||
|
COLUMN_NAME AS '列名',
|
||||||
|
NON_UNIQUE AS '非唯一',
|
||||||
|
INDEX_TYPE AS '索引类型'
|
||||||
|
FROM
|
||||||
|
INFORMATION_SCHEMA.STATISTICS
|
||||||
|
WHERE
|
||||||
|
TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND INDEX_NAME IN ('idx_invite_code', 'idx_invited_by')
|
||||||
|
ORDER BY INDEX_NAME, SEQ_IN_INDEX;
|
||||||
|
|
||||||
|
-- 显示成功消息
|
||||||
|
SELECT '✅ 邀请码字段类型修复完成!' AS '状态';
|
||||||
123
lover/migrations/fix_invite_fields.sql
Normal file
123
lover/migrations/fix_invite_fields.sql
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
-- 修复邀请码功能 - 检查并添加缺失的字段和索引
|
||||||
|
-- 执行时间:2026-02-03
|
||||||
|
|
||||||
|
USE fastadmin;
|
||||||
|
|
||||||
|
-- 检查并添加 invite_code 字段(如果不存在)
|
||||||
|
SET @col_exists = 0;
|
||||||
|
SELECT COUNT(*) INTO @col_exists
|
||||||
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND COLUMN_NAME = 'invite_code';
|
||||||
|
|
||||||
|
SET @sql = IF(@col_exists = 0,
|
||||||
|
'ALTER TABLE `nf_user` ADD COLUMN `invite_code` VARCHAR(10) DEFAULT NULL COMMENT ''邀请码'' AFTER `vip_endtime`',
|
||||||
|
'SELECT ''invite_code 字段已存在'' AS message');
|
||||||
|
PREPARE stmt FROM @sql;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
-- 检查并添加 invited_by 字段(如果不存在)
|
||||||
|
SET @col_exists = 0;
|
||||||
|
SELECT COUNT(*) INTO @col_exists
|
||||||
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND COLUMN_NAME = 'invited_by';
|
||||||
|
|
||||||
|
SET @sql = IF(@col_exists = 0,
|
||||||
|
'ALTER TABLE `nf_user` ADD COLUMN `invited_by` VARCHAR(10) DEFAULT NULL COMMENT ''被谁邀请(邀请码)'' AFTER `invite_code`',
|
||||||
|
'SELECT ''invited_by 字段已存在'' AS message');
|
||||||
|
PREPARE stmt FROM @sql;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
-- 检查并添加 invite_count 字段(如果不存在)
|
||||||
|
SET @col_exists = 0;
|
||||||
|
SELECT COUNT(*) INTO @col_exists
|
||||||
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND COLUMN_NAME = 'invite_count';
|
||||||
|
|
||||||
|
SET @sql = IF(@col_exists = 0,
|
||||||
|
'ALTER TABLE `nf_user` ADD COLUMN `invite_count` INT(11) DEFAULT 0 COMMENT ''邀请人数'' AFTER `invited_by`',
|
||||||
|
'SELECT ''invite_count 字段已存在'' AS message');
|
||||||
|
PREPARE stmt FROM @sql;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
-- 检查并添加 invite_reward_total 字段(如果不存在)
|
||||||
|
SET @col_exists = 0;
|
||||||
|
SELECT COUNT(*) INTO @col_exists
|
||||||
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND COLUMN_NAME = 'invite_reward_total';
|
||||||
|
|
||||||
|
SET @sql = IF(@col_exists = 0,
|
||||||
|
'ALTER TABLE `nf_user` ADD COLUMN `invite_reward_total` DECIMAL(10,2) DEFAULT 0.00 COMMENT ''邀请奖励总额'' AFTER `invite_count`',
|
||||||
|
'SELECT ''invite_reward_total 字段已存在'' AS message');
|
||||||
|
PREPARE stmt FROM @sql;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
-- 检查并添加 invite_code 唯一索引(如果不存在)
|
||||||
|
SET @index_exists = 0;
|
||||||
|
SELECT COUNT(*) INTO @index_exists
|
||||||
|
FROM INFORMATION_SCHEMA.STATISTICS
|
||||||
|
WHERE TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND INDEX_NAME = 'idx_invite_code';
|
||||||
|
|
||||||
|
SET @sql = IF(@index_exists = 0,
|
||||||
|
'ALTER TABLE `nf_user` ADD UNIQUE INDEX `idx_invite_code` (`invite_code`)',
|
||||||
|
'SELECT ''idx_invite_code 索引已存在'' AS message');
|
||||||
|
PREPARE stmt FROM @sql;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
-- 检查并添加 invited_by 索引(如果不存在)
|
||||||
|
SET @index_exists = 0;
|
||||||
|
SELECT COUNT(*) INTO @index_exists
|
||||||
|
FROM INFORMATION_SCHEMA.STATISTICS
|
||||||
|
WHERE TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND INDEX_NAME = 'idx_invited_by';
|
||||||
|
|
||||||
|
SET @sql = IF(@index_exists = 0,
|
||||||
|
'ALTER TABLE `nf_user` ADD INDEX `idx_invited_by` (`invited_by`)',
|
||||||
|
'SELECT ''idx_invited_by 索引已存在'' AS message');
|
||||||
|
PREPARE stmt FROM @sql;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
|
-- 显示最终的字段信息
|
||||||
|
SELECT
|
||||||
|
COLUMN_NAME AS '字段名',
|
||||||
|
COLUMN_TYPE AS '类型',
|
||||||
|
IS_NULLABLE AS '可空',
|
||||||
|
COLUMN_DEFAULT AS '默认值',
|
||||||
|
COLUMN_COMMENT AS '注释'
|
||||||
|
FROM
|
||||||
|
INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE
|
||||||
|
TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND COLUMN_NAME IN ('invite_code', 'invited_by', 'invite_count', 'invite_reward_total')
|
||||||
|
ORDER BY ORDINAL_POSITION;
|
||||||
|
|
||||||
|
-- 显示索引信息
|
||||||
|
SELECT
|
||||||
|
INDEX_NAME AS '索引名',
|
||||||
|
COLUMN_NAME AS '列名',
|
||||||
|
NON_UNIQUE AS '非唯一',
|
||||||
|
INDEX_TYPE AS '索引类型'
|
||||||
|
FROM
|
||||||
|
INFORMATION_SCHEMA.STATISTICS
|
||||||
|
WHERE
|
||||||
|
TABLE_SCHEMA = 'fastadmin'
|
||||||
|
AND TABLE_NAME = 'nf_user'
|
||||||
|
AND INDEX_NAME IN ('idx_invite_code', 'idx_invited_by')
|
||||||
|
ORDER BY INDEX_NAME, SEQ_IN_INDEX;
|
||||||
73
lover/migrations/test_invite_function.sql
Normal file
73
lover/migrations/test_invite_function.sql
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
-- 测试邀请码功能
|
||||||
|
-- 执行时间:2026-02-03
|
||||||
|
|
||||||
|
USE fastadmin;
|
||||||
|
|
||||||
|
-- 1. 查看当前用户的邀请码信息
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
username,
|
||||||
|
nickname,
|
||||||
|
invite_code AS '邀请码',
|
||||||
|
invited_by AS '被谁邀请',
|
||||||
|
invite_count AS '邀请人数',
|
||||||
|
invite_reward_total AS '邀请奖励',
|
||||||
|
money AS '金币余额'
|
||||||
|
FROM nf_user
|
||||||
|
WHERE id IN (
|
||||||
|
SELECT id FROM nf_user
|
||||||
|
ORDER BY id DESC
|
||||||
|
LIMIT 10
|
||||||
|
)
|
||||||
|
ORDER BY id DESC;
|
||||||
|
|
||||||
|
-- 2. 查看有邀请码的用户
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
username,
|
||||||
|
nickname,
|
||||||
|
invite_code AS '邀请码',
|
||||||
|
invite_count AS '邀请人数',
|
||||||
|
invite_reward_total AS '邀请奖励',
|
||||||
|
money AS '金币余额'
|
||||||
|
FROM nf_user
|
||||||
|
WHERE invite_code IS NOT NULL
|
||||||
|
ORDER BY invite_count DESC, id DESC
|
||||||
|
LIMIT 20;
|
||||||
|
|
||||||
|
-- 3. 查看使用了邀请码的用户
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
username,
|
||||||
|
nickname,
|
||||||
|
invited_by AS '使用的邀请码',
|
||||||
|
money AS '金币余额',
|
||||||
|
createtime AS '注册时间'
|
||||||
|
FROM nf_user
|
||||||
|
WHERE invited_by IS NOT NULL
|
||||||
|
ORDER BY id DESC
|
||||||
|
LIMIT 20;
|
||||||
|
|
||||||
|
-- 4. 查看邀请相关的金币日志
|
||||||
|
SELECT
|
||||||
|
l.id,
|
||||||
|
l.user_id AS '用户ID',
|
||||||
|
u.username AS '用户名',
|
||||||
|
l.money AS '金币变动',
|
||||||
|
l.before AS '变动前',
|
||||||
|
l.after AS '变动后',
|
||||||
|
l.memo AS '备注',
|
||||||
|
FROM_UNIXTIME(l.createtime) AS '时间'
|
||||||
|
FROM nf_user_money_log l
|
||||||
|
LEFT JOIN nf_user u ON l.user_id = u.id
|
||||||
|
WHERE l.memo LIKE '%邀请%'
|
||||||
|
ORDER BY l.createtime DESC
|
||||||
|
LIMIT 20;
|
||||||
|
|
||||||
|
-- 5. 统计邀请数据
|
||||||
|
SELECT
|
||||||
|
COUNT(DISTINCT CASE WHEN invite_code IS NOT NULL THEN id END) AS '有邀请码的用户数',
|
||||||
|
COUNT(DISTINCT CASE WHEN invited_by IS NOT NULL THEN id END) AS '使用邀请码的用户数',
|
||||||
|
SUM(CASE WHEN invite_code IS NOT NULL THEN invite_count ELSE 0 END) AS '总邀请人数',
|
||||||
|
SUM(CASE WHEN invite_code IS NOT NULL THEN invite_reward_total ELSE 0 END) AS '总邀请奖励'
|
||||||
|
FROM nf_user;
|
||||||
|
|
@ -929,8 +929,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getBobbiesList: '',
|
getBobbiesList: {
|
||||||
loverBasicList: '',
|
reg_step: 1, // 默认第一步:完善个人资料
|
||||||
|
level: 0,
|
||||||
|
intimacy: 0,
|
||||||
|
next_level_intimacy: 100
|
||||||
|
},
|
||||||
|
loverBasicList: null, // 改为 null 而不是空字符串
|
||||||
underAgeEnabled: false, // 添加青少年模式状态变量
|
underAgeEnabled: false, // 添加青少年模式状态变量
|
||||||
historyModalVisible: false,
|
historyModalVisible: false,
|
||||||
historyModalType: 'sing',
|
historyModalType: 'sing',
|
||||||
|
|
|
||||||
547
开发/2026年2月3日/登录无法进入问题修复.md
Normal file
547
开发/2026年2月3日/登录无法进入问题修复.md
Normal file
|
|
@ -0,0 +1,547 @@
|
||||||
|
# 登录显示成功但无法进入系统问题修复
|
||||||
|
|
||||||
|
## 问题描述
|
||||||
|
|
||||||
|
用户登录后显示"登录成功",但页面一直停留在登录页面或显示空白,无法进入系统。
|
||||||
|
|
||||||
|
## 问题原因分析
|
||||||
|
|
||||||
|
### 原因 1:`getBobbiesList` 初始值为空字符串
|
||||||
|
|
||||||
|
**代码位置**:`xuniYou/pages/index/index.vue` 第 932 行
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
getBobbiesList: '', // ❌ 初始值为空字符串
|
||||||
|
```
|
||||||
|
|
||||||
|
**问题**:
|
||||||
|
- 页面使用 `v-show="getBobbiesList.reg_step == 1 || getBobbiesList.reg_step == 2 || getBobbiesList.reg_step == 3"` 来判断显示哪个界面
|
||||||
|
- 当 `getBobbiesList` 为空字符串时,`getBobbiesList.reg_step` 为 `undefined`
|
||||||
|
- 导致所有 `v-show` 条件都不满足,页面显示空白
|
||||||
|
|
||||||
|
### 原因 2:`getUserBasic()` 调用时机问题
|
||||||
|
|
||||||
|
**代码位置**:`xuniYou/pages/index/index.vue` 第 960-969 行
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
onShow() {
|
||||||
|
this.checkUnderAgeStatus();
|
||||||
|
|
||||||
|
if (uni.getStorageSync('token')) {
|
||||||
|
this.getUserBasic()
|
||||||
|
this.loverBasic()
|
||||||
|
this.loadHomeLooks()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**问题**:
|
||||||
|
- 只有在 `onShow()` 时才调用 `getUserBasic()`
|
||||||
|
- 如果从登录页跳转过来,可能还没来得及执行 `onShow()`
|
||||||
|
- 或者 token 还没有正确保存到 storage
|
||||||
|
|
||||||
|
### 原因 3:API 请求失败
|
||||||
|
|
||||||
|
可能的原因:
|
||||||
|
- PHP 后端服务未启动(端口 30100)
|
||||||
|
- Token 无效或过期
|
||||||
|
- 网络请求失败
|
||||||
|
- CORS 跨域问题
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 解决方案
|
||||||
|
|
||||||
|
### 方案 1:修改 `getBobbiesList` 初始值(推荐)
|
||||||
|
|
||||||
|
将初始值从空字符串改为对象,并设置默认的 `reg_step`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 修改前
|
||||||
|
getBobbiesList: '',
|
||||||
|
|
||||||
|
// 修改后
|
||||||
|
getBobbiesList: {
|
||||||
|
reg_step: 1 // 默认显示第一步:完善个人资料
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方案 2:添加加载状态
|
||||||
|
|
||||||
|
添加一个加载状态,在数据加载完成前显示加载提示:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isLoading: true, // 添加加载状态
|
||||||
|
getBobbiesList: {
|
||||||
|
reg_step: 1
|
||||||
|
},
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
在模板中添加加载提示:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<view v-if="isLoading" class="loading-container">
|
||||||
|
<view class="loading-text">加载中...</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-else>
|
||||||
|
<!-- 原有内容 -->
|
||||||
|
</view>
|
||||||
|
```
|
||||||
|
|
||||||
|
在 `getUserBasic()` 成功后设置:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
getUserBasic() {
|
||||||
|
GetUserBasic({}).then(res => {
|
||||||
|
if (res.code == 1) {
|
||||||
|
let data = res.data
|
||||||
|
// ...
|
||||||
|
this.getBobbiesList = data
|
||||||
|
this.isLoading = false // 加载完成
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.isLoading = false // 加载失败也要隐藏加载状态
|
||||||
|
uni.showToast({
|
||||||
|
title: '加载失败,请重试',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方案 3:在 `onLoad` 时也调用 `getUserBasic()`
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
onLoad(options) {
|
||||||
|
//#ifdef MP-WEIXIN
|
||||||
|
this.checkPermission()
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
// 如果有 tab 参数,切换到对应的 tab
|
||||||
|
if (options && options.tab) {
|
||||||
|
const tabIndex = parseInt(options.tab);
|
||||||
|
if (!isNaN(tabIndex) && tabIndex >= 0 && tabIndex < this.tabs.length) {
|
||||||
|
this.currentTab = tabIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加:在 onLoad 时也检查并加载用户数据
|
||||||
|
if (uni.getStorageSync('token')) {
|
||||||
|
this.getUserBasic()
|
||||||
|
this.loverBasic()
|
||||||
|
this.loadHomeLooks()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onReady() {
|
||||||
|
this.getServerData();
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 快速修复步骤
|
||||||
|
|
||||||
|
### 第 1 步:检查后端服务是否运行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Windows - 检查 PHP 服务
|
||||||
|
netstat -ano | findstr :30100
|
||||||
|
|
||||||
|
# 如果没有运行,启动 PHP 服务
|
||||||
|
cd xunifriend_RaeeC/public
|
||||||
|
php -S 0.0.0.0:30100
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第 2 步:检查浏览器控制台
|
||||||
|
|
||||||
|
1. 打开浏览器开发者工具(F12)
|
||||||
|
2. 切换到 Console 标签
|
||||||
|
3. 查看是否有错误信息
|
||||||
|
4. 切换到 Network 标签
|
||||||
|
5. 查看 API 请求是否成功
|
||||||
|
|
||||||
|
**关键检查点**:
|
||||||
|
- `/api/user_basic/get_user_basic` 请求是否返回 200
|
||||||
|
- 响应数据中是否包含 `reg_step` 字段
|
||||||
|
- Token 是否正确传递
|
||||||
|
|
||||||
|
### 第 3 步:检查 Token
|
||||||
|
|
||||||
|
在浏览器控制台执行:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 检查 token 是否存在
|
||||||
|
console.log('Token:', uni.getStorageSync('token'))
|
||||||
|
|
||||||
|
// 检查用户信息
|
||||||
|
console.log('UserInfo:', uni.getStorageSync('userinfo'))
|
||||||
|
|
||||||
|
// 手动调用 getUserBasic
|
||||||
|
// 在 index 页面的控制台执行
|
||||||
|
this.getUserBasic()
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第 4 步:修改代码(推荐方案 1)
|
||||||
|
|
||||||
|
修改 `xuniYou/pages/index/index.vue` 第 932 行:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 修改前
|
||||||
|
getBobbiesList: '',
|
||||||
|
|
||||||
|
// 修改后
|
||||||
|
getBobbiesList: {
|
||||||
|
reg_step: 1,
|
||||||
|
level: 0,
|
||||||
|
intimacy: 0,
|
||||||
|
next_level_intimacy: 100
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第 5 步:重新编译前端
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 在 xuniYou 目录下
|
||||||
|
npm run dev:h5
|
||||||
|
# 或
|
||||||
|
npm run build:h5
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 调试方法
|
||||||
|
|
||||||
|
### 方法 1:添加调试日志
|
||||||
|
|
||||||
|
在 `getUserBasic()` 方法中添加日志:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
getUserBasic() {
|
||||||
|
console.log('开始获取用户信息...')
|
||||||
|
console.log('Token:', uni.getStorageSync('token'))
|
||||||
|
|
||||||
|
GetUserBasic({}).then(res => {
|
||||||
|
console.log('getUserBasic 响应:', res)
|
||||||
|
|
||||||
|
if (res.code == 1) {
|
||||||
|
let data = res.data
|
||||||
|
console.log('用户数据:', data)
|
||||||
|
console.log('reg_step:', data.reg_step)
|
||||||
|
|
||||||
|
// ...
|
||||||
|
this.getBobbiesList = data
|
||||||
|
console.log('getBobbiesList 已更新:', this.getBobbiesList)
|
||||||
|
} else {
|
||||||
|
console.error('getUserBasic 失败:', res.msg)
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('getUserBasic 异常:', err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方法 2:检查 API 响应
|
||||||
|
|
||||||
|
使用 curl 或 Postman 测试 API:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 替换 YOUR_TOKEN 为实际的 token
|
||||||
|
curl -X GET "http://localhost:30100/api/user_basic/get_user_basic" \
|
||||||
|
-H "token: YOUR_TOKEN"
|
||||||
|
```
|
||||||
|
|
||||||
|
**预期响应**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 1,
|
||||||
|
"msg": "成功",
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"username": "18800000001",
|
||||||
|
"nickname": "用户昵称",
|
||||||
|
"avatar": "头像URL",
|
||||||
|
"reg_step": 4,
|
||||||
|
"level": 1,
|
||||||
|
"intimacy": 50,
|
||||||
|
"next_level_intimacy": 100,
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方法 3:临时绕过检查
|
||||||
|
|
||||||
|
如果需要紧急修复,可以临时修改 `v-show` 条件:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<!-- 修改前 -->
|
||||||
|
<view v-show="getBobbiesList.reg_step == 1 || getBobbiesList.reg_step == 2 || getBobbiesList.reg_step == 3">
|
||||||
|
|
||||||
|
<!-- 修改后(临时) -->
|
||||||
|
<view v-show="!getBobbiesList || getBobbiesList.reg_step == 1 || getBobbiesList.reg_step == 2 || getBobbiesList.reg_step == 3">
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 常见错误和解决方法
|
||||||
|
|
||||||
|
### 错误 1:Cannot read property 'reg_step' of ''
|
||||||
|
|
||||||
|
**原因**:`getBobbiesList` 为空字符串
|
||||||
|
|
||||||
|
**解决**:使用方案 1,将初始值改为对象
|
||||||
|
|
||||||
|
### 错误 2:Network Error
|
||||||
|
|
||||||
|
**原因**:后端服务未启动或网络问题
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
1. 检查 PHP 服务是否运行
|
||||||
|
2. 检查端口是否正确(30100)
|
||||||
|
3. 检查防火墙设置
|
||||||
|
|
||||||
|
### 错误 3:401 Unauthorized
|
||||||
|
|
||||||
|
**原因**:Token 无效或过期
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
1. 清除本地存储,重新登录
|
||||||
|
2. 检查 token 是否正确保存
|
||||||
|
3. 检查后端 token 验证逻辑
|
||||||
|
|
||||||
|
### 错误 4:页面显示空白
|
||||||
|
|
||||||
|
**原因**:所有 `v-show` 条件都不满足
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
1. 检查 `getBobbiesList.reg_step` 的值
|
||||||
|
2. 添加默认显示逻辑
|
||||||
|
3. 使用方案 2 添加加载状态
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 完整修复代码
|
||||||
|
|
||||||
|
### 修改 `xuniYou/pages/index/index.vue`
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// ... 其他数据
|
||||||
|
|
||||||
|
// 修改这里:添加默认值
|
||||||
|
getBobbiesList: {
|
||||||
|
reg_step: 1, // 默认第一步
|
||||||
|
level: 0,
|
||||||
|
intimacy: 0,
|
||||||
|
next_level_intimacy: 100
|
||||||
|
},
|
||||||
|
|
||||||
|
loverBasicList: null, // 改为 null 而不是空字符串
|
||||||
|
|
||||||
|
// 添加加载状态
|
||||||
|
isLoading: true,
|
||||||
|
|
||||||
|
// ... 其他数据
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onLoad(options) {
|
||||||
|
//#ifdef MP-WEIXIN
|
||||||
|
this.checkPermission()
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
console.log('uni.env.', uni.env)
|
||||||
|
|
||||||
|
// 如果有 tab 参数,切换到对应的 tab
|
||||||
|
if (options && options.tab) {
|
||||||
|
const tabIndex = parseInt(options.tab);
|
||||||
|
if (!isNaN(tabIndex) && tabIndex >= 0 && tabIndex < this.tabs.length) {
|
||||||
|
this.currentTab = tabIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加:在 onLoad 时也加载用户数据
|
||||||
|
const token = uni.getStorageSync('token')
|
||||||
|
console.log('onLoad - Token:', token)
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
this.getUserBasic()
|
||||||
|
this.loverBasic()
|
||||||
|
this.loadHomeLooks()
|
||||||
|
} else {
|
||||||
|
// 没有 token,显示默认状态
|
||||||
|
this.isLoading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getUserBasic() {
|
||||||
|
console.log('开始获取用户信息...')
|
||||||
|
|
||||||
|
GetUserBasic({}).then(res => {
|
||||||
|
console.log('getUserBasic 响应:', res)
|
||||||
|
|
||||||
|
if (res.code == 1) {
|
||||||
|
let data = res.data
|
||||||
|
const conversationStore = useConversationStore();
|
||||||
|
let listener = {
|
||||||
|
nickname: data.username,
|
||||||
|
headImage: data.avatar,
|
||||||
|
openid: data.wxapp_openid,
|
||||||
|
}
|
||||||
|
conversationStore.setUserInfo(listener);
|
||||||
|
|
||||||
|
this.getBobbiesList = data
|
||||||
|
this.isLoading = false // 加载完成
|
||||||
|
|
||||||
|
console.log('用户数据已更新:', this.getBobbiesList)
|
||||||
|
this.getServerData();
|
||||||
|
} else {
|
||||||
|
this.isLoading = false
|
||||||
|
uni.showToast({
|
||||||
|
title: res.msg,
|
||||||
|
icon: 'none',
|
||||||
|
position: 'top'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('getUserBasic 异常:', err)
|
||||||
|
this.isLoading = false
|
||||||
|
uni.showToast({
|
||||||
|
title: '加载失败,请重试',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
### 在模板中添加加载状态
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<!-- 加载状态 -->
|
||||||
|
<view v-if="isLoading" class="loading-container">
|
||||||
|
<view class="loading-spinner"></view>
|
||||||
|
<view class="loading-text">加载中...</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 原有内容 -->
|
||||||
|
<view v-else>
|
||||||
|
<!-- ... -->
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.loading-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-spinner {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border: 3px solid #e0e0e0;
|
||||||
|
border-top-color: #9F47FF;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-text {
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 测试步骤
|
||||||
|
|
||||||
|
1. **清除缓存**
|
||||||
|
```javascript
|
||||||
|
// 在浏览器控制台执行
|
||||||
|
uni.clearStorageSync()
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **重新登录**
|
||||||
|
- 输入手机号和密码
|
||||||
|
- 点击登录
|
||||||
|
- 观察是否正常跳转
|
||||||
|
|
||||||
|
3. **检查日志**
|
||||||
|
- 查看控制台是否有错误
|
||||||
|
- 查看 Network 标签的 API 请求
|
||||||
|
- 查看 `getUserBasic` 的响应数据
|
||||||
|
|
||||||
|
4. **验证功能**
|
||||||
|
- 确认能正常进入首页
|
||||||
|
- 确认能看到用户信息
|
||||||
|
- 确认能正常使用各个功能
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 预防措施
|
||||||
|
|
||||||
|
1. **始终为对象类型的数据设置默认值**
|
||||||
|
```javascript
|
||||||
|
// ❌ 不好
|
||||||
|
userData: ''
|
||||||
|
|
||||||
|
// ✅ 好
|
||||||
|
userData: {
|
||||||
|
id: 0,
|
||||||
|
name: '',
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **添加错误处理**
|
||||||
|
```javascript
|
||||||
|
GetUserBasic({}).then(res => {
|
||||||
|
// ...
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('错误:', err)
|
||||||
|
// 显示友好的错误提示
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **添加加载状态**
|
||||||
|
- 让用户知道系统正在处理
|
||||||
|
- 避免用户重复点击
|
||||||
|
|
||||||
|
4. **添加调试日志**
|
||||||
|
- 方便排查问题
|
||||||
|
- 生产环境可以关闭
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 总结
|
||||||
|
|
||||||
|
登录无法进入的主要原因是 `getBobbiesList` 初始值为空字符串,导致页面判断逻辑失效。
|
||||||
|
|
||||||
|
**推荐修复方案**:
|
||||||
|
1. 将 `getBobbiesList` 初始值改为对象
|
||||||
|
2. 添加加载状态
|
||||||
|
3. 在 `onLoad` 时也调用 `getUserBasic()`
|
||||||
|
4. 添加完善的错误处理
|
||||||
|
|
||||||
|
修复后,用户登录成功就能正常进入系统了!
|
||||||
236
开发/2026年2月3日/邀请码功能修复.md
Normal file
236
开发/2026年2月3日/邀请码功能修复.md
Normal file
|
|
@ -0,0 +1,236 @@
|
||||||
|
# 邀请码功能修复
|
||||||
|
|
||||||
|
## 问题描述
|
||||||
|
|
||||||
|
用户使用邀请码登录后,没有成功获得5金币奖励。
|
||||||
|
|
||||||
|
## 问题原因
|
||||||
|
|
||||||
|
数据库表 `nf_user` 缺少邀请码相关的字段:
|
||||||
|
- `invite_code` - 邀请码
|
||||||
|
- `invited_by` - 被谁邀请
|
||||||
|
- `invite_count` - 邀请人数
|
||||||
|
- `invite_reward_total` - 邀请奖励总额
|
||||||
|
|
||||||
|
这些字段只在 Python 的 `lover/models.py` 中定义了,但数据库中并没有实际创建这些列。
|
||||||
|
|
||||||
|
## 解决方案
|
||||||
|
|
||||||
|
### 情况 1:字段不存在
|
||||||
|
|
||||||
|
如果数据库中没有邀请码字段,执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/add_invite_fields.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### 情况 2:字段已存在(推荐)
|
||||||
|
|
||||||
|
如果遇到 "Duplicate column name" 错误,说明字段已存在,使用智能修复脚本:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/fix_invite_fields.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
这个脚本会:
|
||||||
|
- 检查每个字段是否存在,只添加缺失的字段
|
||||||
|
- 检查索引是否存在,只添加缺失的索引
|
||||||
|
- 显示最终的字段和索引信息
|
||||||
|
|
||||||
|
### 1. 执行修复脚本
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 推荐:使用智能修复脚本(自动检查并修复)
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/fix_invite_fields.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 检查字段状态
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看邀请码相关字段
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/check_invite_fields.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 测试邀请码功能
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看邀请码数据和日志
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/test_invite_function.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
1. **获取邀请码**
|
||||||
|
- 登录系统
|
||||||
|
- 访问"我的" -> "邀请好友"页面
|
||||||
|
- 系统会自动生成邀请码
|
||||||
|
|
||||||
|
2. **使用邀请码**
|
||||||
|
- 新用户注册/登录时
|
||||||
|
- 在登录页面输入邀请码
|
||||||
|
- 登录成功后会自动调用邀请码接口
|
||||||
|
|
||||||
|
3. **验证奖励**
|
||||||
|
- 邀请人获得 10 金币
|
||||||
|
- 被邀请人获得 5 金币
|
||||||
|
- 检查 `nf_user_money_log` 表中的记录
|
||||||
|
|
||||||
|
## 邀请码功能说明
|
||||||
|
|
||||||
|
### 奖励规则
|
||||||
|
|
||||||
|
- **邀请人奖励**:10 金币
|
||||||
|
- **被邀请人奖励**:5 金币
|
||||||
|
- 每个用户只能使用一次邀请码
|
||||||
|
- 不能使用自己的邀请码
|
||||||
|
|
||||||
|
### API 接口
|
||||||
|
|
||||||
|
#### 1. 获取邀请信息
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /config/invite/info
|
||||||
|
Authorization: Bearer {token}
|
||||||
|
```
|
||||||
|
|
||||||
|
响应:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 1,
|
||||||
|
"data": {
|
||||||
|
"invite_code": "ABC123",
|
||||||
|
"invite_count": 5,
|
||||||
|
"invite_reward_total": 50.00,
|
||||||
|
"invite_url": "https://your-domain.com/register?invite=ABC123"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. 使用邀请码
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /config/invite/apply
|
||||||
|
Authorization: Bearer {token}
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"invite_code": "ABC123"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
响应:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 1,
|
||||||
|
"data": {
|
||||||
|
"message": "邀请码使用成功!您获得了5.0金币",
|
||||||
|
"reward": 5.0,
|
||||||
|
"balance": 5.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 前端调用流程
|
||||||
|
|
||||||
|
1. **登录页面** (`xuniYou/pages/login/index.vue`)
|
||||||
|
- 用户输入邀请码(可选)
|
||||||
|
- 登录成功后自动调用 `applyInviteCode()` 方法
|
||||||
|
|
||||||
|
2. **邀请页面** (`xuniYou/pages/mine/invite.vue`)
|
||||||
|
- 显示用户的邀请码
|
||||||
|
- 显示邀请统计(邀请人数、奖励总额)
|
||||||
|
- 提供复制邀请码功能
|
||||||
|
|
||||||
|
### 数据库表结构
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- nf_user 表新增字段
|
||||||
|
invite_code VARCHAR(10) DEFAULT NULL COMMENT '邀请码'
|
||||||
|
invited_by VARCHAR(10) DEFAULT NULL COMMENT '被谁邀请(邀请码)'
|
||||||
|
invite_count INT(11) DEFAULT 0 COMMENT '邀请人数'
|
||||||
|
invite_reward_total DECIMAL(10,2) DEFAULT 0.00 COMMENT '邀请奖励总额'
|
||||||
|
|
||||||
|
-- 索引
|
||||||
|
UNIQUE INDEX idx_invite_code (invite_code)
|
||||||
|
INDEX idx_invited_by (invited_by)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 金币日志记录
|
||||||
|
|
||||||
|
所有邀请奖励都会记录在 `nf_user_money_log` 表中:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 邀请人的记录
|
||||||
|
memo = '邀请新用户奖励'
|
||||||
|
money = 10.00
|
||||||
|
|
||||||
|
-- 被邀请人的记录
|
||||||
|
memo = '使用邀请码奖励'
|
||||||
|
money = 5.00
|
||||||
|
```
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **邀请码生成规则**
|
||||||
|
- 6位字符
|
||||||
|
- 只包含大写字母和数字
|
||||||
|
- 排除易混淆字符(0、O、1、I)
|
||||||
|
- 自动检查重复
|
||||||
|
|
||||||
|
2. **安全性**
|
||||||
|
- 使用数据库行锁防止并发问题
|
||||||
|
- 验证邀请码是否存在
|
||||||
|
- 验证用户是否已使用过邀请码
|
||||||
|
- 不能使用自己的邀请码
|
||||||
|
|
||||||
|
3. **事务处理**
|
||||||
|
- 使用数据库事务确保数据一致性
|
||||||
|
- 失败时自动回滚
|
||||||
|
- 记录详细的金币日志
|
||||||
|
|
||||||
|
## 测试步骤
|
||||||
|
|
||||||
|
### 1. 本地测试
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 执行数据库迁移
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/add_invite_fields.sql
|
||||||
|
|
||||||
|
# 2. 重启 Python 服务
|
||||||
|
# Windows
|
||||||
|
taskkill /F /IM python.exe
|
||||||
|
python -m uvicorn lover.main:app --host 0.0.0.0 --port 30101 --reload
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
sudo systemctl restart aigirlfriend-python
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 功能测试
|
||||||
|
|
||||||
|
1. 用户 A 登录,获取邀请码
|
||||||
|
2. 用户 B 注册/登录时输入用户 A 的邀请码
|
||||||
|
3. 检查用户 A 和用户 B 的金币余额
|
||||||
|
4. 检查 `nf_user_money_log` 表中的记录
|
||||||
|
|
||||||
|
### 3. 异常测试
|
||||||
|
|
||||||
|
1. 使用不存在的邀请码 → 应提示"邀请码不存在"
|
||||||
|
2. 重复使用邀请码 → 应提示"您已经使用过邀请码"
|
||||||
|
3. 使用自己的邀请码 → 应提示"不能使用自己的邀请码"
|
||||||
|
|
||||||
|
## 相关文件
|
||||||
|
|
||||||
|
- **数据库迁移**:`lover/migrations/add_invite_fields.sql`
|
||||||
|
- **数据模型**:`lover/models.py`
|
||||||
|
- **后端 API**:`lover/routers/config.py`
|
||||||
|
- **前端登录页**:`xuniYou/pages/login/index.vue`
|
||||||
|
- **前端邀请页**:`xuniYou/pages/mine/invite.vue`
|
||||||
|
|
||||||
|
## 更新日志
|
||||||
|
|
||||||
|
- **2026-02-03**:创建邀请码字段迁移文件
|
||||||
|
- **2026-02-03**:编写修复文档
|
||||||
|
|
||||||
|
## 下一步
|
||||||
|
|
||||||
|
1. 执行数据库迁移
|
||||||
|
2. 测试邀请码功能
|
||||||
|
3. 更新部署文档,添加邀请码迁移步骤
|
||||||
329
开发/2026年2月3日/邀请码问题诊断.md
Normal file
329
开发/2026年2月3日/邀请码问题诊断.md
Normal file
|
|
@ -0,0 +1,329 @@
|
||||||
|
# 邀请码功能问题诊断
|
||||||
|
|
||||||
|
## 快速诊断步骤
|
||||||
|
|
||||||
|
### 第 1 步:检查数据库字段
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/check_invite_fields.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
**预期结果**:应该看到 4 个字段
|
||||||
|
- `invite_code` - VARCHAR(10)
|
||||||
|
- `invited_by` - VARCHAR(10)
|
||||||
|
- `invite_count` - INT(11)
|
||||||
|
- `invite_reward_total` - DECIMAL(10,2)
|
||||||
|
|
||||||
|
**如果字段不完整**:执行修复脚本
|
||||||
|
```bash
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/fix_invite_fields.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 第 2 步:测试后端 API
|
||||||
|
|
||||||
|
#### 2.1 测试获取邀请信息
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 替换 YOUR_TOKEN 为实际的用户 token
|
||||||
|
curl -X GET "http://localhost:30101/config/invite/info" \
|
||||||
|
-H "token: YOUR_TOKEN"
|
||||||
|
```
|
||||||
|
|
||||||
|
**预期响应**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 1,
|
||||||
|
"data": {
|
||||||
|
"invite_code": "ABC123",
|
||||||
|
"invite_count": 0,
|
||||||
|
"invite_reward_total": 0.0,
|
||||||
|
"invite_url": "https://your-domain.com/register?invite=ABC123"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**如果返回 401 错误**:token 无效或过期
|
||||||
|
**如果返回 500 错误**:检查 Python 服务日志
|
||||||
|
|
||||||
|
#### 2.2 测试使用邀请码
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 替换 YOUR_TOKEN 和 INVITE_CODE
|
||||||
|
curl -X POST "http://localhost:30101/config/invite/apply" \
|
||||||
|
-H "token: YOUR_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"invite_code": "ABC123"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**预期响应**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 1,
|
||||||
|
"data": {
|
||||||
|
"message": "邀请码使用成功!您获得了5.0金币",
|
||||||
|
"reward": 5.0,
|
||||||
|
"balance": 5.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 第 3 步:检查 Python 服务日志
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Windows
|
||||||
|
# 查看控制台输出
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
sudo journalctl -u aigirlfriend-python -n 50 -f
|
||||||
|
# 或
|
||||||
|
sudo tail -f /var/log/aigirlfriend-python.log
|
||||||
|
```
|
||||||
|
|
||||||
|
**关键日志**:
|
||||||
|
- `认证调试` - 查看 token 是否正确解析
|
||||||
|
- `用户中心调试` - 查看是否成功获取用户信息
|
||||||
|
- 任何 `ERROR` 或 `Exception` 信息
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 第 4 步:检查数据库数据
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/test_invite_function.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
这会显示:
|
||||||
|
1. 最近 10 个用户的邀请码信息
|
||||||
|
2. 有邀请码的用户列表
|
||||||
|
3. 使用了邀请码的用户列表
|
||||||
|
4. 邀请相关的金币日志
|
||||||
|
5. 邀请数据统计
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 常见问题排查
|
||||||
|
|
||||||
|
### 问题 1:字段类型错误(最常见!)
|
||||||
|
|
||||||
|
**错误表现**:邀请码功能不工作,用户没有获得金币
|
||||||
|
|
||||||
|
**原因**:数据库字段类型不正确
|
||||||
|
- `invited_by` 应该是 `varchar(10)` 但实际是 `int`
|
||||||
|
- `invite_reward_total` 应该是 `decimal(10,2)` 但实际是 `int`
|
||||||
|
|
||||||
|
**检查方法**:
|
||||||
|
```bash
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/check_invite_fields.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
**预期结果**:
|
||||||
|
```
|
||||||
|
字段名 |类型 |
|
||||||
|
-------------------+-------------+
|
||||||
|
invite_code |varchar(10) | ✅
|
||||||
|
invited_by |varchar(10) | ✅ 应该是这个
|
||||||
|
invite_count |int(11) | ✅
|
||||||
|
invite_reward_total|decimal(10,2)| ✅ 应该是这个
|
||||||
|
```
|
||||||
|
|
||||||
|
**如果类型错误**:
|
||||||
|
```bash
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/fix_invite_field_types.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 问题 2:字段已存在错误
|
||||||
|
|
||||||
|
**错误信息**:`Duplicate column name 'invite_code'`
|
||||||
|
|
||||||
|
**原因**:字段已经存在
|
||||||
|
|
||||||
|
**解决**:使用智能修复脚本
|
||||||
|
```bash
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/fix_invite_fields.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 问题 2:用户没有获得金币
|
||||||
|
|
||||||
|
**可能原因**:
|
||||||
|
|
||||||
|
#### A. 邀请码不存在
|
||||||
|
```sql
|
||||||
|
-- 检查邀请码是否存在
|
||||||
|
SELECT id, username, invite_code
|
||||||
|
FROM nf_user
|
||||||
|
WHERE invite_code = 'ABC123';
|
||||||
|
```
|
||||||
|
|
||||||
|
#### B. 用户已使用过邀请码
|
||||||
|
```sql
|
||||||
|
-- 检查用户是否已使用过邀请码
|
||||||
|
SELECT id, username, invited_by
|
||||||
|
FROM nf_user
|
||||||
|
WHERE id = 用户ID;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### C. 使用了自己的邀请码
|
||||||
|
- 检查邀请码是否是用户自己的
|
||||||
|
|
||||||
|
#### D. API 调用失败
|
||||||
|
- 检查前端是否正确调用了 `/config/invite/apply` 接口
|
||||||
|
- 检查 token 是否正确传递
|
||||||
|
- 查看浏览器控制台的网络请求
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 问题 3:前端没有调用邀请码接口
|
||||||
|
|
||||||
|
**检查点**:
|
||||||
|
|
||||||
|
1. **登录页面** (`xuniYou/pages/login/index.vue`)
|
||||||
|
- 第 412 行:检查是否有邀请码判断
|
||||||
|
- 第 434 行:检查 `applyInviteCode()` 方法
|
||||||
|
|
||||||
|
2. **浏览器控制台**
|
||||||
|
- 打开开发者工具 → Network 标签
|
||||||
|
- 登录时查看是否有 `/config/invite/apply` 请求
|
||||||
|
- 查看请求参数和响应
|
||||||
|
|
||||||
|
3. **手动测试**
|
||||||
|
```javascript
|
||||||
|
// 在浏览器控制台执行
|
||||||
|
uni.request({
|
||||||
|
url: 'http://localhost:30101/config/invite/apply',
|
||||||
|
method: 'POST',
|
||||||
|
header: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'token': uni.getStorageSync('token')
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
invite_code: 'ABC123'
|
||||||
|
},
|
||||||
|
success: (res) => {
|
||||||
|
console.log('邀请码响应:', res);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 问题 4:Python 服务认证失败
|
||||||
|
|
||||||
|
**检查 token 传递**:
|
||||||
|
|
||||||
|
前端应该使用以下任一方式传递 token:
|
||||||
|
- `Authorization: Bearer {token}`
|
||||||
|
- `X-Token: {token}`
|
||||||
|
- `token: {token}` (header)
|
||||||
|
- `token: {token}` (cookie)
|
||||||
|
|
||||||
|
**当前前端使用**:`token: {token}` (header)
|
||||||
|
|
||||||
|
**验证**:
|
||||||
|
```bash
|
||||||
|
# 查看 Python 日志中的认证调试信息
|
||||||
|
# 应该看到:
|
||||||
|
# 认证调试 - token_header: YOUR_TOKEN
|
||||||
|
# 认证调试 - 提取的 token: YOUR_TOKEN
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 完整测试流程
|
||||||
|
|
||||||
|
### 1. 准备两个测试账号
|
||||||
|
|
||||||
|
- **用户 A**(邀请人):18800000001
|
||||||
|
- **用户 B**(被邀请人):18800000002
|
||||||
|
|
||||||
|
### 2. 用户 A 获取邀请码
|
||||||
|
|
||||||
|
1. 登录用户 A
|
||||||
|
2. 进入"我的" → "邀请好友"
|
||||||
|
3. 记录邀请码(例如:ABC123)
|
||||||
|
4. 记录当前金币余额
|
||||||
|
|
||||||
|
### 3. 用户 B 使用邀请码
|
||||||
|
|
||||||
|
1. 退出登录
|
||||||
|
2. 使用用户 B 登录
|
||||||
|
3. 在登录页面输入邀请码:ABC123
|
||||||
|
4. 登录成功
|
||||||
|
|
||||||
|
### 4. 验证结果
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 查看用户 A 的数据
|
||||||
|
SELECT id, username, invite_code, invite_count, invite_reward_total, money
|
||||||
|
FROM nf_user
|
||||||
|
WHERE username = '18800000001';
|
||||||
|
|
||||||
|
-- 查看用户 B 的数据
|
||||||
|
SELECT id, username, invited_by, money
|
||||||
|
FROM nf_user
|
||||||
|
WHERE username = '18800000002';
|
||||||
|
|
||||||
|
-- 查看金币日志
|
||||||
|
SELECT
|
||||||
|
l.user_id,
|
||||||
|
u.username,
|
||||||
|
l.money,
|
||||||
|
l.before,
|
||||||
|
l.after,
|
||||||
|
l.memo,
|
||||||
|
FROM_UNIXTIME(l.createtime) AS time
|
||||||
|
FROM nf_user_money_log l
|
||||||
|
LEFT JOIN nf_user u ON l.user_id = u.id
|
||||||
|
WHERE l.memo LIKE '%邀请%'
|
||||||
|
ORDER BY l.createtime DESC
|
||||||
|
LIMIT 10;
|
||||||
|
```
|
||||||
|
|
||||||
|
**预期结果**:
|
||||||
|
- 用户 A:`invite_count` +1,`invite_reward_total` +10,`money` +10
|
||||||
|
- 用户 B:`invited_by` = 'ABC123',`money` +5
|
||||||
|
- 金币日志中有两条记录
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 如果问题仍未解决
|
||||||
|
|
||||||
|
### 收集以下信息:
|
||||||
|
|
||||||
|
1. **数据库字段检查结果**
|
||||||
|
```bash
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/check_invite_fields.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Python 服务日志**(最近 50 行)
|
||||||
|
```bash
|
||||||
|
# 复制日志内容
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **浏览器控制台错误**
|
||||||
|
- Network 标签中的请求详情
|
||||||
|
- Console 标签中的错误信息
|
||||||
|
|
||||||
|
4. **测试 API 的响应**
|
||||||
|
```bash
|
||||||
|
curl -X GET "http://localhost:30101/config/invite/info" \
|
||||||
|
-H "token: YOUR_TOKEN"
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **数据库测试结果**
|
||||||
|
```bash
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/test_invite_function.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 联系支持
|
||||||
|
|
||||||
|
提供以上信息可以帮助快速定位问题。
|
||||||
690
部署指南.md
Normal file
690
部署指南.md
Normal file
|
|
@ -0,0 +1,690 @@
|
||||||
|
# 🚀 AI 女友项目部署指南
|
||||||
|
|
||||||
|
## 📋 项目架构
|
||||||
|
|
||||||
|
- **PHP 后端**:FastAdmin + ThinkPHP(用户管理、基础功能)
|
||||||
|
- **Python 后端**:FastAPI(AI 功能、唱歌、跳舞等)
|
||||||
|
- **前端**:uni-app(H5/小程序/APP)
|
||||||
|
- **数据库**:MySQL
|
||||||
|
- **文件存储**:阿里云 OSS
|
||||||
|
|
||||||
|
## 🖥️ 服务器要求
|
||||||
|
|
||||||
|
### 最低配置
|
||||||
|
- CPU: 2核
|
||||||
|
- 内存: 4GB
|
||||||
|
- 硬盘: 40GB
|
||||||
|
- 带宽: 5Mbps
|
||||||
|
|
||||||
|
### 推荐配置
|
||||||
|
- CPU: 4核
|
||||||
|
- 内存: 8GB
|
||||||
|
- 硬盘: 100GB
|
||||||
|
- 带宽: 10Mbps
|
||||||
|
|
||||||
|
### 操作系统
|
||||||
|
- Ubuntu 20.04/22.04 LTS(推荐)
|
||||||
|
- CentOS 7/8
|
||||||
|
- Debian 10/11
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📦 第一步:准备服务器环境
|
||||||
|
|
||||||
|
### 1.1 更新系统
|
||||||
|
```bash
|
||||||
|
# Ubuntu/Debian
|
||||||
|
sudo apt update && sudo apt upgrade -y
|
||||||
|
|
||||||
|
# CentOS
|
||||||
|
sudo yum update -y
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2 安装必要软件
|
||||||
|
```bash
|
||||||
|
# Ubuntu/Debian
|
||||||
|
sudo apt install -y git curl wget vim unzip
|
||||||
|
|
||||||
|
# CentOS
|
||||||
|
sudo yum install -y git curl wget vim unzip
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐘 第二步:安装 PHP 环境
|
||||||
|
|
||||||
|
### 2.1 安装 PHP 8.0
|
||||||
|
```bash
|
||||||
|
# Ubuntu/Debian
|
||||||
|
sudo apt install -y software-properties-common
|
||||||
|
sudo add-apt-repository ppa:ondrej/php -y
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y php8.0 php8.0-fpm php8.0-mysql php8.0-xml php8.0-mbstring \
|
||||||
|
php8.0-curl php8.0-zip php8.0-gd php8.0-bcmath php8.0-json
|
||||||
|
|
||||||
|
# CentOS
|
||||||
|
sudo yum install -y epel-release
|
||||||
|
sudo yum install -y https://rpms.remirepo.net/enterprise/remi-release-8.rpm
|
||||||
|
sudo yum module reset php -y
|
||||||
|
sudo yum module enable php:remi-8.0 -y
|
||||||
|
sudo yum install -y php php-fpm php-mysql php-xml php-mbstring \
|
||||||
|
php-curl php-zip php-gd php-bcmath php-json
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 配置 PHP
|
||||||
|
```bash
|
||||||
|
# 编辑 php.ini
|
||||||
|
sudo vim /etc/php/8.0/fpm/php.ini
|
||||||
|
|
||||||
|
# 修改以下配置
|
||||||
|
upload_max_filesize = 100M
|
||||||
|
post_max_size = 100M
|
||||||
|
max_execution_time = 300
|
||||||
|
memory_limit = 256M
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 启动 PHP-FPM
|
||||||
|
```bash
|
||||||
|
# Ubuntu/Debian
|
||||||
|
sudo systemctl start php8.0-fpm
|
||||||
|
sudo systemctl enable php8.0-fpm
|
||||||
|
|
||||||
|
# CentOS
|
||||||
|
sudo systemctl start php-fpm
|
||||||
|
sudo systemctl enable php-fpm
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐍 第三步:安装 Python 环境
|
||||||
|
|
||||||
|
### 3.1 安装 Python 3.10+
|
||||||
|
```bash
|
||||||
|
# Ubuntu/Debian
|
||||||
|
sudo apt install -y python3.10 python3.10-venv python3-pip
|
||||||
|
|
||||||
|
# CentOS
|
||||||
|
sudo yum install -y python3 python3-pip python3-devel
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 创建虚拟环境
|
||||||
|
```bash
|
||||||
|
cd /var/www/AI_GirlFriend
|
||||||
|
python3 -m venv venv
|
||||||
|
source venv/bin/activate
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 安装 Python 依赖
|
||||||
|
```bash
|
||||||
|
cd lover
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🗄️ 第四步:安装和配置 MySQL
|
||||||
|
|
||||||
|
### 4.1 安装 MySQL 8.0
|
||||||
|
```bash
|
||||||
|
# Ubuntu/Debian
|
||||||
|
sudo apt install -y mysql-server
|
||||||
|
|
||||||
|
# CentOS
|
||||||
|
sudo yum install -y mysql-server
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 启动 MySQL
|
||||||
|
```bash
|
||||||
|
sudo systemctl start mysql
|
||||||
|
sudo systemctl enable mysql
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 安全配置
|
||||||
|
```bash
|
||||||
|
sudo mysql_secure_installation
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.4 创建数据库和用户
|
||||||
|
```bash
|
||||||
|
sudo mysql -u root -p
|
||||||
|
|
||||||
|
# 在 MySQL 中执行
|
||||||
|
CREATE DATABASE fastadmin CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
CREATE USER 'aiuser'@'localhost' IDENTIFIED BY '你的强密码';
|
||||||
|
GRANT ALL PRIVILEGES ON fastadmin.* TO 'aiuser'@'localhost';
|
||||||
|
FLUSH PRIVILEGES;
|
||||||
|
EXIT;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.5 导入数据库
|
||||||
|
```bash
|
||||||
|
# 导入 PHP 后端数据库
|
||||||
|
mysql -u aiuser -p fastadmin < 归档/xunifriend.sql
|
||||||
|
|
||||||
|
# 执行音乐库迁移
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/add_music_library.sql
|
||||||
|
|
||||||
|
# 执行邀请码功能迁移
|
||||||
|
mysql -u aiuser -p fastadmin < lover/migrations/add_invite_fields.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🌐 第五步:安装和配置 Nginx
|
||||||
|
|
||||||
|
### 5.1 安装 Nginx
|
||||||
|
```bash
|
||||||
|
# Ubuntu/Debian
|
||||||
|
sudo apt install -y nginx
|
||||||
|
|
||||||
|
# CentOS
|
||||||
|
sudo yum install -y nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 创建 Nginx 配置
|
||||||
|
```bash
|
||||||
|
sudo vim /etc/nginx/sites-available/aigirlfriend
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.3 Nginx 配置内容
|
||||||
|
```nginx
|
||||||
|
# PHP 后端配置
|
||||||
|
server {
|
||||||
|
listen 30100;
|
||||||
|
server_name your-domain.com; # 改为你的域名或 IP
|
||||||
|
|
||||||
|
root /var/www/AI_GirlFriend/xunifriend_RaeeC/public;
|
||||||
|
index index.php index.html;
|
||||||
|
|
||||||
|
# 日志
|
||||||
|
access_log /var/log/nginx/php_access.log;
|
||||||
|
error_log /var/log/nginx/php_error.log;
|
||||||
|
|
||||||
|
# PHP 处理
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.php?$query_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ \.php$ {
|
||||||
|
fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
|
||||||
|
fastcgi_index index.php;
|
||||||
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
include fastcgi_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 静态文件
|
||||||
|
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
expires 30d;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# 禁止访问隐藏文件
|
||||||
|
location ~ /\. {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Python 后端配置
|
||||||
|
server {
|
||||||
|
listen 30101;
|
||||||
|
server_name your-domain.com; # 改为你的域名或 IP
|
||||||
|
|
||||||
|
# 日志
|
||||||
|
access_log /var/log/nginx/python_access.log;
|
||||||
|
error_log /var/log/nginx/python_error.log;
|
||||||
|
|
||||||
|
# 反向代理到 Python 应用
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:8000;
|
||||||
|
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_connect_timeout 300s;
|
||||||
|
proxy_send_timeout 300s;
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 静态文件(如果有)
|
||||||
|
location /static/ {
|
||||||
|
alias /var/www/AI_GirlFriend/lover/static/;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.4 启用配置
|
||||||
|
```bash
|
||||||
|
# Ubuntu/Debian
|
||||||
|
sudo ln -s /etc/nginx/sites-available/aigirlfriend /etc/nginx/sites-enabled/
|
||||||
|
sudo nginx -t
|
||||||
|
sudo systemctl restart nginx
|
||||||
|
|
||||||
|
# CentOS
|
||||||
|
sudo cp /etc/nginx/sites-available/aigirlfriend /etc/nginx/conf.d/aigirlfriend.conf
|
||||||
|
sudo nginx -t
|
||||||
|
sudo systemctl restart nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 第六步:上传项目文件
|
||||||
|
|
||||||
|
### 6.1 创建项目目录
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p /var/www/AI_GirlFriend
|
||||||
|
sudo chown -R $USER:$USER /var/www/AI_GirlFriend
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.2 上传文件(使用 Git 或 FTP)
|
||||||
|
|
||||||
|
**方法 1:使用 Git**
|
||||||
|
```bash
|
||||||
|
cd /var/www
|
||||||
|
git clone https://your-repo-url.git AI_GirlFriend
|
||||||
|
```
|
||||||
|
|
||||||
|
**方法 2:使用 SCP**
|
||||||
|
```bash
|
||||||
|
# 在本地电脑执行
|
||||||
|
scp -r C:\Users\Administrator\Desktop\Project\AI_GirlFriend user@server-ip:/var/www/
|
||||||
|
```
|
||||||
|
|
||||||
|
**方法 3:使用 FTP 工具**
|
||||||
|
- 使用 FileZilla 或 WinSCP
|
||||||
|
- 上传整个项目文件夹
|
||||||
|
|
||||||
|
### 6.3 设置权限
|
||||||
|
```bash
|
||||||
|
cd /var/www/AI_GirlFriend
|
||||||
|
|
||||||
|
# PHP 项目权限
|
||||||
|
sudo chown -R www-data:www-data xunifriend_RaeeC/
|
||||||
|
sudo chmod -R 755 xunifriend_RaeeC/
|
||||||
|
sudo chmod -R 777 xunifriend_RaeeC/runtime/
|
||||||
|
sudo chmod -R 777 xunifriend_RaeeC/public/uploads/
|
||||||
|
|
||||||
|
# Python 项目权限
|
||||||
|
sudo chown -R $USER:$USER lover/
|
||||||
|
sudo chmod -R 755 lover/
|
||||||
|
sudo mkdir -p public/tts public/music
|
||||||
|
sudo chmod -R 777 public/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ 第七步:配置环境变量
|
||||||
|
|
||||||
|
### 7.1 配置 PHP 后端
|
||||||
|
```bash
|
||||||
|
cd /var/www/AI_GirlFriend/xunifriend_RaeeC
|
||||||
|
|
||||||
|
# 编辑数据库配置
|
||||||
|
vim application/database.php
|
||||||
|
```
|
||||||
|
|
||||||
|
修改数据库配置:
|
||||||
|
```php
|
||||||
|
return [
|
||||||
|
'type' => 'mysql',
|
||||||
|
'hostname' => '127.0.0.1',
|
||||||
|
'database' => 'fastadmin',
|
||||||
|
'username' => 'aiuser',
|
||||||
|
'password' => '你的数据库密码',
|
||||||
|
'hostport' => '3306',
|
||||||
|
'charset' => 'utf8mb4',
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.2 配置 Python 后端
|
||||||
|
```bash
|
||||||
|
cd /var/www/AI_GirlFriend/lover
|
||||||
|
|
||||||
|
# 创建 .env 文件
|
||||||
|
vim .env
|
||||||
|
```
|
||||||
|
|
||||||
|
.env 文件内容:
|
||||||
|
```env
|
||||||
|
# 应用配置
|
||||||
|
APP_ENV=production
|
||||||
|
DEBUG=False
|
||||||
|
|
||||||
|
# 数据库配置
|
||||||
|
DB_HOST=127.0.0.1
|
||||||
|
DB_PORT=3306
|
||||||
|
DB_USER=aiuser
|
||||||
|
DB_PASSWORD=你的数据库密码
|
||||||
|
DB_NAME=fastadmin
|
||||||
|
|
||||||
|
# JWT 配置
|
||||||
|
JWT_SECRET_KEY=你的随机密钥(至少32位)
|
||||||
|
JWT_ALGORITHM=HS256
|
||||||
|
JWT_EXPIRE_MINUTES=43200
|
||||||
|
|
||||||
|
# DashScope API(阿里云通义千问)
|
||||||
|
DASHSCOPE_API_KEY=sk-2473385fd6d54a58a703ce6b92a62074
|
||||||
|
|
||||||
|
# 阿里云 OSS 配置
|
||||||
|
OSS_ACCESS_KEY_ID=LTAI5tBzjogJDx4JzRYoDyEM
|
||||||
|
OSS_ACCESS_KEY_SECRET=43euicRkkzlLjGTYzFYkTupcW7N5w3
|
||||||
|
OSS_BUCKET=hello12312312
|
||||||
|
OSS_ENDPOINT=https://oss-cn-hangzhou.aliyuncs.com
|
||||||
|
CDN_DOMAIN=https://hello12312312.oss-cn-hangzhou.aliyuncs.com
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 第八步:配置 Systemd 服务(Python 后端)
|
||||||
|
|
||||||
|
### 8.1 创建 Systemd 服务文件
|
||||||
|
```bash
|
||||||
|
sudo vim /etc/systemd/system/aigirlfriend-python.service
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.2 服务文件内容
|
||||||
|
```ini
|
||||||
|
[Unit]
|
||||||
|
Description=AI GirlFriend Python Backend
|
||||||
|
After=network.target mysql.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=www-data
|
||||||
|
Group=www-data
|
||||||
|
WorkingDirectory=/var/www/AI_GirlFriend
|
||||||
|
Environment="PATH=/var/www/AI_GirlFriend/venv/bin"
|
||||||
|
ExecStart=/var/www/AI_GirlFriend/venv/bin/uvicorn lover.main:app --host 0.0.0.0 --port 8000 --workers 4
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
|
||||||
|
# 日志
|
||||||
|
StandardOutput=append:/var/log/aigirlfriend-python.log
|
||||||
|
StandardError=append:/var/log/aigirlfriend-python-error.log
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.3 启动服务
|
||||||
|
```bash
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl start aigirlfriend-python
|
||||||
|
sudo systemctl enable aigirlfriend-python
|
||||||
|
sudo systemctl status aigirlfriend-python
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔥 第九步:配置防火墙
|
||||||
|
|
||||||
|
### 9.1 开放端口
|
||||||
|
```bash
|
||||||
|
# Ubuntu/Debian (UFW)
|
||||||
|
sudo ufw allow 30100/tcp
|
||||||
|
sudo ufw allow 30101/tcp
|
||||||
|
sudo ufw allow 80/tcp
|
||||||
|
sudo ufw allow 443/tcp
|
||||||
|
sudo ufw enable
|
||||||
|
|
||||||
|
# CentOS (Firewalld)
|
||||||
|
sudo firewall-cmd --permanent --add-port=30100/tcp
|
||||||
|
sudo firewall-cmd --permanent --add-port=30101/tcp
|
||||||
|
sudo firewall-cmd --permanent --add-port=80/tcp
|
||||||
|
sudo firewall-cmd --permanent --add-port=443/tcp
|
||||||
|
sudo firewall-cmd --reload
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📱 第十步:部署前端
|
||||||
|
|
||||||
|
### 10.1 修改 API 地址
|
||||||
|
```bash
|
||||||
|
cd /var/www/AI_GirlFriend/xuniYou
|
||||||
|
vim utils/request.js
|
||||||
|
```
|
||||||
|
|
||||||
|
修改为生产环境地址:
|
||||||
|
```javascript
|
||||||
|
// 生产环境
|
||||||
|
export const baseURL = 'http://your-domain.com:30100' // 或使用域名
|
||||||
|
export const baseURLPy = 'http://your-domain.com:30101'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10.2 编译 H5 版本
|
||||||
|
```bash
|
||||||
|
# 在本地开发机器上
|
||||||
|
cd xuniYou
|
||||||
|
npm install
|
||||||
|
npm run build:h5
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10.3 上传 H5 文件
|
||||||
|
```bash
|
||||||
|
# 将 unpackage/dist/build/h5 目录上传到服务器
|
||||||
|
scp -r unpackage/dist/build/h5/* user@server-ip:/var/www/AI_GirlFriend/h5/
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10.4 配置 Nginx 服务 H5
|
||||||
|
```bash
|
||||||
|
sudo vim /etc/nginx/sites-available/aigirlfriend-h5
|
||||||
|
```
|
||||||
|
|
||||||
|
添加配置:
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name your-domain.com;
|
||||||
|
|
||||||
|
root /var/www/AI_GirlFriend/h5;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 静态资源缓存
|
||||||
|
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
expires 30d;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
启用配置:
|
||||||
|
```bash
|
||||||
|
sudo ln -s /etc/nginx/sites-available/aigirlfriend-h5 /etc/nginx/sites-enabled/
|
||||||
|
sudo nginx -t
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔒 第十一步:配置 HTTPS(可选但推荐)
|
||||||
|
|
||||||
|
### 11.1 安装 Certbot
|
||||||
|
```bash
|
||||||
|
# Ubuntu/Debian
|
||||||
|
sudo apt install -y certbot python3-certbot-nginx
|
||||||
|
|
||||||
|
# CentOS
|
||||||
|
sudo yum install -y certbot python3-certbot-nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### 11.2 获取 SSL 证书
|
||||||
|
```bash
|
||||||
|
sudo certbot --nginx -d your-domain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### 11.3 自动续期
|
||||||
|
```bash
|
||||||
|
sudo certbot renew --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 第十二步:监控和日志
|
||||||
|
|
||||||
|
### 12.1 查看日志
|
||||||
|
```bash
|
||||||
|
# Nginx 日志
|
||||||
|
sudo tail -f /var/log/nginx/php_access.log
|
||||||
|
sudo tail -f /var/log/nginx/python_access.log
|
||||||
|
|
||||||
|
# Python 应用日志
|
||||||
|
sudo tail -f /var/log/aigirlfriend-python.log
|
||||||
|
|
||||||
|
# PHP 日志
|
||||||
|
sudo tail -f /var/log/php8.0-fpm.log
|
||||||
|
|
||||||
|
# 系统日志
|
||||||
|
sudo journalctl -u aigirlfriend-python -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### 12.2 性能监控
|
||||||
|
```bash
|
||||||
|
# 安装监控工具
|
||||||
|
sudo apt install -y htop iotop nethogs
|
||||||
|
|
||||||
|
# 查看资源使用
|
||||||
|
htop
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 第十三步:测试部署
|
||||||
|
|
||||||
|
### 13.1 测试 PHP 后端
|
||||||
|
```bash
|
||||||
|
curl http://your-domain.com:30100
|
||||||
|
```
|
||||||
|
|
||||||
|
### 13.2 测试 Python 后端
|
||||||
|
```bash
|
||||||
|
curl http://your-domain.com:30101/health
|
||||||
|
curl http://your-domain.com:30101/docs # API 文档
|
||||||
|
```
|
||||||
|
|
||||||
|
### 13.3 测试前端
|
||||||
|
```bash
|
||||||
|
# 在浏览器中访问
|
||||||
|
http://your-domain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 常见问题排查
|
||||||
|
|
||||||
|
### 问题 1:502 Bad Gateway
|
||||||
|
```bash
|
||||||
|
# 检查 PHP-FPM 状态
|
||||||
|
sudo systemctl status php8.0-fpm
|
||||||
|
|
||||||
|
# 检查 Python 服务状态
|
||||||
|
sudo systemctl status aigirlfriend-python
|
||||||
|
|
||||||
|
# 查看错误日志
|
||||||
|
sudo tail -f /var/log/nginx/error.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题 2:数据库连接失败
|
||||||
|
```bash
|
||||||
|
# 检查 MySQL 状态
|
||||||
|
sudo systemctl status mysql
|
||||||
|
|
||||||
|
# 测试数据库连接
|
||||||
|
mysql -u aiuser -p fastadmin
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题 3:权限问题
|
||||||
|
```bash
|
||||||
|
# 重新设置权限
|
||||||
|
sudo chown -R www-data:www-data /var/www/AI_GirlFriend/xunifriend_RaeeC/
|
||||||
|
sudo chmod -R 777 /var/www/AI_GirlFriend/xunifriend_RaeeC/runtime/
|
||||||
|
sudo chmod -R 777 /var/www/AI_GirlFriend/public/
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题 4:Python 依赖问题
|
||||||
|
```bash
|
||||||
|
# 重新安装依赖
|
||||||
|
cd /var/www/AI_GirlFriend
|
||||||
|
source venv/bin/activate
|
||||||
|
pip install -r lover/requirements.txt --upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 性能优化建议
|
||||||
|
|
||||||
|
### 1. 启用 Gzip 压缩
|
||||||
|
在 Nginx 配置中添加:
|
||||||
|
```nginx
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 配置 Redis 缓存
|
||||||
|
```bash
|
||||||
|
# 安装 Redis
|
||||||
|
sudo apt install -y redis-server
|
||||||
|
sudo systemctl start redis
|
||||||
|
sudo systemctl enable redis
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 使用 CDN
|
||||||
|
- 将静态资源上传到阿里云 OSS
|
||||||
|
- 配置 CDN 加速
|
||||||
|
|
||||||
|
### 4. 数据库优化
|
||||||
|
```sql
|
||||||
|
-- 添加索引
|
||||||
|
ALTER TABLE nf_user ADD INDEX idx_token (token);
|
||||||
|
ALTER TABLE nf_chat_message ADD INDEX idx_user_session (user_id, session_id);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 部署检查清单
|
||||||
|
|
||||||
|
- [ ] 服务器环境准备完成
|
||||||
|
- [ ] PHP 8.0 安装并配置
|
||||||
|
- [ ] Python 3.10+ 安装并配置
|
||||||
|
- [ ] MySQL 8.0 安装并配置
|
||||||
|
- [ ] Nginx 安装并配置
|
||||||
|
- [ ] 项目文件上传完成
|
||||||
|
- [ ] 数据库导入完成
|
||||||
|
- [ ] 环境变量配置完成
|
||||||
|
- [ ] Systemd 服务配置完成
|
||||||
|
- [ ] 防火墙端口开放
|
||||||
|
- [ ] 前端编译并部署
|
||||||
|
- [ ] HTTPS 证书配置(可选)
|
||||||
|
- [ ] 所有服务测试通过
|
||||||
|
- [ ] 日志监控配置完成
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 技术支持
|
||||||
|
|
||||||
|
如遇到问题,请检查:
|
||||||
|
1. 服务器日志:`/var/log/nginx/`, `/var/log/aigirlfriend-python.log`
|
||||||
|
2. 系统日志:`sudo journalctl -xe`
|
||||||
|
3. 服务状态:`sudo systemctl status [service-name]`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**部署完成!** 🎉
|
||||||
|
|
||||||
|
访问地址:
|
||||||
|
- 前端:http://your-domain.com
|
||||||
|
- PHP 后端:http://your-domain.com:30100
|
||||||
|
- Python 后端:http://your-domain.com:30101
|
||||||
|
- API 文档:http://your-domain.com:30101/docs
|
||||||
Loading…
Reference in New Issue
Block a user