task.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. function Point (x, y) {
  2. this.x = x
  3. this.y = y
  4. }
  5. function Map (w, h) {
  6. this.width = w
  7. this.height = h
  8. }
  9. // 画布中生成随机不重叠的坐标
  10. // 坐标点以左上角为中心
  11. function RandomCoordinate (conf) {
  12. conf = conf || {}
  13. this.el = conf.el || '' // 画布选择器或者dom
  14. this.pointSize = conf.pointSize || new Map(1, 1) // 坐标点半径(最大)
  15. this.total = conf.total || 1 // 生成多少个随机不重叠坐标
  16. this.pointCoordList = [] // 生成坐标点数组
  17. this.init = function () {
  18. if (!this.el) return console.warn('画布选择器必传')
  19. // 获取画布宽高
  20. this.map = this.getMapSize()
  21. this.getPointCoordLimits()
  22. this.create()
  23. }
  24. this.getMapSize = function () {
  25. this.$el = $(this.el)
  26. var w = this.$el.width()
  27. var h = this.$el.height()
  28. return new Map(w, h)
  29. }
  30. this.getPointCoordLimits = function () {
  31. var xMax = this.map.width - this.pointSize.width
  32. var yMax = this.map.height - this.pointSize.height
  33. if (xMax <= 0) {
  34. xMax = 1
  35. }
  36. if (yMax <= 0) {
  37. yMax = 1
  38. }
  39. this.coordLimits = new Point(xMax, yMax)
  40. }
  41. // this.check
  42. // 检查是否和已创建的有重叠
  43. this.checkListOverlap = function (p) {
  44. if (this.pointCoordList.length <= 0) return true
  45. var pass = true // pass,所有都不重叠
  46. for (var i = 0; i < this.pointCoordList.length; i++) {
  47. var overlap = this.checkOverlap(p, this.pointCoordList[i])
  48. if (overlap) {
  49. pass = false
  50. break
  51. }
  52. }
  53. return pass
  54. },
  55. // point为矩形左上的碰撞检测:碰撞返回true
  56. // 利用两圆相切,圆心距离小于2r表示两圆相交(r圆半径)。把矩形对角线看作圆的直径
  57. // 如果两个矩形左上角的点间距离大于矩形对角线长度,则认为两矩形无碰撞(无重叠)
  58. // 参考:https://segmentfault.com/a/1190000017463616
  59. this.checkOverlap = function (nPoint, oPoint) {
  60. // 两矩形左上角坐标距离(三角函数)
  61. // https://www.qttc.net/171-javascript-get-two-points-distance.html
  62. var dx = Math.abs(nPoint.x - oPoint.x)
  63. var dy = Math.abs(nPoint.y - oPoint.y)
  64. var distance = Math.sqrt(dx * dx + dy * dy)
  65. // 矩形对角线长度
  66. var w = this.pointSize.width
  67. var h = this.pointSize.height
  68. var diagonal = Math.sqrt(w * w + h * h)
  69. return distance <= diagonal
  70. }
  71. // 创建一个坐标
  72. this.createOne = function () {
  73. var createTimes = 0
  74. var createFailTimes = 0
  75. var maxCreateFailTime = 200
  76. var x,y
  77. while (createFailTimes < maxCreateFailTime) {
  78. createTimes++
  79. x = Math.floor(Math.random() * this.coordLimits.x)
  80. y = Math.floor(Math.random() * this.coordLimits.y)
  81. var point = new Point(x, y)
  82. var pass = this.checkListOverlap(point)
  83. if (pass) {
  84. this.pointCoordList.push(point)
  85. break
  86. } else {
  87. createFailTimes++
  88. }
  89. }
  90. if (createFailTimes >= maxCreateFailTime) {
  91. console.log('随机生成坐标%s次失败,停止随机生成', maxCreateFailTime)
  92. } else {
  93. console.log('随机生成坐标次数:%s,\n随机生成坐标失败次数:%s\n获得坐标:', createTimes, createFailTimes, JSON.stringify(point))
  94. }
  95. }
  96. this.create = function () {
  97. for (var i = 0; i < this.total; i++) {
  98. this.createOne()
  99. }
  100. this.pointCoordList = this.pointCoordList.sort(function (a, b) {
  101. return a.x - b.x
  102. })
  103. }
  104. this.init()
  105. }
  106. // 判断活动是否结束
  107. var initPageTime = new Date().getTime()
  108. var initActiveOverCheck = -1
  109. function activeOverCheck (endTime, callback) {
  110. if (initPageTime >= endTime) {
  111. return callback()
  112. }
  113. clearTimeout(initActiveOverCheck)
  114. var reloadTime = endTime - new Date().getTime()
  115. if (reloadTime <= (10 * 60 * 1000) ) {
  116. initActiveOverCheck = setTimeout(function (){
  117. callback()
  118. }, reloadTime)
  119. }
  120. }
  121. // toast上限提示
  122. function toastFn (text, duration) {
  123. if (duration) {
  124. duration = 1000
  125. }
  126. var _html = ""
  127. _html+='<div class="custom-toast"><div class="mask" style="background-color: transparent;"></div><div class="toast-container">'
  128. _html+='<span>' + text + '</span></div></div>'
  129. $('body').append(_html)
  130. setTimeout(function(){
  131. $(".custom-toast").fadeOut().remove();
  132. },duration)
  133. }
  134. // 展示弹窗
  135. function showDialogOfType (type) {
  136. // $('#active-tip-modal').attr('data-modal-type', 'success').modal('show')
  137. // $('#active-tip-modal').attr('data-modal-type', 'over').modal('show')
  138. // $('#active-tip-modal').attr('data-modal-type', 'code').modal('show')
  139. $('#active-tip-modal').attr('data-modal-type', type).modal('show')
  140. }
  141. // 固定事件
  142. $(function () {
  143. // 扫一扫 二维码
  144. $.ajax({
  145. url: '/publicapply/shareFission/info',
  146. success: function (res) {
  147. if (res.error_code === 0 && res.data) {
  148. $('#active-tip-modal .active-tip--code .code-img').attr('src', 'data:image/png;base64,' + res.data.erUrl)
  149. }
  150. }
  151. })
  152. // 弹窗按钮事件
  153. $('#dialog-button--over').on('click', function () {
  154. location.href = '/swordfish/frontPage/share/sess/index'
  155. })
  156. $('#dialog-button--success').on('click', function () {})
  157. })
  158. var task = new Vue({
  159. el: '#main-app',
  160. delimiters: ['${', '}'],
  161. data: {
  162. progress: {
  163. min: 0,
  164. max: 1000,
  165. current: 0, // 当前剑鱼币
  166. pointImgMap: {
  167. unreceived: '/frontRouter/pc/activity/image/unreceived@2x.png',
  168. received: '/frontRouter/pc/activity/image/received@2x.png',
  169. wait: '/frontRouter/pc/activity/image/received@2x.png'
  170. },
  171. anchorList: [
  172. {
  173. id: '',
  174. className: 'first',
  175. rate: 0, // 进度,单位%,最大为100
  176. pointImg: '', // ''/unreceived/received
  177. anchorText: '0剑鱼币'
  178. },
  179. {
  180. id: '800',
  181. className: 'unreceived',
  182. rate: 80,
  183. pointImg: 'unreceived',
  184. anchorText: '800剑鱼币',
  185. tipText: '7天超级订阅'
  186. },
  187. {
  188. id: '1000',
  189. className: 'unreceived',
  190. rate: 100,
  191. pointImg: 'unreceived',
  192. anchorText: '1000剑鱼币',
  193. tipText: '30天超级订阅'
  194. }
  195. ],
  196. },
  197. // 任务球
  198. missionsList: [
  199. {
  200. id: 'subscribe',
  201. x: 0,
  202. y: 0,
  203. num: 300,
  204. unit: '剑鱼币',
  205. complete: false,
  206. hide: false,
  207. name: '超级订阅' // 任务描述
  208. },
  209. {
  210. id: 'invite',
  211. x: 0,
  212. y: 0,
  213. num: 500,
  214. unit: '剑鱼币',
  215. complete: false,
  216. hide: false,
  217. name: '邀请领好礼'
  218. },
  219. {
  220. id: 'improveInfo',
  221. x: 0,
  222. y: 0,
  223. num: 200,
  224. unit: '剑鱼币',
  225. complete: false,
  226. hide: false,
  227. name: '完善信息'
  228. }
  229. ],
  230. rewardList: [],
  231. toolBoxList: [
  232. {
  233. text: '超级订阅',
  234. url: '/front/subscribe.html'
  235. },
  236. {
  237. text: '大会员',
  238. url: '/big/page/index'
  239. },
  240. {
  241. text: '企业商机管理',
  242. url: '/swordfish/frontPage/entpc/free/enptc_index'
  243. },
  244. {
  245. text: '数据定制服务',
  246. url: '/front/structed/pc_index.html'
  247. },
  248. {
  249. text: '数据自助导出',
  250. url: '/front/dataExport/toSieve'
  251. },
  252. {
  253. text: '数据流量包',
  254. url: '/front/dataPack/createOrder'
  255. },
  256. {
  257. text: '电信行业解决方案',
  258. url: '/swordfish/frontPage/solution/free/index'
  259. },
  260. {
  261. text: '中标必听课',
  262. url: '/jyxspc'
  263. },
  264. {
  265. text: '剑鱼文库',
  266. url: '/swordfish/docs'
  267. },
  268. ],
  269. rulesList: [
  270. {
  271. text: '活动期内,用户分别完成各任务即可获得相对应的剑鱼币,达到800剑鱼币免费领7天超级订阅,达到1000剑鱼币免费领30天超级订阅,完成【免费订阅】可获得300剑鱼币,完成【邀请领好礼】可获得500剑鱼币,完成【完善信息】可获得200剑鱼币。'
  272. },
  273. {
  274. text: '完成免费订阅、邀请领好礼、完善信息三个任务且活动页剑鱼币累计达到1000即可领取超级订阅权益,一共可领37天,通过其他形式获取的剑鱼币将不作为领取超级订阅的依据。'
  275. },
  276. {
  277. text: '活动期一个用户最高可领取65天超级订阅,集齐1000剑鱼币一共可领37天超级订阅,成功参与邀请领好礼活动,最高可得28天超级订阅,领取后在【我的奖励】中查看并使用超级订阅权限。'
  278. },
  279. {
  280. text: '免费订阅需设置"区域、关键词”视为完成该任务,旧版免费订阅需更新为新版免费订阅视为完成该任务。'
  281. },
  282. {
  283. text: '法律许可范围内本次活动解释权归北京剑鱼信息技术有限公司所有。'
  284. }
  285. ]
  286. },
  287. computed: {
  288. rate: function () {
  289. var calcRate = (this.progress.current / this.progress.max) * 100
  290. if (calcRate > 100) {
  291. calcRate = 100
  292. }
  293. if (calcRate < 0) {
  294. calcRate = 0
  295. }
  296. return calcRate
  297. },
  298. progressAnchorList: function () {
  299. var progressList = JSON.parse(JSON.stringify(this.progress.anchorList))
  300. var rate = this.rate
  301. var existRate = false
  302. for (var i = 0; i < progressList.length; i++) {
  303. if (progressList[i].rate === rate) {
  304. existRate = true
  305. break
  306. }
  307. }
  308. if (!existRate) {
  309. progressList.push({
  310. rate: this.rate, // 进度,单位%,最大为100
  311. anchorText: this.progress.current + '剑鱼币'
  312. })
  313. }
  314. return progressList.sort(function (a, b) {
  315. return a.rate - b.rate
  316. })
  317. }
  318. },
  319. created: function () {
  320. this.ajaxActiveStatus()
  321. this.ajaxProgress()
  322. this.ajaxList()
  323. },
  324. mounted: function () {
  325. this.calcPointList()
  326. },
  327. methods: {
  328. calcPointList: function () {
  329. var dom = this.$refs.missions
  330. window.points = new RandomCoordinate({
  331. el: dom,
  332. total: this.missionsList.length,
  333. pointSize: new Map(142, 160)
  334. })
  335. var pointList = points.pointCoordList
  336. for (var i = 0; i < this.missionsList.length; i++) {
  337. this.missionsList[i].x = pointList[i].x
  338. this.missionsList[i].y = pointList[i].y
  339. }
  340. },
  341. onClickLink: function (item) {
  342. window.open(item.url)
  343. },
  344. onClickListItem: function (item) {
  345. if (item.icon === 'jy-svip') {
  346. location.href = '/front/subscribe.html'
  347. } else {
  348. location.href = '/swordfish/integral/index/detail'
  349. }
  350. },
  351. onClickReceive: function (type, item) {
  352. var status = false
  353. if (type === 'schedule' && item.className === 'wait') {
  354. status = true
  355. } else if (type === 'mission' && item.complete) {
  356. status = true
  357. }
  358. if (!status) {
  359. switch (item.id) {
  360. case 'subscribe': {
  361. showDialogOfType('code')
  362. break
  363. }
  364. case 'invite': {
  365. location.href = '/swordfish/frontPage/share/sess/index'
  366. break
  367. }
  368. case 'improveInfo': {
  369. // 留资
  370. vm.isNeedSubmit('activity_free_plan', function(){
  371. vm.showSuccess = true
  372. })
  373. break
  374. }
  375. }
  376. return
  377. }
  378. var _this = this
  379. this.ajaxReceive({ type: type, value: item.id }, function (result, msg) {
  380. if (result) {
  381. switch (item.id) {
  382. case 'subscribe': {
  383. toastFn('已成功领取300剑鱼币', 1500)
  384. break
  385. }
  386. case 'invite': {
  387. toastFn('已成功领取500剑鱼币', 1500)
  388. break
  389. }
  390. case 'improveInfo': {
  391. // 留资
  392. toastFn('已成功领取200剑鱼币', 1500)
  393. break
  394. }
  395. case '800': {
  396. $('.active-tip--success .text-give-day').text('7')
  397. showDialogOfType('success')
  398. break
  399. }
  400. case '1000': {
  401. $('.active-tip--success .text-give-day').text('30')
  402. showDialogOfType('success')
  403. break
  404. }
  405. }
  406. _this.ajaxActiveStatus()
  407. _this.ajaxProgress()
  408. _this.ajaxList()
  409. } else {
  410. toastFn(msg, 1500)
  411. }
  412. })
  413. },
  414. ajaxReceive: function (data, callback) {
  415. $.ajax({
  416. url: '/jyActivity/bidderPlan/receive',
  417. type: 'post',
  418. data: data,
  419. success: function (res) {
  420. return callback(res.data)
  421. }
  422. })
  423. },
  424. ajaxProgress: function () {
  425. var _this = this
  426. $.ajax({
  427. url: '/jyActivity/bidderPlan/schedule',
  428. type:' post',
  429. success: function (res) {
  430. if (res.error_code === 0 && res.data) {
  431. _this.progress.current = res.data.nowNum
  432. _this.missionsList[0].complete = res.data.missions.subscribe === 1
  433. _this.missionsList[1].complete = res.data.missions.invite === 1
  434. _this.missionsList[2].complete = res.data.missions.improveInfo === 1
  435. _this.missionsList[0].hide = res.data.missions.subscribe === -1
  436. _this.missionsList[1].hide = res.data.missions.invite === -1
  437. _this.missionsList[2].hide = res.data.missions.improveInfo === -1
  438. var anchorStatus = {
  439. 1: 'wait',
  440. 0: 'unreceived',
  441. '-1': 'received',
  442. }
  443. _this.progress.anchorList[1].className = anchorStatus[res.data.schedule['800']]
  444. _this.progress.anchorList[2].className = anchorStatus[res.data.schedule['1000']]
  445. }
  446. }
  447. })
  448. },
  449. ajaxActiveStatus: function () {
  450. $.ajax({
  451. url: '/jyActivity/bidderPlan/period',
  452. type: 'get',
  453. success: function (res) {
  454. activeOverCheck(res.data.end * 1000, function () {
  455. showDialogOfType('over')
  456. })
  457. }
  458. })
  459. },
  460. ajaxList: function () {
  461. var _this = this
  462. $.ajax({
  463. url: '/jyActivity/myAward/awardlist',
  464. type: 'post',
  465. data: {
  466. code: 'bidderPlan',
  467. pageSize: 10,
  468. pageNum: 0
  469. },
  470. success: function (res) {
  471. if (res.error_code === 0 && res.data) {
  472. if (res.data.list && typeof res.data.list.map === 'function') {
  473. _this.rewardList = res.data.list.map(function (v) {
  474. return {
  475. id: v._id,
  476. icon: v.award.indexOf('订阅') !== -1 ? 'jy-svip' : 'jy-coin',
  477. rewardText: v.award,
  478. receiveTime: new Date(v.date * 1000).pattern('yyyy-MM-dd HH:mm:ss'),
  479. receiveFrom: v.getway
  480. }
  481. })
  482. }
  483. }
  484. }
  485. })
  486. }
  487. }
  488. ,
  489. })