更新后端接口

This commit is contained in:
2026-01-19 14:52:08 +08:00
parent cc603cb158
commit 1d5930dc4c
8 changed files with 1448 additions and 3 deletions

View File

@@ -0,0 +1,303 @@
<?php
// +----------------------------------------------------------------------
// | SentCMS [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2024 http://www.tensent.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: molong <molong@tensent.cn> <http://www.tensent.cn>
// +----------------------------------------------------------------------
namespace Modules\Account\Services;
use Illuminate\Http\Request;
use Modules\Account\Models\Bill;
use Modules\Account\Models\Family;
use Modules\Account\Models\FamilyMember;
use Illuminate\Support\Facades\DB;
class AdminStatisticsService {
/**
* @title 获取概览统计
*
* @param Request $request
* @return array
*/
public function getOverview($request) {
$year = $request->input('year', date('Y'));
$month = $request->input('month', date('m'));
$startDate = $year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT) . '-01';
$endDate = $year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT) . '-31';
// 总账单数
$totalBills = Bill::count();
// 当月账单数
$monthBills = Bill::whereBetween('bill_date', [$startDate, $endDate])->count();
// 总收入
$totalIncome = (float)Bill::where('type', 'income')->sum('amount');
// 总支出
$totalExpense = (float)Bill::where('type', 'expense')->sum('amount');
// 当月收入
$monthIncome = (float)Bill::where('type', 'income')
->whereBetween('bill_date', [$startDate, $endDate])
->sum('amount');
// 当月支出
$monthExpense = (float)Bill::where('type', 'expense')
->whereBetween('bill_date', [$startDate, $endDate])
->sum('amount');
// 总用户数
$totalUsers = DB::table('auth_users')->count();
// 总家庭数
$totalFamilies = Family::count();
// 活跃用户数(本月有记账的用户)
$activeUsers = Bill::whereBetween('bill_date', [$startDate, $endDate])
->distinct('user_id')
->count('user_id');
// 活跃家庭数(本月有记账的家庭)
$activeFamilies = Bill::whereBetween('bill_date', [$startDate, $endDate])
->whereNotNull('family_id')
->distinct('family_id')
->count('family_id');
return [
'total_bills' => $totalBills,
'month_bills' => $monthBills,
'total_income' => $totalIncome,
'total_expense' => $totalExpense,
'total_balance' => $totalIncome - $totalExpense,
'month_income' => $monthIncome,
'month_expense' => $monthExpense,
'month_balance' => $monthIncome - $monthExpense,
'total_users' => $totalUsers,
'total_families' => $totalFamilies,
'active_users' => $activeUsers,
'active_families' => $activeFamilies
];
}
/**
* @title 获取趋势统计
*
* @param Request $request
* @return array
*/
public function getTrend($request) {
$type = $request->input('type', 'month'); // month 或 year
$year = $request->input('year', date('Y'));
$months = $request->input('months', 12);
$years = $request->input('years', 5);
if ($type === 'month') {
// 月度趋势
$data = [];
for ($i = $months - 1; $i >= 0; $i--) {
$date = date('Y-m', strtotime("-$i months"));
$startDate = $date . '-01';
$endDate = date('Y-m-t', strtotime($date));
$income = (float)Bill::where('type', 'income')
->whereBetween('bill_date', [$startDate, $endDate])
->sum('amount');
$expense = (float)Bill::where('type', 'expense')
->whereBetween('bill_date', [$startDate, $endDate])
->sum('amount');
$count = Bill::whereBetween('bill_date', [$startDate, $endDate])->count();
$data[] = [
'date' => $date,
'income' => $income,
'expense' => $expense,
'balance' => $income - $expense,
'count' => $count
];
}
} else {
// 年度趋势
$data = [];
for ($i = $years - 1; $i >= 0; $i--) {
$currentYear = date('Y') - $i;
$income = (float)Bill::where('type', 'income')
->whereYear('bill_date', $currentYear)
->sum('amount');
$expense = (float)Bill::where('type', 'expense')
->whereYear('bill_date', $currentYear)
->sum('amount');
$count = Bill::whereYear('bill_date', $currentYear)->count();
$data[] = [
'year' => $currentYear,
'income' => $income,
'expense' => $expense,
'balance' => $income - $expense,
'count' => $count
];
}
}
return $data;
}
/**
* @title 获取分类统计
*
* @param Request $request
* @return array
*/
public function getCategoryStatistics($request) {
$type = $request->input('type', 'expense'); // income 或 expense
$year = $request->input('year', date('Y'));
$month = $request->input('month');
$query = Bill::where('type', $type);
if ($year && $month) {
$startDate = $year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT) . '-01';
$endDate = $year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT) . '-31';
$query->whereBetween('bill_date', [$startDate, $endDate]);
} else {
$query->whereYear('bill_date', $year);
}
$bills = $query->get();
// 按分类汇总
$data = $bills->groupBy('category')->map(function ($items) {
return [
'category' => $items->first()->category,
'count' => $items->count(),
'amount' => (float)$items->sum('amount')
];
})->sortByDesc('amount')->values();
// 计算总金额和占比
$totalAmount = $data->sum('amount');
$data = $data->map(function ($item) use ($totalAmount) {
$item['percentage'] = $totalAmount > 0 ? round($item['amount'] / $totalAmount * 100, 2) : 0;
return $item;
});
return [
'type' => $type,
'total_amount' => (float)$totalAmount,
'total_count' => $data->sum('count'),
'categories' => $data
];
}
/**
* @title 获取用户统计
*
* @param Request $request
* @return array
*/
public function getUserStatistics($request) {
$limit = $request->input('limit', 20);
$type = $request->input('type', 'expense'); // income 或 expense
$year = $request->input('year', date('Y'));
$month = $request->input('month');
$query = Bill::select('user_id')
->selectRaw('COUNT(*) as bill_count')
->selectRaw('SUM(CASE WHEN type = "income" THEN amount ELSE 0 END) as total_income')
->selectRaw('SUM(CASE WHEN type = "expense" THEN amount ELSE 0 END) as total_expense')
->selectRaw('SUM(CASE WHEN type = "income" THEN amount ELSE 0 END) - SUM(CASE WHEN type = "expense" THEN amount ELSE 0 END) as balance')
->with('user:uid,nickname,username');
if ($year && $month) {
$startDate = $year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT) . '-01';
$endDate = $year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT) . '-31';
$query->whereBetween('bill_date', [$startDate, $endDate]);
} else {
$query->whereYear('bill_date', $year);
}
$users = $query->groupBy('user_id')
->orderBy($type === 'income' ? 'total_income' : 'total_expense', 'desc')
->limit($limit)
->get();
return [
'type' => $type,
'users' => $users->map(function ($user) {
return [
'user_id' => $user->user_id,
'name' => $user->user->nickname ?? $user->user->username,
'username' => $user->user->username,
'bill_count' => $user->bill_count,
'total_income' => (float)$user->total_income,
'total_expense' => (float)$user->total_expense,
'balance' => (float)$user->balance
];
})
];
}
/**
* @title 获取家庭统计
*
* @param Request $request
* @return array
*/
public function getFamilyStatistics($request) {
$limit = $request->input('limit', 20);
$type = $request->input('type', 'expense'); // income 或 expense
$year = $request->input('year', date('Y'));
$month = $request->input('month');
$query = Bill::select('family_id')
->selectRaw('COUNT(*) as bill_count')
->selectRaw('SUM(CASE WHEN type = "income" THEN amount ELSE 0 END) as total_income')
->selectRaw('SUM(CASE WHEN type = "expense" THEN amount ELSE 0 END) as total_expense')
->selectRaw('SUM(CASE WHEN type = "income" THEN amount ELSE 0 END) - SUM(CASE WHEN type = "expense" THEN amount ELSE 0 END) as balance')
->whereNotNull('family_id')
->with('family:id,name,owner_id');
if ($year && $month) {
$startDate = $year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT) . '-01';
$endDate = $year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT) . '-31';
$query->whereBetween('bill_date', [$startDate, $endDate]);
} else {
$query->whereYear('bill_date', $year);
}
$families = $query->groupBy('family_id')
->orderBy($type === 'income' ? 'total_income' : 'total_expense', 'desc')
->limit($limit)
->get();
// 获取成员数量
$familyIds = $families->pluck('family_id')->toArray();
$memberCounts = FamilyMember::whereIn('family_id', $familyIds)
->selectRaw('family_id, COUNT(*) as member_count')
->groupBy('family_id')
->pluck('member_count', 'family_id');
return [
'type' => $type,
'families' => $families->map(function ($family) use ($memberCounts) {
return [
'family_id' => $family->family_id,
'name' => $family->family->name,
'member_count' => $memberCounts[$family->family_id] ?? 0,
'bill_count' => $family->bill_count,
'total_income' => (float)$family->total_income,
'total_expense' => (float)$family->total_expense,
'balance' => (float)$family->balance
];
})
];
}
}