123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- <template>
- <view class="uni-stat--x p-m">
- <view class="uni-stat-card-header">漏斗分析</view>
- <!-- 时间纬度 -->
- <view class="flex">
- <uni-stat-tabs type="box" :current="dateTabs.index" :tabs="dateTabs.list" @change="dateTabsChange" />
- <uni-datetime-picker type="date" v-model="dateTabs.time" :end="Date.now()" return-type="timestamp" :clear-icon="false" class="uni-stat-datetime-picker" @change="datePickerChange" />
- <view class="uni-stat--tips" v-if="dateTabs.timeStr">当前时间范围:{{ dateTabs.timeStr }}</view>
- </view>
- <!-- 漏斗 -->
- <view class="uni-charts-box" v-if="!notData">
- <qiun-data-charts type="funnel" :chartData="chartData" :opts="opts" :errorMessage="errorMessage" />
- </view>
- <view class="uni-charts-box flex center" v-else>
- <view >暂无数据</view>
- </view>
- </view>
- </template>
- <script>
- import {
- mapfields,
- stringifyQuery,
- stringifyField,
- stringifyGroupField,
- getTimeOfSomeDayAgo,
- division,
- format,
- formatDate,
- parseDateTime,
- getFieldTotal,
- debounce
- } from '@/js_sdk/uni-stat/util.js'
- import timeUtil from "@/js_sdk/uni-stat/timeUtil.js"
- import {
- fieldsMap,
- } from '../fieldsMap.js'
- export default {
- props: {
- // 组件外部查询条件,一般包含 appid version_id platform_id
- query: {
- type: [Object],
- default: function() {
- return {}
- }
- }
- },
- data() {
- return {
- tableName: 'uni-stat-pay-result',
- fieldsMap,
- chartData: {},
- errorMessage:"",
- notData: false,
- opts: {
- color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272", "#FC8452", "#9A60B4", "#ea7ccc"],
- padding: [15, 15, 0, 15],
- extra: {
- funnel: {
- activeOpacity: 0.3,
- activeWidth: 10,
- border: true,
- borderWidth: 2,
- borderColor: "#FFFFFF",
- fillOpacity: 1,
- labelAlign: "right",
- linearType: "custom",
- minSize: 20
- }
- }
- },
- // 时间选项
- dateTabs: {
- time: Date.now(),
- timeStr:"",
- index: 0,
- list: [
- { _id: "day", name: '日维度' },
- { _id: "week", name: '周维度' },
- { _id: "month", name: '月维度' }
- ]
- }
- }
- },
- created() {
- this.getCloudDataDebounce = debounce(() => {
- this.getCloudData();
- }, 400);
- this.getCloudDataDebounce();
- },
- methods: {
- calcPercentage(v1, v2) {
- return v2 > 0 ? parseFloat((v1 / v2 * 100).toFixed(2)) : 0;
- },
- // 获取云端数据
- getCloudData() {
- let query = this.query;
- if (!query.appid){
- this.errorMessage = "请先选择应用";
- return;
- }
- this.errorMessage = "";
- let insideQuery = this.getWhere();
- let where = {
- ...query,
- ...insideQuery
- };
- const day = 24 * 60 * 60 * 1000;
- let start_time;
- where = stringifyQuery(where, false, ['uni_platform']);
- //console.log('where: ', where);
- const db = uniCloud.database();
- const subTable = db.collection(this.tableName)
- .where(where)
- .field(`${stringifyField(fieldsMap)}, dimension, stat_date.date_str as stat_time, start_time`)
- .groupBy(`null`)
- .groupField(stringifyGroupField(fieldsMap))
- .get()
- .then(res => {
- let data = res.result.data;
- if (!data.length) {
- this.errorMessage = "暂无数据";
- return;
- }
- this.errorMessage = "";
- //console.log('data: ', data);
- data.map((item) => {
- for (let key in item) {
- if (key.indexOf("_amount") > 1) {
- item[key] = Number((item[key] / 100).toFixed(2));
- }
- }
- });
- let {
- activity_device_count = 0,
- activity_user_count = 0,
- pay_user_count = 0,
- } = data[0] || {};
- this.notData = !activity_device_count && !activity_user_count && !pay_user_count ? true : false;
- let chartData = {
- series: [{
- data: [
- {
- "name": "活跃设备数量",
- "value": activity_device_count,
- "centerText": `${activity_device_count}`,
"labelText": `活跃设备数`
- },
- {
- "name": "活跃用户数量",
- "value": activity_user_count,
- "centerText": `${activity_user_count}`,
- "labelText": `活跃用户数(用户转化率:${this.calcPercentage(activity_user_count,activity_device_count)}%)`
- },
- {
- "name": "支付用户数量",
- "value": pay_user_count,
- "centerText": `${pay_user_count}`,
- "labelText": `支付用户数(支付转化率:${this.calcPercentage(pay_user_count,activity_user_count)}%)`,
- },
- ],
- }]
- };
- this.chartData = chartData;
- })
- },
- // 监听 - 日期标签更改
- dateTabsChange(id, index) {
- this.dateTabs.index = index;
- this.getCloudData();
- },
- // 监听 - 日期选择更改
- datePickerChange(time) {
- this.dateTabs.time = time;
- this.getCloudData();
- },
- // 获取查询条件
- getWhere() {
- let time = this.dateTabs.time; // 当前选择的时间
- let dimension = this.dateTabs.list[this.dateTabs.index]._id || "day"; // 获取时间纬度
- let start_time = [];
- if (dimension === "day") {
- let { startTime, endTime } = timeUtil.getOffsetStartAndEnd("day", 0, time);
- start_time = [startTime, endTime];
- } else if (dimension === "week") {
- let { startTime, endTime } = timeUtil.getOffsetStartAndEnd("week",0, time);
- start_time = [startTime, endTime];
- } else if (dimension === "month") {
- let { startTime, endTime } = timeUtil.getOffsetStartAndEnd("month", 0, time);
- start_time = [startTime, endTime];
- }
- this.dateTabs.timeStr = `${timeUtil.timeFormat(start_time[0])} ~ ${timeUtil.timeFormat(start_time[1])}`;
- return {
- dimension, // 时间纬度
- start_time, // 时间范围
- }
- }
- },
- watch: {
- query: {
- deep: true,
- handler(val) {
- this.getCloudDataDebounce();
- }
- }
- },
- computed: {
- }
- }
- </script>
- <style lang="scss" scoped>
- .flex.center{
- justify-content: center;
- align-items: center;
- color: #666;
- }
- </style>
|