acfun统计

acfun统计(目前只包含送出礼物和收到礼物的统计)

目前為 2021-02-27 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==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.9
// @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
// @require https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.9.0/viewer.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',
		ACFUN_API_SERVER : 'http://api-ipv6.app.acfun.cn',
		ACFUNLIVE_SERVER : 'https://live.acfun.cn',
		URLS : {
			ACFUN_USER : {
				INFO : '/rest/pc-direct/user/userInfo',
				PUSH : '/member/#area=push',
				FOLLOWING : '/member/#area=following',
				FOLLOWER : '/member/#area=followers',
				SPACE : '/u',
				FEED : '/rest/app/feed/followFeedV2',
			},
			WALLET : {
				SEND_GIFT : '/rest/apph5-direct/pay/reward/giveRecords',
				RECEIVE_GIFT : '/rest/apph5-direct/pay/reward/receiveRecords',
			}
		},

		HEADERS : {
			ACFUN_API_SERVER : {
				acPlatform : 'ANDROID_PHONE',
				appVersion : '6.40.1.486',
			},
		},

		UBB : {
			PATTERN : {
				AT : /\[at\s+uid=(?<uid>\d+)\]\@(?<userName>.+?)\[\/at\]/g,
				IMG : /\[img=(?<title>.+?)\](?<url>.+?)\[\/img\]/g,
			},
		},

	};
 
	
	// 是否为空
	function isNullOrEmpty(val){
		return _.isUndefined(val) || _.isNull(val) || _.isNaN(val) || (((_.isObject(val) && !_.isDate(val)) || _.isArray(val) || _.isString(val)) && _.isEmpty(val))
	}

	function matchAll(text, pattern){
		var result = [];
		for(var match of text.matchAll(pattern)){

			result.push({
				text : match[0],
				groups : match.groups,
			});
		}

		return result;
	}

	
	// 通用请求
	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');
	// 加载图片查看器样式
	addCssResource('https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.9.0/viewer.min.css');
 
	var statVue = null;
	var feedVue = null;
 
	// 加载统计页面Vue实例
	function loadStatVue(){
		
 
 		// 若vue已实例化,且对应的el元素存在,则表示已加载结束
		if(statVue && !document.querySelector('#acfunstat-container')){
			return true;
		}

		// 容器
		var navEle = document.querySelector('#list-guide-left');
 
 		// 容器不存在
		if(!navEle){
			return false;
		}

		// 添加导航选项
		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(){
 			e.stopPropatation = true;
 
	 		// 若vue已实例化,且对应的el元素存在,则表示已加载结束
			if(statVue && !document.querySelector('#acfunstat-container')){
				return;
			}

			// 删除其它菜单项的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');

 
			// 初始化实例
			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;
		
	}
 
	
	// 加载动态页面Vue实例
	function loadFeedVue(){
		
		var vue = null;
 
 		// 若vue已实例化,且对应的el元素存在,则表示已加载结束
		if(vue && !document.querySelector('#acfunfeed-container')){
			return true;
		}

		// 检查是否为“圈子”导航菜单
		pushEle = document.querySelector('#list-guide-left a[href="#area=push"]');
		if(pushEle){
			if(!pushEle.parentElement.parentElement.classList.contains('active')){
				return false;
			}
		}
		else{
			return false;
		}

		// 容器
		var navEle = document.querySelector('#block-banner-right');
 
		// 容器不存在,无法挂载
		if(!navEle){
			return false;
		}

		// 添加导航选项
		var navItem = document.createElement('a');
		navItem.id = 'area-feed';
		navItem.href = 'javascript:void(0)';
		navItem.classList.add('tab');
		navItem.innerHTML = `
			<i class="icon"></i>
			动态推送
			<span class="hint hidden hint-feed-left">(0)</span>
		`;

		// 添加元素
		navEle.append(navItem);

		// 监听点击事件
		navItem.addEventListener('click', function(e){

 			e.stopPropatation = true;

 
	 		// 若vue已实例化,且对应的el元素存在,则表示已加载结束
			if(feedVue && !document.querySelector('#acfunfeed-container')){
				return;
			}

			// 删除其它菜单项的active类
			var activeNavItem = navEle.querySelector('.active');
			activeNavItem.classList.remove('active');
			// 添加active类
			navItem.classList.add('active');

			history.replaceState(null, null, '/member/#area=feed');

			// 修改标题
			document.querySelector('#block-title-banner p').innerText = '动态推送';
			document.querySelector('#block-title-banner .d').innerText = 'Feed';
			document.title = '动态推送';

			// 分页HTML
			var paginatorHTML = `
				<div class="area-pager">
					<span class="pager pager-last" v-if="page>1" @click="toFirstPage"><i class="icon icon-step-backward" title="最初"></i></span>
					<span class="pager pager-fore" v-if="page>1" @click="toPrevPage"><i class="icon icon-chevron-left" title="上一页"></i></span>
					<span :class="{pager:true,'pager-fores':choosePage!=page,'pager-here':choosePage==page,'active':choosePage==page}" :data-page="choosePage"  @click="toJumpPage(choosePage)" :key="choosePage" v-for="choosePage in pages">{{choosePage}}</span>
					<span class="pager pager-hind" @click="toNextPage"><i class="icon icon-chevron-right" title="下一页"></i></span>
					<span class="pager pager-first" @click="toFinalPage"><i class="icon icon-step-forward" title="最末"></i></span>
					<span class="hint">当前位置:<input class="ipt-pager" type="number" v-model="jumpPage" :data-max="total"><button class="btn mini btn-pager" @click="toJumpPage(jumpPage)">跳页</button>&nbsp;&nbsp;共{{total}}页</span>
					<span class="clearfix"></span>
				</div>
			`;

			// 视频内容HTML
			var videoHTML = `
				<div :data-aid="feed.resourceId" :class="{block:true,item:!isInRepost}" :key="feed.resourceId">
					<div class="inner">
						<div class="l">
							<a target="_blank" :href="feed.shareUrl" class="thumb thumb-preview"><img :data-aid="feed.resourceId" :src="feed.coverUrl" class="preview" />
								<div class="cover"></div></a>
							<a target="_blank" :href="feed.userInfo.shareUrl" :title="feed.userInfo.hoverText" class="thumb thumb-avatar"><img :data-uid="feed.userInfo.id" :data-name="feed.userInfo.name" :src="feed.userInfo.headUrl" class="avatar" /></a>
						</div>
						<div class="r">
							<p class="block-title"><a :href="feed.channel.shareUrl" :title="feed.channel.hoverText" target="_blank" class="channel">{{feed.channel.name}}</a><a :data-aid="feed.resourceId" target="_blank" :href="feed.shareUrl" class="title">{{feed.caption}}</a></p>
							<div class="info">
								<a target="_blank" :data-uid="feed.userInfo.id" :href="feed.userInfo.shareUrl" class="name">{{feed.userInfo.name}}</a>&nbsp;&nbsp;/&nbsp;&nbsp;发布于
								<span class="time">{{feed.time}}</span>&nbsp;&nbsp;/&nbsp;&nbsp;播放:
								<span class="views pts">{{feed.detail.viewCount}}</span>&nbsp;&nbsp;评论:
								<span class="comments pts">{{feed.detail.commentCount}}</span>&nbsp;&nbsp;收藏:
								<span class="favors pts">{{feed.detail.stowCount}}</span>
							</div>
							<p class="desc">{{feed.detail.description}}</p>
							<div class="area-tag">
								<template v-if="feed.tag && feed.tag.length>0">
									<a class="tag" target="_blank" :key="tag.tagId" v-for="tag in feed.tag" :href="tag.shareUrl">{{tag.tagName}}</a>
								</template>
								<template v-else>
									该稿件暂无标签。
								</template>
							</div>
						</div>
						<span class="clearfix"></span>
					</div>
				</div>
				
			`;

			// 文章内容HTML
			var articleHTML = `

				<div :data-aid="feed.resourceId" :class="{block:true,item:!isInRepost}" :key="feed.resourceId">
					<div class="inner">
						<div class="l">
							<a target="_blank" :href="feed.shareUrl" class="thumb thumb-preview"><img :data-aid="feed.resourceId" :src="feed.coverUrl" class="preview" />
								<div class="cover"></div></a>
							<a target="_blank" :href="feed.userInfo.shareUrl" :title="feed.userInfo.hoverText" class="thumb thumb-avatar"><img :data-uid="feed.userInfo.id" :data-name="feed.userInfo.name" :src="feed.userInfo.headUrl" class="avatar" /></a>
						</div>
						<div class="r">
							<p class="block-title"><a :href="feed.channel.shareUrl" :title="feed.channel.hoverText" target="_blank" class="channel">{{feed.channel.name}}</a><a :data-aid="feed.resourceId" target="_blank" :href="feed.shareUrl" class="title">{{feed.caption}}</a></p>
							<div class="info">
								<a target="_blank" :data-uid="feed.userInfo.id" :href="feed.userInfo.shareUrl" class="name">{{feed.userInfo.name}}</a>&nbsp;&nbsp;/&nbsp;&nbsp;发布于
								<span class="time">{{feed.time}}</span>&nbsp;&nbsp;/&nbsp;&nbsp;播放:
								<span class="views pts">{{feed.viewCount}}</span>&nbsp;&nbsp;评论:
								<span class="comments pts">{{feed.commentCount}}</span>&nbsp;&nbsp;收藏:
								<span class="favors pts">{{feed.stowCount}}</span>
							</div>
							<p class="desc">{{feed.beginParagraph}}</p>
							<div class="area-tag">
								<template v-if="feed.tag && feed.tag.length>0">
									<a class="tag" target="_blank" :key="tag.tagId" v-for="tag in feed.tag" :href="tag.shareUrl">{{tag.tagName}}</a>
								</template>
								<template v-else>
									该稿件暂无标签。
								</template>
							</div>
						</div>
						<span class="clearfix"></span>
					</div>
				</div>
			`;

			// 动态内容HTML
			var activityHTML = `
				<div :data-aid="feed.resourceId" :class="{block:true,item:!isInRepost}" :key="feed.resourceId">
					<div :class="{inner : true, repost:feed.isRepost}">
						<div class="l" v-if="!feed.isRepost">
							<a target="_blank" class="thumb thumb-preview" @click.prevent.stop="handleActivityCoverClick(feed, $event)"><img :data-aid="feed.resourceId" :src="feed.coverUrl" class="preview" />
								<div class="cover"></div></a>
							<a target="_blank" :href="feed.userInfo.shareUrl" :title="feed.userInfo.hoverText" class="thumb thumb-avatar"><img :data-uid="feed.userInfo.id" :data-name="feed.userInfo.name" :src="feed.userInfo.headUrl" class="avatar" /></a>
						</div>
						<div class="r">
							<p class="block-title"><a href="javascript:void(0)" :title="feed.isRepost?'转发':'动态'" target="_blank" class="channel">{{feed.isRepost?'转发':'动态'}}</a><a :data-aid="feed.resourceId" target="_blank" :href="feed.shareUrl" class="title">{{feed.caption}}</a></p>
							<div class="info">
								<a target="_blank" :data-uid="feed.userInfo.id" :href="feed.userInfo.shareUrl" class="name">{{feed.userInfo.name}}</a>&nbsp;&nbsp;/&nbsp;&nbsp;发布于
								<span class="time">{{feed.time}}</span>
							</div>
							<p class="desc" style="white-space:pre-line;" v-html="feed.moment.htmlText" @click="handleActivityContentClick(feed, $event)"></p>

							
							<!-- 包含转发内容 -->
							<template v-if="feed.repostSource">
								
								<p class="btn-toggle-info"><span><i class="icon icon-chevron-down"></i>以下是转发内容</span></p>

								<div class="area-repost">
									<!-- 转发视频 -->
									<template v-if="feed.repostSource.isVideo">
										<feed-video :feed="feed.repostSource" :isInRepost="true"/>
									</template>
									<!-- 转发文章 -->
									<template v-else-if="feed.repostSource.isArticle">
										<feed-article :feed="feed.repostSource" :isInRepost="true"/>
									</template>
									<!-- 转发动态 -->
									<template v-if="feed.repostSource.isActivity">
										<feed-activity :feed="feed.repostSource" :isInRepost="true" @content-click="handleActivityContentClick"  @cover-click="handleActivityCoverClick"/>
									</template>
								</div>
							</template>
						</div>
						<span class="clearfix"></span>
					</div>

				</div>
			`;

			Vue.component('feed-paginator', {
				data : function(){
					return {
						page : 1,
						pageSize : 20,
						pageRange : 4,

						jumpPage : 1,
					};
				},
				methods : {
					toNextPage : function(){
						this.page += 1;
						this.jumpPage = this.page;
						this.$emit('change', {
							page : this.page,
							total : this.total,
							pageSize : this.pageSize,
							pcursor : this.pcursors[this.page-1],
						});
					},
					toPrevPage : function(){
						this.page -= 1;
						this.jumpPage = this.page;
						this.$emit('change', {
							page : this.page,
							total : this.total,
							pageSize : this.pageSize,
							pcursor : this.pcursors[this.page-1],
						});

					},
					toFinalPage : function(){
						this.page = this.total;
						this.jumpPage = this.page;
						this.$emit('change', {
							page : this.page,
							total : this.total,
							pageSize : this.pageSize,
							pcursor : this.pcursors[this.page-1],
						});
					},
					toFirstPage : function(){
						this.page = 1;
						this.jumpPage = this.page;
						this.$emit('change', {
							page : this.page,
							total : this.total,
							pageSize : this.pageSize,
							pcursor : this.pcursors[this.page-1],
						});
					},
					toJumpPage : function(page){
						if(page>this.total){
							this.$message({
								type : 'error',
								message : `无法跳至指定位置(页码不得大于${this.total})`,
							});
						}
						else{
							this.page = page;
							this.$emit('change', {
								page : this.page,
								total : this.total,
								pageSize : this.pageSize,
								pcursor : this.pcursors[this.page-1],
							});
						}
					},
				},
				computed : {
					total : function(){
						return this.pcursors.length;
					},
					minPage : function(){
						// 当前页码往前N页
						return Math.max(1, this.page - this.pageRange);
					},
					maxPage : function(){

						// 当前页码往后N页
						return Math.min(this.total, this.page + this.pageRange);
					},
					pages : function(){
						var minPage = this.minPage,maxPage = this.maxPage;
						
						var pages = [];
						for(var page=minPage;page<=maxPage;++page){
							pages.push(page);
						}

						return pages;

					},
				},
				props : ['pcursors', 'pcursor', 'page'],
				template : paginatorHTML,
			});

			Vue.component('feed-video', {
				data : function(){
					return {};
				},
				props : ['feed', 'isInRepost'],
				template : videoHTML,
			});

			Vue.component('feed-article', {
				data : function(){
					return {};
				},
				props : ['feed', 'isInRepost'],
				template : articleHTML,
			});

			Vue.component('feed-activity', {
				data : function(){
					return {};
				},
				props : ['feed', 'isInRepost'],
				methods : {
					// 点击动态内容
					handleActivityContentClick : function(feed, event){
						this.$emit('content-click', feed, event);
					},
					// 点击动态封面
					handleActivityCoverClick : function(feed, event){
						this.$emit('cover-click', feed, event);
					},
				},
				template : activityHTML,
			});


			// 修改展示内容
			document.querySelector('#block-first>.mainer').innerHTML = `

				<style>

 
					.btn-toggle-info{
						margin-top : 10px;
					    border-top: 1px dashed #999;
					    text-align: center;
					    color: #999;
					    height: 16px;
					    line-height: 16px;
					}
					.btn-toggle-info span{
					    display: block;
					    margin-top: -8px;
					    background-color: #fff;
					    width: 128px;
					}

					#block-first .name {
						color : #c66 !important;
					}

					#block-first .banner .more {
						overflow: visible;
						margin: 0 8px 0 0;
						padding: 0
					}

					#block-first .banner .more:hover {
						background: none;
						box-shadow: none
					}

					#block-first .mainer {
						padding: 8px
					}

					#block-first .unit .l {
						width: 120px;
						padding: 0 0 0 40px
					}

					#block-first .unit .r {
						width: 620px
					}

					#block-first .subtitle {
						margin: 4px 0;
						height: 24px;
						line-height: 24px;
						font-size: 13px;
						padding: 0 4px;
						border-radius: 2px;
						box-shadow: 0 1px 1px rgba(0,0,0,0.2);
						background-color: #c66;
						color: #fff;
						display: inline-block;
						*display: inline;
						cursor: default
					}

					#block-first .item {
						position: relative;
						overflow: hidden;
						border: 1px solid #eee;
						box-shadow: none;
						background-color: #fcfcfc
					}

					#block-first .item:hover .block-manage {
						right: 8px
					}

					#block-first .item .area-cont {
						width: auto;
						height: auto;
						margin: 8px 10px;
						padding: 8px;
						background-color: #ffe;
						color: #333;
						display: none;
						border: 1px solid #ddd;
						border-top: 1px solid #ebebeb;
						border-bottom: 1px solid #b7b7b7;
						box-shadow: 0 1px 1px rgba(0,0,0,0.1)
					}

					#block-first .item .desc {
						color: #666;
						margin: 4px auto 0
					}

					#block-first .item .block-manage {
						position: absolute;
						left: auto;
						top: auto;
						right: -128px;
						bottom: 8px;
						transition: .2s all ease .2s
					}

					#block-first .item .l {
						position: relative;
						width : 19%;
					}

					#block-first .item .r {
						position: relative;
						width : 78%;
					}

					#block-first .item .repost {
						width : 97%;
					}

					#block-first .item .repost>.r {
						position: relative;
						width : 100%;
					}

					#block-first .item .thumb {
						border: none;
						background: none;
						box-shadow: none
					}

					#block-first .item .preview {
						width: 122px;
						height: 69.5px
					}

					#block-first .item .avatar {
						width: 40px;
						height: 40px;
						box-shadow: 0 1px 4px rgba(0,0,0,0.3);
						background-color: #fff;
						border-radius: 2px
					}

					#block-first .item .thumb-preview {
						margin: 8px 0 16px 8px
					}

					#block-first .item .thumb-avatar {
						position: absolute;
						left: 96px;
						top: 45px
					}

					#block-first .item .block-title {
						margin: 10px auto 0
					}

					#block-first .item .channel {
						background-color: #c66;
						position: static;
						display: inline-block;
						*display: inline;
						margin: 0 4px 4px 0;
						padding: 0 4px
					}

					#block-first .item .title {
						color: #08c;
						font-size: 14px
					}

					#block-first .inner {
						position: relative
					}

					#block-first #list-feed-feed .item .info {
						color: #999;
						margin: 4px auto 0
					}

					#block-first .area-tag {
						display: inline-block;
						*display: inline;
						border-top: 1px dashed #ddd;
						margin: 8px 0 16px;
						padding: 8px 16px 0 0;
						color: #999;
						font-size: 12px
					}

					#block-first .area-tag a {
						margin: 0 8px 8px 0;
						color: #369
					}

					#block-first .area-repost {
						padding : 10px !important;
					}

					#block-first .area-repost .block .r{
						width : 76%;
					}


					#block-first .btn-history-delete {
						float: right;
						height: 24px;
						line-height: 24px;
						font-size: 12px;
						color: #999;
						background-color: #eee;
						padding: 0 8px;
						border-radius: 2px;
						box-shadow: inset 0 1px 2px rgba(0,0,0,0.2);
						cursor: pointer;
						font-family: "Microsoft YaHei","微软雅黑",tahoma,arial,simsun,"宋体";
						margin: 4px
					}

					#block-first .btn-history-delete:hover {
						color: #fff;
						background-color: #c33;
						box-shadow: inset 0 1px 2px rgba(0,0,0,0.5)
					}

					#block-first .removed {
						text-align: center;
						line-height: 8;
						color: #999
					}

					#block-first .hint-list-index {
						position: absolute;
						left: auto;
						top: auto;
						right: 12px;
						bottom: 0;
						font-size: 64px;
						line-height: 64px;
						height: 64px;
						width: auto;
						text-align: right;
						color: #eee;
						z-index: 0;
						letter-spacing: -.1em;
						cursor: default
					}

					#block-first .area-pager {
						padding: 0;
						margin: 8px auto
					}

					#block-first .area-pager .pager {
						min-width: 31px
					}

					#block-first .item-comms .area-cont {
						display: block
					}

					.no-rgba #block-first .item {
						border-color: #ccc
					}

					#list-channel-push {
						margin: 8px auto 16px;
						padding: 0 0 16px;
						border-bottom: 1px dashed #ddd
					}

					#list-group-push {
						overflow: visible;
						margin: 0 auto 16px;
						padding: 0 0 16px;
						border-bottom: 1px #ddd dashed
					}

					#list-group-push .item-push {
						display: inline-block;
						*display: inline;
						float: left;
						margin: 4px 8px 0 0;
						position: relative;
						overflow: hidden;
						border-color: rgba(0,0,0,0.1)
					}

					.btn-manage-push {
						min-width: 0;
						*width: auto;
						padding: 0
					}

					.btn-manage-push .icon {
						margin: 0 .2em
					}

					.btn-manage-push .item {
						background-color: #fff
					}

					@media screen and (min-width:1440px) {
						#list-feed-feed .item .r {
							width: 750px
						}

						#block-first .item .preview {
							width: 130px;
							height: 74px
						}

						#block-first .item .thumb-avatar {
							top: 48px;
							left: 104px
						}
					}

					#block-first .item .ubb-at {
						cursor : pointer;
						color : #08c;
					}

					#block-first .item .ubb-img {
						cursor : pointer;
						color : #08c;
					}

				</style>


				<p class="alert alert-info">目前还不支持交互功能,如评论、点赞、投蕉。。。</p>


				<div id="acfunfeed-container" v-cloak>

					<!-- 分页 -->
					<div>
						<feed-paginator :pcursors="pcursors" :pcursor="pcursor" :page="page" @change="getFeedList"/>
					</div>

					<div id="list-feed-feed">
						<template v-for="feed in feedList">

							<!-- 视频 -->
							<feed-video :feed="feed" :isInRepost="false" v-if="feed.isVideo"></feed-video>
							<!-- 文章 -->
							<feed-article :feed="feed" :isInRepost="false" v-else-if="feed.isArticle"></feed-article>
							<!-- 动态 -->
							<feed-activity :feed="feed" :isInRepost="false" v-else-if="feed.isActivity" @content-click="handleActivityContentClick" @cover-click="handleActivityCoverClick"></feed-activity>

						</template>
					</div>

					<!-- 分页 -->
					<div>
						<feed-paginator :pcursors="pcursors" :pcursor="pcursor" :page="page" @change="getFeedList"/>
					</div>

					<!-- 一个隐藏域用于显示图片 -->
					<div id="preview-image" class="hidden" v-if="previewImages && previewImages.length>0">
						<li v-for="image in previewImages"><img :src="image.originUrl?image.originUrl:image.url" :alt="image.title?image.title:'图片'"></li>
					</div>
				
				</div>
			`;
 
 
			// 初始化实例
			new Vue({
				el : '#acfunfeed-container',
				data : function(){
 
					return {
 						
 						page : 1,
 						pcursor : "0",
 						pcursors : ["0"],
 						feedList : [],

 						previewImages : null,
 
					};
				},
				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);
							}
 
						});
					},
					getFeedList : function(pageObj){
						
						var vue = this;
						
						this.page = pageObj.page;

						var position = $("#block-first").offset();
						position.top = position.top-60;
						$("html,body").animate({scrollTop:position.top}, 100);

						// 已获取结束
						if(pageObj.pcursor == "no_more"){
							callback(true, []);
							return;
						}

						commonRequrest(config.ACFUN_API_SERVER + config.URLS.ACFUN_USER.FEED, 'get',{pcursor : pageObj.pcursor,count:pageObj.pageSize,},true,
							function(isSuccess, data){

								if(!isSuccess){

									vue.$message({
										type : 'error',
										message : '获取动态推送失败',
									});

									return;

								}

								data = JSON.parse(data);

								// 最新一页
								if(pageObj.page == pageObj.total){
									vue.pcursors.push(data.pcursor);
								}

								data.feedList.forEach(function(feed){

									vue.processFeed(feed);

								});

								vue.feedList = data.feedList;

							}, config.HEADERS.ACFUN_API_SERVER,
						);
 
					},
					
					// 跳转至用户主页
					toUserSpace : function(userInfo){
						window.open(config.ACFUN_SERVER + config.URLS.ACFUN_USER.SPACE + `/${userInfo.uid}`);
					},
					
					// 处理动态
					processFeed : function(feed){

						feed.userInfo.shareUrl = `/u/${feed.userInfo.id}`;
						feed.userInfo.hoverText = `点击访问[${feed.userInfo.name}]的个人空间`;

						feed.tagResourceTypeText = this.getResourceText(feed.tagResourceType);

						// 动态类型
						if(feed.tagResourceType == 3){

							// 设置动态文本
							feed.moment.htmlText = this.ubb2html(feed, feed.moment.text);

							// 转发动态
							if(feed.repostSource){

								feed.isRepost = true;

								// 处理转发内容
								this.processFeed(feed.repostSource);

								feed.caption = `${feed.userInfo.name}转发了@${feed.repostSource.userInfo.name}的${feed.repostSource.tagResourceTypeText}`;
							

							}
							else{
								feed.caption = `${feed.userInfo.name}发布了新动态`;
							}
							feed.isActivity = true;
						}
						// 视频类型
						else if(feed.tagResourceType == 2){

							feed.channel.shareUrl = `/v/list${feed.channel.id}/index.htm`;
							feed.channel.hoverText = `点击访问${feed.channel.name}频道`;

							// 无简介
							if(!feed.detail.description){
								feed.detail.description = '此稿件暂无简介。';
							}


							// 包含标签
							if(feed.tag && feed.tag.length>0){
								feed.tag.forEach(function(tag){
									tag.shareUrl = `/search?keyword=${tag.tagName}`;
								});
							}

							feed.isVideo = true;

						}
						// 文章类型
						else if(feed.tagResourceType == 1){

							feed.caption = feed.articleTitle;

							feed.channel.shareUrl = `/v/list${feed.channel.id}/index.htm`;
							feed.channel.hoverText = `点击访问${feed.channel.name}频道`;


							// 包含标签
							if(feed.tag && feed.tag.length>0){
								feed.tag.forEach(function(tag){
									tag.shareUrl = `/search?keyword=${tag.tagName}`;
								});
							}


							feed.isArticle = true;
						}

					},

					// 获取动态类型
					getResourceText : function(resourceType){
						if(resourceType == 1){
							return '文章';
						}
						else if(resourceType == 2){
							return '视频';
						}
						else if(resourceType == 3){
							return '动态';
						}

					},

					// ubb转html
					ubb2html : function(feed, text){

						// 转化艾特
						var matchAt = matchAll(text, config.UBB.PATTERN.AT);

						matchAt.forEach(function(match){

							var html = `<a target="_blank" href="${config.ACFUN_SERVER + config.URLS.ACFUN_USER.SPACE}/${match.groups.uid}" class="ubb-at">@${match.groups.userName}</a>`;
							text = text.replace(match.text, html);

						});

						// 转化图片
						var matchImg = matchAll(text, config.UBB.PATTERN.IMG);

						var images = [];
						matchImg.forEach(function(match){

							var html = `<span class="ubb-img"><i class="icon icon-image"></i>${match.groups.title}</span>`;
							text = text.replace(match.text, html);

							images.push(match.groups);

						});

						if(images.length>0){
							feed.moment.imgs = images;
						}

						return text;

					},
					handleActivityContentClick : function(feed, event){
						
						// 点击查看图片
						if(event.target.classList.contains('ubb-img') || event.target.parentElement.classList.contains('ubb-img')){
							this.openImageViewer(feed.moment.imgs);
						}

					},
					handleActivityCoverClick : function(feed, event){

						// 查看动态图片
						if(feed.moment.imgs && feed.moment.imgs.length>0){
							this.openImageViewer(feed.moment.imgs);
						}

					},
					openImageViewer : function(images){

						this.previewImages = images;
						this.$nextTick(function(){

							// 已初始化,则更新图片数据
							if(this.gallery){
								this.gallery.update();
							}
							// 初始化
							else{
								this.gallery = new Viewer(document.getElementById('preview-image'));
							}

							
							this.gallery.show();
						});

					},

				},
				computed : {
					
				},
				
				mounted : function(){
 					this.getFeedList({
 						page : 1,
 						total : 1,
 						pcursor : "0",
 					});
				},
			});
 
		});
 
 
 
 
 
		return true;
		
	}



	function checkLoadVue(loadFunc){

		window.setTimeout(function(){

			var isSuccess = loadFunc();
			console.log('加载', isSuccess);
			if(!isSuccess){
				checkLoadVue();
			}

		}, 1000);

	}


	window.onload = function(){
 
		checkLoadVue(loadStatVue);

		// 推送页面
		if([config.ACFUN_SERVER + config.URLS.ACFUN_USER.PUSH, config.ACFUN_SERVER + config.URLS.ACFUN_USER.FOLLOWER, config.ACFUN_SERVER + config.URLS.ACFUN_USER.FOLLOWING].indexOf(window.location.href) != -1){
			checkLoadVue(loadFeedVue);
		}


	};

	window.onhashchange = function(event){
		// 推送页面
		if([config.ACFUN_SERVER + config.URLS.ACFUN_USER.PUSH, config.ACFUN_SERVER + config.URLS.ACFUN_USER.FOLLOWER, config.ACFUN_SERVER + config.URLS.ACFUN_USER.FOLLOWING].indexOf(window.location.href) != -1){
			checkLoadVue(loadFeedVue);
		}
	};
	
	
	
})();