Skip to content
This repository has been archived by the owner on Aug 11, 2024. It is now read-only.

Commit

Permalink
feat: pull gacha data on demand
Browse files Browse the repository at this point in the history
  • Loading branch information
Tsuk1ko committed Feb 5, 2022
1 parent 91a7765 commit cbc8ec9
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 247 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

## TODO

- [ ] 按需拉取寻访数据
- [x] 按需拉取寻访数据
- [ ] 自动定时更新寻访数据

## Devlopment
Expand Down
12 changes: 2 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "arknights-gacha-export",
"version": "0.0.1",
"version": "0.0.2",
"main": "./dist/electron/main/main.js",
"author": "神代绮凛 <https://github.com/Tsuk1ko>",
"license": "MIT",
Expand Down Expand Up @@ -103,7 +103,6 @@
"lodash-es": "^4.17.21",
"moment": "^2.29.1",
"multispinner": "^0.2.1",
"ora": "^5.4.1",
"portfinder": "^1.0.28",
"postcss": "^8.4.6",
"prettier": "^2.5.1",
Expand All @@ -112,13 +111,6 @@
"tailwindcss": "^3.0.18",
"vite": "2.7.13",
"vue": "^3.2.29",
"winreg": "^1.2.4",
"yauzl": "^2.10.0"
},
"keywords": [
"vite",
"electron",
"vue3",
"rollup"
]
}
}
24 changes: 14 additions & 10 deletions src/main/getData.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,25 +92,25 @@ const getGachaLog = async ({ page, url, retryCount }) => {
}
}

const getGachaLogs = async (token) => {
const getGachaLogs = async (token, localLatestTs) => {
const text = i18n.log
let page = 1
const list = []
let res = {}
let page = 1
let data
const url = `${apiDomain}/user/api/inquiry/gacha?token=${encodeURIComponent(token)}`
do {
if (page % 10 === 0) {
sendMsg(i18n.parse(text.fetch.interval, { page }))
await sleep(1)
}
sendMsg(i18n.parse(text.fetch.current, { page }))
res = await getGachaLog({ page, url, retryCount: 5 })
if (!res) break
list.push(...res.list)
if (list.length >= res.pagination.total) break
data = await getGachaLog({ page, url, retryCount: 5 })
list.push(...data.list)
const oldestTs = _.last(data.list)?.ts
if (oldestTs < localLatestTs || list.length >= data.pagination.total) break
page += 1
await sleep(0.3)
} while (res.list.length > 0)
} while (data.list.length > 0)
return list
}

Expand All @@ -120,6 +120,9 @@ const checkGachaResStatus = (res) => {
sendMsg(message)
throw new Error(message)
}
if (!res.data) {
throw new Error('no data')
}
return res
}

Expand Down Expand Up @@ -167,10 +170,11 @@ const fetchData = async (token) => {
// 获取用户信息
const { uid, nickName } = await tryGetUserInfo(token)
// 获取寻访记录
const result = await getGachaLogs(token)
const localData = dataMap.get(uid)
const localLatestTs = localData?.result?.length ? _.last(localData.result).ts : 0
const result = await getGachaLogs(token, localLatestTs)
result.reverse()
const data = { result, time: Date.now(), uid, nickName }
const localData = dataMap.get(uid)
if (!nickName) data.nickName = localData.nickName
data.result = mergeData(localData, data)
dataMap.set(uid, data)
Expand Down
146 changes: 58 additions & 88 deletions src/renderer/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"
class="w-44"
@change="changeCurrent"
v-model="uidSelectText"
:model-value="uidSelectText"
>
<el-option v-for="[uid, { nickName }] of state.dataMap" :key="uid" :label="nickName" :value="uid"></el-option>
</el-select>
Expand All @@ -66,6 +66,7 @@
<Setting
v-show="state.showSetting"
:i18n="state.i18n"
:has-data="!!gachaData"
@changeLang="getI18nData()"
@close="showSetting(false)"
></Setting>
Expand Down Expand Up @@ -100,14 +101,15 @@
</template>

<script setup>
const { ipcRenderer } = require('electron')
import { reactive, computed, onMounted, toRaw } from 'vue'
import PieChart from './components/PieChart.vue'
import GachaDetail from './components/GachaDetail.vue'
import Setting from './components/Setting.vue'
import Link from './components/Link.vue'
import gachaDetail from './gachaDetail'
import { version } from '../../package.json'
import { componentSafeIpcRenderOn } from './utils'
const { ipcRenderer } = require('electron')
const state = reactive({
status: 'init',
Expand All @@ -122,65 +124,44 @@ const state = reactive({
config: {}
})
const ui = computed(() => {
if (state.i18n) {
return state.i18n.ui
}
})
const ui = computed(() => state.i18n?.ui)
const gachaData = computed(() => {
return state.dataMap.get(state.current)
})
const gachaData = computed(() => state.dataMap.get(state.current))
const uidSelectText = computed(() => {
if (state.current === 0) {
return state.i18n.ui.select.newAccount
} else {
return state.current
}
})
const uidSelectText = computed(() => (state.current === 0 ? state.i18n.ui.select.newAccount : state.current))
const allowClick = () => {
const data = state.dataMap.get(state.current)
const data = gachaData.value
if (!data) return true
if (Date.now() - data.time < 1000 * 60) {
return false
}
return true
return Date.now() - data.time >= 1000 * 60
}
const hint = computed(() => {
const data = state.dataMap.get(state.current)
if (!state.i18n) {
return 'Loading...'
}
if (!state.i18n) return 'Loading...'
const { hint } = state.i18n.ui
const { colon } = state.i18n.symbol
if (state.status === 'init') {
return hint.init
} else if (state.status === 'loaded') {
return `${hint.lastUpdate}${colon}${new Date(data.time).toLocaleString()}`
} else if (state.status === 'loading') {
return state.log || 'Loading...'
} else if (state.status === 'updated') {
return state.log
} else if (state.status === 'failed') {
return state.log + ` - ${hint.failed}`
switch (state.status) {
case 'init':
return hint.init
case 'loading':
return state.log || 'Loading...'
case 'updated':
return state.log
case 'failed':
return state.log + ` - ${hint.failed}`
case 'loaded':
return `${hint.lastUpdate}${colon}${new Date(gachaData.value?.time).toLocaleString()}`
default:
return '\u00a0'
}
return ' '
})
const detail = computed(() => {
const data = state.dataMap.get(state.current)
if (data) {
return gachaDetail(toRaw(data.result))
}
const data = gachaData.value
if (data) return gachaDetail(toRaw(data.result))
})
const typeMap = computed(() => {
const data = state.dataMap.get(state.current)
return data.typeMap
})
const typeMap = computed(() => gachaData.value?.typeMap)
const fetchData = async (token) => {
state.status = 'loading'
Expand All @@ -199,9 +180,7 @@ const readData = async () => {
if (data) {
state.dataMap = data.dataMap
state.current = data.current
if (data.dataMap.get(data.current)) {
state.status = 'loaded'
}
if (gachaData.value) state.status = 'loaded'
}
}
Expand All @@ -218,22 +197,14 @@ const saveExcel = async () => {
}
const changeCurrent = async (uid) => {
if (uid === 0) {
state.status = 'init'
} else {
state.status = 'loaded'
}
state.status = uid === 0 ? 'init' : 'loaded'
state.current = uid
await ipcRenderer.invoke('CHANGE_UID', uid)
}
const newUser = async () => {
await changeCurrent(0)
}
const newUser = () => changeCurrent(0)
const relaunch = async () => {
await ipcRenderer.invoke('RELAUNCH')
}
const relaunch = () => ipcRenderer.invoke('RELAUNCH')
const showSetting = (show) => {
if (show) {
Expand All @@ -244,17 +215,6 @@ const showSetting = (show) => {
}
}
const optionCommand = (type) => {
if (type === 'setting') {
showSetting(true)
} else if (type === 'url') {
state.urlInput = ''
state.showUrlDlg = true
} else if (type === 'proxy') {
fetchData('proxy')
}
}
const setTitle = () => {
document.title = `${state.i18n.ui.win.title} - v${version}`
}
Expand All @@ -263,27 +223,37 @@ const updateConfig = async () => {
state.config = await ipcRenderer.invoke('GET_CONFIG')
}
componentSafeIpcRenderOn([
[
'LOAD_DATA_STATUS',
(event, message) => {
state.log = message
}
],
[
'ERROR',
(event, err) => {
console.error(err)
}
],
[
'UPDATE_HINT',
(event, message) => {
state.log = message
state.status = 'updated'
}
],
[
'TOKEN_NOT_SET',
() => {
state.showUrlDlg = true
}
]
])
onMounted(async () => {
await readData()
await getI18nData()
ipcRenderer.on('LOAD_DATA_STATUS', (event, message) => {
state.log = message
})
ipcRenderer.on('ERROR', (event, err) => {
console.error(err)
})
ipcRenderer.on('UPDATE_HINT', (event, message) => {
state.log = message
state.status = 'updated'
})
ipcRenderer.on('TOKEN_NOT_SET', () => {
state.showUrlDlg = true
})
await updateConfig()
})
</script>
Expand Down
1 change: 1 addition & 0 deletions src/renderer/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Security-Policy" content="script-src 'self'" />
<title></title>
</head>
<body>
Expand Down
34 changes: 18 additions & 16 deletions src/renderer/utils.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import * as IconComponents from "@element-plus/icons-vue";
const weaponTypeNames = new Set([
'武器', 'Weapon', '무기', 'Arma', 'Arme', 'Оружие', 'อาวุธ', 'Vũ Khí', 'Waffe', 'Senjata'
])
import { onBeforeUnmount } from 'vue'
import * as IconComponents from '@element-plus/icons-vue'
const { ipcRenderer } = require('electron')

const characterTypeNames = new Set([
'角色', 'Character', '캐릭터', 'キャラクター', 'Personaje', 'Personnage', 'Персонажи', 'ตัวละคร', 'Nhân Vật', 'Figur', 'Karakter', 'Personagem'
])

const isCharacter = (name) => characterTypeNames.has(name)
const isWeapon = (name) => weaponTypeNames.has(name)

const IconInstaller = (app) => {
Object.values(IconComponents).forEach(component => {
export const IconInstaller = (app) => {
Object.values(IconComponents).forEach((component) => {
app.component(component.name, component)
})
}

export {
isWeapon, isCharacter, IconInstaller
}
/**
* @param {Array<Parameters<import('electron')['ipcRenderer']['on']>>} params
*/
export const componentSafeIpcRenderOn = (params) => {
params.forEach((args) => {
ipcRenderer.on(...args)
})
onBeforeUnmount(() => {
params.forEach((args) => {
ipcRenderer.off(...args)
})
})
}
Loading

0 comments on commit cbc8ec9

Please sign in to comment.