chore: 重写初始提交(清空历史,整理后全量提交)

This commit is contained in:
ywxapp
2026-08-16 16:54:14 +08:00
commit 6c1a106bc1
1808 changed files with 238144 additions and 0 deletions
+135
View File
@@ -0,0 +1,135 @@
<?php
// +----------------------------------------------------------------------
// | YwxApp [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: ywxapp<admin@ywxapp.cn>
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace addon\haonav\controller;
use ywxapp\controller\FrontendBase;
use ywxapp\model\MemberUser as UserModel;
/**
* 前台会员登录 / 注册 / 退出 / 资料
*
* 复用框架前台 AuthAuthorization 头或 access_token Cookie)。
* 登录/注册成功后 JwtService 把 token 写入 Result 单例,
* 由 Result::applyTokenCookies() 随响应写回非 httpOnly Cookiepath=/),
* 前端(整页/iframe)后续请求自动带登录态,无需前端额外存储。
*
* 注:框架 Auth::register() 内部依赖不存在的 UserModel::checkExists()
* 故注册在此控制器用 Member 模型直接建号,再用 Auth::login() 建立登录态与 token。
*
* @author ywxapp <admin@ywxapp.cn>
*/
class Account extends FrontendBase
{
protected $noNeedLogin = ['login', 'register'];
protected $noNeedVerify = ['*'];
/**
* 规整要返回给前端的用户资料
*/
protected function userInfo(): array
{
$info = $this->auth->info ?? [];
if (is_object($info)) {
$info = $info->toArray();
}
return [
'uid' => (int)($info['uid'] ?? 0),
'account' => (string)($info['account'] ?? ''),
'nickname' => (string)($info['nickname'] ?? ''),
'avatar' => (string)($info['avatar'] ?? ''),
];
}
/**
* 登录
* POST /haonav/account/login {account, password}
*/
public function login()
{
$account = trim((string)$this->request->post('account', ''));
$password = (string)$this->request->post('password', '');
if ($account === '' || $password === '') {
return $this->result->error('请输入账号和密码');
}
try {
$this->auth->login($account, $password);
} catch (\Throwable $e) {
// Auth::login 内部已通过 Result 输出错误则不会到这里;此处兜底
return $this->result->error('登录失败:' . $e->getMessage());
}
return $this->result->success($this->userInfo(), '登录成功');
}
/**
* 注册
* POST /haonav/account/register {account, password, nickname?}
*/
public function register()
{
$account = trim((string)$this->request->post('account', ''));
$password = (string)$this->request->post('password', '');
$nickname = trim((string)$this->request->post('nickname', ''));
if ($account === '' || $password === '') {
return $this->result->error('请输入账号和密码');
}
if (mb_strlen($password) < 6) {
return $this->result->error('密码至少 6 位');
}
if (!preg_match('/^[\x{4e00}-\x{9fa5}a-zA-Z0-9_@.\-]+$/u', $account)) {
return $this->result->error('账号仅支持中英文、数字、_@.- 等字符');
}
// 账号查重(框架 UserModel::checkExists 不存在,这里直接查询)
if (UserModel::where('account', $account)->findOrEmpty()->isExists()) {
return $this->result->error('该账号已被注册');
}
$user = new UserModel();
$user->account = $account;
$user->nickname = $nickname !== '' ? mb_substr($nickname, 0, 30) : ('用户' . mb_substr($account, 0, 4));
// email 为 NOT NULL + 唯一:用本地占位邮箱保证唯一且不报错(非真实邮箱)
$user->email = $account . '@haonav.local';
$user->password = $password; // 触发 Member 模型 setPasswordAttr 自动加盐加密
$user->status = 1;
$user->gid = (int)config('fastadmin.user_default_group') ?: 0;
$user->create_ip = $this->request->ip();
$user->update_ip = $this->request->ip();
$user->save();
// 建号后建立登录态并写回 token Cookie
try {
$this->auth->login($account, $password);
} catch (\Throwable $e) {
return $this->result->error('注册成功但自动登录失败,请手动登录');
}
return $this->result->success($this->userInfo(), '注册成功');
}
/**
* 退出登录
* POST /haonav/account/logout
*/
public function logout()
{
$this->auth->logout();
return $this->result->success([], '已退出登录');
}
/**
* 当前登录资料(用于前端刷新登录态)
* GET /haonav/account/profile
*/
public function profile()
{
if (! $this->auth || ! $this->auth->isLogin) {
return $this->result->error('未登录', 401);
}
return $this->result->success($this->userInfo());
}
}