feat: 新增皮肤站原生登录与验证码弹窗
Sync source to CNB / Sync Git ref (push) Skipped

登录入口原先会切到主页并打开内嵌网页。改为弹出启动器自己的登录弹窗:

- SkinSiteLoginModal:账号密码校验规则与皮肤站一致,登录前走验证码,
  成功后保存 JWT 并刷新会话。
- SkinSiteCaptchaModal:拉取旋转图片验证码,用滑块调整角度后提交。
- AccountsCard 的登录按钮改为打开该弹窗,登录成功后重新拉取玩家列表。
- 修正 verifyCaptcha 的参数:服务端校验的是旋转角度 degree,不是文字答案。
This commit is contained in:
AxTps committed 2026-10-17 18:42:34 +08:00
1 parent 0edf96fc2c
commit 00f0f111d8
4 files changed
+312 -13

No files matched your search

@@ -244,6 +244,7 @@
</div>
</Accordion>
<MinecraftLoginModal ref="minecraftLoginModal" @complete="onMicrosoftLogin" />
<SkinSiteLoginModal ref="skinSiteLoginModal" @signed-in="onSkinSiteSignedIn" />
</template>
<script setup lang="ts">
@@ -269,12 +270,12 @@ import { useQueryClient } from '@tanstack/vue-query'
import { listen } from '@tauri-apps/api/event'
import type { Ref } from 'vue'
import { computed, nextTick, onUnmounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useRoute } from 'vue-router'
import axolotlLogo from '@/assets/netherstar.png'
import MinecraftLoginModal from '@/components/ui/MinecraftLoginModal.vue'
import SkinSiteLoginModal from '@/components/ui/skin-site/SkinSiteLoginModal.vue'
import {
openSkinSiteLogin,
requestSkinSitePlayers,
selectedSkinSitePlayerId,
selectSkinSitePlayer,
@@ -298,21 +299,20 @@ import { getPlayerHeadUrl } from '@/helpers/rendering/batch-skin-renderer.ts'
import type { Skin } from '@/helpers/skins'
import { get_available_skins } from '@/helpers/skins'
import { handleSevereError } from '@/store/error.js'
import { useTheming } from '@/store/state'
const { formatMessage } = useVIntl()
const { handleError } = injectNotificationManager()
const { browserOffline, offline, refreshBrowserOffline } = useNetworkStatus()
const queryClient = useQueryClient()
const route = useRoute()
const router = useRouter()
const themeStore = useTheming()
const skinSiteLoginModal = ref<InstanceType<typeof SkinSiteLoginModal>>()
async function goToSkinSiteLogin() {
openSkinSiteLogin()
// The login action must reveal the iframe even if Minimal Home was selected.
themeStore.homeLayout = 'standard'
await router.push('/').catch(handleError)
skinSiteLoginModal.value?.show()
}
function onSkinSiteSignedIn() {
void requestSkinSitePlayers().catch(() => {})
}
const refreshingNetwork = ref(false)