Files
anxinyan/server-api/app/controller/app/MessagesController.php
wushumin edd1a02157 first
2026-05-11 15:28:27 +08:00

278 lines
8.9 KiB
PHP

<?php
namespace app\controller\app;
use app\support\ContentService;
use support\Request;
use support\think\Db;
class MessagesController
{
public function summary(Request $request)
{
$userId = app_user_id($request);
$rows = Db::name('user_messages')
->where('user_id', $userId)
->order('id', 'desc')
->select()
->toArray();
$latest = $rows[0] ?? null;
$summary = $this->buildSummary($rows);
return api_success([
'total_count' => $summary['total_count'],
'unread_count' => $summary['unread_count'],
'category_counts' => $summary['category_counts'],
'latest_title' => $latest['title'] ?? '',
'latest_time' => $latest['created_at'] ?? '',
]);
}
public function meta(Request $request)
{
$content = new ContentService();
return api_success([
'message_page_copy' => $content->getMessagePageCopy(),
]);
}
public function index(Request $request)
{
$userId = app_user_id($request);
$category = $this->normalizeCategory((string)$request->input('category', 'all'));
$unreadOnly = (bool)$request->input('unread_only', false);
$rows = Db::name('user_messages')
->where('user_id', $userId)
->order('id', 'desc')
->select()
->toArray();
$filteredRows = array_values(array_filter($rows, function (array $item) use ($category, $unreadOnly) {
if ($unreadOnly && (bool)$item['is_read']) {
return false;
}
if ($category !== 'all' && $this->messageCategory($item['biz_type'] ?? '') !== $category) {
return false;
}
return true;
}));
$list = array_map(function (array $item) {
[$targetUrl, $targetLabel] = $this->resolveMessageTarget($item);
$messageCategory = $this->messageCategory($item['biz_type']);
return [
'id' => (int)$item['id'],
'title' => $item['title'],
'content' => $item['content'] ?: '',
'biz_type' => $item['biz_type'],
'biz_type_text' => $this->bizTypeText($item['biz_type']),
'category' => $messageCategory,
'category_text' => $this->categoryText($messageCategory),
'biz_id' => (int)($item['biz_id'] ?? 0),
'is_read' => (bool)$item['is_read'],
'created_at' => $item['created_at'],
'target_url' => $targetUrl,
'target_label' => $targetLabel,
];
}, $filteredRows);
$summary = $this->buildSummary($rows);
return api_success([
'list' => $list,
'summary' => array_merge($summary, [
'current_count' => count($list),
'current_category' => $category,
'unread_only' => $unreadOnly,
]),
]);
}
public function read(Request $request)
{
$id = (int)$request->input('id', 0);
if ($id <= 0) {
return api_error('消息 ID 不能为空', 422);
}
$message = Db::name('user_messages')->where('id', $id)->where('user_id', app_user_id($request))->find();
if (!$message) {
return api_error('消息不存在', 404);
}
if (!(bool)$message['is_read']) {
$now = date('Y-m-d H:i:s');
Db::name('user_messages')->where('id', $id)->update([
'is_read' => 1,
'read_at' => $now,
'updated_at' => $now,
]);
}
return api_success([
'id' => $id,
'is_read' => true,
], '已标记为已读');
}
public function readAll(Request $request)
{
$userId = app_user_id($request);
$now = date('Y-m-d H:i:s');
$affected = Db::name('user_messages')
->where('user_id', $userId)
->where('is_read', 0)
->update([
'is_read' => 1,
'read_at' => $now,
'updated_at' => $now,
]);
return api_success([
'affected' => (int)$affected,
], '已全部标记为已读');
}
private function resolveMessageTarget(array $message): array
{
$bizType = $message['biz_type'] ?? '';
$bizId = (int)($message['biz_id'] ?? 0);
if ($bizType === 'report' && $bizId > 0) {
$report = Db::name('reports')->where('id', $bizId)->find();
if ($report) {
return ["/pages/report/detail?report_no=" . rawurlencode((string)$report['report_no']), '查看报告'];
}
}
if ($bizType === 'order' && $bizId > 0) {
$order = Db::name('orders')->where('id', $bizId)->find();
if ($order) {
return ["/pages/order/detail?id={$bizId}", '查看订单'];
}
}
if ($bizType === 'return_shipped' && $bizId > 0) {
$order = Db::name('orders')->where('id', $bizId)->find();
if ($order) {
return ["/pages/order/detail?id={$bizId}", '查看物流'];
}
}
if ($bizType === 'return_received' && $bizId > 0) {
$order = Db::name('orders')->where('id', $bizId)->find();
if ($order) {
return ["/pages/order/detail?id={$bizId}", '查看订单'];
}
}
if ($bizType === 'supplement' && $bizId > 0) {
$supplementTask = Db::name('order_supplement_tasks')->where('id', $bizId)->find();
if ($supplementTask) {
if (($supplementTask['status'] ?? '') === 'pending') {
return ["/pages/order/supplement?order_id={$supplementTask['order_id']}", '去补资料'];
}
return ["/pages/order/detail?id={$supplementTask['order_id']}", '查看进度'];
}
}
if ($bizType === 'ticket_message' && $bizId > 0) {
$ticketMessage = Db::name('ticket_messages')->where('id', $bizId)->find();
if ($ticketMessage) {
return ["/pages/support/detail?id={$ticketMessage['ticket_id']}", '查看工单'];
}
}
if (in_array($bizType, ['ticket_waiting_user', 'ticket_resolved', 'ticket_closed'], true) && $bizId > 0) {
$ticket = Db::name('tickets')->where('id', $bizId)->find();
if ($ticket) {
return ["/pages/support/detail?id={$ticket['id']}", '查看工单'];
}
}
return ['', '查看详情'];
}
private function bizTypeText(string $bizType): string
{
return match ($bizType) {
'report' => '报告通知',
'order' => '订单通知',
'return_shipped' => '回寄通知',
'return_received' => '签收通知',
'supplement' => '补资料通知',
'ticket_message' => '工单通知',
'ticket_waiting_user' => '工单通知',
'ticket_resolved' => '工单通知',
'ticket_closed' => '工单通知',
default => '系统通知',
};
}
private function buildSummary(array $rows): array
{
$categoryCounts = [
'all' => count($rows),
'order' => 0,
'report' => 0,
'supplement' => 0,
'ticket' => 0,
];
$unreadCount = 0;
foreach ($rows as $item) {
$category = $this->messageCategory($item['biz_type'] ?? '');
if ($category !== 'all' && isset($categoryCounts[$category])) {
$categoryCounts[$category]++;
}
if (!(bool)($item['is_read'] ?? false)) {
$unreadCount++;
}
}
return [
'total_count' => count($rows),
'unread_count' => $unreadCount,
'category_counts' => $categoryCounts,
];
}
private function normalizeCategory(string $category): string
{
return in_array($category, ['all', 'order', 'report', 'supplement', 'ticket'], true)
? $category
: 'all';
}
private function messageCategory(string $bizType): string
{
return match ($bizType) {
'order' => 'order',
'return_shipped' => 'order',
'return_received' => 'order',
'report' => 'report',
'supplement' => 'supplement',
'ticket_message', 'ticket_waiting_user', 'ticket_resolved', 'ticket_closed' => 'ticket',
default => 'all',
};
}
private function categoryText(string $category): string
{
return match ($category) {
'order' => '订单',
'report' => '报告',
'supplement' => '补资料',
'ticket' => '工单',
default => '全部',
};
}
}