function Point (x, y) { this.x = x this.y = y } function Map (w, h) { this.width = w this.height = h } // 画布中生成随机不重叠的坐标 // 坐标点以左上角为中心 function RandomCoordinate (conf) { conf = conf || {} this.el = conf.el || '' // 画布选择器或者dom this.pointSize = conf.pointSize || new Map(1, 1) // 坐标点半径(最大) this.total = conf.total || 1 // 生成多少个随机不重叠坐标 this.pointCoordList = [] // 生成坐标点数组 this.init = function () { if (!this.el) return console.warn('画布选择器必传') // 获取画布宽高 this.map = this.getMapSize() this.getPointCoordLimits() this.create() } this.getMapSize = function () { this.$el = $(this.el) var w = this.$el.width() var h = this.$el.height() return new Map(w, h) } this.getPointCoordLimits = function () { var xMax = this.map.width - this.pointSize.width var yMax = this.map.height - this.pointSize.height if (xMax <= 0) { xMax = 1 } if (yMax <= 0) { yMax = 1 } this.coordLimits = new Point(xMax, yMax) } // this.check // 检查是否和已创建的有重叠 this.checkListOverlap = function (p) { if (this.pointCoordList.length <= 0) return true var pass = true // pass,所有都不重叠 for (var i = 0; i < this.pointCoordList.length; i++) { var overlap = this.checkOverlap(p, this.pointCoordList[i]) if (overlap) { pass = false break } } return pass }, // point为矩形左上的碰撞检测:碰撞返回true // 利用两圆相切,圆心距离小于2r表示两圆相交(r圆半径)。把矩形对角线看作圆的直径 // 如果两个矩形左上角的点间距离大于矩形对角线长度,则认为两矩形无碰撞(无重叠) // 参考:https://segmentfault.com/a/1190000017463616 this.checkOverlap = function (nPoint, oPoint) { // 两矩形左上角坐标距离(三角函数) // https://www.qttc.net/171-javascript-get-two-points-distance.html var dx = Math.abs(nPoint.x - oPoint.x) var dy = Math.abs(nPoint.y - oPoint.y) var distance = Math.sqrt(dx * dx + dy * dy) // 矩形对角线长度 var w = this.pointSize.width var h = this.pointSize.height var diagonal = Math.sqrt(w * w + h * h) return distance <= diagonal } // 创建一个坐标 this.createOne = function () { var createTimes = 0 var createFailTimes = 0 var maxCreateFailTime = 200 var x,y while (createFailTimes < maxCreateFailTime) { createTimes++ x = Math.floor(Math.random() * this.coordLimits.x) y = Math.floor(Math.random() * this.coordLimits.y) var point = new Point(x, y) var pass = this.checkListOverlap(point) if (pass) { this.pointCoordList.push(point) break } else { createFailTimes++ } } if (createFailTimes >= maxCreateFailTime) { console.log('随机生成坐标%s次失败,停止随机生成', maxCreateFailTime) } else { console.log('随机生成坐标次数:%s,\n随机生成坐标失败次数:%s\n获得坐标:', createTimes, createFailTimes, JSON.stringify(point)) } } this.create = function () { for (var i = 0; i < this.total; i++) { this.createOne() } this.pointCoordList = this.pointCoordList.sort(function (a, b) { return a.x - b.x }) } this.init() } // 判断活动是否结束 var initPageTime = new Date().getTime() var initActiveOverCheck = -1 function activeOverCheck (endTime, callback) { if (initPageTime >= endTime) { return callback() } clearTimeout(initActiveOverCheck) var reloadTime = endTime - new Date().getTime() if (reloadTime <= (10 * 60 * 1000) ) { initActiveOverCheck = setTimeout(function (){ callback() }, reloadTime) } } // toast上限提示 function toastFn (text, duration) { if (duration) { duration = 1000 } var _html = "" _html+='
' _html+='' + text + '
' $('body').append(_html) setTimeout(function(){ $(".custom-toast").fadeOut().remove(); },duration) } // 展示弹窗 function showDialogOfType (type) { // $('#active-tip-modal').attr('data-modal-type', 'success').modal('show') // $('#active-tip-modal').attr('data-modal-type', 'over').modal('show') // $('#active-tip-modal').attr('data-modal-type', 'code').modal('show') $('#active-tip-modal').attr('data-modal-type', type).modal('show') } // 固定事件 $(function () { // 扫一扫 二维码 $.ajax({ url: '/publicapply/shareFission/info', success: function (res) { if (res.error_code === 0 && res.data) { $('#active-tip-modal .active-tip--code .code-img').attr('src', 'data:image/png;base64,' + res.data.erUrl) } } }) // 弹窗按钮事件 $('#dialog-button--over').on('click', function () { location.href = '/swordfish/frontPage/share/sess/index' }) $('#dialog-button--success').on('click', function () {}) }) var task = new Vue({ el: '#main-app', delimiters: ['${', '}'], data: { progress: { min: 0, max: 1000, current: 0, // 当前剑鱼币 pointImgMap: { unreceived: '/frontRouter/pc/activity/image/unreceived@2x.png', received: '/frontRouter/pc/activity/image/received@2x.png', wait: '/frontRouter/pc/activity/image/received@2x.png' }, anchorList: [ { id: '', className: 'first', rate: 0, // 进度,单位%,最大为100 pointImg: '', // ''/unreceived/received anchorText: '0剑鱼币' }, { id: '800', className: 'unreceived', rate: 80, pointImg: 'unreceived', anchorText: '800剑鱼币', tipText: '7天超级订阅' }, { id: '1000', className: 'unreceived', rate: 100, pointImg: 'unreceived', anchorText: '1000剑鱼币', tipText: '30天超级订阅' } ], }, // 任务球 missionsList: [ { id: 'subscribe', x: 0, y: 0, num: 300, unit: '剑鱼币', complete: false, hide: false, name: '超级订阅' // 任务描述 }, { id: 'invite', x: 0, y: 0, num: 500, unit: '剑鱼币', complete: false, hide: false, name: '邀请领好礼' }, { id: 'improveInfo', x: 0, y: 0, num: 200, unit: '剑鱼币', complete: false, hide: false, name: '完善信息' } ], rewardList: [], toolBoxList: [ { text: '超级订阅', url: '/front/subscribe.html' }, { text: '大会员', url: '/big/page/index' }, { text: '企业商机管理', url: '/swordfish/frontPage/entpc/free/enptc_index' }, { text: '数据定制服务', url: '/front/structed/pc_index.html' }, { text: '数据自助导出', url: '/front/dataExport/toSieve' }, { text: '数据流量包', url: '/front/dataPack/createOrder' }, { text: '电信行业解决方案', url: '/swordfish/frontPage/solution/free/index' }, { text: '中标必听课', url: '/jyxspc' }, { text: '剑鱼文库', url: '/swordfish/docs' }, ], rulesList: [ { text: '活动期内,用户分别完成各任务即可获得相对应的剑鱼币,达到800剑鱼币免费领7天超级订阅,达到1000剑鱼币免费领30天超级订阅,完成【免费订阅】可获得300剑鱼币,完成【邀请领好礼】可获得500剑鱼币,完成【完善信息】可获得200剑鱼币。' }, { text: '完成免费订阅、邀请领好礼、完善信息三个任务且活动页剑鱼币累计达到1000即可领取超级订阅权益,一共可领37天,通过其他形式获取的剑鱼币将不作为领取超级订阅的依据。' }, { text: '活动期一个用户最高可领取65天超级订阅,集齐1000剑鱼币一共可领37天超级订阅,成功参与邀请领好礼活动,最高可得28天超级订阅,领取后在【我的奖励】中查看并使用超级订阅权限。' }, { text: '免费订阅需设置"区域、关键词”视为完成该任务,旧版免费订阅需更新为新版免费订阅视为完成该任务。' }, { text: '法律许可范围内本次活动解释权归北京剑鱼信息技术有限公司所有。' } ] }, computed: { rate: function () { var calcRate = (this.progress.current / this.progress.max) * 100 if (calcRate > 100) { calcRate = 100 } if (calcRate < 0) { calcRate = 0 } return calcRate }, progressAnchorList: function () { var progressList = JSON.parse(JSON.stringify(this.progress.anchorList)) var rate = this.rate var existRate = false for (var i = 0; i < progressList.length; i++) { if (progressList[i].rate === rate) { existRate = true break } } if (!existRate) { progressList.push({ rate: this.rate, // 进度,单位%,最大为100 anchorText: this.progress.current + '剑鱼币' }) } return progressList.sort(function (a, b) { return a.rate - b.rate }) } }, created: function () { this.ajaxActiveStatus() this.ajaxProgress() this.ajaxList() }, mounted: function () { this.calcPointList() }, methods: { calcPointList: function () { var dom = this.$refs.missions window.points = new RandomCoordinate({ el: dom, total: this.missionsList.length, pointSize: new Map(142, 160) }) var pointList = points.pointCoordList for (var i = 0; i < this.missionsList.length; i++) { this.missionsList[i].x = pointList[i].x this.missionsList[i].y = pointList[i].y } }, onClickLink: function (item) { window.open(item.url) }, onClickListItem: function (item) { if (item.icon === 'jy-svip') { location.href = '/front/subscribe.html' } else { location.href = '/swordfish/integral/index/detail' } }, onClickReceive: function (type, item) { var status = false if (type === 'schedule' && item.className === 'wait') { status = true } else if (type === 'mission' && item.complete) { status = true } if (!status) { switch (item.id) { case 'subscribe': { showDialogOfType('code') break } case 'invite': { location.href = '/swordfish/frontPage/share/sess/index' break } case 'improveInfo': { // 留资 vm.isNeedSubmit('activity_free_plan', function(){ vm.showSuccess = true }) break } } return } var _this = this this.ajaxReceive({ type: type, value: item.id }, function (result, msg) { if (result) { switch (item.id) { case 'subscribe': { toastFn('已成功领取300剑鱼币', 1500) break } case 'invite': { toastFn('已成功领取500剑鱼币', 1500) break } case 'improveInfo': { // 留资 toastFn('已成功领取200剑鱼币', 1500) break } case '800': { $('.active-tip--success .text-give-day').text('7') showDialogOfType('success') break } case '1000': { $('.active-tip--success .text-give-day').text('30') showDialogOfType('success') break } } _this.ajaxActiveStatus() _this.ajaxProgress() _this.ajaxList() } else { toastFn(msg, 1500) } }) }, ajaxReceive: function (data, callback) { $.ajax({ url: '/jyActivity/bidderPlan/receive', type: 'post', data: data, success: function (res) { return callback(res.data) } }) }, ajaxProgress: function () { var _this = this $.ajax({ url: '/jyActivity/bidderPlan/schedule', type:' post', success: function (res) { if (res.error_code === 0 && res.data) { _this.progress.current = res.data.nowNum _this.missionsList[0].complete = res.data.missions.subscribe === 1 _this.missionsList[1].complete = res.data.missions.invite === 1 _this.missionsList[2].complete = res.data.missions.improveInfo === 1 _this.missionsList[0].hide = res.data.missions.subscribe === -1 _this.missionsList[1].hide = res.data.missions.invite === -1 _this.missionsList[2].hide = res.data.missions.improveInfo === -1 var anchorStatus = { 1: 'wait', 0: 'unreceived', '-1': 'received', } _this.progress.anchorList[1].className = anchorStatus[res.data.schedule['800']] _this.progress.anchorList[2].className = anchorStatus[res.data.schedule['1000']] } } }) }, ajaxActiveStatus: function () { $.ajax({ url: '/jyActivity/bidderPlan/period', type: 'get', success: function (res) { activeOverCheck(res.data.end * 1000, function () { showDialogOfType('over') }) } }) }, ajaxList: function () { var _this = this $.ajax({ url: '/jyActivity/myAward/awardlist', type: 'post', data: { code: 'bidderPlan', pageSize: 10, pageNum: 0 }, success: function (res) { if (res.error_code === 0 && res.data) { if (res.data.list && typeof res.data.list.map === 'function') { _this.rewardList = res.data.list.map(function (v) { return { id: v._id, icon: v.award.indexOf('订阅') !== -1 ? 'jy-svip' : 'jy-coin', rewardText: v.award, receiveTime: new Date(v.date * 1000).pattern('yyyy-MM-dd HH:mm:ss'), receiveFrom: v.getway } }) } } } }) } } , })