|
@@ -1,5 +1,5 @@
|
|
|
<template>
|
|
|
- <div class="Content">
|
|
|
+ <div class="Channle">
|
|
|
<el-breadcrumb separator-class="el-icon-arrow-right">
|
|
|
<el-breadcrumb-item>新媒体</el-breadcrumb-item>
|
|
|
<el-breadcrumb-item>应用分析</el-breadcrumb-item>
|
|
@@ -90,8 +90,20 @@
|
|
|
<el-card class="box-card">
|
|
|
<div style="text-align: right">
|
|
|
<el-button-group>
|
|
|
- <el-button size="small" type="primary"> 新用户数 </el-button>
|
|
|
- <el-button size="small" type="primary"> 启动次数 </el-button>
|
|
|
+ <el-button
|
|
|
+ size="small"
|
|
|
+ :type="numType === 'newUser' ? 'primary' : 'plain'"
|
|
|
+ @click="() => selectNumType('newUser')"
|
|
|
+ >
|
|
|
+ 新用户数
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ size="small"
|
|
|
+ :type="numType === 'startTimes' ? 'primary' : 'plain'"
|
|
|
+ @click="() => selectNumType('startTimes')"
|
|
|
+ >
|
|
|
+ 启动次数
|
|
|
+ </el-button>
|
|
|
</el-button-group>
|
|
|
</div>
|
|
|
<br />
|
|
@@ -110,35 +122,22 @@
|
|
|
<br />
|
|
|
<br />
|
|
|
<el-table
|
|
|
- :data="table.records || []"
|
|
|
+ :data="table || []"
|
|
|
style="width: 100%"
|
|
|
- @sort-change="tableChange"
|
|
|
:header-cell-style="{
|
|
|
backgroundColor: '#f4f5f7',
|
|
|
color: '#606266',
|
|
|
}"
|
|
|
>
|
|
|
<el-table-column
|
|
|
- prop="contentId"
|
|
|
- header-align="center"
|
|
|
- align="center"
|
|
|
- label="内容ID"
|
|
|
- show-overflow-tooltip
|
|
|
- >
|
|
|
- <template #default="scope">
|
|
|
- <span v-text="scope.row.contentId || '-'"></span>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column
|
|
|
- prop="title"
|
|
|
+ prop="appVersion"
|
|
|
header-align="center"
|
|
|
align="center"
|
|
|
- width="300"
|
|
|
- label="标题"
|
|
|
+ label="渠道"
|
|
|
show-overflow-tooltip
|
|
|
>
|
|
|
<template #default="scope">
|
|
|
- <span v-text="scope.row.title || '-'"></span>
|
|
|
+ <span v-text="scope.row.appVersion || '-'"></span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
@@ -152,118 +151,62 @@
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
|
- prop="publishTime"
|
|
|
+ prop="newUser"
|
|
|
header-align="center"
|
|
|
align="center"
|
|
|
- label="发布时间"
|
|
|
+ label="本渠道新用户"
|
|
|
show-overflow-tooltip
|
|
|
- >
|
|
|
- <template #default="scope">
|
|
|
- <span v-text="scope.row.publishTime || '-'"></span>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column
|
|
|
- label="平均阅读时长"
|
|
|
- header-align="center"
|
|
|
- align="center"
|
|
|
- sortable
|
|
|
- :sort-orders="['descending', null]"
|
|
|
- prop="cduration"
|
|
|
- >
|
|
|
- <template #default="scope">
|
|
|
- <span v-text="timeFormat(scope.row.cduration)"></span>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column
|
|
|
- label="阅读次数"
|
|
|
- header-align="center"
|
|
|
- align="center"
|
|
|
- sortable
|
|
|
- :sort-orders="['descending', null]"
|
|
|
- prop="cpv"
|
|
|
>
|
|
|
<template #default="scope">
|
|
|
<countTo
|
|
|
- :startVal="0"
|
|
|
- :endVal="scope.row.cpv || 0"
|
|
|
+ :startVal="scope.row.newUser || 0"
|
|
|
+ :endVal="scope.row.newUser || 0"
|
|
|
:duration="100"
|
|
|
></countTo>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
|
- label="点赞次数"
|
|
|
+ prop="startTimes"
|
|
|
header-align="center"
|
|
|
align="center"
|
|
|
- sortable
|
|
|
- :sort-orders="['descending', null]"
|
|
|
- prop="csupport"
|
|
|
- >
|
|
|
- <template #default="scope">
|
|
|
- <countTo
|
|
|
- :startVal="0"
|
|
|
- :endVal="scope.row.csupport || 0"
|
|
|
- :duration="100"
|
|
|
- ></countTo>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column
|
|
|
- label="收藏次数"
|
|
|
- header-align="center"
|
|
|
- align="center"
|
|
|
- sortable
|
|
|
- :sort-orders="['descending', null]"
|
|
|
- prop="ccollect"
|
|
|
+ label="启动次数"
|
|
|
+ show-overflow-tooltip
|
|
|
>
|
|
|
<template #default="scope">
|
|
|
<countTo
|
|
|
- :startVal="0"
|
|
|
- :endVal="scope.row.ccollect || 0"
|
|
|
+ :startVal="scope.row.startTimes || 0"
|
|
|
+ :endVal="scope.row.startTimes || 0"
|
|
|
:duration="100"
|
|
|
></countTo>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
|
- label="分享次数"
|
|
|
+ prop="activeUser"
|
|
|
header-align="center"
|
|
|
align="center"
|
|
|
- sortable
|
|
|
- :sort-orders="['descending', null]"
|
|
|
- prop="cshare"
|
|
|
+ label="启动户数"
|
|
|
+ show-overflow-tooltip
|
|
|
>
|
|
|
<template #default="scope">
|
|
|
<countTo
|
|
|
- :startVal="0"
|
|
|
- :endVal="scope.row.cshare || 0"
|
|
|
+ :startVal="scope.row.activeUser || 0"
|
|
|
+ :endVal="scope.row.activeUser || 0"
|
|
|
:duration="100"
|
|
|
></countTo>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
|
- label="观看用户数"
|
|
|
+ prop="distribution"
|
|
|
header-align="center"
|
|
|
align="center"
|
|
|
- sortable
|
|
|
- :sort-orders="['descending', null]"
|
|
|
- prop="cuser"
|
|
|
+ label="平均使用时长"
|
|
|
+ show-overflow-tooltip
|
|
|
>
|
|
|
<template #default="scope">
|
|
|
- <countTo
|
|
|
- :startVal="0"
|
|
|
- :endVal="scope.row.cuser || 0"
|
|
|
- :duration="100"
|
|
|
- ></countTo>
|
|
|
+ {{timeFormat(scope.row.distribution )}}
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
- <br />
|
|
|
- <el-pagination
|
|
|
- layout="prev, pager, next"
|
|
|
- :page-size="form.size"
|
|
|
- :current-page="form.page"
|
|
|
- :total="table.total"
|
|
|
- background
|
|
|
- @current-change="changePage"
|
|
|
- />
|
|
|
</el-card>
|
|
|
</div>
|
|
|
</template>
|
|
@@ -273,8 +216,8 @@ import {
|
|
|
getRule,
|
|
|
getAppList,
|
|
|
getSearchData,
|
|
|
- getContentChart,
|
|
|
- getContentPage,
|
|
|
+ getChannleChart,
|
|
|
+ getChannlePage,
|
|
|
} from "@/api/index";
|
|
|
|
|
|
import countTo from "@/components/counto/vue-countTo.vue";
|
|
@@ -298,14 +241,15 @@ echarts.use([
|
|
|
LegendComponent,
|
|
|
]);
|
|
|
|
|
|
-import config from "@/config/index";
|
|
|
+// import config from "@/config/index";
|
|
|
let chart = undefined;
|
|
|
export default {
|
|
|
name: "Version",
|
|
|
data() {
|
|
|
return {
|
|
|
lastParams: {},
|
|
|
- table: {},
|
|
|
+ table: [],
|
|
|
+ numType: "newUser",
|
|
|
form: {
|
|
|
app: "",
|
|
|
version: [],
|
|
@@ -326,27 +270,26 @@ export default {
|
|
|
value: "mname",
|
|
|
label: "mname",
|
|
|
};
|
|
|
+ const channel = [];
|
|
|
this.cycle = this.verifyList(appli, source, keys, false);
|
|
|
- this.channel = this.verifyList(appCLi, appC, keys, true);
|
|
|
+ this.channel = this.verifyList(appCLi, appC, keys, false);
|
|
|
this.version = this.verifyList(appVLi, appV, keys, true);
|
|
|
+ for (let i = 0; i < this.channel.length; i++) {
|
|
|
+ if (i > 4) break;
|
|
|
+ const v = this.channel[i];
|
|
|
+ channel.push(v.value)
|
|
|
+ }
|
|
|
this.form = {
|
|
|
// app: (this.cycle[0] || { value: "" }).value,
|
|
|
app: "起点新闻",
|
|
|
version: [(this.version[0] || { value: "" }).value],
|
|
|
- channel: [(this.channel[0] || { value: "" }).value],
|
|
|
+ channel,
|
|
|
date: [new Date(Date.now() - 604800000), new Date(Date.now() - 86400000)],
|
|
|
- page: 1,
|
|
|
- size: 20,
|
|
|
};
|
|
|
this.onSubmit();
|
|
|
},
|
|
|
computed: {},
|
|
|
methods: {
|
|
|
- tableChange() {
|
|
|
- this.form.page = 1;
|
|
|
- this.lastParams.page = 1;
|
|
|
- getContentPage(this.lastParams).then(r => (this.table = r || {}));
|
|
|
- },
|
|
|
verifyList(list, verify, obj, more) {
|
|
|
if (!obj) return;
|
|
|
let li = list || [];
|
|
@@ -362,9 +305,23 @@ export default {
|
|
|
}
|
|
|
return out;
|
|
|
},
|
|
|
- changePage(e) {
|
|
|
- this.form.page = e;
|
|
|
- this.onSubmit();
|
|
|
+ selectNumType(type) {
|
|
|
+ this.numType = type;
|
|
|
+ getChannleChart(this.lastParams).then(resChart => {
|
|
|
+ const c = resChart || {};
|
|
|
+ let keyList = [],
|
|
|
+ valueList = [],
|
|
|
+ titles = [];
|
|
|
+ if ((resChart || []).length && chart && chart.clear)
|
|
|
+ return chart.clear();
|
|
|
+ for (let index = 0; index < (Object.keys(c) || []).length; index++) {
|
|
|
+ const v = (Object.keys(c) || [])[index];
|
|
|
+ valueList.push((c[v] || []).map(v => v[this.numType]));
|
|
|
+ titles.push(v);
|
|
|
+ if (!keyList.length) keyList = (c[v] || []).map(v => v.dt);
|
|
|
+ }
|
|
|
+ this.createImage(keyList, valueList, titles);
|
|
|
+ });
|
|
|
},
|
|
|
onSubmit() {
|
|
|
this.lastParams = {
|
|
@@ -373,21 +330,21 @@ export default {
|
|
|
end: this.FormData(this.form.date[1]),
|
|
|
manufacturer: this.form.channel == -1 ? undefined : this.form.channel,
|
|
|
version: this.form.version == -1 ? undefined : this.form.version,
|
|
|
- page: this.form.page,
|
|
|
- pageSize: this.form.size,
|
|
|
};
|
|
|
- getContentPage(this.lastParams).then(r => (this.table = r || {}));
|
|
|
- getContentChart({
|
|
|
- app: this.form.app,
|
|
|
- start: this.FormData(this.form.date[0]),
|
|
|
- end: this.FormData(this.form.date[1]),
|
|
|
- version: this.form.version == -1 ? undefined : this.form.version,
|
|
|
- }).then(resChart => {
|
|
|
+ getChannlePage(this.lastParams).then(r => (this.table = r || []));
|
|
|
+ getChannleChart(this.lastParams).then(resChart => {
|
|
|
+ const c = resChart || {};
|
|
|
let keyList = [],
|
|
|
valueList = [],
|
|
|
titles = [];
|
|
|
if ((resChart || []).length && chart && chart.clear)
|
|
|
return chart.clear();
|
|
|
+ for (let index = 0; index < (Object.keys(c) || []).length; index++) {
|
|
|
+ const v = (Object.keys(c) || [])[index];
|
|
|
+ valueList.push((c[v] || []).map(v => v[this.numType]));
|
|
|
+ titles.push(v);
|
|
|
+ if (!keyList.length) keyList = (c[v] || []).map(v => v.dt);
|
|
|
+ }
|
|
|
this.createImage(keyList, valueList, titles);
|
|
|
});
|
|
|
},
|
|
@@ -396,8 +353,10 @@ export default {
|
|
|
chart.resize({
|
|
|
height: (this.$refs.regionChart.offsetWidth * 4) / 16,
|
|
|
});
|
|
|
+ chart.clear();
|
|
|
chart.setOption({
|
|
|
tooltip: {
|
|
|
+ confine: true,
|
|
|
trigger: "axis",
|
|
|
},
|
|
|
toolbox: {
|
|
@@ -588,15 +547,10 @@ export default {
|
|
|
gcode: "CHANNEL",
|
|
|
source: this.form.app,
|
|
|
}).then(r => {
|
|
|
- let channel = [
|
|
|
- {
|
|
|
- label: "不限",
|
|
|
- value: -1,
|
|
|
- },
|
|
|
- ];
|
|
|
+ let channel = [];
|
|
|
r.map(v => {
|
|
|
if ((appV.length && appV[v.mcode]) || appV.length === 0)
|
|
|
- channel.push({
|
|
|
+ channel.push({
|
|
|
value: v.mname,
|
|
|
label: v.mname,
|
|
|
});
|
|
@@ -640,24 +594,45 @@ export default {
|
|
|
const E = this.form.date[1]
|
|
|
? this.FormData(this.form.date[1])
|
|
|
: undefined;
|
|
|
- const app = this.lastParams.app || this.form.app;
|
|
|
- const version =
|
|
|
- this.form.version == -1 ? undefined : this.form.version.join(",");
|
|
|
- const manufacturer =
|
|
|
- this.lastParams.manufacturer || this.form.channel.join(",");
|
|
|
- let url =
|
|
|
- config.base.leverAudience +
|
|
|
- "/cxzx-program/new-media/content/export?start=" +
|
|
|
- S +
|
|
|
- "&end=" +
|
|
|
- E +
|
|
|
- "&app=" +
|
|
|
- app;
|
|
|
- version && (url += "&version=" + version);
|
|
|
- manufacturer &&
|
|
|
- manufacturer !== -1 &&
|
|
|
- (url += "&manufacturer=" + manufacturer);
|
|
|
- window.open(url);
|
|
|
+ let p = this.lastParams.app
|
|
|
+ ? this.lastParams
|
|
|
+ : {
|
|
|
+ app: this.form.app,
|
|
|
+ start: S,
|
|
|
+ end: E,
|
|
|
+ manufacturer:
|
|
|
+ this.form.channel == -1 ? undefined : this.form.channel,
|
|
|
+ version: this.form.version == -1 ? undefined : this.form.version,
|
|
|
+ };
|
|
|
+ getChannlePage(p).then(r => {
|
|
|
+ // 生成数据
|
|
|
+ let strcsv =
|
|
|
+ "data:text/csv;charset=utf-8,版本,应用,升级用户数,新用户数,活跃用户数,启动次数,启动用户(分布),平均使用时长\r\n";
|
|
|
+ (r || []).map(v => {
|
|
|
+ strcsv += [
|
|
|
+ v.appVersion,
|
|
|
+ p.app,
|
|
|
+ v.upgradeUser,
|
|
|
+ v.newUser,
|
|
|
+ v.activeUser,
|
|
|
+ v.startTimes,
|
|
|
+ v.distribution + "%",
|
|
|
+ this.timeFormat(v.duration),
|
|
|
+ "\r\n",
|
|
|
+ ].join(",");
|
|
|
+ });
|
|
|
+ // 导出
|
|
|
+ let link = document.createElement("a");
|
|
|
+ link.id = "download-csv";
|
|
|
+ link.setAttribute("href", encodeURI(strcsv));
|
|
|
+ link.setAttribute(
|
|
|
+ "download",
|
|
|
+ p.app + "版本分析" + S + "_" + E + ".csv"
|
|
|
+ );
|
|
|
+ // document.body.appendChild(link);
|
|
|
+ link.click();
|
|
|
+ link = undefined;
|
|
|
+ });
|
|
|
},
|
|
|
},
|
|
|
components: {
|
|
@@ -667,7 +642,7 @@ export default {
|
|
|
</script>
|
|
|
|
|
|
<style>
|
|
|
-.Content {
|
|
|
+.Channle {
|
|
|
margin: 10px 15px;
|
|
|
}
|
|
|
.libTitle {
|