574 lines
17 KiB
Vue
574 lines
17 KiB
Vue
|
<template>
|
|||
|
<!-- 对应页面: app崩溃 -->
|
|||
|
<view class="fix-top-window">
|
|||
|
<view class="uni-header">
|
|||
|
<uni-stat-breadcrumb class="uni-stat-breadcrumb-on-phone" />
|
|||
|
<view class="uni-group hide-on-phone">
|
|||
|
<view class="uni-sub-title">开发者可以在这里快速查询原生应用最近出现的具体崩溃内容,了解崩溃概况信息,以便快速修复问题</view>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
<view class="uni-container">
|
|||
|
<view class="uni-stat--x flex p-1015">
|
|||
|
<view class="uni-stat--app-select">
|
|||
|
<uni-data-select collection="opendb-app-list" field="appid as value, name as text" orderby="text asc" :defItem="1" label="应用选择" v-model="query.appid" :clear="false" />
|
|||
|
<uni-data-select ref="app-versions" collection="opendb-app-versions" :where="versionQuery" class="ml-m" field="_id as value, version as text, uni_platform as label, create_date as date" format="{label} - {text}" orderby="date desc" label="版本选择" v-model="query.version_id" />
|
|||
|
</view>
|
|||
|
<uni-stat-tabs label="平台选择" type="boldLine" :all="false" mode="platform-channel" v-model="query.platform_id" @change="changePlatform" />
|
|||
|
</view>
|
|||
|
<view class="uni-stat--x flex">
|
|||
|
<uni-stat-tabs label="日期选择" :current="currentDateTab" :yesterday="false" mode="date" @change="changeTimeRange" />
|
|||
|
<uni-datetime-picker type="datetimerange" :end="new Date().getTime()" v-model="query.start_time"
|
|||
|
returnType="timestamp" :clearIcon="false" class="uni-stat-datetime-picker"
|
|||
|
:class="{'uni-stat__actived': currentDateTab < 0 && !!query.start_time.length}"
|
|||
|
@change="useDatetimePicker" />
|
|||
|
</view>
|
|||
|
<view class="uni-stat--x" style="padding: 15px 0;">
|
|||
|
<uni-stat-panel :items="panelData" class="uni-stat-panel" />
|
|||
|
<uni-stat-tabs type="box" v-model="chartTab" :tabs="chartTabs" class="mb-l" />
|
|||
|
<view class="uni-charts-box">
|
|||
|
<qiun-data-charts type="area" :chartData="chartData" :eopts="{notMerge:true}" echartsH5 echartsApp tooltipFormat="tooltipCustom" :errorMessage="errorMessage"/>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
|
|||
|
<view class="uni-stat--x p-m">
|
|||
|
<view class="flex-between">
|
|||
|
<view class="uni-stat-card-header">信息列表</view>
|
|||
|
<view class="uni-group">
|
|||
|
<!-- #ifdef H5 -->
|
|||
|
<download-excel class="hide-on-phone" :fields="exportExcel.fields" :data="exportExcelData"
|
|||
|
:type="exportExcel.type" :name="exportExcel.filename">
|
|||
|
<button class="uni-button" type="primary" size="mini">导出 Excel</button>
|
|||
|
</download-excel>
|
|||
|
<!-- #endif -->
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
|
|||
|
<unicloud-db ref="udb" :collection="collectionList"
|
|||
|
field="appid,version,platform,channel,sdk_version,device_id,device_net,device_os,device_os_version,device_vendor,device_model,device_is_root,device_os_name,device_batt_level,device_batt_temp,device_memory_use_size,device_memory_total_size,device_disk_use_size,device_disk_total_size,device_abis,app_count,app_use_memory_size,app_webview_count,app_use_duration,app_run_fore,package_name,package_version,page_url,error_msg,create_time"
|
|||
|
:where="where" page-data="replace" :orderby="orderby" :getcount="true" :page-size="options.pageSize"
|
|||
|
:page-current="options.pageCurrent" loadtime="manual"
|
|||
|
v-slot:default="{data,pagination,loading,error,options}" :options="options" @load="onqueryload">
|
|||
|
<uni-table ref="table" :loading="loading" border stripe :emptyText="errorMessage || $t('common.empty')"
|
|||
|
style="overflow-y: scroll;">
|
|||
|
<uni-tr>
|
|||
|
<block v-for="(mapper, index) in fieldsMap" :key="index">
|
|||
|
<uni-th v-if="mapper.title" :key="index" align="center"
|
|||
|
:style="{'minWidth':`${mapper.title.length * 15 + 80}px`}">
|
|||
|
<!-- #ifdef MP -->
|
|||
|
{{mapper.title}}
|
|||
|
<!-- #endif -->
|
|||
|
<!-- #ifndef MP -->
|
|||
|
<uni-tooltip>
|
|||
|
{{mapper.title}}
|
|||
|
<uni-icons v-if="mapper.tooltip" type="help" color="#666" />
|
|||
|
<template v-if="mapper.tooltip" v-slot:content>
|
|||
|
<view class="uni-stat-tooltip-s">
|
|||
|
{{mapper.tooltip}}
|
|||
|
</view>
|
|||
|
</template>
|
|||
|
</uni-tooltip>
|
|||
|
<!-- #endif -->
|
|||
|
</uni-th>
|
|||
|
</block>
|
|||
|
</uni-tr>
|
|||
|
<uni-tr v-for="(item ,i) in tableData" :key="i">
|
|||
|
<block v-for="(mapper, index) in fieldsMap" :key="index">
|
|||
|
<uni-td v-if="mapper.field === 'error_msg'" :key="mapper.field" align="left"
|
|||
|
style="min-width: 500px;">
|
|||
|
<!-- #ifdef MP -->
|
|||
|
{{item.error_msg ? item.error_msg.substring(0, 100) + '...' : '-'}}
|
|||
|
<!-- #endif -->
|
|||
|
<!-- #ifndef MP -->
|
|||
|
<uni-tooltip>
|
|||
|
{{item.error_msg ? item.error_msg.substring(0, 100) + '...' : ''}}
|
|||
|
<uni-icons v-if="item.error_msg" type="help" color="#666" />
|
|||
|
<template v-if="item.error_msg" v-slot:content>
|
|||
|
<view class="uni-stat-tooltip-l">
|
|||
|
{{item.error_msg}}
|
|||
|
</view>
|
|||
|
</template>
|
|||
|
</uni-tooltip>
|
|||
|
<!-- #endif -->
|
|||
|
</uni-td>
|
|||
|
<uni-td v-else-if="mapper.field === 'create_time'" :key="mapper.field" align="center">
|
|||
|
<uni-dateformat :threshold="[0, 0]" :date="item.create_time"></uni-dateformat>
|
|||
|
</uni-td>
|
|||
|
<uni-td v-else :key="mapper.field" align="center">
|
|||
|
{{item[mapper.field] !== undefined ? item[mapper.field] : '-'}}
|
|||
|
</uni-td>
|
|||
|
</block>
|
|||
|
</uni-tr>
|
|||
|
</uni-table>
|
|||
|
<view class="uni-pagination-box">
|
|||
|
<uni-pagination show-icon :page-size="pagination.size" v-model="pagination.current"
|
|||
|
:total="pagination.count" @change="onPageChanged" />
|
|||
|
</view>
|
|||
|
</unicloud-db>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
|
|||
|
<!-- #ifndef H5 -->
|
|||
|
<fix-window />
|
|||
|
<!-- #endif -->
|
|||
|
</view>
|
|||
|
</template>
|
|||
|
|
|||
|
<script>
|
|||
|
import {
|
|||
|
mapfields,
|
|||
|
stringifyQuery,
|
|||
|
getTimeOfSomeDayAgo,
|
|||
|
division,
|
|||
|
format,
|
|||
|
formatDate,
|
|||
|
parseDateTime,
|
|||
|
debounce,
|
|||
|
getAllDateCN
|
|||
|
} from '@/js_sdk/uni-stat/util.js'
|
|||
|
import {
|
|||
|
fieldsMap,
|
|||
|
} from './fieldsMap.js'
|
|||
|
|
|||
|
const panelOption = [{
|
|||
|
title: '崩溃总数',
|
|||
|
field: 'count',
|
|||
|
value: 0,
|
|||
|
formatter: ',',
|
|||
|
tooltip: '指原生应用在某个时间段内出现崩溃的总数'
|
|||
|
}, {
|
|||
|
title: '崩溃率',
|
|||
|
field: 'count/app_launch_count',
|
|||
|
computed: 'count/app_launch_count',
|
|||
|
formatter: '%',
|
|||
|
value: 0,
|
|||
|
tooltip: '时间范围内的总崩溃数/原生应用启动次数,如果小于0.01%,默认显示为0'
|
|||
|
}]
|
|||
|
|
|||
|
import {
|
|||
|
enumConverter,
|
|||
|
filterToWhere
|
|||
|
} from '@/js_sdk/validator/uni-stat-app-crash-logs.js';
|
|||
|
|
|||
|
const db = uniCloud.database()
|
|||
|
// 表查询配置
|
|||
|
const dbOrderBy = 'create_time desc' // 排序字段
|
|||
|
const dbSearchFields = [] // 模糊搜索字段,支持模糊搜索的字段列表。联表查询格式: 主表字段名.副表字段名,例如用户表关联角色表 role.role_name
|
|||
|
// 分页配置
|
|||
|
const pageSize = 20
|
|||
|
const pageCurrent = 1
|
|||
|
|
|||
|
const orderByMapping = {
|
|||
|
"ascending": "asc",
|
|||
|
"descending": "desc"
|
|||
|
}
|
|||
|
|
|||
|
export default {
|
|||
|
data() {
|
|||
|
return {
|
|||
|
fieldsMap,
|
|||
|
//todo:要与schema 生成页面一起工作,stringifyQuery 需要与 schema 查询逻辑相容
|
|||
|
query: {
|
|||
|
type: "crash",
|
|||
|
dimension: "day",
|
|||
|
appid: "",
|
|||
|
platform_id: '',
|
|||
|
uni_platform: '',
|
|||
|
version_id: '',
|
|||
|
start_time: [],
|
|||
|
},
|
|||
|
loading: false,
|
|||
|
popupLoading: false,
|
|||
|
currentDateTab: 0,
|
|||
|
// currentChartTab: ,
|
|||
|
tableData: [],
|
|||
|
popupTableData: [],
|
|||
|
panelData: JSON.parse(JSON.stringify(panelOption)),
|
|||
|
chartData: {},
|
|||
|
chartTab: 'errorCount',
|
|||
|
chartTabs: [{
|
|||
|
_id: 'errorCount',
|
|||
|
name: '崩溃次数'
|
|||
|
}, {
|
|||
|
_id: 'errorRate',
|
|||
|
name: '崩溃率'
|
|||
|
}],
|
|||
|
|
|||
|
collectionList: "uni-stat-app-crash-logs",
|
|||
|
schemaQuery: '',
|
|||
|
where: this.tableData,
|
|||
|
orderby: dbOrderBy,
|
|||
|
orderByFieldName: "",
|
|||
|
selectedIndexs: [],
|
|||
|
options: {
|
|||
|
pageCurrent: 1, // 当前页
|
|||
|
total: 0, // 数据总量
|
|||
|
pageSizeIndex: 0, // 与 pageSizeRange 一起计算得出 pageSize
|
|||
|
pageSizeRange: [10, 20, 50, 100],
|
|||
|
pageSize,
|
|||
|
pageCurrent,
|
|||
|
filterData: {},
|
|||
|
...enumConverter
|
|||
|
},
|
|||
|
errorMessage: "",
|
|||
|
exportExcel: {
|
|||
|
"filename": "uni-stat-app-crash-logs.xls",
|
|||
|
"type": "xls",
|
|||
|
"fields": {
|
|||
|
"appid": "appid",
|
|||
|
"version": "version",
|
|||
|
"platform": "platform",
|
|||
|
"channel": "channel",
|
|||
|
"sdk_version": "sdk_version",
|
|||
|
"device_id": "device_id",
|
|||
|
"device_net": "device_net",
|
|||
|
"device_os": "device_os",
|
|||
|
"device_os_version": "device_os_version",
|
|||
|
"device_vendor": "device_vendor",
|
|||
|
"device_model": "device_model",
|
|||
|
"device_is_root": "device_is_root",
|
|||
|
"device_os_name": "device_os_name",
|
|||
|
"device_batt_level": "device_batt_level",
|
|||
|
"device_batt_temp": "device_batt_temp",
|
|||
|
"device_memory_use_size": "device_memory_use_size",
|
|||
|
"device_memory_total_size": "device_memory_total_size",
|
|||
|
"device_disk_use_size": "device_disk_use_size",
|
|||
|
"device_disk_total_size": "device_disk_total_size",
|
|||
|
"device_abis": "device_abis",
|
|||
|
"app_count": "app_count",
|
|||
|
"app_use_memory_size": "app_use_memory_size",
|
|||
|
"app_webview_count": "app_webview_count",
|
|||
|
"app_use_duration": "app_use_duration",
|
|||
|
"app_run_fore": "app_run_fore",
|
|||
|
"package_name": "package_name",
|
|||
|
"package_version": "package_version",
|
|||
|
"page_url": "page_url",
|
|||
|
"error_msg": "error_msg",
|
|||
|
"create_time": "create_time"
|
|||
|
}
|
|||
|
},
|
|||
|
exportExcelData: []
|
|||
|
}
|
|||
|
},
|
|||
|
computed: {
|
|||
|
queryStr() {
|
|||
|
return stringifyQuery(this.query)
|
|||
|
},
|
|||
|
tableQuery() {
|
|||
|
const {
|
|||
|
appid,
|
|||
|
platform_id,
|
|||
|
version_id,
|
|||
|
start_time
|
|||
|
} = this.query
|
|||
|
|
|||
|
// 从本地存储中取到数据做过滤
|
|||
|
const platform = this.getPlatform(platform_id);
|
|||
|
const version = this.getVersion(version_id);
|
|||
|
|
|||
|
const query = stringifyQuery({
|
|||
|
appid,
|
|||
|
create_time: start_time,
|
|||
|
platform: platform,
|
|||
|
version: version
|
|||
|
})
|
|||
|
//console.log('query: ', query)
|
|||
|
return query
|
|||
|
},
|
|||
|
versionQuery() {
|
|||
|
const {
|
|||
|
appid,
|
|||
|
uni_platform
|
|||
|
} = this.query
|
|||
|
const query = stringifyQuery({
|
|||
|
appid,
|
|||
|
uni_platform,
|
|||
|
type: 'native_app'
|
|||
|
})
|
|||
|
//console.log('query: ', query)
|
|||
|
return query
|
|||
|
}
|
|||
|
},
|
|||
|
created() {
|
|||
|
this.debounceGet = debounce(() => {
|
|||
|
this.getAllData(this.queryStr)
|
|||
|
this.where = this.tableQuery
|
|||
|
this.$nextTick(() => {
|
|||
|
this.$refs.udb && this.$refs.udb.loadData()
|
|||
|
}, 200)
|
|||
|
},300);
|
|||
|
this.debounceGet();
|
|||
|
},
|
|||
|
watch: {
|
|||
|
query: {
|
|||
|
deep: true,
|
|||
|
handler(val) {
|
|||
|
this.options.pageCurrent = 1 // 重置分页
|
|||
|
this.debounceGet()
|
|||
|
}
|
|||
|
},
|
|||
|
chartTab(val) {
|
|||
|
this.getChartData(this.queryStr)
|
|||
|
}
|
|||
|
},
|
|||
|
onLoad() {
|
|||
|
this._filter = {}
|
|||
|
},
|
|||
|
methods: {
|
|||
|
onqueryload(data) {
|
|||
|
this.exportExcelData = data
|
|||
|
this.tableData = data
|
|||
|
},
|
|||
|
getWhere() {
|
|||
|
const query = this.schemaQuery.trim()
|
|||
|
if (!query) {
|
|||
|
return ''
|
|||
|
}
|
|||
|
const queryRe = new RegExp(query, 'i')
|
|||
|
return dbSearchFields.map(name => queryRe + '.test(' + name + ')').join(' || ')
|
|||
|
},
|
|||
|
loadData(clear = true) {
|
|||
|
this.$refs.udb.loadData({
|
|||
|
clear
|
|||
|
})
|
|||
|
},
|
|||
|
onPageChanged(e) {
|
|||
|
this.selectedIndexs.length = 0
|
|||
|
this.$refs.table.clearSelection()
|
|||
|
this.$refs.udb.loadData({
|
|||
|
current: e.current
|
|||
|
})
|
|||
|
},
|
|||
|
sortChange(e, name) {
|
|||
|
this.orderByFieldName = name;
|
|||
|
if (e.order) {
|
|||
|
this.orderby = name + ' ' + orderByMapping[e.order]
|
|||
|
} else {
|
|||
|
this.orderby = ''
|
|||
|
}
|
|||
|
this.$refs.table.clearSelection()
|
|||
|
this.$nextTick(() => {
|
|||
|
this.$refs.udb.loadData()
|
|||
|
})
|
|||
|
},
|
|||
|
filterChange(e, name) {
|
|||
|
this._filter[name] = {
|
|||
|
type: e.filterType,
|
|||
|
value: e.filter
|
|||
|
}
|
|||
|
let newWhere = filterToWhere(this._filter, db.command)
|
|||
|
if (Object.keys(newWhere).length) {
|
|||
|
this.where = newWhere
|
|||
|
} else {
|
|||
|
this.where = ''
|
|||
|
// this.where = this.tableQuery
|
|||
|
}
|
|||
|
this.$nextTick(() => {
|
|||
|
this.$refs.udb.loadData()
|
|||
|
})
|
|||
|
},
|
|||
|
useDatetimePicker() {
|
|||
|
this.currentDateTab = -1
|
|||
|
},
|
|||
|
changePlatform(id, index, name, item) {
|
|||
|
this.query.version_id = 0
|
|||
|
this.query.uni_platform = item.code
|
|||
|
},
|
|||
|
changeTimeRange(id, index) {
|
|||
|
this.currentDateTab = index
|
|||
|
const start = getTimeOfSomeDayAgo(id),
|
|||
|
end = getTimeOfSomeDayAgo(0) - 1
|
|||
|
this.query.start_time = [start, end]
|
|||
|
},
|
|||
|
|
|||
|
getPlatform(platform_id){
|
|||
|
const statTabsData = uni.getStorageSync('uni-admin-statTabsData');
|
|||
|
const platforms = statTabsData["platform-channel"];
|
|||
|
const p = Array.isArray(platforms) && platforms.find(p => p._id === platform_id)
|
|||
|
return p && p.code || '';
|
|||
|
},
|
|||
|
getVersion(version_id){
|
|||
|
let versions = [];
|
|||
|
if (this.$refs["app-versions"] && typeof this.$refs["app-versions"].getLoadData === "function") {
|
|||
|
versions = this.$refs["app-versions"].getLoadData();
|
|||
|
}
|
|||
|
const v = Array.isArray(versions) && versions.find(v => v._id === version_id);
|
|||
|
return v && v.text || '';
|
|||
|
},
|
|||
|
|
|||
|
getAllData(query) {
|
|||
|
if (query.indexOf("appid") === -1) {
|
|||
|
this.errorMessage = "请先选择应用";
|
|||
|
return; // 如果appid为空,则不进行查询
|
|||
|
}
|
|||
|
this.errorMessage = "";
|
|||
|
this.getPanelData(query)
|
|||
|
this.getChartData(query)
|
|||
|
},
|
|||
|
|
|||
|
getPanelData(query) {
|
|||
|
let querystr = stringifyQuery(this.query, false, ['uni_platform'])
|
|||
|
const db = uniCloud.database()
|
|||
|
db.collection('uni-stat-error-result')
|
|||
|
.where(querystr)
|
|||
|
.field('count as temp_count, app_launch_count as temp_app_launch_count, appid')
|
|||
|
.groupBy('appid')
|
|||
|
.groupField('sum(temp_count) as count, sum(temp_app_launch_count) as app_launch_count')
|
|||
|
.get({
|
|||
|
getCount: true
|
|||
|
})
|
|||
|
.then(res => {
|
|||
|
const {
|
|||
|
count,
|
|||
|
data
|
|||
|
} = res.result
|
|||
|
const item = res.result.data[0] || {count:0,app_launch_count:0}
|
|||
|
// this.panelData = []
|
|||
|
let queryTemp = Object.assign({}, this.query)
|
|||
|
delete queryTemp.type
|
|||
|
this.getTotalLaunch(stringifyQuery(queryTemp, false, ['uni_platform'])).then(res => {
|
|||
|
const total = res.result.data[0]
|
|||
|
if (item) {
|
|||
|
let launch_count = total && total.total_app_launch_count
|
|||
|
item.app_launch_count = launch_count
|
|||
|
this.panelData = mapfields(panelOption, item)
|
|||
|
}
|
|||
|
})
|
|||
|
})
|
|||
|
},
|
|||
|
getTotalLaunch(query) {
|
|||
|
const db = uniCloud.database()
|
|||
|
return db.collection('uni-stat-result')
|
|||
|
.where(query)
|
|||
|
.groupBy('appid')
|
|||
|
.groupField('sum(app_launch_count) as total_app_launch_count')
|
|||
|
.get()
|
|||
|
},
|
|||
|
getChartData(query, field = 'day_count') {
|
|||
|
let querystr = stringifyQuery(this.query, false, ['uni_platform'])
|
|||
|
this.chartData = {}
|
|||
|
const {
|
|||
|
pageCurrent
|
|||
|
} = this.options
|
|||
|
const db = uniCloud.database()
|
|||
|
const [start_time, end_tiem] = this.query.start_time
|
|||
|
// 时间补全
|
|||
|
const timeAll = getAllDateCN(new Date(start_time), new Date(end_tiem))
|
|||
|
|
|||
|
db.collection('uni-stat-error-result')
|
|||
|
.where(querystr)
|
|||
|
.field('count as temp_count, app_launch_count as temp_app_launch_count, start_time')
|
|||
|
.groupBy('start_time')
|
|||
|
.groupField('sum(temp_count) as count, sum(temp_app_launch_count) as app_launch_count')
|
|||
|
.orderBy('start_time', 'asc')
|
|||
|
.get({
|
|||
|
getCount: true
|
|||
|
})
|
|||
|
.then(res => {
|
|||
|
const {
|
|||
|
count,
|
|||
|
data
|
|||
|
} = res.result
|
|||
|
let dataAll = []
|
|||
|
timeAll.forEach(v => {
|
|||
|
let item = data.find(item => item.start_time === v)
|
|||
|
if (item) {
|
|||
|
dataAll.push(item)
|
|||
|
} else {
|
|||
|
dataAll.push({
|
|||
|
app_launch_count: 0,
|
|||
|
count: 0,
|
|||
|
start_time: v
|
|||
|
})
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
|
|||
|
const options = {
|
|||
|
categories: [],
|
|||
|
series: [{
|
|||
|
name: '暂无数据',
|
|||
|
data: []
|
|||
|
}]
|
|||
|
}
|
|||
|
if (this.chartTab === 'errorCount') {
|
|||
|
const countLine = options.series[0] = {
|
|||
|
name: '崩溃次数',
|
|||
|
data: []
|
|||
|
}
|
|||
|
const xAxis = options.categories
|
|||
|
for (const item of dataAll) {
|
|||
|
let date = item.start_time
|
|||
|
const x = formatDate(date, 'day')
|
|||
|
const countY = item.count
|
|||
|
xAxis.push(x)
|
|||
|
countLine.data.push(countY)
|
|||
|
}
|
|||
|
this.chartData = options
|
|||
|
} else {
|
|||
|
const rateLine = options.series[0] = {
|
|||
|
name: '崩溃率(%)',
|
|||
|
data: [],
|
|||
|
lineStyle: {
|
|||
|
color: '#EE6666',
|
|||
|
width: 1,
|
|||
|
},
|
|||
|
itemStyle: {
|
|||
|
borderWidth: 1,
|
|||
|
borderColor: '#EE6666',
|
|||
|
color: '#EE6666'
|
|||
|
},
|
|||
|
areaStyle: {
|
|||
|
color: {
|
|||
|
colorStops: [{
|
|||
|
offset: 0,
|
|||
|
color: '#EE6666', // 0% 处的颜色
|
|||
|
}, {
|
|||
|
offset: 1,
|
|||
|
color: '#FFFFFF' // 100% 处的颜色
|
|||
|
}]
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
const xAxis = options.categories
|
|||
|
for (const item of dataAll) {
|
|||
|
const {
|
|||
|
count,
|
|||
|
app_launch_count
|
|||
|
} = item
|
|||
|
let date = item.start_time
|
|||
|
const x = formatDate(date, 'day')
|
|||
|
xAxis.push(x)
|
|||
|
let y = count / app_launch_count
|
|||
|
y = !y ? 0 : y.toFixed(2)
|
|||
|
rateLine.data.push(y)
|
|||
|
}
|
|||
|
this.chartData = options
|
|||
|
}
|
|||
|
}).finally(() => {})
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
<style>
|
|||
|
.flex-between {
|
|||
|
margin-bottom: 10px;
|
|||
|
display: flex;
|
|||
|
justify-content: space-between;
|
|||
|
align-items: center;
|
|||
|
}
|
|||
|
|
|||
|
.uni-stat-panel {
|
|||
|
box-shadow: unset;
|
|||
|
border-bottom: 1px solid #eee;
|
|||
|
padding: 0;
|
|||
|
margin: 0 15px;
|
|||
|
}
|
|||
|
|
|||
|
.uni-stat-tooltip-s {
|
|||
|
width: 160px;
|
|||
|
white-space: normal;
|
|||
|
}
|
|||
|
</style>
|