first version

This commit is contained in:
liu
2026-07-23 20:41:25 +08:00
parent 00a0938a1b
commit 10cff754a4
211 changed files with 11577 additions and 842 deletions
@@ -0,0 +1,136 @@
<?php
namespace App\Http\Controllers\Mini;
use App\Exceptions\RepositoryException;
use App\Models\StoreModel;
use App\Models\SupplierModel;
use App\Models\UserModel;
use App\Services\WechatService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Modules\AnnoRoute\Attribute\GetRoute;
use Modules\AnnoRoute\Attribute\PostRoute;
use Modules\AnnoRoute\Attribute\RequestAttribute;
/**
* 小程序认证(微信登录 / 手机号绑定 / 当前用户信息)
*
* authGuard: usersprovider 指向 UserModel,与后台 sys_users 天然隔离);
* authorize: true 仅要求登录(sanctum + authGuard:users),不做细粒度权限点;
* token abilities ['mini'] 作来源标记。
*/
#[RequestAttribute('/mini', 'mini', authGuard: 'users')]
class AuthController extends BaseMiniController
{
/** 小程序登录:wx.login 的 code → openid → 自动注册/登录 → 签发 token */
#[PostRoute('/auth/login', authorize: false)]
public function login(Request $request): JsonResponse
{
$data = $request->validate([
'code' => 'required|string',
], [
'code.required' => '缺少登录凭证 code',
]);
$session = app(WechatService::class)->code2Session($data['code']);
$user = UserModel::firstOrNew(['openid' => $session['openid']]);
$isNew = ! $user->exists;
if ($user->status === UserModel::STATUS_DISABLED) {
throw new RepositoryException('账号已被停用,请联系客服');
}
if ($isNew) {
$user->type = UserModel::TYPE_PENDING;
$user->status = UserModel::STATUS_NORMAL;
}
if (! empty($session['unionid'])) {
$user->unionid = $session['unionid'];
}
$user->last_login_at = now();
$user->save();
$token = $user->createToken('mini', ['mini'])->plainTextToken;
return $this->success([
'token' => $token,
'user' => $this->formatUser($user->fresh(['store.level:id,name', 'supplier:id,name'])),
], $isNew ? '注册成功' : '登录成功');
}
/**
* 绑定手机号:phoneCode 换手机号 → 按手机号自动匹配门店/供应商
* (命中门店 → type=1+store_id;命中供应商 → type=2+supplier_id;都不命中 → 保持待绑定,后台人工处理)
*/
#[PostRoute('/auth/phone', authorize: true)]
public function phone(Request $request): JsonResponse
{
$data = $request->validate([
'phoneCode' => 'required|string',
], [
'phoneCode.required' => '缺少手机号授权凭证 phoneCode',
]);
$phone = app(WechatService::class)->getPhone($data['phoneCode']);
$user = $this->currentUser($request);
$user->phone = $phone;
if (! $user->isBound()) {
$store = StoreModel::where('phone', $phone)
->where('status', StoreModel::STATUS_NORMAL)
->first();
if ($store !== null) {
$user->type = UserModel::TYPE_STORE;
$user->store_id = $store->id;
$user->supplier_id = 0;
} else {
$supplier = SupplierModel::where('phone', $phone)
->where('status', SupplierModel::STATUS_NORMAL)
->first();
if ($supplier !== null) {
$user->type = UserModel::TYPE_SUPPLIER;
$user->supplier_id = $supplier->id;
$user->store_id = 0;
}
}
}
$user->save();
return $this->success([
'user' => $this->formatUser($user->fresh(['store.level:id,name', 'supplier:id,name'])),
]);
}
/** 当前用户信息(含门店客户等级 —— 全局价格体系依据 / 供应商信息) */
#[GetRoute('/auth/info', authorize: true)]
public function info(Request $request): JsonResponse
{
$user = UserModel::with(['store.level:id,name', 'supplier:id,name'])
->find($request->user()->id);
if ($user === null) {
throw new RepositoryException('账号不存在');
}
return $this->success(['user' => $this->formatUser($user)]);
}
/**
* 小程序端用户信息输出结构
*
* @return array<string, mixed>
*/
private function formatUser(UserModel $user): array
{
return [
'id' => $user->id,
'nickname' => $user->nickname,
'avatar' => $user->avatar,
'phone' => $user->phone,
'type' => $user->type,
'store' => $user->store,
'supplier' => $user->supplier,
];
}
}