279 lines
7.2 KiB
Vue
279 lines
7.2 KiB
Vue
<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="datetimerange" v-model="dateTabs.time" :end="Date.now()" return-type="timestamp" :clear-icon="false" class="uni-stat-datetime-picker" @change="datePickerChange" />
|
||
</view>
|
||
<uni-stat-tabs type="box" :current="statTabs.index" :tabs="statTabs.list" @change="statTabsChange" />
|
||
<view class="uni-charts-box">
|
||
<qiun-data-charts type="area" :chartData="chartData" :opts="opts" :errorMessage="errorMessage"/>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import {
|
||
formatterData, // 格式化字段数据
|
||
fillTrendChartData,
|
||
stringifyQuery, // 对象转JQL查询字符串
|
||
parseDateTime, // 格式化时间
|
||
debounce, // 防抖函数
|
||
stringifyField,
|
||
stringifyGroupField,
|
||
getTimeOfSomeDayAgo,
|
||
} from '@/js_sdk/uni-stat/util.js'
|
||
import timeUtil from "@/js_sdk/uni-stat/timeUtil.js"
|
||
import {
|
||
fieldsGroupMap,
|
||
} from '../fieldsMap.js'
|
||
let statTabsList = [];
|
||
fieldsGroupMap.forEach(item => {
|
||
const _id = item.group
|
||
const name = item.title
|
||
if (_id && name) {
|
||
statTabsList.push({
|
||
_id,
|
||
name,
|
||
list: item.list
|
||
})
|
||
}
|
||
});
|
||
|
||
export default {
|
||
props: {
|
||
query: {
|
||
type: [Object],
|
||
default: function(){
|
||
return {}
|
||
}
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
tableName: 'uni-stat-pay-result',
|
||
chartData: {},
|
||
errorMessage: "",
|
||
opts: {
|
||
color: ["#1890FF","#91CB74","#FAC858","#EE6666","#73C0DE","#3CA272","#FC8452","#9A60B4","#ea7ccc"],
|
||
padding: [15,15,0,15],
|
||
legend: {},
|
||
enableScroll: true,
|
||
dataLabel: false, // 是否显示数据标签
|
||
xAxis: {
|
||
disableGrid: true,
|
||
itemCount: 24,
|
||
fontSize:12,
|
||
boundaryGap:"center", // center justify
|
||
},
|
||
yAxis: {
|
||
gridType: "dash",
|
||
dashLength: 2,
|
||
data:[
|
||
{
|
||
tofix:2
|
||
}
|
||
]
|
||
},
|
||
extra: {
|
||
area: {
|
||
type: "straight",
|
||
opacity: 0.2,
|
||
addLine: true,
|
||
width: 2,
|
||
gradient: false,
|
||
},
|
||
},
|
||
legend:{
|
||
position:"bottom"
|
||
}
|
||
},
|
||
// 时间选项
|
||
dateTabs: {
|
||
time: [],
|
||
timeStr:"",
|
||
index: 2, // 默认最近7天
|
||
list: [
|
||
{ _id: 1, name: '昨天', dimension:"hour" },
|
||
{ _id: 0, name: '今天', dimension:"hour" },
|
||
{ _id: 7, name: '最近七天', dimension:"day" },
|
||
{ _id: 30, name: '最近30天', dimension:"day" },
|
||
{ _id: 90, name: '最近90天', dimension:"day" },
|
||
{ _id: 372, name: '月纬度', dimension:"month" },
|
||
{ _id: 1116, name: '季纬度', dimension:"quarter" },
|
||
{ _id: 4392, name: '年纬度', dimension:"year" },
|
||
]
|
||
},
|
||
statTabs:{
|
||
index: 0,
|
||
list: statTabsList
|
||
},
|
||
queryMode: 0
|
||
}
|
||
},
|
||
created() {
|
||
this.getCloudDataDebounce = debounce(() => {
|
||
this.getCloudData();
|
||
}, 300);
|
||
this.getCloudDataDebounce();
|
||
},
|
||
methods: {
|
||
// 获取云端数据
|
||
getCloudData(obj={}) {
|
||
let query = this.query;
|
||
if (!query.appid){
|
||
this.errorMessage = "请先选择应用";
|
||
return; // 如果appid为空,则不进行查询
|
||
}
|
||
this.errorMessage = "";
|
||
let insideQuery = this.getWhere();
|
||
let where = {
|
||
...query,
|
||
...insideQuery
|
||
};
|
||
let fieldsMap = this.statTabs.list[this.statTabs.index].list;
|
||
where = stringifyQuery(where, true, ['uni_platform']);
|
||
//console.log('trendChart-where: ', where);
|
||
const db = uniCloud.database();
|
||
db.collection(this.tableName)
|
||
.where(where)
|
||
.field(`${stringifyField(fieldsMap)}, start_time`)
|
||
.groupBy(`start_time`)
|
||
.groupField(stringifyGroupField(fieldsMap))
|
||
.orderBy('start_time', 'asc')
|
||
.limit(100)
|
||
.get({
|
||
getCount: true
|
||
})
|
||
.then(res => {
|
||
let {
|
||
count,
|
||
data
|
||
} = res.result;
|
||
data = fillTrendChartData(data, insideQuery, fieldsMap); // 补全数据
|
||
// 数据格式化
|
||
data = formatterData({
|
||
fieldsMap,
|
||
data,
|
||
formatter: false
|
||
});
|
||
//console.log('trendChartData: ', data)
|
||
this.setChartData(data, fieldsMap, insideQuery);
|
||
}).catch((err) => {
|
||
console.error(err);
|
||
}).finally(() => {})
|
||
},
|
||
// 设置图表数据
|
||
setChartData(data, fieldsMap, insideQuery){
|
||
let chartData = {
|
||
categories: [],
|
||
series: []
|
||
};
|
||
fieldsMap.map((item, index) => {
|
||
if (item.trendChart) {
|
||
chartData.series.push({
|
||
name: item.title,
|
||
data:[]
|
||
});
|
||
}
|
||
});
|
||
for (const item of data) {
|
||
const x = this.formatDate(item.start_time, insideQuery.dimension);
|
||
chartData.categories.push(x);
|
||
fieldsMap.map((item2, index) => {
|
||
if (item2.trendChart) {
|
||
let y = Number(item[item2.field]);
|
||
chartData.series[index].data.push(y);
|
||
}
|
||
});
|
||
}
|
||
this.chartData = chartData;
|
||
},
|
||
formatDate(date, type){
|
||
let d = new Date(date);
|
||
let year = d.getFullYear();
|
||
let month = d.getMonth() + 1;
|
||
let day = d.getDate();
|
||
let hour = d.getHours();
|
||
let quarter = Math.floor((d.getMonth() + 3) / 3); //季度
|
||
if (month < 10) month = "0"+ month;
|
||
if (day < 10) day = "0"+ day;
|
||
if (type === 'hour') {
|
||
return `${hour}时`;
|
||
} else if (type === 'month') {
|
||
return `${year}-${month}`;
|
||
} else if (type === 'quarter') {
|
||
return `${year}/Q${quarter}`;
|
||
} else if (type === 'year') {
|
||
return `${year}`;
|
||
} else {
|
||
return parseDateTime(d);
|
||
}
|
||
},
|
||
// 监听 - 日期选择更改
|
||
datePickerChange(time) {
|
||
this.dateTabs.time = time;
|
||
//this.dateTabs.index = null;
|
||
this.queryMode = 1;
|
||
this.getCloudData();
|
||
},
|
||
// 监听 - 日期选择更改
|
||
dateTabsChange(id, index) {
|
||
this.dateTabs.index = index;
|
||
this.queryMode = 0;
|
||
this.getCloudData();
|
||
},
|
||
// 监听 - 统计字段纬度更改
|
||
statTabsChange(id, index, name) {
|
||
this.statTabs.index = index;
|
||
this.getCloudData({
|
||
field: id,
|
||
name
|
||
});
|
||
},
|
||
// 获取查询条件
|
||
getWhere() {
|
||
const day = 24 * 60 * 60 * 1000;
|
||
let start_time = [];
|
||
let item = this.dateTabs.list[this.dateTabs.index] || {};
|
||
if (typeof item._id === "number" && this.queryMode === 0) {
|
||
let start = getTimeOfSomeDayAgo(item._id);
|
||
let end = timeUtil.getOffsetStartAndEnd("day", 0).endTime; // end默认=今天的截止时间
|
||
if (item._id == 1) {
|
||
// 如果是查昨天,则特殊处理下,end=昨天的截止时间
|
||
end = timeUtil.getOffsetStartAndEnd("day", 0, start).endTime;
|
||
}
|
||
start_time = [start, end];
|
||
} else if (this.dateTabs.time){
|
||
start_time = this.dateTabs.time; // 当前选择的时间
|
||
}
|
||
let dimension = item.dimension || "day"; // 获取时间纬度
|
||
this.dateTabs.timeStr = `${timeUtil.timeFormat(start_time[0])} ~ ${timeUtil.timeFormat(start_time[1])}`;
|
||
this.dateTabs.time = start_time;
|
||
return {
|
||
dimension, // 时间纬度
|
||
start_time, // 时间范围
|
||
}
|
||
}
|
||
},
|
||
watch: {
|
||
query: {
|
||
deep: true,
|
||
handler(val) {
|
||
this.getCloudDataDebounce();
|
||
}
|
||
}
|
||
},
|
||
computed: {
|
||
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.justify-center{
|
||
justify-content: center;
|
||
}
|
||
</style>
|