├── image ├── overview.png └── lighthouse.png ├── .fatherrc.js ├── package.json ├── index.js ├── .gitignore ├── README.md ├── test ├── workbox.js ├── index.html └── service-worker.js ├── index.css └── App.jsx /image/overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lie5860/hypergryph-gacha/HEAD/image/overview.png -------------------------------------------------------------------------------- /image/lighthouse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lie5860/hypergryph-gacha/HEAD/image/lighthouse.png -------------------------------------------------------------------------------- /.fatherrc.js: -------------------------------------------------------------------------------- 1 | export default { 2 | entry: './index.js', 3 | // esm: 'webpack', 4 | umd: true, 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-hello", 3 | "version": "0.0.1", 4 | "scripts": { 5 | "build": "father-build" 6 | }, 7 | "dependencies": {}, 8 | "devDependencies": { 9 | "father-build": "^1.21.1", 10 | "@babel/core": "^7.12.3" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import React, {createElement} from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App.jsx' 4 | 5 | 6 | // 初始化 7 | export function bootstrap() { 8 | } 9 | 10 | // 挂载 11 | export function mount(container, props) { 12 | console.log(props, 'props') 13 | ReactDOM.render(createElement(App, props, null), container); 14 | } 15 | 16 | // 更新 17 | export function updated(attrName, value, container, props) { 18 | ReactDOM.render(createElement(App, props, null), container); 19 | } 20 | 21 | window.App = { 22 | bootstrap, mount, updated 23 | } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | .pnp 4 | .pnp.js 5 | .env.*.local 6 | .history 7 | .rts* 8 | *.log* 9 | *.pid 10 | *.pid.* 11 | *.report 12 | *.lcov 13 | lib-cov 14 | 15 | node_modules/ 16 | .npm 17 | .lock-wscript 18 | .yarn-integrity 19 | .node_repl_history 20 | .nyc_output 21 | *.tsbuildinfo 22 | .eslintcache 23 | .sonarlint 24 | 25 | dist/ 26 | coverage/ 27 | release/ 28 | output/ 29 | output_resource/ 30 | 31 | .vscode/**/* 32 | !.vscode/settings.json 33 | !.vscode/extensions.json 34 | .idea/ 35 | 36 | **/*/typings/auto-generated 37 | **/*/adapters/**/index.ts 38 | **/*/adapters/**/index.js 39 | 40 | .changeset/pre.json 41 | 42 | .pnpm-store/ 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hypergryph-gacha 2 | 一个明日方舟的寻访记录查看工具,可以方便的统计出货概率,缓存历史寻访记录。 3 | 4 | 数据使用阿里云FC node写入,私有mongo存储。 5 | 6 | 该站点当前所有部分使用React开发,使用magic转Web Component使用。 7 | 8 | 线上访问地址:[ak.saki.cc](http://ak.saki.cc) 9 | 10 | 概览图 11 | 12 | ![概览图](https://github.com/lie5860/hypergryph-gacha/blob/main/image/overview.png?raw=true) 13 | 14 | Lighthouse结果 15 | 16 | ![Lighthouse结果](https://github.com/lie5860/hypergryph-gacha/blob/main/image/lighthouse.png?raw=true) 17 | 18 | 本地调试方式 npm i => npm run build => 打开test目录下的index.html访问 19 | 20 | 欢迎小伙伴提Issue给这个小工具提一些建议和想法。 21 | 22 | ## 版本履历 23 | 24 | #### v0.8 25 | 通过Lighthouse报告进行部分优化 26 | 27 | #### v0.7 28 | 域名支持HTTPS 增加Service Worker缓存 支持无网络访问 29 | 30 | #### v0.6 31 | 增加暗黑模式 32 | 33 | mongo增加索引、支持追加数据,优化非首次爬取时长 34 | 35 | #### v0.5 36 | 引入shoelace webcomponent组件库优化页面 37 | 38 | #### v0.4 39 | 使用magic将项目使用react打包成webcomponent使用 40 | 41 | 优化分析,合并所有非限定池,并根据最终结果按照时间倒序展示各池子情况 42 | 43 | #### v0.3 44 | 支持数据远端存储,爬取的数据将存入mongo进行分析 45 | -------------------------------------------------------------------------------- /test/workbox.js: -------------------------------------------------------------------------------- 1 | var workbox=function(){"use strict";try{self.workbox.v["workbox:sw:3.3.0"]=1}catch(t){}const t={backgroundSync:"background-sync",broadcastUpdate:"broadcast-cache-update",cacheableResponse:"cacheable-response",core:"core",expiration:"cache-expiration",googleAnalytics:"google-analytics",precaching:"precaching",rangeRequests:"range-requests",routing:"routing",strategies:"strategies",streams:"streams"};return new class{constructor(){return this.v={},this.t={debug:"localhost"===self.location.hostname,modulePathPrefix:null,modulePathCb:null},this.e=this.t.debug?"dev":"prod",this.s=!1,new Proxy(this,{get(e,s){if(e[s])return e[s];const o=t[s];return o&&e.loadModule(`workbox-${o}`),e[s]}})}setConfig(t={}){if(this.s)throw new Error("Config must be set before accessing workbox.* modules");Object.assign(this.t,t),this.e=this.t.debug?"dev":"prod"}skipWaiting(){self.addEventListener("install",()=>self.skipWaiting())}clientsClaim(){self.addEventListener("activate",()=>self.clients.claim())}loadModule(t){const e=this.o(t);try{importScripts(e),this.s=!0}catch(s){throw console.error(`Unable to import module '${t}' from '${e}'.`),s}}o(t){if(this.t.modulePathCb)return this.t.modulePathCb(t,this.t.debug);let e=["https://storage.googleapis.com/workbox-cdn/releases/3.3.0"];const s=`${t}.${this.e}.js`,o=this.t.modulePathPrefix;return o&&""===(e=o.split("/"))[e.length-1]&&e.splice(e.length-1,1),e.push(s),e.join("/")}}}(); 2 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 11 | 13 | 14 | hypergryph-gacha 15 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /test/service-worker.js: -------------------------------------------------------------------------------- 1 | //首先是异常处理 2 | self.addEventListener('error', function (e) { 3 | self.clients.matchAll() 4 | .then(function (clients) { 5 | if (clients && clients.length) { 6 | clients[0].postMessage({ 7 | type: 'ERROR', 8 | msg: e.message || null, 9 | stack: e.error ? e.error.stack : null 10 | }); 11 | } 12 | }); 13 | }); 14 | self.addEventListener('unhandledrejection', function (e) { 15 | self.clients.matchAll() 16 | .then(function (clients) { 17 | if (clients && clients.length) { 18 | clients[0].postMessage({ 19 | type: 'REJECTION', 20 | msg: e.reason ? e.reason.message : null, 21 | stack: e.reason ? e.reason.stack : null 22 | }); 23 | } 24 | }); 25 | }) 26 | //然后引入workbox 27 | importScripts( 28 | "./workbox.js" 29 | ); 30 | if (workbox) { 31 | console.log('workbox加载成功'); 32 | } else { 33 | console.log('workbox加载失败'); 34 | } 35 | //关闭控制台中的输出 36 | workbox.setConfig({debug: false}); 37 | 38 | //直接激活跳过等待阶段 39 | workbox.skipWaiting(); 40 | workbox.clientsClaim(); 41 | // 定义缓存名称 42 | workbox.core.setCacheNameDetails({ 43 | prefix: 'react-wc', 44 | suffix: 'v1' 45 | }); 46 | const urls = [ 47 | 'https://unpkg.com/@magic-microservices/magic@1.1.3/dist/index.umd.js', 48 | 'https://cdn.jsdelivr.net/npm/echarts@5.3.0/dist/echarts.js', 49 | 'https://unpkg.com/react@17/umd/react.production.min.js', 50 | 'https://unpkg.com/react-dom@17/umd/react-dom.production.min.js', 51 | 'https://unpkg.com/axios/dist/axios.min.js', 52 | ] 53 | var fileList = urls.map(url => ({url})); 54 | //precache 适用于支持跨域的cdn和域内静态资源 55 | workbox.precaching.suppressWarnings(); 56 | workbox.precaching.precacheAndRoute(fileList, { 57 | "ignoreUrlParametersMatching": [/./] 58 | }); 59 | //staleWhileRevalidate 60 | // 这种策略的意思是当请求的路由有对应的 Cache 缓存结果就直接返回, 61 | // 在返回 Cache 缓存结果的同时会在后台发起网络请求拿到请求结果并更新 Cache 缓存, 62 | // 如果本来就没有 Cache 缓存的话,直接就发起网络请求并返回结果,这对用户来说是一种非常安全的策略,能保证用户最快速的拿到请求的结果。 63 | // 但是也有一定的缺点,就是还是会有网络请求占用了用户的网络带宽。可以像如下的方式使用 State While Revalidate 策略: 64 | workbox.routing.registerRoute( 65 | new RegExp('https://74082082-1683720436570405.test.functioncompute.com/'), 66 | workbox.strategies.staleWhileRevalidate({ 67 | //cache名称 68 | cacheName: 'lf-sw:static', 69 | plugins: [ 70 | new workbox.expiration.Plugin({ 71 | //cache最大数量 72 | maxEntries: 30 73 | }) 74 | ] 75 | }) 76 | ); 77 | //cacheFirst 78 | // 这个策略的意思就是当匹配到请求之后直接从 Cache 缓存中取得结果, 79 | // 如果 Cache 缓存中没有结果,那就会发起网络请求, 80 | // 拿到网络请求结果并将结果更新至 Cache 缓存, 81 | // 并将结果返回给客户端。这种策略比较适合结果不怎么变动且对实时性要求不高的请求。 82 | // 可以像如下方式使用 Cache First 策略: 83 | workbox.routing.registerRoute( 84 | new RegExp('https://cdn\.jsdelivr\.net/npm/@shoelace-style/'), 85 | workbox.strategies.cacheFirst({ 86 | cacheName: 'lf-sw:img', 87 | plugins: [ 88 | //如果要拿到域外的资源,必须配置 89 | //因为跨域使用fetch配置了 90 | //mode: 'no-cors',所以status返回值为0,故而需要兼容 91 | new workbox.cacheableResponse.Plugin({ 92 | statuses: [0, 200] 93 | }), 94 | new workbox.expiration.Plugin({ 95 | maxEntries: 150, 96 | //缓存的时间 97 | maxAgeSeconds: 60 * 60 * 24 * 365 98 | }) 99 | ] 100 | }) 101 | ); 102 | console.log('Hello from service-worker.js'); 103 | -------------------------------------------------------------------------------- /index.css: -------------------------------------------------------------------------------- 1 | * { 2 | -webkit-font-smoothing: antialiased; 3 | -webkit-overflow-scrolling: touch; 4 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 5 | -webkit-text-size-adjust: none; 6 | -webkit-touch-callout: none; 7 | box-sizing: border-box; 8 | } 9 | 10 | :root { 11 | --three-color: var(--sl-color-neutral-600); 12 | --four-color: var(--sl-color-purple-600); 13 | --five-color: var(--sl-color-amber-500); 14 | --six-color: var(--sl-color-orange-600); 15 | --tip: var(--sl-color-neutral-600); 16 | --black: var(--sl-color-neutral-1000); 17 | --white: var(--sl-color-neutral-0); 18 | } 19 | 20 | html { 21 | background: var(--sl-color-neutral-0); 22 | color: var(--sl-color-neutral-1000); 23 | } 24 | 25 | body { 26 | background-color: var(--white); 27 | } 28 | 29 | @media (min-width: 800px) and (-webkit-device-pixel-ratio: 1) { 30 | .detail-data { 31 | break-inside: avoid; 32 | counter-increment: item-counter; 33 | float: unset !important; 34 | } 35 | 36 | .dataGrid { 37 | column-count: 2; /*css3新增,把contaner容器中的内容分为三列*/ 38 | column-gap: 10px; /*定义列之间的间隙为20px*/ 39 | } 40 | } 41 | 42 | @media (min-width: 1600px) and (-webkit-device-pixel-ratio: 2) { 43 | .detail-data { 44 | break-inside: avoid; 45 | counter-increment: item-counter; 46 | float: unset !important; 47 | } 48 | 49 | .dataGrid { 50 | column-count: 2; /*css3新增,把contaner容器中的内容分为三列*/ 51 | column-gap: 10px; /*定义列之间的间隙为20px*/ 52 | } 53 | } 54 | 55 | @media (min-width: 2400px) and (-webkit-device-pixel-ratio: 3) { 56 | .detail-data { 57 | break-inside: avoid; 58 | counter-increment: item-counter; 59 | float: unset !important; 60 | } 61 | 62 | .dataGrid { 63 | column-count: 2; /*css3新增,把contaner容器中的内容分为三列*/ 64 | column-gap: 10px; /*定义列之间的间隙为20px*/ 65 | } 66 | } 67 | 68 | a { 69 | color: var(--sl-color-primary-600); 70 | } 71 | 72 | .title { 73 | font-size: 20px; 74 | font-weight: 700; 75 | margin: 0; 76 | } 77 | 78 | body { 79 | margin: 0; 80 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 81 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 82 | sans-serif; 83 | -webkit-font-smoothing: antialiased; 84 | -moz-osx-font-smoothing: grayscale; 85 | 86 | box-sizing: border-box; 87 | } 88 | 89 | .main-container { 90 | padding: 20px; 91 | font-size: 1rem; 92 | } 93 | 94 | .alert--closable { 95 | margin-bottom: 1rem; 96 | } 97 | 98 | .token { 99 | display: inline-block; 100 | width: calc(100% - 84px); 101 | } 102 | 103 | .submitBtn { 104 | display: inline-block; 105 | } 106 | 107 | .dataGrid { 108 | text-align: center; 109 | } 110 | 111 | .pBlue { 112 | color: var(--sl-color-primary-700); 113 | } 114 | 115 | .detail-data { 116 | box-sizing: border-box; 117 | padding: 10px; 118 | text-align: left; 119 | line-height: 1.5; 120 | float: left; 121 | width: 100%; 122 | } 123 | 124 | .pt10 { 125 | padding-top: 10px 126 | } 127 | 128 | .clean-float:after { /*伪元素是行内元素 正常浏览器清除浮动方法*/ 129 | content: ""; 130 | display: block; 131 | height: 0; 132 | clear: both; 133 | visibility: hidden; 134 | } 135 | 136 | .spinner-icon { 137 | position: fixed; 138 | top: 0; 139 | bottom: 0; 140 | left: 0; 141 | right: 0; 142 | display: flex; 143 | align-items: center; 144 | justify-content: center; 145 | background-color: transparent; 146 | } 147 | 148 | .spinner-bg { 149 | position: fixed; 150 | top: 0; 151 | bottom: 0; 152 | left: 0; 153 | right: 0; 154 | display: flex; 155 | align-items: center; 156 | justify-content: center; 157 | background-color: var(--sl-color-neutral-700); 158 | opacity: 0.5; 159 | } 160 | 161 | .echart-c { 162 | display: flex; 163 | align-items: center; 164 | justify-content: center; 165 | } 166 | 167 | .avatar-me { 168 | display: flex; 169 | justify-content: center; 170 | align-items: center; 171 | } 172 | 173 | .new-tag { 174 | font-family: 'monospace'; 175 | color: var(--sl-color-primary-400); 176 | } 177 | 178 | 179 | .tip { 180 | font-family: 'monospace'; 181 | color: var(--sl-color-neutral-600); 182 | } 183 | 184 | .title-container { 185 | text-align: center; 186 | margin: 10px 0; 187 | } 188 | -------------------------------------------------------------------------------- /App.jsx: -------------------------------------------------------------------------------- 1 | import './index.css' 2 | // 可注释 3 | // import React from "react"; 4 | // import axios from 'axios'; 5 | // import * as echarts from 'echarts/core'; 6 | // import { 7 | // TitleComponent, 8 | // TooltipComponent, 9 | // LegendComponent 10 | // } from 'echarts/components'; 11 | // import {PieChart} from 'echarts/charts'; 12 | // import {LabelLayout} from 'echarts/features'; 13 | // import {CanvasRenderer} from 'echarts/renderers'; 14 | // 15 | // echarts.use([ 16 | // TitleComponent, 17 | // TooltipComponent, 18 | // LegendComponent, 19 | // PieChart, 20 | // CanvasRenderer, 21 | // LabelLayout 22 | // ]); 23 | 24 | // 可注释 end 25 | function dateFormat(fmt, date) { 26 | let ret; 27 | const opt = { 28 | "Y+": date.getFullYear().toString(), // 年 29 | "m+": (date.getMonth() + 1).toString(), // 月 30 | "d+": date.getDate().toString(), // 日 31 | "H+": date.getHours().toString(), // 时 32 | "M+": date.getMinutes().toString(), // 分 33 | "S+": date.getSeconds().toString(), // 秒 34 | // 有其他格式化字符需求可以继续添加,必须转化成字符串 35 | }; 36 | for (let k in opt) { 37 | ret = new RegExp("(" + k + ")").exec(fmt); 38 | if (ret) { 39 | fmt = fmt.replace( 40 | ret[1], 41 | ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, "0") 42 | ); 43 | } 44 | } 45 | return fmt; 46 | } 47 | 48 | const transformEchartsData = (item, color) => { 49 | const { 50 | name, 51 | firstTime, 52 | lastTime, 53 | threeTime, 54 | fourTime, 55 | fiveTime, 56 | sixTime, 57 | } = item; 58 | return { 59 | title: { 60 | top: "0%", 61 | text: name, 62 | subtext: `${dateFormat( 63 | "YYYY-mm-dd HH:MM:SS", 64 | new Date(firstTime * 1000) 65 | )} - ${dateFormat( 66 | "YYYY-mm-dd HH:MM:SS", 67 | new Date(lastTime * 1000) 68 | )}`, 69 | textStyle: { 70 | color: color.black 71 | }, 72 | subtextStyle: { 73 | color: color.tip 74 | }, 75 | left: "center", 76 | }, 77 | tooltip: { 78 | trigger: "item", 79 | }, 80 | itemStyle: { 81 | borderColor: color.white, 82 | borderWidth: 1 83 | }, 84 | legend: { 85 | top: "14%", 86 | left: "center", 87 | textStyle: { 88 | color: color.tip 89 | } 90 | }, 91 | label: { 92 | alignTo: 'edge', 93 | formatter: "{b}\n{c}个\n{d}%", 94 | minMargin: 5, 95 | edgeDistance: 10, 96 | lineHeight: 15, 97 | color: color.black 98 | }, 99 | labelLine: { 100 | length: 15, 101 | length2: 0, 102 | maxSurfaceAngle: 80 103 | }, 104 | series: [ 105 | { 106 | type: "pie", 107 | legendHoverLink: false, 108 | radius: ["15%", "45%"], 109 | center: ['50%', '60%'], 110 | data: [ 111 | { 112 | value: sixTime || '--', 113 | name: "6星干员", 114 | itemStyle: {color: color['color6']}, 115 | }, 116 | { 117 | value: fiveTime || '--', 118 | name: "5星干员", 119 | itemStyle: {color: color['color5']}, 120 | }, 121 | { 122 | value: fourTime || '--', 123 | name: "4星干员", 124 | itemStyle: {color: color['color4']}, 125 | }, 126 | { 127 | value: threeTime || '--', 128 | name: "3星干员", 129 | itemStyle: {color: color['color3']}, 130 | }, 131 | ], 132 | emphasis: { 133 | disabled: true 134 | }, 135 | }, 136 | ], 137 | }; 138 | } 139 | const ListItem = ({data, color}) => { 140 | const {ts, pool, times, name, isNew} = data; 141 | return <> 142 | 143 | 144 | [{times}] 146 | {name}{isNew ? NEW : ''} 147 | 148 | ({pool}) 149 | 150 | 151 |
152 | 153 | } 154 | const GridItem = ({item, color}) => { 155 | const ref = React.useRef(null); 156 | const echartRef = React.useRef(null); 157 | const {total, sixTag, fiveTag, avgSix, avgFive, name, sixItem, fiveItem} = item; 158 | 159 | React.useEffect(() => { 160 | if (ref.current) { 161 | echartRef.current = echarts.init(ref.current); 162 | echartRef.current?.setOption(transformEchartsData(item, color)); 163 | echartRef.current?.resize() 164 | return () => { 165 | echartRef.current?.clear(); 166 | }; 167 | } 168 | }, []) 169 | React.useEffect(() => { 170 | echartRef.current?.setOption(transformEchartsData(item, color)); 171 | echartRef.current?.resize() 172 | }, [color]) 173 | return
174 |
175 |
184 |
185 |
186 |
一共 {total} 抽,已累计 {sixTag} 抽未出6星 188 |
189 |
平均出货次数:
190 |
191 |
192 | 6星:{avgSix} 193 |
194 |
195 | 5星:{avgFive} 196 |
197 |
198 | 199 |
200 | {sixItem.map((item, i) => )} 201 |
202 |
203 | 204 |
205 | {fiveItem.map((item, i) => )} 206 |
207 |
208 |
209 |
210 | } 211 | const DataGrid = ({res, color}) => { 212 | const {data, uid, nickName} = res; 213 | return
214 |
215 |
UID: {uid}
216 |
{nickName}
217 |
218 |
219 | {data.map((item, i) => )} 220 |
221 |
window.open('https://github.com/lie5860/hypergryph-gacha')}> 222 | 226 | 本站由FC与WebComponent驱动 227 |
228 |
229 | } 230 | 231 | export default function Home() { 232 | const [token, setToken] = React.useState('') 233 | const [res, setRes] = React.useState(null) 234 | const [loading, setLoading] = React.useState(false) 235 | const [darkMode, setDarkMode] = React.useState(false) 236 | const [color, setColor] = React.useState({}) 237 | const ref = React.useRef() 238 | React.useEffect(() => { 239 | // 绑定媒体查询变更时间 240 | window.matchMedia("(prefers-color-scheme: dark)").addEventListener('change', sql => { 241 | setDarkMode(sql.matches) 242 | }); 243 | //初始化业务数据 244 | const token = localStorage.getItem('token'); 245 | token && setToken(token) 246 | const uid = localStorage.getItem("lastUid"); 247 | uid && setRes(JSON.parse(localStorage.getItem("dealData" + uid) || "{}")) 248 | ref.current.addEventListener('sl-input', (e) => { 249 | setToken(e.target.value) 250 | }); 251 | }, []) 252 | React.useEffect(() => { 253 | // 初始化颜色 254 | const obj = {} 255 | const dict = { 256 | '--three-color': 'color3', 257 | '--four-color': 'color4', 258 | '--five-color': 'color5', 259 | '--six-color': 'color6', 260 | '--tip': 'tip', 261 | '--black': 'black', 262 | '--white': 'white', 263 | } 264 | const style = getComputedStyle(document.documentElement); 265 | Object.keys(dict).forEach(k => { 266 | obj[dict[k]] = style.getPropertyValue(k)?.trim() 267 | }) 268 | setColor(obj) 269 | }, [darkMode]) 270 | const clear = () => { 271 | localStorage.setItem("lastUid", ""); 272 | setRes(null) 273 | } 274 | const init = (e) => { 275 | e.preventDefault(); 276 | localStorage.setItem('token', token) 277 | let dealValue = token; 278 | try { 279 | dealValue = /"content":"(.*?)"/.exec(dealValue)[1] 280 | // dealValue = JSON.parse(token).data.token; 281 | } catch (e) { 282 | } 283 | setLoading(true) 284 | const url = `https://1683720436570405.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/hypergryph.LATEST/hypergryph_test/?token=${encodeURIComponent( 285 | dealValue 286 | )}`; 287 | axios 288 | .get(url, {responseType: "json"}) 289 | .then(function (response) { 290 | const {uid, msg, data, nickName} = response.data; 291 | if (msg) { 292 | alert(msg); 293 | clear(); 294 | } else { 295 | localStorage.setItem("lastUid", uid); 296 | localStorage.setItem( 297 | "dealData" + uid, 298 | JSON.stringify({data, uid, nickName}) 299 | ); 300 | setRes(response.data) 301 | } 302 | }) 303 | .catch(function (error) { 304 | if (error.message === 'Network Error') { 305 | alert('请连接网络后重试。') 306 | } else { 307 | clear(); 308 | } 309 | }).finally(() => { 310 | setLoading(false) 311 | }); 312 | return true 313 | } 314 | return ( 315 |
316 | 317 | 请首先在 官网 登录,随后访问 此处 复制全部内容(如了解JSON也可仅复制data中的token),然后在此填入。(请使用同一浏览器 319 | 320 |
321 |
322 |
323 | setToken(e.target.value)} 331 | /> 332 |
333 | 生成 334 |
335 | {loading && <> 336 |
337 |
338 | 339 |
340 | } 341 | {!loading && res && } 342 |
343 | ) 344 | } 345 | --------------------------------------------------------------------------------