Prechádzať zdrojové kódy

Merge branch 'test' of 121.36.198.49:zy_duanju/zhiyu_duanju_distribution_manage_front into psl_test_souquan

pansl 1 rok pred
rodič
commit
2188a96cab

+ 33 - 0
src/api/dataStatistics/userStatistics.ts

@@ -0,0 +1,33 @@
+import http from '@/api/http';
+
+/**
+ *  用户统计
+ */
+
+/**
+ * 用户统计-列表,导出
+ */
+export function getstatisticUserList(params?: object) {
+  return http.get('/statistic/users/list', params);
+}
+/**
+ * 用户统计-列表 统计
+ */
+export function statisticUserList(params?: object) {
+  return http.get('/statistic/users/list_statistics', params);
+}
+
+
+/**
+ * 用户统计-今日数据
+ */
+export function statisticUserTodayData() {
+  return http.get('/statistic/users/today');
+}
+
+/**
+ * 用户统计-今日数据
+ */
+export function statisticUserHistoryData() {
+  return http.get('/statistic/users/stats');
+}

+ 12 - 0
src/views/dataStatistics/userStatistics/excelTitle.ts

@@ -0,0 +1,12 @@
+// 导出中文/字段
+export const titleObj = {
+  时间: 'date',
+  优化师: 'username',
+  小程序名称: 'miniprogram_name',
+  当日新增用户数: 'new_user_num',
+  当日新增用户充值人数: 'new_user_recharge_num',
+  当日新增用户充值率: 'recharge_rate',
+  当日新增用户充值总额: 'new_user_recharge_total',
+  当日新增用户人均充值: 'recharge_mean',
+};
+

+ 296 - 0
src/views/dataStatistics/userStatistics/index.vue

@@ -0,0 +1,296 @@
+<template>
+  <div>
+    <!-- 统计 -->
+    <summaryStatistics></summaryStatistics>
+    <Search :search="moreSearch" :reset="moreReset">
+      <template v-slot:body>
+        <el-form-item label="时间">
+          <el-date-picker unlink-panels clearable @change="timeChange" format="YYYY/MM/DD" value-format="YYYY-MM-DD"
+            v-model="query.time" type="daterange" :shortcuts="shortcuts" range-separator="To" start-placeholder="开始时间"
+            end-placeholder="结束时间" />
+        </el-form-item>
+        <el-form-item label="优化师" prop="user_id" v-if="!rolesIdentify.includes('optimizer')">
+          <el-select v-model="query.user_id" filterable remote clearable
+            :remote-method="(query) => { remoteMethod(query, 'channelPromotionsUsers') }" placeholder="选择优化师">
+            <el-option v-for="item in promotionsUsersList" :key="item.user_id" :label="item.name" :value="item.user_id" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="小程序" prop="miniprogram_id">
+          <el-select v-model="query.miniprogram_id" filterable remote
+            :remote-method="(query) => { remoteMethod(query, 'channelMiniprogram') }" clearable placeholder="选择小程序">
+            <el-option v-for="item in channelMiniprogram" :key="item.miniprogram_id" :label="item.name"
+              :value="item.miniprogram_id" />
+          </el-select>
+        </el-form-item>
+      </template>
+      <template v-slot:extra_button>
+        <exportExcel api="statistic/users/list"  v-action="'statistic.UserStatistics.export'" sheet_name="充值统计" :title_obj="titleObj"
+          :extro_params="{ is_all: true, ...query }">
+        </exportExcel>
+      </template>
+     
+    </Search>
+	<div style="margin:8px 6px;">
+	          <el-card shadow="hover" :body-style="{ padding: '20px' }">
+	            <div class="stat-wrapper">
+	              <div>所选时间段内累计充新增用户数:
+	                <span class="ml-2 mr-4 stat">{{ statisticalData.new_user_num || '暂无数据' }}</span>
+	              </div>
+	              <div>累计新用户充值人数:
+	                <span class="ml-2 mr-4 stat">{{ statisticalData.new_user_recharge_num || '暂无数据' }}</span>
+	              </div>
+	            </div>
+	          </el-card>
+	        </div>
+	        <div class="table-default" >
+	          <el-table :data="tableData" class="mt-3" v-loading="loading">
+	            <el-table-column prop="date" min-width="120px" label="时间" />
+	            <el-table-column prop="username" label="优化师" min-width="160px" />
+	            <el-table-column prop="miniprogram_name" label="小程序名称" min-width="160px" />
+	            <el-table-column label="当日新增用户数" prop="new_user_num" min-width="160px">
+	              <template #header>
+	                <div class="flex items-center">
+						<el-tooltip placement="top">
+						  <template #content>
+						    当天的新增用户<br />
+						  </template>
+						  <el-icon>
+						    <InfoFilled />
+						  </el-icon>
+						</el-tooltip>
+	                  <span>当日新增用户数</span>
+	                </div>
+	              </template>
+	              <template #default="scope">
+	                <div class="wrapper">
+	                  <div>{{ scope.row.new_user_num }}</div>
+	                </div>
+	              </template>
+	            </el-table-column>
+	            <el-table-column label="当日新增用户充值人数" prop="pay_count" min-width="180px">
+	              <template #header>
+	                <div class="flex items-center">
+						<el-tooltip placement="top">
+						  <template #content>
+						    当日新增用户充值人数<br />
+						  </template>
+						  <el-icon>
+						    <InfoFilled />
+						  </el-icon>
+						</el-tooltip>
+	                  <span>当日新增用户充值人数</span>
+	                  
+	                </div>
+	              </template>
+	              <template #default="scope">
+	                <div class="wrapper">
+	                  <div>{{ scope.row.new_user_recharge_num }}</div>
+	                </div>
+	              </template>
+	            </el-table-column>
+	           <el-table-column label="当日新增用户充率" prop="recharge_rate" min-width="180px">
+	             <template #header>
+	               <div class="flex items-center">
+	           		<el-tooltip placement="top">
+	           		  <template #content>
+	           		    当日新增用户充率<br />
+	           		  </template>
+	           		  <el-icon>
+	           		    <InfoFilled />
+	           		  </el-icon>
+	           		</el-tooltip>
+	                 <span>当日新增用户充率</span>
+	                 
+	               </div>
+	             </template>
+	             <template #default="scope">
+	               <div class="wrapper">
+	                 <div>{{ scope.row.recharge_rate }}</div>
+	               </div>
+	             </template>
+	           </el-table-column>
+	           	<el-table-column label="当日新增用户充总额" prop="new_user_recharge_total" min-width="180px">
+	           	  <template #header>
+	           	    <div class="flex items-center">
+	           			<el-tooltip placement="top">
+	           			  <template #content>
+	           			    当日新增用户充总额<br />
+	           			  </template>
+	           			  <el-icon>
+	           			    <InfoFilled />
+	           			  </el-icon>
+	           			</el-tooltip>
+	           	      <span>当日新增用户充总额</span>
+	           	      
+	           	    </div>
+	           	  </template>
+	           	  <template #default="scope">
+	           	    <div class="wrapper">
+	           	      <div>{{ scope.row.new_user_recharge_total }}</div>
+	           	    </div>
+	           	  </template>
+	           	</el-table-column>
+				<el-table-column label="新增用户人均充值" prop="recharge_mean" min-width="180px">
+				  <template #header>
+				    <div class="flex items-center">
+						<el-tooltip placement="top">
+						  <template #content>
+						    新增用户人均充值<br />
+						  </template>
+						  <el-icon>
+						    <InfoFilled />
+						  </el-icon>
+						</el-tooltip>
+				      <span>新增用户人均充值</span>
+				      
+				    </div>
+				  </template>
+				  <template #default="scope">
+				    <div class="wrapper">
+				      <div>{{ scope.row.recharge_mean }}</div>
+				    </div>
+				  </template>
+				</el-table-column>		   
+	          </el-table>
+	          <Paginate />
+	        </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import summaryStatistics from './summaryStatistics.vue';
+import { shortcuts } from '@/utils/shortcuts'
+import { useRouter, useRoute } from 'vue-router'
+import { InfoFilled } from '@element-plus/icons-vue';
+import { useGetList } from '@/hook/curd/useGetList';
+import { statisticUserList } from '@/api/dataStatistics/userStatistics'
+import { titleObj } from "./excelTitle";
+import moment from 'moment';
+const start_date = moment().subtract(7, 'days').format('YYYY-MM-DD');
+const end_date = moment().format('YYYY-MM-DD');
+const statisticalData = ref({})
+const api = '/statistic/users/list';
+const router = useRouter()
+const route = useRoute()
+const rolesIdentify = inject('rolesIdentify')
+import {
+  channelMiniprogramUseList,
+  channelPromotionsUsers,
+} from '@/api/orders/index'
+const channelMiniprogram = ref([])
+const promotionsUsersList = ref([])
+const { data, query, search, reset, loading } = useGetList(api);
+const remoteMethod = (query: string, type: string,) => {
+  console.log(query, 'queryquery', type);
+  switch (type) {
+    case 'channelPromotionsUsers':
+      initRemoteOption('channelPromotionsUsers', { name: query })
+      break;
+    case 'channelMiniprogram':
+      initRemoteOption('channelMiniprogram', { name: query })
+      break;
+  }
+}
+
+const initRemoteOption = (type: string, params?: object) => {
+  switch (type) {
+    case 'channelPromotionsUsers':
+      channelPromotionsUsers({ limit: 30, ...params }).then(res => {
+        promotionsUsersList.value = res.data
+      })
+      break;
+    case 'channelMiniprogram':
+      channelMiniprogramUseList({ limit: 30, ...params }).then(res => {
+        channelMiniprogram.value = res.data
+      })
+      break;
+  }
+}
+
+
+const timeChange = (e: object) => {
+  console.log(e, 'timeChangetimeChangetimeChange');
+  if (query.value.time) {
+    const timeArr = toRaw(e);
+    query.value.start_at = timeArr[0]
+    query.value.end_at = timeArr[1]
+  } else {
+    delete query.value.start_at
+    delete query.value.end_at
+  }
+}
+
+const moreSearch = () => {
+  search();
+  statisticUserList({ ...query.value }).then(res => {
+    statisticalData.value = res.data
+  })
+}
+
+const moreReset = () => {
+  reset()
+  statisticUserList({ ...query.value }).then(res => {
+    statisticalData.value = res.data
+  })
+}
+
+const tableData = computed(() => data.value?.data);
+
+onMounted(() => {
+  initRemoteOption('channelPromotionsUsers')
+  initRemoteOption('channelMiniprogram')
+  query.value.time = [start_date, end_date];
+  query.value.start_at = start_date;
+  query.value.end_at = end_date;
+  moreSearch();
+});
+</script>
+
+<style scoped lang="scss">
+.box-card {
+  width: 300px;
+  margin: 8px;
+
+  .money-wrapper {
+    height: 50px;
+    width: 100%;
+    color: #ed892c;
+    font-size: 26px;
+  }
+}
+
+.stat-wrapper {
+  display: flex;
+  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+
+  .stat {
+    box-sizing: border-box;
+    font-size: 18px;
+    font-weight: 550;
+    padding: 0 12px;
+  }
+}
+
+.table-default {
+  padding: 2px 4px 8px 4px;
+
+  .set-warpper {
+    height: 60px;
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+  }
+
+  .wrapper {
+    margin: 8px;
+
+    .label {
+      margin-right: 6px;
+    }
+
+    .content {
+      font-size: 15px;
+    }
+  }
+}
+</style>

+ 261 - 0
src/views/dataStatistics/userStatistics/summaryStatistics.vue

@@ -0,0 +1,261 @@
+<template>
+  <div class="flex w-full card-wrapper">
+    <el-card class="box-card" shadow="hover" v-action="'statistic.chargeTJ.todayCharge'">
+      <template #header>
+        <div class="flex items-center justify-between card-header">
+          <div class="flex items-center">
+			  <el-tooltip placement="top">
+			    <template #content>
+			      截至当前时间,今日新增用户数量<br />
+			    </template>
+			    <el-icon>
+			      <InfoFilled />
+			    </el-icon>
+			  </el-tooltip>
+            <span>今日新增用户</span>
+          </div>
+          <p class="text-red-300">{{ timer.seconds }}s后刷新</p>
+        </div>
+      </template>
+      <div class="money-wrapper">{{ todayChargeData.new_user_num || '0' }}</div>
+      <div class="flex items-center justify-between">
+        <div>
+          <!-- <p class="text-lg font-bold">普通充值</p> -->
+          <div>
+			<el-tooltip placement="top">
+				<template #content>
+				  新增用户中进行充值的人数<br />
+				</template>
+				<el-icon>
+				  <InfoFilled />
+				</el-icon>
+			</el-tooltip>
+            <span class="text-sm">充值人数:</span>
+		
+            <span class="text-base">{{ todayChargeData.new_user_recharge_num || '0' }}人</span>
+          </div>
+          <div>
+            <span class="text-sm">会员充值:</span>
+            <span class="text-base">{{ todayChargeData.recharge_vip_num || '0' }}人</span>
+          </div>
+          <div>
+            <span class="text-sm">普通充值:</span>
+            <span class="text-base">{{ todayChargeData.recharge_coin_num || '0' }}人</span>
+          </div>
+        </div>
+        <div>
+          <!-- <p class="text-lg font-bold">会员充值</p> -->
+          <div>
+			  <el-tooltip placement="top">
+			  	<template #content>
+			  	  新增用户当天充值金额<br />
+			  	</template>
+			  	<el-icon>
+			  	  <InfoFilled />
+			  	</el-icon>
+			  </el-tooltip>
+            <span class="text-sm">充值金额:</span>
+            <span class="text-base">{{ todayChargeData.new_user_recharge_total || '-' }}</span>
+          </div>
+          <div>
+			  <el-tooltip placement="top">
+			  	<template #content>
+			  	  新增用户当天充值金额/新用户当天充值人数<br />
+			  	</template>
+			  	<el-icon>
+			  	  <InfoFilled />
+			  	</el-icon>
+			  </el-tooltip>
+            <span class="text-sm">人均充值:</span>
+            <span class="text-base">{{ todayChargeData.recharge_mean || '-' }}</span>
+          </div>
+          <div>
+			  <el-tooltip placement="top">
+			  	<template #content>
+			  	  充值人数/新增用户数<br />
+			  	</template>
+			  	<el-icon>
+			  	  <InfoFilled />
+			  	</el-icon>
+			  </el-tooltip>
+            <span class="text-sm">充值率:</span>
+            <span class="text-base">{{ todayChargeData.recharge_rate || '-' }}</span>
+          </div>
+        </div>
+      </div>
+    </el-card>
+    <el-card class="box-card" shadow="hover" v-action="'statistic.chargeTJ.currentMonthCharge'">
+      <template #header>
+        <div class="flex items-center justify-between card-header">
+          <div class="flex items-center">
+            <span>本月新增用户</span>
+            <el-tooltip placement="top">
+              <template #content>
+                本月截至昨日的累计新增用户数量<br />
+              </template>
+              <el-icon>
+                <InfoFilled />
+              </el-icon>
+            </el-tooltip>
+            <span class="ml-2 text-red-300">(不包含当日)</span>
+          </div>
+        </div>
+      </template>
+      <div class="money-wrapper">{{ currentMonth.new_user_num || '-' }}</div>
+      <div class="flex items-center justify-between">
+        <div>
+          
+          <div>
+            <span class="text-sm">充值人数:</span>
+            <span class="text-base">{{ currentMonth.new_user_recharge_num || '-' }}人</span>
+          </div>
+          <div>
+            <span class="text-sm">会员充值:</span>
+            <span class="text-base">{{ currentMonth.new_user_recharge_vip_num || '-' }}人</span>
+          </div>
+          <div>
+            <span class="text-sm">普通充值:</span>
+            <span class="text-base">{{ currentMonth.new_user_recharge_coin_num || '-' }}人</span>
+          </div>
+        </div>
+       
+      </div>
+    </el-card>
+    <el-card class="box-card" shadow="hover" v-action="'statistic.chargeTJ.lastMonthCharge'">
+      <template #header>
+        <div class="flex items-center justify-between card-header">
+          <div class="flex items-center">
+            <span>上月新增用户</span>
+            <el-tooltip placement="top">
+              <template #content>
+                上月的累计新增用户数量<br />
+              </template>
+              <el-icon>
+                <InfoFilled />
+              </el-icon>
+            </el-tooltip>
+          </div>
+        </div>
+      </template>
+      <div class="money-wrapper">{{ lastMonth.new_user_num || '-' }}</div>
+      <div class="flex items-center justify-between">
+        <div>
+          <div>
+            <span class="text-sm">充值人数:</span>
+            <span class="text-base">{{ lastMonth.new_user_recharge_num || '-' }}人</span>
+          </div>
+          <div>
+            <span class="text-sm">会员充值:</span>
+            <span class="text-base">{{ lastMonth.new_user_recharge_vip_num || '-' }}人</span>
+          </div>
+          <div>
+            <span class="text-sm">普通充值:</span>
+            <span class="text-base">{{ lastMonth.new_user_recharge_coin_num || '-' }}人</span>
+          </div>
+        </div>
+      </div>
+    </el-card>
+    <el-card class="box-card" shadow="hover" v-action="'statistic.chargeTJ.totalCharge'">
+      <template #header>
+        <div class="flex items-center justify-between card-header">
+          <div class="flex items-center">
+            <span>累计新增用户</span>
+            <el-tooltip placement="top">
+              <template #content>
+                昨日及之前的所有累计新增用户数量<br />
+              </template>
+              <el-icon>
+                <InfoFilled />
+              </el-icon>
+            </el-tooltip>
+            <span class="ml-2 text-red-300">(不包含当日)</span>
+          </div>
+        </div>
+      </template>
+      <div class="money-wrapper">{{ totalData.new_user_total || '-' }}</div>
+      <div class="flex items-center justify-between">
+        <div>
+        
+          <div>
+            <span class="text-sm">累计充值人数:</span>
+            <span class="text-base">{{ totalData.recharge_user_total || '-' }}人</span>
+          </div>
+         
+        </div>
+       
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { checkPermission } from '@/directives/permission';
+import { InfoFilled } from '@element-plus/icons-vue';
+import { useCountdownTimer } from '@/utils/timerUtils';
+import {
+  statisticUserTodayData,
+  statisticUserHistoryData,
+} from '@/api/dataStatistics/userStatistics'
+
+const todayChargeData = ref({})
+const currentMonth = ref({})
+const lastMonth = ref({})
+const totalData = ref({})
+const rolesIdentify = inject('rolesIdentify')
+const refreshInterface = (): void => {
+  initTodayCharge()
+};
+const timer = useCountdownTimer(60, refreshInterface);
+
+const initTodayCharge = () => {
+ 
+  statisticUserTodayData().then(res => {
+    todayChargeData.value = res.data
+  })
+}
+const init = () => {
+  
+    statisticUserHistoryData().then(res => {
+		currentMonth.value = res.data.month;
+		lastMonth.value = res.data.lastMonth;
+		totalData.value = res.data.history;
+    })
+  // }
+  // if (checkPermission('statistic.chargeTJ.lastMonthCharge')) {
+  //   statisticChargeLastMonthCharge().then(res => {
+  //     lastMonthChargeData.value = res.data;
+  //   })
+  // }
+  // if (checkPermission('statistic.chargeTJ.totalCharge')) {
+  //   statisticChargeTotalCharge().then(res => {
+  //     totalChargeData.value = res.data;
+  //   })
+  // }
+}
+
+onMounted(() => {
+  init()
+  initTodayCharge()
+});
+
+</script>
+
+<style scoped lang="scss">
+.box-card {
+  width: 300px;
+  margin: 8px;
+
+  .money-wrapper {
+    height: 50px;
+    width: 100%;
+    color: #ed892c;
+    font-size: 26px;
+  }
+}
+
+.card-wrapper {
+  background-color: #ffffff;
+  margin-bottom: 8px;
+  padding: 16px;
+}
+</style>