FastMovieAI AI短剧创作平台 二开基线

- 源码: xhadmincn/FastMovieAI (Apache 2.0)
- 二开: Docker部署, Swoole改Select, route.php修复, 补update/VERSION
- vendor/示例资源已gitignore
This commit is contained in:
李建琦
2026-08-26 18:37:36 +08:00
commit eae151fd57
888 changed files with 105571 additions and 0 deletions
@@ -0,0 +1,445 @@
<?php
namespace plugin\user\app\api\controller;
use app\Basic;
use app\expose\enum\ResponseCode;
use app\expose\enum\ResponseEvent;
use app\expose\enum\State;
use plugin\control\expose\helper\Vcode;
use app\expose\utils\TwofaAuthenticator;
use app\model\Uploads;
use app\model\UploadsClassify;
use plugin\finance\app\model\PluginFinanceWallet;
use plugin\user\app\model\PluginUser;
use plugin\user\app\model\PluginUserInvitationCode;
use plugin\user\app\model\PluginUserTwofaSecret;
use plugin\user\app\model\PluginUserWechat;
use plugin\user\expose\helper\User;
use plugin\user\utils\enum\TotpApp;
use plugin\user\utils\enum\VcodeScene;
use Shopwwi\WebmanFilesystem\Facade\Storage;
use support\Request;
use think\facade\Db;
class UserController extends Basic
{
protected $notNeedTwofa = ['getTwofaList', 'refreshTwofaSecret'];
protected $notNeedLogin = ['checkInvitationCode'];
public function info(Request $request)
{
$user = PluginUser::where(['id' => $request->uid])->find();
if (!$user) {
return $this->fail('用户不存在');
}
$info = PluginUser::getTokenInfo($user, $request->twofa);
$count = PluginUserInvitationCode::where(['uid' => $request->uid])->where('state', State::YES['value'])->where('status', 'unused')->count();
$info->invitation_code_count = $count;
return $this->resData($info);
}
public function update(Request $request)
{
$D = $request->post();
try {
if ($request->twofa_state) {
$time = time() - (10 * 60);
if ($request->twofa['time'] < $time) {
return $this->fail('请验证你的身份', [
'code' => ResponseCode::NEED_TWOFA,
'action' => 'stop'
]);
}
switch (true) {
case isset($D['username']):
$PluginUser = PluginUser::where(['id' => $request->uid])->find();
$username_time = $PluginUser->username_time ? 30 - ceil((time() - strtotime($PluginUser->username_time)) / 86400) : 0;
if ($username_time > 0) {
return $this->fail('30天内仅支持修改一次');
}
break;
case isset($D['mobile']):
Vcode::check($D['mobile'], $D['vcode'], VcodeScene::BIND_MOBILE['value'], $D['token']);
break;
case isset($D['email']):
Vcode::check($D['email'], $D['vcode'], VcodeScene::BIND_EMAIL['value'], $D['token']);
break;
case isset($D['password']):
if (empty($D['vpassword'])) {
return $this->fail('两次输入的密码不一致');
}
if ($D['password'] != $D['vpassword']) {
return $this->fail('两次输入的密码不一致');
}
Vcode::check($D['username'], $D['vcode'], VcodeScene::SET_PASSWORD['value'], $D['token'] ?? null);
break;
}
}
$D['channels_uid'] = $request->channels_uid;
User::update($request->uid, $D);
} catch (\Throwable $th) {
return $this->exception($th);
}
return $this->code(ResponseCode::SUCCESS_EVENT_PUSH, '更新成功', [
'event' => ResponseEvent::UPDATE_USERINFO
]);
}
public function checkUsername(Request $request)
{
$username = $request->post('username');
$user = PluginUser::where(['username' => $username])->find();
if ($user && $user->id != $request->uid) {
return $this->fail('用户名已存在');
}
return $this->success();
}
public function checkMobile(Request $request)
{
$mobile = $request->post('mobile');
$user = PluginUser::where(['mobile' => $mobile])->find();
if ($user) {
if ($user->id == $request->uid) {
return $this->fail('和原手机号一致');
}
return $this->fail('手机号已存在');
}
return $this->success();
}
public function checkEmail(Request $request)
{
$email = $request->post('email');
$user = PluginUser::where(['email' => $email])->find();
if ($user) {
if ($user->id == $request->uid) {
return $this->fail('和原邮箱一致');
}
return $this->fail('邮箱已存在');
}
return $this->success();
}
public function checkTwofa(Request $request)
{
if (!$request->twofa_state) {
return $this->success();
}
$time = time() - (10 * 60);
if ($request->twofa['time'] < $time) {
return $this->fail('请验证你的身份', [
'code' => ResponseCode::NEED_TWOFA,
'action' => 'stop'
]);
}
return $this->success();
}
public function uploadHeadimg(Request $request)
{
$default_channels = config('plugin.shopwwi.filesystem.app.default');
$UploadsClassify = UploadsClassify::where(['dir_name' => 'uploads/default', 'is_system' => 1, 'channels' => $default_channels])->find();
if (!$UploadsClassify) {
return $this->fail('分类不存在');
}
$date_path = date('Ymd');
//单文件上传
$file = $request->file('file');
try {
$result = Storage::adapter($UploadsClassify->channels)->path($UploadsClassify->dir_name . '/' . $date_path)->upload($file);
} catch (\Throwable $th) {
return $this->exception($th);
}
try {
$Uploads = new Uploads();
$Uploads->uid = $request->uid;
$Uploads->classify_id = $UploadsClassify->id;
$Uploads->filename = $result->origin_name;
$Uploads->path = $result->file_name;
$Uploads->ext = $result->extension;
$Uploads->mime = $result->mime_type;
$Uploads->size = $result->size;
$Uploads->channels = $UploadsClassify->channels;
$Uploads->save();
} catch (\Throwable $th) {
return $this->exception($th);
}
$user = PluginUser::where(['id' => $request->uid])->find();
$user->headimg = $result->file_url;
$user->save();
return $this->code(ResponseCode::SUCCESS_EVENT_PUSH, '保存成功', [
'event' => ResponseEvent::UPDATE_USERINFO
]);
}
public function outLogin(Request $request)
{
return $this->success();
}
/**
* 获取两步验证密钥
*/
public function getTwofaSecret(Request $request)
{
try {
$ga = new TwofaAuthenticator();
$secret = $ga->createSecret();
$PluginUser = PluginUser::where(['id' => $request->uid])->find();
// 生成 otpauth URL
$appName = "XH";
$accountName = $PluginUser->nickname;
$qrCodeUrl = $ga->getQRCode($appName . ':' . $accountName, $secret, $appName);
} catch (\Throwable $th) {
return $this->exception($th);
}
return $this->resData([
'secret' => $secret,
'qrcode' => $qrCodeUrl
]);
}
/**
* 验证两步验证密钥
*/
public function verifyTwofaSecret(Request $request)
{
$code = $request->post('code');
$secret = $request->post('secret');
$totp_app = $request->post('totp_app');
$ga = new TwofaAuthenticator();
$isValid = $ga->verifyCode($secret, $code, 2); // 1 = 30 秒容差
if ($isValid) {
Db::startTrans();
try {
$PluginUser = PluginUser::where(['id' => $request->uid])->find();
$PluginUser->twofa_state = State::YES['value'];
$PluginUser->save();
$PluginUserTwofaSecret = new PluginUserTwofaSecret();
$PluginUserTwofaSecret->uid = $request->uid;
$PluginUserTwofaSecret->secret = $secret;
$PluginUserTwofaSecret->totp_app = $totp_app;
$PluginUserTwofaSecret->is_default = PluginUserTwofaSecret::where(['uid' => $request->uid])->count() == 0 ? 1 : 0;
$PluginUserTwofaSecret->save();
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
return $this->exception($th);
}
return $this->success('验证成功');
} else {
return $this->fail('验证码错误');
}
}
/**
* 刷新账户两步验证时效
*/
public function refreshTwofaSecret(Request $request)
{
$code = $request->post('code');
$totp_app = $request->post('totp_app');
$ga = new TwofaAuthenticator();
$PluginUserTwofaSecret = PluginUserTwofaSecret::where(['uid' => $request->uid, 'id' => $totp_app])->find();
if (!$PluginUserTwofaSecret) {
return $this->fail('两步验证密钥不存在');
}
$secret = $PluginUserTwofaSecret->secret;
$isValid = $ga->verifyCode($secret, $code, 2); // 1 = 30 秒容差
if ($isValid) {
$user = PluginUser::where(['id' => $request->uid])->find();
if (!$user) {
return $this->fail('用户不存在');
}
$info = PluginUser::getTokenInfo($user, true);
return $this->resData($info);
} else {
return $this->fail('验证码错误');
}
}
public function getTwofaList(Request $request)
{
$PluginUserTwofaSecret = PluginUserTwofaSecret::where(['uid' => $request->uid])->order('is_default desc,id desc')->select()->scene('external')->each(function ($item) {
$item->totp_app_text = TotpApp::get($item->totp_app);
});
return $this->resData($PluginUserTwofaSecret);
}
public function setDefaultTwofa(Request $request)
{
$id = $request->post('id');
$PluginUserTwofaSecret = PluginUserTwofaSecret::where(['uid' => $request->uid, 'id' => $id])->find();
if (!$PluginUserTwofaSecret) {
return $this->fail('两步验证密钥不存在');
}
Db::startTrans();
try {
PluginUserTwofaSecret::where(['uid' => $request->uid])->update(['is_default' => 0]);
$PluginUserTwofaSecret->is_default = 1;
$PluginUserTwofaSecret->save();
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
return $this->exception($th);
}
return $this->success('设置成功');
}
public function deleteTwofa(Request $request)
{
$id = $request->post('id');
$PluginUserTwofaSecret = PluginUserTwofaSecret::where(['uid' => $request->uid, 'id' => $id])->find();
if (!$PluginUserTwofaSecret) {
return $this->fail('两步验证密钥不存在');
}
Db::startTrans();
try {
// 判断是否还有其它两步验证密钥
$PluginUserTwofaSecretOther = PluginUserTwofaSecret::where(['uid' => $request->uid])->where('id', '<>', $id)->order('id desc')->find();
if ($PluginUserTwofaSecretOther) {
if ($PluginUserTwofaSecret->is_default == 1) {
$PluginUserTwofaSecretOther->is_default = 1;
$PluginUserTwofaSecretOther->save();
}
} else {
$PluginUser = PluginUser::where(['id' => $request->uid])->find();
$PluginUser->twofa_state = State::NO['value'];
$PluginUser->save();
}
$PluginUserTwofaSecret->delete();
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
return $this->exception($th);
}
return $this->success('删除成功');
}
/**
* 获取用户未使用的邀请码
* @author:1950781041@qq.com
* @Date:2026-01-07
*/
public function getUnusedInvitationCode(Request $request)
{
$PluginUserInvitationCode = PluginUserInvitationCode::where(['uid' => $request->uid])
->with(['useUser'])
->where('channels_uid', $request->channels_uid)
->where('state', State::YES['value'])
->select();
return $this->resData($PluginUserInvitationCode);
}
/**
* 用户绑定邀请码
* @author:1950781041@qq.com
* @Date:2026-01-15
*/
public function bindInvitationCode(Request $request)
{
$code = $request->post('code');
$PluginUserInvitationCode = PluginUserInvitationCode::where(['code' => $code])->find();
if (!$PluginUserInvitationCode) {
return $this->fail('邀请码不存在');
}
if ($PluginUserInvitationCode->uid == $request->uid) {
return $this->fail('不能邀请自己');
}
if (!empty($PluginUserInvitationCode->use_uid)) {
return $this->fail('邀请码已使用');
}
if ($PluginUserInvitationCode->status != 'unused') {
return $this->fail('邀请码已使用');
}
if ($PluginUserInvitationCode->state != State::YES['value']) {
return $this->fail('邀请码已失效');
}
$PluginUserInvitationCode->status = 'used';
$PluginUserInvitationCode->use_uid = $request->uid;
$PluginUserInvitationCode->use_time = date('Y-m-d H:i:s');
$PluginUserInvitationCode->save();
$PluginUser = PluginUser::where(['id' => $request->uid])->find();
$PluginUser->activation_time = date('Y-m-d H:i:s');
$PluginUser->puid = $PluginUserInvitationCode->uid;
$PluginUser->save();
return $this->success('绑定成功');
}
/**
* 用户绑定电话
* @author:1950781041@qq.com
* @Date:2026-01-15
*/
public function bindMobile(Request $request)
{
$mobile = $request->post('username');
$username = $request->post('username');
$vcode = $request->post('vcode');
$token = $request->post('token');
if (empty($username) || empty($vcode) || empty($token)) {
return $this->fail('参数错误');
}
Vcode::check($username, $vcode, VcodeScene::BIND_MOBILE['value'], $token);
$PluginUser = PluginUser::where(['mobile' => $mobile, 'channels_uid' => $request->channels_uid])->find();
if ($PluginUser) {
PluginUser::where(['id' => $request->uid])->update(['username' => '']);
$wechat = PluginUserWechat::where(['uid' => $request->uid])->find();
$wechat->uid = $PluginUser->id;
$wechat->save();
return $this->resData(PluginUser::getTokenInfo($PluginUser, true));
}
$PluginUser = PluginUser::where(['id' => $request->uid])->find();
if ($PluginUser->mobile) {
return $this->fail('电话已绑定');
}
$PluginUser->mobile = $mobile;
$PluginUser->save();
return $this->resData(PluginUser::getTokenInfo($PluginUser, true));
}
/**
* 修改密码
* @author:1950781041@qq.com
* @Date:2026-01-17
*/
public function setPassword(Request $request)
{
$password = $request->post('password');
$token = $request->post('token');
$vcode = $request->post('vcode');
$username = $request->post('username');
if (empty($password) || empty($token) || empty($vcode) || empty($username)) {
return $this->fail('参数错误');
}
Vcode::check($username, $vcode, VcodeScene::BIND_MOBILE['value'], $token);
$PluginUser = PluginUser::where(['id' => $request->uid])->find();
$PluginUser->password = $password;
$PluginUser->save();
return $this->success('修改成功');
}
public function wallet(Request $request)
{
$wallet = PluginFinanceWallet::where(['uid' => $request->uid])->find();
if (!$wallet) {
return $this->fail('钱包不存在');
}
return $this->resData($wallet);
}
/**
* 验证邀请码是否被使用
* @author:1950781041@qq.com
* @Date:2026-01-26
*/
public function checkInvitationCode(Request $request)
{
$code = $request->post('code');
$PluginUserInvitationCode = PluginUserInvitationCode::where(['code' => $code])->find();
if (!$PluginUserInvitationCode) {
return $this->fail('邀请码不存在');
}
if ($PluginUserInvitationCode->uid == $request->uid) {
return $this->fail('不能邀请自己');
}
if (!empty($PluginUserInvitationCode->use_uid)) {
return $this->fail('邀请码已使用');
}
if ($PluginUserInvitationCode->status != 'unused') {
return $this->fail('邀请码已使用');
}
return $this->success();
}
}