您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
acfunlivedanmaku
// ==UserScript== // @name acfunlivedanmake // @description acfunlivedanmaku // @namespace syachiku // @author syachiku // @match https://live.acfun.cn/live/* // @run-at document-end // @grant GM_addStyle // @grant GM_getResourceURL // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @version 1.1.0 // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/qs.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/uuidv4.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/min/moment.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/lib/index.js // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/FileSaver.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/exceljs.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/build/clipboard-polyfill.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/keymaster.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/demo/easy-Danmaku.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.countdown.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/hotkeys.min.js // ==/UserScript== ;(async function(){ const config = { UID : parseInt(window.location.href.split('/').pop()), TOKEN : null, ACFUN_SERVER : 'https://www.acfun.cn', ACFUNLIVE_SERVER : 'https://live.acfun.cn', URLS : { USER : { INFO : '/user/info', }, ACFUN_USER : { VUP : '/user/acfun_user_info_simplified', INFO : '/rest/pc-direct/user/userInfo', SPACE : '/u' }, DOUGA : { COMMENT : '/rest/pc-direct/comment/list', VIDEO : '/v', ARTICLE : '/a', BANGUMI : '/bangumi' }, }, RESPONSE : { FIELD : { STATUS : 'code', MSG : 'message', DATA : 'data', }, STATUS : { SUCCESS : 200, } } }; const css = ` /* base html */ #header,#footer, .main>.list-container.outer-wrapper, .main>.list-container.outer-wrapper:before, .container-live>.left, .live-feed-watching, .container-live-feed-messages:before {display:none!important} #app>.main, .player-outer-wrapper, .player-outer-wrapper>.container-live, .player-outer-wrapper>.container-live>.container-live-feed.right, .player-outer-wrapper>.container-live>.container-live-feed.right>.live-feed, .player-outer-wrapper>.container-live>.container-live-feed.right>.live-feed>.container-live-feed-messages, .player-outer-wrapper>.container-live>.container-live-feed.right>.live-feed>.container-live-feed-messages>.live-feed-messages { display:block!important; position:fixed!important; width:100%!important; height:100%!important; margin:0!important; padding:0!important; border:0!important; top:0!important; bottom:0!important; word-break:break-all!important; } .live-feed-input{ display : none !important; } @keyframes scaleDraw { /*定义关键帧、scaleDrew是需要绑定到选择器的关键帧名称*/ 0%{ transform: scale(1); /*开始为原始大小*/ } 25%{ transform: scale(1.5); /*放大1.1倍*/ } 50%{ transform: scale(1); } 75%{ transform: scale(1.5); } } .scale-anime{ -webkit-animation: scaleDraw 5s ease-in-out; } .container-live-feed-messages-acfunlive:before{ display:none!important; } .container-live-feed-messages-acfunlive{ display:block!important; position:fixed!important; width:100%!important; height:100%!important; margin:0!important; padding:0!important; border:0!important; top:0!important; bottom:0!important; word-break:break-all!important; } .container-live-feed-messages-acfunlive .live-message-container.live-message-container-vertical{ height: 100%; overflow-y: auto; } .container-live-feed-messages-acfunlive .live-message-container.live-message-container-horizontal{ width: 100%; height: 100%; overflow-x: auto; overflow-y: hidden; display : flex; flex-direction: column; flex-wrap: wrap; } .container-live-feed-messages-acfunlive .live-message-container.live-message-container-vertical.active::-webkit-scrollbar{ width: 10px; height: 1px; } .container-live-feed-messages-acfunlive .live-message-container.live-message-container-vertical.inactive::-webkit-scrollbar{ display:none; } .container-live-feed-messages-acfunlive .live-message-container.live-message-container-vertical::-webkit-scrollbar-thumb { border-radius: 10px; -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); background: #535353; } .container-live-feed-messages-acfunlive .live-message-container.live-message-container-vertical::-webkit-scrollbar-track { -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); border-radius: 10px; background: #EDEDED; } .container-live-feed-messages-acfunlive .live-message-container.live-message-container-horizontal.active::-webkit-scrollbar{ height: 10px; width: 1px; } .container-live-feed-messages-acfunlive .live-message-container.live-message-container-horizontal.inactive::-webkit-scrollbar{ display:none; } .container-live-feed-messages-acfunlive .live-message-container.live-message-container-horizontal::-webkit-scrollbar-thumb { border-radius: 10px; -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); background: #535353; } .container-live-feed-messages-acfunlive .live-message-container.live-message-container-horizontal::-webkit-scrollbar-track { -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); border-radius: 10px; background: #EDEDED; } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup{ display:flex; padding: 7px; width: 100%; } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-popup-right{ margin-left : 5px; width: 90%; } @keyframes clippath{ 0%, 100% {clip-path: inset(0 0 100% 0);} 25% {clip-path: inset(0 100% 0 0);} 50% {clip-path: inset(100% 0 0 0);} 75% {clip-path: inset(0 0 0 100%);} } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-border-flow{ position: relative; } .live-message-border-flow .border-flow-item::before,.live-message-border-flow .border-flow-item::after{ content: ""; position: absolute; transition: all .5s; animation: clippath 3s infinite linear; } .live-message-border-flow .border-flow-item::after{ animation: clippath 3s -1.5s infinite linear; } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-danmaku{ margin-top: 3px; padding: 5px 12px 5px 12px; box-sizing: border-box; word-break: break-all; cursor: pointer; } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-danmaku .live-message-douga{ margin-top: 10px; } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-danmaku .live-message-douga .el-card{ background: transparent; border: transparent; box-shadow: 0px 2px 12px rgba(0, 0, 0, 30%); border-radius: 0px; } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-danmaku .live-message-douga .el-card__body{ padding: 10px; } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-danmaku .live-message-douga .douga-info{ } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-danmaku .live-message-douga .douga-info .douga-info-right{ height : 100%; display:flex; flex-direction:column; justify-content:space-between; } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-danmaku .live-message-douga .douga-info .cover{ display:inline-block; border-radius : 4px; } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-danmaku .live-message-douga .douga-info .cover >img{ object-fit:cover; display: block; height: 100%; vertical-align: middle; } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-danmaku .live-message-douga .douga-info .title-container{ overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-danmaku .live-message-douga .douga-info.article .title{ overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-danmaku .live-message-douga .douga-info.article .description{ overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; filter : invert(100%); } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-danmaku .live-message-douga .douga-info .up{ overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-danmaku .live-message-douga .douga-info .play-count{ } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-gift{ width: max-content; display: table-cell; margin-top: 3px; padding: 5px 12px 5px 12px; box-sizing: border-box; word-break: break-all; } .container-live-feed-messages-acfunlive .live-message-container .live-message-popup .live-message-gift .live-message-gift-count{ pointer-events: none; display: inline-block; } .user-info-badge{ border-radius: 4px; padding-left: 4px; padding-right: 4px; color: white; } .user-info-badge-green{ background-image: linear-gradient(30deg, #14bd5a, #40E584, #01b54c); } .user-info-badge-blue{ background-image: linear-gradient(30deg, #32A9DE, #4fbdef, #0e9ada); } .user-info-badge-orange{ background-image: linear-gradient(30deg, #eb9f19, #e6a01b, #f19b00); } .user-info-badge-red{ background-image: linear-gradient(30deg, #d43535, #e25537, #e94a47); } .user-info-badge-purple{ background-image: linear-gradient(30deg, #4801FF, #7918F2, #AC32E4); } .user-info-badge-black{ background-image: linear-gradient(30deg, #5e659d, #5e659d, #3c4270); } .user-info-badge-vup{ background-image: linear-gradient(30deg, #32A9DE, #4fbdef, #0e9ada); } .user-info-username{ } .container-live-feed-messages-acfunlive .live-message-container .live-message-inline{ text-align : center; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; overflow: hidden; } .container-live-feed-messages-acfunlive .live-feed-dropmenu.live-feed-dropmenu-horizontal{ display:block; position:absolute; top : 50px; left : 50px; z-index : 999999; } .container-live-feed-messages-acfunlive .live-feed-dropmenu.live-feed-dropmenu-vertical{ display:block; position:absolute; top : 50px; right : 50px; z-index : 999999; } /*.live-feed-input:hover{ opacity : 1; }*/ @font-face{ font-family:element-icons; src:url('https://cdn.jsdelivr.net/npm/[email protected]/lib/theme-chalk/fonts/element-icons.ttf'); } .lottery-form-dialog { z-index : 999999; height: 400px; } .lottery-form-dialog .el-dialog__body{ height : 80%; overflow-y: auto; } .lottery-form .gift-selector .el-select-dropdown__item{ height : 40px; line-height : 40px; } .lottery-form .el-divider{ margin-top : 40px; } .lottery-form .el-divider .el-divider__text{ color : #409EFF; } .lottery-form .douga-list-wrapper{ overflow:auto; height:200px; } .lottery-form .douga-list-wrapper .douga-list .douga-list-item.video .douga-info{ height : 100px; } .lottery-form .douga-list-wrapper .douga-list .douga-list-item.article .douga-info{ height : 60px; } .lottery-form .douga-list-wrapper .douga-list .douga-list-item .douga-info .douga-info-right{ height : 100%; display:flex; flex-direction:column; justify-content:space-between; } .lottery-form .douga-list-wrapper .douga-list .douga-list-item .cover{ display:inline-block; height:100px; width:177px; line-height:100px; border-radius : 4px; } .lottery-form .douga-list-wrapper .douga-list .douga-list-item .cover >img{ object-fit:cover; display: block; height: 100%; vertical-align: middle; } .lottery-form .douga-list-wrapper .douga-list .douga-list-item.video .title{ height:60px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; font-weight : bold; } .lottery-form .douga-list-wrapper .douga-list .douga-list-item.article .title{ height:40px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; text-decoration : underline; font-weight : bold; } .lottery-form .douga-list-wrapper .douga-list .douga-list-item .el-card:hover{ background-color : #409effb0; cursor:pointer; color : white; } .lottery-form .douga-list-wrapper .douga-list .douga-list-item.active .el-timeline-item__tail{ border-left: 2px solid #409EFF; } .lottery-form .douga-list-wrapper .douga-list .douga-list-item.active .el-timeline-item__node{ background-color : #409EFF; } .lottery-form .douga-list-wrapper .douga-list .douga-list-item.active .el-card{ color : white; background-color : #409eff; } .lottery-table .lottery-status-finish{ background: #8aec53; } .lottery-table-dialog{ z-index : 999999; } .lottery-table-dialog .el-dialog__body{ height : 80%; overflow-y: auto; } .user-table-dialog{ z-index : 999999; } .user-table-dialog .el-dialog__body{ height : 80%; overflow-y: auto; } .lottery-countdown-dialog{ z-index : 999999; background-color : rgba(0,0,0,0) !important; box-shadow : none !important; } .lottery-countdown-dialog button[data-setter] { outline: none; background: transparent; border: none; font-family: 'Roboto'; font-weight: 300; font-size: 18px; width: 25px; height: 30px; color: #409EFF; cursor: pointer; } .lottery-countdown-dialog button[data-setter]:hover { opacity: 0.5; } .lottery-countdown-dialog .container { position: relative; top: 30px; width: 300px; margin: 0 auto; } .lottery-countdown-dialog .setters { position: absolute; left: 85px; top: 75px; } .lottery-countdown-dialog .minutes-set { float: left; margin-right: 28px; } .lottery-countdown-dialog .seconds-set { float: right; } .lottery-countdown-dialog .controlls { position: absolute; left: 75px; top: 105px; text-align: center; } .lottery-countdown-dialog .display-remain-time { font-family: 'Roboto'; font-weight: bold; font-size: 65px; color: #409EFF; } .lottery-countdown-dialog #pause { outline: none; background: transparent; border: none; margin-top: 10px; width: 50px; height: 50px; position: relative; } .lottery-countdown-dialog .play::before { display: block; content: ""; position: absolute; top: 8px; left: 16px; border-top: 15px solid transparent; border-bottom: 15px solid transparent; border-left: 22px solid #409EFF; } .lottery-countdown-dialog .pause::after { content: ""; position: absolute; top: 8px; left: 12px; width: 15px; height: 30px; background-color: transparent; border-radius: 1px; border: 5px solid #409EFF; border-top: none; border-bottom: none; } .lottery-countdown-dialog #pause:hover { opacity: 0.8; } .lottery-countdown-dialog .e-c-base { fill: none; stroke: #B6B6B6; stroke-width: 15px; } .lottery-countdown-dialog .e-c-progress { fill: none; stroke: #409EFF; stroke-width: 15px; transition: stroke-dashoffset 0.7s; } .lottery-countdown-dialog .e-c-pointer { fill: #FFF; stroke: #409EFF; stroke-width: 2px; } .lottery-countdown-dialog #e-pointer { transition: transform 0.7s; } .lottery-start-dialog{ z-index : 999999; } .lottery-start-dialog .el-carousel__item{ background-color: #99a9bf; opacity: 0.75; margin: 0; display:flex; width : 250px; justify-content:center; align-items:center; flex-direction:column; } .lottery-start-dialog .el-dialog__header{ display:none; } .lottery-start-dialog .el-carousel__item.highlight{ background-color: gold; } .lottery-start-dialog .el-carousel__item .nickname{ font-size : 20px; color : white; text-shadow : 0px 2px 2px black, 0px -2px 2px black, 2px 0px 2px black, -2px 0px 2px black, 2px 2px 2px black, -2px -2px 2px black, 2px -2px 2px black, -2px 2px 2px black; font-weight: bold; } .login-form-dialog { z-index : 999999; height: 400px; } .audio-form-dialog { z-index : 999999; height: 400px; } .audio-form-dialog .el-dialog__body{ height : 80%; overflow-y: auto; } .interaction-form-dialog { z-index : 999999; height: 400px; } .interaction-form-dialog .el-dialog__body{ height : 80%; overflow-y: auto; } .interaction-form .el-divider .el-divider__text{ color : #409EFF; } .guess-form-dialog { z-index : 999999; height: 400px; } .guess-form-dialog .el-dialog__body{ height : 100%; overflow-y: auto; } .guess-start-dialog { z-index : 999999; height: 400px; } .guess-start-dialog .el-dialog__body{ height : 100%; overflow-y: auto; } .guess-danmaku-dialog { z-index : 999999; height: 400px; } .guess-danmaku-dialog .el-dialog__body{ height : 100%; overflow-y: auto; } .guess-danmaku-dialog .guess-danmaku-container{ height : 100%; width : 100%; } .guess-danmaku-dialog .guess-danmaku-danmu{ display : flex; color: rgb(255, 255, 255); font-size: 25px; font-family: buding; text-shadow: rgb(0 0 0) 0px 1px 1px, rgb(0 0 0) 0px -1px 1px, rgb(0 0 0) 1px 0px 1px, rgb(0 0 0) -1px 0px 1px, rgb(0 0 0) 1px 1px 1px, rgb(0 0 0) -1px -1px 1px, rgb(0 0 0) 1px -1px 1px, rgb(0 0 0) -1px 1px 1px; cursor : pointer; } .guess-danmaku-dialog .guess-danmaku-danmu.is-select{ border : 1px solid red; } .guess-danmaku-dialog .guess-danmaku-danmu >img{ width : 20px; height : 20px; border-radius : 10px; } .guess-table-dialog { z-index : 999999; height: 400px; } .guess-table-dialog .el-dialog__body{ height : 100%; overflow-y: auto; } `; GM_addStyle(css); var audio = null; // 检查token是否存在 var token = await GM_getValue("token"); if(token){ config.TOKEN = token; } // 禁止播放视频 function disableVideos(){ window.setInterval(function(){ let videoEles = document.querySelectorAll('video'); for(let videoEle of videoEles){ videoEle.src = null; } }, 500); } // 是否为空 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 formatText(text, params){ for(var key in params){ text = text.replace(new RegExp('\\$\\{'+ key +'\\}', 'g'), params[key]); } return text; } function addCssResource(url){ commonRequrest(url, 'get', null, true, function(isSuccess, css){ if(isSuccess){ GM_addStyle(css); } }) } // 添加element-ui样式 addCssResource('https://cdn.jsdelivr.net/npm/[email protected]/lib/theme-chalk/index.css'); class CallbackManager{ constructor(feedback){ this.callbacks = {}; this.callbackGroupMapper = {}; } register(group, func, params, first){ if(!(group in this.callbacks)){ this.callbacks[group] = []; } var callback = { id : uuidv4(), func : func, params : params }; // 添加到最前 if(first){ this.callbacks[group].splice(0, 0, callback); } else{ this.callbacks[group].push(callback); } this.callbackGroupMapper[callback.id] = group; return callback.id; } cancel(handler){ if(!(handler in this.callbackGroupMapper) || !(this.callbackGroupMapper[handler] in this.callbacks)){ return; } var findIndex = _.findIndex(this.callbacks[this.callbackGroupMapper[handler]], {id:handler}); if(findIndex==-1){ return; } this.callbacks[this.callbackGroupMapper[handler]].splice(findIndex, 1); delete this.callbackGroupMapper[handler]; } feed(group, data){ if(!(group in this.callbacks)){ return; } this.callbacks[group].forEach(function(callback){ callback.func(data, callback.params); }); } } var callbackManager = new CallbackManager(); const acSeriesPattern = /[aA][aAbBcC][=号]?\s*(\d+)/; function extractAcSeries(text){ var match = text.match(acSeriesPattern); if(match){ return parseInt(match[match.length-1]); } else{ return null; } } const giftPattern = /送出((?<count>\d+)个)?(?<name>.+)/; function extractGift(text){ var match = text.match(giftPattern); if(match){ return { name : match.groups.name, count : match.groups.count?parseInt(match.groups.count):1, }; } else{ return null; } } const modalClassNamePattern = /medal-lv-(?<level>\d+)/; function extractLevel(text){ var match = text.match(modalClassNamePattern); if(match){ return parseInt(match.groups.level); } else{ return null; } } const commandPattern = /^\/(?<command>[^s]+)\s+(?<text>[^s]+)$/; function extractCommand(text){ var match = text.match(commandPattern); if(match){ return match.groups; } else{ return null; } } var userInfo = {}; var vupInfo = {}; var refreshTimeoutHandler = null; // 开始 function start(){ // 监听弹幕添加 var messageContainer = document.querySelector('.live-feed-messages'); var observer = new MutationObserver(function(mutations, observer){ // 遍历改变 mutations.forEach(function(mutation){ // 子节点发生变化 if(mutation.type == 'childList'){ if(refreshTimeoutHandler){ window.clearTimeout(refreshTimeoutHandler); } // 3分钟内没接收到信息,刷新 refreshTimeoutHandler = window.setTimeout(()=>window.location.reload(), 3 * 60 * 1000); // 遍历新增节点 mutation.addedNodes.forEach(function(node){ // 获取用户名元素 var userEle = node.querySelector('.nickname'); var userName = userEle.innerText; var uid = null; var badgeName = null; var badgeLevel = null; var badgeColor = null; // 查看是否有徽章 var badgeContainerEle = node.querySelector('.medal-wrapper'); if(badgeContainerEle){ badgeName = badgeContainerEle.querySelector('.medal-name').innerText; badgeContainerEle.classList.forEach(function(className){ if(extractLevel(className)!=null){ badgeLevel = extractLevel(className); } }); if(badgeLevel >= 1 && badgeLevel <= 3){ badgeColor = 'green'; } else if(badgeLevel >= 4 && badgeLevel <= 6){ badgeColor = 'blue'; } else if(badgeLevel >= 7 && badgeLevel <= 9){ badgeColor = 'orange'; } else if(badgeLevel >= 10 && badgeLevel <= 12){ badgeColor = 'red'; } else if(badgeLevel >= 13 && badgeLevel <= 15){ badgeColor = 'purple'; } else if(badgeLevel >= 16 && badgeLevel <= 20){ badgeColor = 'black'; } } if(userEle && userEle.attributes['data-user-id']){ uid = parseInt(userEle.attributes['data-user-id'].value); } var interaction = { id : uuidv4(), sendTime : new Date(), }; // 弹幕 if(node.classList.contains('comment')){ interaction.type = 'danmaku'; interaction.content = _.trimStart(node.querySelector('.comment-text').innerText, ':'); } // 送礼 else if(node.classList.contains('gift')){ var giftText = userEle.nextElementSibling.innerText; var gift = extractGift(giftText); interaction.type = 'gift'; interaction.giftName = gift.name; interaction.giftCount = gift.count; } // 点赞 else if(node.classList.contains('like')){ interaction.type = 'like'; } // 进入直播间 else if(node.classList.contains('user-enter')){ interaction.type = 'enterroom'; } // 关注了主播 else if(node.classList.contains('follow')){ interaction.type = 'follow'; } // 加入守护团 else if(node.classList.contains('join-club')){ interaction.type = 'joinclub'; } // vup if(uid in vupInfo){ addBadgeToUser(userEle); } if(uid in userInfo){ callbackManager.feed('message', { uid : uid, vup : uid in vupInfo, userName : userName, badgeName : badgeName, badgeLevel : badgeLevel, badgeColor : badgeColor, photo : userInfo[uid].photo, interaction : interaction, }); } else{ // 获取用户信息 commonRequrest(config.ACFUNLIVE_SERVER + config.URLS.ACFUN_USER.INFO + `?userId=${uid}`, 'get', null, true, function(isSuccess, data){ var photo = null; if(data){ data = JSON.parse(data); if(data.result == 0){ photo = data.profile.headUrl; } } userInfo[uid] = { userName : userName, photo : photo, }; callbackManager.feed('message', { uid : uid, vup : uid in vupInfo, userName : userName, photo : userInfo[uid].photo, badgeName : badgeName, badgeLevel : badgeLevel, badgeColor : badgeColor, interaction : interaction, }); }); } }); } }); }); observer.observe(messageContainer, {childList:true}); } // 加载Vue实例 function loadVue(){ var vue = null; // 获取礼物列表 var giftList = []; var giftContainerEles = document.querySelectorAll('.item-gift'); giftContainerEles.forEach(function(giftContainerEle, giftIndex){ var gift = { index : giftIndex, id : giftContainerEle.attributes['data-gift-id'].value, name : giftContainerEle.querySelector('.name').textContent, price : _.parseInt(giftContainerEle.attributes['data-gift-price'].value), img : giftContainerEle.querySelector('img').attributes['src'].value, }; // 设置香蕉的价格为0 if(gift.name == '香蕉'){ gift.price = 0; } giftList.push(gift); }); // 无法获取礼物列表 if(giftList.length==0){ return; } // 将礼物按照AC币排序 giftList = _.sortBy(giftList, ['price', 'index']); // 隐藏原有弹幕 document.querySelector('.container-live-feed-messages').style.setProperty('display', 'none', 'important'); // 添加悬浮菜单 // 容器 var containerEle = document.querySelector('.container-live-feed .live-feed'); // 悬浮菜单元素 var menuEle = document.createElement('div'); menuEle.className = 'container-live-feed-messages-acfunlive'; menuEle.innerHTML = ` <div :class="{'live-message-container':true, 'active':mouseOn, 'inactive':!mouseOn, 'live-message-container-horizontal':interactionFormData.direction=='horizontal', 'live-message-container-vertical':interactionFormData.direction!='horizontal'}" :style="backgroundStyle"> <template v-for="message in messageData"> <!--弹幕--> <template v-if="message.interaction.type=='danmaku' && message.interaction.content"> <div class="live-message-popup" :style="danmakuMessageContainerStyle" :key="message.interaction.id"> <div class="live-message-popup-left"> <el-avatar shape="circle" fit="fill" :size="userPhotoSize" :src="message.photo"></el-avatar> </div> <div class="live-message-popup-right"> <div class="user-info-container"> <span class="user-info-badge user-info-badge-vup" :style="userBadgeStyle" v-if="message.vup">VUP</span> <span :style="userBadgeStyle" :class="{'user-info-badge':true,'user-info-badge-black':message.badgeColor=='black','user-info-badge-purple':message.badgeColor=='purple','user-info-badge-red':message.badgeColor=='red','user-info-badge-orange':message.badgeColor=='orange','user-info-badge-blue':message.badgeColor=='blue','user-info-badge-green':message.badgeColor=='green'}" v-if="message.badgeName">LV.{{message.badgeLevel}} {{message.badgeName}}</span> <span class="user-info-username" :style="userNameMessageStyle">{{message.userName}}</span> </div> <div :class="danmakuMessageClass.concat([!lastDanmakuMessage || message.interaction.id == lastDanmakuMessage.interaction.id?'active':'inactive'])" :style="danmakuMessageStyle"> <div class="border-flow-item" :style="borderFlowItemStyle"></div> <span @click="clickMessage(message)">{{message.interaction.content}}</span> <div class="live-message-douga" @click="clickMessage(message, true)" v-if="message.interaction.douga"> <el-card :title="message.interaction.douga.title" :style="danmakuDougaMessageStyle"> <el-row :class="{'douga-info':true, 'article':message.interaction.douga.type == 'article', 'video':['video', 'bangumi'].indexOf(message.interaction.douga.type) != -1}" :style="danmakuDougaContainerStyle"> <template v-if="message.interaction.douga.type == 'video'"> <div class="douga-info-left" :style="danmakuDougaLeftColStyle"> <span class="cover" :style="danmakuDougaCoverStyle"> <img :src="message.interaction.douga.cover"> </span> </div> <div class="douga-info-right" :style="danmakuDougaRightColStyle"> <div class="title-container" :style="danmakuDougaTitleStyle"><span>{{message.interaction.douga.title}}</span></div> <div class="info" :style="danmakuDougaInfoStyle"> <p class="up"><span>up主:</span><span>{{message.interaction.douga.userName}}</span></p> <p class="play-count" :style="danmakuDougaInfoStyle">播放量:<span>{{message.interaction.douga.playCountText}}</span></p> </div> </div> </template> <template v-if="message.interaction.douga.type == 'article'"> <div class="title-container" :style="danmakuDougaTitleStyle"> <p class="title">{{message.interaction.douga.title}}</p> <p class="description" :style="danmakuDougaDescriptionStyle">{{message.interaction.douga.description}}</p> </div> <div class="info" :style="danmakuDougaInfoStyle"> <p class="up"><span>up主:</span><span>{{message.interaction.douga.userName}}</span></p> <p class="play-count" :style="danmakuDougaInfoStyle">访问量:<span>{{message.interaction.douga.playCountText}}</span></p> </div> </template> <template v-if="message.interaction.douga.type == 'bangumi'"> <div class="douga-info-left" :style="danmakuDougaLeftColStyle"> <span class="cover" :style="danmakuDougaCoverStyle"> <img :src="message.interaction.douga.cover"> </span> </div> <div class="douga-info-right" :style="danmakuDougaRightColStyle"> <div class="title-container" :style="danmakuDougaTitleStyle"> <el-tag effect="dark" type="danger" v-if="message.interaction.douga.acfunOnly">A站独播</el-tag> <span>{{message.interaction.douga.title}}</span> </div> <div class="info" :style="danmakuDougaInfoStyle"> <p class="stow-count" :style="danmakuDougaInfoStyle">追番人数:<span>{{message.interaction.douga.stowCountText}}</span></p> <p class="play-count" :style="danmakuDougaInfoStyle">播放量:<span>{{message.interaction.douga.playCountText}}</span></p> </div> </div> </template> </el-row> </el-card> </div> </div> </div> </div> </template> <!--点赞--> <template v-if="message.interaction.type=='like' && message.interaction.content"> <div class="live-message-inline" :style="likeMessageContainerStyle" :key="message.interaction.id"> <span :style="likeMessageStyle"> <span v-if="message.vup">【VUP】</span> <span class="user-info-username">{{message.userName}}</span> <span>{{message.interaction.content}}</span> </span> </div> </template> <!--礼物--> <template v-if="message.interaction.type=='gift' && message.interaction.content"> <div class="live-message-popup" :style="giftMessageContainerStyle" :key="message.interaction.id"> <div class="live-message-popup-left"> <el-avatar shape="circle" fit="fill" :size="userPhotoSize" :src="message.photo"></el-avatar> </div> <div class="live-message-popup-right"> <div class="user-info-container"> <span :style="userBadgeStyle" class="user-info-badge user-info-badge-vup" v-if="message.vup">VUP</span> <span :style="userBadgeStyle" :class="{'user-info-badge':true,'user-info-badge-black':message.badgeColor=='black','user-info-badge-purple':message.badgeColor=='purple','user-info-badge-red':message.badgeColor=='red','user-info-badge-orange':message.badgeColor=='orange','user-info-badge-blue':message.badgeColor=='blue','user-info-badge-green':message.badgeColor=='green'}" v-if="message.badgeName">LV.{{message.badgeLevel}} {{message.badgeName}}</span> <span class="user-info-username" :style="userNameMessageStyle">{{message.userName}}</span> </div> <div class="live-message-gift" :style="giftMessageStyle"> <span >{{message.interaction.content}}</span> <el-avatar shape="square" :size="giftImageSize" fit="fill" :src="giftNameMapper[message.interaction.giftName].img" style="background-color:transparent;vertical-align:bottom;"></el-avatar> <span :class="{'live-message-gift-count':true, 'scale-anime':message.interaction.doAnime}" v-if="message.interaction.giftCount>0" :style="giftCountStyle"> x{{message.interaction.giftCount}} </span> </div> </div> </div> </template> <!--进入直播间--> <template v-if="message.interaction.type=='enterroom' && message.interaction.content"> <div class="live-message-inline" :style="enterroomMessageContainerStyle" :key="message.interaction.id"> <span :style="enterroomMessageStyle"> <span v-if="message.vup">【VUP】</span> <span class="user-info-username">{{message.userName}}</span> <span class="live-message-enterroom">{{message.interaction.content}}</span> </span> </div> </template> <!--关注--> <template v-if="message.interaction.type=='follow' && message.interaction.content"> <div class="live-message-inline" :style="followMessageContainerStyle" :key="message.interaction.id"> <span :style="followMessageStyle"> <span v-if="message.vup">【VUP】</span> <span class="user-info-username">{{message.userName}}</span> <span class="live-message-follow">{{message.interaction.content}}</span> </span> </div> </template> <!--加入守护团--> <template v-if="message.interaction.type=='joinclub' && message.interaction.content"> <div class="live-message-inline" :style="joinclubMessageContainerStyle" :key="message.interaction.id"> <span :style="joinclubMessageStyle"> <span v-if="message.vup">【VUP】</span> <span class="user-info-username">{{message.userName}}</span> <span class="live-message-joinclub">{{message.interaction.content}}</span> </span> </div> </template> </template> </div> <div :class="{'live-feed-dropmenu':true, 'live-feed-dropmenu-horizontal':interactionFormData.direction=='horizontal','live-feed-dropmenu-vertical':interactionFormData.direction!='horizontal'}"> <el-dropdown trigger="click" @command="handleDropdownMenuClick"> <span class="el-dropdown-link" style="font-size:32px;"> <i class="el-icon-menu"></i> </span> <el-dropdown-menu slot="dropdown"> <el-dropdown-item icon="el-icon-edit" command="editInteraction">弹幕编辑</el-dropdown-item> <el-dropdown-item> <el-dropdown trigger="hover" placement="right-start" trigger="click" @command="handleDropdownMenuClick"> <span class="el-icon-lollipop"> 直播抽奖<i class="el-icon-arrow-down el-icon--right"></i> </span> <el-dropdown-menu slot="dropdown"> <el-dropdown-item icon="el-icon-circle-plus" command="newLottery">添加抽奖</el-dropdown-item> <el-dropdown-item icon="el-icon-info" command="lotteryTable">查看抽奖</el-dropdown-item> <el-dropdown-item icon="el-icon-download" command="exportLottery">导出名单</el-dropdown-item> </el-dropdown-menu> </el-dropdown> </el-dropdown-item> <!-- <el-dropdown-item> <el-dropdown trigger="hover" placement="right-start" trigger="click" @command="handleDropdownMenuClick"> <span class="el-icon-chat-dot-round"> 直播竞猜<i class="el-icon-arrow-down el-icon--right"></i> </span> <el-dropdown-menu slot="dropdown"> <el-dropdown-item icon="el-icon-circle-plus" command="newGuess">添加竞猜</el-dropdown-item> <el-dropdown-item icon="el-icon-info" command="guessTable">查看竞猜</el-dropdown-item> <el-dropdown-item icon="el-icon-download" command="exportGuess">导出名单</el-dropdown-item> </el-dropdown-menu> </el-dropdown> </el-dropdown-item> --> <el-dropdown-item icon="el-icon-notebook-1" command="help">帮助文档</el-dropdown-item> </el-dropdown-menu> </el-dropdown> <el-dialog v-dialog-drag title="查看抽奖" :visible.sync="lotteryTableDialogVisible" :modal="false" width="550px" custom-class="lottery-table-dialog" :close-on-click-modal="false"> <el-table :data="lotteryTableData" style="width: 100%" class="lottery-table" :row-class-name="lotteryTableRowClassName"> <el-table-column prop="name" label="奖品名称" :width="150"> </el-table-column> <el-table-column prop="startTimeText" label="开奖时间" :width="100"> </el-table-column> <el-table-column label="操作" :width="250"> <template slot-scope="scope"> <el-button type="text" @click="handleLotteryModify(scope.row)">编辑</el-button> <el-button type="text" @click="handleLotteryCopy(scope.row)">复制</el-button> <el-button type="text" @click="handleLotteryCandidatesCheck(scope.row)" v-if="scope.row.status == '未开始'">查看候选名单</el-button> <el-button type="text" @click="handleLotteryWinnersCheck(scope.row)" v-if="scope.row.status == '已结束'">查看中奖名单</el-button> </template> </el-table-column> </el-table> </el-dialog> <el-dialog v-dialog-drag :title="lotteryFormDialogTitle" :visible.sync="lotteryFormDialogVisible" :modal="false" width="550px" custom-class="lottery-form-dialog" :close-on-click-modal="false"> <el-form :model="lotteryFormData" class="lottery-form" ref="form" :rules="lotteryFormRules" @submit.native.prevent v-loading="lotteryFormData.loading" :element-loading-text="lotteryFormData.loadingText" element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.8)"> <el-form-item label="奖品名称" label-width="130px" prop="name"> <el-input v-model="lotteryFormData.name" autocomplete="off" style="width:100%;"></el-input> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="抽奖倒计时(秒)" label-width="130px" prop="countdown"> <el-input-number size="medium" v-model="lotteryFormData.countdown" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="开奖时间" label-width="100px" prop="startTime"> <el-time-picker v-model="lotteryFormData.startTime" :picker-options="timePickerOptions" style="width:100%;"> </el-time-picker> </el-form-item> </el-row> </el-form-item> <el-form-item label="互斥抽奖" label-width="130px" prop="mutualLotteryList"> <el-select v-model="lotteryFormData.mutualLotteryList" multiple placeholder="请选择互斥的抽奖" style="width:100%;"> <el-option :value="lottery.id" :label="lottery.name" :key="lottery.id" v-if="lottery.id != lotteryFormData.id" v-for="lottery in lotteryTableData" > </el-option> </el-select> </el-form-item> <!-- <el-form-item label="抽奖权重" label-width="130px" prop="weight"> <el-switch v-model="lotteryFormData.weight" active-text="加权" inactive-text="等权"> </el-switch> </el-form-item> --> <el-form-item> <el-col :span="13"> <el-form-item label="牌子名称" label-width="130px" prop="medalName"> <el-input v-model="lotteryFormData.medalName" autocomplete="off" style="width:100%;"></el-input> </el-form-item> </el-col> <el-col :span="11"> <el-form-item label="牌子等级" label-width="130px" prop="medalLevel"> <el-input-number v-model="lotteryFormData.medalLevel" autocomplete="off" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-col> </el-form-item> <el-form-item label="抽奖来源" label-width="130px" prop="source"> <el-radio-group v-model="lotteryFormData.source" style="width:100%;"> <el-radio label="livestream">直播间抽奖</el-radio> <el-radio label="douga">稿件抽奖</el-radio> </el-radio-group> </el-form-item> <template v-if="lotteryFormData.source == 'livestream'"> <el-form-item label="抽奖参与方式" label-width="130px" prop="joinMethod"> <el-checkbox-group v-model="lotteryFormData.joinMethod" style="width:100%;"> <el-checkbox label="danmaku">弹幕</el-checkbox> <el-checkbox label="gift">礼物</el-checkbox> <el-checkbox label="like">点赞</el-checkbox> </el-checkbox-group> </el-form-item> <!-- 弹幕 --> <template v-if="lotteryFormData.joinMethod.indexOf('danmaku')!=-1"> <el-form-item label="抽奖参与关键词" label-width="130px" prop="joinKeyword"> <el-input v-model="lotteryFormData.joinKeyword" autocomplete="off" style="width:100%;" placeholder="请输入参与抽奖的弹幕关键词"></el-input> </el-form-item> </template> <!-- 礼物 --> <template v-if="lotteryFormData.joinMethod.indexOf('gift')!=-1"> <el-form-item label="抽奖参与礼物" label-width="130px" prop="joinGiftList"> <el-select v-model="lotteryFormData.joinGiftList" multiple placeholder="请选择礼物" popper-class="gift-selector" style="width:100%;"> <el-option :label="gift.name" :value="gift.id" :key="gift.id" v-for="gift in giftList" > <el-row> <el-col :span="8"> <el-avatar shape="square" :size="40" fit="fill" :src="gift.img" style="background-color:white;"></el-avatar> </el-col> <el-col :span="6" :offset="4"> <span>{{gift.name}}</span> </el-col> <el-col :span="6"> <span v-if="gift.price>0">({{gift.price}}AC币)</span> </el-col> </el-row> </el-option> </el-select> </el-form-item> </template> </template> <template v-else-if="lotteryFormData.source == 'douga'"> <el-form-item label="抽奖稿件类型" label-width="130px" prop="dougaType"> <el-radio-group v-model="lotteryFormData.dougaType" style="width:100%;" @change="refreshDougaList"> <el-radio label="video">视频投稿</el-radio> <el-radio label="article">文章投稿</el-radio> </el-radio-group> </el-form-item> <!-- <el-form-item label="抽奖参与方式" label-width="130px" prop="joinMethod"> <el-checkbox-group v-model="lotteryFormData.joinMethod" style="width:100%;"> <el-checkbox label="comment">评论</el-checkbox> <el-checkbox label="subcomment">楼中楼</el-checkbox> <el-checkbox label="floor">指定楼层</el-checkbox> </el-checkbox-group> </el-form-item> --> <el-divider>请选取参与抽奖的稿件</el-divider> <el-row class="douga-list-wrapper"> <el-timeline class="douga-list" v-infinite-scroll="getDougaList" :infinite-scroll-disabled="lotteryFormData.dougaListDisabled"> <el-timeline-item :class="{'douga-list-item':true,'active':lotteryFormData.dougaListActiveIndex == dougaIndex, 'video':lotteryFormData.dougaType == 'video', 'article' : lotteryFormData.dougaType == 'article'}" :timestamp="douga.uploadDateText" placement="top" v-for="(douga, dougaIndex) in lotteryFormData.dougaList" :key="douga.id"> <el-card :title="douga.title" @click.native="handleDougaListItemClick(dougaIndex)"> <el-row class="douga-info"> <template v-if="lotteryFormData.dougaType == 'video'"> <el-col :span="12" class="douga-info-left"> <span class="cover"> <img :src="douga.cover" @click.stop="handleDougaListItemDetailClick(dougaIndex)"> </span> </el-col> <el-col :span="12" class="douga-info-right"> <p class="title"><span>{{douga.title}}</span></p> <p class="play-count">播放量:<span>{{douga.playCountText}}</span></p> </el-col> </template> <template v-if="lotteryFormData.dougaType == 'article'"> <p class="title"><span @click.stop="handleDougaListItemDetailClick(dougaIndex)">{{douga.title}}</span></p> <p class="play-count">访问量:<span>{{douga.playCountText}}</span></p> </template> </el-row> </el-card> </el-timeline-item> </el-timeline> <p v-if="lotteryFormData.dougaListLoading">...正在加载投稿稿件...</p> <p v-if="lotteryFormData.dougaListNoMore">加载完毕</p> </el-row> </template> <el-form-item style="display:flex;justify-content:center;"> <el-button type="primary" @click="handleLotteryFormSubmit">立即创建</el-button> </el-form-item> </el-form> </el-dialog> <el-dialog v-dialog-drag :title="userTableDialogTitle" :visible.sync="userTableDialogVisible" :modal="false" width="550px" custom-class="user-table-dialog" :close-on-click-modal="false"> <el-table :data="userTableData" style="width: 100%" class="user-table"> <el-table-column prop="userName" label="用户名" :width="300"> <template slot-scope="scope"> <el-avatar shape="circle" fit="fill" size="40" :src="scope.row.photo"></el-avatar> <span>{{scope.row.userName}}</span> </template> </el-table-column> <el-table-column prop="uid" label="用户uid" :width="150"> </el-table-column> </el-table> </el-dialog> <el-dialog v-dialog-drag :visible.sync="lotteryCountdownDialogVisible" :modal="false" width="550px" custom-class="lottery-countdown-dialog" :close-on-click-modal="false" :show-close="false"> <div class="container"> <div class="circle"> <svg width="300" viewBox="0 0 220 220" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(110,110)"> <circle r="100" class="e-c-base"/> <g transform="rotate(-90)"> <circle r="100" class="e-c-progress"/> <g id="e-pointer"> <circle cx="100" cy="0" r="15" class="e-c-pointer"/> </g> </g> </g> </svg> </div> <div class="controlls"> <div class="display-remain-time">{{activeLottery.countdownText}}</div> </div> </div> </el-dialog> <el-dialog v-dialog-drag :visible.sync="lotteryStartDialogVisible" :modal="false" width="550px" custom-class="lottery-start-dialog" :close-on-click-modal="false" :destroy-on-close="true" :show-close="false"> <el-row v-if="activeLottery!=null && activeLottery.name" style="text-align:center;margin-bottom:20px;"> <p style="font-size:30px;font-weight:bold;">{{activeLottery.name}}</p> <p> <span>已中奖人数:<span style="color:#409EFF;font-weight:bold;">{{activeLottery.winnerCount}}</span>名</span> <span style="margin-left:20px;">候选人数:<span style="color:#409EFF;font-weight:bold;">{{activeLottery.startCandidates.length}}</span>人</span> </p> </el-row> <el-row class="carousel-container" v-if="activeLottery!=null && activeLottery.name"> <el-carousel ref="carousel" type="card" height="200px" indicator-position="none" arrow="never" :autoplay="false"> <el-carousel-item v-for="candidate in activeLottery.startCandidates" :class="candidate.highlight?'highlight':''"> <el-row> <el-avatar shape="square" :size="120" fit="fill" :src="candidate.photo"></el-avatar> </el-row> <el-row> <span class="nickname" style="cursor:pointer;">{{candidate.userName}}</span> </el-row> <el-row> <span :style="userBadgeStyle" :class="{'user-info-badge':true,'user-info-badge-black':candidate.medalColor=='black','user-info-badge-purple':candidate.medalColor=='purple','user-info-badge-red':candidate.medalColor=='red','user-info-badge-orange':candidate.medalColor=='orange','user-info-badge-blue':candidate.medalColor=='blue','user-info-badge-green':candidate.medalColor=='green'}" v-if="candidate.medalName">LV.{{candidate.medalLevel}} {{candidate.medalName}}</span> </el-row> </el-carousel-item> </el-carousel> </el-row> <el-row style="text-align:center;margin-top:20px;" v-if="!activeLottery.rolling && activeLottery.activeIndex!=null && activeLottery.activeIndex!=-1"> <el-tag type="warning" effect="dark" v-if="userInfo[activeLottery.startCandidates[activeLottery.activeIndex].uid].hasEnterroom">进入直播间</el-tag> <el-tag type="warning" effect="dark" v-if="userInfo[activeLottery.startCandidates[activeLottery.activeIndex].uid].hasLike">点赞</el-tag> <el-tag type="warning" effect="dark" v-if="userInfo[activeLottery.startCandidates[activeLottery.activeIndex].uid].hasDanmaku">弹幕</el-tag> <el-tag type="warning" effect="dark" v-if="userInfo[activeLottery.startCandidates[activeLottery.activeIndex].uid].hasGift">礼物</el-tag> <el-tag type="warning" effect="dark" v-if="userInfo[activeLottery.startCandidates[activeLottery.activeIndex].uid].hasFollow">关注</el-tag> </el-row> <el-row style="text-align:center;margin-top:20px;"> <el-button-group v-if="!activeLottery.rolling"> <el-button type="primary" icon="el-icon-refresh-left" @click="activeLottery.nextFunc(false)">重新抽选</el-button> <el-button type="primary" icon="el-icon-right" @click="activeLottery.nextFunc(true)">继续抽选</el-button> <el-button type="primary" icon="el-icon-check" @click="activeLottery.finishFunc()">结束抽选</el-button> <el-button-group> </el-row> </el-dialog> <el-dialog v-dialog-drag title="弹幕预设" :visible.sync="interactionPresetDialogVisible" :modal="false" width="550px" custom-class="interaction-preset-dialog" :close-on-click-modal="false"> <el-row style="display:flex;justify-content:end;"> <el-button icon="el-icon-circle-plus-outline" type="primary" @click="handleInteractionFormOpen()">新增预设</el-button> </el-row> <!-- 预设 --> <el-table :data="interactionPreset" style="width: 100%" class="interaction-preset-table" border ref="interactionPresetTable" height="200"> <el-table-column prop="index" label="序号" min-width="10%"> </el-table-column> <el-table-column prop="name" label="名称" min-width="45%"> </el-table-column> <el-table-column prop="hotkey" label="热键" min-width="20%"> </el-table-column> <el-table-column label="操作" min-width="25%"> <template slot-scope="scope"> <el-button type="text" @click="handleInteractionFormOpen(scope.row)">编辑</el-button> <el-button type="text" @click="removeInteractionPreset(scope.row)">删除</el-button> </template> </el-table-column> </el-table> </el-dialog> <el-dialog v-dialog-drag title="弹幕编辑" :visible.sync="interactionFormDialogVisible" :modal="false" width="550px" custom-class="interaction-form-dialog" :close-on-click-modal="false" :destroy-on-close="true"> <el-form :model="interactionFormData" class="interaction-form" ref="interactionForm" :rules="interactionFormRules" @submit.native.prevent> <!-- <el-form-item label="是否启动" label-width="130px" prop="enable"> <el-switch v-model="interactionFormData.enable" active-text="启动" inactive-text="不启动"> </el-switch> </el-form-item> --> <template v-if="interactionFormData.enable"> <!-- 排版 --> <!--<el-divider>排版配置</el-divider> <el-form-item label="排版方向" label-width="130px" prop="direction"> <el-select v-model="interactionFormData.direction" style="width:100%;"> <el-option value="vertical" label="纵版" key="vertical"></el-option> <el-option value="horizontal" label="横版" key="horizontal"></el-option> </el-select> </el-form-item> <el-form-item label="弹幕/礼物单列显示" label-width="130px" prop="displayNotWrap"> <el-switch v-model="interactionFormData.displayNotWrap" active-text="是" inactive-text="否"> </el-switch> </el-form-item>--> <!-- 历史 --> <!-- <el-divider>互动历史配置</el-divider> --> <!-- 全局 --> <el-divider>全局配置</el-divider> <el-form-item> <el-form-item label="预设名称" label-width="130px" prop="name"> <el-input v-model="interactionFormData.name" autocomplete="off" style="width:100%;" placeholder="请输入预设名称"></el-input> </el-form-item> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="背景颜色" label-width="130px" prop="backgroundColor"> <el-color-picker v-model="interactionFormData.backgroundColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> </el-form-item> <el-form-item label="互动信息保留" label-width="130px" prop="historyMinutes"> <el-input-number size="medium" v-model="interactionFormData.historyMinutes" :min="1" controls-position="right" style="width:30%;"></el-input-number> <span>分钟</span> </el-form-item> <el-form-item label="互动信息保留" label-width="130px" prop="historyCount"> <el-input-number size="medium" v-model="interactionFormData.historyCount" :min="1" controls-position="right" style="width:30%;"></el-input-number> <span>条</span> </el-form-item> <el-form-item style="display:flex;justify-content:center;"> <el-button type="primary" @click="handleInteractionFormInit">重置为默认配置</el-button> </el-form-item> <!-- 边框 --> <el-divider>边框配置</el-divider> <el-form-item> <el-col :span="11"> <el-form-item label="边框宽度" label-width="130px" prop="borderWidth"> <el-select v-model="interactionFormData.borderWidth" style="width:100%;"> <el-option value="auto" label="自适应" key="auto"></el-option> <el-option value="fixed" label="定宽" key="fixed"></el-option> </el-select> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="边框形状" label-width="100px" prop="borderShape"> <el-select v-model="interactionFormData.borderShape" style="width:100%;"> <el-option value="rect" label="矩形" key="rect"></el-option> <el-option value="round" label="圆角矩形" key="round"></el-option> <el-option value="flow" label="流动矩形" key="flow"></el-option> </el-select> </el-form-item> </el-col> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="边框颜色" label-width="130px" prop="borderColor"> <el-color-picker v-model="interactionFormData.borderColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="边框大小" label-width="100px" prop="borderSize"> <el-input-number size="medium" v-model="interactionFormData.borderSize" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-col> </el-form-item> <!-- 用户名 --> <!-- 字体 --> <el-divider>字体配置</el-divider> <el-form-item label="字体名称" label-width="130px" prop="fontFamily"> <el-cascader v-model="interactionFormData.fontFamily" :options="fontOptions" style="width:100%;" @change="handleFontSelectChange"> </elcascader> </el-form-item> <!-- 用户名 --> <el-divider>用户名配置</el-divider> <el-form-item> <el-col :span="11"> <el-form-item label="字体颜色" label-width="130px" prop="userNameFontColor"> <el-color-picker v-model="interactionFormData.userNameFontColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="字体大小" label-width="100px" prop="userNameFontSize"> <el-input-number size="medium" v-model="interactionFormData.userNameFontSize" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-row> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="阴影颜色" label-width="130px" prop="userNameFontShadowColor"> <el-color-picker v-model="interactionFormData.userNameFontShadowColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="阴影大小" label-width="100px" prop="userNameFontShadowSize"> <el-input-number size="medium" v-model="interactionFormData.userNameFontShadowSize" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-row> </el-form-item> <!-- 弹幕 --> <el-divider>弹幕信息配置</el-divider> <el-form-item> <el-col :span="11"> <el-form-item label="背景颜色" label-width="130px" prop="danmakuBackgroundColor"> <el-color-picker v-model="interactionFormData.danmakuBackgroundColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="渐变为" label-width="100px" prop="danmakuBackgroundGradientColor"> <el-color-picker v-model="interactionFormData.danmakuBackgroundGradientColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="字体颜色" label-width="130px" prop="danmakuFontColor"> <el-color-picker v-model="interactionFormData.danmakuFontColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="字体大小" label-width="100px" prop="danmakuFontSize"> <el-input-number size="medium" v-model="interactionFormData.danmakuFontSize" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-row> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="阴影颜色" label-width="130px" prop="danmakuFontShadowColor"> <el-color-picker v-model="interactionFormData.danmakuFontShadowColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="阴影大小" label-width="100px" prop="danmakuFontShadowSize"> <el-input-number size="medium" v-model="interactionFormData.danmakuFontShadowSize" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-row> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="稿件背景颜色" label-width="130px" prop="danmakuDougaBackgroundColor"> <el-color-picker v-model="interactionFormData.danmakuDougaBackgroundColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> </el-form-item> <el-form-item style="display:flex;justify-content:center;"> <el-button type="primary" @click="pushTestDanmakuMessage">测试一下</el-button> </el-form-item> <!-- 礼物 --> <el-divider>礼物信息配置</el-divider> <el-form-item> <el-col :span="11"> <el-form-item label="背景颜色" label-width="130px" prop="giftBackgroundColor"> <el-color-picker v-model="interactionFormData.giftBackgroundColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="渐变为" label-width="100px" prop="giftBackgroundGradientColor"> <el-color-picker v-model="interactionFormData.giftBackgroundGradientColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> </el-form-item> <el-form-item label="礼物信息" label-width="130px" prop="giftFormat"> <el-input v-model="interactionFormData.giftFormat" autocomplete="off" style="width:100%;" placeholder="请输入参与抽奖的弹幕关键词"></el-input> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="字体颜色" label-width="130px" prop="giftFontColor"> <el-color-picker v-model="interactionFormData.giftFontColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="字体大小" label-width="100px" prop="giftFontSize"> <el-input-number size="medium" v-model="interactionFormData.giftFontSize" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-row> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="阴影颜色" label-width="130px" prop="giftFontShadowColor"> <el-color-picker v-model="interactionFormData.giftFontShadowColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="阴影大小" label-width="100px" prop="giftFontShadowSize"> <el-input-number size="medium" v-model="interactionFormData.giftFontShadowSize" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-row> </el-form-item> <el-form-item style="display:flex;justify-content:center;"> <el-button type="primary" @click="pushTestGiftMessage">测试一下</el-button> </el-form-item> <!-- 点赞 --> <el-divider>点赞信息配置</el-divider> <el-form-item label="点赞信息" label-width="130px" prop="likeFormat"> <el-input v-model="interactionFormData.likeFormat" autocomplete="off" style="width:100%;" placeholder="请输入参与抽奖的弹幕关键词"></el-input> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="字体颜色" label-width="130px" prop="likeFontColor"> <el-color-picker v-model="interactionFormData.likeFontColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="字体大小" label-width="100px" prop="likeFontSize"> <el-input-number size="medium" v-model="interactionFormData.likeFontSize" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-row> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="阴影颜色" label-width="130px" prop="likeFontShadowColor"> <el-color-picker v-model="interactionFormData.likeFontShadowColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="阴影大小" label-width="100px" prop="likeFontShadowSize"> <el-input-number size="medium" v-model="interactionFormData.likeFontShadowSize" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-row> </el-form-item> <el-form-item style="display:flex;justify-content:center;"> <el-button type="primary" @click="pushTestLikeMessage">测试一下</el-button> </el-form-item> <!-- 进入直播间 --> <el-divider>进入直播间信息配置</el-divider> <el-form-item label="进入直播间信息" label-width="130px" prop="enterroomFormat"> <el-input v-model="interactionFormData.enterroomFormat" autocomplete="off" style="width:100%;" placeholder="请输入参与抽奖的弹幕关键词"></el-input> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="字体颜色" label-width="130px" prop="enterroomFontColor"> <el-color-picker v-model="interactionFormData.enterroomFontColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="字体大小" label-width="100px" prop="enterroomFontSize"> <el-input-number size="medium" v-model="interactionFormData.enterroomFontSize" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-row> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="阴影颜色" label-width="130px" prop="enterroomFontShadowColor"> <el-color-picker v-model="interactionFormData.enterroomFontShadowColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="阴影大小" label-width="100px" prop="enterroomFontShadowSize"> <el-input-number size="medium" v-model="interactionFormData.enterroomFontShadowSize" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-row> </el-form-item> <el-form-item style="display:flex;justify-content:center;"> <el-button type="primary" @click="pushTestEnterRoomMessage">测试一下</el-button> </el-form-item> <!-- 关注 --> <el-divider>关注信息配置</el-divider> <el-form-item label="关注信息" label-width="130px" prop="followFormat"> <el-input v-model="interactionFormData.followFormat" autocomplete="off" style="width:100%;" placeholder="请输入参与抽奖的弹幕关键词"></el-input> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="字体颜色" label-width="130px" prop="followFontColor"> <el-color-picker v-model="interactionFormData.followFontColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="字体大小" label-width="100px" prop="followFontSize"> <el-input-number size="medium" v-model="interactionFormData.followFontSize" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-row> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="阴影颜色" label-width="130px" prop="followFontShadowColor"> <el-color-picker v-model="interactionFormData.followFontShadowColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="阴影大小" label-width="100px" prop="followFontShadowSize"> <el-input-number size="medium" v-model="interactionFormData.followFontShadowSize" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-row> </el-form-item> <el-form-item style="display:flex;justify-content:center;"> <el-button type="primary" @click="pushTestFollowMessage">测试一下</el-button> </el-form-item> <!-- 加入守护团 --> <el-divider>加入守护团信息配置</el-divider> <el-form-item label="加入守护团信息" label-width="130px" prop="joinclubFormat"> <el-input v-model="interactionFormData.joinclubFormat" autocomplete="off" style="width:100%;" placeholder="请输入参与抽奖的弹幕关键词"></el-input> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="字体颜色" label-width="130px" prop="joinclubFontColor"> <el-color-picker v-model="interactionFormData.joinclubFontColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="字体大小" label-width="100px" prop="joinclubFontSize"> <el-input-number size="medium" v-model="interactionFormData.joinclubFontSize" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-row> </el-form-item> <el-form-item> <el-col :span="11"> <el-form-item label="阴影颜色" label-width="130px" prop="joinclubFontShadowColor"> <el-color-picker v-model="interactionFormData.joinclubFontShadowColor" show-alpha style="width:100%;" :predefine="predefineColors"></el-color-picker> </el-form-item> </el-col> <el-col :span="13"> <el-form-item label="阴影大小" label-width="100px" prop="joinclubFontShadowSize"> <el-input-number size="medium" v-model="interactionFormData.joinclubFontShadowSize" :min="0" controls-position="right" style="width:100%;"></el-input-number> </el-form-item> </el-row> </el-form-item> <el-form-item style="display:flex;justify-content:center;"> <el-button type="primary" @click="pushTestJoinClubMessage">测试一下</el-button> </el-form-item> </template> <el-form-item style="display:flex;justify-content:center;"> <el-button type="primary" @click="handleInteractionFormSubmit">提交</el-button> </el-form-item> </el-form> </el-dialog> <el-dialog v-dialog-drag title="添加竞猜" :visible.sync="guessFormDialogVisible" :modal="false" width="550px" custom-class="guess-form-dialog" :close-on-click-modal="false"> <el-form :model="guessFormData" class="guess-form" ref="form" :rules="guessFormRules" @submit.native.prevent> <el-form-item label="竞猜标题" label-width="150px" prop="title"> <el-input v-model="guessFormData.title" autocomplete="off" style="width:100%;"></el-input> </el-form-item> <el-form-item label="竞猜问题挑选方式" label-width="150px" prop="chooseWay"> <el-radio-group v-model="guessFormData.chooseWay" style="width:100%;"> <el-radio label="manual">手动挑选</el-radio> <el-radio label="random">随机挑选</el-radio> </el-radio-group> </el-form-item> <el-form-item label="竞猜问题挑选倒计时" label-width="150px" prop="countdown"> <el-input-number size="medium" v-model="guessFormData.countdown" :min="0" controls-position="right" style="width:50%;"></el-input-number><span>(秒,0表示不做限制)</span> </el-form-item> <el-form-item label="总共可竞猜次数" label-width="150px" prop="maxGuess"> <el-input-number size="medium" v-model="guessFormData.maxGuess" :min="0" controls-position="right" style="width:50%;"></el-input-number><span>(0表示不做限制)</span> </el-form-item> <el-form-item label="每个用户可竞猜次数" label-width="150px" prop="maxGuessPerUser"> <el-input-number size="medium" v-model="guessFormData.maxGuessPerUser" :min="0" controls-position="right" style="width:50%;"></el-input-number><span>(0表示不做限制)</span> </el-form-item> <el-form-item label="总共可狙击次数" label-width="150px" prop="maxDirectGuess"> <el-input-number size="medium" v-model="guessFormData.maxDirectGuess" :min="0" controls-position="right" style="width:50%;"></el-input-number><span>(0表示不做限制)</span> </el-form-item> <el-form-item label="每个用户可狙击次数" label-width="150px" prop="maxDirectGuessPerUser"> <el-input-number size="medium" v-model="guessFormData.maxDirectGuessPerUser" :min="0" controls-position="right" style="width:50%;"></el-input-number><span>(0表示不做限制)</span> </el-form-item> <el-form-item style="display:flex;justify-content:center;"> <el-button type="primary" @click="handleGuessFormSubmit">立即创建</el-button> </el-form-item> </el-form> </el-dialog> <el-dialog ref="guessStartDialog" v-dialog-drag title="竞猜详情" :visible.sync="guessStartDialogVisible" :modal="false" width="1000px" custom-class="guess-start-dialog" :close-on-click-modal="false" @closed="handleGuessStartDialogClose"> <template v-if="activeGuess"> <el-row> <span>{{activeGuess.displayDirectGuess?'狙击':'竞猜'}}问题列表</span> <el-button type="primary" @click="handleGuessDanmakuSubmit" size="small" v-if="activeGuess.status == '进行中' && (activeGuess.maxGuess==0 || activeGuess.maxGuess > activeGuess.guessList.length)">开始下一个问题</el-button> <el-button type="primary" @click="activeGuess.displayDirectGuess = !activeGuess.displayDirectGuess" size="small">{{activeGuess.displayDirectGuess?'隐藏狙击问题':'显示狙击问题'}}</el-button> <el-button type="primary" @click="activeGuess.onlyDisplayMatch = !activeGuess.onlyDisplayMatch" size="small">{{activeGuess.onlyDisplayMatch?'显示未命中问题':'隐藏未命中问题'}}</el-button> </el-row> <el-table :data="activeGuessGuessListData" style="width: 100%" class="guess-list-table" border ref="guessListTable" height="330"> <el-table-column prop="index" label="序号" min-width="5%"> </el-table-column> <el-table-column prop="userName" label="用户" min-width="25%"> <template slot-scope="scope"> <el-avatar shape="circle" fit="fill" size="40" :src="scope.row.photo"></el-avatar> <span>{{scope.row.userName}}</span> </template> </el-table-column> <el-table-column prop="guess" label="问题" min-width="60%"> </el-table-column> <el-table-column prop="isValid" label="是否命中" min-width="10%"> <template slot-scope="scope"> <i class="el-icon-check" v-if="scope.row.isValid==true" style="font-size:50px;color:#409EFF;"></i> <i class="el-icon-close" v-if="scope.row.isValid==false" style="font-size:50px;color:#F56C6C;"></i> </template> </el-table-column> </el-table> </template> </el-dialog> <el-dialog ref="guessDanmakuDialog" v-dialog-drag :visible.sync="guessDanmakuDialogVisible" :modal="false" width="550px" custom-class="guess-danmaku-dialog" :close-on-click-modal="false" :destroy-on-close="true" @closed="handleGuessDanmakuDialogClose"> <template slot="title"> <el-row type="flex"> <span class="el-dialog__title">弹幕竞猜</span> <span style="font-size:16px;color:#303133" v-show="activeGuess && activeGuess.chooseWay == 'random'"> <span>(倒计时</span> <span style="background-color:#66b1ff;color:white;border-radius:5px;font-weight:bold;" id="guess-danmaku-countdown-text"></span> <span>)</span> </span> </el-row> </template> <el-row class="guess-danmaku-container"> </el-row> </el-dialog> <el-dialog v-dialog-drag title="查看竞猜" :visible.sync="guessTableDialogVisible" :modal="false" width="1000px" custom-class="guess-table-dialog" :close-on-click-modal="false"> <el-table :data="guessTableData" style="width: 100%" class="guess-table" > <el-table-column prop="title" label="竞猜标题" min-width="50%"> </el-table-column> <el-table-column prop="status" label="状态" min-width="10%"> </el-table-column> <el-table-column prop="winner" label="狙击成功用户" min-width="30%"> <template slot-scope="scope"> <template v-if="scope.row.winner"> <el-avatar shape="circle" fit="fill" size="40" :src="scope.row.winner.photo"></el-avatar> <span>{{scope.row.winner.userName}}</span> </template> <span v-else></span> </template> </el-table-column> <el-table-column label="操作" min-width="10%"> <template slot-scope="scope"> <el-button type="text" @click="openGuessStartDialog(scope.row)">进入竞猜</el-button> </template> </el-table-column> </el-table> </el-dialog> <div id="douga-result" style="display:none;"></div> </div> `; containerEle.append(menuEle); // 对话框拖动指令 Vue.directive('dialog-drag', function(el, binding, vnode, oldVnode) { // 弹框可拉伸最小宽高 const minWidth = 400 const minHeight = 300 // 初始非全屏 let isFullScreen = false // 当前顶部高度 let nowMarginTop = 0 // 获取弹框头部(这部分可双击全屏) const dialogHeaderEl = el.querySelector('.el-dialog__header') // 弹窗 const dragDom = el.querySelector('.el-dialog') // 给弹窗加上overflow auto;不然缩小时框内的标签可能超出dialog; dragDom.style.overflow = 'hidden' // 清除选择头部文字效果 // dialogHeaderEl.onselectstart = new Function("return false"); // 头部加上可拖动cursor dialogHeaderEl.style.cursor = 'move' // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null); const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null) const moveDown = e => { // 鼠标按下,计算当前元素距离可视区的距离 const disX = e.clientX - dialogHeaderEl.offsetLeft const disY = e.clientY - dialogHeaderEl.offsetTop // 获取到的值带px 正则匹配替换 let styL, styT // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px if (sty.left.includes('%')) { styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100) styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100) } else { styL = +sty.left.replace(/\px/g, '') styT = +sty.top.replace(/\px/g, '') } document.onmousemove = function(e) { // 通过事件委托,计算移动的距离 const l = e.clientX - disX const t = e.clientY - disY // 移动当前元素 dragDom.style.left = `${l + styL}px` dragDom.style.top = `${t + styT}px` // 将此时的位置传出去 // binding.value({x:e.pageX,y:e.pageY}) } document.onmouseup = function(e) { document.onmousemove = null document.onmouseup = null } } dialogHeaderEl.onmousedown = moveDown // 当前宽高 let nowWidth = 0 // let nowHight = 0 // 双击头部全屏效果 dialogHeaderEl.ondblclick = e => { if (isFullScreen === false) { // nowHight = dragDom.clientHeight nowWidth = dragDom.clientWidth nowMarginTop = dragDom.style.marginTop dragDom.style.left = 0 dragDom.style.top = 0 dragDom.style.height = '100VH' dragDom.style.width = '100VW' dragDom.style.marginTop = 0 isFullScreen = true dialogHeaderEl.style.cursor = 'initial' dialogHeaderEl.onmousedown = null } else { dragDom.style.height = 'auto' dragDom.style.width = nowWidth + 'px' dragDom.style.marginTop = nowMarginTop isFullScreen = false dialogHeaderEl.style.cursor = 'move' dialogHeaderEl.onmousedown = moveDown } } dragDom.onmousemove = function(e) { // let moveE = e if ( e.clientX > dragDom.offsetLeft + dragDom.clientWidth - 10 || dragDom.offsetLeft + 10 > e.clientX ) { dragDom.style.cursor = 'w-resize' } else if ( el.scrollTop + e.clientY > dragDom.offsetTop + dragDom.clientHeight - 10 ) { dragDom.style.cursor = 's-resize' } else { dragDom.style.cursor = 'default' dragDom.onmousedown = null } dragDom.onmousedown = e => { const clientX = e.clientX const clientY = e.clientY const elW = dragDom.clientWidth const elH = dragDom.clientHeight const EloffsetLeft = dragDom.offsetLeft const EloffsetTop = dragDom.offsetTop dragDom.style.userSelect = 'none' const ELscrollTop = el.scrollTop // 判断点击的位置是不是为头部 if ( clientX > EloffsetLeft && clientX < EloffsetLeft + elW && clientY > EloffsetTop && clientY < EloffsetTop + 100 ) { // 如果是头部在此就不做任何动作,以上有绑定dialogHeaderEl.onmousedown = moveDown; } else { document.onmousemove = function(e) { // 移动时禁用默认事件 e.preventDefault() // 左侧鼠标拖拽位置 if (clientX > EloffsetLeft && clientX < EloffsetLeft + 10) { // 往左拖拽 if (clientX > e.clientX) { dragDom.style.width = elW + (clientX - e.clientX) * 2 + 'px' } // 往右拖拽 if (clientX < e.clientX) { if (dragDom.clientWidth < minWidth) { } else { dragDom.style.width = elW - (e.clientX - clientX) * 2 + 'px' } } } // 右侧鼠标拖拽位置 if ( clientX > EloffsetLeft + elW - 10 && clientX < EloffsetLeft + elW ) { // 往左拖拽 if (clientX > e.clientX) { if (dragDom.clientWidth < minWidth) { } else { dragDom.style.width = elW - (clientX - e.clientX) * 2 + 'px' } } // 往右拖拽 if (clientX < e.clientX) { dragDom.style.width = elW + (e.clientX - clientX) * 2 + 'px' } } // 底部鼠标拖拽位置 if ( ELscrollTop + clientY > EloffsetTop + elH - 20 && ELscrollTop + clientY < EloffsetTop + elH ) { // 往上拖拽 if (clientY > e.clientY) { if (dragDom.clientHeight < minHeight) { } else { dragDom.style.height = elH - (clientY - e.clientY) * 2 + 'px' } } // 往下拖拽 if (clientY < e.clientY) { dragDom.style.height = elH + (e.clientY - clientY) * 2 + 'px' } } } // 拉伸结束 document.onmouseup = function(e) { document.onmousemove = null document.onmouseup = null vue.onDialogResize(dragDom); } } } } }); Vue.use(ELEMENT); Vue.prototype.$message = ELEMENT.Message; if(!document.querySelector('.container-live-feed-messages-acfunlive')){ return false; } // 初始化实例 vue = new Vue({ el : '.container-live-feed-messages-acfunlive', components : { }, data : function(){ var vue = this; var lotteryFormDataDefault = { joinMethod : [], weight : false, joinGiftList : [], mutualLotteryList : [], countdown : 10, status : '未开始', candidates : {}, winners : [], startCandidates : [], medalName : '', medalLevel : 0, source : 'livestream', dougaType : 'video', dougaList : [], dougaListPage : 1, dougaListDisabled : false, dougaListLoading : false, dougaListNoMore : false, dougaListActiveIndex : null, loading : false, rolling : false, loadingText : '', winnerCount : 0, }; var guessFormDataDefault = { title : '', countdown : 20, chooseWay : 'random', status : '进行中', maxGuess : 0, maxGuessPerUser : 0, maxQuestionPerUser : 0, maxDirectGuess : 0, maxDirectGuessPerUser : 1, guessList : [], matchGuessList : [], directGuessList : [], guessIndex : 1, displayDirectGuess : false, onlyDisplayMatch : false, }; var interactionFormDataInit = { enable : true, historyMinutes : 10, historyCount : 200, direction : 'vertical', displayNotWrap : false, fontFamily : ['default', 'inherit'], userNameFontSize : 18, userNameFontColor : 'rgba(255, 69, 0, 1)', userNameFontShadowColor : 'rgba(0, 0, 0, 1)', userNameFontShadowSize : 1, danmakuBackgroundColor : 'rgba(30, 144, 255, 1)', danmakuBackgroundGradientColor : 'rgba(30, 144, 255, 1)', danmakuFontSize : 25, danmakuFontColor : 'rgba(255, 255, 255, 1)', danmakuFontShadowColor : 'rgba(0, 0, 0, 1)', danmakuFontShadowSize : 1, danmakuDougaBackgroundColor: 'rgba(255, 255, 255, 1)', giftBackgroundColor: 'rgba(255, 166, 104, 1)', giftBackgroundGradientColor: 'rgba(252, 91, 108, 1)', giftFormat : '送出了${礼物名称}', giftFontSize : 25, giftFontColor : 'rgba(255, 176, 35, 1)', giftFontShadowColor : 'rgba(0, 0, 0, 1)', giftFontShadowSize : 1, likeFormat : '点赞了', likeFontSize : 18, likeFontColor : 'rgba(255, 0, 0, 1)', likeFontShadowColor : 'rgba(255, 255, 255, 1)', likeFontShadowSize : 2, enterroomFormat : '进入直播间', enterroomFontSize : 18, enterroomFontColor : 'rgba(30, 144, 255, 1)', enterroomFontShadowColor : '#FFF', enterroomFontShadowSize : 2, followFormat : '关注了主播', followFontSize : 20, followFontColor : 'rgba(199, 21, 133, 1)', followFontShadowColor : 'rgba(255, 255, 255, 1)', followFontShadowSize : 2, joinclubFormat : '加入主播的守护团', joinclubFontSize : 20, joinclubFontColor : 'rgba(199, 21, 133, 1)', joinclubFontShadowColor : 'rgba(255, 255, 255, 1)', joinclubFontShadowSize : 2, backgroundColor: 'rgba(0, 204, 0, 1)', borderShape: 'round', borderWidth: 'auto', borderSize: 2, borderColor: 'rgba(30, 144, 255, 1)', }; return { messageData : [], lastDanmakuMessage : null, userInfo : userInfo, uid : config.UID, loginFormDialogVisible : false, lotteryTableDialogVisible : false, lotteryFormDialogVisible : false, userTableDialogVisible : false, lotteryCountdownDialogVisible : false, lotteryStartDialogVisible : false, lotteryFormDialogTitle : '', userTableDialogTitle : '', audioFormDialogVisible : false, interactionFormDialogVisible : false, interactionPresetDialogVisible: false, loginFormData : { token : '', }, loginFormRules : { token : [{ required : true, message : '请输入口令', trigger : 'blur', }], }, lotteryFormDataDefault : _.cloneDeep(lotteryFormDataDefault), lotteryFormData : _.cloneDeep(lotteryFormDataDefault), lotteryFormRules : { name : [{ required : true, message : '请输入奖品名称', trigger : 'blur', }], countdown : [{ required : true, message : '请输入抽奖倒计时', trigger : 'blur', }], startTime : [{ required : true, message : '请设置开奖时间', trigger : 'blur', },{ trigger : 'blur', message : '开奖时间与当前时间差距低于1分钟', validator : function(rule, value, callback){ if(value && moment(value, 'HH:mm:ss').subtract(1, 'minutes') < moment()){ callback(new Error(rule.message)); } else{ callback(); } }, },], /*joinMethod : [{ required : true, message : '请设置抽奖参与方式', trigger : 'blur', },{ trigger : 'blur', message : '请选择至少一个抽奖参与方式', validator : function(rule, value, callback){ if(value.length==0){ callback(new Error(rule.message)); } else{ callback(); } }, }],*/ /*joinKeyword : [{ trigger : 'blur', message : '请输入参与抽奖的弹幕关键词', validator : function(rule, value, callback){ // 抽奖参与方式为弹幕 if(vue.lotteryFormData.joinMethod == 'danmaku' && !value){ callback(new Error(rule.message)); }else{ callback(); } }, }],*/ /*joinGiftList : [{ trigger : 'blur', message : '请选择参与抽奖的礼物,至少一个', validator : function(rule, value, callback){ // 抽奖参与方式为礼物 if(vue.lotteryFormData.joinMethod == 'gift' && (!value || value.length==0)){ callback(new Error(rule.message)); }else{ callback(); } }, }],*/ }, giftList : giftList, giftNameMapper : {}, lotteryTableData : [], userTableData : [], // 时间筛选范围,为当前时间至23:59:59 timePickerOptions : { selectableRange : `${moment().format("HH:mm:ss")} - 23:59:59`, "value-format" : 'HH:mm:ss', }, // 当前活跃抽奖 activeLottery : {}, // 可选语音 audioVoiceOptions : null, // 语速 speechRateMarks : { 250 : '更慢', 500 : '默认', 750 : '更快', }, speechVolumeMarks : { 25 : '更小', 50 : '默认', 75 : '更大', }, // 语音配置表单规则 audioFormRules : { }, // 语音配置表单数据 audioFormData : { voice : ['general', 'Xiaoyun'], enable : false, speechRate : 500, speechVolume : 50, joinMethod : ['danmaku', 'gift', 'follow'], danmakuFormat : '${用户名}说${弹幕内容}', likeFormat : '${用户名}点赞了', giftFormat : '${用户名}送出${礼物数量}个${礼物名称}', enterroomFormat : '${用户名}进入直播间', followFormat : '${用户名}关注了主播', danmakuTimeout : 0, likeTimeout : 0, giftTimeout : 2, enterroomTimeout : 0, followTimeout : 0, consumeing : false, interactions : [], messageBuffer : {}, }, // 弹幕配置表单规则 interactionFormRules : {}, interactionFormDataInit: interactionFormDataInit, // 弹幕配置表单数据 interactionFormData : { index: null, name: "", ..._.cloneDeep(interactionFormDataInit) }, // 竞猜表单 guessFormDialogVisible : false, guessFormDataDefault : _.cloneDeep(guessFormDataDefault), guessFormData : _.cloneDeep(guessFormDataDefault), guessFormRules : { title : [{ required : true, message : '竞猜标题不可为空', trigger : 'blur', }], countdown : [{ trigger : 'blur', message : '竞猜挑选方式为“随机挑选”时,竞猜挑选倒计时至少为10(秒)', validator : function(rule, value, callback){ if(vue.guessFormData.chooseWay == 'random' && value < 10){ callback(new Error(rule.message)); } else{ callback(); } }, }], }, // 当前活跃竞猜 activeGuess : null, // 竞猜表格 guessTableDialogVisible : false, guessTableData : [], // 开始竞猜 guessStartDialogVisible : false, // 弹幕竞猜 guessDanmakuDialogVisible : false, // 请求acfun用户投稿时使用 reqId : 1, // 鼠标悬浮状态 mouseOn : false, // 预定义颜色 predefineColors : [ '#ff4500', '#ff8c00', '#ffd700', '#90ee90', '#00ced1', '#1e90ff', '#c71585', 'rgba(255, 69, 0, 0.68)', 'rgb(255, 120, 0)', 'hsv(51, 100, 98)', 'hsva(120, 40, 94, 0.5)', 'hsl(181, 100%, 37%)', 'hsla(209, 100%, 56%, 0.73)', '#c7158577' ], // 字体选项 fontOptions : null, // 下载过的字体 downloadedFonts : {}, // 弹幕配置 danmaku : null, candidateInfoCallbacks : [], isGettingCandidate : false, // 弹幕配置预设值 interactionPreset : [ ], }; }, methods : { filter : _.filter, // 下拉菜单点击回调 handleDropdownMenuClick : function(command){ var vue = this; // 添加抽奖 if(command=='newLottery'){ this.addOrUpdateLottery(); } // 查看抽奖表格 else if(command=='lotteryTable'){ this.lotteryTableDialogVisible = true; } // 导出中奖名单 else if(command=='exportLottery'){ this.exportLottery(); } // 添加竞猜 else if(command=='newGuess'){ this.guessFormDialogVisible = true; } // 查看竞猜表格 else if(command=='guessTable'){ this.guessTableDialogVisible = true; } // 弹幕编辑 else if(command=='editInteraction'){ this.interactionPresetDialogVisible = true; } // 帮助手册 else if(command == 'help'){ window.open('https://docs.qq.com/doc/DZXF2aFJWb0FxR3N4', '_blank'); } }, // 对话框大小修改 onDialogResize : function(diagDom){ }, // 抽奖表单提交回调 handleLotteryFormSubmit : function(){ var vue = this; function addOrUpdateLottery(){ var isNew = !vue.lotteryFormData.id; // 设置状态 vue.lotteryFormData.status = '未开始'; // 设置开奖时间文字 vue.lotteryFormData.startTimeText = moment(vue.lotteryFormData.startTime).format('HH:mm:ss'); // 备选 vue.lotteryFormData.candidates = {}; vue.lotteryFormData.startCandidates = []; // 获奖者 vue.lotteryFormData.winners = []; // 新增抽奖 if(!vue.lotteryFormData.id){ // 添加id vue.lotteryFormData.id = uuidv4(); vue.lotteryTableData.splice(0, 0, vue.lotteryFormData); } // 注册(不可用)抽奖回调 vue.registerLotteryCallback(vue.lotteryFormData); vue.lotteryFormDialogVisible = false; vue.$message({ message : isNew?'添加抽奖成功':'修改抽奖信息成功', type : 'info', duration : 2000, }); } this.$refs.form.validate((valid) => { // 通过校验 if(valid){ // 如果是稿件抽奖,查看是否有选中稿件 if(this.lotteryFormData.source == 'douga' && this.lotteryFormData.dougaListActiveIndex==null){ this.$message({ message : '请选择稿件', type : 'error', }); return; } // 稿件抽奖 if(this.lotteryFormData.source=='douga'){ var processMessage = null;; // 获取稿件评论 this.getCommentList(this.lotteryFormData.dougaList[this.lotteryFormData.dougaListActiveIndex], true, function(isSuccess, isFinish, commentCount, page, totalPage){ // 错误 if(!isSuccess){ vue.lotteryFormData.loading = false; vue.$message({ message : '获取稿件评论信息错误', type : 'error', }); } else{ // 开始加载 vue.lotteryFormData.loadingText = `正在加载 ${page}/${totalPage} 页评论`; vue.lotteryFormData.loading = true; // 加载完毕 if(isFinish){ vue.lotteryFormData.loading = false; addOrUpdateLottery(); } } }); } else{ addOrUpdateLottery(); } } else{ this.$message({ message : '提交失败,请检查是否填写正确', type : 'error', }); } }); }, // 修改抽奖信息 handleLotteryModify : function(lottery){ this.addOrUpdateLottery(lottery); }, // 复制抽奖 handleLotteryCopy : function(lottery){ this.addOrUpdateLottery(lottery, true); }, // 查看候选人 handleLotteryCandidatesCheck : function(lottery){ var userTableData = []; for(var uid in lottery.candidates){ var candidate = lottery.candidates[uid]; userTableData.push(candidate); } this.userTableData = _.sortBy(userTableData, 'index'); this.userTableDialogTitle = '候选名单'; this.userTableDialogVisible = true; }, // 查看中奖者 handleLotteryWinnersCheck : function(lottery){ this.userTableData = lottery.winners; this.userTableDialogTitle = '中奖名单'; this.userTableDialogVisible = true; }, login : function(callback){ this.loginFormDialogVisible = true; if(_.isFunction(callback)){ this.loginFormData.nextCallback = callback; } else{ this.loginFormData.nextCallback = null; } }, addOrUpdateLottery : function(lottery, copy){ if(lottery && lottery.id){ // 复制抽奖信息 if(copy){ this.lotteryFormData = { name : lottery.name, weight : lottery.weight, soucre : lottery.source, startTime : lottery.startTime, countdown : lottery.countdown, medalName : lottery.medalName, medalLevel : lotter.medalLevel, mutualLotteryList : _.cloneDeep(lottery.mutualLotteryList), joinMethod : _.cloneDeep(lottery.joinMethod), joinKeyword : lottery.joinKeyword, joinGiftList : _.cloneDeep(lottery.joinGiftList), candidates : {}, startCandidates : [], winners : [], dougaType : lottery.dougaType, dougaList : lottery.dougaList, dougaListPage : lottery.dougaListPage, dougaListDisabled : lottery.dougaListDisabled, dougaListLoading : lottery.dougaListLoading, dougaListNoMore : lottery.dougaListNoMore, dougaListActiveIndex : lottery.dougaListActiveIndex, }; this.lotteryFormDialogTitle = '添加抽奖'; } // 修改抽奖信息 else{ this.lotteryFormData = lottery; this.lotteryFormDialogTitle = '修改抽奖'; } } else{ this.lotteryFormData = _.cloneDeep(this.lotteryFormDataDefault); this.lotteryFormDialogTitle = '添加抽奖'; } this.lotteryFormDialogVisible = true; }, // 注册(不可用)抽奖回调 registerLotteryCallback : function(lottery){ var vue = this; function updateCandidates(){ var candidates = {}; lottery.dougaList[lottery.dougaListActiveIndex].commentList.forEach(function(comment, index){ var pass = true; // 如果设置了互斥抽奖 if(lottery.mutualLotteryList && lottery.mutualLotteryList.length>0){ _.filter(vue.lotteryTableData, function(o){return lottery.mutualLotteryList.indexOf(o.id)!=-1}).every(function(anotherLottery){ if(_.findIndex(anotherLottery.winners, {uid:comment.uid})!=-1){ pass = false; return false; } else{ return true; } }); } if(!pass){ return; } if(!(comment.uid in candidates)){ let candidate = { index : -comment.floor, uid : comment.uid, userName : comment.userName, photo : comment.photo, }; // 如果筛选了牌子 if(lottery.medalName && lottery.medalLevel){ vue.getCandidateInfo(candidate, (isSuccess, )=>{ if(candidate.medalName == lottery.medalName && candidate.medalLevel >= lottery.medalLevel){ candidates[comment.uid] = candidate; } }); } else{ candidates[comment.uid] = candidate; } } }); lottery.candidates = candidates; } // 如果是稿件抽奖 if(lottery.source=='douga'){ // 是否注册(不可用)过数据回调 if(lottery.messageHandler){ window.clearInterval(lottery.messageHandler); lottery.messageHandler = null; // 清空候选 lottery.candidates = {}; lottery.startCandidates = []; lottery.winners = []; } // 更新候选名单 updateCandidates(); // 注册(不可用)数据回调(每30秒执行) /*lottery.messageHandler = window.setInterval(function(){ // 获取评论 vue.getCommentList(lottery.dougaList[lottery.dougaListActiveIndex], true, function(isSuccess, isFinish, commentCount, page, totalPage){ // 获取完毕 if(isFinish){ // 更新候选名单 updateCandidates(); } }); }, 30 * 1000);*/ } // 直播间抽奖 else{ // 是否注册(不可用)过数据回调 if(lottery.messageHandler){ callbackManager.cancel(lottery.messageHandler); lottery.messageHandler = null; // 清空候选 lottery.candidates = {}; lottery.startCandidates = []; lottery.winners = []; } // 注册(不可用)数据回调 lottery.messageHandler = callbackManager.register('message', function(data){ // 不符合参与方式 if(!( (lottery.joinMethod.indexOf('danmaku')!=-1 && data.interaction.type=='danmaku') || (lottery.joinMethod.indexOf('gift')!=-1 && data.interaction.type=='gift') || (lottery.joinMethod.indexOf('like')!=-1 && data.interaction.type=='like') ) ){ return; } // 如果参与方式是弹幕 if(data.interaction.type=='danmaku' && (lottery.joinKeyword && data.interaction.content.indexOf(lottery.joinKeyword)==-1)){ return; } // 如果参与方式是礼物 if(data.interaction.type=='gift' && (lottery.joinGiftList.length>0 && lottery.joinGiftList.indexOf(vue.giftNameMapper[data.interaction.giftName].id)==-1)){ return; } var pass = true; // 如果设置了互斥抽奖 if(lottery.mutualLotteryList && lottery.mutualLotteryList.length>0){ _.filter(vue.lotteryTableData, function(o){return lottery.mutualLotteryList.indexOf(o.id)!=-1}).every(function(anotherLottery){ if(_.findIndex(anotherLottery.winners, {uid:data.uid})!=-1){ pass = false; return false; } else{ return true; } }); } if(!pass){ return; } // 第一次被侦测 if(!(data.uid in lottery.candidates)){ let candidate = { uid : data.uid, userName : data.userName, photo : data.photo, weight : 0, index : Object.keys(lottery.candidates).length, }; // 如果筛选了牌子 if(lottery.medalName && lottery.medalLevel){ vue.getCandidateInfo(candidate, (isSuccess, )=>{ if(candidate.medalName == lottery.medalName && candidate.medalLevel >= lottery.medalLevel){ lottery.candidates[data.uid] = candidate; if(data.interaction.type=='danmaku'){ lottery.candidates[data.uid].weight += 1; } else if(data.interaction.type=='gift'){ lottery.candidates[data.uid].weight += vue.giftNameMapper[data.interaction.giftName].price * data.interaction.giftCount; } else if(data.interaction.type=='like'){ lottery.candidates[data.uid].weight += 0.5; } } }); } else{ lottery.candidates[data.uid] = candidate; if(data.interaction.type=='danmaku'){ lottery.candidates[data.uid].weight += 1; } else if(data.interaction.type=='gift'){ lottery.candidates[data.uid].weight += vue.giftNameMapper[data.interaction.giftName].price * data.interaction.giftCount; } else if(data.interaction.type=='like'){ lottery.candidates[data.uid].weight += 0.5; } } } }); } var startLotteryTimeout = lottery.startTime - new Date(); var countdownTimeout = startLotteryTimeout - lottery.countdown * 1000; // 是否已经注册(不可用)过抽奖倒计时 if(lottery.countdownHandler){ window.clearTimeout(lottery.countdownHandler); lottery.countdownHandler = null; } if(lottery.countdown>0){ lottery.countdownHandler = window.setTimeout(function(){ lottery.countdownHandler = null; lottery.countdownText = `${lottery.countdown/60>=10?'':'0'}${_.floor(lottery.countdown/60)}:${lottery.countdown%60>=10?'':'0'}${lottery.countdown%60}`; vue.activeLottery = lottery; // 展示倒计时 vue.showLotteryCountdown(lottery); }, countdownTimeout); } // 是否已经注册(不可用)过抽奖 if(lottery.startHandler){ window.clearTimeout(lottery.startHandler); lottery.startHandler = null; } lottery.startHandler = window.setTimeout(function(){ // 清除数据回调 if(lottery.source=='douga'){ window.clearInterval(lottery.messageHandler) } else{ callbackManager.cancel(lottery.messageHandler); } lottery.messageHandler = null; lottery.startHandler = null; vue.activeLottery = lottery; // 展示结果 vue.showLotteryStart(lottery); }, startLotteryTimeout); }, // 返回抽奖表格行类名 lotteryTableRowClassName : function({row}){ if(row.status == '未开始'){ return 'lottery-status-unstart'; } if(row.status == '已结束'){ return 'lottery-status-finish'; } }, getCandidateInfo(candidate, callback){ this.candidateInfoCallbacks.push([candidate, callback]); }, // 获取用户信息 _getCandidateInfo(candidate, callback){ if(candidate.medalName){ if(_.isFunction){ callback(true, candidate); } return; } commonRequrest(config.ACFUN_SERVER + config.URLS.ACFUN_USER.SPACE + `/${candidate.uid}`, 'get', null, true, function(isSuccess, data){ // 获取成功 if(isSuccess){ let medalDataJsonMatch = data.match(/data-medal='(?<medal>.+?)'/); if(medalDataJsonMatch!=null){ let medalData = JSON.parse(medalDataJsonMatch.groups['medal']); let medalColor = 'green'; if(medalData.level >= 1 && medalData.level <= 3){ medalColor = 'green'; } else if(medalData.level >= 4 && medalData.level <= 6){ medalColor = 'blue'; } else if(medalData.level >= 7 && medalData.level <= 9){ medalColor = 'orange'; } else if(medalData.level >= 10 && medalData.level <= 12){ medalColor = 'red'; } else if(medalData.level >= 13 && medalData.level <= 15){ medalColor = 'purple'; } else if(medalData.level >= 16 && medalData.level <= 20){ medalColor = 'black'; } Object.assign(candidate, { medalName : medalData.clubName, medalLevel : medalData.level, medalColor : medalColor, }); } if(_.isFunction){ callback(true, candidate); } } else{ if(_.isFunction){ callback(false, candidate); } } }); }, // 开始倒计时 showLotteryCountdown : function(lottery){ var vue = this; this.lotteryStartDialogVisible = false; this.lotteryCountdownDialogVisible = true; this.$nextTick(function(){ //circle start var progressBar = document.querySelector('.lottery-countdown-dialog .e-c-progress'); var indicator = document.querySelector('.lottery-countdown-dialog #e-indicator'); var pointer = document.querySelector('.lottery-countdown-dialog #e-pointer'); var length = Math.PI * 2 * 100; progressBar.style.strokeDasharray = length; function update(value, timePercent) { var offset = - length - length * value / (timePercent); progressBar.style.strokeDashoffset = offset; pointer.style.transform = `rotate(${360 * value / (timePercent)}deg)`; }; //circle ends const displayOutput = document.querySelector('.lottery-countdown-dialog .display-remain-time') var intervalTimer; var timeLeft; var wholeTime = lottery.countdown; // manage this to set the whole time var isPaused = false; var isStarted = false; update(wholeTime,wholeTime); //refreshes progress bar displayTimeLeft(wholeTime); function changeWholeTime(seconds){ if ((wholeTime + seconds) > 0){ wholeTime += seconds; update(wholeTime,wholeTime); } } function timer (seconds){ //counts time, takes seconds var remainTime = Date.now() + (seconds * 1000); displayTimeLeft(seconds); intervalTimer = window.setInterval(function(){ timeLeft = Math.round((remainTime - Date.now()) / 1000); // 倒计时结束 if(timeLeft < 0){ window.clearInterval(intervalTimer); isStarted = false; // 隐藏对话框 vue.lotteryCountdownDialogVisible = false; return ; } displayTimeLeft(timeLeft); }, 1000); } function displayTimeLeft (timeLeft){ //displays time on the input var minutes = Math.floor(timeLeft / 60); var seconds = timeLeft % 60; var displayString = `${minutes < 10 ? '0' : ''}${minutes}:${seconds < 10 ? '0' : ''}${seconds}`; displayOutput.textContent = displayString; update(timeLeft, wholeTime); } timer(wholeTime); }); }, // 开始抽奖 showLotteryStart : function(lottery){ var vue = this; var stop = false; lottery.activeIndex = -1; this.lotteryCountdownDialogVisible = false; var rollIntervalHandler = null; // 候选人数为0 if(Object.keys(lottery.candidates).length == 0){ this.$message({ type : 'info', message : '无参与抽奖人员', }); lottery.winners = _.flatMap(lottery.candidates); lottery.status = '已结束'; this.handleLotteryWinnersCheck(lottery); return; } function roll(){ if(stop){ // 获取当前赢家 // vue.$refs.carousel.setActiveItem(_.findIndex(lottery.startCandidates, {uid:lottery.winners[lottery.winners.length-1].uid})); } else{ vue.$refs.carousel.next(); } } function changeRollIntervals(intervals, timeouts, callback){ if(!timeouts){ timeouts = 0; } if(!_.isArray(intervals)){ intervals = [intervals]; } if(!_.isArray(timeouts)){ timeouts = [timeouts]; if(timeouts.length>intervals.length){ timeouts = timeouts.slice(0, intervals.length); } if(timeouts.length<intervals.length){ var npads = intervals.length-timeouts.length; for(var i=0;i<npads;++i){ timeouts.splice(0, 0, 0); } } } intervals.forEach(function(interval, index){ window.setTimeout(function(){ if(rollIntervalHandler!=null){ window.clearTimeout(rollIntervalHandler); } if(interval != null){ rollIntervalHandler = window.setInterval(roll, interval); } else{ stop = true; vue.$nextTick(function(){ vue.$refs.carousel.$nextTick(function(){ // 获取当前赢家 lottery.activeIndex = vue.$refs.carousel.activeIndex; // 高亮 lottery.startCandidates[lottery.activeIndex].highlight = true; vue.$refs.carousel.$nextTick(function(){ // 停止回调 if(_.isFunction(callback)){ callback(); } }); }); }); } }, timeouts[index]); }); } // 当前滚动名单 vue.$set(lottery, 'startCandidates', _.flatMap(lottery.candidates)); this.$nextTick(function(){ var startChoose = function(){ lottery.rolling = true; // 获取中奖者 vue.lotteryStartDialogVisible = true; stop = false; // 8秒内需要滚动完所有用户 var interval = Math.min(Math.max(Math.floor(8000/lottery.startCandidates.length), 150), 350); // 高速转动 // 10秒后停止转动 changeRollIntervals( [interval, null], [0, 10000], // 转动结束后获取当前用户 function(){ lottery.rolling = false; }, ); }; function checkWinner(valid){ // 去除高亮 lottery.startCandidates[lottery.activeIndex].highlight = false; // 删除候选 let candidate = lottery.startCandidates.splice(lottery.activeIndex, 1)[0]; // 删除候选 delete lottery.candidates[candidate.uid]; // 如果有效,添加入赢家 if(valid){ // 添加赢家 lottery.winners.push(candidate); } lottery.winnerCount = lottery.winners.length; } // 设置抽奖结束函数 lottery.finishFunc = function(){ if(lottery.rolling){ return; } checkWinner(true); lottery.status = '已结束'; // 关闭弹窗 vue.lotteryStartDialogVisible = false; // 打开中奖名单 vue.handleLotteryWinnersCheck(lottery); }; // 设置继续抽奖函数 lottery.nextFunc = function(valid){ if(lottery.rolling){ return; } // 查看候选人数是否足够 if(valid && lottery.startCandidates.length == 0){ vue.$message({ type : 'error', message : '人数不足,无法抽奖' }); return; } checkWinner(valid); // 关闭弹窗 // vue.lotteryStartDialogVisible = false; vue.activeLottery = {}; vue.$nextTick(function(){ // 1秒后重新开始 window.setTimeout(function(){ // 打乱顺序 vue.$set(lottery, 'startCandidates', _.shuffle(lottery.startCandidates)); vue.$nextTick(function(){ lottery.activeIndex = -1; vue.activeLottery = lottery; startChoose(); }); }, 1000); }); }; // 开始抽奖 startChoose(); }); }, // 导出中奖名单 exportLottery : function(){ var workbook = new ExcelJS.Workbook(); var sheet = workbook.addWorksheet('中奖名单'); sheet.columns = [ { key: 'userName', width: 30, }, { key: 'uid', width: 10, }, ]; var rowIndex = 1; // 遍历所有已结束的抽奖 this.lotteryTableData.forEach(function(lottery){ if(lottery.status != '已结束'){ return true; } // 添加标题 sheet.addRow([lottery.name]); sheet.mergeCells(rowIndex,1,rowIndex,2); // 设置标题样式 var titleRow = sheet.getRow(rowIndex); var titleCell = titleRow.getCell(1); // 文字居中 titleCell.alignment = {vertical: 'middle', horizontal: 'center'}; // 添加边框 titleCell.border = { top: {style:'thin'}, left: {style:'thin'}, bottom: {style:'thin'}, right: {style:'thin'}, }; // 加粗字体 titleCell.font = { bold : true, }; sheet.addRow({userName: '用户名', uid : '用户uid'}); // 设置列名样式 var headerRow = sheet.getRow(rowIndex + 1); for(var i=1;i<=2;++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'}, }; } // 遍历中奖用户 lottery.winners.forEach(function(winner, index){ sheet.addRow({userName: winner.userName, uid : winner.uid}); // 设置记录样式 var recordRow = sheet.getRow(rowIndex + 2 + index); for(var i=1;i<=2;++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'}, }; } }); // 添加两个空白行 sheet.addRow(); sheet.addRow(); rowIndex += 1 + 1 + lottery.winners.length + 2; }); ;(async function(){ var buffer = await workbook.xlsx.writeBuffer(); var file = new File([buffer], '中奖名单.xlsx'); saveAs(file); })(); }, // 语音配置表单提交 handleAudioFormSubmit : function(){ var vue = this; this.$refs.audioForm.validate((valid) => { // 通过校验 if(valid){ // 提交修改 GM_setValue('audioFormData', JSON.stringify({ voice : this.audioFormData.voice, enable : this.audioFormData.enable, speechRate : this.audioFormData.speechRate, speechVolume : this.audioFormData.speechVolume, joinMethod : this.audioFormData.joinMethod, danmakuFormat : this.audioFormData.danmakuFormat, likeFormat : this.audioFormData.likeFormat, giftFormat : this.audioFormData.giftFormat, enterroomFormat : this.audioFormData.enterroomFormat, followFormat : this.audioFormData.followFormat, danmakuTimeout : this.audioFormData.danmakuTimeout, likeTimeout : this.audioFormData.likeTimeout, giftTimeout : this.audioFormData.giftTimeout, enterroomTimeout : this.audioFormData.enterroomTimeout, followTimeout : this.audioFormData.followTimeout, consumeing : false, interactions : [], messageBuffer : {}, })); this.handleAudioFormSubmitValid(); } }); }, handleAudioFormSubmitValid : function(){ var vue = this; // 检测当前是否有缓冲 for(var bufferKey in this.audioFormData.messageBuffer){ window.clearTimeout(this.audioFormData.messageBuffer[bufferKey].handler); } this.audioFormData.messageBuffer = {}; // 检测是否已经添加了语音播报 if(this.audioFormData.messageHandler){ callbackManager.cancel(this.audioFormData.messageHandler); this.audioFormData.messageHandler = null; } // 开启播报 if(this.audioFormData.enable){ this.audioFormData.messageHandler = callbackManager.register('message', function(data){ // 不是允许的互动类型 if(vue.audioFormData.joinMethod.indexOf(data.interaction.type)==-1){ return; } var bufferKey = null; var timeout = 0; if(data.interaction.type=='gift'){ bufferKey = data.uid + data.interaction.type + data.interaction.giftName; timeout = vue.audioFormData.giftTimeout; } // 不进行缓存,直接播报 if(bufferKey==null || timeout == 0){ data.interaction = [data.interaction]; vue.consumeAudio(vue.audioFormData, data); return; } // 已有相同信息 if(bufferKey in vue.audioFormData.messageBuffer){ window.clearTimeout(vue.audioFormData.messageBuffer[bufferKey].handler); vue.audioFormData.messageBuffer[bufferKey].interaction.push(data.interaction); } else{ vue.audioFormData.messageBuffer[bufferKey] = { uid : data.uid, userName : data.userName, interaction : [data.interaction], }; } vue.audioFormData.messageBuffer[bufferKey].handler = window.setTimeout(function(){ var data = vue.audioFormData.messageBuffer[bufferKey]; vue.audioFormData.messageBuffer[bufferKey].handler = null; delete vue.audioFormData.messageBuffer[bufferKey]; vue.consumeAudio(vue.audioFormData, data); }, timeout*1000); }); } // 关闭弹窗 this.audioFormDialogVisible = false; }, // 字体选择回调 handleFontSelectChange : function(value){ this.addFont(value[value.length-1]); }, // 新增预设 addInteractionPreset: function(item){ this.interactionPreset.push(_.cloneDeep(item)); this.interactionPreset[this.interactionPreset.length-1].index = this.interactionPreset.length; this.interactionPreset[this.interactionPreset.length-1].hotkey = this.interactionPreset.length<=9?`ctrl+alt+${this.interactionPreset.length}`:'预设过多,无法激活'; return this.interactionPreset[this.interactionPreset.length-1]; }, // 编辑预设 editInteractionPreset: function(item){ console.log('edit', item) this.interactionPreset[item.index-1] = _.cloneDeep(item); return this.interactionPreset[item.index-1]; }, // 激活某一预设 activeInteractionPreset: function(item){ for(var preset of this.interactionPreset){ preset.active = false; } item.active = true; console.log('item', item) this.interactionFormData = _.cloneDeep(item); this.handleInteractionFormSubmitValid(); }, // 删除某一预设 removeInteractionPreset: function(item){ this.$confirm(`确定删除预设:${item.name}`, '是否删除', { confirmButtonText: '确定', cancelButtonText: '取消', }).then(() => { this.interactionPreset.splice(item.index-1, 1); this.interactionPreset.forEach(function(item, index){ item.index = index + 1; item.hotkey = index<9?`ctrl+alt+${index+1}`:'预设过多,无法激活'; }); // 提交修改 GM_setValue('interactionPreset', JSON.stringify(vue.interactionPreset)); }); }, // 打开弹幕配置表单 handleInteractionFormOpen(item){ var vue = this; // 新增预设 if(item==null){ this.interactionFormData.name = ""; this.interactionFormData.index = null; } // 编辑预设 else{ this.activeInteractionPreset(item); } this.interactionFormDialogVisible = true; }, // 重置配置表单 handleInteractionFormInit: function(){ this.interactionFormData = { ...this.interactionFormData, ..._.cloneDeep(this.interactionFormDataInit), }; }, // 弹幕配置表单提交 handleInteractionFormSubmit : function(){ var vue = this; this.$refs.interactionForm.validate((valid) => { // 通过校验 if(valid){ var fontName = vue.interactionFormData.fontFamily[vue.interactionFormData.fontFamily.length-1]; if(fontName!='inherit'){ // 添加缓存 GM_setValue('downloadedFonts', vue.downloadedFonts); } var preset = null; // 编辑 if(vue.interactionFormData.index!=null){ preset = vue.editInteractionPreset(vue.interactionFormData); } // 新增 else{ preset = vue.addInteractionPreset(vue.interactionFormData); } console.log('submit', preset) vue.activeInteractionPreset(preset); vue.interactionFormDialogVisible = false; // 提交修改 GM_setValue('interactionPreset', JSON.stringify(vue.interactionPreset)); } }); }, handleInteractionFormSubmitValid : function(){ var vue = this; if(vue.interactionFormData.enable){ vue.interactionFormData.modifyContentFunc = function(data){ if(data.interaction.type == 'gift'){ data.interaction.content = formatText(vue.interactionFormData.giftFormat, { '礼物名称' : data.interaction.giftName, }); } else if(data.interaction.type == 'enterroom'){ data.interaction.content = vue.interactionFormData.enterroomFormat; } else if(data.interaction.type == 'like'){ data.interaction.content = vue.interactionFormData.likeFormat; } else if(data.interaction.type == 'follow'){ data.interaction.content = vue.interactionFormData.followFormat; } else if(data.interaction.type == 'joinclub'){ data.interaction.content = vue.interactionFormData.joinclubFormat; } } if(vue.interactionFormData.cleanInteractionHistoryHandler){ window.clearInterval(vue.interactionFormData.cleanInteractionHistoryHandler); } // 清除弹幕历史 vue.interactionFormData.cleanInteractionHistoryHandler = window.setInterval(function(){ let historyMinuteStartIndex = 0; let historyCountStartIndex = vue.messageData.length - vue.interactionFormData.historyCount; let sendTimeLower = new Date(); sendTimeLower.setMinutes(sendTimeLower.getMinutes()-vue.interactionFormData.historyMinutes); vue.messageData.every(function(message, messageIndex){ if(message.interaction.sendTime>=sendTimeLower){ historyMinuteStartIndex = messageIndex; return false; } else{ return true; } }); let historyStartIndex = Math.max(0, Math.max(historyMinuteStartIndex, historyCountStartIndex)); if(historyStartIndex==0){ return; } else{ vue.messageData.splice(0, historyStartIndex); } }, 5 * 1000); } else{ vue.interactionFormData.modifyContentFunc = null; window.clearInterval(vue.interactionFormData.cleanInteractionHistoryHandler); } }, consumeAudio(audioFormData, interactionData){ var vue = this; // 弹幕合并 if(interactionData.interaction[0].type == 'danmaku'){ interactionData.interaction = { type : 'danmaku', content : _.reduce(interactionData.interaction, function(text, interaction){ return text + (text==''?'':'<break time=\"500ms\"/>') + interaction.content; }, ''), }; } // 礼物合并 else if(interactionData.interaction[0].type == 'gift'){ // 有连击 let findIndex = _.findIndex(interactionData.interaction, {'doAnime': true}); interactionData.interaction = { type : 'gift', giftName : interactionData.interaction[0].giftName, giftCount : findIndex==-1?_.sumBy(interactionData.interaction, 'giftCount'):interactionData.interaction[findIndex].giftCount, } } // 其他合并 else{ interactionData.interaction = interactionData.interaction[0]; } audioFormData.interactions.push(interactionData); if(audioFormData.consumeing){ return; } audioFormData.consumeing = true; new Promise(function(resolve, reject) { var readInteractionAudio = function(){ // 如果停止了语音 if(!audioFormData.enable){ audioFormData.interactions = []; resolve(); return; } if(audioFormData.interactions.length==0){ audioFormData.consumeing = false; resolve(); return; } var interactionData = audioFormData.interactions.splice(0, 1)[0]; vue.readInteractionAudio(audioFormData, interactionData, readInteractionAudio); } readInteractionAudio(); }).then(function(){ }).catch(function(err){ }); }, readInteractionAudio(audioFormData, interactionData, callback){ // 弹幕 if(interactionData.interaction.type == 'danmaku'){ nls(`<speak>${audioFormData.danmakuFormat}</speak>`, audioFormData.voice[audioFormData.voice.length-1], audioFormData.speechRate - 500, audioFormData.speechVolume, { '用户名' : interactionData.userName + '<break time=\"500ms\"/>', '弹幕内容' : '<break time=\"500ms\"/>' + interactionData.interaction.content, }, callback); } // 礼物 else if(interactionData.interaction.type == 'gift'){ nls(`<speak>${audioFormData.giftFormat}</speak>`, audioFormData.voice[audioFormData.voice.length-1], audioFormData.speechRate - 500, audioFormData.speechVolume, { '用户名' : interactionData.userName + '<break time=\"500ms\"/>', '礼物数量' : interactionData.interaction.giftCount, '礼物名称' : interactionData.interaction.giftName, }, callback); } // 点赞 else if(interactionData.interaction.type == 'like'){ nls(`<speak>${audioFormData.likeFormat}</speak>`, audioFormData.voice[audioFormData.voice.length-1], audioFormData.speechRate - 500, audioFormData.speechVolume, { '用户名' : interactionData.userName + '<break time=\"500ms\"/>', }, callback); } // 进入直播间 else if(interactionData.interaction.type == 'enterroom'){ nls(`<speak>${audioFormData.enterroomFormat}</speak>`, audioFormData.voice[audioFormData.voice.length-1], audioFormData.speechRate - 500, audioFormData.speechVolume, { '用户名' : interactionData.userName + '<break time=\"500ms\"/>', }, callback); } // 关注 else if(interactionData.interaction.type == 'follow'){ nls(`<speak>${audioFormData.followFormat}</speak>`, audioFormData.voice[audioFormData.voice.length-1], audioFormData.speechRate - 500, audioFormData.speechVolume, { '用户名' : interactionData.userName + '<break time=\"500ms\"/>', }, callback); } else{ callback(); } }, // 竞猜表单提交回调 handleGuessFormSubmit : function(){ var vue = this; this.$refs.form.validate((valid) => { // 通过校验 if(valid){ // 添加id vue.guessFormData.id = uuidv4(); vue.guessTableData.splice(0, 0, vue.guessFormData); vue.guessFormDialogVisible = false; vue.guessFormData = _.cloneDeep(vue.guessFormDataDefault); vue.$message({ message : '添加竞猜成功', type : 'info', duration : 2000, }); // 进入竞猜 vue.openGuessStartDialog(vue.guessTableData[0]); } else{ this.$message({ message : '提交失败,请检查是否填写正确', type : 'error', }); } }); }, // 竞猜开始下一个问题回调 handleGuessDanmakuSubmit : function(){ var vue = this; this.guessDanmakuDialogVisible = true; this.$nextTick(function(){ this.activeGuess.guessDanmakuList = []; var danmakuList = []; var danmakuUserMapper = {}; var danmakuContentMapper = {}; var hoverDanmakuItem = null; var randomId = uuidv4(); // 随机给定一个id var containerEle = document.querySelector('.guess-danmaku-dialog .guess-danmaku-container'); containerEle.setAttribute('id', 'R' + randomId); this.activeGuess.danmaku = new EasyDanmaku({ el: `#R${randomId}`, // 彩色弹幕 colourful : false, // 弹幕行数 line : 10, // 弹幕样式 wrapperStyle : 'guess-danmaku-danmu', // 弹幕播放速度 speed : 3, // 播放一次时长 runtime : 3, // 鼠标悬浮暂停 hover : true, coefficient : 5, }); // 添加监听 this.activeGuess.messageHandler = callbackManager.register('command:提问', function(data){ // 非弹幕 if(data.interaction.type != 'danmaku'){ return; } // 只有一次提问机会 if(data.uid in danmakuUserMapper){ return; } // 不允许重复提问 if(data.interaction.content in danmakuContentMapper){ return; } // 达到单个用户可提问上限 if(vue.activeGuess.maxGuessPerUser>0){ if(_.filter(vue.activeGuess.guessList, {uid:data.uid}).length>=vue.activeGuess.maxGuessPerUser){ return; } } var danmakuItem = _.cloneDeep(data); danmakuList.push(danmakuItem); vue.activeGuess.danmaku.send(danmakuItem.interaction.content); danmakuItem.sendTime = new Date(); danmakuUserMapper[danmakuItem.uid] = true; danmakuContentMapper[danmakuItem.interaction.content] = danmakuItem; }); // 鼠标事件回调 $('.guess-danmaku-container').on('mouseenter', '.guess-danmaku-danmu', function(e){ var danmakuItem = danmakuContentMapper[e.target.innerText]; if(danmakuItem){ danmakuItem.hover = true; hoverDanmakuItem = danmakuItem; // 如果是手动选择模式,添加class if(vue.activeGuess.chooseWay == 'manual'){ e.target.classList.add('is-select'); } } }); $('.guess-danmaku-container').on('mouseout', '.guess-danmaku-danmu', function(e){ if(hoverDanmakuItem){ hoverDanmakuItem.hover = false; hoverDanmakuItem.sendTime = new Date(); hoverDanmakuItem = null; // 如果是手动选择模式,删除class if(vue.activeGuess.chooseWay == 'manual'){ e.target.classList.remove('is-select'); } } }); $('.guess-danmaku-container').on('click', '.guess-danmaku-danmu', function(e){ // 只有挑选方式为手动时才可点击 if(hoverDanmakuItem && vue.activeGuess.chooseWay == 'manual'){ // 暂停播放 vue.activeGuess.danmaku.pause(); var hoverDanmakuItem_ = hoverDanmakuItem; hoverDanmakuItem_.guess = hoverDanmakuItem_.interaction.content; vue.$confirm(`${hoverDanmakuItem_.guess}${hoverDanmakuItem_.guess.endsWith('?')?'':'?'}`, '是否命中', { confirmButtonText: '命中', cancelButtonText: '未命中', closeOnClickModal : false, closeOnPressEscape : false, }).then(() => { hoverDanmakuItem_.isValid = true; hoverDanmakuItem_.index = vue.activeGuess.guessIndex; vue.activeGuess.guessIndex += 1; vue.activeGuess.guessList.splice(0, 0, hoverDanmakuItem_); vue.activeGuess.matchGuessList.splice(0, 0, hoverDanmakuItem_); // 关闭弹窗 vue.guessDanmakuDialogVisible = false; }).catch((action) => { if(action=='cancel'){ hoverDanmakuItem_.isValid = false; hoverDanmakuItem_.index = vue.activeGuess.guessIndex; vue.activeGuess.guessIndex += 1; vue.activeGuess.guessList.splice(0, 0, hoverDanmakuItem_); // 关闭弹窗 vue.guessDanmakuDialogVisible = false; } else{ } }); } }); // 开启轮询 this.activeGuess.danmakuLoopHandler = window.setInterval(function(){ var now = new Date(); var findIndex = _.findIndex(danmakuList, function(danmaku){ // 距离上次发送已经超过5秒 return now - danmaku.sendTime >= 3*1000 && !danmaku.hover; }); if(findIndex != -1){ vue.activeGuess.danmaku.send(danmakuList[findIndex].interaction.content); danmakuList[findIndex].sendTime = now; } }, 50); // 如果是随机选择,随机选中 if(vue.activeGuess.chooseWay == 'random'){ var now = new Date(); // 竞猜问题倒计时结束 vue.activeGuess.handleGuessDanmakuCountdownFinish = function(){ // 暂停随机选中 window.clearInterval(vue.activeGuess.randomSelectHandler); // 暂停弹幕 vue.activeGuess.danmaku.pause(); // 获取选中 var selectedEle = containerEle.querySelector('.is-select'); // 未选中信息 if(selectedEle==null){ vue.$message({ type : 'error', message : '无法选中弹幕信息,本次问题获取失败', }); // 关闭弹窗 vue.guessDanmakuDialogVisible = false; } else{ // 获取对应弹幕信息 var danmakuItem = danmakuContentMapper[selectedEle.innerText]; danmakuItem.guess = danmakuItem.interaction.content; vue.$confirm(`${danmakuItem.guess}${danmakuItem.guess.endsWith('?')?'':'?'}`, '是否命中', { distinguishCancelAndClose : true, confirmButtonText: '命中', cancelButtonText: '未命中', closeOnClickModal : false, closeOnPressEscape : false, }).then(() => { danmakuItem.isValid = true; // 添加序号 danmakuItem.index = vue.activeGuess.guessIndex; vue.activeGuess.guessIndex += 1; vue.activeGuess.guessList.splice(0, 0, danmakuItem); vue.activeGuess.matchGuessList.splice(0, 0, danmakuItem); // 关闭弹窗 vue.guessDanmakuDialogVisible = false; }).catch((action ) => { // 未命中 if(action=='cancel'){ danmakuItem.isValid = false; danmakuItem.index = vue.activeGuess.guessIndex; vue.activeGuess.guessIndex += 1; vue.activeGuess.guessList.splice(0, 0, danmakuItem); // 关闭弹窗 vue.guessDanmakuDialogVisible = false; } else{ } }); } }; vue.activeGuess.randomSelectHandler = window.setInterval(function(){ // 删除已选中 var selectedEle = containerEle.querySelector('.is-select'); if(selectedEle){ selectedEle.classList.remove('is-select'); } if(containerEle.children.length>0){ // 如果未有选中,或者没有兄弟节点,则选中第一个 if(selectedEle==null || selectedEle.nextElementSibling==null){ selectedEle = containerEle.children[0]; } // 否则选中下一个 else{ selectedEle = selectedEle.nextElementSibling; } selectedEle.classList.add('is-select'); } }, 100); vue.$refs.guessDanmakuDialog.$nextTick(function(){ // 倒计时文字 $('#guess-danmaku-countdown-text') .countdown(new Date().getTime() + vue.activeGuess.countdown*1000, function(event){$(this).html(event.strftime('【%M:%S】'))}) .on('finish.countdown', vue.activeGuess.handleGuessDanmakuCountdownFinish); }); } }); }, openGuessStartDialog : function(guessFormData){ var vue = this; this.guessStartDialogVisible = true; this.activeGuess = guessFormData; var danmakuContentMapper = {}; var isInDirectGuess = false; // 监听狙击消息 this.activeGuess.directGuessMessageHandler = callbackManager.register('command:狙击', function(data){ // 当前是否位于狙击状态 if(isInDirectGuess){ return; } // 非弹幕 if(data.interaction.type != 'danmaku'){ return; } // 已结束竞猜 if(vue.activeGuess.status != '进行中'){ return; } // 达到狙击总上限 if(vue.activeGuess.maxDirectGuess > 0 && vue.activeGuess.directGuessList.length>=vue.activeGuess.maxDirectGuess){ return; } // 达到单个用户可狙击上限 if(vue.activeGuess.maxDirectGuessPerUser>0 && _.filter(vue.activeGuess.directGuessList, {uid:data.uid}).length >= vue.activeGuess.maxDirectGuessPerUser ){ return; } // 不允许重复提问 if(data.interaction.content in danmakuContentMapper){ return; } isInDirectGuess = true; var danmakuItem = _.cloneDeep(data); danmakuItem.guess = data.interaction.content; danmakuItem.sendTime = new Date(); danmakuContentMapper[danmakuItem.interaction.content] = danmakuItem; // 打开询问 vue.$confirm(`${danmakuItem.guess}${danmakuItem.guess.endsWith('?')?'':'?'}`, '狙击!是否命中?', { confirmButtonText: '命中', cancelButtonText: '未命中', closeOnClickModal : false, closeOnPressEscape : false, }).then(() => { danmakuItem.isValid = true; danmakuItem.index = vue.activeGuess.guessIndex; vue.activeGuess.guessIndex += 1; vue.activeGuess.directGuessList.splice(0, 0, danmakuItem); // 关闭弹窗 vue.guessDanmakuDialogVisible = false; isInDirectGuess = false; vue.activeGuess.winner = danmakuItem; // 修改状态 vue.activeGuess.status = '竞猜成功'; vue.$message({ type : 'info', message : '竞猜成功!', }); }).catch((action) => { if(action=='cancel'){ danmakuItem.isValid = false; danmakuItem.index = vue.activeGuess.guessIndex; vue.activeGuess.guessIndex += 1; vue.activeGuess.directGuessList.splice(0, 0, danmakuItem); isInDirectGuess = false; // 达到狙击上限,竞猜失败 if(vue.activeGuess.maxDirectGuess>0 && vue.activeGuess.maxDirectGuess<=vue.activeGuess.directGuessList.length){ // 修改状态 vue.activeGuess.status = '竞猜失败'; vue.$message({ type : 'error', message : '竞猜失败!', }); } } else{ } }); }); }, // 竞猜弹幕弹窗关闭回调 handleGuessDanmakuDialogClose : function(){ delete this.activeGuess.danmaku; if(this.activeGuess.messageHandler){ callbackManager.cancel(this.activeGuess.messageHandler); this.activeGuess.messageHandler = null; } window.clearInterval(this.activeGuess.danmakuLoopHandler); this.activeGuess.danmakuLoopHandler = null; if(this.activeGuess.randomSelectHandler){ window.clearInterval(this.activeGuess.randomSelectHandler); this.activeGuess.randomSelectHandler = null; } if(this.activeGuess.handleGuessDanmakuCountdownFinish){ this.activeGuess.handleGuessDanmakuCountdownFinish = null; } }, // 竞猜详情弹窗关闭 handleGuessStartDialogClose : function(){ // 关闭狙击消息获取 if(this.activeGuess.directGuessMessageHandler){ callbackManager.cancel(this.activeGuess.directGuessMessageHandler); this.activeGuess.directGuessMessageHandler = null; } this.activeGuess = null; }, // 获取投稿数据 getDougaList(){ var vue = this; var pageSize = null; if(this.lotteryFormData.dougaType == 'video'){ pageSize = 10; } else if(this.lotteryFormData.dougaType == 'article'){ pageSize = 10; } var params = { 'quickViewId' : `ac-space-${this.lotteryFormData.dougaType}-list`, 'reqID': this.reqId, 'ajaxpipe': 1, 'type': this.lotteryFormData.dougaType, 'order': 'newest', 'page' : this.lotteryFormData.dougaListPage, 'pageSize': pageSize, }; this.reqId += 1; vue.lotteryFormData.dougaListLoading = true; commonRequrest(config.ACFUN_SERVER + config.URLS.ACFUN_USER.SPACE + `/${this.uid}`, 'get', params, true, function(isSuccess, data){ // 获取成功 if(isSuccess){ document.querySelector('#douga-result').innerHTML = JSON.parse(data.replace('/*<!-- fetch-stream -->*/', ''))['html']; var dougaEleList = null; // 查看视频投稿 if(params.type == 'video'){ dougaEleList = document.querySelectorAll('#douga-result #ac-space-video-list a'); } // 查看文章投稿 else if(params.type == 'article'){ dougaEleList = document.querySelectorAll('#douga-result #ac-space-article-list article'); } // 无结果 if(!dougaEleList || dougaEleList.length==0){ vue.lotteryFormData.dougaListDisabled = true; vue.lotteryFormData.dougaListNoMore = true; } else{ var dougaList = []; // 视频投稿 if(params.type == 'video'){ dougaEleList.forEach(function(dougaEle){ dougaList.push({ id : dougaEle.attributes.href.value.split('/').pop().replace('ac', ''), href : config.ACFUN_SERVER + dougaEle.attributes.href.value, cover : dougaEle.querySelector('img').src, title : dougaEle.querySelector('figcaption .title').title, uploadDateText : dougaEle.querySelector('figcaption .date').innerText, playCountText : dougaEle.querySelector('figcaption .play-info').innerText.match(/观看(?<count>[0-9\.万]+)/).groups['count'], }); }); } // 文章投稿 else if(params.type == 'article'){ dougaEleList.forEach(function(dougaEle){ dougaList.push({ id : dougaEle.querySelector('a').attributes.href.value.split('/').pop().replace('ac', ''), href : config.ACFUN_SERVER + dougaEle.querySelector('a').attributes.href.value, title : dougaEle.querySelector('a').title, uploadDateText : dougaEle.querySelector('.info').innerText.match(/发布于\s*(?<date>\d{4}\/\d{2}\/\d{2})/).groups['date'], playCountText : dougaEle.querySelector('.info').innerText.match(/(?<count>[0-9\.万]+)人围观/).groups['count'], }); }); } vue.lotteryFormData.dougaList.splice(vue.lotteryFormData.dougaList.length, 0, ...dougaList); vue.lotteryFormData.dougaListPage += 1; } } else{ vue.lotteryFormData.dougaListDisabled = true; vue.lotteryFormData.dougaListNoMore = true; } vue.lotteryFormData.dougaListLoading = false; }); }, // 刷新投稿数据 refreshDougaList(){ this.lotteryFormData.dougaList = []; this.lotteryFormData.dougaListPage = 1; this.lotteryFormData.dougaListDisabled = false; this.lotteryFormData.dougaListLoading = false; this.lotteryFormData.dougaListNoMore = false; this.lotteryFormData.dougaListActiveIndex = null; this.getDougaList(); }, handleDougaListItemClick(dougaIndex){ // 点击已选中投稿表示取消选中 if(this.lotteryFormData.dougaListActiveIndex == dougaIndex){ this.lotteryFormData.dougaListActiveIndex = null; } else{ this.lotteryFormData.dougaListActiveIndex = dougaIndex; } }, handleDougaListItemDetailClick(dougaIndex){ window.open(this.lotteryFormData.dougaList[dougaIndex].href, '_blank'); }, // 获取投稿 getCommentList(douga, all, callback){ var vue = this; var params = { sourceId : douga.id, sourceType : 3, page : 1, pivotCommentId : 0, supportZtEmot : true, }; var fetch = true; var commentList = []; var preCommentId = douga.commentList && douga.commentList.length>0?douga.commentList[0].id:null; var getData = function(){ commonRequrest(config.ACFUN_SERVER + config.URLS.DOUGA.COMMENT, 'get', params, true, function(isSuccess, data){ // 获取失败 if(!isSuccess){ callback(false, false, douga.commentCount, params.page, douga.commentListTotalPage); fetch = false; } else{ data = JSON.parse(data); // 返回错误 if(data.result != 0){ fetch = false; return; } // 设置评论数量 douga.commentCount = data.commentCount; douga.commentListTotalPage = data.totalPage; data.rootComments.every(function(comment, commentIndex){ // 如果是已经获取过的评论,结束获取 if(comment.commentId == preCommentId){ fetch = false; return false; } // 如果是未获取过的用户,添加 if(!(comment.userId in userInfo)){ userInfo[comment.userId] = { uid : comment.userId, userName : comment.userName, photo : comment.headUrl[0].url, }; } commentList.push({ id : comment.commentId, uid : comment.userId, userName : comment.userName, photo : comment.headUrl[0].url, content : comment.content.replace(/\[emot=[^\[\]]*\]/g, ''), floor : comment.floor, date : moment(comment.timestamp).toDate(), dateText : moment(comment.timestamp).format('MM-DD HH:mm'), }); return true; }); // 获取结束 if(params.page == douga.commentListTotalPage){ fetch = false; } } if(!all){ fetch = false; } // 获取完毕 else if(params.page == douga.commentListTotalPage){ fetch = false; } // 继续获取 if(fetch){ params.page += 1; // 回调 if(_.isFunction(callback)){ callback(true, false, douga.commentCount, params.page, douga.commentListTotalPage); } getData(); } // 获取结束 else{ // 添加评论 if(!douga.commentList){ douga.commentList = []; } if(commentList.length>0){ douga.commentList.splice(0, 0, ...commentList); } // 回调 if(_.isFunction(callback)){ callback(true, true, douga.commentCount, params.page, douga.commentListTotalPage); } } }); } // 获取数据 getData(); }, clickMessage : function(message, isDouga){ // 弹幕 if(message.interaction.type == 'danmaku'){ // 点击稿件,则复制稿件ac号 if(isDouga){ clipboard.writeText(message.interaction.acSeries); this.$message({ message : '已复制ac号:' + message.interaction.acSeries, type : 'info', duration : 2000, }); } // 否则复制弹幕内容 else{ clipboard.writeText(message.interaction.content); this.$message({ message : '已复制弹幕:' + message.interaction.content, type : 'info', duration : 2000, }); } } }, getDougaByAcSeries(acSeries, callback){ let vue = this; // 获取视频 this.getVideoByAcSeries(acSeries, function(isSuccess, data){ // 获取成功 if(isSuccess){ if(_.isFunction(callback)){ callback(isSuccess, data); } } // 获取失败,则获取文章 else{ // 获取文章 vue.getArticleByAcSeries(acSeries, function(isSuccess, data){ // 获取成功 if(isSuccess){ if(_.isFunction(callback)){ callback(isSuccess, data); } } else{ // 获取番剧 vue.getBangumiByAcSeries(acSeries, function(isSuccess, data){ // 获取成功 if(isSuccess){ if(_.isFunction(callback)){ callback(isSuccess, data); } } else{ if(_.isFunction(callback)){ callback(isSuccess, data); } } }); } }); } }); }, getVideoByAcSeries(acSeries, callback){ commonRequrest(config.ACFUN_SERVER + config.URLS.DOUGA.VIDEO + `/ac${acSeries}`, 'get', null, true, function(isSuccess, data){ // 获取成功 if(isSuccess){ var match = data.match(new RegExp('window.videoInfo = (?<data>.+)')); // 匹配成功 if(match){ eval('var videoInfo = ' + match.groups.data); if(_.isFunction(callback)){ callback(true, { type : 'video', title : videoInfo.title, cover : videoInfo.coverUrl, channel : videoInfo.channel, description : videoInfo.description, danmakuCount : videoInfo.danmakuCount, danmakuCountText : videoInfo.danmakuCountShow, playCount : videoInfo.viewCount, playCountText : videoInfo.viewCountShow, uid : parseInt(videoInfo.user.id), userName : videoInfo.user.name, }); } } else{ if(_.isFunction(callback)){ callback(false); } } } else{ if(_.isFunction(callback)){ callback(false); } } }); }, getArticleByAcSeries(acSeries, callback){ commonRequrest(config.ACFUN_SERVER + config.URLS.DOUGA.ARTICLE + `/ac${acSeries}`, 'get', null, true, function(isSuccess, data){ // 获取成功 if(isSuccess){ var match = data.match(new RegExp('window.articleInfo = (?<data>.+)')); // 匹配成功 if(match){ eval('var articleInfo = ' + match.groups.data); if(_.isFunction(callback)){ callback(true, { type : 'article', title : articleInfo.title, // cover : articleInfo.coverUrl, description : articleInfo.description, channel : articleInfo.channel, playCount : articleInfo.viewCount, playCountText : articleInfo.formatViewCount, uid : parseInt(articleInfo.user.id), userName : articleInfo.user.name, }); } } else{ if(_.isFunction(callback)){ callback(false); } } } else{ if(_.isFunction(callback)){ callback(false); } } }); }, getBangumiByAcSeries(acSeries, callback){ commonRequrest(config.ACFUN_SERVER + config.URLS.DOUGA.BANGUMI + `/aa${acSeries}`, 'get', null, true, function(isSuccess, data){ // 获取成功 if(isSuccess){ var match = data.match(new RegExp('window.bangumiData = (?<data>.+)')); // 匹配成功 if(match){ eval('var bangumiData = ' + match.groups.data); if(_.isFunction(callback)){ callback(true, { type : 'bangumi', title : bangumiData.bangumiTitle, acfunOnly : bangumiData.acfunOnly, cover : bangumiData.bangumiCoverImageH, description : bangumiData.bangumiIntro, channel : bangumiData.channel, playCount : bangumiData.playCount, playCountText : bangumiData.playCountShow, stowCount : bangumiData.stowCount, stowCountText : bangumiData.stowCountShow, }); } } else{ if(_.isFunction(callback)){ callback(false); } } } else{ if(_.isFunction(callback)){ callback(false); } } }); }, // 发送一条测试用的弹幕 pushTestMessage : function(type){ var message = { uid : 37693149, vup : false, userName : '特工澪', badgeName : '505团', badgeLevel : 999, badgeColor : 'black', photo : 'https://tx-free-imgs2.acfun.cn/kimg/EJjM1y8qPQoFYWNmdW4SBWltYWdlGi0zNzY5MzE0OV8yYTE4YjBiZTZhZTM0OTc1OTkyNDIyZGFhMTdlNzA0MS5wbmc.png', interaction : { type: type, sendTime : new Date(), id: uuidv4(), giftName: '猴岛', giftCount: 1, content: type == 'danmaku'?'听我说👂👂👂谢谢你🙏🙏🙏因为有你👉👉👉温暖了四季🌈🌈🌈谢谢你🙏🙏🙏感谢有你👉👉👉世界更美丽🌏🌏🌏我要谢谢你🙏🙏🙏因为有你👉👉👉爱常在心底💃💃💃谢谢你 🙏🙏🙏感谢有你🙇♂🙇♂🙇♂把幸福传递 ac32814163':'', }, }; if(!(message.uid in userInfo)){ userInfo[message.uid] = { userName: message.userName, photo: message.photo, }; } callbackManager.feed('message', message); }, pushTestDanmakuMessage: function(){ this.pushTestMessage('danmaku'); }, pushTestGiftMessage: function(){ this.pushTestMessage('gift'); }, pushTestLikeMessage: function(){ this.pushTestMessage('like'); }, pushTestEnterRoomMessage: function(){ this.pushTestMessage('enterroom'); }, pushTestFollowMessage: function(){ this.pushTestMessage('follow'); }, pushTestJoinClubMessage: function(){ this.pushTestMessage('joinclub'); }, }, computed : { danmakuMessageClass: function(){ return ['live-message-danmaku'].concat(this.borderClass); }, backgroundStyle: function(){ style = { background: this.interactionFormData.backgroundColor, }; return style; }, borderClass: function(){ classes = []; // 圆角矩形边框 if(this.interactionFormData.borderShape == 'round'){ } // 矩形 else if(this.interactionFormData.borderShape == 'rect'){ } // 流动 else if(this.interactionFormData.borderShape == 'flow'){ classes.push('live-message-border-flow') } return classes; }, borderStyle: function(){ style = {}; // 圆角矩形边框 if(this.interactionFormData.borderShape == 'round'){ style['border-radius'] = '6px'; style['border'] = `${this.interactionFormData.borderSize}px solid ${this.interactionFormData.borderColor}`; } // 矩形 else if(this.interactionFormData.borderShape == 'rect'){ style['border'] = `${this.interactionFormData.borderSize}px solid ${this.interactionFormData.borderColor}`; } // 流动 else if(this.interactionFormData.borderShape == 'flow'){ GM_addStyle(` .live-message-border-flow.active{ border: ${this.interactionFormData.borderSize}px solid transparent } .live-message-border-flow.inactive{ border: ${this.interactionFormData.borderSize}px solid ${this.interactionFormData.borderColor} } `); } // 自适应宽度 if(this.interactionFormData.borderWidth == 'auto'){ style['width'] = 'max-content'; style['display'] = 'table-cell'; } // 定宽 else if(this.interactionFormData.borderWidth == 'fixed'){ style['width'] = '100%'; style['display'] = 'block'; } return style; }, borderFlowItemStyle: function(){ style = {}; // 圆角矩形边框 if(this.interactionFormData.borderShape == 'round'){ } // 矩形 else if(this.interactionFormData.borderShape == 'rect'){ } // 流动 else if(this.interactionFormData.borderShape == 'flow'){ GM_addStyle(` .live-message-border-flow.active .border-flow-item::before,.live-message-border-flow.active .border-flow-item::after{ border: ${this.interactionFormData.borderSize}px solid ${this.interactionFormData.borderColor} } .live-message-border-flow .border-flow-item::before,.live-message-border-flow .border-flow-item::after{ top: -${this.interactionFormData.borderSize}px; bottom: -${this.interactionFormData.borderSize}px; left: -${this.interactionFormData.borderSize}px; right: -${this.interactionFormData.borderSize}px; } `); } return style; }, userNameMessageStyle : function(){ return { 'color':this.interactionFormData.userNameFontColor, 'font-size':this.interactionFormData.userNameFontSize + 'px', 'font-family' : this.interactionFormData.fontFamily[this.interactionFormData.fontFamily.length-1], 'text-shadow':`0px ${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowColor}, 0px -${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowColor}, ${this.interactionFormData.userNameFontShadowSize}px 0px ${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowColor}, -${this.interactionFormData.userNameFontShadowSize}px 0px ${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowColor}, ${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowColor}, -${this.interactionFormData.userNameFontShadowSize}px -${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowColor}, ${this.interactionFormData.userNameFontShadowSize}px -${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowColor}, -${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowSize}px ${this.interactionFormData.userNameFontShadowColor}`, }; }, userBadgeStyle : function(){ return { 'font-size':this.interactionFormData.userNameFontSize*0.8 + 'px', 'font-family' : this.interactionFormData.fontFamily[this.interactionFormData.fontFamily.length-1], }; }, userPhotoSize : function(){ return this.interactionFormData.userNameFontSize*2; }, danmakuMessageStyle : function(){ return { ...this.borderStyle, 'background-image' : `linear-gradient(to right, ${this.interactionFormData.danmakuBackgroundColor}, ${this.interactionFormData.danmakuBackgroundGradientColor})`, 'color':this.interactionFormData.danmakuFontColor, 'font-size':this.interactionFormData.danmakuFontSize + 'px', 'font-family' : this.interactionFormData.fontFamily[this.interactionFormData.fontFamily.length-1], 'text-shadow':`0px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, 0px -${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, ${this.interactionFormData.danmakuFontShadowSize}px 0px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, -${this.interactionFormData.danmakuFontShadowSize}px 0px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, -${this.interactionFormData.danmakuFontShadowSize}px -${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, ${this.interactionFormData.danmakuFontShadowSize}px -${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, -${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}`, }; }, danmakuMessageContainerStyle : function(){ // 横版 if(this.interactionFormData.direction == 'horizontal'){ var style = { 'max-width' : this.interactionFormData.danmakuFontSize*20 + 'px', }; if(this.interactionFormData.displayNotWrap){ style.height = '100%'; } return style; } // 纵版 else{ } }, danmakuDougaMessageStyle: function(){ return { ...this.borderStyle, 'border': 'transparent', 'display': 'block', 'width': this.danmakuDougaContainerStyle.width, 'background-image' : `linear-gradient(to right, ${this.interactionFormData.danmakuDougaBackgroundColor}, ${this.interactionFormData.danmakuDougaBackgroundColor})`, 'color':this.interactionFormData.danmakuFontColor, 'font-size':this.interactionFormData.danmakuFontSize + 'px', 'font-family' : this.interactionFormData.fontFamily[this.interactionFormData.fontFamily.length-1], 'text-shadow':`0px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, 0px -${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, ${this.interactionFormData.danmakuFontShadowSize}px 0px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, -${this.interactionFormData.danmakuFontShadowSize}px 0px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, -${this.interactionFormData.danmakuFontShadowSize}px -${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, ${this.interactionFormData.danmakuFontShadowSize}px -${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, -${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowSize}px ${this.interactionFormData.danmakuFontShadowColor}`, }; }, danmakuDougaContainerStyle: function(){ var height = Math.ceil(this.interactionFormData.danmakuFontSize*0.8*1.3*3 + this.interactionFormData.danmakuFontSize*0.6*1.3*2); var width = Math.ceil(height*16/9)*2; return { 'width' : width + 'px', }; }, danmakuDougaTitleStyle : function(){ var fontSize = Math.ceil(this.interactionFormData.danmakuFontSize*0.8); var shadowSize = Math.ceil(this.interactionFormData.danmakuFontShadowSize*0.8); var height = Math.ceil(fontSize*1.3 * 3); return { 'height': height + 'px', 'color':this.interactionFormData.danmakuFontColor, 'font-size':fontSize + 'px', 'font-family' : this.interactionFormData.fontFamily[this.interactionFormData.fontFamily.length-1], 'text-shadow':`0px ${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, 0px -${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, ${shadowSize}px 0px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, -${shadowSize}px 0px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, ${shadowSize}px ${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, -${shadowSize}px -${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, ${shadowSize}px -${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, -${shadowSize}px ${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}`, }; }, danmakuDougaDescriptionStyle : function(){ var fontSize = Math.ceil(this.interactionFormData.danmakuFontSize*0.6); var shadowSize = Math.ceil(this.interactionFormData.danmakuFontShadowSize*0.6); return { 'font-size':fontSize + 'px', 'text-shadow':`0px ${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, 0px -${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, ${shadowSize}px 0px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, -${shadowSize}px 0px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, ${shadowSize}px ${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, -${shadowSize}px -${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, ${shadowSize}px -${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, -${shadowSize}px ${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}`, }; }, danmakuDougaCoverStyle : function(){ var height = Math.ceil(this.interactionFormData.danmakuFontSize*0.8*1.3*3 + this.interactionFormData.danmakuFontSize*0.6*1.3*2); var width = Math.ceil(height*16/9); return { 'height' : height + 'px', 'width' : width + 'px', }; }, danmakuDougaLeftColStyle : function(){ return { 'width': this.danmakuDougaCoverStyle.width, 'display': 'inline-block', 'float': 'left', }; }, danmakuDougaRightColStyle : function(){ return { 'width': `calc(100% - ${this.danmakuDougaLeftColStyle.width})`, 'display': 'inline-block', 'float': 'left', }; }, danmakuDougaInfoStyle : function(){ var fontSize = Math.ceil(this.interactionFormData.danmakuFontSize*0.6); var shadowSize = Math.ceil(this.interactionFormData.danmakuFontShadowSize*0.6); return { 'color':this.interactionFormData.danmakuFontColor, 'font-size':fontSize + 'px', 'font-family' : this.interactionFormData.fontFamily[this.interactionFormData.fontFamily.length-1], 'text-shadow':`0px ${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, 0px -${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, ${shadowSize}px 0px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, -${shadowSize}px 0px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, ${shadowSize}px ${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, -${shadowSize}px -${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, ${shadowSize}px -${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}, -${shadowSize}px ${shadowSize}px ${shadowSize}px ${this.interactionFormData.danmakuFontShadowColor}`, }; }, giftMessageStyle : function(){ return { ...this.borderStyle, 'background-image' : `linear-gradient(to right, ${this.interactionFormData.giftBackgroundColor}, ${this.interactionFormData.giftBackgroundGradientColor})`, 'color':this.interactionFormData.giftFontColor, 'font-size':this.interactionFormData.giftFontSize + 'px', 'font-family' : this.interactionFormData.fontFamily[this.interactionFormData.fontFamily.length-1], 'text-shadow':`0px ${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowColor}, 0px -${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowColor}, ${this.interactionFormData.giftFontShadowSize}px 0px ${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowColor}, -${this.interactionFormData.giftFontShadowSize}px 0px ${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowColor}, ${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowColor}, -${this.interactionFormData.giftFontShadowSize}px -${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowColor}, ${this.interactionFormData.giftFontShadowSize}px -${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowColor}, -${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowSize}px ${this.interactionFormData.giftFontShadowColor}`, }; }, giftMessageContainerStyle : function(){ // 横版 if(this.interactionFormData.direction == 'horizontal'){ var style = { 'max-width' : this.interactionFormData.giftFontSize*20 + 'px', }; if(this.interactionFormData.displayNotWrap){ style.height = '100%'; } return style; } // 纵版 else{ } }, giftImageSize : function(){ return this.interactionFormData.giftFontSize*1.5; }, giftCountStyle : function(){ return { 'font-size':this.interactionFormData.giftFontSize*1.5 + 'px', 'font-family' : this.interactionFormData.fontFamily[this.interactionFormData.fontFamily.length-1] == 'inherit' ? 'gift':this.interactionFormData.fontFamily[this.interactionFormData.fontFamily.length-1], }; }, likeMessageStyle : function(){ return { 'color':this.interactionFormData.likeFontColor, 'font-size':this.interactionFormData.likeFontSize + 'px', 'font-family' : this.interactionFormData.fontFamily[this.interactionFormData.fontFamily.length-1], 'text-shadow':`0px ${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowColor}, 0px -${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowColor}, ${this.interactionFormData.likeFontShadowSize}px 0px ${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowColor}, -${this.interactionFormData.likeFontShadowSize}px 0px ${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowColor}, ${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowColor}, -${this.interactionFormData.likeFontShadowSize}px -${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowColor}, ${this.interactionFormData.likeFontShadowSize}px -${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowColor}, -${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowSize}px ${this.interactionFormData.likeFontShadowColor}`, }; }, likeMessageContainerStyle : function(){ // 横版 if(this.interactionFormData.direction == 'horizontal'){ return { 'max-width' : this.interactionFormData.likeFontSize*20 + 'px', } } // 纵版 else{ } }, enterroomMessageStyle : function(){ return { 'color':this.interactionFormData.enterroomFontColor, 'font-size':this.interactionFormData.enterroomFontSize + 'px', 'font-family' : this.interactionFormData.fontFamily[this.interactionFormData.fontFamily.length-1], 'text-shadow':`0px ${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowColor}, 0px -${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowColor}, ${this.interactionFormData.enterroomFontShadowSize}px 0px ${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowColor}, -${this.interactionFormData.enterroomFontShadowSize}px 0px ${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowColor}, ${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowColor}, -${this.interactionFormData.enterroomFontShadowSize}px -${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowColor}, ${this.interactionFormData.enterroomFontShadowSize}px -${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowColor}, -${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowSize}px ${this.interactionFormData.enterroomFontShadowColor}`, }; }, enterroomMessageContainerStyle : function(){ // 横版 if(this.interactionFormData.direction == 'horizontal'){ return { 'max-width' : this.interactionFormData.enterroomFontSize*20 + 'px', } } // 纵版 else{ } }, followMessageStyle : function(){ return { 'color':this.interactionFormData.followFontColor, 'font-size':this.interactionFormData.followFontSize + 'px', 'font-family' : this.interactionFormData.fontFamily[this.interactionFormData.fontFamily.length-1], 'text-shadow':`0px ${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowColor}, 0px -${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowColor}, ${this.interactionFormData.followFontShadowSize}px 0px ${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowColor}, -${this.interactionFormData.followFontShadowSize}px 0px ${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowColor}, ${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowColor}, -${this.interactionFormData.followFontShadowSize}px -${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowColor}, ${this.interactionFormData.followFontShadowSize}px -${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowColor}, -${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowSize}px ${this.interactionFormData.followFontShadowColor}`, }; }, followMessageContainerStyle : function(){ // 横版 if(this.interactionFormData.direction == 'horizontal'){ return { 'max-width' : this.interactionFormData.followFontSize*20 + 'px', } } // 纵版 else{ } }, joinclubMessageStyle : function(){ return { 'color':this.interactionFormData.joinclubFontColor, 'font-size':this.interactionFormData.joinclubFontSize + 'px', 'font-family' : this.interactionFormData.fontFamily[this.interactionFormData.fontFamily.length-1], 'text-shadow':`0px ${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowColor}, 0px -${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowColor}, ${this.interactionFormData.joinclubFontShadowSize}px 0px ${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowColor}, -${this.interactionFormData.joinclubFontShadowSize}px 0px ${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowColor}, ${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowColor}, -${this.interactionFormData.joinclubFontShadowSize}px -${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowColor}, ${this.interactionFormData.joinclubFontShadowSize}px -${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowColor}, -${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowSize}px ${this.interactionFormData.joinclubFontShadowColor}`, }; }, joinclubMessageContainerStyle : function(){ // 横版 if(this.interactionFormData.direction == 'horizontal'){ return { 'max-width' : this.interactionFormData.joinclubFontSize*20 + 'px', } } // 纵版 else{ } }, activeGuessGuessListData : function(){ var listData = this.activeGuess.displayDirectGuess?this.activeGuess.directGuessList:(this.activeGuess.onlyDisplayMatch?this.activeGuess.matchGuessList:this.activeGuess.guessList); return listData?listData:[]; }, toUserSpace: function(...args){ console.log(args) // console.log(candidate, config.ACFUN_SERVER + config.URLS.ACFUN_USER.SPACE + '/' + candidate.uid) // window.open(config.ACFUN_SERVER + config.URLS.ACFUN_USER.SPACE + '/' + candidate.uid); }, }, mounted : function(){ var vue = this; var messageContainerEle = document.querySelector('.container-live-feed-messages-acfunlive .live-message-container'); // 获取弹幕消息 callbackManager.register('message', function(data){ // 修改信息 if(_.isFunction(vue.interactionFormData.modifyContentFunc)){ vue.interactionFormData.modifyContentFunc(data); } if(data.interaction.type == 'enterroom'){ userInfo[data.uid].hasEnterroom = true; } else if(data.interaction.type == 'danmaku'){ userInfo[data.uid].hasDanmaku = true; vue.lastDanmakuMessage = data; } else if(data.interaction.type == 'like'){ userInfo[data.uid].hasLike = true; } else if(data.interaction.type == 'gift'){ userInfo[data.uid].hasGift = true; } else if(data.interaction.type == 'follow'){ userInfo[data.uid].hasFollow = true; } // 礼物合并 if( data.interaction.type == 'gift' && userInfo[data.uid].lastInteraction && userInfo[data.uid].lastInteraction.type == 'gift' && data.interaction.giftName == userInfo[data.uid].lastInteraction.giftName && data.interaction.sendTime - userInfo[data.uid].lastInteraction.sendTime<=5*1000*(data.interaction.giftName=='香蕉'?2:1) ){ userInfo[data.uid].lastInteraction.giftCount += data.interaction.giftCount; userInfo[data.uid].lastInteraction.sendTime = data.interaction.sendTime; userInfo[data.uid].lastInteraction.doAnime = false; userInfo[data.uid].lastInteraction.doAnime = true; } else{ vue.messageData.push(data); userInfo[data.uid].lastInteraction = data.interaction; } if(data.interaction.type == 'danmaku'){ // 如果有ac号,获取稿件信息 data.interaction.acSeries = extractAcSeries(data.interaction.content); if(data.interaction.acSeries != null){ vue.getDougaByAcSeries(data.interaction.acSeries, function(isSuccess, douga){ // 获取稿件成功 if(isSuccess){ data.interaction.douga = douga; } }); } // 如果是指令 var command = extractCommand(data.interaction.content); if(command!=null){ data = _.cloneDeep(data); data.command = command.command; data.interaction.content = command.text; callbackManager.feed('command:'+command.command, data); } } // 如果鼠标没有悬浮,则自动滚动至底部 if(!vue.mouseOn){ vue.$nextTick(function(){ // 横版滚动 if(vue.interactionFormData.direction=='horizontal'){ messageContainerEle.scrollLeft = messageContainerEle.scrollWidth; } // 纵版滚动 else{ messageContainerEle.scrollTop = messageContainerEle.scrollHeight; } }); } }); // 监听事件 messageContainerEle.addEventListener('mouseenter', function(e){ // 鼠标悬浮,显示滚动条 vue.mouseOn = true; }); messageContainerEle.addEventListener('mouseleave', function(e){ // 鼠标离开,隐藏滚动条 vue.mouseOn = false; }); this.giftList.forEach(function(gift){ vue.giftNameMapper[gift.name] = gift; }); async function loadData(){ // 查看缓存的数据 var audioFormData = await GM_getValue('audioFormData'); if(audioFormData){ vue.audioFormData = JSON.parse(audioFormData); vue.handleAudioFormSubmitValid(); } var interactionPreset = await GM_getValue('interactionPreset'); if(interactionPreset){ interactionPreset = JSON.parse(interactionPreset); vue.interactionPreset = interactionPreset; var activeInteractionPresetIndex = _.findIndex(interactionPreset, {active:true}); if(activeInteractionPresetIndex!=-1){ vue.activeInteractionPreset(interactionPreset[activeInteractionPresetIndex]); vue.downloadedFonts = await GM_getValue('downloadedFonts'); for(var fontName in vue.downloadedFonts){ // 添加字体 GM_addStyle(` @font-face{ font-family : ${fontName}; src: url(data:font/truetype;charset=utf-8;base64,${vue.downloadedFonts[fontName]}) format('truetype'); } `); } } } else{ vue.handleInteractionFormSubmitValid(); } /*var interactionFormData = await GM_getValue('interactionFormData'); if(interactionFormData){ interactionFormData = JSON.parse(interactionFormData); if(!interactionFormData.historyMinutes){ interactionFormData.historyMinutes = 10; } if(!interactionFormData.historyCount){ interactionFormData.historyCount = 200; } if(interactionFormData.joinclubFontSize){ vue.interactionFormData = interactionFormData; vue.handleInteractionFormSubmitValid(); // 默认字体 if(!vue.interactionFormData.fontFamily){ vue.interactionFormData.fontFamily = ['default', 'inherit']; } var fontName = vue.interactionFormData.fontFamily[vue.interactionFormData.fontFamily.length-1]; if(fontName!='inherit'){ vue.downloadedFonts = await GM_getValue('downloadedFonts'); for(var fontName in vue.downloadedFonts){ // 添加字体 GM_addStyle(` @font-face{ font-family : ${fontName}; src: url(data:font/truetype;charset=utf-8;base64,${vue.downloadedFonts[fontName]}) format('truetype'); } `); } } } } else{ vue.handleInteractionFormSubmitValid(); }*/ } loadData(); // 每500毫秒获取一次用户信息,避免被封 window.setInterval(()=>{ if(vue.candidateInfoCallbacks.length>0){ let [candidate, callback] = vue.candidateInfoCallbacks.splice(0, 1)[0]; vue._getCandidateInfo(candidate, callback); [candidate, callback] = vue.candidateInfoCallbacks.splice(0, 1)[0]; vue._getCandidateInfo(candidate, callback); [candidate, callback] = vue.candidateInfoCallbacks.splice(0, 1)[0]; vue._getCandidateInfo(candidate, callback); } }, 500); // 按键绑定,从ctrl+alt+0到ctrl+alt+9 hotkeys(_.range(10).map((index)=>`ctrl+alt+${index}`).join(','), (event, handler)=>{ var index = parseInt(handler.key.split('+')[2]); console.log('key', index, this.interactionPreset[index-1]) if(index<=this.interactionPreset.length){ this.activeInteractionPreset(this.interactionPreset[index-1]); } }); }, }); return vue; } disableVideos(); window.onload = function(){ start(); var intervalHandler = window.setInterval(function(){ if(loadVue()){ window.clearInterval(intervalHandler); } }, 500); }; })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址