Compare commits

...

3 Commits

Author SHA1 Message Date
liutk 3cfdae17e3 补充竞猜记录 2024-05-19 20:53:36 +08:00
liutk 4601be715e 补充更新用户信息接口 2024-05-19 19:57:06 +08:00
liutk e6bb448140 添加竞猜接口 2024-05-19 18:06:59 +08:00
15 changed files with 369 additions and 25 deletions

View File

@ -20,9 +20,16 @@ class ActivityController extends ApiController
return $this->success(['activities' => ActivityResource::collection($activities)->resolve()]); return $this->success(['activities' => ActivityResource::collection($activities)->resolve()]);
} }
public function show(Activity $activity) public function show(Activity $activity, Request $request)
{ {
return ActivityResource::make($activity); $resource = ActivityResource::make($activity);
//判断当前用户是否在该活动有奖品
$resource->offsetSet('has_gift', UserActivity::where([
'user_id' => $request->user()->id,
'activity_id' => $activity->id
])->value('has_gift') ?? 0);
return $resource;
} }
public function rankList(Request $request) public function rankList(Request $request)
@ -30,7 +37,7 @@ class ActivityController extends ApiController
$activityId = $request->input('activity_id', 0); $activityId = $request->input('activity_id', 0);
//获取排行表 //获取排行表
$list = UserActivity::with('user')->where('activity_id', $activityId)->sort()->limit(30)->get(); $list = UserActivity::with('user')->where('activity_id', $activityId)->where('mark', '>', 0)->sort()->limit(30)->get();
//获取当前排名; //获取当前排名;
$userMark = UserActivity::where([ $userMark = UserActivity::where([

View File

@ -8,9 +8,14 @@ use Illuminate\Support\Arr;
use App\Models\Activity; use App\Models\Activity;
use App\Models\ActivityGame; use App\Models\ActivityGame;
use App\Http\Resources\Api\ActivityGameResource; use App\Http\Resources\Api\ActivityGameResource;
use App\Http\Requests\JoinGameRequest;
use App\Services\Api\ActivityGameService;
class ActivityGameController extends ApiController class ActivityGameController extends ApiController
{ {
protected string $serviceName = ActivityGameService::class;
public function index(Request $request) public function index(Request $request)
{ {
$activityId = $request->input('activity_id', 0); $activityId = $request->input('activity_id', 0);
@ -51,4 +56,15 @@ class ActivityGameController extends ApiController
return $this->success(); return $this->success();
} }
public function joinGame(ActivityGame $activityGame, JoinGameRequest $request)
{
$res = $this->service->join($activityGame, $request->user(), $request->input('score'));
if($res['status']){
return $this->success(null, '竞猜成功');
}else{
return $this->error($res['message']);
}
}
} }

View File

@ -4,12 +4,18 @@ namespace App\Http\Controllers\Api;
use Cache; use Cache;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Http\Request; use Slowlyo\OwlAdmin\Admin;
use App\Http\Requests\CodeRequest;
use App\Services\Api\UserService;
use App\Http\Resources\Api\UserResource;
use Overtrue\LaravelWeChat\EasyWeChat; use Overtrue\LaravelWeChat\EasyWeChat;
use Illuminate\Http\Request;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Storage;
use App\Services\Api\UserService;
use App\Http\Requests\CodeRequest;
use App\Http\Requests\UserInfoRequest;
use App\Models\Activity;
use App\Models\UserActivity;
use App\Http\Resources\Api\UserResource;
use App\Http\Resources\Api\UserActivityResource;
class UserController extends ApiController class UserController extends ApiController
{ {
@ -41,15 +47,119 @@ class UserController extends ApiController
// $phone = '17784326301'; // $phone = '17784326301';
$res = $this->service->bindPhone($user, $phone); $res = $this->service->bindPhone($user, $phone);
if($res){ if($res['status']){
return $this->success(null, '绑定成功'); return $this->success(null, '绑定成功');
}else{
return $this->error($res['message']);
}
}
public function activityList(Request $request)
{
$userActivities = UserActivity::with(['activity' => function($q) {
$q->show();
}])
->where(['user_id'=>$request->user()->id])
->orderBy('created_at', 'desc')
->simplePaginate($request->query('per_page', 20));
return $this->success(['activities' => UserActivityResource::collection($userActivities)->resolve()]);
}
public function updateUserInfo(UserInfoRequest $request)
{
$user = $request->user();
$nickName = $request->input('nick_name');
$avatar = $request->input('avatar');
//处理头像;
$avatarName = substr( $avatar , strrpos($avatar , '/')+1);
$filePath = 'avatars/'.$avatarName;
$file = file_get_contents($avatar);
Storage::disk(Admin::config('admin.upload.disk'))->put($filePath, $file);
$avatar = Storage::disk(Admin::config('admin.upload.disk'))->url($filePath);
$user->update([
'avatar' => $avatar,
'nick_name' => $nickName
]);
return $this->success(null, '修改成功');
}
/**
* 执行资源上传
*/
public function uploadResource(Request $request)
{
$path = $request->input('path', 'uploads') . '/temporary/' . date('Y-m-d');
$result = [];
// file 文件
$files = $request->file();
if($files){
foreach ($files as $key => $fileData) {
$item = null;
if (is_array($fileData)) {
foreach ($fileData as $file) {
if($_save_res = $this->saveFile($path, $file)){
$file_path = Storage::disk(Admin::config('admin.upload.disk'))->url($_save_res);
}else{
$file_path = '';
}
$item[] = $file_path;
}
} else {
if($save_res = $this->saveFile($path, $fileData)){
$file_path = Storage::disk(Admin::config('admin.upload.disk'))->url($save_res);
}else{
$file_path = '';
}
$item = $file_path;
}
$result[$key] = $item;
}
}else{
$data = $request->except(['path']);
foreach ($data as $key => $files) {
$item = null;
if (is_array($files)) {
// $_stop = 0;
foreach ($files as $file) {
$item[] = Storage::disk(Admin::config('admin.upload.disk'))->url($this->saveFile($path, $file));
}
} else {
$item = Storage::disk(Admin::config('admin.upload.disk'))->url($this->saveFile($path, $files));
}
$result[$key] = $item;
}
} }
return $this->error('绑定失败,请稍后重试'); return $this->json($result);
} }
public function updateUserInfo() protected function saveFile($path, $file = null)
{ {
if (gettype($file) == 'object') {
//获取文件大小
if($size = $file->getSize() > 2*1024*1024){//大于2M
return false;
}
$type = $file->getClientOriginalExtension();
if (in_array($type, array('jpeg', 'jpg', 'bmp', 'png'))) {
$file = Storage::disk(Admin::config('admin.upload.disk'))->putFile($path, $file);
}else{
return false;
}
} else if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $file, $result)) {
$type = $result[2];
if (in_array($type, array('jpeg', 'jpg', 'bmp', 'png'))) {
$savePath = $path . '/' . uniqid() . '.' . $type;
Storage::disk(Admin::config('admin.upload.disk'))->put($savePath, base64_decode(str_replace($result[1], '', $file)));
$file = $savePath;
}else{
return false;
}
}
return $file;
} }
} }

View File

@ -0,0 +1,49 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Contracts\Validation\Validator;
use App\Enums\Score;
use Illuminate\Validation\Rules\Enum;
class JoinGameRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'score' => [
'required',
new Enum(Score::class)
]
];
}
public function messages(){
$message = [
'score.required' => '竞猜比分为必选',
];
return $message;
}
protected function failedValidation(Validator $validator){
$error = $validator->errors()->all();
throw new HttpResponseException(response()->json(['data' => null, 'code' => 400, 'message' => $error[0]]));
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Contracts\Validation\Validator;
class UserInfoRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
'avatar'=> 'required|url',
'nick_name' => 'required|max:10',
];
}
public function messages(){
$messages = [
'avatar.required'=>'请选择头像',
'avatar.url'=>'头像参数错误',
'nick_name.required'=>'昵称必填',
'nick_name.max'=>'昵称长度不能超过10位',
];
return $messages;
}
protected function failedValidation(Validator $validator){
$error = $validator->errors()->all();
throw new HttpResponseException(response()->json(['data' => [], 'code' => 400, 'message' => $error[0]]));
}
}

View File

@ -23,6 +23,8 @@ class ActivityResource extends JsonResource
'start_at' => $this->start_at->format('Y-m-d H:i'), 'start_at' => $this->start_at->format('Y-m-d H:i'),
'end_at' => $this->end_at->format('Y-m-d H:i'), 'end_at' => $this->end_at->format('Y-m-d H:i'),
'state' => $this->state, 'state' => $this->state,
'has_gift' => $this->when($this->has_gift !== null, $this->has_gift),
]; ];
} }

View File

@ -16,12 +16,19 @@ class UserActivityResource extends JsonResource
public function toArray($request) public function toArray($request)
{ {
return [ return [
'nick_name' => $this->user?->nick_name ?? '', 'nick_name' => $this->whenLoaded('user', function () {
'avatar' => $this->user?->avatar ?? '', return $this->user?->nick_name ?? '';
}, ''),
'avatar' => $this->whenLoaded('user', function () {
return $this->user?->avatar ?? '';
}, ''),
'join_times' => $this->join_times, 'join_times' => $this->join_times,
'right_times' => $this->right_times, 'right_times' => $this->right_times,
'mark' => $this->mark, 'mark' => $this->mark,
'has_gift' => $this->has_gift,
'activity' => ActivityResource::make($this->whenLoaded('activity'))
]; ];
} }

View File

@ -16,8 +16,7 @@ class Activity extends Model
]; ];
public function scopeShow($q){ public function scopeShow($q){
$q->where('state', '>' ,0) $q->where('state', '>' ,0);
->where('start_at', '<', now());
} }
public function scopeSort($q) public function scopeSort($q)

View File

@ -11,6 +11,8 @@ class UserActivity extends Model
use HasFactory; use HasFactory;
protected $fillable = [ protected $fillable = [
'user_id', 'activity_id', 'join_times',
'right_times', 'last_join_at',
'mark','has_gift' 'mark','has_gift'
]; ];
@ -21,6 +23,11 @@ class UserActivity extends Model
->orderBy('last_join_at', 'asc'); ->orderBy('last_join_at', 'asc');
} }
public function activity()
{
return $this->belongsTo(Activity::class, 'activity_id');
}
public function user() public function user()
{ {
return $this->belongsTo(User::class, 'user_id'); return $this->belongsTo(User::class, 'user_id');

View File

@ -10,6 +10,10 @@ class UserGame extends Model
use HasFactory; use HasFactory;
protected $fillable = [ protected $fillable = [
'user_id',
'activity_id',
'game_id',
'score',
'is_right' 'is_right'
]; ];
} }

View File

@ -91,7 +91,7 @@ class ActivityGameService extends BaseService
) )
->incrementEach([ ->incrementEach([
'mark'=> $activityGame->mark, 'mark'=> $activityGame->mark,
'right_time'=> 1 'right_times'=> 1
]); ]);
DB::commit(); DB::commit();

View File

@ -0,0 +1,83 @@
<?php
namespace App\Services\Api;
use DB;
use App\Models\User;
use App\Models\ActivityGame;
use App\Models\UserActivity;
use App\Models\UserGame;
use Illuminate\Http\Response;
class ActivityGameService
{
public static function make(): static
{
return new static;
}
public function join(ActivityGame $game, User $user, $score)
{
$res = [
'status' => false,
'message'=> '',
];
//判断是否参加对应竞猜场次;
if(UserGame::where([
'user_id' => $user->id,
'game_id' => $game->id,
])->exists()){
$res['message'] = '您已参与竞猜,请勿重复提交';
return $res;
}
//判断该场竞猜是否还能参加
if($game->state != 1 || $game->game_at <= now()){
$res['message'] = '该场竞猜已结束,请选择其他场次参与';
return $res;
}
//判断活动是否还能参加
if($game->activity->start_at > now() || $game->activity->end_at < now()){
$res['message'] = '活动已结束,请选择其他活动参与';
return $res;
}
try{
DB::beginTransaction();
//添加活动参与记录;
$userActivity = UserActivity::where([
'user_id' => $user->id,
'activity_id' => $game->activity_id,
])->first();
if(!$userActivity){
$userActivity = new UserActivity();
$userActivity->user_id = $user->id;
$userActivity->activity_id = $game->activity_id;
$userActivity->save();
}
//添加场次竞猜记录;
UserGame::create([
'user_id' => $user->id,
'activity_id' =>$game->activity_id,
'game_id'=>$game->id,
'score'=>$score,
]);
//更新活动参与记录;
$userActivity->update([
'last_join_at' => now()
]);
$userActivity->increment('join_times');
DB::commit();
}
catch(Throwable $th){
DB::rollBack();
report($th);
$res['message'] = '系统错误,请刷新后重试';
return $res;
}
$res['status'] = true;
return $res;
}
}

View File

@ -5,10 +5,6 @@ namespace App\Services\Api;
use App\Models\User; use App\Models\User;
use Illuminate\Http\Response; use Illuminate\Http\Response;
/**
* @method User getModel()
* @method User|\Illuminate\Database\Query\Builder query()
*/
class UserService class UserService
{ {
public static function make(): static public static function make(): static
@ -46,14 +42,24 @@ class UserService
public function bindPhone(User $user, $phone) public function bindPhone(User $user, $phone)
{ {
$res = [
'status' => false,
'message'=> ''
];
if(User::where('phone', $phone)->where('id', '<>', $user->id)->exists()){ if(User::where('phone', $phone)->where('id', '<>', $user->id)->exists()){
return response()->json(['data'=>[], 'code'=> Response::HTTP_BAD_REQUEST, 'message' => '该手机号已被其他微信号绑定,请更换手机号绑定']); $res['message'] = '该手机号已被其他微信号绑定,请更换手机号绑定';
return $res;
} }
return $user->update([ $user->update([
'phone' => $phone, 'phone' => $phone,
'bind_phone_at' => now() 'bind_phone_at' => now()
]); ]);
$res['status'] = true;
return $res;
} }
} }

View File

@ -112,7 +112,7 @@ trait UploadTrait
}else{ }else{
$fileValue = $file['value']; $fileValue = $file['value'];
} }
Storage::disk(Admin::config('admin.upload.disk'))->move($file['value'], $filePath); Storage::disk(Admin::config('admin.upload.disk'))->move($fileValue, $filePath);
$fileArr[] = Storage::disk(Admin::config('admin.upload.disk'))->url($filePath); $fileArr[] = Storage::disk(Admin::config('admin.upload.disk'))->url($filePath);
} }
break; break;

View File

@ -36,13 +36,18 @@ Route::group(['prefix' => 'miniprogram', 'namespace' => 'Api\Miniprogram'], func
Route::get('games', [App\Http\Controllers\Api\ActivityGameController::class, 'index']); Route::get('games', [App\Http\Controllers\Api\ActivityGameController::class, 'index']);
// 绑定接口 // 绑定接口
Route::put('users/bind-phone', [App\Http\Controllers\Api\UserController::class, 'bindPhone']); Route::post('users/bind-phone', [App\Http\Controllers\Api\UserController::class, 'bindPhone']);
// 已授权绑定手机号 // 已授权绑定手机号
Route::middleware([HasBindPhone::class])->group(function(){ Route::middleware([HasBindPhone::class])->group(function(){
//参与竞猜 //参与竞猜
//更新资料 Route::post('games/{game}/join', [App\Http\Controllers\Api\ActivityGameController::class, 'joinGame']);
//资源上传;
Route::post('upload-avatar', [App\Http\Controllers\Api\UserController::class, 'uploadResource']);
//更新头像昵称
Route::post('user/update-info', [App\Http\Controllers\Api\UserController::class, 'updateUserInfo']);
//竞猜记录 //竞猜记录
Route::get('user-activities', [App\Http\Controllers\Api\UserController::class, 'activityList']);
//中奖记录 //中奖记录
//领奖 //领奖
//中奖记录详情; //中奖记录详情;