diff --git a/app/Domains/Stats/Http/Controllers/RenewalController.php b/app/Domains/Stats/Http/Controllers/RenewalController.php
new file mode 100644
index 00000000..b7de3d2b
--- /dev/null
+++ b/app/Domains/Stats/Http/Controllers/RenewalController.php
@@ -0,0 +1,38 @@
+request = $request;
+ $this->renewalService = $renewalService;
+ }
+
+ /**
+ * 列表.
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function index()
+ {
+ $conditions = $this->request->all();
+
+ $res = $this->renewalService->index($conditions);
+
+ return res($res, '续费率统计', 201);
+ }
+}
diff --git a/app/Domains/Stats/Routes/api.php b/app/Domains/Stats/Routes/api.php
index bdd37c90..936ae067 100644
--- a/app/Domains/Stats/Routes/api.php
+++ b/app/Domains/Stats/Routes/api.php
@@ -20,4 +20,7 @@ $router->group(['prefix' => 'stats', 'as' => 'stats', 'middleware' => ['adminAut
// 销售激活统计
$router->get('/sold-activated', ['as' => 'sold-activated.index', 'uses' => 'SoldActivatedController@index']);
+
+ // 续费率统计
+ $router->get('/renewal', ['as' => 'renewal.index', 'uses' => 'RenewalController@index']);
});
diff --git a/app/Domains/Stats/Services/RenewalService.php b/app/Domains/Stats/Services/RenewalService.php
new file mode 100644
index 00000000..a3bced6b
--- /dev/null
+++ b/app/Domains/Stats/Services/RenewalService.php
@@ -0,0 +1,68 @@
+= ' . $conditions['activate_start_time'] . ' ';
+ }
+
+ if($conditions['activate_end_time']){
+ $where .= 'AND c.service_end_at <= ' . $conditions['activate_end_time'] . ' ';
+ }
+
+ if($conditions['renewal_start_time']){
+ $where .= 'AND p.service_start_at >= ' . $conditions['renewal_start_time'] . ' ';
+ }
+
+ if($conditions['renewal_start_time']){
+ $where .= 'AND p.service_start_at >= ' . $conditions['renewal_start_time'] . ' ';
+ }
+
+ $sql = $sql . $where . $group;
+
+ $data = DB::select($sql);
+
+ if(!$data){
+ return [];
+ }
+
+ foreach ($data as $item) {
+ $item = (array)$item;
+ $item['company_name'] = CompanyService::load($item['company_id'])['name'];
+ $item['ratio'] = $item['activates'] == 0 ? 0 : $item['renewals']/$item['activates'];
+ $item['ratio'] = sprintf('%.02f', $item['ratio']);
+ }
+
+ return $data;
+ }
+}
diff --git a/database/seeds/PermissionSeeder.php b/database/seeds/PermissionSeeder.php
index fdc76a5e..da9149fe 100644
--- a/database/seeds/PermissionSeeder.php
+++ b/database/seeds/PermissionSeeder.php
@@ -336,6 +336,12 @@ class PermissionSeeder extends Seeder
['name' => 'stats.sold-activated.show', 'title' => '明细', 'description' => 'show', 'type' => 1],
]
],
+ [
+ 'name' => 'stats.renewal', 'title' => '续费率统计', 'path' => '/stats/renewal', 'icon' => 'md-bowtie', 'type' => 0, 'open' => 3,
+ 'children' => [
+ ['name' => 'stats.renewal.export', 'title' => '导出', 'description' => 'output', 'type' => 1],
+ ]
+ ],
[
'name' => 'stats.flow-pools', 'title' => '流量池统计', 'path' => '/flow-pools', 'icon' => 'md-swap', 'type' => 0, 'open' => 3,
'children' => [
diff --git a/frontend/public/config.js b/frontend/public/config.js
index ae4513f9..0434dccc 100644
--- a/frontend/public/config.js
+++ b/frontend/public/config.js
@@ -3,7 +3,7 @@ var CONFIG = {
login_background: '/assets/login_background.jpg',
logo_big: '/assets/logo_big.png',
logo_small: '/assets/logo_small.png',
- url: (window.location.hostname === 'localhost') ? 'http://vd.dipp.ink/' : '/'
+ url: (window.location.hostname === 'localhost') ? 'http://127.0.0.1:8000/' : '/'
};
window.CONFIG = CONFIG;
diff --git a/frontend/src/router/routes.js b/frontend/src/router/routes.js
index 904dda59..a7fd0f3a 100644
--- a/frontend/src/router/routes.js
+++ b/frontend/src/router/routes.js
@@ -31,6 +31,7 @@ const routes = [
{ path: '/stats/order/:type', name: 'StatsOrder', component: load('stats/order/index'), meta: { title: '订单统计' } },
{ path: '/stats/company-report/:type', name: 'StatsCompanyReport', component: load('stats/company-report/index'), meta: { title: '月报表' } },
{ path: '/stats/sold-activated', name: 'SoldActivated', component: load('stats/sold-activated/index'), meta: { title: '销售激活统计' } },
+ { path: '/stats/renewal', name: 'Renewal', component: load('stats/renewal/index'), meta: { title: '续费率统计' } },
{ path: '/artisan/real-sync', name: 'RealSync', component: load('artisan/real-sync/index'), meta: { title: 'RD数据同步' } },
{ path: '/flow-pools', name: 'FlowPools', component: load('virtual/flow_pools/index'), meta: { title: '流量池管理' } }
]
diff --git a/frontend/src/views/stats/renewal/index.vue b/frontend/src/views/stats/renewal/index.vue
new file mode 100644
index 00000000..c4718f86
--- /dev/null
+++ b/frontend/src/views/stats/renewal/index.vue
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+ -
+
+ 全部信息
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/stats/renewal/js/index.js b/frontend/src/views/stats/renewal/js/index.js
new file mode 100644
index 00000000..4046302c
--- /dev/null
+++ b/frontend/src/views/stats/renewal/js/index.js
@@ -0,0 +1,149 @@
+export default {
+ name: 'StatsRenewal',
+ data() {
+ return {
+ search: {
+ show: true
+ },
+ options: {
+ name: '',
+ time: [
+ this.moment().subtract('1', 'months').startOf('month').format('YYYY-MM-DD'),
+ this.moment().subtract('1', 'months').endOf('month').format('YYYY-MM-DD')
+ ]
+ },
+ data: [],
+ list: [],
+ stats: {},
+ page: {
+ total: 0,
+ limit: 10,
+ page: 1
+ },
+ columns: [
+ {
+ title: '企业ID',
+ key: 'company_id',
+ width: 80
+ },
+ {
+ title: '企业名称',
+ key: 'company_name'
+ },
+ {
+ title: '激活数',
+ key: 'activates',
+ width: 120
+ },
+ {
+ title: '续费数',
+ key: 'renewals',
+ width: 120
+ },
+ {
+ title: '续费率',
+ key: 'ratio',
+ width: 120
+ }
+ ]
+ };
+ },
+ created() {
+ this.index();
+ },
+ methods: {
+ /**
+ * [index 列表]
+ * @param {Number} page [description]
+ * @return {[type]} [description]
+ */
+ index() {
+ let options = Object.assign({
+ orderBy: 'id',
+ sortedBy: 'asc'
+ },
+ this.options);
+
+ let params = this.searchDataHandle({}, {
+ limit: 0
+ }, options);
+
+ this.isShowLoading(true);
+
+ service.get('api/stats/renewal', {
+ 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('1', 'months').startOf('month').format('YYYY-MM');
+ } else {
+ this.options[k] = '';
+ }
+ }
+
+ 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);
+ },
+
+ exportExcel() {
+ this.isShowLoading(true);
+
+ let options = Object.assign({
+ orderBy: 'id',
+ sortedBy: 'asc'
+ },
+
+ this.options);
+
+ let params = this.searchDataHandle({}, {}, options);
+
+ this.isShowLoading(true);
+
+ service.get('api/stats/company-count/export', {
+ params
+ }).then((res) => {
+ if (res.code === 0) {
+ this.downloadFile(res.data);
+ }
+
+ this.isShowLoading(false);
+ }).catch(() => {
+ this.isShowLoading(false);
+ });
+ }
+ }
+};
diff --git a/tests/ExampleTest.php b/tests/ExampleTest.php
index ba86289f..4de10a10 100644
--- a/tests/ExampleTest.php
+++ b/tests/ExampleTest.php
@@ -2,6 +2,7 @@
use App\Domains\Stats\Services\OrderService;
use App\Domains\Export\Services\ExportService;
+use App\Domains\Stats\Services\RenewalService;
use App\Domains\Virtual\Services\PropertyService;
use App\Domains\Stats\Exports\CompanyReportDetailExport;