feat(api): add sign required-article endpoint

GET /api/sign/required_article returns one random article from the
"签到广告" article category (status=1, is_del=0, hidden=0). Empty
category or no articles returns null so clients can fall through to
direct sign-in. Powers the pre-sign-in reading gate per
docs/project-shaoyaoju/prd-require.md §6.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
danaisuiyuan
2026-05-10 15:47:48 +08:00
parent 9559031536
commit b3a1dabf87
3 changed files with 55 additions and 0 deletions

View File

@@ -6,6 +6,7 @@
namespace app\controller\api\v1\user; namespace app\controller\api\v1\user;
use app\Request; use app\Request;
use app\services\article\ArticleServices;
use app\services\user\member\MemberCardServices; use app\services\user\member\MemberCardServices;
use app\services\user\UserServices; use app\services\user\UserServices;
use app\services\user\UserSignServices; use app\services\user\UserSignServices;
@@ -147,4 +148,26 @@ class UserSign
$this->services->setSignRemind($uid, $status); $this->services->setSignRemind($uid, $status);
return app('json')->success('设置成功'); return app('json')->success('设置成功');
} }
/**
* 签到前置阅读:从"签到广告"分类下随机返回一篇文章
* 分类不存在 / 无文章 时返回 null前端跳过门槛直接签到
*/
public function required_article(ArticleServices $articleServices)
{
$article = $articleServices->getRandomByCategoryTitle('签到广告');
if (!$article) {
return app('json')->successful(null);
}
$img = $article['image_input'] ?? '';
if (is_array($img)) {
$img = $img[0] ?? '';
}
return app('json')->successful([
'id' => (int)($article['id'] ?? 0),
'title' => (string)($article['title'] ?? ''),
'image' => (string)$img,
'view_required_seconds' => 10,
]);
}
} }

View File

@@ -119,6 +119,37 @@ class ArticleServices extends BaseServices
return $this->dao->update($id, ['product_id' => $product_id]); return $this->dao->update($id, ['product_id' => $product_id]);
} }
/**
* 按分类标题获取一条随机文章(用于签到前置阅读门槛)
* @param string $categoryTitle 分类标题(如"签到广告"
* @return array|null id/title/image_input/visit分类或文章不存在时返回 null
*/
public function getRandomByCategoryTitle(string $categoryTitle)
{
/** @var ArticleCategoryServices $categoryServices */
$categoryServices = app()->make(ArticleCategoryServices::class);
$cat = $categoryServices->getOne([
'title' => $categoryTitle,
'status' => 1,
'is_del' => 0,
'hidden' => 0,
], 'id');
if (!$cat) {
return null;
}
$where = ['cid' => (int)$cat['id'], 'status' => 1, 'hide' => 0];
$ids = $this->dao->getColumn($where, 'id');
if (!$ids) {
return null;
}
$pickId = (int)$ids[array_rand($ids)];
$article = $this->dao->getOne(['id' => $pickId], 'id,title,image_input,visit,add_time');
if (!$article) {
return null;
}
return is_array($article) ? $article : $article->toArray();
}
/** /**
* 获取数量 * 获取数量
* @param array $where * @param array $where

View File

@@ -275,6 +275,7 @@ Route::group('api', function () {
Route::post('sign/integral', 'v1.user.UserSign/sign_integral')->middleware(BlockerMiddleware::class)->name('signIntegral');//签到 Route::post('sign/integral', 'v1.user.UserSign/sign_integral')->middleware(BlockerMiddleware::class)->name('signIntegral');//签到
Route::get('sign/remind/:status', 'v1.user.UserSign/sign_remind')->name('signRemind');//用户设置签到提醒 Route::get('sign/remind/:status', 'v1.user.UserSign/sign_remind')->name('signRemind');//用户设置签到提醒
Route::get('sign/calendar', 'v1.user.UserSign/sign_calendar')->name('signCalendar');//日历数据 Route::get('sign/calendar', 'v1.user.UserSign/sign_calendar')->name('signCalendar');//日历数据
Route::get('sign/required_article', 'v1.user.UserSign/required_article')->name('signRequiredArticle');//签到前置阅读文章("签到广告"分类随机一条)
//优惠券类 //优惠券类
Route::post('coupon/receive', 'v1.activity.StoreCoupons/receive')->middleware(BlockerMiddleware::class)->name('couponReceive'); //领取优惠券 Route::post('coupon/receive', 'v1.activity.StoreCoupons/receive')->middleware(BlockerMiddleware::class)->name('couponReceive'); //领取优惠券
Route::post('coupon/receive/batch', 'v1.activity.StoreCoupons/receive_batch')->name('couponReceiveBatch'); //批量领取优惠券 Route::post('coupon/receive/batch', 'v1.activity.StoreCoupons/receive_batch')->name('couponReceiveBatch'); //批量领取优惠券