|
@@ -113,12 +113,7 @@
|
|
|
v-for="(item, i) in oriData.total"
|
|
|
:key="i + item.key"
|
|
|
class="head-item"
|
|
|
- @click="
|
|
|
- () =>
|
|
|
- item.key !== 'downloads' &&
|
|
|
- type !== item.key &&
|
|
|
- changeData(item.key, item.name)
|
|
|
- "
|
|
|
+ @click="() => changeData(item.key, item.name)"
|
|
|
:style="{
|
|
|
borderTopColor: type === item.key ? '#396fff' : '#fff',
|
|
|
}"
|
|
@@ -207,20 +202,20 @@
|
|
|
|
|
|
<script>
|
|
|
// @ is an alias to /src
|
|
|
-import { getRule, getAppList, getHistory, getSearchData } from "@/api/index";
|
|
|
+import { getRule, getAppList, getHistory, getSearchData } from '@/api/index';
|
|
|
|
|
|
-import countTo from "@/components/counto/vue-countTo.vue";
|
|
|
+import countTo from '@/components/counto/vue-countTo.vue';
|
|
|
|
|
|
-import * as echarts from "echarts/core";
|
|
|
-import { LineChart } from "echarts/charts";
|
|
|
+import * as echarts from 'echarts/core';
|
|
|
+import { LineChart } from 'echarts/charts';
|
|
|
import {
|
|
|
TitleComponent,
|
|
|
TooltipComponent,
|
|
|
GridComponent,
|
|
|
ToolboxComponent,
|
|
|
LegendComponent,
|
|
|
-} from "echarts/components";
|
|
|
-import { CanvasRenderer } from "echarts/renderers";
|
|
|
+} from 'echarts/components';
|
|
|
+import { CanvasRenderer } from 'echarts/renderers';
|
|
|
echarts.use([
|
|
|
TitleComponent,
|
|
|
TooltipComponent,
|
|
@@ -234,18 +229,18 @@ echarts.use([
|
|
|
// import config from "@/config/index";
|
|
|
let chart = undefined;
|
|
|
export default {
|
|
|
- name: "RealOnline",
|
|
|
+ name: 'RealOnline',
|
|
|
data() {
|
|
|
return {
|
|
|
- type: "",
|
|
|
+ type: '',
|
|
|
lastParams: {},
|
|
|
page: 1,
|
|
|
form: {
|
|
|
- app: "",
|
|
|
+ app: '',
|
|
|
version: [],
|
|
|
channel: [],
|
|
|
date: [],
|
|
|
- client: "",
|
|
|
+ client: '',
|
|
|
},
|
|
|
cycle: [],
|
|
|
oriData: {},
|
|
@@ -257,11 +252,11 @@ export default {
|
|
|
},
|
|
|
async mounted() {
|
|
|
if (chart && chart.dispose) chart.dispose();
|
|
|
- const { source, appV, appC, clentV, appli, appCLi, appVLi, clentli } =
|
|
|
+ const { source, appV, appC, clentV, appli, appCLi, appVLi, clentli } =
|
|
|
await this.getAppListFunc();
|
|
|
- const keys = {
|
|
|
- value: "mname",
|
|
|
- label: "mname",
|
|
|
+ const keys = {
|
|
|
+ value: 'mname',
|
|
|
+ label: 'mname',
|
|
|
};
|
|
|
const clentliList = clentli.find(r => r.mdefault) || false;
|
|
|
let client = clentliList ? clentliList.mcode.toString() : -1;
|
|
@@ -272,17 +267,17 @@ export default {
|
|
|
clentli,
|
|
|
clentV,
|
|
|
{
|
|
|
- value: "mcode",
|
|
|
- label: "mname",
|
|
|
+ value: 'mcode',
|
|
|
+ label: 'mname',
|
|
|
},
|
|
|
true
|
|
|
);
|
|
|
this.form = {
|
|
|
// app: (this.cycle[0] || { value: "" }).value,
|
|
|
- app: "起点新闻",
|
|
|
- version: [(this.version[0] || { value: "" }).value],
|
|
|
+ app: '起点新闻',
|
|
|
+ version: [(this.version[0] || { value: '' }).value],
|
|
|
client,
|
|
|
- channel: [(this.channel[0] || { value: "" }).value],
|
|
|
+ channel: [(this.channel[0] || { value: '' }).value],
|
|
|
date: [new Date(Date.now() - 604800000), new Date(Date.now() - 86400000)],
|
|
|
};
|
|
|
this.onSubmit();
|
|
@@ -293,7 +288,7 @@ export default {
|
|
|
if (!obj) return;
|
|
|
let li = list || [];
|
|
|
const out = [];
|
|
|
- more && out.push({ value: -1, label: "不限" });
|
|
|
+ more && out.push({ value: -1, label: '不限' });
|
|
|
for (let i = 0; i < li.length; i++) {
|
|
|
const v = li[i];
|
|
|
if (verify.length !== 0 && !verify[v.mcode]) continue;
|
|
@@ -333,7 +328,7 @@ export default {
|
|
|
let oriData = r || {};
|
|
|
const total = oriData.total || {},
|
|
|
keys = Object.keys(total),
|
|
|
- color = ["rgb(244, 127, 146)", "rgb(17, 160, 248)"],
|
|
|
+ color = ['rgb(244, 127, 146)', 'rgb(17, 160, 248)'],
|
|
|
p = [];
|
|
|
let tab = undefined,
|
|
|
tabName = undefined;
|
|
@@ -341,11 +336,18 @@ export default {
|
|
|
const v = keys[i];
|
|
|
if (!total[v].value && total[v].value !== 0) continue;
|
|
|
let isNum = isNaN(total[v].value);
|
|
|
- let value = "";
|
|
|
- if (isNum && !/次数/g.test(total[v].name) && !/下载量/g.test(total[v].name) && !/装机量/g.test(total[v].name) && !/用户数/g.test(total[v].name) && typeof total[v].value === "number")
|
|
|
+ let value = '';
|
|
|
+ if (
|
|
|
+ isNum &&
|
|
|
+ !/次数/g.test(total[v].name) &&
|
|
|
+ !/下载量/g.test(total[v].name) &&
|
|
|
+ !/装机量/g.test(total[v].name) &&
|
|
|
+ !/用户数/g.test(total[v].name) &&
|
|
|
+ typeof total[v].value === 'number'
|
|
|
+ )
|
|
|
value = this.timeFormat(total[v].value);
|
|
|
else value = total[v].value;
|
|
|
- if (!tab && v !== "downloads") {
|
|
|
+ if (!tab && v !== 'downloads') {
|
|
|
tab = v;
|
|
|
tabName = total[v].name;
|
|
|
}
|
|
@@ -354,7 +356,7 @@ export default {
|
|
|
value,
|
|
|
color: color[i % 2],
|
|
|
key: v,
|
|
|
- isNum
|
|
|
+ isNum,
|
|
|
});
|
|
|
}
|
|
|
this.oriData = {
|
|
@@ -373,6 +375,12 @@ export default {
|
|
|
});
|
|
|
},
|
|
|
changeData(type, title) {
|
|
|
+ const ret = {
|
|
|
+ downloads: true,
|
|
|
+ ip: true
|
|
|
+ };
|
|
|
+ if (this.type === type) return;
|
|
|
+ if (ret[type]) return;
|
|
|
this.type = type;
|
|
|
const keyList = [],
|
|
|
valueList = [];
|
|
@@ -395,19 +403,19 @@ export default {
|
|
|
chart.setOption({
|
|
|
tooltip: {
|
|
|
confine: true,
|
|
|
- trigger: "axis",
|
|
|
+ trigger: 'axis',
|
|
|
formatter(v) {
|
|
|
const item = v[0] || {};
|
|
|
let val = item.data || 0;
|
|
|
if (/duration/.test(_this.type)) val = _this.timeFormat(val);
|
|
|
- return item.axisValue + "<br />" + title + ":" + val;
|
|
|
+ return item.axisValue + '<br />' + title + ':' + val;
|
|
|
},
|
|
|
},
|
|
|
toolbox: {
|
|
|
feature: {
|
|
|
saveAsImage: {
|
|
|
- type: "jpg",
|
|
|
- name: "趋势",
|
|
|
+ type: 'jpg',
|
|
|
+ name: '趋势',
|
|
|
},
|
|
|
},
|
|
|
},
|
|
@@ -415,29 +423,29 @@ export default {
|
|
|
data: [title],
|
|
|
},
|
|
|
grid: {
|
|
|
- left: "3%",
|
|
|
- right: "4%",
|
|
|
- bottom: "3%",
|
|
|
+ left: '3%',
|
|
|
+ right: '4%',
|
|
|
+ bottom: '3%',
|
|
|
containLabel: true,
|
|
|
},
|
|
|
xAxis: {
|
|
|
- type: "category",
|
|
|
+ type: 'category',
|
|
|
boundaryGap: true,
|
|
|
data: keyList,
|
|
|
},
|
|
|
yAxis: {
|
|
|
- type: "value",
|
|
|
+ type: 'value',
|
|
|
scale: true,
|
|
|
minInterval: 1,
|
|
|
axisLabel: {
|
|
|
formatter(v) {
|
|
|
let val = v;
|
|
|
- if (_this.type === "duration") val = _this.timeFormat(val);
|
|
|
+ if (_this.type === 'duration') val = _this.timeFormat(val);
|
|
|
else {
|
|
|
if (val >= 100000000) {
|
|
|
- val = (val / 100000000).toFixed(2) + "亿";
|
|
|
+ val = (val / 100000000).toFixed(2) + '亿';
|
|
|
} else if (val >= 10000) {
|
|
|
- val = (val / 10000).toFixed(2) + "万";
|
|
|
+ val = (val / 10000).toFixed(2) + '万';
|
|
|
}
|
|
|
}
|
|
|
return val;
|
|
@@ -452,12 +460,12 @@ export default {
|
|
|
lineStyle: {
|
|
|
width: 1,
|
|
|
},
|
|
|
- type: "line",
|
|
|
+ type: 'line',
|
|
|
smooth: true,
|
|
|
- color: "rgba(58,132,255,.9)",
|
|
|
+ color: 'rgba(58,132,255,.9)',
|
|
|
areaStyle: {
|
|
|
color: {
|
|
|
- type: "linear",
|
|
|
+ type: 'linear',
|
|
|
x: 0,
|
|
|
y: 0,
|
|
|
x2: 0,
|
|
@@ -465,11 +473,11 @@ export default {
|
|
|
colorStops: [
|
|
|
{
|
|
|
offset: 0,
|
|
|
- color: "rgba(58,132,255, 0.8)", // 0% 处的颜色
|
|
|
+ color: 'rgba(58,132,255, 0.8)', // 0% 处的颜色
|
|
|
},
|
|
|
{
|
|
|
offset: 1,
|
|
|
- color: "rgba(58,132,255, 0.1)", // 100% 处的颜色
|
|
|
+ color: 'rgba(58,132,255, 0.1)', // 100% 处的颜色
|
|
|
},
|
|
|
],
|
|
|
global: false, // 缺省为 false
|
|
@@ -490,19 +498,20 @@ export default {
|
|
|
appCLi = [];
|
|
|
let clentV = { length: 0 },
|
|
|
clentli = [];
|
|
|
- let prvList = r.output && r.output.data ? r.output.data.prvRolectrl || [] : [];
|
|
|
+ let prvList =
|
|
|
+ r.output && r.output.data ? r.output.data.prvRolectrl || [] : [];
|
|
|
for (let i = 0; i < prvList.length; i++) {
|
|
|
const v = prvList[i];
|
|
|
- if (v.controlid == "RMT_SOURCE")
|
|
|
+ if (v.controlid == 'RMT_SOURCE')
|
|
|
(source[v.detid] = true), (source.length = source.length + 1);
|
|
|
- if (v.controlid == "APP_VERSION")
|
|
|
+ if (v.controlid == 'APP_VERSION')
|
|
|
(appV[v.detid] = true), (appV.length = appV.length + 1);
|
|
|
- if (v.controlid == "CHANNEL")
|
|
|
+ if (v.controlid == 'CHANNEL')
|
|
|
(appC[v.detid] = true), (appC.length = appC.length + 1);
|
|
|
- if (v.controlid == "CLIENT_TYPE")
|
|
|
+ if (v.controlid == 'CLIENT_TYPE')
|
|
|
(clentV[v.detid] = true), (clentV.length = clentV.length + 1);
|
|
|
}
|
|
|
- if (li.status === "0") appli = li.output.data || [];
|
|
|
+ if (li.status === '0') appli = li.output.data || [];
|
|
|
if (appVersion.length) appVLi = appVersion || [];
|
|
|
if (channel.length) appCLi = channel || [];
|
|
|
if (clientList.length) clentli = clientList || [];
|
|
@@ -519,42 +528,42 @@ export default {
|
|
|
},
|
|
|
async getAppListOri() {
|
|
|
const roleid = JSON.parse(
|
|
|
- window.parent.localStorage.userinfo || "{}"
|
|
|
+ window.parent.localStorage.userinfo || '{}'
|
|
|
).roleid;
|
|
|
const r = await getRule({
|
|
|
- db: "authplat",
|
|
|
- exportMark: "0",
|
|
|
+ db: 'authplat',
|
|
|
+ exportMark: '0',
|
|
|
menuid: 399,
|
|
|
roleid,
|
|
|
});
|
|
|
// 应用列表
|
|
|
|
|
|
const li = await getAppList({
|
|
|
- exportMark: "0",
|
|
|
- gcode: "SOURCE",
|
|
|
+ exportMark: '0',
|
|
|
+ gcode: 'SOURCE',
|
|
|
pageid: 1,
|
|
|
pagesize: 1000,
|
|
|
});
|
|
|
- const defaultAppName = "起点新闻";
|
|
|
+ const defaultAppName = '起点新闻';
|
|
|
// 应用版本列表
|
|
|
const appVersion = await getSearchData({
|
|
|
- gcode: "APP_VERSION",
|
|
|
+ gcode: 'APP_VERSION',
|
|
|
source: defaultAppName,
|
|
|
});
|
|
|
// 端列表
|
|
|
const clientList = await getSearchData({
|
|
|
- gcode: "CLIENT_TYPE",
|
|
|
+ gcode: 'CLIENT_TYPE',
|
|
|
source: defaultAppName,
|
|
|
});
|
|
|
// 应用渠道列表
|
|
|
const channel = await getSearchData({
|
|
|
- gcode: "CHANNEL",
|
|
|
+ gcode: 'CHANNEL',
|
|
|
source: defaultAppName,
|
|
|
});
|
|
|
return { r, li, appVersion, channel, clientList };
|
|
|
},
|
|
|
disabledDate(time) {
|
|
|
- const first = new Date("2021-06-21 00:00:00");
|
|
|
+ const first = new Date('2021-06-21 00:00:00');
|
|
|
return (
|
|
|
time.getTime() > Date.now() - 86400000 ||
|
|
|
time.getTime() < first.getTime()
|
|
@@ -564,9 +573,9 @@ export default {
|
|
|
const d = new Date(date || Date.now() - 86400000);
|
|
|
const year = d.getFullYear();
|
|
|
const month =
|
|
|
- d.getMonth() <= 8 ? "0" + (d.getMonth() + 1) : d.getMonth() + 1;
|
|
|
- const day = d.getDate() <= 9 ? "0" + d.getDate() : d.getDate();
|
|
|
- return [year, month, day].join("-");
|
|
|
+ d.getMonth() <= 8 ? '0' + (d.getMonth() + 1) : d.getMonth() + 1;
|
|
|
+ const day = d.getDate() <= 9 ? '0' + d.getDate() : d.getDate();
|
|
|
+ return [year, month, day].join('-');
|
|
|
},
|
|
|
timeFormat(t) {
|
|
|
const Time = t || 0;
|
|
@@ -574,40 +583,43 @@ export default {
|
|
|
let hour = (Time - mH) / 3600;
|
|
|
let min = (mH - (mH % 60)) / 60;
|
|
|
let son = Number(mH % 60).toFixed(0);
|
|
|
- hour = hour <= 9 ? "0" + hour : hour;
|
|
|
- min = min <= 9 ? "0" + min : min;
|
|
|
- son = son <= 9 ? "0" + son : son;
|
|
|
+ hour = hour <= 9 ? '0' + hour : hour;
|
|
|
+ min = min <= 9 ? '0' + min : min;
|
|
|
+ son = son <= 9 ? '0' + son : son;
|
|
|
let out = [];
|
|
|
if (hour * 1 > 0) out.push(hour);
|
|
|
out.push(...[min, son]);
|
|
|
- return out.join(":");
|
|
|
+ return out.join(':');
|
|
|
},
|
|
|
change() {
|
|
|
const roleid = JSON.parse(
|
|
|
- window.parent.localStorage.userinfo || "{}"
|
|
|
+ window.parent.localStorage.userinfo || '{}'
|
|
|
).roleid;
|
|
|
const appV = {
|
|
|
length: 0,
|
|
|
};
|
|
|
getRule({
|
|
|
- db: "authplat",
|
|
|
- exportMark: "0",
|
|
|
+ db: 'authplat',
|
|
|
+ exportMark: '0',
|
|
|
menuid: 399,
|
|
|
roleid,
|
|
|
}).then(rule => {
|
|
|
- let prvList = rule.output && rule.output.data ? rule.output.data.prvRolectrl || [] : [];
|
|
|
+ let prvList =
|
|
|
+ rule.output && rule.output.data
|
|
|
+ ? rule.output.data.prvRolectrl || []
|
|
|
+ : [];
|
|
|
for (let i = 0; i < prvList.length; i++) {
|
|
|
const v = prvList[i];
|
|
|
- if (v.controlid == "APP_VERSION")
|
|
|
+ if (v.controlid == 'APP_VERSION')
|
|
|
(appV[v.detid] = true), (appV.length = appV.length + 1);
|
|
|
}
|
|
|
getSearchData({
|
|
|
- gcode: "APP_VERSION",
|
|
|
+ gcode: 'APP_VERSION',
|
|
|
source: this.form.app,
|
|
|
}).then(r => {
|
|
|
let version = [
|
|
|
{
|
|
|
- label: "不限",
|
|
|
+ label: '不限',
|
|
|
value: -1,
|
|
|
},
|
|
|
];
|
|
@@ -670,7 +682,7 @@ export default {
|
|
|
getHistory(p).then(r => {
|
|
|
// 生成数据
|
|
|
let strcsv =
|
|
|
- "data:text/csv;charset=utf-8,\uFEFF日期,活跃用户,新增用户,累计用户,人均使用时长,次均使用时长\r\n";
|
|
|
+ 'data:text/csv;charset=utf-8,\uFEFF日期,活跃用户,新增用户,累计用户,人均使用时长,次均使用时长\r\n';
|
|
|
(r.list || []).map(v => {
|
|
|
strcsv += [
|
|
|
v.dt + '\t',
|
|
@@ -679,16 +691,16 @@ export default {
|
|
|
v.totalUser,
|
|
|
this.timeFormat(v.durationUser) + '\t',
|
|
|
this.timeFormat(v.durationTimes) + '\t',
|
|
|
- "\r\n",
|
|
|
- ].join(",");
|
|
|
+ '\r\n',
|
|
|
+ ].join(',');
|
|
|
});
|
|
|
// 导出
|
|
|
- let link = document.createElement("a");
|
|
|
- link.id = "download-csv";
|
|
|
- link.setAttribute("href", encodeURI(strcsv));
|
|
|
+ let link = document.createElement('a');
|
|
|
+ link.id = 'download-csv';
|
|
|
+ link.setAttribute('href', encodeURI(strcsv));
|
|
|
link.setAttribute(
|
|
|
- "download",
|
|
|
- p.app + "用户趋势" + S + "_" + E + ".csv"
|
|
|
+ 'download',
|
|
|
+ p.app + '用户趋势' + S + '_' + E + '.csv'
|
|
|
);
|
|
|
// document.body.appendChild(link);
|
|
|
link.click();
|