// ==UserScript==
// @name acfun统计
// @description acfun统计(目前只包含送出礼物和收到礼物的统计)
// @namespace syachiku
// @author syachiku
// @match https://www.acfun.cn/member*
// @run-at document-end
// @grant GM_addStyle
// @grant GM_xmlhttpRequest
// @version 0.0.8
// @require https://cdnjs.cloudflare.com/ajax/libs/qs/6.9.4/qs.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.12/vue.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.14.1/index.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/echarts/5.0.2/echarts.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/exceljs/4.2.0/exceljs.min.js
// ==/UserScript==
;(async function(){
Vue.use(ELEMENT);
Vue.prototype.$message = ELEMENT.Message;
const config = {
ACFUN_SERVER : 'https://www.acfun.cn',
ACFUN_MOBILE_SERVER : 'https://m.acfun.cn',
ACFUNLIVE_SERVER : 'https://live.acfun.cn',
URLS : {
ACFUN_USER : {
INFO : '/rest/pc-direct/user/userInfo',
SPACE : '/u'
},
WALLET : {
SEND_GIFT : '/rest/apph5-direct/pay/reward/giveRecords',
RECEIVE_GIFT : '/rest/apph5-direct/pay/reward/receiveRecords',
}
},
};
// 是否为空
function isNullOrEmpty(val){
return _.isUndefined(val) || _.isNull(val) || _.isNaN(val) || (((_.isObject(val) && !_.isDate(val)) || _.isArray(val) || _.isString(val)) && _.isEmpty(val))
}
// 通用请求
function commonRequrest(url, method, form, raw, callback, headers){
var isSuccess = false;
var data = null;
if(!headers){
headers = {};
}
if(!raw){
if(method == 'post'){
headers['Content-Type'] = 'application/x-www-form-urlencoded';
if(form){
form = Qs.stringify(form);
}
}
}
if(method == 'get' && form){
form = Qs.stringify(form);
url += '?' + form;
}
// 获取了token
if(config.TOKEN){
headers['Authorization'] = `Token ${config.TOKEN}`;
}
GM_xmlhttpRequest({
synchronous : !_.isFunction(callback),
method : method,
url : url,
data : form,
headers : headers,
onload : function(res){
// 200
if(res.status==200){
if(raw){
callback(true, res.responseText);
}
else{
res = JSON.parse(res.responseText);
isSuccess = res[config.RESPONSE.FIELD.STATUS] == config.RESPONSE.STATUS.SUCCESS;
data = res[config.RESPONSE.FIELD.DATA];
if(_.isFunction(callback)){
callback(isSuccess, data);
}
}
}
else{
if(_.isFunction(callback)){
callback(isSuccess, data);
}
}
},
onerror : function(){
if(_.isFunction(callback)){
callback(isSuccess, data);
}
},
onabort : function(){
if(_.isFunction(callback)){
callback(isSuccess, data);
}
},
});
return [isSuccess, data];
}
function addCssResource(url){
commonRequrest(url, 'get', null, true, function(isSuccess, css){
if(isSuccess){
GM_addStyle(css);
}
})
}
// 添加element-ui样式
addCssResource('https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.14.1/theme-chalk/index.min.css');
// 加载Vue实例
function loadVue(){
var vue = null;
// 容器
var navEle = document.querySelector('#list-guide-left');
// 添加导航选项
var navItem = document.createElement('div');
navItem.classList.add('part-guide-left');
navItem.innerHTML = `
<div class="banner">
<a href="javascript:void(0)" class="tab fixed">
<i class="icon icon-bar-chart"></i>统计
</a>
</div>
`;
// 监听点击事件
navItem.addEventListener('click', function(){
// 删除其它菜单项的active类
var activeNavItem = navEle.querySelector('.part-guide-left.active');
activeNavItem.classList.remove('active');
// 添加active类
navItem.classList.add('active');
// 修改展示内容
document.querySelector('#area-main-right').innerHTML = `
<style>
@font-face{
font-family:element-icons;
src:url('https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.14.1/theme-chalk/fonts/element-icons.ttf');
}
#block-first .item{
font-family: verdana,Tahoma,Arial,"微软雅黑","宋体",sans-serif;
margin: 0 0 16px;
width : 50%;
}
#block-first .item .l .icon {
font-size: 24px;
color: #ccc;
margin: 12px 8px 0 0;
}
#block-first .item .a {
font-size: 18px;
font-weight: bold;
letter-spacing: -.1em;
line-height: 1.2;
color: #333;
}
#block-first .item .a .pts {
font-family: Candara,verdana,Tahoma,Arial,"微软雅黑","宋体",sans-serif;
font-size: 32px;
margin: 0 8px;
}
#block-first .item .b {
font-size: 12px;
font-style: italic;
line-height: 1.2;
color: #999;
}
#block-detail .item{
width : 50%;
}
#block-detail .item li {
list-style:none;
color: #3a9bd9 !important;
}
#block-detail .item li span {
color: #666;
font-weight: bold;
}
#block-detail .item.l{
border-right: 1px solid #ddd;
}
.el-table__body-wrapper.is-scrolling-none::-webkit-scrollbar{
width: 10px;
height: 1px;
}
.el-table__body-wrapper.is-scrolling-none::-webkit-scrollbar-thumb {
border-radius: 10px;
-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
background: #535353;
}
.el-table__body-wrapper.is-scrolling-none::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
border-radius: 10px;
background: #EDEDED;
}
.btn-toggle-info{
border-top: 1px dashed #999;
text-align: center;
color: #08c;
height: 16px;
line-height: 16px;
}
.btn-toggle-info span{
display: block;
margin-top: -8px;
cursor: pointer;
background-color: #fff;
width: 128px;
}
#gift-trend-container{
height : 200px;
width : 100%;
}
</style>
<div id="block-title-banner">
<p>统计</p>
<div>
<a href="/member/">AcFun</a><span class="d">Stat</span>
</div>
<span class="clearfix"></span>
</div>
<div id="block-banner-right" class="block banner">
<a href="#area=acfunstat" data-type="views" class="tab">
<i class="icon"></i>送出/收到礼物
</a>
</div>
<div id="acfunstat-container" v-cloak>
<div class="block" v-if="isGettingSendGiftList">
<div class="mainer">
<span>正在获取送出礼物记录。已获取{{sendGiftList.length}}条记录</span>
</div>
</div>
<div class="block" v-if="isGettingReceiveGiftList">
<div class="mainer">
<span>正在获取收到礼物记录。已获取{{receiveGiftList.length}}条记录</span>
</div>
</div>
<template v-if="hasGetSendGiftList && hasGetReceiveGiftList">
<div id="block-first" class="block">
<div class="mainer">
<div class="banner">
<p class="tab fixed">总体{{filterText}}</p>
<p class="r">
<i class="icon icon-cog" title="配置" style="color: #3a9bd9;font-size:24px;cursor:pointer;" @click="openSettingDialog"></i>
<i class="icon icon-book" title="导出excel" style="color: #3a9bd9;font-size:24px;cursor:pointer;" @click="exportGift"></i>
</p>
</div>
<div class="item l">
<div class="l">
<i style="color: #f69;" class="icon icon-gift"></i>
</div>
<div class="l">
<div class="a">
送出礼物价值<span id="pts-online-splash" style="color: #f69;" class="pts">{{send}}</span>AC币
</div>
<div class="b">
用户送出礼物价值的AC币总和
</div>
</div>
<span class="clearfix"></span>
</div>
<div class="item r">
<div class="l">
<i style="color: #f69;" class="icon icon-gift"></i>
</div>
<div class="l">
<div class="a">
收到礼物价值<span id="pts-online-splash" style="color: #f69;" class="pts">{{receive}}</span>钻石
</div>
<div class="b">
用户收到礼物价值的钻石总和
</div>
</div>
<span class="clearfix"></span>
</div>
<span class="clearfix"></span>
</div>
</div>
<div id="block-detail" class="block">
<div class="mainer">
<div class="item l">
<div class="banner">
<p class="tab fixed">送出礼物用户排行</p>
</div>
<div id="send-gift-user-table">
<el-table :data="sendUserList" style="width: 100%" class="user-table" height="400">
<el-table-column prop="userName" label="用户名" min-width="50%">
<template slot-scope="scope">
<el-avatar shape="circle" fit="fill" size="40" :src="scope.row.photo"></el-avatar>
<el-link style="cursor:pointer;" @click="toUserSpace(scope.row)">{{scope.row.userName}}</el-link>
</template>
</el-table-column>
<el-table-column prop="uid" label="用户uid" min-width="30%">
</el-table-column>
<el-table-column prop="send" label="AC币" min-width="20%">
</el-table-column>
</el-table>
</div>
<span class="clearfix"></span>
</div>
<div class="item r">
<div class="banner">
<p class="tab fixed">收到礼物用户排行</p>
</div>
<div id="receive-gift-user-table">
<el-table :data="receiveUserList" style="width: 100%" class="user-table" height="400">
<el-table-column prop="userName" label="用户名" min-width="50%">
<template slot-scope="scope">
<el-avatar shape="circle" fit="fill" size="40" :src="scope.row.photo"></el-avatar>
<el-link style="cursor:pointer;" @click="toUserSpace(scope.row)">{{scope.row.userName}}</el-link>
</template>
</el-table-column>
<el-table-column prop="uid" label="用户uid" min-width="30%">
</el-table-column>
<el-table-column prop="receive" label="钻石" min-width="20%">
</el-table-column>
</el-table>
</div>
<span class="clearfix"></span>
</div>
<span class="clearfix"></span>
</div>
</div>
<p class="btn-toggle-info" @click="handleShowGiftTrend" v-if="!showGiftTrend"><span><i class="icon icon-chevron-down"></i>点击查看礼物趋势</span></p>
<div class="block" v-if="showGiftTrend">
<div class="mainer">
<div class="banner">
<p class="tab fixed">{{switchToSendGiftTrend?'送出礼物趋势':'收到礼物趋势'}}</p>
<div class="r">
<el-form :inline="true" :model="giftTrendFormData" size="mini">
<el-form-item>
<el-select v-model="giftTrendFormData.unit" style="width:100px;">
<el-option label="按天展示" value="day" key="day"></el-option>
<el-option label="按周展示" value="week" key="week"></el-option>
<el-option label="按月展示" value="month" key="month"></el-option>
<el-option label="按年展示" value="year" key="year"></el-option>
</el-select>
</el-form-item>
<el-form-item v-if="switchToSendGiftTrend">
<el-select v-model="giftTrendFormData.uid" filterable placeholder="用户筛选">
<el-option label="不筛选" value=""></el-option>
<el-option :label="userInfo.userName" :value="userInfo.uid" :key="userInfo.uid" v-for="userInfo in sendUserList"></el-option>
</el-select>
</el-form-item>
<el-form-item v-else>
<el-select v-model="giftTrendFormData.uid" filterable placeholder="用户筛选">
<el-option label="不筛选" value=""></el-option>
<el-option :label="userInfo.userName" :value="userInfo.uid" :key="userInfo.uid" v-for="userInfo in receiveUserList"/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSwitchToSendGiftTrend">{{switchToSendGiftTrend?'切换至收到礼物趋势':'切换至送出礼物趋势'}}</el-button>
</el-form-item>
</el-form>
</div>
</div>
<div id="gift-trend-container">
</div>
</div>
</div>
</template>
<el-drawer :title="switchToSendGiftTrend?'送出礼物详情':'收到礼物详情'" :visible.sync="showGiftDetail" direction="ltr" :modal="false" :size="670">
<div v-if="switchToSendGiftTrend">
<div id="send-gift-table">
<el-table :data="giftDetailList" style="width: 100%" class="user-table" height="500">
<el-table-column prop="userName" label="用户名" :width="200">
<template slot-scope="scope">
<el-avatar shape="circle" fit="fill" size="40" :src="userInfo[scope.row.userId].photo"></el-avatar>
<el-link style="cursor:pointer;" @click="toUserSpace(userInfo[scope.row.userId])">{{userInfo[scope.row.userId].userName}}</el-link>
</template>
</el-table-column>
<el-table-column prop="userId" label="用户uid" :width="100">
</el-table-column>
<el-table-column prop="createTimeText" label="送出时间" :width="150">
</el-table-column>
<el-table-column prop="giftText" label="送出礼物" :width="100">
</el-table-column>
<el-table-column prop="acoin" label="AC币" :width="70">
</el-table-column>
</el-table>
</div>
</div>
<div v-else>
<div id="receive-gift-table">
<el-table :data="giftDetailList" style="width: 100%" class="user-table" height="500">
<el-table-column prop="userName" label="用户名" width="200">
<template slot-scope="scope">
<el-avatar shape="circle" fit="fill" size="40" :src="userInfo[scope.row.userId].photo"></el-avatar>
<el-link style="cursor:pointer;" @click="toUserSpace(userInfo[scope.row.userId])">{{userInfo[scope.row.userId].userName}}</el-link>
</template>
</el-table-column>
<el-table-column prop="userId" label="用户uid" width="100">
</el-table-column>
<el-table-column prop="createTimeText" label="收到时间" width="150">
</el-table-column>
<el-table-column prop="giftText" label="收到礼物" width="100">
</el-table-column>
<el-table-column prop="azuanAmount" label="钻石" width="70">
</el-table-column>
</el-table>
</div>
</div>
</el-drawer>
<el-dialog title="设置" :visible.sync="settingFormDialogVisible" :modal="false" width="550px" custom-class="setting-form-dialog" :modal-append-to-body="false">
<el-form :model="settingFormData" class="setting-form" ref="settingForm" :rules="settingFormRules" @submit.native.prevent>
<el-form-item label="礼物筛选" label-width="130px" prop="isContainPeach">
<el-switch v-model="settingFormData.isContainPeach" active-text="包括桃子" inactive-text="不包括桃子">
</el-switch>
</el-form-item>
<el-form-item label="时间范围" label-width="130px" prop="dateRegion">
<el-date-picker
v-model="settingFormData.dateRegion"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:picker-options="settingFormPickerOptions"
style="width:100%"
>
</el-date-picker>
</el-form-item>
<el-form-item style="display:flex;justify-content:center;">
<el-button type="primary" @click="handleSettingFormSubmit">提交</el-button>
</el-form-item>
</el-form>
</el-dialog>
</div>
`;
history.replaceState(null, null, '/member/#area=acfunstat');
// 已初始化vue实例
if(vue){
return;
}
// 初始化实例
new Vue({
el : '#acfunstat-container',
data : function(){
return {
send : 0,
receive : 0,
sendGiftList : [],
receiveGiftList : [],
giftDetailList : [],
showGiftDetail : false,
showGiftTrend : false,
sendUserList : [],
receiveUserList : [],
userInfo : {},
isGettingSendGiftList : false,
isGettingReceiveGiftList : false,
hasGetReceiveGiftList : false,
hasGetSendGiftList : false,
filterText : '',
settingFormDialogVisible : false,
settingFormData : {
isContainPeach : true,
},
settingFormRules : {
},
settingFormPickerOptions : {
shortcuts : [{
text : '本周',
onClick(picker) {
const end = moment().endOf('week').add(1, 'days')._d;
const start = moment().startOf('week').add(1, 'days')._d;
picker.$emit('pick', [start, end]);
},
},{
text : '上周',
onClick(picker) {
const end = moment().subtract(1, 'weeks').endOf('week').add(1, 'days')._d;
const start = moment().subtract(1, 'weeks').startOf('week').add(1, 'days')._d;
picker.$emit('pick', [start, end]);
},
},{
text : '本月',
onClick(picker) {
const end = moment().endOf('month')._d;
const start = moment().startOf('month')._d;
picker.$emit('pick', [start, end]);
},
},{
text : '上月',
onClick(picker) {
const end = moment().subtract(1, 'months').endOf('month')._d;
const start = moment().subtract(1, 'months').startOf('month')._d;
picker.$emit('pick', [start, end]);
},
},]
},
switchToSendGiftList : true,
switchToSendGiftTrend : true,
giftTrendFormData : {
unit : 'day',
},
};
},
methods : {
getUserInfo : function(uid, userName, callback){
var vue = this;
if(uid in this.userInfo){
if(_.isFunction(callback)){
callback(true, this.userInfo[uid]);
}
return;
}
// 获取用户信息
commonRequrest(config.ACFUNLIVE_SERVER + config.URLS.ACFUN_USER.INFO + `?userId=${uid}`, 'get', null, true, function(isSuccess, data){
var userInfo = null;
if(data){
data = JSON.parse(data);
if(data.result == 0){
userInfo = {
uid : uid,
photo : data.profile.headUrl,
userName : data.profile.name,
};
}
else{
userInfo = {
uid : uid,
userName : userName,
photo : 'https://tx-free-imgs.acfun.cn/style/image/defaultAvatar.jpg',
};
}
}
else{
userInfo = {
uid : uid,
userName : userName,
photo : 'https://tx-free-imgs.acfun.cn/style/image/defaultAvatar.jpg',
};
}
vue.userInfo[uid] = userInfo;
if(_.isFunction(callback)){
callback(isSuccess, userInfo);
}
});
},
getSendGiftList : function(callback){
var vue = this;
var startDate = null,endDate=null;
var isContainPeach = this.settingFormData.isContainPeach;
// 筛选了时间范围
if(this.settingFormData.dateRegion && this.settingFormData.dateRegion.length==2){
startDate = this.settingFormData.dateRegion[0].getTime();
endDate = this.settingFormData.dateRegion[1].getTime();
}
// 获取数据时的游标
var pcursor = "0";
var getSendGiftList = function(){
vue.isGettingSendGiftList = true;
if(pcursor == 'no_more'){
// 统计送出礼物总ac币
vue.send = _.sumBy(_.flatMap(vue.userInfo), 'send');
vue.send = vue.send?vue.send:0;
// 讲用户按送出ac币价值倒序
vue.sendUserList = _.sortBy(_.filter(vue.userInfo, (userInfo)=>{return userInfo.send>0;}), function(userInfo){
return -userInfo.send;
});
vue.isGettingSendGiftList = false;
vue.hasGetSendGiftList = true;
if(_.isFunction(callback)){
callback();
}
return;
}
else{
commonRequrest(config.ACFUN_MOBILE_SERVER + config.URLS.WALLET.SEND_GIFT, 'get',{pcursor : pcursor,},true,
function(isSuccess, data){
// 获取数据失败
if(!isSuccess){
vue.$message({
type : 'error',
message : '获取送出礼物列表失败',
});
pcursor = 'no_more';
getSendGiftList();
}
else{
data = JSON.parse(data);
pcursor = data['pcursor'];
if(data.records || data.records.length==0){
var uids = {};
var uidUserNameMapper = {};
// 获取用户信息
data.records.forEach(function(record){
// 指定了起始时间
if(startDate && record.createTime<startDate){
pcursor = "no_more";
return;
}
// 指定了终止时间
else if(endDate && record.createTime>endDate){
return;
}
// 不包含桃子
else if(!isContainPeach && record.giftName == '桃子'){
return;
}
if(!(record.userId in uids)){
uids[record.userId] = [];
}
uidUserNameMapper[record.userId] = record.userName;
var now = moment(record.createTime);
// 设置送出时间
record.createTimeText = now.format('YYYY-MM-DD hh:mm:ss');
record.giftText = `${record.giftCount}个${record.giftName}`;
// 设置时间单位,便于获取趋势
record.dayUnitText = now.format('YYYY-MM-DD');
record.monthUnitText = now.format('YYYY-MM');
record.yearUnitText = now.format('YYYY');
record.weekUnitText = now.startOf('week').add(1, 'days').format('YYYY-MM-DD');
uids[record.userId].push(record);
vue.sendGiftList.push(record);
});
// 没有任何记录
if(Object.keys(uids).length==0){
getSendGiftList();
}
else{
var nextGetSendGiftList = _.after(Object.keys(uids).length, getSendGiftList);
for(var uid in uids){
vue.getUserInfo(uid, uidUserNameMapper[uid], function(isSuccess, userInfo){
// 统计送出给用户AC币
if(userInfo.sendGiftList == null){
userInfo.sendGiftList = [];
}
if(userInfo.send==null){
userInfo.send = 0;
}
userInfo.sendGiftList.splice(userInfo.sendGiftList.length, 0, ...uids[userInfo.uid]);
userInfo.send += _.sumBy(uids[userInfo.uid], 'acoin');
nextGetSendGiftList();
});
}
}
}
else{
getSendGiftList();
}
}
},
);
}
}
getSendGiftList();
},
getReceiveGiftList : function(callback){
var vue = this;
var startDate = null,endDate=null;
var isContainPeach = this.settingFormData.isContainPeach;
// 筛选了时间范围
if(this.settingFormData.dateRegion && this.settingFormData.dateRegion.length==2){
startDate = this.settingFormData.dateRegion[0].getTime();
endDate = this.settingFormData.dateRegion[1].getTime();
}
// 获取数据时的游标
var pcursor = "0";
var getReceiveGiftList = function(){
vue.isGettingReceiveGiftList = true;
if(pcursor == 'no_more'){
// 统计送出礼物总ac币
vue.receive = _.sumBy(_.flatMap(vue.userInfo), 'receive');
vue.receive = vue.receive?vue.receive:0;
// 讲用户按送出ac币价值倒序
vue.receiveUserList = _.sortBy(_.filter(vue.userInfo, (userInfo)=>{return userInfo.receive>0;}), function(userInfo){
return -userInfo.receive;
});
vue.isGettingReceiveGiftList = false;
vue.hasGetReceiveGiftList = true;
if(_.isFunction(callback)){
callback();
}
return;
}
else{
commonRequrest(config.ACFUN_MOBILE_SERVER + config.URLS.WALLET.RECEIVE_GIFT, 'get',{pcursor : pcursor,},true,
function(isSuccess, data){
// 获取数据失败
if(!isSuccess){
vue.$message({
type : 'error',
message : '获取送出礼物列表失败',
});
pcursor = 'no_more';
getReceiveGiftList();
}
else{
data = JSON.parse(data);
pcursor = data['pcursor'];
if(data.records || data.records.length==0){
var uids = {};
var uidUserNameMapper = {};
// 获取用户信息
data.records.forEach(function(record){
// 指定了起始时间
if(startDate && record.createTime<startDate){
pcursor = "no_more";
return;
}
// 指定了终止时间
else if(endDate && record.createTime>endDate){
return;
}
// 不包含桃子
else if(!isContainPeach && record.giftName == '桃子'){
return;
}
if(!(record.userId in uids)){
uids[record.userId] = [];
}
uidUserNameMapper[record.userId] = record.userName;
var now = moment(record.createTime);
// 设置送出时间
record.createTimeText = now.format('YYYY-MM-DD hh:mm:ss');
record.giftText = `${record.giftCount}个${record.giftName}`;
// 设置时间单位,便于获取趋势
record.dayUnitText = now.format('YYYY-MM-DD');
record.monthUnitText = now.format('YYYY-MM');
record.yearUnitText = now.format('YYYY');
record.weekUnitText = now.startOf('week').add(1, 'days').format('YYYY-MM-DD');
uids[record.userId].push(record);
vue.receiveGiftList.push(record);
});
// 没有任何记录
if(Object.keys(uids).length==0){
getReceiveGiftList();
}
else{
var nextGetReceiveGiftList = _.after(Object.keys(uids).length, getReceiveGiftList);
for(var uid in uids){
vue.getUserInfo(uid, uidUserNameMapper[uid], function(isSuccess, userInfo){
// 统计送出给用户AC币
if(userInfo.receiveGiftList == null){
userInfo.receiveGiftList = [];
}
if(userInfo.receive==null){
userInfo.receive = 0;
}
userInfo.receiveGiftList.splice(userInfo.receiveGiftList.length, 0, ...uids[userInfo.uid]);
userInfo.receive += _.sumBy(uids[userInfo.uid], 'azuanAmount');
nextGetReceiveGiftList();
});
}
}
}
else{
getReceiveGiftList();
}
}
},
);
}
}
getReceiveGiftList();
},
// 渲染趋势
renderGiftTrend : function(){
var vue = this;
var data = this.switchToSendGiftTrend?this.sendGiftList:this.receiveGiftList;
// 筛选用户
if(this.giftTrendFormData.uid){
data = _.filter(data, {userId:_.parseInt(this.giftTrendFormData.uid)});
}
// 按时间分组
data = _.groupBy(data, function(item){
// 按天筛选
if(vue.giftTrendFormData.unit == 'day'){
return item.dayUnitText;
}
// 按周筛选
if(vue.giftTrendFormData.unit == 'week'){
return item.weekUnitText;
}
// 按月筛选
if(vue.giftTrendFormData.unit == 'month'){
return item.monthUnitText;
}
// 按年筛选
if(vue.giftTrendFormData.unit == 'year'){
return item.yearUnitText;
}
});
// 转化格式
var lineNameData = _.sortBy(Object.keys(data));
var lineValueData = [];
lineNameData.forEach(function(unit){
lineValueData.push(_.sumBy(data[unit], vue.switchToSendGiftTrend?'acoin':'azuanAmount'));
});
var chart = echarts.init(document.getElementById('gift-trend-container'));
var option = {
xAxis: {
type: 'category',
name : '时间',
data : lineNameData,
},
yAxis: {
type: 'value',
name : this.switchToSendGiftTrend?'AC币':'钻石',
},
series: [{
type: 'line',
data : lineValueData,
name : this.switchToSendGiftTrend?'AC币':'钻石',
},],
tooltip : {
trigger : 'axis',
axisPointer : {
type : 'line',
axis : 'x',
},
confine : true,
},
dataZoom : [{
type : 'inside',
orient : 'horizontal',
}],
};
chart.setOption(option);
chart.on('click', function (params) {
// 隐藏tooltip
chart.dispatchAction({
type: 'hideTip',
});
// 设置礼物数据
vue.giftDetailList = data[params.name];
// 展示
vue.showGiftDetail = true;
});
},
// 打开设置弹窗
openSettingDialog : function(){
this.settingFormDialogVisible = true;
},
// 更改设置提交
handleSettingFormSubmit : function(){
var vue = this;
this.$refs.settingForm.validate((valid) => {
// 通过校验
if(valid){
this.hasGetSendGiftList = false;
this.hasGetReceiveGiftList = false;
this.showGiftDetail = false;
this.showGiftTrend = false;
this.send = 0;
this.receive = 0;
this.sendGiftList = [];
this.receiveGiftList = [];
this.giftDetailList = [];
this.sendUserList = [];
this.receiveUserList = [];
for(var uid in this.userInfo){
this.userInfo[uid] = {
uid : uid,
userName : this.userInfo[uid].userName,
photo : this.userInfo[uid].photo,
};
}
this.$message({
type : 'info',
message : '开始获取数据',
});
this.settingFormDialogVisible = false;
this.getSendGiftList(function(){
vue.getReceiveGiftList(function(){
vue.$message({
type : 'success',
message : '数据获取成功',
});
// 生成筛选文字
vue.filterText = vue.formatFilterText();
});
});
}
});
},
// 导出excel
exportGift : function(){
var vue = this;
var workbook = new ExcelJS.Workbook();
var sheet = workbook.addWorksheet('送出礼物用户排行榜');
sheet.columns = [
{ key: 'userName', width: 30, },
{ key: 'uid', width: 10, },
{ key: 'acoin', width: 20, },
];
var rowIndex = 1;
sheet.addRow({userName: '用户名', uid : '用户uid', 'acoin' : 'AC币'});
// 设置列名样式
var headerRow = sheet.getRow(rowIndex);
for(var i=1;i<=sheet.columns.length;++i){
headerRow.getCell(i).alignment = {vertical: 'middle', horizontal: 'center'};
headerRow.getCell(i).border = {
top: {style:'thin'},
left: {style:'thin'},
bottom: {style:'thin'},
right: {style:'thin'},
};
}
rowIndex += 1;
// 获取送出礼物用户排行
this.sendUserList.forEach(function(userInfo){
sheet.addRow({userName: userInfo.userName, uid : userInfo.uid, acoin:userInfo.send});
// 设置记录样式
var recordRow = sheet.getRow(rowIndex);
for(var i=1;i<=sheet.columns.length;++i){
// recordRow.getCell(i).alignment = {vertical: 'middle', horizontal: 'center'};
recordRow.getCell(i).border = {
top: {style:'thin'},
left: {style:'thin'},
bottom: {style:'thin'},
right: {style:'thin'},
};
}
rowIndex += 1;
});
sheet = workbook.addWorksheet('收到礼物用户排行榜');
sheet.columns = [
{ key: 'userName', width: 30, },
{ key: 'uid', width: 10, },
{ key: 'azuanAmount', width: 20, },
];
rowIndex = 1;
sheet.addRow({userName: '用户名', uid : '用户uid', 'azuanAmount' : '钻石'});
// 设置列名样式
var headerRow = sheet.getRow(rowIndex);
for(var i=1;i<=sheet.columns.length;++i){
headerRow.getCell(i).alignment = {vertical: 'middle', horizontal: 'center'};
headerRow.getCell(i).border = {
top: {style:'thin'},
left: {style:'thin'},
bottom: {style:'thin'},
right: {style:'thin'},
};
}
rowIndex += 1;
// 获取送出礼物用户排行
this.receiveUserList.forEach(function(userInfo){
sheet.addRow({userName: userInfo.userName, uid : userInfo.uid, azuanAmount:userInfo.receive});
// 设置记录样式
var recordRow = sheet.getRow(rowIndex);
for(var i=1;i<=sheet.columns.length;++i){
// recordRow.getCell(i).alignment = {vertical: 'middle', horizontal: 'center'};
recordRow.getCell(i).border = {
top: {style:'thin'},
left: {style:'thin'},
bottom: {style:'thin'},
right: {style:'thin'},
};
}
rowIndex += 1;
});
sheet = workbook.addWorksheet('送出礼物详情');
sheet.columns = [
{ key: 'userName', width: 30, },
{ key: 'uid', width: 10, },
{ key: 'createTimeText', width: 20, },
{ key: 'giftName', width: 20, },
{ key: 'giftCount', width: 20, },
{ key: 'acoin', width: 20, },
];
var rowIndex = 1;
sheet.addRow({userName: '用户名', uid : '用户uid', createTimeText : '送出时间', giftName:'礼物名称', giftCount:'礼物数量', acoin : 'AC币'});
// 设置列名样式
var headerRow = sheet.getRow(rowIndex);
for(var i=1;i<=sheet.columns.length;++i){
headerRow.getCell(i).alignment = {vertical: 'middle', horizontal: 'center'};
headerRow.getCell(i).border = {
top: {style:'thin'},
left: {style:'thin'},
bottom: {style:'thin'},
right: {style:'thin'},
};
}
rowIndex += 1;
// 获取送出礼物详情
this.sendGiftList.forEach(function(giftDetail){
sheet.addRow({userName: giftDetail.userName, uid : giftDetail.userId, createTimeText:giftDetail.createTimeText, giftName:giftDetail.giftName, giftCount:giftDetail.giftCount, acoin:giftDetail.acoin});
// 设置记录样式
var recordRow = sheet.getRow(rowIndex);
for(var i=1;i<=sheet.columns.length;++i){
// recordRow.getCell(i).alignment = {vertical: 'middle', horizontal: 'center'};
recordRow.getCell(i).border = {
top: {style:'thin'},
left: {style:'thin'},
bottom: {style:'thin'},
right: {style:'thin'},
};
}
rowIndex += 1;
});
sheet = workbook.addWorksheet('收到礼物详情');
sheet.columns = [
{ key: 'userName', width: 30, },
{ key: 'uid', width: 10, },
{ key: 'createTimeText', width: 20, },
{ key: 'giftName', width: 20, },
{ key: 'giftCount', width: 20, },
{ key: 'azuanAmount', width: 20, },
];
var rowIndex = 1;
sheet.addRow({userName: '用户名', uid : '用户uid', createTimeText : '收到时间', giftName:'礼物名称', giftCount:'礼物数量', azuanAmount : '钻石'});
// 设置列名样式
var headerRow = sheet.getRow(rowIndex);
for(var i=1;i<=sheet.columns.length;++i){
headerRow.getCell(i).alignment = {vertical: 'middle', horizontal: 'center'};
headerRow.getCell(i).border = {
top: {style:'thin'},
left: {style:'thin'},
bottom: {style:'thin'},
right: {style:'thin'},
};
}
rowIndex += 1;
// 获取送出礼物详情
this.receiveGiftList.forEach(function(giftDetail){
sheet.addRow({userName: giftDetail.userName, uid : giftDetail.userId, createTimeText:giftDetail.createTimeText, giftName:giftDetail.giftName, giftCount:giftDetail.giftCount, azuanAmount:giftDetail.azuanAmount});
// 设置记录样式
var recordRow = sheet.getRow(rowIndex);
for(var i=1;i<=sheet.columns.length;++i){
// recordRow.getCell(i).alignment = {vertical: 'middle', horizontal: 'center'};
recordRow.getCell(i).border = {
top: {style:'thin'},
left: {style:'thin'},
bottom: {style:'thin'},
right: {style:'thin'},
};
}
rowIndex += 1;
});
;(async function(){
var buffer = await workbook.xlsx.writeBuffer();
var file = new File([buffer], `【${moment().format('YYYY-MM-DD')}】acfun统计${vue.filterText}.xlsx`);
saveAs(file);
})();
},
// 展示趋势
handleShowGiftTrend : function(){
this.showGiftTrend = true;
this.$nextTick(function(){
this.renderGiftTrend();
});
},
// 切换趋势
handleSwitchToSendGiftTrend : function(){
this.switchToSendGiftTrend = !this.switchToSendGiftTrend;
this.$nextTick(function(){
this.renderGiftTrend();
});
},
// 跳转至用户主页
toUserSpace : function(userInfo){
window.open(config.ACFUN_SERVER + config.URLS.ACFUN_USER.SPACE + `/${userInfo.uid}`);
},
formatFilterText : function(){
var dateRegionText = null,isContainPeachText=null;
// 筛选了时间范围
if(this.settingFormData.dateRegion && this.settingFormData.dateRegion.length==2){
dateRegionText = `${moment(this.settingFormData.dateRegion[0]).format('YYYY-MM-DD')} 至 ${moment(this.settingFormData.dateRegion[1]).format('YYYY-MM-DD')}`;
}
if(!this.settingFormData.isContainPeach){
isContainPeachText = '不包含桃子';
}
var texts = _.filter([dateRegionText, isContainPeachText]).join('、');
if(isNullOrEmpty(texts)){
return '';
}
else{
return '(' + texts + ')';
}
},
},
computed : {
},
watch: {
// 监听趋势表单数据变化
giftTrendFormData : {
deep : true,
handler : function(newVal, oldVal){
if(this.showGiftTrend){
this.renderGiftTrend();
}
},
},
},
mounted : function(){
// 打开弹窗
this.openSettingDialog();
},
});
});
navEle.append(navItem);
return true;
}
window.onload = function(){
var intervalHandler = window.setInterval(function(){
if(loadVue()){
window.clearInterval(intervalHandler);
}
}, 500);
};
})();