202402.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. // 判断活动是否结束
  2. var initPageTime = new Date().getTime()
  3. var initActiveOverCheck = -1
  4. function activeOverCheck (endTime, callback) {
  5. if (initPageTime >= endTime) {
  6. return callback()
  7. }
  8. clearTimeout(initActiveOverCheck)
  9. var reloadTime = endTime - new Date().getTime()
  10. if (reloadTime <= (10 * 60 * 1000) ) {
  11. initActiveOverCheck = setTimeout(function (){
  12. callback()
  13. }, reloadTime)
  14. }
  15. }
  16. // 注册埋点
  17. function trackClick (c_type) {
  18. if (!c_type) return
  19. try {
  20. clab_tracker.track('c_202402_activity', {
  21. c_platform: 'pc',
  22. c_type: c_type,
  23. date: new Date()
  24. })
  25. } catch (error) {
  26. console.dir(error)
  27. }
  28. }
  29. // toast上限提示
  30. function toastFn (text, duration) {
  31. if (!duration) {
  32. duration = 1000
  33. }
  34. var _html = ""
  35. _html+='<div class="custom-toast"><div class="mask" style="background-color: transparent;"></div><div class="toast-container">'
  36. _html+='<span>' + text + '</span></div></div>'
  37. $('body').append(_html)
  38. setTimeout(function(){
  39. $(".custom-toast").fadeOut().remove();
  40. },duration)
  41. }
  42. // 展示弹窗
  43. function showDialogOfType (type) {
  44. // $('#active-tip-modal').attr('data-modal-type', 'success').modal('show')
  45. // $('#active-tip-modal').attr('data-modal-type', 'over').modal('show')
  46. // $('#active-tip-modal').attr('data-modal-type', 'code').modal('show')
  47. var modal = $('#active-tip-modal')
  48. modal.attr('data-modal-type', type).modal('show')
  49. if (type === 'over') {
  50. modal.off('click')
  51. } else if (type === 'success') {
  52. // 点击按钮关闭
  53. $('.close-dialog-icon-bottom').show().off('click').on('click', function () {
  54. modal.modal('hide')
  55. })
  56. } else {
  57. modal.off('click').on('click', function () {
  58. modal.modal('hide')
  59. })
  60. }
  61. }
  62. function closeDialog () {
  63. var modal = $('#active-tip-modal')
  64. modal.modal('hide')
  65. }
  66. function loginCallback (r) {
  67. // task.hasLogin = loginflag
  68. var hasLogin = !!r
  69. task.hasLogin = hasLogin
  70. if (hasLogin) {
  71. task.ajaxCoinCount()
  72. task.getCoinMissionComplete()
  73. }
  74. }
  75. // 固定事件
  76. $(function () {
  77. // 弹窗按钮事件
  78. $('#dialog-button--over').on('click', function () {
  79. window.open('/swordfish/frontPage/share/sess/index')
  80. })
  81. $('#dialog-button--success').on('click', function () {})
  82. })
  83. var task = new Vue({
  84. el: '#main-app',
  85. delimiters: ['${', '}'],
  86. data: {
  87. conf: {
  88. now: Date.now(),
  89. header_pic: '',
  90. },
  91. loading: false,
  92. confLoaded: false,
  93. coinCount: 0, // 剑鱼币剩余数量
  94. activityId: '',
  95. hasLogin: false,
  96. hasCoinMission: false, // 是否有剑鱼币任务
  97. isPersonalIdentity: false, // 是否是个人版身份
  98. activityConf: {
  99. name: '天天抢会员,助力复工免费领会员', // 活动名称
  100. active_start_time: 1707926400, // 活动开始时间 2024.2.15
  101. active_end_time: 1708358400, // 活动结束时间
  102. lottery_start_time: 10, // 抽奖开始时间(活动期间内的某个整点)
  103. lottery_end_time: 24, // 抽奖结束时间(活动期间内的某个整点)
  104. lottery_start_unix: 0, // 当天抽奖时间
  105. cost: 100, // 抽奖花费:默X个剑鱼币兑换1次抽奖机会
  106. rule: [], // 活动规则
  107. share_copy: {}, // 分享文案
  108. prize: [], // 奖品图片列表
  109. prompt_msg: '',
  110. status: 0, // 状态 0-抽奖状态 1-未开始(倒计时) 2-根据prompt_msg展示文案
  111. now_unix: 0,
  112. },
  113. shareInfo: {},
  114. rewardList: [],
  115. rulesList: [
  116. // {
  117. // text: '活动时间:2024.2.15-2024.2.20,活动期间每天10:00开始抢会员。'
  118. // },
  119. // {
  120. // text: '活动对象:仅限已注册“剑鱼标讯”的用户。'
  121. // },
  122. // {
  123. // text: '活动介绍:用户进入天天抢会员活动页面,使用100剑鱼币即可获得1次抽奖机会,每天仅限100个中奖名额,每人每天每个身份仅有1次抽奖机会,中奖之后在活动页面“我的奖励”中查看兑换码进行兑换。'
  124. // },
  125. // {
  126. // text: '免费订阅需设置"活动福利:超级订阅周卡/月卡、WPS会员月卡、网易云音乐黑胶VIP月卡、喜马拉雅会员2个月、腾讯视频会员周卡、120剑鱼币。'
  127. // },
  128. // {
  129. // text: '兑换方式:打开链接<a class="rules-link" target="_blank" href="https://22233.cn/2258">(https://22233.cn/2258)</a>输入兑换码和手机号,即可兑换使用,兑换成功后可用充值的账号登录官方APP进行查询,每个兑换码只能兑换1次且兑换过程中不可更换充值账号,请确认充值账号无误后进行兑换。'
  130. // },
  131. // {
  132. // text: '本活动最终解释权归剑鱼标讯所有。'
  133. // },
  134. ],
  135. tipInfo: {
  136. timerId: '',
  137. countdown: false,
  138. countdownText: '',
  139. text: '', // 内容
  140. },
  141. dialog: {
  142. confirm: false,
  143. },
  144. timerId: null,
  145. animateMinDelay: 2000,
  146. animateDebounce: false,
  147. animateTimestamp: 0,
  148. ballList: [],
  149. pageDOM: {
  150. ratio: 1,
  151. },
  152. },
  153. computed: {
  154. now: function () {
  155. var now = this.conf.now
  156. // console.log(new Date(now).pattern('yyyy.MM.dd HH:mm:ss'))
  157. return now
  158. },
  159. coinMissionCompleted: function () {
  160. if (this.isPersonalIdentity) {
  161. return !this.hasCoinMission
  162. } else {
  163. return true
  164. }
  165. },
  166. shareInfoPlatform: function () {
  167. if (this.shareInfo && this.shareInfo.PC) {
  168. return this.shareInfo.PC
  169. } else {
  170. return {}
  171. }
  172. },
  173. copyLinkText: function () {
  174. if (this.shareInfoPlatform.href) {
  175. return location.origin + this.shareInfoPlatform.href
  176. } else {
  177. return location.href
  178. }
  179. },
  180. pointerShow: function () {
  181. return this.activityConf.status === 0
  182. },
  183. activeStartTime: function () {
  184. var conf = this.activityConf
  185. return new Date(conf.active_start_time * 1000).pattern('yyyy.MM.dd')
  186. },
  187. activeEndTime: function () {
  188. var conf = this.activityConf
  189. return new Date(conf.active_end_time * 1000).pattern('yyyy.MM.dd')
  190. },
  191. },
  192. created: function () {
  193. var activityId = getParam('id')
  194. if (activityId) {
  195. this.activityId = activityId
  196. }
  197. this.ajaxActiveStatus()
  198. this.ajaxList()
  199. },
  200. mounted: function () {
  201. this.bindCalcScale()
  202. },
  203. methods: {
  204. add0: function (t) {
  205. return t < 10 ? ('0' + t) : t
  206. },
  207. toLogin: function () {
  208. $('#header-login-btn').trigger('click')
  209. },
  210. doCopy: function () {
  211. trackClick('点击复制链接')
  212. var shareText = this.shareInfoPlatform.subtitle || ''
  213. var copyLinkText = this.copyLinkText
  214. this.copyText(shareText + '\n' + copyLinkText)
  215. toastFn('复制成功', 2000)
  216. },
  217. copyText: function (text) {
  218. const input = document.createElement('textarea') // js创建一个input输入框
  219. input.value = text // 将需要复制的文本赋值到创建的input输入框中
  220. document.body.appendChild(input) // 将输入框暂时创建到实例里面
  221. input.select() // 选中输入框中的内容
  222. document.execCommand('copy') // 执行复制操作
  223. document.body.removeChild(input) // 最后删除实例中临时创建的input输入框,完成复制操作
  224. },
  225. onClickListItem: function (item) {
  226. var delay = 0
  227. if (item.attribute > 0) {
  228. // 第三方。复制兑换码
  229. if (item.code) {
  230. // 复制成功2s后跳转
  231. this.copyText(item.code)
  232. delay = 1000
  233. toastFn('复制成功', delay)
  234. }
  235. }
  236. setTimeout(function () {
  237. if (item.url) {
  238. window.open(item.url)
  239. }
  240. }, delay)
  241. },
  242. calcTimeString: function (t) {
  243. return new Date(t).pattern('yyyy.MM.dd HH:mm:ss')
  244. },
  245. calcLastTimeDiff: function (timestamp) {
  246. var diff = moment.duration(Math.abs(timestamp))
  247. var days = diff.days()
  248. var hours = diff.hours()
  249. var minutes = diff.minutes()
  250. var seconds = diff.seconds()
  251. return {
  252. days: days,
  253. hours: hours,
  254. minutes: minutes,
  255. seconds: seconds
  256. }
  257. },
  258. getCoinMissionComplete: function () {
  259. var _this = this
  260. $.ajax({
  261. url: '/jyActivity/task',
  262. type: 'POST',
  263. success: function (res) {
  264. if (res && res.data) {
  265. if (!$.isArray(res.data.limitedTask)) {
  266. res.data.limitedTask = []
  267. }
  268. if (!$.isArray(res.data.newbieTask)) {
  269. res.data.newbieTask = []
  270. }
  271. var statusArr = []
  272. var missionList = res.data.limitedTask.concat(res.data.newbieTask)
  273. missionList.forEach(function (item) {
  274. // status是否完成 0未完成 1完成
  275. statusArr.push(item.status == 1)
  276. })
  277. _this.hasCoinMission = statusArr.indexOf(false) !== -1
  278. }
  279. }
  280. })
  281. // 获取当前身份
  282. $.ajax({
  283. url: '/publicapply/identity/list',
  284. type: 'POST',
  285. success: function (res) {
  286. if (res && $.isArray(res.data)) {
  287. var list = res.data
  288. for (var i = 0; i < list.length; i++) {
  289. if (list[i].checked == 1 && list[i].positionType == 0) {
  290. _this.isPersonalIdentity = true
  291. break
  292. }
  293. }
  294. }
  295. }
  296. })
  297. },
  298. ajaxCoinCount: function () {
  299. var _this = this
  300. $.ajax({
  301. url: '/jyintegral/getList',
  302. type: 'POST',
  303. data: {
  304. B: true
  305. },
  306. success: function (res) {
  307. if (res && res.data && res.data.points) {
  308. _this.coinCount = res.data.points.balance || 0
  309. }
  310. }
  311. })
  312. },
  313. toEarnCoin: function () {
  314. if (this.coinMissionCompleted) {
  315. // 充值剑鱼币
  316. window.open('/swordfish/integral/index/recharge')
  317. } else {
  318. // 赚剑鱼币
  319. window.open('/page_workDesktop/work-bench/app/points/earn')
  320. }
  321. },
  322. ajaxActiveStatus: function () {
  323. var _this = this
  324. $.ajax({
  325. url: '/publicapply/activity/day/info',
  326. type: 'post',
  327. async: false,
  328. data: {
  329. id: this.activityId
  330. },
  331. success: function (res) {
  332. if (res && res.data) {
  333. _this.$set(_this, 'activityConf', res.data)
  334. // 数据赋值
  335. if ($.isArray(res.data.rule)) {
  336. _this.rulesList = res.data.rule
  337. }
  338. if (res.data.now_unix) {
  339. _this.conf.now = res.data.now_unix * 1000
  340. }
  341. _this.shareInfo = res.data.share_copy
  342. activeOverCheck(res.data.active_end_time * 1000, function () {
  343. _this.activeOver()
  344. })
  345. _this.initActivity()
  346. } else {
  347. _this.activeOver()
  348. }
  349. },
  350. complete: function () {
  351. _this.confLoaded = true
  352. }
  353. })
  354. },
  355. activeOver: function () {
  356. var conf = this.activityConf
  357. conf.status = 2
  358. conf.prompt_msg = '活动已结束'
  359. },
  360. startNowTimer: function () {
  361. var _this = this
  362. if (this.timerId) {
  363. clearInterval(this.timerId)
  364. }
  365. var func = function () {
  366. _this.conf.now = _this.conf.now + 1000
  367. }
  368. func()
  369. this.timerId = setInterval(func, 1000)
  370. },
  371. // 初始化
  372. initActivity: function () {
  373. var _this = this
  374. this.startNowTimer()
  375. var conf = this.activityConf
  376. var now = this.now
  377. console.log('活动时间:', this.calcTimeString(conf.active_start_time * 1000), '-->', this.calcTimeString(conf.active_end_time * 1000))
  378. this.calcTipInfoText()
  379. this.calcBallList()
  380. document.title = conf.name
  381. this.conf.header_pic = conf.pic || '/frontRouter/pc/activity/image/202402/header-banner-title@2x.png'
  382. setTimeout(function () {
  383. _this.resizeCallback()
  384. }, 100)
  385. },
  386. calcCountdownText: function (t) {
  387. var diff = 0
  388. if (this.now < t) {
  389. // 计算倒数计
  390. diff = t - this.now
  391. var lastTimeConf = this.calcLastTimeDiff(diff)
  392. var days = lastTimeConf.days
  393. var hours = lastTimeConf.hours
  394. var minutes = lastTimeConf.minutes
  395. var seconds = lastTimeConf.seconds
  396. var hms = [this.add0(hours), this.add0(minutes), this.add0(seconds)].join(':')
  397. var r = ''
  398. if (days > 0) {
  399. r = days + '天 ' + hms
  400. } else {
  401. r = hms
  402. }
  403. }
  404. this.tipInfo.countdownText = r
  405. return diff
  406. },
  407. calcTipInfoText: function () {
  408. var _this = this
  409. var conf = this.activityConf
  410. var status = conf.status // 状态 0-抽奖状态 1-未开始(倒计时) 2-根据prompt_msg展示文案
  411. if (this.tipInfo.timerId) {
  412. clearInterval(this.tipInfo.timerId)
  413. }
  414. if (status === 1) {
  415. var func = function () {
  416. var diff = _this.calcCountdownText(conf.lottery_start_unix * 1000)
  417. if (diff <= 0) {
  418. clearInterval(_this.tipInfo.timerId)
  419. _this.activityConf.status = 0
  420. _this.calcTipInfoText()
  421. }
  422. }
  423. func()
  424. this.tipInfo.timerId = setInterval(func, 1000)
  425. this.tipInfo.countdown = true
  426. } else {
  427. this.tipInfo.countdown = false
  428. }
  429. this.tipInfo.text = conf.prompt_msg
  430. },
  431. startChou: function () {
  432. var conf = this.activityConf
  433. if (!this.hasLogin) {
  434. return this.toLogin()
  435. }
  436. if (conf.status === 1) {
  437. return toastFn('活动未开始', 2000)
  438. }
  439. if (conf.status >= 2) {
  440. return
  441. }
  442. if (this.coinCount < conf.cost) {
  443. return toastFn('剑鱼币余额不足', 2000)
  444. }
  445. // 二次确认
  446. this.dialog.confirm = true
  447. },
  448. confirmChou: function () {
  449. var _this = this
  450. this.loading = true
  451. this.dialog.confirm = false
  452. this.startAnimate()
  453. $.ajax({
  454. url: '/publicapply/activity/day/raffle',
  455. type: 'post',
  456. data: {
  457. id: this.activityId
  458. },
  459. success: function (res) {
  460. if (res && res.error_code === 0 && res.data) {
  461. // 动画最少执行3s
  462. _this.stopAnimateDelay(_this.animateMinDelay, function () {
  463. _this.showSuccessDialog(res.data)
  464. _this.ajaxActiveStatus()
  465. _this.ajaxList()
  466. _this.ajaxCoinCount()
  467. })
  468. } else {
  469. _this.stopAnimateDelay(_this.animateMinDelay, function () {
  470. toastFn(res.error_msg || '请求失败', 2000)
  471. })
  472. }
  473. },
  474. error: function () {
  475. _this.stopAnimateDelay(_this.animateMinDelay)
  476. },
  477. complete: function () {
  478. _this.loading = false
  479. }
  480. })
  481. },
  482. ajaxList: function () {
  483. var _this = this
  484. $.ajax({
  485. url: '/publicapply/activity/day/list',
  486. type: 'POST',
  487. data: {
  488. id: this.activityId
  489. },
  490. success: function (res) {
  491. if (res && $.isArray(res.data)) {
  492. _this.rewardList = res.data.map(function (v) {
  493. var desc = ''
  494. if (v.attribute > 0) {
  495. // 第三方
  496. desc += '<p>兑换码:'+ v.code +'</p>'
  497. desc += '<p>兑换截止日期:'+ v.ex_end_time.split(' ')[0] +'</p>'
  498. } else {
  499. desc += v.notes
  500. }
  501. return {
  502. attribute: v.attribute,
  503. code: v.code,
  504. create_time: v.create_time,
  505. ex_end_time: v.ex_end_time,
  506. name: v.name,
  507. url: v.url,
  508. pic: v.pic,
  509. rewardText: v.name,
  510. receiveTime: v.create_time,
  511. desc: desc,
  512. }
  513. })
  514. }
  515. }
  516. })
  517. },
  518. showSuccessDialog: function (info) {
  519. var _this = this
  520. $('.reward-img > img').attr('src', info.pic)
  521. var textArr = []
  522. textArr.push('恭喜您成功获得' + info.name)
  523. if (info.attribute > 0) {
  524. // 第三方
  525. textArr.push('兑换码:' + info.redeemCode)
  526. textArr.push('兑换截止日期: ' + info.redeemDeadline)
  527. $('.active-tip-success-content .activity-red-button').text('复制兑换码,去兑换').on('click', function () {
  528. closeDialog()
  529. toastFn('复制成功', 1000)
  530. _this.copyText(info.redeemCode)
  531. setTimeout(function () {
  532. window.open(info.url)
  533. }, 1000)
  534. })
  535. } else {
  536. textArr.push(info.subtitle)
  537. $('.active-tip-success-content .activity-red-button').text('去查看').on('click', function () {
  538. closeDialog()
  539. window.open(info.url)
  540. })
  541. }
  542. $('.reward-float-tip').show().find('.float-tip-content').text(info.label)
  543. $('.reward-success-text').html(textArr.join('<br />'))
  544. showDialogOfType('success')
  545. },
  546. startAnimate: function () {
  547. console.time('动画执行时间')
  548. this.animateTimestamp = Date.now()
  549. this.animateDebounce = true
  550. },
  551. stopAnimate: function () {
  552. this.animateDebounce = false
  553. },
  554. // 最少动画执行delay毫秒
  555. stopAnimateDelay: function (delay, callback) {
  556. if (!delay) {
  557. delay = 3000
  558. }
  559. console.log('动画最小执行时间:%sms', delay)
  560. var _this = this
  561. var now = Date.now()
  562. var diff = now - this.animateTimestamp
  563. var timeDelay = delay - diff
  564. if (diff >= delay) {
  565. this.stopAnimate()
  566. console.timeEnd('动画执行时间')
  567. console.log('距离动画开始时间:%sms,动画已执行时间大于最小执行时间,直接结束动画', diff)
  568. callback && callback()
  569. } else {
  570. console.log('距离动画开始时间:%sms,需要补充动画时间:%sms', diff, timeDelay)
  571. setTimeout(function () {
  572. console.timeEnd('动画执行时间')
  573. _this.stopAnimate()
  574. callback && callback()
  575. }, timeDelay)
  576. }
  577. },
  578. calcBallList: function () {
  579. var conf = this.activityConf
  580. var prizeList = conf.prize
  581. var ballConf = {
  582. ballWidth: 80,
  583. ballHeight: 80
  584. }
  585. if (!$.isArray(prizeList)) return
  586. var calcBallList = ballUtils.init(prizeList, ballConf)
  587. this.ballList = calcBallList
  588. },
  589. getScreenWidth: function () {
  590. var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
  591. return width;
  592. },
  593. calcScale: function () {
  594. var screenWidth = this.getScreenWidth()
  595. // scale计算
  596. var scale = 1
  597. if (screenWidth < 1920) {
  598. scale = screenWidth/1920
  599. }
  600. if (scale < 0.85) {
  601. scale = 0.85
  602. }
  603. if (scale > 1) {
  604. scale = 1
  605. }
  606. this.pageDOM.ratio = scale
  607. var contentWrapper = $('.page-container-content')
  608. contentWrapper.css({ transform: 'scale('+scale+')' })
  609. },
  610. // 外层盒子高度和内容缩放后的实际高度相同
  611. calcMainAppHeight: function () {
  612. var mainApp = $('#main-app')
  613. var contentWrapper = $('.page-container-content')
  614. var ratio = this.pageDOM.ratio
  615. mainApp.css({ height: contentWrapper.height()*ratio })
  616. },
  617. resizeCallback: function () {
  618. this.calcScale()
  619. this.calcMainAppHeight()
  620. },
  621. bindCalcScale: function () {
  622. var _this = this
  623. this.resizeCallback()
  624. window.addEventListener('resize', function () {
  625. _this.resizeCallback()
  626. })
  627. },
  628. }
  629. })