93 lines
3.5 KiB
PHP
93 lines
3.5 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Mini;
|
|
|
|
use App\Exceptions\RepositoryException;
|
|
use App\Models\NoticeModel;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Modules\AnnoRoute\Attribute\GetRoute;
|
|
use Modules\AnnoRoute\Attribute\PutRoute;
|
|
use Modules\AnnoRoute\Attribute\RequestAttribute;
|
|
|
|
/**
|
|
* 小程序通知(本店通知 + 全员广播)
|
|
*
|
|
* 广播已读处理:store_id=0 的广播是全局共享记录,直接改 is_read 会影响其他门店,
|
|
* 因此标记已读时复制一条本店专属的已读记录(data.broadcast_from 记来源),
|
|
* 列表查询时排除已有已读副本的广播。
|
|
*/
|
|
#[RequestAttribute('/mini', 'mini', authGuard: 'users')]
|
|
class NoticeController extends BaseMiniController
|
|
{
|
|
/** 本店通知 + 全员广播(store_id in [0, 当前id]),分页 + unread_count */
|
|
#[GetRoute('/notice', authorize: true)]
|
|
public function index(Request $request): JsonResponse
|
|
{
|
|
$store = $this->currentStore($request);
|
|
|
|
// 本店已读过的广播来源ID(已读副本记录)
|
|
$readBroadcastIds = NoticeModel::query()
|
|
->where('store_id', $store->id)
|
|
->whereNotNull('data->broadcast_from')
|
|
->pluck('data')
|
|
->map(static fn (?array $data) => $data['broadcast_from'] ?? null)
|
|
->filter()
|
|
->values();
|
|
|
|
$query = NoticeModel::query()->where(function ($q) use ($store, $readBroadcastIds) {
|
|
$q->where('store_id', $store->id)
|
|
->orWhere(function ($broadcastQuery) use ($readBroadcastIds) {
|
|
$broadcastQuery->where('store_id', NoticeModel::BROADCAST_STORE_ID);
|
|
if ($readBroadcastIds->isNotEmpty()) {
|
|
$broadcastQuery->whereNotIn('id', $readBroadcastIds->all());
|
|
}
|
|
});
|
|
});
|
|
|
|
$unreadCount = (clone $query)->where('is_read', NoticeModel::UNREAD)->count();
|
|
|
|
$data = $query->orderBy('id', 'desc')
|
|
->paginate((int) $request->input('pageSize', 10))
|
|
->toArray();
|
|
$data['unread_count'] = $unreadCount;
|
|
|
|
return $this->success($data);
|
|
}
|
|
|
|
/** 标记已读(广播 → 复制本店已读副本;定向通知 → 直接更新) */
|
|
#[PutRoute('/notice/{id}/read', authorize: true, where: ['id' => '[0-9]+'])]
|
|
public function read(int $id, Request $request): JsonResponse
|
|
{
|
|
$store = $this->currentStore($request);
|
|
|
|
$notice = NoticeModel::whereIn('store_id', [NoticeModel::BROADCAST_STORE_ID, $store->id])->find($id);
|
|
if ($notice === null) {
|
|
throw new RepositoryException('通知不存在');
|
|
}
|
|
|
|
if ($notice->store_id === NoticeModel::BROADCAST_STORE_ID) {
|
|
$exists = NoticeModel::where('store_id', $store->id)
|
|
->where('data->broadcast_from', $notice->id)
|
|
->exists();
|
|
if (! $exists) {
|
|
NoticeModel::create([
|
|
'store_id' => $store->id,
|
|
'type' => $notice->type,
|
|
'title' => $notice->title,
|
|
'content' => $notice->content,
|
|
'data' => ['broadcast_from' => $notice->id] + (array) $notice->data,
|
|
'is_read' => NoticeModel::READ,
|
|
'read_at' => now(),
|
|
]);
|
|
}
|
|
} elseif ($notice->is_read === NoticeModel::UNREAD) {
|
|
$notice->is_read = NoticeModel::READ;
|
|
$notice->read_at = now();
|
|
$notice->save();
|
|
}
|
|
|
|
return $this->success();
|
|
}
|
|
}
|