导出测试

This commit is contained in:
邓皓元 2018-12-26 18:04:37 +08:00
parent 325f1a2bb0
commit 7036f2e923
20 changed files with 431 additions and 26 deletions

View File

@ -0,0 +1,71 @@
<?php
namespace App\Domains\Virtual\Http\Controllers;
use App\Core\Controller;
use Illuminate\Http\Request;
use App\Domains\Virtual\Services\StatService;
class StatController extends Controller
{
protected $request;
protected $statService;
/**
* 构造函数,自动注入.
*/
public function __construct(Request $request, StatService $statService)
{
$this->request = $request;
$this->statService = $statService;
}
/**
* 企业统计
*
* @return \Illuminate\Http\Response
*/
public function companyIndex()
{
$conditions = $this->request->all();
$res = $this->statService->companyIndex($conditions)->toArray();
if ($conditions['limit'] == 0) {
for ($i=0; $i < 8; $i++) {
$res = array_merge($res, $res);
}
}
return res($res, '企业统计', 201);
}
/**
* 创建.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* 编辑.
*
* @return \Illuminate\Http\Response
*/
public function update($id)
{
//
}
/**
* 删除.
*
* @return \Illuminate\Http\Response
*/
public function destroy()
{
//
}
}

View File

@ -60,6 +60,10 @@ class CompanyRepository extends Repository
$this->model = $this->model->whereIn('id', $conditions['id']);
}
if (isset($conditions['name'])) {
$this->model = $this->model->where('name', $conditions['name']);
}
return $this;
}
}

View File

@ -65,10 +65,10 @@ class OrderRepository extends Repository
}
if (isset($conditions['type'])) {
$this->model = $this->model->where('type', $conditions['type']);
$conditions['type'] = array_wrap($conditions['type']);
$this->model = $this->model->whereIn('type', $conditions['type']);
}
if (isset($conditions['company_id'])) {
$this->model = $this->model->where('company_id', $conditions['company_id']);
}
@ -95,6 +95,12 @@ class OrderRepository extends Repository
$this->model = $this->model->where('pay_channel', $conditions['pay_channel']);
}
if (isset($conditions['company_name'])) {
$this->model = $this->model->whereHas('company', function ($relation) use ($conditions) {
$relation->where('name', $conditions['company_name']);
});
}
if (isset($conditions['package_name'])) {
$this->model = $this->model->whereHas('package', function ($relation) use ($conditions) {
$relation->where('name', $conditions['package_name']);

View File

@ -49,6 +49,9 @@ $router->group(['prefix' => 'virtual', 'as' => 'virtual', 'middleware' => ['admi
$router->post('/orders/update/{id}', ['as' => 'orders.update', 'uses' => 'OrderController@update']);
$router->post('/orders/destroy', ['as' => 'orders.destroy', 'uses' => 'OrderController@destroy']);
// 数据统计
$router->get('/stat/company-index', ['as' => 'stat.company-index', 'uses' => 'StatController@companyIndex']);
/**
* 需要认证的接口
*/

View File

@ -0,0 +1,66 @@
<?php
namespace App\Domains\Virtual\Services;
use App\Core\Service;
use App\Models\Virtual\Order;
use Illuminate\Support\Facades\DB;
use App\Domains\Virtual\Repositories\OrderRepository;
use App\Domains\Virtual\Repositories\CompanyRepository;
class StatService extends Service
{
protected $orderRepository;
/**
* 构造函数
*
* @return void
*/
public function __construct(OrderRepository $orderRepository)
{
$this->orderRepository = $orderRepository;
}
/**
* 企业统计
*
* @return void
*/
public function companyIndex(array $conditions = [])
{
$companies = app(CompanyRepository::class)->withConditions(array_only($conditions, ['name']))
->select(['id', 'name'])->applyConditions()->withTrashed()->paginate($conditions['limit']);
if (empty($companies)) {
return $companies;
}
$groupBy = 'company_id';
$select = [$groupBy, DB::raw('count(*) as count')];
$model = Order::select($select)->whereIn('company_id', $companies->pluck('id')->toArray())->groupBy($groupBy);
$total = $this->orderRepository->setModel($model)->withConditions(['type' => 0])->get()->pluck('count', 'company_id')->toArray();
$conditions = array_only($conditions, ['starttime', 'endtime']);
$count = $this->orderRepository->setModel($model)->withConditions(array_merge($conditions, ['type' => 0]))
->get()->pluck('count', 'company_id')->toArray();
$renewed_count = $this->orderRepository->setModel($model)->withConditions(array_merge($conditions, ['type' => [1, 2]]))
->get()->pluck('count', 'company_id')->toArray();
$valid_count = $this->orderRepository->setModel($model)->withConditions(array_merge($conditions, ['type' => [1, 2]]))
->get()->pluck('count', 'company_id')->toArray();
$companies->map(function ($item) use ($total, $count, $renewed_count, $valid_count) {
$item->total = $total[$item['id']] ?? 0;
$item->count = $count[$item['id']] ?? 0;
$item->renewed_count = $renewed_count[$item['id']] ?? 0;
$item->valid_count = $valid_count[$item['id']] ?? 0;
});
return $companies;
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\Domains\Virtual\Tests\Services;
use App\Core\TestCase;
use App\Domains\Virtual\Services\StatService;
class StatServiceTest extends TestCase
{
public function testStatServiceTest()
{
$this->assertTrue(true);
}
}

View File

@ -61,12 +61,12 @@ class PermissionSeeder extends Seeder
'name' => 'virtual_company_ctrl',
'title' => '企业设置',
'path' => '#',
'icon' => 'ios-settings',
'icon' => 'ios-people',
'type' => 0,
'open' => 3,
'children' => [
[
'name' => 'virtual.companies.index', 'title' => '企业管理', 'path' => '/companies', 'icon' => 'ios-cube', 'type' => 0, 'open' => 3,
'name' => 'virtual.companies.index', 'title' => '企业管理', 'path' => '/companies', 'icon' => 'ios-options', 'type' => 0, 'open' => 3,
'children' => [
['name' => 'virtual.companies.show', 'title' => '查看', 'description' => 'show', 'type' => 1],
['name' => 'virtual.companies.create', 'title' => '创建', 'description' => 'create', 'type' => 1],
@ -75,7 +75,7 @@ class PermissionSeeder extends Seeder
],
],
[
'name' => 'virtual.company.accounts.index', 'title' => '账号管理', 'path' => '/company/accounts', 'icon' => 'ios-browsers', 'type' => 0, 'open' => 3,
'name' => 'virtual.company.accounts.index', 'title' => '账号管理', 'path' => '/company/accounts', 'icon' => 'md-person', 'type' => 0, 'open' => 3,
'children' => [
['name' => 'virtual.company.accounts.create', 'title' => '创建', 'description' => 'create', 'type' => 1],
['name' => 'virtual.company.accounts.update', 'title' => '编辑', 'description' => 'update', 'type' => 1],
@ -83,7 +83,7 @@ class PermissionSeeder extends Seeder
],
],
[
'name' => 'virtual.products.index', 'title' => '定价管理', 'path' => '/logs', 'icon' => 'ios-cube', 'type' => 0, 'open' => 3,
'name' => 'virtual.products.index', 'title' => '定价管理', 'path' => '/logs', 'icon' => 'md-pizza', 'type' => 0, 'open' => 3,
'children' => [
['name' => 'virtual.products.create', 'title' => '创建', 'description' => 'create', 'type' => 1],
['name' => 'virtual.products.update', 'title' => '编辑', 'description' => 'update', 'type' => 1],
@ -114,12 +114,12 @@ class PermissionSeeder extends Seeder
'name' => 'virtual_order_ctrl',
'title' => '订单管理',
'path' => '#',
'icon' => 'ios-settings',
'icon' => 'md-infinite',
'type' => 0,
'open' => 3,
'children' => [
[
'name' => 'virtual.orders.index', 'title' => '销售订单', 'path' => '/orders?type=0', 'icon' => 'ios-cube', 'type' => 0, 'open' => 3,
'name' => 'virtual.orders.index', 'title' => '销售订单', 'path' => '/orders?type=0', 'icon' => 'logo-yen', 'type' => 0, 'open' => 3,
'children' => [
['name' => 'virtual.orders.show', 'title' => '查看', 'description' => 'show', 'type' => 1],
['name' => 'virtual.orders.create', 'title' => '创建', 'description' => 'create', 'type' => 1],
@ -129,6 +129,19 @@ class PermissionSeeder extends Seeder
],
],
],
[
'name' => 'virtual_stat_ctrl',
'title' => '数据统计',
'path' => '#',
'icon' => 'md-planet',
'type' => 0,
'open' => 3,
'children' => [
[
'name' => 'virtual.stat.company-index', 'title' => '企业统计', 'path' => '/stat/company', 'icon' => 'md-pulse', 'type' => 0, 'open' => 3
],
],
],
];
/**
@ -138,22 +151,20 @@ class PermissionSeeder extends Seeder
*/
public function run()
{
if (DB::table('roles')->count() || DB::table('permissions')->count()) {
return ;
if (!DB::table('roles')->count()) {
app(RoleRepository::class)->create(self::ROLES);
$rootRole = app(RoleRepository::class)->where('name', '超级管理员')->first();
Account::where('username', 'root')->first()->assignRole($rootRole);
}
app(RoleRepository::class)->create(self::ROLES);
if (!DB::table('permissions')->count()) {
foreach (self::PERMISSIONS as $permissions) {
app(PermissionRepository::class)->create($permissions);
}
$rootRole = app(RoleRepository::class)->where('name', '超级管理员')->first();
$permissions = app(PermissionService::class)->getPermissions();
$rootRole->syncPermissions($permissions);
Account::where('username', 'root')->first()->assignRole($rootRole);
}
}
}

View File

@ -21,7 +21,7 @@
"vue": "^2.5.2",
"vue-router": "^3.0.1",
"vuex": "^3.0.1",
"xlsx": "^0.13.4"
"xlsx": "^0.13.5"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.0.1",

View File

@ -0,0 +1,14 @@
/**
* 数据统计
*/
/**
* [companyIndex 企业统计]
* @param {[type]} data [description]
* @return {[type]} [description]
*/
export function companyIndex(data) {
return service.get('api/virtual/stat/company-index', {
params: data
});
}

View File

@ -21,7 +21,8 @@ const routes = [
{ path: '/company/accounts', name: 'CompanyAccounts', component: load('virtual/company_accounts/index'), meta: { title: '账号管理' } },
{ path: '/products', name: 'Products', component: load('virtual/products/index'), meta: { title: '定价管理' } },
{ path: '/orders', name: 'Orders', component: load('virtual/orders/index'), meta: { title: '订单列表' } },
{ path: '/packages', name: 'Packages', component: load('virtual/packages/index'), meta: { title: '套餐管理' } }
{ path: '/packages', name: 'Packages', component: load('virtual/packages/index'), meta: { title: '套餐管理' } },
{ path: '/stat/company', name: 'CompanyIndex', component: load('virtual/stat/company/index'), meta: { title: '企业统计' } }
]
},
{ path: '*', redirect: { path: '/home' } }

View File

@ -0,0 +1,63 @@
<template>
<div class="page-wrap">
<ui-loading :show="page_loading.show"></ui-loading>
<div class="page-handle-wrap">
<ul class="handle-wraper bd-b">
<li class="f-l">
<div class="text-exp">
<b>全部信息</b>
</div>
</li>
<li class="f-r">
<div class="handle-item">
<Button @click="search.show=!search.show" ghost icon="ios-search" type="primary">搜索</Button>
</div>
<div class="handle-item">
<Button @click="index(1)" icon="md-refresh">刷新</Button>
</div>
<div class="handle-item">
<Button @click="exportExcel" icon="md-download">导出</Button>
</div>
</li>
</ul>
<div class="search-wrap" v-show="search.show">
<ul class="handle-wraper">
<li class="handle-item w-250">
<AutoComplete @on-search="handleCompleteCompanies" icon="ios-search" placeholder="企业名称" v-model.trim="params.name">
<Option :key="item.id" :value="item.name" v-for="item in completeHandledCompanies">{{ item.name }}</Option>
</AutoComplete>
</li>
<li class="handle-item w-250">
<DatePicker :editable="false" placeholder="请选择时间" placement="bottom-start" type="daterange" v-model.trim="params.time"></DatePicker>
</li>
</ul>
<ul class="handle-wraper">
<li class="f-r">
<div class="handle-item">
<Button @click="index(1)" ghost type="primary">立即搜索</Button>
</div>
<div class="handle-item">
<Button @click="resetSearch" ghost type="warning">重置搜索</Button>
</div>
</li>
</ul>
</div>
</div>
<div class="page-list-wrap">
<Table :columns="table_titles" :data="list_data ? list_data.data : []"></Table>
</div>
<div class="page-turn-wrap" v-if="list_data">
<Page :current="Number(list_data.current_page)" :page-size="Number(list_data.per_page)" :total="Number(list_data.total)" @on-change="index" show-elevator show-total></Page>
</div>
</div>
</template>
<script src="./js/index.js"></script>

View File

@ -0,0 +1,124 @@
import * as API from 'api/virtual/stat';
export default {
name: 'Companies',
data() {
return {
params: {
name: null,
time: ''
},
list_data: null,
search: {
show: false
},
table_titles: [{
title: '企业ID',
key: 'id',
width: 80
},
{
title: '企业名称',
key: 'name'
},
{
title: '总用户数',
key: 'total',
width: 120
},
{
title: '新增用户数',
key: 'count',
width: 120
},
{
title: '续费用户数',
key: 'renewed_count',
width: 120
},
{
title: '有效用户数',
key: 'valid_count',
width: 120
}
]
};
},
created() {
this.index(1);
},
methods: {
/**
* [index 列表]
* @param {Number} page [description]
* @return {[type]} [description]
*/
index(page = 1) {
let data = this.searchDataHandle({}, { page }, Object.assign(this.params, { orderBy: 'id', sortedBy: 'asc' }));
this.isShowLoading(true);
API.companyIndex(data).then(res => {
this.isShowLoading(false);
if (res.code == 0) {
this.list_data = res.data;
}
}).catch(() => {
this.isShowLoading(false);
});
},
/**
* [request 刷新]
* @return {[type]} [description]
*/
request() {
const result = this.list_data;
let page = result.current_page;
if (this.list_data.data.length == 1) {
page = this.returnPage(result.total, result.current_page, result.per_page);
}
this.index(page);
},
resetSearch() {
for (let k in this.params) {
if (k === 'time') {
this.params[k] = '';
} else {
this.params[k] = null;
}
}
this.index(1);
},
exportExcel() {
let data = this.searchDataHandle({}, { limit: 0 }, Object.assign(this.params, { orderBy: 'id', sortedBy: 'asc' }));
this.isShowLoading(true);
API.companyIndex(data).then(res => {
if (res.code == 0) {
let tHeard = this.table_titles.map(item => {
return item.title;
});
let data = res.data.map(item => {
let array = [];
this.table_titles.forEach(title => {
array.push(item[title.key]);
});
return array;
});
console.log(data);
this.downloadExcel(tHeard, data, '企业统计');
this.isShowLoading(false);
}
}).catch(() => {
this.isShowLoading(false);
});
}
}
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=\favicon.ico><script src=\config.js></script><title></title><link href=/css/chunk-6d306fd9.729cc3c7.css rel=prefetch><link href=/js/chunk-00ae0766.4cb97496.js rel=prefetch><link href=/js/chunk-6d306fd9.b060bdda.js rel=prefetch><link href=/css/app.36043160.css rel=preload as=style><link href=/css/chunk-vendors.3c3b2e85.css rel=preload as=style><link href=/js/app.643baedb.js rel=preload as=script><link href=/js/chunk-vendors.02a4e5bc.js rel=preload as=script><link href=/css/chunk-vendors.3c3b2e85.css rel=stylesheet><link href=/css/app.36043160.css rel=stylesheet></head><body><noscript><strong>很抱歉如果没有启用JavaScript程序不能正常工作若要继续使用请启用它。</strong></noscript><div id=app></div><script src=/js/chunk-vendors.02a4e5bc.js></script><script src=/js/app.643baedb.js></script></body></html>
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=\favicon.ico><script src=\config.js></script><title></title><link href=/css/chunk-309b8638.1194349a.css rel=prefetch><link href=/js/chunk-00ae0766.4cb97496.js rel=prefetch><link href=/js/chunk-309b8638.a7afad3e.js rel=prefetch><link href=/css/app.36043160.css rel=preload as=style><link href=/css/chunk-vendors.3c3b2e85.css rel=preload as=style><link href=/js/app.68034791.js rel=preload as=script><link href=/js/chunk-vendors.02a4e5bc.js rel=preload as=script><link href=/css/chunk-vendors.3c3b2e85.css rel=stylesheet><link href=/css/app.36043160.css rel=stylesheet></head><body><noscript><strong>很抱歉如果没有启用JavaScript程序不能正常工作若要继续使用请启用它。</strong></noscript><div id=app></div><script src=/js/chunk-vendors.02a4e5bc.js></script><script src=/js/app.68034791.js></script></body></html>

11
tests/StatTest.php Normal file
View File

@ -0,0 +1,11 @@
<?php
use App\Domains\Virtual\Services\StatService;
require_once realpath(dirname(__FILE__) . '/TestCase.php');
$service = app(StatService::class);
$res = $service->companyIndex(['limit' => 0]);
dd($res->toArray());

View File

@ -164,8 +164,13 @@ abstract class Repository implements RepositoryInterface, CacheableInterface, Cr
*/
public function paginate($limit = null, $columns = ['*'], $pageName = 'page', $page = null)
{
$limit = $limit ? : RequestFacade::get('limit');
$limit = $limit ?? RequestFacade::get('limit');
$limit = is_null($limit) ? config('dipper.repository.pagination.limit', 10) : $limit;
if (!$limit) {
return $this->get($columns);
}
$page = $page ?: Paginator::resolveCurrentPage($pageName);
$total = $this->getCountForPagination();
@ -199,8 +204,13 @@ abstract class Repository implements RepositoryInterface, CacheableInterface, Cr
*/
public function simplePaginate($limit = 15, $columns = ['*'], $pageName = 'page', $page = null)
{
$limit = $limit ? : RequestFacade::get('limit');
$limit = $limit ?? RequestFacade::get('limit');
$limit = is_null($limit) ? config('dipper.repository.pagination.limit', 10) : $limit;
if (!$limit) {
return $this->get($columns);
}
$page = $page ?: Paginator::resolveCurrentPage($pageName);
$this->skip(($page - 1) * $limit)->take($limit + 1);