掘金抽奖

掘金抽奖 签到 免费抽奖 5连抽 10连抽 可视化抽奖 petite-vue

  1. // ==UserScript==
  2. // @name 掘金抽奖
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.2.5
  5. // @description 掘金抽奖 签到 免费抽奖 5连抽 10连抽 可视化抽奖 petite-vue
  6. // @author 无仙
  7. // @match https://juejin.cn/*
  8. // @icon https://lf3-cdn-tos.bytescm.com/obj/static/xitu_juejin_web//static/favicons/favicon-32x32.png
  9. // @require https://unpkg.com/petite-vue
  10. // ==/UserScript==
  11.  
  12. (async function () {
  13. 'use strict';
  14.  
  15. const { createApp } = PetiteVue; // 不会吧不会吧,不会还有人不知道petite-vue吧
  16.  
  17. const root = document.createElement('div');
  18. root.class = 'wx_draw_wrap';
  19. root.innerHTML = `
  20. <div v-show="!popup" class="wx_draw" @click="open">掘金抽奖</div>
  21.  
  22. <div v-if="popup" class="wx_popup">
  23. <div class="wx_mask" @click="popup = false"></div>
  24.  
  25. <div class="wx_main">
  26. <div class="wx_header">
  27. <div>掘金抽奖</div>
  28. <div class="wx_score">当前矿石:{{ score }}</div>
  29. </div>
  30.  
  31. <div class="wx_body">
  32. <div class="wx_options">
  33. <div @click="check_in" v-if="check_status === -1 || check_status === false">签到</div>
  34. <div @click="get_free" v-else>签到成功</div>
  35. <div @click="draw(5)">5连抽</div>
  36. <div @click="draw(10)">10连抽</div>
  37. <div @click="draw(undefined)">梭哈抽奖</div>
  38. </div>
  39.  
  40. <table cellpadding="0" cellspacing="0" border="0" width="100%">
  41. <thead>
  42. <tr>
  43. <th>奖品图片</th>
  44. <th>奖品名称</th>
  45. <th>中奖次数</th>
  46. </tr>
  47. </thead>
  48. <tbody>
  49. <tr v-for="item in award">
  50. <td><img :src="item.lottery_image"/></td>
  51. <td>{{ item.lottery_name }}</td>
  52. <td>{{ item.times }}</td>
  53. </tr>
  54. </tbody>
  55. </table>
  56.  
  57. <div class="wx_loading" v-if="loading">
  58. <svg class="circular" viewBox="25 25 50 50">
  59. <circle class="path" cx="50" cy="50" r="20" fill="none" />
  60. </svg>
  61. </div>
  62. </div>
  63.  
  64. <div class="wx_footer">
  65. <div class="wx_confirm wx_btn" @click="popup = false">关闭</div>
  66. </div>
  67. </div>
  68. </div>
  69. `;
  70.  
  71. // 查询奖品列表
  72. const res = await fetch('https://api.juejin.cn/growth_api/v1/lottery_config/get', {
  73. headers: {
  74. cookie: document.cookie
  75. },
  76. method: 'GET',
  77. credentials: 'include'
  78. }).then((res) => res.json());
  79.  
  80. const award = (res.data && res.data.lottery ? res.data.lottery : []).map((item) => ({ ...item, times: 0 }));
  81. const { free_count, point_cost } = res.data; // 剩余免费抽奖次数,单次抽奖消耗数
  82.  
  83. document.body.appendChild(root); // 插入DOM
  84.  
  85. // petite-vue init初始化
  86. createApp({
  87. award,
  88. popup: false,
  89. loading: false,
  90. score: 0,
  91. free_count,
  92. check_status: -1,
  93.  
  94. async open() {
  95. const res = await fetch('https://api.juejin.cn/growth_api/v1/get_cur_point', {
  96. headers: {
  97. cookie: document.cookie
  98. },
  99. method: 'GET',
  100. credentials: 'include'
  101. }).then((res) => res.json());
  102.  
  103. this.score = res.data; // 当前分数
  104.  
  105. this.popup = true;
  106.  
  107. (this.check_status === -1 || this.check_status === false) && this.get_status();
  108. },
  109. async draw(times, is_not_free = true) {
  110. if (this.loading || times === 0) return;
  111.  
  112. // const is_not_free = !(this.free_count && times === 1);
  113.  
  114. if (is_not_free && this.score < point_cost * (times || 1)) return alert('分都不够想啥呢?');
  115.  
  116. let i = 0;
  117. const drawFn = async () => {
  118. if ((is_not_free && this.score < point_cost) || i === times) {
  119. this.free_count = 0;
  120. this.loading = false;
  121. this.open();
  122. console.log(`${times ? times + '连抽' : '梭哈'}结束!`);
  123. return;
  124. }
  125.  
  126. const result = await fetch('https://api.juejin.cn/growth_api/v1/lottery/draw', {
  127. headers: {
  128. cookie: document.cookie
  129. },
  130. method: 'POST',
  131. credentials: 'include'
  132. }).then((res) => res.json());
  133.  
  134. if (result.err_no !== 0) {
  135. console.log(result.err_msg);
  136. this.loading = false;
  137. this.open();
  138. return;
  139. }
  140.  
  141. i++;
  142. is_not_free && (this.score -= point_cost);
  143.  
  144. if (result.data.lottery_type === 1) this.score += 66;
  145.  
  146. const item = this.award.find((item) => item.lottery_id === result.data.lottery_id);
  147. item.times++;
  148.  
  149. console.log(`抽到:${result.data.lottery_name}`);
  150. drawFn();
  151. };
  152.  
  153. console.log(`开始${times ? times + '连抽' : '梭哈'}!`);
  154. this.loading = true;
  155. this.award.forEach((item) => {
  156. item.times = 0;
  157. });
  158. try {
  159. drawFn();
  160. } catch (error) {
  161. this.loading = false;
  162. console.error(error);
  163. }
  164. },
  165. async check_in() {
  166. if (this.check_status) {
  167. this.get_free(); // 免费抽奖
  168. return;
  169. }
  170.  
  171. // 签到
  172. const check_in = await fetch('https://api.juejin.cn/growth_api/v1/check_in', {
  173. headers: {
  174. cookie: document.cookie
  175. },
  176. method: 'POST',
  177. credentials: 'include'
  178. }).then((res) => res.json());
  179.  
  180. if (check_in.err_no !== 0) {
  181. alert('签到失败!');
  182. this.check_status = false;
  183. return;
  184. }
  185.  
  186. this.check_status = true;
  187. this.score = check_in.data.sum_point;
  188. this.get_free(); // 免费抽奖
  189. },
  190. async get_status() {
  191. // 查询签到状态
  192. const today_status = await fetch('https://api.juejin.cn/growth_api/v1/get_today_status', {
  193. headers: {
  194. cookie: document.cookie
  195. },
  196. method: 'GET',
  197. credentials: 'include'
  198. }).then((res) => res.json());
  199.  
  200. this.check_status = today_status.data;
  201. },
  202. async get_free() {
  203. // 查询是否有免费抽奖次数
  204. const res = await fetch('https://api.juejin.cn/growth_api/v1/lottery_config/get', {
  205. headers: {
  206. cookie: document.cookie
  207. },
  208. method: 'GET',
  209. credentials: 'include'
  210. }).then((res) => res.json());
  211.  
  212. this.free_count = res.data.free_count;
  213.  
  214. if (res.data.free_count) {
  215. // 有免费抽奖次数
  216. this.draw(res.data.free_count, false);
  217. }
  218. }
  219. }).mount();
  220.  
  221. // 处理样式
  222. const style = `
  223. .wx_draw_wrap {
  224. box-sizing: border-box;
  225. position: fixed;
  226. top: 50%;
  227. left: 0px;
  228. z-index: 888888;
  229. margin-top: -20px;
  230. }
  231. .wx_draw {
  232. box-sizing: border-box;
  233. position: fixed;
  234. top: 50%;
  235. left: 0px;
  236. z-index: 888888;
  237. width: 40px;
  238. height: 40px;
  239. line-height: 16px;
  240. font-size: 12px;
  241. padding: 4px;
  242. background-color: rgb(232, 243, 255);
  243. border: 1px solid rgb(232, 243, 255);
  244. color: rgb(30, 128, 255);
  245. text-align: center;
  246. overflow: hidden;
  247. cursor: pointer;
  248. }
  249. .wx_popup {
  250. position: fixed;
  251. left: 0;
  252. top: 0;
  253. right: 0;
  254. bottom: 0;
  255. z-index: 999999;
  256. }
  257. .wx_mask {
  258. width: 100%;
  259. height: 100%;
  260. background: rgba(0,0,0,0.5);
  261. }
  262. .wx_main {
  263. --width: 460px;
  264. position: absolute;
  265. left: 50%;
  266. top: 50%;
  267. width: var(--width);
  268. transform: translate(-50%, -50%);
  269. background: #fff;
  270. border-radius: 4px;
  271. }
  272. .wx_main .wx_header {
  273. height: 40px;
  274. line-height: 40px;
  275. font-size: 16px;
  276. padding: 0 16px;
  277. border-bottom: 1px solid #999;
  278. display: flex;
  279. align-items: center;
  280. justify-content: space-between;
  281. color: #000;
  282. font-weight: 400;
  283. }
  284. .wx_score {
  285. font-size: 12px;
  286. font-size: #00a100;
  287. }
  288. .wx_main .wx_body {
  289. padding: 16px;
  290. border-bottom: 1px solid #999;
  291. position: relative;
  292. }
  293. .wx_main .wx_options {
  294. display: flex;
  295. align-items: center;
  296. justify-content: space-between;
  297. margin-bottom: 8px;
  298. }
  299. .wx_main .wx_options div {
  300. width: 80px;
  301. text-align: center;
  302. height: 24px;
  303. line-height: 24px;
  304. background-color: rgb(232, 243, 255);
  305. border: 1px solid #c9d4e3;
  306. color: rgb(30, 128, 255);
  307. cursor: pointer;
  308. border-radius: 2px;
  309. }
  310. .wx_main .wx_body p {
  311. margin: 0 0 8px;
  312. }
  313. .wx_body table {
  314. width: 100%;
  315. text-align: center;
  316. border-left: 1px solid #ccc;
  317. border-top: 1px solid #ccc;
  318. }
  319. .wx_body table th,
  320. .wx_body table td {
  321. border-right: 1px solid #ccc;
  322. border-bottom: 1px solid #ccc;
  323. line-height: 20px;
  324. }
  325. .wx_body table th {
  326. line-height: 28px;
  327. }
  328. .wx_main .wx_body img {
  329. vertical-align: middle;
  330. width: 40px;
  331. height: 40px;
  332. }
  333. .wx_main .wx_footer {
  334. padding: 12px 16px;
  335. text-align: right;
  336. }
  337. .wx_btn {
  338. display: inline-block;
  339. width: 48px;
  340. cursor: pointer;
  341. text-align: center;
  342. height: 20px;
  343. line-height: 20px;
  344. background-color: rgb(232, 243, 255);
  345. border: 1px solid #c9d4e3;
  346. color: rgb(30, 128, 255);
  347. border-radius: 2px;
  348. }
  349. .wx_loading {
  350. position: absolute;
  351. left: 0;
  352. top: 0;
  353. right: 0;
  354. bottom: 0;
  355. z-index: 9999999;
  356. background: rgba(0,0,0,0.65);
  357. }
  358. .wx_loading .circular {
  359. height: 42px;
  360. width: 42px;
  361. -webkit-animation: loading-rotate 2s linear infinite;
  362. animation: loading-rotate 2s linear infinite;
  363. position: absolute;
  364. left: 50%;
  365. top: 50%;
  366. margin-top: -21px;
  367. margin-left: -21px;
  368. }
  369. .wx_loading .path {
  370. -webkit-animation: loading-dash 1.5s ease-in-out infinite;
  371. animation: loading-dash 1.5s ease-in-out infinite;
  372. stroke-dasharray: 90, 150;
  373. stroke-dashoffset: 0;
  374. stroke-width: 2;
  375. stroke: #409eff;
  376. stroke-linecap: round;
  377. }
  378. @keyframes loading-rotate {
  379. 100% {
  380. -webkit-transform: rotate(360deg);
  381. transform: rotate(360deg);
  382. }
  383. }
  384. @keyframes loading-dash {
  385. 0% {
  386. stroke-dasharray: 1, 200;
  387. stroke-dashoffset: 0;
  388. }
  389. 50% {
  390. stroke-dasharray: 90, 150;
  391. stroke-dashoffset: -40px;
  392. }
  393. 100% {
  394. stroke-dasharray: 90, 150;
  395. stroke-dashoffset: -120px;
  396. }
  397. }
  398. `;
  399.  
  400. const styleEl = document.createElement('style');
  401. styleEl.textContent = style;
  402. document.head.appendChild(styleEl);
  403. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址