feat(uigf): support UIGFv4.0(Beta)

Users don't have to delete their data. New data structure is used automatically when new data is fetched

- Set `count` to `"1"` as default for old data
- Record `count` from API
- Link to the UIGF website

BREAKING CHANGE: SRGF is no longer supported, use UIGFv4.0(Beta) instead
This commit is contained in:
Zichao Lin 2024-07-23 11:10:27 +08:00
parent f1e3b76d85
commit 0e4f3599c9
Signed by: earthjasonlin
GPG Key ID: 406D9913DE2E42FB
9 changed files with 43 additions and 30 deletions

@ -5,7 +5,7 @@
"ui.button.directUpdate": "Direct update", "ui.button.directUpdate": "Direct update",
"ui.button.files": "Export Files", "ui.button.files": "Export Files",
"ui.button.excel": "Export Excel", "ui.button.excel": "Export Excel",
"ui.button.srgf": "Export JSON", "ui.button.uigf": "Export UIGF (Beta)",
"ui.button.url": "Input URL", "ui.button.url": "Input URL",
"ui.button.setting": "Settings", "ui.button.setting": "Settings",
"ui.button.option": "Option", "ui.button.option": "Option",
@ -99,7 +99,7 @@
"excel.customFont": "Arial", "excel.customFont": "Arial",
"excel.filePrefix": "Zenless Zone Zero Signal Search Log", "excel.filePrefix": "Zenless Zone Zero Signal Search Log",
"excel.fileType": "Excel file", "excel.fileType": "Excel file",
"srgf.fileType": "Zenless Zone Zero Gacha Log Format file (SRGF)", "uigf.fileType": "Uniformed Interchangeable GachaLog Format v4.0 (Beta)",
"ui.extra.cacheClean": "1. Confirm whether the search history in the game has been opened, and if the error \"User authentication expired\" still appears, try the following steps \n2. Close the game window of Zenless Zone Zero \n3. Click the \"Open Web Cache Folder\" button above to open the \"Cache\" folder \n4. Delete the \"Cache_Data\" folder \n5. Start the Zenless Zone Zero game and open the search history page in the game \n6. Close this dialog and click the \"Update Data\" button", "ui.extra.cacheClean": "1. Confirm whether the search history in the game has been opened, and if the error \"User authentication expired\" still appears, try the following steps \n2. Close the game window of Zenless Zone Zero \n3. Click the \"Open Web Cache Folder\" button above to open the \"Cache\" folder \n4. Delete the \"Cache_Data\" folder \n5. Start the Zenless Zone Zero game and open the search history page in the game \n6. Close this dialog and click the \"Update Data\" button",
"ui.extra.findCacheFolder": "If the \"Open cache folder\" button does not respond, you can manually find the game's web cache folder. The directory is \"Your game installation path/ZenlessZoneZero_Data/webCaches/Cache/\"", "ui.extra.findCacheFolder": "If the \"Open cache folder\" button does not respond, you can manually find the game's web cache folder. The directory is \"Your game installation path/ZenlessZoneZero_Data/webCaches/Cache/\"",
"ui.extra.urlCopied": "URL Copied" "ui.extra.urlCopied": "URL Copied"

@ -5,7 +5,7 @@
"ui.button.directUpdate": "直接更新", "ui.button.directUpdate": "直接更新",
"ui.button.files": "导出文件", "ui.button.files": "导出文件",
"ui.button.excel": "导出Excel", "ui.button.excel": "导出Excel",
"ui.button.srgf":"导出JSON", "ui.button.uigf":"导出UIGF (Beta)",
"ui.button.url": "输入URL", "ui.button.url": "输入URL",
"ui.button.setting": "设置", "ui.button.setting": "设置",
"ui.button.option": "选项", "ui.button.option": "选项",
@ -98,7 +98,7 @@
"excel.customFont": "微软雅黑", "excel.customFont": "微软雅黑",
"excel.filePrefix": "绝区零调频记录", "excel.filePrefix": "绝区零调频记录",
"excel.fileType": "Excel文件", "excel.fileType": "Excel文件",
"srgf.fileType":"绝区零调频记录格式文件SRGF", "uigf.fileType":"统一可交换抽卡记录标准 v4.0Beta",
"ui.extra.cacheClean": "1. 确认是否已经打开游戏内的抽卡历史记录,如果仍然出现“身份认证已过期”的错误,再尝试下面的步骤\n2. 关闭绝区零的游戏窗口\n3. 点击上方的“打开缓存文件夹”按钮打开Cache文件夹\n4. 删除Cache_Data文件夹\n5. 启动绝区零游戏,打开游戏内抽卡历史记录页面\n6. 关闭这个对话框,再点击“更新数据”按钮", "ui.extra.cacheClean": "1. 确认是否已经打开游戏内的抽卡历史记录,如果仍然出现“身份认证已过期”的错误,再尝试下面的步骤\n2. 关闭绝区零的游戏窗口\n3. 点击上方的“打开缓存文件夹”按钮打开Cache文件夹\n4. 删除Cache_Data文件夹\n5. 启动绝区零游戏,打开游戏内抽卡历史记录页面\n6. 关闭这个对话框,再点击“更新数据”按钮",
"ui.extra.findCacheFolder": "如果点“打开缓存文件夹”按钮没有反应,可以手动找到游戏的网页缓存文件夹,目录为“你的游戏安装路径/ZenlessZoneZero_Data/webCaches/Cache/”", "ui.extra.findCacheFolder": "如果点“打开缓存文件夹”按钮没有反应,可以手动找到游戏的网页缓存文件夹,目录为“你的游戏安装路径/ZenlessZoneZero_Data/webCaches/Cache/”",
"ui.extra.urlCopied": "URL已复制" "ui.extra.urlCopied": "URL已复制"

@ -5,7 +5,7 @@
"ui.button.directUpdate": "直接更新", "ui.button.directUpdate": "直接更新",
"ui.button.files": "導出文件", "ui.button.files": "導出文件",
"ui.button.excel": "導出Excel", "ui.button.excel": "導出Excel",
"ui.button.srgf":"導出JSON", "ui.button.uigf":"導出UIGF (Beta)",
"ui.button.url": "輸入URL", "ui.button.url": "輸入URL",
"ui.button.setting": "設置", "ui.button.setting": "設置",
"ui.button.option": "選項", "ui.button.option": "選項",
@ -97,7 +97,7 @@
"excel.customFont": "微軟雅黑", "excel.customFont": "微軟雅黑",
"excel.filePrefix": "絕區零調頻記錄", "excel.filePrefix": "絕區零調頻記錄",
"excel.fileType": "Excel文件", "excel.fileType": "Excel文件",
"srgf.fileType":"絕區零調頻記錄格式文件SRGF", "uigf.fileType":"統一可交換抽卡記錄標準 v4.0Beta",
"ui.extra.cacheClean": "1. 確認是否已經打開遊戲內的抽卡歷史記錄,如果仍然出現「身份認證已過期」的錯誤,再嘗試下面的步驟\n2. 關閉絕區零的遊戲窗口\n3. 點擊上方的「打開緩存文件夾」按鈕打開Cache文件夾\n4. 刪除Cache_Data文件夾\n5. 啟動絕區零遊戲,打開遊戲內抽卡歷史記錄頁面\n6. 關閉這個對話框,再點擊「更新數據」按鈕", "ui.extra.cacheClean": "1. 確認是否已經打開遊戲內的抽卡歷史記錄,如果仍然出現「身份認證已過期」的錯誤,再嘗試下面的步驟\n2. 關閉絕區零的遊戲窗口\n3. 點擊上方的「打開緩存文件夾」按鈕打開Cache文件夾\n4. 刪除Cache_Data文件夾\n5. 啟動絕區零遊戲,打開遊戲內抽卡歷史記錄頁面\n6. 關閉這個對話框,再點擊「更新數據」按鈕",
"ui.extra.findCacheFolder": "如果點「打開緩存文件夾」按鈕沒有反應,可以手動找到遊戲的網頁緩存文件夾,目錄為「你的遊戲安裝路徑/ZenlessZoneZero_Data/webCaches/Cache/」", "ui.extra.findCacheFolder": "如果點「打開緩存文件夾」按鈕沒有反應,可以手動找到遊戲的網頁緩存文件夾,目錄為「你的遊戲安裝路徑/ZenlessZoneZero_Data/webCaches/Cache/」",
"ui.extra.urlCopied": "URL已復製" "ui.extra.urlCopied": "URL已復製"

@ -2,8 +2,9 @@ const { app, ipcMain, dialog } = require('electron')
const fs = require('fs-extra') const fs = require('fs-extra')
const path = require('path') const path = require('path')
const getData = require('./getData').getData const getData = require('./getData').getData
const { version } = require('../../package.json') const { name, version } = require('../../package.json')
const i18n = require('./i18n') const i18n = require('./i18n')
const { exit } = require('process')
const getTimeString = () => { const getTimeString = () => {
return new Date().toLocaleString('sv').replace(/[- :]/g, '').slice(0, -2) return new Date().toLocaleString('sv').replace(/[- :]/g, '').slice(0, -2)
@ -24,17 +25,20 @@ const start = async () => {
} }
const result = { const result = {
info: { info: {
uid: data.uid,
lang: data.lang,
export_time: formatDate(new Date()),
export_timestamp: Math.ceil(Date.now() / 1000), export_timestamp: Math.ceil(Date.now() / 1000),
export_app: 'zzz-signal-search-export', export_app: `${name}`,
export_app_version: `v${version}`, export_app_version: `v${version}`,
region_time_zone: data.region_time_zone, version: "v4.0"
srgf_version: 'v1.0'
}, },
nap: [
{
uid: current,
timezone: data.region_time_zone,
lang: data.lang,
list: [] list: []
} }
]
}
const listTemp = [] const listTemp = []
for (let [type, arr] of data.result) { for (let [type, arr] of data.result) {
arr.forEach(log => { arr.forEach(log => {
@ -42,7 +46,7 @@ const start = async () => {
gacha_id: log.gacha_id, gacha_id: log.gacha_id,
gacha_type: log.gacha_type, gacha_type: log.gacha_type,
item_id: log.item_id, item_id: log.item_id,
count: '1', count: log.count,
time: log.time, time: log.time,
name: log.name, name: log.name,
item_type: log.item_type, item_type: log.item_type,
@ -53,14 +57,14 @@ const start = async () => {
} }
listTemp.sort((a, b) => Number(BigInt(a.id) - BigInt(b.id))) listTemp.sort((a, b) => Number(BigInt(a.id) - BigInt(b.id)))
listTemp.forEach(item => { listTemp.forEach(item => {
result.list.push({ result.nap[0].list.push({
...item ...item
}) })
}) })
const filePath = dialog.showSaveDialogSync({ const filePath = dialog.showSaveDialogSync({
defaultPath: path.join(app.getPath('downloads'), `SRGF_${data.uid}_${getTimeString()}`), defaultPath: path.join(app.getPath('downloads'), `UIGF_${data.uid}_${getTimeString()}`),
filters: [ filters: [
{ name: i18n.srgf.fileType, extensions: ['json'] } { name: i18n.uigf.fileType, extensions: ['json'] }
] ]
}) })
if (filePath) { if (filePath) {
@ -69,6 +73,6 @@ const start = async () => {
} }
} }
ipcMain.handle('EXPORT_SRGF_JSON', async () => { ipcMain.handle('EXPORT_UIGF_JSON', async () => {
await start() await start()
}) })

@ -58,6 +58,13 @@ const readData = async () => {
const data = await readJSON(dataPath, name) const data = await readJSON(dataPath, name)
data.typeMap = new Map(data.typeMap) || defaultTypeMap data.typeMap = new Map(data.typeMap) || defaultTypeMap
data.result = new Map(data.result) data.result = new Map(data.result)
data.result.forEach((value, key) => {
value.forEach(item => {
if (!('count' in item)) {
item.count = "1";
}
});
});
if (data.uid) { if (data.uid) {
dataMap.set(data.uid, data) dataMap.set(data.uid, data)
} }
@ -423,8 +430,8 @@ const fetchData = async (urlOverride) => {
for (const type of gachaType) { for (const type of gachaType) {
const { list, uid, region, region_time_zone } = await getGachaLogs(type, queryString) const { list, uid, region, region_time_zone } = await getGachaLogs(type, queryString)
const logs = list.map((item) => { const logs = list.map((item) => {
const { id, item_id, item_type, name, rank_type, time, gacha_id, gacha_type } = item const { id, item_id, item_type, name, rank_type, time, gacha_id, gacha_type, count} = item
return { id, item_id, item_type, name, rank_type, time, gacha_id, gacha_type } return { id, item_id, item_type, name, rank_type, time, gacha_id, gacha_type, count }
}) })
logs.reverse() logs.reverse()
typeMap.set(type.key, type.name) typeMap.set(type.key, type.name)

@ -66,7 +66,7 @@ const parseText = (text, data) => {
} }
const mainProps = [ const mainProps = [
'symbol', 'ui', 'log', 'excel',"srgf" 'symbol', 'ui', 'log', 'excel',"uigf"
] ]
const i18n = new Proxy(raw, { const i18n = new Proxy(raw, {

@ -4,7 +4,7 @@ const { disableProxy, proxyStatus } = require('./module/system-proxy')
require('./getData') require('./getData')
require('./bridge') require('./bridge')
require('./excel') require('./excel')
require('./SRGFJson') require('./UIGFJson')
const { getUpdateInfo } = require('./update/index') const { getUpdateInfo } = require('./update/index')
const isDev = !app.isPackaged const isDev = !app.isPackaged

@ -11,7 +11,7 @@
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item command="excel">{{ui.button.excel}}</el-dropdown-item> <el-dropdown-item command="excel">{{ui.button.excel}}</el-dropdown-item>
<el-dropdown-item command="srgf-json">{{ui.button.srgf}}</el-dropdown-item> <el-dropdown-item command="uigf-json">{{ui.button.uigf}}</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
</el-dropdown> </el-dropdown>
@ -238,15 +238,15 @@ const saveExcel = async () => {
await ipcRenderer.invoke('SAVE_EXCEL') await ipcRenderer.invoke('SAVE_EXCEL')
} }
const exportSRGFJSON = () => { const exportUIGFJSON = () => {
ipcRenderer.invoke('EXPORT_SRGF_JSON') ipcRenderer.invoke('EXPORT_UIGF_JSON')
} }
const exportCommand = (type) => { const exportCommand = (type) => {
if (type === 'excel') { if (type === 'excel') {
saveExcel() saveExcel()
} else if (type === 'srgf-json') { } else if (type === 'uigf-json') {
exportSRGFJSON() exportUIGFJSON()
} }
} }

@ -48,7 +48,8 @@
</el-form> </el-form>
<h3 class="text-lg my-4">{{about.title}}</h3> <h3 class="text-lg my-4">{{about.title}}</h3>
<p class="text-gray-600 text-xs mt-1">{{about.license}}</p> <p class="text-gray-600 text-xs mt-1">{{about.license}}</p>
<p class="text-gray-600 text-xs mt-1 pb-6">Github: <a @click="openGithub" class="cursor-pointer text-blue-400">https://github.com/earthjasonlin/zzz-signal-search-export</a></p> <p class="text-gray-600 text-xs mt-1">GitHub: <a @click="openGithub" class="cursor-pointer text-blue-400">https://github.com/earthjasonlin/zzz-signal-search-export</a></p>
<p class="text-gray-600 text-xs mt-1 pb-6">UIGF: <a @click="openUIGF" class="cursor-pointer text-blue-400">https://uigf.org/</a></p>
<el-dialog v-model="state.showDataDialog" :title="common.dataManage" width="90%"> <el-dialog v-model="state.showDataDialog" :title="common.dataManage" width="90%">
<div class=""> <div class="">
<el-table :data="gachaDataInfo" border stripe> <el-table :data="gachaDataInfo" border stripe>
@ -130,6 +131,7 @@ const disableProxy = async () => {
} }
const openGithub = () => shell.openExternal('https://github.com/earthjasonlin/zzz-signal-search-export') const openGithub = () => shell.openExternal('https://github.com/earthjasonlin/zzz-signal-search-export')
const openUIGF = () => shell.openExternal('https://uigf.org/')
const openLink = (link) => shell.openExternal(link) const openLink = (link) => shell.openExternal(link)
const deleteData = async (uid, action) => { const deleteData = async (uid, action) => {