FastMovieAI 二开基线 v1.0 (完整源码)

This commit is contained in:
李建琦
2026-08-26 18:41:02 +08:00
parent fad7690c0c
commit d54584f70d
888 changed files with 105571 additions and 1 deletions
@@ -0,0 +1,188 @@
<?php
namespace plugin\user\expose\helper;
use app\expose\enum\EventName;
use app\expose\utils\Rsa;
use plugin\user\app\model\PluginUser;
use Webman\Event\Event;
/**
* 用户助手类
*
* Class User
* @package app\helper
*
* @method static PluginUser create(array $data)
* @method static PluginUser register(array $data)
* @method static PluginUser login(array $data)
* @method static PluginUser update(int $uid, array $data)
* @method static PluginUser info(int $uid)
* @method static string getIcode(int $uid)
* @method static int getUidByIcode(string $icode)
*
*/
class User
{
/**
* 创建用户
*
* @param array $data
* @param string $data['username'] 用户名(唯一性),可登录
* @param string $data['mobile'] 手机号(唯一性),可登录
* @param string $data['email'] 邮箱
* @param string $data['password'] 密码
* @param string $data['activation_time'] 激活时间
*
* @return PluginUser
*/
public static function create($data)
{
$insterData = [];
if (empty($data['channels_uid'])) {
throw new \Exception('渠道用户ID不能为空');
}
$insterData['channels_uid'] = $data['channels_uid'];
if (!empty($data['icode'])) {
$insterData['puid'] = self::getUidByIcode($data['icode']);
}
if (empty($data['username']) && empty($data['mobile'])) {
throw new \Exception('用户名、手机号至少填写一项');
}
if (!empty($data['username'])) {
$Find = PluginUser::where(['username' => $data['username']])->find();
if ($Find) {
return $Find;
}
$insterData['username'] = $data['username'];
}
if (!empty($data['mobile'])) {
$Find = PluginUser::where(['mobile' => $data['mobile']])->find();
if ($Find) {
return $Find;
}
$insterData['mobile'] = $data['mobile'];
}
if (!empty($data['email'])) {
$insterData['email'] = $data['email'];
}
if (!empty($data['password'])) {
$insterData['password'] = $data['password'];
}
if (!empty($data['activation_time'])) {
$insterData['activation_time'] = $data['activation_time'];
}
if (!empty($data['nickname'])) {
$insterData['nickname'] = $data['nickname'];
}
if (!empty($data['headimg'])) {
$insterData['headimg'] = $data['headimg'];
}
$model = new PluginUser();
$model->save($insterData);
// Event::emit(EventName::USER_REGISTER['value'], $model);
return $model;
}
/**
* 注册
*
* @param array $data
* @param string $data['icode'] 邀请码
* @param string $data['username'] 用户名(唯一性),可登录
* @param string $data['mobile'] 手机号(唯一性),可登录
* @param string $data['email'] 邮箱
* @param string $data['password'] 密码
*
* @return PluginUser
*/
public static function register($data)
{
$request = request();
if ($request->icode) {
$data['icode'] = $request->icode;
}
return self::create($data);
}
/**
* 更新
*
* @param int $uid 用户ID
* @param array $data 更新数据
* @param string $data['username'] 用户名
* @param string $data['mobile'] 手机号
* @param string $data['email'] 邮箱
* @return PluginUser
*/
public static function update($uid, $data)
{
$user = PluginUser::where(['id' => $uid, 'channels_uid' => $data['channels_uid']])->find();
if (!$user) {
throw new \Exception('用户不存在');
}
if (!empty($data['password'])) {
$user->password = $data['password'];
}
if (!empty($data['username'])) {
$Find = PluginUser::where(['username' => $data['username']])->find();
if ($Find && $Find->id != $uid) {
throw new \Exception('用户名已存在');
}
$user->username = $data['username'];
$user->username_time = date('Y-m-d H:i:s');
}
if (!empty($data['mobile'])) {
$Find = PluginUser::where(['mobile' => $data['mobile']])->find();
if ($Find && $Find->id != $uid) {
throw new \Exception('手机号已存在');
}
$user->mobile = $data['mobile'];
}
if (!empty($data['email'])) {
$user->email = $data['email'];
}
if (!empty($data['nickname'])) {
$user->nickname = $data['nickname'];
}
if (!empty($data['headimg'])) {
$user->headimg = $data['headimg'];
}
$user->save();
Event::emit(EventName::USER_UPDATE['value'], $user);
return $user;
}
/**
* 获取用户信息
*
* @param int $uid 用户ID
* @return PluginUser
*/
public static function info($uid)
{
$Find = PluginUser::where(['id' => $uid])->find();
if (!$Find) {
throw new \Exception('用户不存在');
}
return $Find;
}
/**
* 获取邀请码
*
* @param int $uid 用户ID
* @return string
*/
public static function getIcode($uid)
{
$user = PluginUser::where(['id' => $uid])->find();
return Rsa::encryptNumber($user->id);
}
/**
* 邀请码换取用户ID
*
* @param string $icode 邀请码
* @return int
*/
public static function getUidByIcode($icode)
{
return Rsa::decryptNumber($icode);
}
}
@@ -0,0 +1,111 @@
<?php
namespace plugin\user\expose\helper;
use app\expose\enum\State;
use plugin\user\app\model\PluginUser;
use plugin\user\app\model\PluginUserInvitationCode;
use plugin\user\app\model\PluginUserWechat;
use support\Redis;
class WechatOfficialAccount
{
public $FromUserName;
public $ToUserName;
public $MsgType;
public $Event;
public $EventKey;
public $data;
public function bind($params)
{
$PluginUserWechat = PluginUserWechat::where('openid', $this->FromUserName)->find();
if ($PluginUserWechat) {
if ($PluginUserWechat->uid && $PluginUserWechat->uid != $params['uid']) {
Redis::set($this->EventKey . '.bind', json_encode([
'status' => 'fail',
'message' => '当前微信已绑定其他账号'
]), 'EX', 60);
throw new \Exception('当前微信已绑定其他账号');
}
} else {
$PluginUserWechat = new PluginUserWechat();
$PluginUserWechat->openid = $this->FromUserName;
}
$PluginUserWechat->uid = $params['uid'];
$PluginUserWechat->subscribe = State::YES['value'];
$PluginUserWechat->channels_uid = $params['channels_uid'];
$PluginUserWechat->save();
Redis::set($this->EventKey . '.bind', json_encode([
'status' => 'success',
'uid' => $params['uid']
]), 'EX', 60);
return '绑定成功';
}
public function login($params)
{
try {
$PluginUserInvitationCode = null;
if (!empty($params['code'])) {
$PluginUserInvitationCode = PluginUserInvitationCode::where(['code' => $params['code']])->find();
if (!$PluginUserInvitationCode) {
$PluginUserInvitationCode = null;
}
if ($PluginUserInvitationCode->status != 'unused') {
$PluginUserInvitationCode = null;
}
if ($PluginUserInvitationCode->state != State::YES['value']) {
$PluginUserInvitationCode = null;
}
}
$PluginUserWechat = PluginUserWechat::where('openid', $this->FromUserName)->find();
if ($PluginUserWechat) {
if ($PluginUserWechat->uid) {
Redis::set($this->EventKey . '.login', json_encode([
'status' => 'success',
'uid' => $PluginUserWechat->uid,
]), 'EX', 60);
return '登录成功';
}
} else {
$PluginUserWechat = new PluginUserWechat();
$PluginUserWechat->openid = $this->FromUserName;
$PluginUserWechat->subscribe = State::YES['value'];
$PluginUserWechat->channels_uid = $params['channels_uid'];
}
$data = [
'channels_uid' => $params['channels_uid'],
'username' => $this->FromUserName,
'state' => State::YES['value'],
];
if ($PluginUserInvitationCode != null) {
$data['puid'] = $PluginUserInvitationCode->uid;
$data['activation_time'] = date('Y-m-d H:i:s');
}
$UserModel = new PluginUser();
$UserModel->save($data);
if ($PluginUserInvitationCode != null) {
$PluginUserInvitationCode->status = 'used';
$PluginUserInvitationCode->use_uid = $UserModel->id;
$PluginUserInvitationCode->use_time = date('Y-m-d H:i:s');
$PluginUserInvitationCode->save();
}
$PluginUserWechat->uid = $UserModel->id;
$PluginUserWechat->save();
Redis::set($this->EventKey . '.login', json_encode([
'status' => 'success',
'id' => $PluginUserWechat->id,
'uid' => $UserModel->id
]), 'EX', 60);
return '登录成功';
} catch (\Throwable $th) {
Redis::set($this->EventKey . '.login', json_encode([
'status' => 'fail',
'message' => $th->getMessage()
]), 'EX', 60);
return $th->getMessage();
}
}
}
@@ -0,0 +1,79 @@
<?php
namespace plugin\user\expose\middleware;
use app\expose\enum\ResponseCode;
use app\expose\trait\Json;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
use app\expose\exception\Exception;
use support\Log;
/**
* 前台应用必须引用此中间件,否者无法验证用户两步验证
*/
class Twofa implements MiddlewareInterface
{
use Json;
public function process(Request $request, callable $next): Response
{
if ($request->method() == 'OPTIONS') {
return response('', 204);
}
// 鉴权检测
try {
$this->Authorization($request);
$response = $next($request);
} catch (\Throwable $th) {
if ($request->expectsJson()) {
$response = $this->exception($th);
} else {
if (config('app.debug')) {
Log::error($th->getTraceAsString());
throw $th;
} else {
$response = response($th->getMessage(), 500);
}
}
}
return $response;
}
public function Authorization(Request $request)
{
# 无控制器地址
if (!$request->controller) {
return true;
}
# 获取控制器鉴权信息
$controller = new \ReflectionClass($request->controller);
$properties = $controller->getDefaultProperties();
$notNeedLogin = $properties['notNeedLogin'] ?? [];
$notNeedTwofa = array_merge($notNeedLogin, $properties['notNeedTwofa'] ?? []);
$notNeedTwofaAll = $properties['notNeedTwofaAll'] ?? false;
if ($notNeedTwofaAll) {
$notNeedTwofa = array_merge($notNeedTwofa, [$request->action]);
}
# 是否强制登录
if (in_array($request->action, $notNeedTwofa)) {
return true;
}
if ($request->source === 'saas') {
return true;
}
if (!$request->user) {
return true;
}
if (empty($request->user['twofa_state'])) {
return true;
}
if (empty($request->user['twofa']['expire'])) {
throw new Exception('需要两步验证', ResponseCode::NEED_TWOFA,['action'=>'logout']);
}
if (time() > $request->user['twofa']['expire']) {
throw new Exception('需要两步验证', ResponseCode::NEED_TWOFA,['action'=>'logout']);
}
$request->twofa_state = true;
$request->twofa = $request->user['twofa'];
}
}
@@ -0,0 +1,109 @@
<?php
namespace plugin\user\expose\middleware;
use app\expose\enum\ResponseCode;
use app\expose\enum\State;
use app\expose\trait\Json;
use Exception;
use loong\oauth\exception\LockException;
use loong\oauth\exception\TokenExpireException;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
use loong\oauth\facade\Auth;
use plugin\user\app\model\PluginUser;
use support\Log;
/**
* 前台应用必须引用此中间件,否者无法获取用户信息
*/
class UserAuth implements MiddlewareInterface
{
use Json;
public function process(Request $request, callable $next): Response
{
if ($request->method() == 'OPTIONS') {
return response('', 204);
}
// 鉴权检测
try {
$this->Authorization($request);
$response = $next($request);
} catch (\Throwable $th) {
if ($request->expectsJson()) {
$response = $this->exception($th);
} else {
if (config('app.debug')) {
Log::error($th->getTraceAsString());
throw $th;
} else {
$response = response($th->getMessage(), 500);
}
}
}
return $response;
}
/**
* 业务逻辑
* @author 贵州猿创科技有限公司
* @Email unknown.renlong@gmail.com
* @DateTime 2023-03-11
*/
public function Authorization(Request $request)
{
# 无控制器地址
if (!$request->controller) {
return true;
}
# 获取控制器鉴权信息
$controller = new \ReflectionClass($request->controller);
$properties = $controller->getDefaultProperties();
# 无需登录方法
$notNeedLogin = $properties['notNeedLogin'] ?? [];
# 是否整个控制器都不需要登录
$notNeedLoginAll = $properties['notNeedLoginAll'] ?? false;
if ($notNeedLoginAll) {
$notNeedLogin = array_merge($notNeedLogin, [$request->action]);
}
# 是否强制登录
$isForceLogin = true;
if (in_array($request->action, $notNeedLogin)) {
$isForceLogin = false;
}
try {
# 令牌验证
$token = $request->header('authorization');
if (!$token) {
throw new Exception('请先登录', ResponseCode::NEED_LOGIN);
}
$user = Auth::setPrefix('CONTROL')->decrypt($token);
if (!$user) {
throw new TokenExpireException();
}
$request->token = $token;
$request->user = $user;
$request->channels_uid = $user['channels_uid'];
$request->uid = $user['uid'];
} catch (TokenExpireException $e) {
if ($isForceLogin) {
throw new Exception('登录已过期,请重新登录', ResponseCode::NEED_LOGIN);
}
} catch (LockException $e) {
if ($isForceLogin) {
throw new Exception($e->getMessage(), ResponseCode::LOCK);
}
} catch (\Throwable $th) {
if ($isForceLogin) {
throw new \Exception($th->getMessage(), ResponseCode::NEED_LOGIN);
}
}
if ($request->uid) {
$User = PluginUser::where('id', $request->uid)->find();
if ($User->state != State::YES['value']) {
throw new Exception("您的账号已被禁用", ResponseCode::NEED_LOGIN);
}
}
}
}