permissions
This commit is contained in:
parent
31b0a2fb44
commit
655a043712
@ -46,10 +46,6 @@ class AccountController extends Controller
|
|||||||
{
|
{
|
||||||
$attributes = $this->request->all();
|
$attributes = $this->request->all();
|
||||||
|
|
||||||
// if (!$this->request->user()->can('api.accounts.root')) {
|
|
||||||
// $attributes['parent_id'] = $this->account->id;
|
|
||||||
// }
|
|
||||||
|
|
||||||
$account = $this->accountService->store($attributes);
|
$account = $this->accountService->store($attributes);
|
||||||
|
|
||||||
return res($account, '创建成功');
|
return res($account, '创建成功');
|
||||||
|
@ -29,7 +29,7 @@ class PermissionController extends Controller
|
|||||||
{
|
{
|
||||||
$conditions = [];
|
$conditions = [];
|
||||||
|
|
||||||
if (!$this->account->can('api.permissions.create')) {
|
if (!$this->account->can('permissions.create')) {
|
||||||
$conditions['role_ids'] = $this->account->roles->pluck('id')->toArray();
|
$conditions['role_ids'] = $this->account->roles->pluck('id')->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ class PermissionRepository extends Repository
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->model = $this->model->orderBy('displayorder', 'desc');
|
$this->model = $this->model->orderBy('displayorder', 'desc')->orderBy('id', 'asc');
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,20 @@ namespace App\Domains\Stats\Http\Controllers;
|
|||||||
|
|
||||||
use App\Core\Controller;
|
use App\Core\Controller;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use App\Domains\Stats\Services\CompanyReportService;
|
||||||
|
|
||||||
class CompanyReportController extends Controller
|
class CompanyReportController extends Controller
|
||||||
{
|
{
|
||||||
protected $request;
|
protected $request;
|
||||||
|
protected $companyReportService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造函数,自动注入.
|
* 构造函数,自动注入.
|
||||||
*/
|
*/
|
||||||
public function __construct(Request $request)
|
public function __construct(Request $request, CompanyReportService $companyReportService)
|
||||||
{
|
{
|
||||||
$this->request = $request;
|
$this->request = $request;
|
||||||
|
$this->companyReportService = $companyReportService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,37 +26,26 @@ class CompanyReportController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
//
|
$conditions = $this->request->all();
|
||||||
|
$conditions['type'] = $this->request->ids('type');
|
||||||
|
|
||||||
|
$res = $this->companyReportService->index($conditions);
|
||||||
|
|
||||||
|
return res($res, '企业月报表', 201);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建.
|
* 统计明细.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\Response
|
* @return \Illuminate\Http\Response
|
||||||
*/
|
*/
|
||||||
public function create()
|
public function detail()
|
||||||
{
|
{
|
||||||
//
|
$conditions = $this->request->all();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$res = $this->companyReportService->detail($conditions);
|
||||||
* 编辑.
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\Response
|
|
||||||
*/
|
|
||||||
public function update($id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return res($res, '统计明细', 201);
|
||||||
* 删除.
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\Response
|
|
||||||
*/
|
|
||||||
public function destroy()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,4 +12,7 @@ $router->group(['prefix' => 'stats', 'as' => 'stats', 'middleware' => ['adminAut
|
|||||||
$router->get('/order/detail', ['as' => 'order.detail', 'uses' => 'OrderController@detail']);
|
$router->get('/order/detail', ['as' => 'order.detail', 'uses' => 'OrderController@detail']);
|
||||||
$router->get('/order/detail/export', ['as' => 'order.detail.export', 'uses' => 'OrderController@detailExport']);
|
$router->get('/order/detail/export', ['as' => 'order.detail.export', 'uses' => 'OrderController@detailExport']);
|
||||||
|
|
||||||
|
// 企业月报表
|
||||||
|
$router->get('/company-report', ['as' => 'company-report.index', 'uses' => 'CompanyReportController@index']);
|
||||||
|
$router->get('/company-report/detail', ['as' => 'company-report.detail', 'uses' => 'CompanyReportController@detail']);
|
||||||
});
|
});
|
||||||
|
@ -1,18 +1,106 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace App\Domains\Stats\Services;
|
namespace App\Domains\Stats\Services;
|
||||||
|
|
||||||
|
use App\Dicts;
|
||||||
use App\Core\Service;
|
use App\Core\Service;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use App\Domains\Virtual\Services\CompanyService;
|
||||||
|
use App\Domains\Virtual\Services\PackageService;
|
||||||
|
use App\Domains\Virtual\Services\ProductService;
|
||||||
|
use App\Domains\Virtual\Repositories\OrderCardPartitionRepository;
|
||||||
|
|
||||||
class CompanyReportService extends Service
|
class CompanyReportService extends Service
|
||||||
{
|
{
|
||||||
|
protected $orderCardPartitionRepository;
|
||||||
|
|
||||||
|
protected static $typeNames = ['首年', '非首年', '续费包', '流量包'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造函数
|
* 构造函数
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct(OrderCardPartitionRepository $orderCardPartitionRepository)
|
||||||
{
|
{
|
||||||
//
|
$this->orderCardPartitionRepository = $orderCardPartitionRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业月报表
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function index(array $conditions = [])
|
||||||
|
{
|
||||||
|
$select = [
|
||||||
|
'company_id',
|
||||||
|
'package_id',
|
||||||
|
'type',
|
||||||
|
DB::raw("MAX(order_id) as order_id"),
|
||||||
|
DB::raw('COUNT(id) as counts'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$query = $this->orderCardPartitionRepository->select($select)
|
||||||
|
->withConditions($conditions)
|
||||||
|
->groupBy(['company_id', 'package_id', 'type'])
|
||||||
|
->orderBy('type')->orderBy('company_id')->orderBy('package_id');
|
||||||
|
|
||||||
|
$res = $query->paginate($conditions['limit']);
|
||||||
|
|
||||||
|
$res->load('order:id,unit_price');
|
||||||
|
|
||||||
|
$res->map(function ($item) {
|
||||||
|
$company = app(CompanyService::class)->load($item->company_id);
|
||||||
|
$package = app(PackageService::class)->load($item->package_id);
|
||||||
|
$item->company_name = $company['name'];
|
||||||
|
$item->package_name = $package['name'];
|
||||||
|
$item->service_months = $package['service_months'] ?? 1;
|
||||||
|
$item->unit_price = sprintf('%.02f', $item->order['unit_price']/100);
|
||||||
|
$item->month_price = sprintf('%.02f', $item->unit_price/$item->service_months);
|
||||||
|
$item->total_price = sprintf('%.02f', $item->month_price*$item->counts);
|
||||||
|
$item->type_name = self::$typeNames[$item->type];
|
||||||
|
unset($item->order);
|
||||||
|
});
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业月报表明细
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function detail(array $conditions = [])
|
||||||
|
{
|
||||||
|
$select = [
|
||||||
|
'sim',
|
||||||
|
'company_id',
|
||||||
|
'package_id',
|
||||||
|
'order_id',
|
||||||
|
'type',
|
||||||
|
];
|
||||||
|
|
||||||
|
$query = $this->orderCardPartitionRepository->select($select)
|
||||||
|
->withConditions($conditions)
|
||||||
|
->orderBy('id', 'desc');
|
||||||
|
|
||||||
|
$res = $query->paginate($conditions['limit']);
|
||||||
|
|
||||||
|
$res->load('order:id,unit_price');
|
||||||
|
|
||||||
|
$carrierOperators = app(Dicts::class)->get('carrier_operator');
|
||||||
|
|
||||||
|
$res->map(function ($item) use ($carrierOperators) {
|
||||||
|
$company = app(CompanyService::class)->load($item->company_id);
|
||||||
|
$package = app(PackageService::class)->load($item->package_id);
|
||||||
|
$item->company_name = $company['name'];
|
||||||
|
$item->package_name = $package['name'];
|
||||||
|
$item->carrier_operator_name = $carrierOperators[$package['carrier_operator']];
|
||||||
|
$month_price = $item->order['unit_price'] / $package['service_months'];
|
||||||
|
$item->month_price = sprintf('%.02f', $month_price/100);
|
||||||
|
unset($item->order);
|
||||||
|
});
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ use App\Domains\Virtual\Repositories\PackageRepository;
|
|||||||
use App\Domains\Virtual\Repositories\ProductRepository;
|
use App\Domains\Virtual\Repositories\ProductRepository;
|
||||||
use App\Domains\Virtual\Repositories\OrderCardRepository;
|
use App\Domains\Virtual\Repositories\OrderCardRepository;
|
||||||
use App\Domains\Virtual\Repositories\OrderRenewalCardRepository;
|
use App\Domains\Virtual\Repositories\OrderRenewalCardRepository;
|
||||||
|
use App\Domains\Virtual\Repositories\OrderCardPartitionRepository;
|
||||||
use App\Domains\Virtual\Repositories\OrderFlowPackageCardsRepository;
|
use App\Domains\Virtual\Repositories\OrderFlowPackageCardsRepository;
|
||||||
use App\Domains\Virtual\Repositories\OrderRenewalPackageCardRepository;
|
use App\Domains\Virtual\Repositories\OrderRenewalPackageCardRepository;
|
||||||
|
|
||||||
@ -161,6 +162,7 @@ class LogSyncJob implements ShouldQueue
|
|||||||
app(OrderRenewalCardRepository::class)->forgetCached();
|
app(OrderRenewalCardRepository::class)->forgetCached();
|
||||||
app(OrderRenewalPackageCardRepository::class)->forgetCached();
|
app(OrderRenewalPackageCardRepository::class)->forgetCached();
|
||||||
app(OrderFlowPackageCardsRepository::class)->forgetCached();
|
app(OrderFlowPackageCardsRepository::class)->forgetCached();
|
||||||
|
app(OrderCardPartitionRepository::class)->forgetCached();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,6 +19,11 @@ trait OrderCardConcern
|
|||||||
$query->whereIn('id', $conditions['id']);
|
$query->whereIn('id', $conditions['id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($conditions['type'])) {
|
||||||
|
$conditions['type'] = array_wrap($conditions['type']);
|
||||||
|
$query->whereIn('type', $conditions['type']);
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($conditions['order_id'])) {
|
if (isset($conditions['order_id'])) {
|
||||||
$conditions['order_id'] = array_wrap($conditions['order_id']);
|
$conditions['order_id'] = array_wrap($conditions['order_id']);
|
||||||
$query->whereIn('order_id', $conditions['order_id']);
|
$query->whereIn('order_id', $conditions['order_id']);
|
||||||
@ -66,6 +71,13 @@ trait OrderCardConcern
|
|||||||
if (isset($conditions['endtime'])) {
|
if (isset($conditions['endtime'])) {
|
||||||
$query->where('created_at', '<=', Carbon::parse($conditions['endtime']));
|
$query->where('created_at', '<=', Carbon::parse($conditions['endtime']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($conditions['month'])) {
|
||||||
|
$query->where(function ($subQuery) use ($conditions) {
|
||||||
|
$subQuery->where('service_start_at', '<=', Carbon::parse($conditions['month']))
|
||||||
|
->where('service_end_at', '>=', Carbon::parse($conditions['month']));
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domains\Virtual\Repositories;
|
||||||
|
|
||||||
|
use App\Core\Repository;
|
||||||
|
use App\Models\Virtual\OrderCardPartition as Model;
|
||||||
|
use App\Domains\Virtual\Repositories\Concerns\OrderCardConcern;
|
||||||
|
|
||||||
|
class OrderCardPartitionRepository extends Repository
|
||||||
|
{
|
||||||
|
use OrderCardConcern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否关闭缓存
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
protected $cacheSkip = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否开启数据转化
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $needTransform = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $fieldSearchable = [
|
||||||
|
'id' => '=',
|
||||||
|
'created_at' => 'like',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function model()
|
||||||
|
{
|
||||||
|
return Model::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据格式化
|
||||||
|
*
|
||||||
|
* @param mixed $result
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function transform($model)
|
||||||
|
{
|
||||||
|
return $model->toArray();
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,8 @@ class ProductService extends Service
|
|||||||
{
|
{
|
||||||
protected $productRepository;
|
protected $productRepository;
|
||||||
|
|
||||||
|
protected $products;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造函数
|
* 构造函数
|
||||||
*
|
*
|
||||||
@ -122,4 +124,14 @@ class ProductService extends Service
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function load($id)
|
||||||
|
{
|
||||||
|
if (!$this->products) {
|
||||||
|
$this->products = $this->productRepository->select(['id', 'name', 'company_id', 'package_id', 'base_price', 'renewal_price'])
|
||||||
|
->withTrashed()->get()->keyBy('id');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->products[$id];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,6 +158,8 @@ class PermissionSeeder extends Seeder
|
|||||||
['name' => 'stats.order.1', 'title' => '续费订单统计', 'path' => '/stats/order/1', 'icon' => 'md-pulse', 'type' => 0, 'open' => 3],
|
['name' => 'stats.order.1', 'title' => '续费订单统计', 'path' => '/stats/order/1', 'icon' => 'md-pulse', 'type' => 0, 'open' => 3],
|
||||||
['name' => 'stats.order.2', 'title' => '续费包订单统计', 'path' => '/stats/order/2', 'icon' => 'md-pulse', 'type' => 0, 'open' => 3],
|
['name' => 'stats.order.2', 'title' => '续费包订单统计', 'path' => '/stats/order/2', 'icon' => 'md-pulse', 'type' => 0, 'open' => 3],
|
||||||
['name' => 'stats.order.3', 'title' => '加油包订单统计', 'path' => '/stats/order/3', 'icon' => 'md-pulse', 'type' => 0, 'open' => 3],
|
['name' => 'stats.order.3', 'title' => '加油包订单统计', 'path' => '/stats/order/3', 'icon' => 'md-pulse', 'type' => 0, 'open' => 3],
|
||||||
|
['name' => 'stats.company-report.1', 'title' => '用户月报表', 'path' => '/stats/company-report/1', 'icon' => 'md-pulse', 'type' => 0, 'open' => 3],
|
||||||
|
['name' => 'stats.company-report.2', 'title' => '增值包月报表', 'path' => '/stats/company-report/2', 'icon' => 'md-pulse', 'type' => 0, 'open' => 3],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
@ -26,7 +26,8 @@ const routes = [
|
|||||||
{ path: '/exports', name: 'StatsExports', component: load('exports/index'), meta: { title: '导出记录' } },
|
{ path: '/exports', name: 'StatsExports', component: load('exports/index'), meta: { title: '导出记录' } },
|
||||||
{ path: '/stats/company-count', name: 'StatsCompanyCount', component: load('stats/company-count/index'), meta: { title: '企业统计' } },
|
{ path: '/stats/company-count', name: 'StatsCompanyCount', component: load('stats/company-count/index'), meta: { title: '企业统计' } },
|
||||||
{ path: '/stats/order/:type', name: 'StatsOrder', component: load('stats/order/index'), meta: { title: '订单统计' } },
|
{ path: '/stats/order/:type', name: 'StatsOrder', component: load('stats/order/index'), meta: { title: '订单统计' } },
|
||||||
{ path: '/stats/order/detail/:type', name: 'StatsOrderDetail', component: load('stats/order/detail'), meta: { title: '订单明细' } }
|
{ path: '/stats/company-report/1', name: 'StatsOrderDetail', component: load('stats/company-report/index'), meta: { title: '用户月报表', type: [0, 1] } },
|
||||||
|
{ path: '/stats/company-report/2', name: 'StatsOrderDetail', component: load('stats/company-report/index'), meta: { title: '增值包月报表', type: [2, 3] } }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{ path: '*', redirect: { path: '/home' } }
|
{ path: '*', redirect: { path: '/home' } }
|
||||||
|
36
frontend/src/views/stats/company-report/detail.vue
Normal file
36
frontend/src/views/stats/company-report/detail.vue
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<template>
|
||||||
|
<Modal :footer-hide="true" :mask-closable="false" @on-visible-change="visibleChange" title="详情" v-model="my_show" width="1200">
|
||||||
|
<div class="page-detail-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="index(1)" icon="md-refresh">刷新</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="handle-item">
|
||||||
|
<Button @click="exportExcel" icon="md-download">导出</Button>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="page-list-wrap">
|
||||||
|
<Table :columns="columns" :data="list_data ? list_data.data : []" stripe width="1150"></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>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./js/detail.js"></script>
|
126
frontend/src/views/stats/company-report/index.vue
Normal file
126
frontend/src/views/stats/company-report/index.vue
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<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="options.company_name">
|
||||||
|
<Option :key="item.id" :value="item.name" v-for="item in completeHandledCompanies">{{ item.name }}</Option>
|
||||||
|
</AutoComplete>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="handle-item w-250">
|
||||||
|
<AutoComplete @on-search="handleCompletePackages" icon="ios-search" placeholder="套餐名称" v-model.trim="options.package_name">
|
||||||
|
<Option :key="item.id" :value="item.name" v-for="item in completeHandledPackages">{{ item.name }}</Option>
|
||||||
|
</AutoComplete>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="handle-item w-250">
|
||||||
|
<Select multiple clearable placeholder="类型" v-model="options.type">
|
||||||
|
<Option :value="0" v-if="types.indexOf(0) !== -1">首年</Option>
|
||||||
|
<Option :value="1" v-if="types.indexOf(1) !== -1">非首年</Option>
|
||||||
|
<Option :value="2" v-if="types.indexOf(2) !== -1">续费包</Option>
|
||||||
|
<Option :value="3" v-if="types.indexOf(3) !== -1">加油包</Option>
|
||||||
|
</Select>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<ul class="handle-wraper">
|
||||||
|
<li class="handle-item w-250">
|
||||||
|
<DatePicker :editable="false" placeholder="请选择时间" placement="bottom-start" type="month" v-model.trim="options.month"></DatePicker>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<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="columns" :data="data" :height="page.limit > 12 ? 610 : ''" ref="table" stripe>
|
||||||
|
<template class="table-footer" slot="footer">
|
||||||
|
<colgroup class="table-footer-colgroup"></colgroup>
|
||||||
|
<thead class="ivu-table" v-show="data.length">
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<div class="ivu-table-cell">总计</div>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<div class="ivu-table-cell"></div>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<div class="ivu-table-cell"></div>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<div class="ivu-table-cell"></div>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<div class="ivu-table-cell"></div>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<div class="ivu-table-cell">{{stats.counts}}</div>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<div class="ivu-table-cell">{{Number(stats.total_price).toFixed(2)}}</div>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<div class="ivu-table-cell"></div>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<div class="ivu-table-cell"></div>
|
||||||
|
</th>
|
||||||
|
<th rowspan="1" v-if="page.limit > 12"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</template>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page-turn-wrap">
|
||||||
|
<Page
|
||||||
|
:current="Number(page.page)"
|
||||||
|
:page-size="Number(page.limit)"
|
||||||
|
:page-size-opts="[10, 20, 100, Infinity]"
|
||||||
|
:total="Number(page.total)"
|
||||||
|
@on-change="changePage"
|
||||||
|
@on-page-size-change="changeLimit"
|
||||||
|
show-elevator
|
||||||
|
show-sizer
|
||||||
|
show-total
|
||||||
|
></Page>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ui-detail :list="detailObj.list" :options="detailObj.options" :show.sync="detailObj.show"></ui-detail>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./js/index.js"></script>
|
107
frontend/src/views/stats/company-report/js/detail.js
Normal file
107
frontend/src/views/stats/company-report/js/detail.js
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
export default {
|
||||||
|
name: 'StatsCompanyReportDetail',
|
||||||
|
props: {
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
default: {
|
||||||
|
month: null,
|
||||||
|
type: null,
|
||||||
|
company_id: null,
|
||||||
|
package_id: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
type: Object,
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
show(bool) {
|
||||||
|
this.my_show = bool;
|
||||||
|
},
|
||||||
|
list(obj) {
|
||||||
|
this.list_data = obj;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
my_show: false,
|
||||||
|
list_data: null,
|
||||||
|
columns: [{
|
||||||
|
title: 'SIM',
|
||||||
|
key: 'sim',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '运营商',
|
||||||
|
key: 'carrier_operator_name',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '企业名称',
|
||||||
|
key: 'company_name',
|
||||||
|
width: 300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '套餐名称',
|
||||||
|
key: 'package_name',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '套餐单价(元/月)',
|
||||||
|
key: 'month_price',
|
||||||
|
width: 120
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
visibleChange(bool) {
|
||||||
|
this.$emit('update:show', bool);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* [index 列表]
|
||||||
|
* @param {Number} page [description]
|
||||||
|
* @return {[type]} [description]
|
||||||
|
*/
|
||||||
|
index(page) {
|
||||||
|
this.isShowLoading(true);
|
||||||
|
let params = this.options;
|
||||||
|
params.page = page;
|
||||||
|
|
||||||
|
service.get('api/stats/company-report/detail', { params }).then(res => {
|
||||||
|
this.isShowLoading(false);
|
||||||
|
if (res.code == 0) {
|
||||||
|
this.list_data = res.data;
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.isShowLoading(false);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
exportExcel() {
|
||||||
|
this.isShowLoading(true);
|
||||||
|
let params = this.options;
|
||||||
|
|
||||||
|
service.get('api/stats/company-report/detail/export', { params }).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
if (res.data) {
|
||||||
|
this.downloadFile(res.data);
|
||||||
|
} else {
|
||||||
|
this.$Modal.success({
|
||||||
|
title: '提示',
|
||||||
|
content: '当前导出数据量大,已进入后台队列导出模式,请稍后至导出列表查看下载。'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isShowLoading(false);
|
||||||
|
}).catch(() => {
|
||||||
|
this.isShowLoading(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
266
frontend/src/views/stats/company-report/js/index.js
Normal file
266
frontend/src/views/stats/company-report/js/index.js
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
import {
|
||||||
|
sumBy
|
||||||
|
} from 'service/util';
|
||||||
|
export default {
|
||||||
|
name: 'StatsCompanyReport',
|
||||||
|
components: {
|
||||||
|
UiDetail: resolve => require(['views/stats/order/detail'], resolve)
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
search: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
detailObj: {
|
||||||
|
type: null,
|
||||||
|
options: {}
|
||||||
|
},
|
||||||
|
types: [],
|
||||||
|
options: {
|
||||||
|
company_name: null,
|
||||||
|
package_name: null,
|
||||||
|
type: [],
|
||||||
|
month: this.moment().subtract('2', 'months').startOf('month').format('YYYY-MM')
|
||||||
|
},
|
||||||
|
data: [],
|
||||||
|
list: [],
|
||||||
|
stats: {},
|
||||||
|
page: {
|
||||||
|
total: 0,
|
||||||
|
limit: 10,
|
||||||
|
page: 1
|
||||||
|
},
|
||||||
|
columns: [{
|
||||||
|
title: '企业名称',
|
||||||
|
key: 'company_name',
|
||||||
|
width: 300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '套餐名称',
|
||||||
|
key: 'package_name',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '套餐周期(月)',
|
||||||
|
key: 'service_months',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '套餐价格(元/周期)',
|
||||||
|
key: 'unit_price',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '套餐单价(元/月)',
|
||||||
|
key: 'month_price',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '收费用户数',
|
||||||
|
key: 'counts',
|
||||||
|
width: 130
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '收费总价(元)',
|
||||||
|
key: 'total_price',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '收费类型',
|
||||||
|
key: 'type_name',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
render: (h, {
|
||||||
|
row,
|
||||||
|
column,
|
||||||
|
index
|
||||||
|
}) => {
|
||||||
|
let html = [];
|
||||||
|
|
||||||
|
html.push(h('Button', {
|
||||||
|
props: {
|
||||||
|
type: 'primary',
|
||||||
|
size: 'small',
|
||||||
|
disabled: false,
|
||||||
|
icon: 'ios-create'
|
||||||
|
},
|
||||||
|
class: ['btn'],
|
||||||
|
on: {
|
||||||
|
click: (event) => {
|
||||||
|
this.isShowLoading(true);
|
||||||
|
|
||||||
|
let params = {
|
||||||
|
page: 1,
|
||||||
|
limit: 10,
|
||||||
|
type: row.type,
|
||||||
|
company_id: row.company_id,
|
||||||
|
month: this.options.month,
|
||||||
|
package_id: row.package_id
|
||||||
|
};
|
||||||
|
|
||||||
|
service.get('api/stats/company-report/detail', {
|
||||||
|
params
|
||||||
|
}).then(res => {
|
||||||
|
this.isShowLoading(false);
|
||||||
|
if (res.code == 0) {
|
||||||
|
this.detailObj = {
|
||||||
|
show: true,
|
||||||
|
options: params,
|
||||||
|
list: res.data
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.isShowLoading(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, '查看明细'));
|
||||||
|
|
||||||
|
if (html.length) {
|
||||||
|
return h('div', html);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.types = this.$route.meta.type;
|
||||||
|
this.options.type = this.types;
|
||||||
|
this.index();
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
window.onresize = () => {
|
||||||
|
this.tableFooter();
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* [index 列表]
|
||||||
|
* @param {Number} page [description]
|
||||||
|
* @return {[type]} [description]
|
||||||
|
*/
|
||||||
|
index() {
|
||||||
|
this.isShowLoading(true);
|
||||||
|
|
||||||
|
this.data = [];
|
||||||
|
|
||||||
|
let params = Object.assign(this.options, {
|
||||||
|
limit: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!params.month) {
|
||||||
|
params.month = this.moment().subtract('2', 'months').startOf('month').format('YYYY-MM');
|
||||||
|
} else {
|
||||||
|
params.month = this.moment(params.month).format('YYYY-MM');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.type.length === 0) {
|
||||||
|
params.type = this.types;
|
||||||
|
}
|
||||||
|
|
||||||
|
service.get('api/stats/company-report', {
|
||||||
|
params
|
||||||
|
}).then(res => {
|
||||||
|
this.isShowLoading(false);
|
||||||
|
if (res.code == 0) {
|
||||||
|
this.list = res.data;
|
||||||
|
this.page.total = this.list.length;
|
||||||
|
this.changePage(1);
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.isShowLoading(false);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [request 刷新]
|
||||||
|
* @return {[type]} [description]
|
||||||
|
*/
|
||||||
|
request() {
|
||||||
|
let page = this.page.page;
|
||||||
|
|
||||||
|
if (this.data.length == 1) {
|
||||||
|
page = this.returnPage(this.page.total, this.page.page, this.page.limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.index();
|
||||||
|
this.changePage(page);
|
||||||
|
},
|
||||||
|
|
||||||
|
resetSearch() {
|
||||||
|
for (let k in this.options) {
|
||||||
|
if (k === 'month') {
|
||||||
|
this.options[k] = this.moment().subtract('2', 'months').startOf('month').format('YYYY-MM');
|
||||||
|
} else if (k === 'type') {
|
||||||
|
this.options[k] = [];
|
||||||
|
} else {
|
||||||
|
this.options[k] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.page = {
|
||||||
|
total: 0,
|
||||||
|
limit: 10,
|
||||||
|
page: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
this.index();
|
||||||
|
},
|
||||||
|
changeLimit(limit) {
|
||||||
|
this.page.limit = limit;
|
||||||
|
this.changePage(1);
|
||||||
|
},
|
||||||
|
changePage(page) {
|
||||||
|
this.page.page = page;
|
||||||
|
this.data = this.list.slice((page - 1) * this.page.limit, page * this.page.limit);
|
||||||
|
|
||||||
|
this.stats = {
|
||||||
|
counts: sumBy(this.list, 'counts'),
|
||||||
|
total_price: sumBy(this.list, 'total_price')
|
||||||
|
};
|
||||||
|
|
||||||
|
this.tableFooter();
|
||||||
|
},
|
||||||
|
tableFooter() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
let html = $('.ivu-table-header colgroup').html();
|
||||||
|
$('.table-footer-colgroup').html(html);
|
||||||
|
}, 10);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
exportExcel() {
|
||||||
|
this.isShowLoading(true);
|
||||||
|
|
||||||
|
let params = Object.assign(this.options, {
|
||||||
|
limit: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!params.month) {
|
||||||
|
params.month = this.moment().subtract('2', 'months').startOf('month').format('YYYY-MM');
|
||||||
|
} else {
|
||||||
|
params.month = this.moment(params.month).format('YYYY-MM');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.type.length === 0) {
|
||||||
|
params.type = this.types;
|
||||||
|
}
|
||||||
|
|
||||||
|
service.get('api/stats/company-report/export', {
|
||||||
|
params
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.downloadFile(res.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isShowLoading(false);
|
||||||
|
}).catch(() => {
|
||||||
|
this.isShowLoading(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user