mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-06-25 04:07:17 +08:00
parent
b987ddf083
commit
6cd3fb6d6c
98
app/Http/Admin/Controllers/StatController.php
Normal file
98
app/Http/Admin/Controllers/StatController.php
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Admin\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Admin\Services\Stat as StatService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @RoutePrefix("/admin/stat")
|
||||||
|
*/
|
||||||
|
class StatController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Get("/sales/hot", name="admin.stat.hot_sales")
|
||||||
|
*/
|
||||||
|
public function hotSalesAction()
|
||||||
|
{
|
||||||
|
$statService = new StatService();
|
||||||
|
|
||||||
|
$years = $statService->getYearOptions();
|
||||||
|
$months = $statService->getMonthOptions();
|
||||||
|
$items = $statService->hotSales();
|
||||||
|
|
||||||
|
$this->view->pick('stat/hot_sales');
|
||||||
|
$this->view->setVar('years', $years);
|
||||||
|
$this->view->setVar('months', $months);
|
||||||
|
$this->view->setVar('items', $items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Get("/sales", name="admin.stat.sales")
|
||||||
|
*/
|
||||||
|
public function salesAction()
|
||||||
|
{
|
||||||
|
$statService = new StatService();
|
||||||
|
|
||||||
|
$years = $statService->getYearOptions();
|
||||||
|
$months = $statService->getMonthOptions();
|
||||||
|
$data = $statService->sales();
|
||||||
|
|
||||||
|
$this->view->pick('stat/sales');
|
||||||
|
$this->view->setVar('years', $years);
|
||||||
|
$this->view->setVar('months', $months);
|
||||||
|
$this->view->setVar('data', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Get("/refunds", name="admin.stat.refunds")
|
||||||
|
*/
|
||||||
|
public function refundsAction()
|
||||||
|
{
|
||||||
|
$statService = new StatService();
|
||||||
|
|
||||||
|
$years = $statService->getYearOptions();
|
||||||
|
$months = $statService->getMonthOptions();
|
||||||
|
$data = $statService->refunds();
|
||||||
|
|
||||||
|
$this->view->pick('stat/refunds');
|
||||||
|
$this->view->setVar('years', $years);
|
||||||
|
$this->view->setVar('months', $months);
|
||||||
|
$this->view->setVar('data', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Get("/users/registered", name="admin.stat.reg_users")
|
||||||
|
*/
|
||||||
|
public function registeredUsersAction()
|
||||||
|
{
|
||||||
|
$statService = new StatService();
|
||||||
|
|
||||||
|
$years = $statService->getYearOptions();
|
||||||
|
$months = $statService->getMonthOptions();
|
||||||
|
$data = $statService->registeredUsers();
|
||||||
|
|
||||||
|
$this->view->pick('stat/registered_users');
|
||||||
|
$this->view->setVar('years', $years);
|
||||||
|
$this->view->setVar('months', $months);
|
||||||
|
$this->view->setVar('data', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Get("/users/online", name="admin.stat.online_users")
|
||||||
|
*/
|
||||||
|
public function onlineUsersAction()
|
||||||
|
{
|
||||||
|
$statService = new StatService();
|
||||||
|
|
||||||
|
$years = $statService->getYearOptions();
|
||||||
|
$months = $statService->getMonthOptions();
|
||||||
|
$data = $statService->onlineUsers();
|
||||||
|
|
||||||
|
$this->view->pick('stat/online_users');
|
||||||
|
$this->view->setVar('years', $years);
|
||||||
|
$this->view->setVar('months', $months);
|
||||||
|
$this->view->setVar('data', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -438,6 +438,43 @@ class AuthNode extends Service
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'id' => '2-7',
|
||||||
|
'title' => '数据统计',
|
||||||
|
'type' => 'menu',
|
||||||
|
'children' => [
|
||||||
|
[
|
||||||
|
'id' => '2-7-1',
|
||||||
|
'title' => '热卖商品',
|
||||||
|
'type' => 'menu',
|
||||||
|
'route' => 'admin.stat.hot_sales',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'id' => '2-7-2',
|
||||||
|
'title' => '成交订单',
|
||||||
|
'type' => 'menu',
|
||||||
|
'route' => 'admin.stat.sales',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'id' => '2-7-3',
|
||||||
|
'title' => '售后退款',
|
||||||
|
'type' => 'menu',
|
||||||
|
'route' => 'admin.stat.refunds',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'id' => '2-7-4',
|
||||||
|
'title' => '注册用户',
|
||||||
|
'type' => 'menu',
|
||||||
|
'route' => 'admin.stat.reg_users',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'id' => '2-7-5',
|
||||||
|
'title' => '活跃用户',
|
||||||
|
'type' => 'menu',
|
||||||
|
'route' => 'admin.stat.online_users',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
405
app/Http/Admin/Services/Stat.php
Normal file
405
app/Http/Admin/Services/Stat.php
Normal file
@ -0,0 +1,405 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Admin\Services;
|
||||||
|
|
||||||
|
use App\Models\Order as OrderModel;
|
||||||
|
use App\Repos\Stat as StatRepo;
|
||||||
|
|
||||||
|
class Stat extends Service
|
||||||
|
{
|
||||||
|
|
||||||
|
public function hotSales()
|
||||||
|
{
|
||||||
|
$type = $this->request->getQuery('type', 'int', OrderModel::ITEM_COURSE);
|
||||||
|
$year = $this->request->getQuery('year', 'int', date('Y'));
|
||||||
|
$month = $this->request->getQuery('month', 'int', date('m'));
|
||||||
|
|
||||||
|
$prev = $this->getPrevMonth($year, $month);
|
||||||
|
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'title' => "{$year}-{$month}",
|
||||||
|
'sales' => $this->handleHotSales($type, $year, $month),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => "{$prev['year']}-{$prev['month']}",
|
||||||
|
'sales' => $this->handleHotSales($type, $prev['year'], $prev['month']),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sales()
|
||||||
|
{
|
||||||
|
$year = $this->request->getQuery('year', 'int', date('Y'));
|
||||||
|
$month = $this->request->getQuery('month', 'int', date('m'));
|
||||||
|
|
||||||
|
$prev = $this->getPrevMonth($year, $month);
|
||||||
|
$currSales = $this->handleSales($year, $month);
|
||||||
|
$prevSales = $this->handleSales($prev['year'], $prev['month']);
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
foreach (range(1, 31) as $day) {
|
||||||
|
$date = sprintf('%02d', $day);
|
||||||
|
$prevMonth = "{$prev['year']}-{$prev['month']}";
|
||||||
|
$currMonth = "{$year}-{$month}";
|
||||||
|
$items[] = [
|
||||||
|
'date' => $date,
|
||||||
|
$currMonth => $currSales[$date] ?? 0,
|
||||||
|
$prevMonth => $prevSales[$date] ?? 0,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function refunds()
|
||||||
|
{
|
||||||
|
$year = $this->request->getQuery('year', 'int', date('Y'));
|
||||||
|
$month = $this->request->getQuery('month', 'int', date('m'));
|
||||||
|
|
||||||
|
$prev = $this->getPrevMonth($year, $month);
|
||||||
|
$currRefunds = $this->handleRefunds($year, $month);
|
||||||
|
$prevRefunds = $this->handleRefunds($prev['year'], $prev['month']);
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
foreach (range(1, 31) as $day) {
|
||||||
|
$date = sprintf('%02d', $day);
|
||||||
|
$prevMonth = "{$prev['year']}-{$prev['month']}";
|
||||||
|
$currMonth = "{$year}-{$month}";
|
||||||
|
$items[] = [
|
||||||
|
'date' => $date,
|
||||||
|
$currMonth => $currRefunds[$date] ?? 0,
|
||||||
|
$prevMonth => $prevRefunds[$date] ?? 0,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function registeredUsers()
|
||||||
|
{
|
||||||
|
$year = $this->request->getQuery('year', 'int', date('Y'));
|
||||||
|
$month = $this->request->getQuery('month', 'int', date('m'));
|
||||||
|
|
||||||
|
$prev = $this->getPrevMonth($year, $month);
|
||||||
|
$currUsers = $this->handleRegisteredUsers($year, $month);
|
||||||
|
$prevUsers = $this->handleRegisteredUsers($prev['year'], $prev['month']);
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
foreach (range(1, 31) as $day) {
|
||||||
|
$date = sprintf('%02d', $day);
|
||||||
|
$prevMonth = "{$prev['year']}-{$prev['month']}";
|
||||||
|
$currMonth = "{$year}-{$month}";
|
||||||
|
$items[] = [
|
||||||
|
'date' => $date,
|
||||||
|
$currMonth => $currUsers[$date] ?? 0,
|
||||||
|
$prevMonth => $prevUsers[$date] ?? 0,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onlineUsers()
|
||||||
|
{
|
||||||
|
$year = $this->request->getQuery('year', 'int', date('Y'));
|
||||||
|
$month = $this->request->getQuery('month', 'int', date('m'));
|
||||||
|
|
||||||
|
$prev = $this->getPrevMonth($year, $month);
|
||||||
|
$currUsers = $this->handleOnlineUsers($year, $month);
|
||||||
|
$prevUsers = $this->handleOnlineUsers($prev['year'], $prev['month']);
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
foreach (range(1, 31) as $day) {
|
||||||
|
$date = sprintf('%02d', $day);
|
||||||
|
$prevMonth = "{$prev['year']}-{$prev['month']}";
|
||||||
|
$currMonth = "{$year}-{$month}";
|
||||||
|
$items[] = [
|
||||||
|
'date' => $date,
|
||||||
|
$currMonth => $currUsers[$date] ?? 0,
|
||||||
|
$prevMonth => $prevUsers[$date] ?? 0,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getYearOptions()
|
||||||
|
{
|
||||||
|
$end = date('Y');
|
||||||
|
|
||||||
|
$start = $end - 3;
|
||||||
|
|
||||||
|
return range($start, $end);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMonthOptions()
|
||||||
|
{
|
||||||
|
$options = [];
|
||||||
|
|
||||||
|
foreach (range(1, 12) as $value) {
|
||||||
|
$options[] = sprintf('%02d', $value);
|
||||||
|
}
|
||||||
|
return $options;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function isCurrMonth($year, $month)
|
||||||
|
{
|
||||||
|
return date('Y-m') == "{$year}-{$month}";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getPrevMonth($year, $month)
|
||||||
|
{
|
||||||
|
$currentMonthTime = strtotime("{$year}-{$month}");
|
||||||
|
|
||||||
|
$prevMonthTime = strtotime('-1 month', $currentMonthTime);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'year' => date('Y', $prevMonthTime),
|
||||||
|
'month' => date('m', $prevMonthTime),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getMonthDates($year, $month)
|
||||||
|
{
|
||||||
|
$startTime = strtotime("{$year}-{$month}-01");
|
||||||
|
|
||||||
|
$days = date('t', $startTime);
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
foreach (range(1, $days) as $day) {
|
||||||
|
$result[] = sprintf('%04d-%02d-%02d', $year, $month, $day);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function handleHotSales($type, $year, $month)
|
||||||
|
{
|
||||||
|
$keyName = "stat_hot_sales:{$type}_{$year}_{$month}";
|
||||||
|
|
||||||
|
$cache = $this->getCache();
|
||||||
|
|
||||||
|
$items = $cache->get($keyName);
|
||||||
|
|
||||||
|
if (!$items) {
|
||||||
|
|
||||||
|
$statRepo = new StatRepo();
|
||||||
|
|
||||||
|
$orders = $statRepo->findMonthlyOrders($type, $year, $month);
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
if ($orders->count() > 0) {
|
||||||
|
|
||||||
|
foreach ($orders as $order) {
|
||||||
|
$key = $order->item_id;
|
||||||
|
if (!isset($items[$key])) {
|
||||||
|
$items[$key] = [
|
||||||
|
'title' => $order->subject,
|
||||||
|
'total_count' => 1,
|
||||||
|
'total_amount' => $order->amount,
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$items[$key]['total_count'] += 1;
|
||||||
|
$items[$key]['total_amount'] += $order->amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$totalCount = array_column($items, 'total_count');
|
||||||
|
|
||||||
|
array_multisort($totalCount, SORT_DESC, $items);
|
||||||
|
}
|
||||||
|
|
||||||
|
$queryMonth = "{$year}-{$month}";
|
||||||
|
|
||||||
|
$currMonth = date('Y-m');
|
||||||
|
|
||||||
|
if ($queryMonth < $currMonth) {
|
||||||
|
$cache->save($keyName, $items, 7 * 86400);
|
||||||
|
} else {
|
||||||
|
$cache->save($keyName, $items, 2 * 3600);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function handleSales($year, $month)
|
||||||
|
{
|
||||||
|
$keyName = "stat_sales:{$year}_{$month}";
|
||||||
|
|
||||||
|
$redis = $this->getRedis();
|
||||||
|
|
||||||
|
$list = $redis->hGetAll($keyName);
|
||||||
|
|
||||||
|
$statRepo = new StatRepo();
|
||||||
|
|
||||||
|
$currDate = date('Y-m-d');
|
||||||
|
$currDay = date('d');
|
||||||
|
|
||||||
|
if (!$list) {
|
||||||
|
$dates = $this->getMonthDates($year, $month);
|
||||||
|
foreach ($dates as $date) {
|
||||||
|
$key = substr($date, -2);
|
||||||
|
if ($date < $currDate) {
|
||||||
|
$list[$key] = $statRepo->sumDailySales($date);
|
||||||
|
} elseif ($date == $currDate) {
|
||||||
|
$list[$key] = -999;
|
||||||
|
} else {
|
||||||
|
$list[$key] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$redis->hMSet($keyName, $list);
|
||||||
|
$redis->expire($keyName, 7 * 86400);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($list as $key => $value) {
|
||||||
|
if ($value < 0) {
|
||||||
|
$list[$key] = $statRepo->sumDailySales("{$year}-{$month}-{$key}");
|
||||||
|
$redis->hSet($keyName, $key, $list[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->isCurrMonth($year, $month)) {
|
||||||
|
$list[$currDay] = $statRepo->sumDailySales($currDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function handleRefunds($year, $month)
|
||||||
|
{
|
||||||
|
$keyName = "stat_refunds:{$year}_{$month}";
|
||||||
|
|
||||||
|
$redis = $this->getRedis();
|
||||||
|
|
||||||
|
$list = $redis->hGetAll($keyName);
|
||||||
|
|
||||||
|
$statRepo = new StatRepo();
|
||||||
|
|
||||||
|
$currDate = date('Y-m-d');
|
||||||
|
$currDay = date('d');
|
||||||
|
|
||||||
|
if (!$list) {
|
||||||
|
$dates = $this->getMonthDates($year, $month);
|
||||||
|
foreach ($dates as $date) {
|
||||||
|
$key = substr($date, -2);
|
||||||
|
if ($date < $currDate) {
|
||||||
|
$list[$key] = $statRepo->sumDailyRefunds($date);
|
||||||
|
} elseif ($date == $currDate) {
|
||||||
|
$list[$key] = -999;
|
||||||
|
} else {
|
||||||
|
$list[$key] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$redis->hMSet($keyName, $list);
|
||||||
|
$redis->expire($keyName, 7 * 86400);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($list as $key => $value) {
|
||||||
|
if ($value < 0) {
|
||||||
|
$list[$key] = $statRepo->sumDailyRefunds("{$year}-{$month}-{$key}");
|
||||||
|
$redis->hSet($keyName, $key, $list[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->isCurrMonth($year, $month)) {
|
||||||
|
$list[$currDay] = $statRepo->sumDailyRefunds($currDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function handleRegisteredUsers($year, $month)
|
||||||
|
{
|
||||||
|
$keyName = "stat_reg_users:{$year}_{$month}";
|
||||||
|
|
||||||
|
$redis = $this->getRedis();
|
||||||
|
|
||||||
|
$list = $redis->hGetAll($keyName);
|
||||||
|
|
||||||
|
$statRepo = new StatRepo();
|
||||||
|
|
||||||
|
$currDate = date('Y-m-d');
|
||||||
|
$currDay = date('d');
|
||||||
|
|
||||||
|
if (!$list) {
|
||||||
|
$dates = $this->getMonthDates($year, $month);
|
||||||
|
foreach ($dates as $date) {
|
||||||
|
$key = substr($date, -2);
|
||||||
|
if ($date < $currDate) {
|
||||||
|
$list[$key] = $statRepo->countDailyRegisteredUser($date);
|
||||||
|
} elseif ($date == $currDate) {
|
||||||
|
$list[$key] = -999;
|
||||||
|
} else {
|
||||||
|
$list[$key] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$redis->hMSet($keyName, $list);
|
||||||
|
$redis->expire($keyName, 7 * 86400);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($list as $key => $value) {
|
||||||
|
if ($value < 0) {
|
||||||
|
$list[$key] = $statRepo->countDailyRegisteredUser("{$year}-{$month}-{$key}");
|
||||||
|
$redis->hSet($keyName, $key, $list[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->isCurrMonth($year, $month)) {
|
||||||
|
$list[$currDay] = $statRepo->countDailyRegisteredUser($currDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function handleOnlineUsers($year, $month)
|
||||||
|
{
|
||||||
|
$keyName = "stat_online_users:{$year}_{$month}";
|
||||||
|
|
||||||
|
$redis = $this->getRedis();
|
||||||
|
|
||||||
|
$list = $redis->hGetAll($keyName);
|
||||||
|
|
||||||
|
$statRepo = new StatRepo();
|
||||||
|
|
||||||
|
$currDate = date('Y-m-d');
|
||||||
|
$currDay = date('d');
|
||||||
|
|
||||||
|
if (!$list) {
|
||||||
|
$dates = $this->getMonthDates($year, $month);
|
||||||
|
foreach ($dates as $date) {
|
||||||
|
$key = substr($date, -2);
|
||||||
|
if ($date < $currDate) {
|
||||||
|
$list[$key] = $statRepo->countDailyOnlineUser($date);
|
||||||
|
} elseif ($date == $currDate) {
|
||||||
|
$list[$key] = -999;
|
||||||
|
} else {
|
||||||
|
$list[$key] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$redis->hMSet($keyName, $list);
|
||||||
|
$redis->expire($keyName, 7 * 86400);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($list as $key => $value) {
|
||||||
|
if ($value < 0) {
|
||||||
|
$list[$key] = $statRepo->countDailyOnlineUser("{$year}-{$month}-{$key}");
|
||||||
|
$redis->hSet($keyName, $key, $list[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->isCurrMonth($year, $month)) {
|
||||||
|
$list[$currDay] = $statRepo->countDailyOnlineUser($currDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
101
app/Http/Admin/Views/stat/hot_sales.volt
Normal file
101
app/Http/Admin/Views/stat/hot_sales.volt
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
{% extends 'templates/main.volt' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{%- macro show_sales(sales) %}
|
||||||
|
<table class="layui-table kg-table">
|
||||||
|
<colgroup>
|
||||||
|
<col>
|
||||||
|
<col>
|
||||||
|
<col>
|
||||||
|
<col>
|
||||||
|
</colgroup>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>排序</th>
|
||||||
|
<th>名称</th>
|
||||||
|
<th>数量</th>
|
||||||
|
<th>金额</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for sale in sales %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ loop.index }}</td>
|
||||||
|
<td>{{ sale.title }}</td>
|
||||||
|
<td>{{ sale.total_count }}</td>
|
||||||
|
<td>{{ '¥%0.2f'|format(sale.total_amount) }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{% set types = {'1':'课程','2':'套餐','3':'赞赏','4':'会员'} %}
|
||||||
|
{% set year = request.get('year','int',date('Y')) %}
|
||||||
|
{% set month = request.get('month','int',date('m')) %}
|
||||||
|
{% set type = request.get('type','int',1) %}
|
||||||
|
|
||||||
|
<div class="kg-nav">
|
||||||
|
<div class="kg-nav-left">
|
||||||
|
<span class="layui-breadcrumb">
|
||||||
|
<a><cite>热卖商品统计</cite></a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form class="layui-form kg-search-form" method="GET" action="{{ url({'for':'admin.stat.hot_sales'}) }}">
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">选择类型</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select name="type">
|
||||||
|
{% for key,value in types %}
|
||||||
|
<option value="{{ key }}" {% if key == type %}selected{% endif %}>{{ value }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<label class="layui-form-label">选择年份</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select name="year">
|
||||||
|
{% for value in years %}
|
||||||
|
<option value="{{ value }}" {% if value == year %}selected{% endif %}>{{ value }}年</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<label class="layui-form-label">选择月份</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select name="month">
|
||||||
|
{% for value in months %}
|
||||||
|
<option value="{{ value }}" {% if value == month %}selected{% endif %}>{{ value }}月</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<button class="layui-btn" lay-submit="true">查询</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="kg-sale-list layui-row layui-col-space15">
|
||||||
|
{% for item in items %}
|
||||||
|
<div class="layui-col-md6">
|
||||||
|
<div class="layui-card">
|
||||||
|
<div class="layui-card-header">{{ item.title }}</div>
|
||||||
|
<div class="layui-card-body">{{ show_sales(item.sales) }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block inline_css %}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.kg-sale-list {
|
||||||
|
padding: 10px;
|
||||||
|
background: #f2f2f2;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
{% endblock %}
|
74
app/Http/Admin/Views/stat/online_users.volt
Normal file
74
app/Http/Admin/Views/stat/online_users.volt
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
{% extends 'templates/main.volt' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% set year = request.get('year','int',date('Y')) %}
|
||||||
|
{% set month = request.get('month','int',date('m')) %}
|
||||||
|
|
||||||
|
<div class="kg-nav">
|
||||||
|
<div class="kg-nav-left">
|
||||||
|
<span class="layui-breadcrumb">
|
||||||
|
<a><cite>活跃用户统计</cite></a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form class="layui-form kg-search-form" method="GET" action="{{ url({'for':'admin.stat.online_users'}) }}">
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">选择年份</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select name="year">
|
||||||
|
{% for value in years %}
|
||||||
|
<option value="{{ value }}" {% if value == year %}selected{% endif %}>{{ value }}年</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<label class="layui-form-label">选择月份</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select name="month">
|
||||||
|
{% for value in months %}
|
||||||
|
<option value="{{ value }}" {% if value == month %}selected{% endif %}>{{ value }}月</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<button class="layui-btn" lay-submit="true">查询</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="kg-chart" id="chart"></div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block include_js %}
|
||||||
|
|
||||||
|
{{ js_include('https://cdn.bootcdn.net/ajax/libs/echarts/4.8.0/echarts.min.js', false) }}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block inline_js %}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
var myChart = echarts.init(document.getElementById('chart'));
|
||||||
|
|
||||||
|
var option = {
|
||||||
|
legend: {},
|
||||||
|
tooltip: {},
|
||||||
|
dataset: {
|
||||||
|
source: {{ data|json_encode }}
|
||||||
|
},
|
||||||
|
xAxis: {type: 'category'},
|
||||||
|
yAxis: {},
|
||||||
|
series: [
|
||||||
|
{type: 'line'},
|
||||||
|
{type: 'line'}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
myChart.setOption(option);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
74
app/Http/Admin/Views/stat/refunds.volt
Normal file
74
app/Http/Admin/Views/stat/refunds.volt
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
{% extends 'templates/main.volt' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% set year = request.get('year','int',date('Y')) %}
|
||||||
|
{% set month = request.get('month','int',date('m')) %}
|
||||||
|
|
||||||
|
<div class="kg-nav">
|
||||||
|
<div class="kg-nav-left">
|
||||||
|
<span class="layui-breadcrumb">
|
||||||
|
<a><cite>售后退款统计</cite></a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form class="layui-form kg-search-form" method="GET" action="{{ url({'for':'admin.stat.refunds'}) }}">
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">选择年份</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select name="year">
|
||||||
|
{% for value in years %}
|
||||||
|
<option value="{{ value }}" {% if value == year %}selected{% endif %}>{{ value }}年</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<label class="layui-form-label">选择月份</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select name="month">
|
||||||
|
{% for value in months %}
|
||||||
|
<option value="{{ value }}" {% if value == month %}selected{% endif %}>{{ value }}月</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<button class="layui-btn" lay-submit="true">查询</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="kg-chart" id="chart"></div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block include_js %}
|
||||||
|
|
||||||
|
{{ js_include('https://cdn.bootcdn.net/ajax/libs/echarts/4.8.0/echarts.min.js', false) }}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block inline_js %}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
var myChart = echarts.init(document.getElementById('chart'));
|
||||||
|
|
||||||
|
var option = {
|
||||||
|
legend: {},
|
||||||
|
tooltip: {},
|
||||||
|
dataset: {
|
||||||
|
source: {{ data|json_encode }}
|
||||||
|
},
|
||||||
|
xAxis: {type: 'category'},
|
||||||
|
yAxis: {},
|
||||||
|
series: [
|
||||||
|
{type: 'line'},
|
||||||
|
{type: 'line'}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
myChart.setOption(option);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
74
app/Http/Admin/Views/stat/registered_users.volt
Normal file
74
app/Http/Admin/Views/stat/registered_users.volt
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
{% extends 'templates/main.volt' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% set year = request.get('year','int',date('Y')) %}
|
||||||
|
{% set month = request.get('month','int',date('m')) %}
|
||||||
|
|
||||||
|
<div class="kg-nav">
|
||||||
|
<div class="kg-nav-left">
|
||||||
|
<span class="layui-breadcrumb">
|
||||||
|
<a><cite>注册用户统计</cite></a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form class="layui-form kg-search-form" method="GET" action="{{ url({'for':'admin.stat.reg_users'}) }}">
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">选择年份</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select name="year">
|
||||||
|
{% for value in years %}
|
||||||
|
<option value="{{ value }}" {% if value == year %}selected{% endif %}>{{ value }}年</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<label class="layui-form-label">选择月份</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select name="month">
|
||||||
|
{% for value in months %}
|
||||||
|
<option value="{{ value }}" {% if value == month %}selected{% endif %}>{{ value }}月</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<button class="layui-btn" lay-submit="true">查询</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="kg-chart" id="chart"></div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block include_js %}
|
||||||
|
|
||||||
|
{{ js_include('https://cdn.bootcdn.net/ajax/libs/echarts/4.8.0/echarts.min.js', false) }}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block inline_js %}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
var myChart = echarts.init(document.getElementById('chart'));
|
||||||
|
|
||||||
|
var option = {
|
||||||
|
legend: {},
|
||||||
|
tooltip: {},
|
||||||
|
dataset: {
|
||||||
|
source: {{ data|json_encode }}
|
||||||
|
},
|
||||||
|
xAxis: {type: 'category'},
|
||||||
|
yAxis: {},
|
||||||
|
series: [
|
||||||
|
{type: 'line'},
|
||||||
|
{type: 'line'}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
myChart.setOption(option);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
74
app/Http/Admin/Views/stat/sales.volt
Normal file
74
app/Http/Admin/Views/stat/sales.volt
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
{% extends 'templates/main.volt' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% set year = request.get('year','int',date('Y')) %}
|
||||||
|
{% set month = request.get('month','int',date('m')) %}
|
||||||
|
|
||||||
|
<div class="kg-nav">
|
||||||
|
<div class="kg-nav-left">
|
||||||
|
<span class="layui-breadcrumb">
|
||||||
|
<a><cite>成交订单统计</cite></a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form class="layui-form kg-search-form" method="GET" action="{{ url({'for':'admin.stat.sales'}) }}">
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">选择年份</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select name="year">
|
||||||
|
{% for value in years %}
|
||||||
|
<option value="{{ value }}" {% if value == year %}selected{% endif %}>{{ value }}年</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<label class="layui-form-label">选择月份</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select name="month">
|
||||||
|
{% for value in months %}
|
||||||
|
<option value="{{ value }}" {% if value == month %}selected{% endif %}>{{ value }}月</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<button class="layui-btn" lay-submit="true">查询</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="kg-chart" id="chart"></div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block include_js %}
|
||||||
|
|
||||||
|
{{ js_include('https://cdn.bootcdn.net/ajax/libs/echarts/4.8.0/echarts.min.js', false) }}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block inline_js %}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
var myChart = echarts.init(document.getElementById('chart'));
|
||||||
|
|
||||||
|
var option = {
|
||||||
|
legend: {},
|
||||||
|
tooltip: {},
|
||||||
|
dataset: {
|
||||||
|
source: {{ data|json_encode }}
|
||||||
|
},
|
||||||
|
xAxis: {type: 'category'},
|
||||||
|
yAxis: {},
|
||||||
|
series: [
|
||||||
|
{type: 'line'},
|
||||||
|
{type: 'line'}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
myChart.setOption(option);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
52
app/Listeners/User.php
Normal file
52
app/Listeners/User.php
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Models\Online as OnlineModel;
|
||||||
|
use App\Models\User as UserModel;
|
||||||
|
use App\Repos\Online as OnlineRepo;
|
||||||
|
use App\Traits\Client as ClientTrait;
|
||||||
|
use Phalcon\Events\Event;
|
||||||
|
|
||||||
|
class User extends Listener
|
||||||
|
{
|
||||||
|
|
||||||
|
use ClientTrait;
|
||||||
|
|
||||||
|
public function online(Event $event, $source, UserModel $user)
|
||||||
|
{
|
||||||
|
$now = time();
|
||||||
|
|
||||||
|
if ($now - $user->active_time > 600) {
|
||||||
|
|
||||||
|
$user->active_time = $now;
|
||||||
|
|
||||||
|
$user->update();
|
||||||
|
|
||||||
|
$onlineRepo = new OnlineRepo();
|
||||||
|
|
||||||
|
$online = $onlineRepo->findByUserDate($user->id, date('Y-m-d'));
|
||||||
|
|
||||||
|
if ($online) {
|
||||||
|
|
||||||
|
$online->active_time = $now;
|
||||||
|
$online->client_type = $this->getClientType();
|
||||||
|
$online->client_ip = $this->getClientIp();
|
||||||
|
|
||||||
|
$online->update();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$online = new OnlineModel();
|
||||||
|
|
||||||
|
$online->user_id = $user->id;
|
||||||
|
$online->active_time = $now;
|
||||||
|
$online->client_type = $this->getClientType();
|
||||||
|
$online->client_ip = $this->getClientIp();
|
||||||
|
|
||||||
|
$online->create();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
79
app/Models/Online.php
Normal file
79
app/Models/Online.php
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
class Online extends Model
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键编号
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户编号
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $user_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计划编号
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端类型
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $client_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端IP
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $client_ip;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 活跃时间
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $active_time;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $create_time;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $update_time;
|
||||||
|
|
||||||
|
public function getSource(): string
|
||||||
|
{
|
||||||
|
return 'kg_online';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function beforeCreate()
|
||||||
|
{
|
||||||
|
$this->create_time = time();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function beforeUpdate()
|
||||||
|
{
|
||||||
|
$this->update_time = time();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -63,7 +63,7 @@ class Audit extends Repository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $id
|
* @param int $id
|
||||||
* @return AuditModel|Model|bool
|
* @return AuditModel|Model|bool
|
||||||
*/
|
*/
|
||||||
public function findById($id)
|
public function findById($id)
|
||||||
|
30
app/Repos/Online.php
Normal file
30
app/Repos/Online.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repos;
|
||||||
|
|
||||||
|
use App\Models\Online as OnlineModel;
|
||||||
|
use Phalcon\Mvc\Model;
|
||||||
|
|
||||||
|
class Online extends Repository
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $userId
|
||||||
|
* @param string $activeDate
|
||||||
|
* @return OnlineModel|Model|bool
|
||||||
|
*/
|
||||||
|
public function findByUserDate($userId, $activeDate)
|
||||||
|
{
|
||||||
|
$activeTime = strtotime($activeDate);
|
||||||
|
|
||||||
|
return OnlineModel::findFirst([
|
||||||
|
'conditions' => 'user_id = ?1 AND active_time BETWEEN ?2 AND ?3',
|
||||||
|
'bind' => [
|
||||||
|
1 => $userId,
|
||||||
|
2 => $activeTime,
|
||||||
|
3 => $activeTime + 86400,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
139
app/Repos/Stat.php
Normal file
139
app/Repos/Stat.php
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repos;
|
||||||
|
|
||||||
|
use App\Models\Online as OnlineModel;
|
||||||
|
use App\Models\Order as OrderModel;
|
||||||
|
use App\Models\OrderStatus as OrderStatusModel;
|
||||||
|
use App\Models\Refund as RefundModel;
|
||||||
|
use App\Models\User as UserModel;
|
||||||
|
use Phalcon\Mvc\Model\Resultset;
|
||||||
|
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||||
|
|
||||||
|
class Stat extends Repository
|
||||||
|
{
|
||||||
|
|
||||||
|
public function countDailyRegisteredUser($date)
|
||||||
|
{
|
||||||
|
$startTime = strtotime($date);
|
||||||
|
|
||||||
|
$endTime = $startTime + 86400;
|
||||||
|
|
||||||
|
return (int)UserModel::count([
|
||||||
|
'conditions' => 'create_time BETWEEN :start_time: AND :end_time:',
|
||||||
|
'bind' => ['start_time' => $startTime, 'end_time' => $endTime],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function countDailyOnlineUser($date)
|
||||||
|
{
|
||||||
|
$startTime = strtotime($date);
|
||||||
|
|
||||||
|
$endTime = $startTime + 86400;
|
||||||
|
|
||||||
|
return (int)OnlineModel::count([
|
||||||
|
'conditions' => 'active_time BETWEEN :start_time: AND :end_time:',
|
||||||
|
'bind' => ['start_time' => $startTime, 'end_time' => $endTime],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function countDailySales($date)
|
||||||
|
{
|
||||||
|
$sql = "SELECT count(*) AS total_count FROM %s AS os JOIN %s AS o ON os.order_id = o.id ";
|
||||||
|
|
||||||
|
$sql .= "WHERE os.status = ?1 AND o.create_time BETWEEN ?2 AND ?3";
|
||||||
|
|
||||||
|
$phql = sprintf($sql, OrderStatusModel::class, OrderModel::class);
|
||||||
|
|
||||||
|
$startTime = strtotime($date);
|
||||||
|
|
||||||
|
$endTime = $startTime + 86400;
|
||||||
|
|
||||||
|
$result = $this->modelsManager->executeQuery($phql, [
|
||||||
|
1 => OrderModel::STATUS_FINISHED,
|
||||||
|
2 => $startTime,
|
||||||
|
3 => $endTime,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (float)$result[0]['total_count'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function countDailyRefunds($date)
|
||||||
|
{
|
||||||
|
$startTime = strtotime($date);
|
||||||
|
|
||||||
|
$endTime = $startTime + 86400;
|
||||||
|
|
||||||
|
return (int)RefundModel::count([
|
||||||
|
'conditions' => 'status = ?1 AND create_time BETWEEN ?2 AND ?3',
|
||||||
|
'bind' => [
|
||||||
|
1 => RefundModel::STATUS_FINISHED,
|
||||||
|
2 => $startTime,
|
||||||
|
3 => $endTime,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sumDailySales($date)
|
||||||
|
{
|
||||||
|
$sql = "SELECT sum(o.amount) AS total_amount FROM %s AS os JOIN %s AS o ON os.order_id = o.id ";
|
||||||
|
|
||||||
|
$sql .= "WHERE os.status = ?1 AND o.create_time BETWEEN ?2 AND ?3";
|
||||||
|
|
||||||
|
$phql = sprintf($sql, OrderStatusModel::class, OrderModel::class);
|
||||||
|
|
||||||
|
$startTime = strtotime($date);
|
||||||
|
|
||||||
|
$endTime = $startTime + 86400;
|
||||||
|
|
||||||
|
$result = $this->modelsManager->executeQuery($phql, [
|
||||||
|
1 => OrderModel::STATUS_FINISHED,
|
||||||
|
2 => $startTime,
|
||||||
|
3 => $endTime,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (float)$result[0]['total_amount'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sumDailyRefunds($date)
|
||||||
|
{
|
||||||
|
$startTime = strtotime($date);
|
||||||
|
|
||||||
|
$endTime = $startTime + 86400;
|
||||||
|
|
||||||
|
return (float)RefundModel::sum([
|
||||||
|
'column' => 'amount',
|
||||||
|
'conditions' => 'status = ?1 AND create_time BETWEEN ?2 AND ?3',
|
||||||
|
'bind' => [
|
||||||
|
1 => RefundModel::STATUS_FINISHED,
|
||||||
|
2 => $startTime,
|
||||||
|
3 => $endTime,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $type
|
||||||
|
* @param int $year
|
||||||
|
* @param int $month
|
||||||
|
* @return ResultsetInterface|Resultset|OrderModel[]
|
||||||
|
*/
|
||||||
|
public function findMonthlyOrders($type, $year, $month)
|
||||||
|
{
|
||||||
|
$startTime = strtotime("{$year}-{$month}");
|
||||||
|
|
||||||
|
$endTime = strtotime('+1 month', $startTime);
|
||||||
|
|
||||||
|
$status = OrderModel::STATUS_FINISHED;
|
||||||
|
|
||||||
|
return $this->modelsManager->createBuilder()
|
||||||
|
->addFrom(OrderStatusModel::class, 'os')
|
||||||
|
->join(OrderModel::class, 'os.order_id = o.id', 'o')
|
||||||
|
->columns('o.*')
|
||||||
|
->where('o.item_type = :type:', ['type' => $type])
|
||||||
|
->andWhere('os.status = :status:', ['status' => $status])
|
||||||
|
->betweenWhere('o.create_time', $startTime, $endTime)
|
||||||
|
->getQuery()->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -6,7 +6,8 @@ use App\Models\User as UserModel;
|
|||||||
use App\Repos\User as UserRepo;
|
use App\Repos\User as UserRepo;
|
||||||
use App\Services\Auth as AuthService;
|
use App\Services\Auth as AuthService;
|
||||||
use App\Validators\Validator as AppValidator;
|
use App\Validators\Validator as AppValidator;
|
||||||
use Phalcon\Di;
|
use Phalcon\Di as Di;
|
||||||
|
use Phalcon\Events\Manager as EventsManager;
|
||||||
|
|
||||||
trait Auth
|
trait Auth
|
||||||
{
|
{
|
||||||
@ -24,7 +25,16 @@ trait Auth
|
|||||||
|
|
||||||
$userRepo = new UserRepo();
|
$userRepo = new UserRepo();
|
||||||
|
|
||||||
return $userRepo->findById($authUser['id']);
|
$user = $userRepo->findById($authUser['id']);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var EventsManager $eventsManager
|
||||||
|
*/
|
||||||
|
$eventsManager = Di::getDefault()->getShared('eventsManager');
|
||||||
|
|
||||||
|
$eventsManager->fire('user:online', $this, $user);
|
||||||
|
|
||||||
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,13 +50,7 @@ trait Auth
|
|||||||
|
|
||||||
$userRepo = new UserRepo();
|
$userRepo = new UserRepo();
|
||||||
|
|
||||||
$user = $userRepo->findById($authUser['id']);
|
return $userRepo->findById($authUser['id']);
|
||||||
|
|
||||||
if (time() - $user->active_time > 600) {
|
|
||||||
$user->update(['active_time' => time()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $user;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Listeners\Pay;
|
use App\Listeners\Pay;
|
||||||
|
use App\Listeners\User;
|
||||||
use App\Listeners\UserDailyCounter;
|
use App\Listeners\UserDailyCounter;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'pay' => Pay::class,
|
'pay' => Pay::class,
|
||||||
|
'user' => User::class,
|
||||||
'userDailyCounter' => UserDailyCounter::class,
|
'userDailyCounter' => UserDailyCounter::class,
|
||||||
];
|
];
|
@ -2517,7 +2517,7 @@ class InitTable extends Phinx\Migration\AbstractMigration
|
|||||||
->addColumn('client_ip', 'string', [
|
->addColumn('client_ip', 'string', [
|
||||||
'null' => false,
|
'null' => false,
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'limit' => 30,
|
'limit' => 64,
|
||||||
'collation' => 'utf8mb4_general_ci',
|
'collation' => 'utf8mb4_general_ci',
|
||||||
'encoding' => 'utf8mb4',
|
'encoding' => 'utf8mb4',
|
||||||
'comment' => '终端IP',
|
'comment' => '终端IP',
|
||||||
|
107
db/migrations/20201004095647_create_online_table.php
Normal file
107
db/migrations/20201004095647_create_online_table.php
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Phinx\Db\Adapter\MysqlAdapter;
|
||||||
|
|
||||||
|
class CreateOnlineTable extends Phinx\Migration\AbstractMigration
|
||||||
|
{
|
||||||
|
public function change()
|
||||||
|
{
|
||||||
|
$this->table('kg_online', [
|
||||||
|
'id' => false,
|
||||||
|
'primary_key' => ['id'],
|
||||||
|
'engine' => 'InnoDB',
|
||||||
|
'encoding' => 'utf8mb4',
|
||||||
|
'collation' => 'utf8mb4_general_ci',
|
||||||
|
'comment' => '',
|
||||||
|
'row_format' => 'DYNAMIC',
|
||||||
|
])
|
||||||
|
->addColumn('id', 'integer', [
|
||||||
|
'null' => false,
|
||||||
|
'limit' => MysqlAdapter::INT_REGULAR,
|
||||||
|
'identity' => 'enable',
|
||||||
|
'comment' => '主键编号',
|
||||||
|
])
|
||||||
|
->addColumn('user_id', 'integer', [
|
||||||
|
'null' => false,
|
||||||
|
'default' => '0',
|
||||||
|
'limit' => MysqlAdapter::INT_REGULAR,
|
||||||
|
'comment' => '用户编号',
|
||||||
|
'after' => 'id',
|
||||||
|
])
|
||||||
|
->addColumn('client_type', 'integer', [
|
||||||
|
'null' => false,
|
||||||
|
'default' => '1',
|
||||||
|
'limit' => MysqlAdapter::INT_REGULAR,
|
||||||
|
'comment' => '终端类型',
|
||||||
|
'after' => 'user_id',
|
||||||
|
])
|
||||||
|
->addColumn('client_ip', 'string', [
|
||||||
|
'null' => false,
|
||||||
|
'default' => '',
|
||||||
|
'limit' => 64,
|
||||||
|
'collation' => 'utf8mb4_general_ci',
|
||||||
|
'encoding' => 'utf8mb4',
|
||||||
|
'comment' => '终端IP',
|
||||||
|
'after' => 'client_type',
|
||||||
|
])
|
||||||
|
->addColumn('active_time', 'integer', [
|
||||||
|
'null' => false,
|
||||||
|
'default' => '0',
|
||||||
|
'limit' => MysqlAdapter::INT_REGULAR,
|
||||||
|
'comment' => '活跃时间',
|
||||||
|
'after' => 'client_ip',
|
||||||
|
])
|
||||||
|
->addColumn('create_time', 'integer', [
|
||||||
|
'null' => false,
|
||||||
|
'default' => '0',
|
||||||
|
'limit' => MysqlAdapter::INT_REGULAR,
|
||||||
|
'comment' => '创建时间',
|
||||||
|
'after' => 'active_time',
|
||||||
|
])
|
||||||
|
->addColumn('update_time', 'integer', [
|
||||||
|
'null' => false,
|
||||||
|
'default' => '0',
|
||||||
|
'limit' => MysqlAdapter::INT_REGULAR,
|
||||||
|
'comment' => '更新时间',
|
||||||
|
'after' => 'create_time',
|
||||||
|
])
|
||||||
|
->addIndex(['active_time'], [
|
||||||
|
'name' => 'active_time',
|
||||||
|
'unique' => false,
|
||||||
|
])
|
||||||
|
->addIndex(['user_id'], [
|
||||||
|
'name' => 'user_id',
|
||||||
|
'unique' => false,
|
||||||
|
])
|
||||||
|
->create();
|
||||||
|
$this->table('kg_task', [
|
||||||
|
'id' => false,
|
||||||
|
'primary_key' => ['id'],
|
||||||
|
'engine' => 'InnoDB',
|
||||||
|
'encoding' => 'utf8mb4',
|
||||||
|
'collation' => 'utf8mb4_general_ci',
|
||||||
|
'comment' => '',
|
||||||
|
'row_format' => 'DYNAMIC',
|
||||||
|
])
|
||||||
|
->save();
|
||||||
|
$this->table('kg_trade', [
|
||||||
|
'id' => false,
|
||||||
|
'primary_key' => ['id'],
|
||||||
|
'engine' => 'InnoDB',
|
||||||
|
'encoding' => 'utf8mb4',
|
||||||
|
'collation' => 'utf8mb4_general_ci',
|
||||||
|
'comment' => '',
|
||||||
|
'row_format' => 'DYNAMIC',
|
||||||
|
])
|
||||||
|
->changeColumn('channel_sn', 'string', [
|
||||||
|
'null' => false,
|
||||||
|
'default' => '',
|
||||||
|
'limit' => 64,
|
||||||
|
'collation' => 'utf8mb4_general_ci',
|
||||||
|
'encoding' => 'utf8mb4',
|
||||||
|
'comment' => '平台序号',
|
||||||
|
'after' => 'channel',
|
||||||
|
])
|
||||||
|
->save();
|
||||||
|
}
|
||||||
|
}
|
@ -8822,14 +8822,14 @@ return array(
|
|||||||
'COLUMN_DEFAULT' => '',
|
'COLUMN_DEFAULT' => '',
|
||||||
'IS_NULLABLE' => 'NO',
|
'IS_NULLABLE' => 'NO',
|
||||||
'DATA_TYPE' => 'varchar',
|
'DATA_TYPE' => 'varchar',
|
||||||
'CHARACTER_MAXIMUM_LENGTH' => '30',
|
'CHARACTER_MAXIMUM_LENGTH' => '64',
|
||||||
'CHARACTER_OCTET_LENGTH' => '120',
|
'CHARACTER_OCTET_LENGTH' => '256',
|
||||||
'NUMERIC_PRECISION' => NULL,
|
'NUMERIC_PRECISION' => NULL,
|
||||||
'NUMERIC_SCALE' => NULL,
|
'NUMERIC_SCALE' => NULL,
|
||||||
'DATETIME_PRECISION' => NULL,
|
'DATETIME_PRECISION' => NULL,
|
||||||
'CHARACTER_SET_NAME' => 'utf8mb4',
|
'CHARACTER_SET_NAME' => 'utf8mb4',
|
||||||
'COLLATION_NAME' => 'utf8mb4_general_ci',
|
'COLLATION_NAME' => 'utf8mb4_general_ci',
|
||||||
'COLUMN_TYPE' => 'varchar(30)',
|
'COLUMN_TYPE' => 'varchar(64)',
|
||||||
'COLUMN_KEY' => '',
|
'COLUMN_KEY' => '',
|
||||||
'EXTRA' => '',
|
'EXTRA' => '',
|
||||||
'PRIVILEGES' => 'select,insert,update,references',
|
'PRIVILEGES' => 'select,insert,update,references',
|
||||||
@ -9514,6 +9514,247 @@ return array(
|
|||||||
),
|
),
|
||||||
'foreign_keys' => NULL,
|
'foreign_keys' => NULL,
|
||||||
),
|
),
|
||||||
|
'kg_online' =>
|
||||||
|
array(
|
||||||
|
'table' =>
|
||||||
|
array(
|
||||||
|
'table_name' => 'kg_online',
|
||||||
|
'engine' => 'InnoDB',
|
||||||
|
'table_comment' => '',
|
||||||
|
'table_collation' => 'utf8mb4_general_ci',
|
||||||
|
'character_set_name' => 'utf8mb4',
|
||||||
|
'row_format' => 'Dynamic',
|
||||||
|
),
|
||||||
|
'columns' =>
|
||||||
|
array(
|
||||||
|
'id' =>
|
||||||
|
array(
|
||||||
|
'TABLE_CATALOG' => 'def',
|
||||||
|
'TABLE_NAME' => 'kg_online',
|
||||||
|
'COLUMN_NAME' => 'id',
|
||||||
|
'ORDINAL_POSITION' => '1',
|
||||||
|
'COLUMN_DEFAULT' => NULL,
|
||||||
|
'IS_NULLABLE' => 'NO',
|
||||||
|
'DATA_TYPE' => 'int',
|
||||||
|
'CHARACTER_MAXIMUM_LENGTH' => NULL,
|
||||||
|
'CHARACTER_OCTET_LENGTH' => NULL,
|
||||||
|
'NUMERIC_PRECISION' => '10',
|
||||||
|
'NUMERIC_SCALE' => '0',
|
||||||
|
'DATETIME_PRECISION' => NULL,
|
||||||
|
'CHARACTER_SET_NAME' => NULL,
|
||||||
|
'COLLATION_NAME' => NULL,
|
||||||
|
'COLUMN_TYPE' => 'int',
|
||||||
|
'COLUMN_KEY' => 'PRI',
|
||||||
|
'EXTRA' => 'auto_increment',
|
||||||
|
'PRIVILEGES' => 'select,insert,update,references',
|
||||||
|
'COLUMN_COMMENT' => '主键编号',
|
||||||
|
'GENERATION_EXPRESSION' => '',
|
||||||
|
'SRS_ID' => NULL,
|
||||||
|
),
|
||||||
|
'user_id' =>
|
||||||
|
array(
|
||||||
|
'TABLE_CATALOG' => 'def',
|
||||||
|
'TABLE_NAME' => 'kg_online',
|
||||||
|
'COLUMN_NAME' => 'user_id',
|
||||||
|
'ORDINAL_POSITION' => '2',
|
||||||
|
'COLUMN_DEFAULT' => '0',
|
||||||
|
'IS_NULLABLE' => 'NO',
|
||||||
|
'DATA_TYPE' => 'int',
|
||||||
|
'CHARACTER_MAXIMUM_LENGTH' => NULL,
|
||||||
|
'CHARACTER_OCTET_LENGTH' => NULL,
|
||||||
|
'NUMERIC_PRECISION' => '10',
|
||||||
|
'NUMERIC_SCALE' => '0',
|
||||||
|
'DATETIME_PRECISION' => NULL,
|
||||||
|
'CHARACTER_SET_NAME' => NULL,
|
||||||
|
'COLLATION_NAME' => NULL,
|
||||||
|
'COLUMN_TYPE' => 'int unsigned',
|
||||||
|
'COLUMN_KEY' => 'MUL',
|
||||||
|
'EXTRA' => '',
|
||||||
|
'PRIVILEGES' => 'select,insert,update,references',
|
||||||
|
'COLUMN_COMMENT' => '用户编号',
|
||||||
|
'GENERATION_EXPRESSION' => '',
|
||||||
|
'SRS_ID' => NULL,
|
||||||
|
),
|
||||||
|
'client_type' =>
|
||||||
|
array(
|
||||||
|
'TABLE_CATALOG' => 'def',
|
||||||
|
'TABLE_NAME' => 'kg_online',
|
||||||
|
'COLUMN_NAME' => 'client_type',
|
||||||
|
'ORDINAL_POSITION' => '3',
|
||||||
|
'COLUMN_DEFAULT' => '1',
|
||||||
|
'IS_NULLABLE' => 'NO',
|
||||||
|
'DATA_TYPE' => 'int',
|
||||||
|
'CHARACTER_MAXIMUM_LENGTH' => NULL,
|
||||||
|
'CHARACTER_OCTET_LENGTH' => NULL,
|
||||||
|
'NUMERIC_PRECISION' => '10',
|
||||||
|
'NUMERIC_SCALE' => '0',
|
||||||
|
'DATETIME_PRECISION' => NULL,
|
||||||
|
'CHARACTER_SET_NAME' => NULL,
|
||||||
|
'COLLATION_NAME' => NULL,
|
||||||
|
'COLUMN_TYPE' => 'int unsigned',
|
||||||
|
'COLUMN_KEY' => '',
|
||||||
|
'EXTRA' => '',
|
||||||
|
'PRIVILEGES' => 'select,insert,update,references',
|
||||||
|
'COLUMN_COMMENT' => '终端类型',
|
||||||
|
'GENERATION_EXPRESSION' => '',
|
||||||
|
'SRS_ID' => NULL,
|
||||||
|
),
|
||||||
|
'client_ip' =>
|
||||||
|
array(
|
||||||
|
'TABLE_CATALOG' => 'def',
|
||||||
|
'TABLE_NAME' => 'kg_online',
|
||||||
|
'COLUMN_NAME' => 'client_ip',
|
||||||
|
'ORDINAL_POSITION' => '4',
|
||||||
|
'COLUMN_DEFAULT' => '',
|
||||||
|
'IS_NULLABLE' => 'NO',
|
||||||
|
'DATA_TYPE' => 'varchar',
|
||||||
|
'CHARACTER_MAXIMUM_LENGTH' => '64',
|
||||||
|
'CHARACTER_OCTET_LENGTH' => '256',
|
||||||
|
'NUMERIC_PRECISION' => NULL,
|
||||||
|
'NUMERIC_SCALE' => NULL,
|
||||||
|
'DATETIME_PRECISION' => NULL,
|
||||||
|
'CHARACTER_SET_NAME' => 'utf8mb4',
|
||||||
|
'COLLATION_NAME' => 'utf8mb4_general_ci',
|
||||||
|
'COLUMN_TYPE' => 'varchar(64)',
|
||||||
|
'COLUMN_KEY' => '',
|
||||||
|
'EXTRA' => '',
|
||||||
|
'PRIVILEGES' => 'select,insert,update,references',
|
||||||
|
'COLUMN_COMMENT' => '终端IP',
|
||||||
|
'GENERATION_EXPRESSION' => '',
|
||||||
|
'SRS_ID' => NULL,
|
||||||
|
),
|
||||||
|
'active_time' =>
|
||||||
|
array(
|
||||||
|
'TABLE_CATALOG' => 'def',
|
||||||
|
'TABLE_NAME' => 'kg_online',
|
||||||
|
'COLUMN_NAME' => 'active_time',
|
||||||
|
'ORDINAL_POSITION' => '5',
|
||||||
|
'COLUMN_DEFAULT' => '0',
|
||||||
|
'IS_NULLABLE' => 'NO',
|
||||||
|
'DATA_TYPE' => 'int',
|
||||||
|
'CHARACTER_MAXIMUM_LENGTH' => NULL,
|
||||||
|
'CHARACTER_OCTET_LENGTH' => NULL,
|
||||||
|
'NUMERIC_PRECISION' => '10',
|
||||||
|
'NUMERIC_SCALE' => '0',
|
||||||
|
'DATETIME_PRECISION' => NULL,
|
||||||
|
'CHARACTER_SET_NAME' => NULL,
|
||||||
|
'COLLATION_NAME' => NULL,
|
||||||
|
'COLUMN_TYPE' => 'int unsigned',
|
||||||
|
'COLUMN_KEY' => 'MUL',
|
||||||
|
'EXTRA' => '',
|
||||||
|
'PRIVILEGES' => 'select,insert,update,references',
|
||||||
|
'COLUMN_COMMENT' => '活跃时间',
|
||||||
|
'GENERATION_EXPRESSION' => '',
|
||||||
|
'SRS_ID' => NULL,
|
||||||
|
),
|
||||||
|
'create_time' =>
|
||||||
|
array(
|
||||||
|
'TABLE_CATALOG' => 'def',
|
||||||
|
'TABLE_NAME' => 'kg_online',
|
||||||
|
'COLUMN_NAME' => 'create_time',
|
||||||
|
'ORDINAL_POSITION' => '6',
|
||||||
|
'COLUMN_DEFAULT' => '0',
|
||||||
|
'IS_NULLABLE' => 'NO',
|
||||||
|
'DATA_TYPE' => 'int',
|
||||||
|
'CHARACTER_MAXIMUM_LENGTH' => NULL,
|
||||||
|
'CHARACTER_OCTET_LENGTH' => NULL,
|
||||||
|
'NUMERIC_PRECISION' => '10',
|
||||||
|
'NUMERIC_SCALE' => '0',
|
||||||
|
'DATETIME_PRECISION' => NULL,
|
||||||
|
'CHARACTER_SET_NAME' => NULL,
|
||||||
|
'COLLATION_NAME' => NULL,
|
||||||
|
'COLUMN_TYPE' => 'int unsigned',
|
||||||
|
'COLUMN_KEY' => '',
|
||||||
|
'EXTRA' => '',
|
||||||
|
'PRIVILEGES' => 'select,insert,update,references',
|
||||||
|
'COLUMN_COMMENT' => '创建时间',
|
||||||
|
'GENERATION_EXPRESSION' => '',
|
||||||
|
'SRS_ID' => NULL,
|
||||||
|
),
|
||||||
|
'update_time' =>
|
||||||
|
array(
|
||||||
|
'TABLE_CATALOG' => 'def',
|
||||||
|
'TABLE_NAME' => 'kg_online',
|
||||||
|
'COLUMN_NAME' => 'update_time',
|
||||||
|
'ORDINAL_POSITION' => '7',
|
||||||
|
'COLUMN_DEFAULT' => '0',
|
||||||
|
'IS_NULLABLE' => 'NO',
|
||||||
|
'DATA_TYPE' => 'int',
|
||||||
|
'CHARACTER_MAXIMUM_LENGTH' => NULL,
|
||||||
|
'CHARACTER_OCTET_LENGTH' => NULL,
|
||||||
|
'NUMERIC_PRECISION' => '10',
|
||||||
|
'NUMERIC_SCALE' => '0',
|
||||||
|
'DATETIME_PRECISION' => NULL,
|
||||||
|
'CHARACTER_SET_NAME' => NULL,
|
||||||
|
'COLLATION_NAME' => NULL,
|
||||||
|
'COLUMN_TYPE' => 'int unsigned',
|
||||||
|
'COLUMN_KEY' => '',
|
||||||
|
'EXTRA' => '',
|
||||||
|
'PRIVILEGES' => 'select,insert,update,references',
|
||||||
|
'COLUMN_COMMENT' => '更新时间',
|
||||||
|
'GENERATION_EXPRESSION' => '',
|
||||||
|
'SRS_ID' => NULL,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'indexes' =>
|
||||||
|
array(
|
||||||
|
'active_time' =>
|
||||||
|
array(
|
||||||
|
1 =>
|
||||||
|
array(
|
||||||
|
'Table' => 'kg_online',
|
||||||
|
'Non_unique' => '1',
|
||||||
|
'Key_name' => 'active_time',
|
||||||
|
'Seq_in_index' => '1',
|
||||||
|
'Column_name' => 'active_time',
|
||||||
|
'Collation' => 'A',
|
||||||
|
'Sub_part' => NULL,
|
||||||
|
'Packed' => NULL,
|
||||||
|
'Null' => '',
|
||||||
|
'Index_type' => 'BTREE',
|
||||||
|
'Comment' => '',
|
||||||
|
'Index_comment' => '',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'PRIMARY' =>
|
||||||
|
array(
|
||||||
|
1 =>
|
||||||
|
array(
|
||||||
|
'Table' => 'kg_online',
|
||||||
|
'Non_unique' => '0',
|
||||||
|
'Key_name' => 'PRIMARY',
|
||||||
|
'Seq_in_index' => '1',
|
||||||
|
'Column_name' => 'id',
|
||||||
|
'Collation' => 'A',
|
||||||
|
'Sub_part' => NULL,
|
||||||
|
'Packed' => NULL,
|
||||||
|
'Null' => '',
|
||||||
|
'Index_type' => 'BTREE',
|
||||||
|
'Comment' => '',
|
||||||
|
'Index_comment' => '',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'user_id' =>
|
||||||
|
array(
|
||||||
|
1 =>
|
||||||
|
array(
|
||||||
|
'Table' => 'kg_online',
|
||||||
|
'Non_unique' => '1',
|
||||||
|
'Key_name' => 'user_id',
|
||||||
|
'Seq_in_index' => '1',
|
||||||
|
'Column_name' => 'user_id',
|
||||||
|
'Collation' => 'A',
|
||||||
|
'Sub_part' => NULL,
|
||||||
|
'Packed' => NULL,
|
||||||
|
'Null' => '',
|
||||||
|
'Index_type' => 'BTREE',
|
||||||
|
'Comment' => '',
|
||||||
|
'Index_comment' => '',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'foreign_keys' => NULL,
|
||||||
|
),
|
||||||
'kg_order' =>
|
'kg_order' =>
|
||||||
array(
|
array(
|
||||||
'table' =>
|
'table' =>
|
||||||
@ -9752,14 +9993,14 @@ return array(
|
|||||||
'COLUMN_DEFAULT' => '',
|
'COLUMN_DEFAULT' => '',
|
||||||
'IS_NULLABLE' => 'NO',
|
'IS_NULLABLE' => 'NO',
|
||||||
'DATA_TYPE' => 'varchar',
|
'DATA_TYPE' => 'varchar',
|
||||||
'CHARACTER_MAXIMUM_LENGTH' => '30',
|
'CHARACTER_MAXIMUM_LENGTH' => '64',
|
||||||
'CHARACTER_OCTET_LENGTH' => '120',
|
'CHARACTER_OCTET_LENGTH' => '256',
|
||||||
'NUMERIC_PRECISION' => NULL,
|
'NUMERIC_PRECISION' => NULL,
|
||||||
'NUMERIC_SCALE' => NULL,
|
'NUMERIC_SCALE' => NULL,
|
||||||
'DATETIME_PRECISION' => NULL,
|
'DATETIME_PRECISION' => NULL,
|
||||||
'CHARACTER_SET_NAME' => 'utf8mb4',
|
'CHARACTER_SET_NAME' => 'utf8mb4',
|
||||||
'COLLATION_NAME' => 'utf8mb4_general_ci',
|
'COLLATION_NAME' => 'utf8mb4_general_ci',
|
||||||
'COLUMN_TYPE' => 'varchar(30)',
|
'COLUMN_TYPE' => 'varchar(64)',
|
||||||
'COLUMN_KEY' => '',
|
'COLUMN_KEY' => '',
|
||||||
'EXTRA' => '',
|
'EXTRA' => '',
|
||||||
'PRIVILEGES' => 'select,insert,update,references',
|
'PRIVILEGES' => 'select,insert,update,references',
|
||||||
@ -12811,7 +13052,7 @@ return array(
|
|||||||
'CHARACTER_SET_NAME' => NULL,
|
'CHARACTER_SET_NAME' => NULL,
|
||||||
'COLLATION_NAME' => NULL,
|
'COLLATION_NAME' => NULL,
|
||||||
'COLUMN_TYPE' => 'int',
|
'COLUMN_TYPE' => 'int',
|
||||||
'COLUMN_KEY' => 'MUL',
|
'COLUMN_KEY' => '',
|
||||||
'EXTRA' => '',
|
'EXTRA' => '',
|
||||||
'PRIVILEGES' => 'select,insert,update,references',
|
'PRIVILEGES' => 'select,insert,update,references',
|
||||||
'COLUMN_COMMENT' => '',
|
'COLUMN_COMMENT' => '',
|
||||||
@ -13429,14 +13670,14 @@ return array(
|
|||||||
'COLUMN_DEFAULT' => '',
|
'COLUMN_DEFAULT' => '',
|
||||||
'IS_NULLABLE' => 'NO',
|
'IS_NULLABLE' => 'NO',
|
||||||
'DATA_TYPE' => 'varchar',
|
'DATA_TYPE' => 'varchar',
|
||||||
'CHARACTER_MAXIMUM_LENGTH' => '32',
|
'CHARACTER_MAXIMUM_LENGTH' => '64',
|
||||||
'CHARACTER_OCTET_LENGTH' => '128',
|
'CHARACTER_OCTET_LENGTH' => '256',
|
||||||
'NUMERIC_PRECISION' => NULL,
|
'NUMERIC_PRECISION' => NULL,
|
||||||
'NUMERIC_SCALE' => NULL,
|
'NUMERIC_SCALE' => NULL,
|
||||||
'DATETIME_PRECISION' => NULL,
|
'DATETIME_PRECISION' => NULL,
|
||||||
'CHARACTER_SET_NAME' => 'utf8mb4',
|
'CHARACTER_SET_NAME' => 'utf8mb4',
|
||||||
'COLLATION_NAME' => 'utf8mb4_general_ci',
|
'COLLATION_NAME' => 'utf8mb4_general_ci',
|
||||||
'COLUMN_TYPE' => 'varchar(32)',
|
'COLUMN_TYPE' => 'varchar(64)',
|
||||||
'COLUMN_KEY' => '',
|
'COLUMN_KEY' => '',
|
||||||
'EXTRA' => '',
|
'EXTRA' => '',
|
||||||
'PRIVILEGES' => 'select,insert,update,references',
|
'PRIVILEGES' => 'select,insert,update,references',
|
||||||
|
@ -258,3 +258,20 @@ img.kg-qrcode {
|
|||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
color: rgb(0, 150, 136);
|
color: rgb(0, 150, 136);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.kg-search-form {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-search-form .layui-form-label {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-search-form .layui-input-inline:last-child {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-chart {
|
||||||
|
width: 100%;
|
||||||
|
height: 480px;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user