chore(frontend): introduce prettier + eslint and prune unused code
- Add Prettier 3 with prettier-plugin-organize-imports (sorts/removes unused imports) - Add ESLint 10 flat config with typescript-eslint + eslint-plugin-vue + eslint-config-prettier - Add root scripts: format, format:check, lint, lint:fix - Reformat 257 files across admin-web, ops-web, desktop-client, packages - Remove unused locals/exports flagged by --noUnusedLocals/--noUnusedParameters - Fix duplicate localTabLabel key, surrogate-pair regex u-flag, NBSP literal in regex - Skip server/ (Go) and apps/browser-extension/ (deprecated per ADR) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,81 +1,81 @@
|
||||
<script setup lang="ts">
|
||||
import { onBeforeUnmount, onMounted, reactive, ref } from "vue";
|
||||
import { DEFAULT_API_BASE_URL, useDesktopSession } from "../composables/useDesktopSession";
|
||||
import { onBeforeUnmount, onMounted, reactive, ref } from 'vue'
|
||||
import { DEFAULT_API_BASE_URL, useDesktopSession } from '../composables/useDesktopSession'
|
||||
|
||||
const { apiBaseURL, error, pending, setApiBaseURL, login } = useDesktopSession();
|
||||
const { apiBaseURL, error, pending, setApiBaseURL, login } = useDesktopSession()
|
||||
|
||||
const menuOpen = ref(false);
|
||||
const showServerDialog = ref(false);
|
||||
const rememberPassword = ref(!!localStorage.getItem("geo_rankly_saved_password"));
|
||||
const menuOpen = ref(false)
|
||||
const showServerDialog = ref(false)
|
||||
const rememberPassword = ref(!!localStorage.getItem('geo_rankly_saved_password'))
|
||||
const savedIdentifier =
|
||||
localStorage.getItem("geo_rankly_saved_identifier")
|
||||
?? localStorage.getItem("geo_rankly_saved_email")
|
||||
?? "";
|
||||
localStorage.getItem('geo_rankly_saved_identifier') ??
|
||||
localStorage.getItem('geo_rankly_saved_email') ??
|
||||
''
|
||||
|
||||
const form = reactive({
|
||||
apiBaseURL: apiBaseURL.value,
|
||||
identifier: savedIdentifier,
|
||||
password: localStorage.getItem("geo_rankly_saved_password") || "",
|
||||
});
|
||||
password: localStorage.getItem('geo_rankly_saved_password') || '',
|
||||
})
|
||||
|
||||
const menuRef = ref<HTMLElement | null>(null);
|
||||
const menuRef = ref<HTMLElement | null>(null)
|
||||
|
||||
function toggleMenu() {
|
||||
menuOpen.value = !menuOpen.value;
|
||||
menuOpen.value = !menuOpen.value
|
||||
}
|
||||
|
||||
function onRememberChange(event: Event) {
|
||||
rememberPassword.value = (event.target as HTMLInputElement).checked;
|
||||
rememberPassword.value = (event.target as HTMLInputElement).checked
|
||||
}
|
||||
|
||||
function handleOutsideClick(event: MouseEvent) {
|
||||
if (!menuOpen.value) return;
|
||||
const root = menuRef.value;
|
||||
if (!menuOpen.value) return
|
||||
const root = menuRef.value
|
||||
if (root && !root.contains(event.target as Node)) {
|
||||
menuOpen.value = false;
|
||||
menuOpen.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function openServerSettings() {
|
||||
menuOpen.value = false;
|
||||
form.apiBaseURL = apiBaseURL.value;
|
||||
showServerDialog.value = true;
|
||||
menuOpen.value = false
|
||||
form.apiBaseURL = apiBaseURL.value
|
||||
showServerDialog.value = true
|
||||
}
|
||||
|
||||
function closeServerSettings() {
|
||||
showServerDialog.value = false;
|
||||
showServerDialog.value = false
|
||||
}
|
||||
|
||||
function saveServerSettings() {
|
||||
setApiBaseURL(form.apiBaseURL);
|
||||
showServerDialog.value = false;
|
||||
setApiBaseURL(form.apiBaseURL)
|
||||
showServerDialog.value = false
|
||||
}
|
||||
|
||||
async function submitLogin() {
|
||||
if (rememberPassword.value) {
|
||||
localStorage.setItem("geo_rankly_saved_identifier", form.identifier);
|
||||
localStorage.removeItem("geo_rankly_saved_email");
|
||||
localStorage.setItem("geo_rankly_saved_password", form.password);
|
||||
localStorage.setItem('geo_rankly_saved_identifier', form.identifier)
|
||||
localStorage.removeItem('geo_rankly_saved_email')
|
||||
localStorage.setItem('geo_rankly_saved_password', form.password)
|
||||
} else {
|
||||
localStorage.removeItem("geo_rankly_saved_identifier");
|
||||
localStorage.removeItem("geo_rankly_saved_email");
|
||||
localStorage.removeItem("geo_rankly_saved_password");
|
||||
localStorage.removeItem('geo_rankly_saved_identifier')
|
||||
localStorage.removeItem('geo_rankly_saved_email')
|
||||
localStorage.removeItem('geo_rankly_saved_password')
|
||||
}
|
||||
|
||||
await login({
|
||||
identifier: form.identifier,
|
||||
password: form.password,
|
||||
});
|
||||
await window.desktopBridge?.app?.setWindowMode?.("main", { source: "login" });
|
||||
})
|
||||
await window.desktopBridge?.app?.setWindowMode?.('main', { source: 'login' })
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener("mousedown", handleOutsideClick);
|
||||
});
|
||||
document.addEventListener('mousedown', handleOutsideClick)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
document.removeEventListener("mousedown", handleOutsideClick);
|
||||
});
|
||||
document.removeEventListener('mousedown', handleOutsideClick)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -86,7 +86,7 @@ onBeforeUnmount(() => {
|
||||
<div class="orb orb-3"></div>
|
||||
</div>
|
||||
|
||||
<div class="top-bar" ref="menuRef">
|
||||
<div ref="menuRef" class="top-bar">
|
||||
<button
|
||||
type="button"
|
||||
class="menu-trigger"
|
||||
@@ -99,9 +99,7 @@ onBeforeUnmount(() => {
|
||||
<span></span>
|
||||
</button>
|
||||
<div v-if="menuOpen" class="menu-dropdown">
|
||||
<button type="button" class="menu-item" @click="openServerSettings">
|
||||
服务器设置
|
||||
</button>
|
||||
<button type="button" class="menu-item" @click="openServerSettings">服务器设置</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -136,17 +134,13 @@ onBeforeUnmount(() => {
|
||||
|
||||
<div class="options-row">
|
||||
<label class="check-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="rememberPassword"
|
||||
@change="onRememberChange"
|
||||
/>
|
||||
<input type="checkbox" :checked="rememberPassword" @change="onRememberChange" />
|
||||
<span>记住密码</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="submit-button" :disabled="pending">
|
||||
{{ pending ? "登录中..." : "登 录" }}
|
||||
{{ pending ? '登录中...' : '登 录' }}
|
||||
</button>
|
||||
|
||||
<p v-if="error" class="error-text">{{ error }}</p>
|
||||
@@ -154,11 +148,7 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
|
||||
<Transition name="fade">
|
||||
<div
|
||||
v-if="showServerDialog"
|
||||
class="dialog-mask"
|
||||
@click.self="closeServerSettings"
|
||||
>
|
||||
<div v-if="showServerDialog" class="dialog-mask" @click.self="closeServerSettings">
|
||||
<div class="dialog" role="dialog" aria-modal="true">
|
||||
<header class="dialog-header">
|
||||
<h3>服务器设置</h3>
|
||||
@@ -184,12 +174,8 @@ onBeforeUnmount(() => {
|
||||
<p class="dialog-hint">修改后对本机下次登录生效。</p>
|
||||
</div>
|
||||
<footer class="dialog-footer">
|
||||
<button type="button" class="btn-ghost" @click="closeServerSettings">
|
||||
取消
|
||||
</button>
|
||||
<button type="button" class="btn-primary" @click="saveServerSettings">
|
||||
保存
|
||||
</button>
|
||||
<button type="button" class="btn-ghost" @click="closeServerSettings">取消</button>
|
||||
<button type="button" class="btn-primary" @click="saveServerSettings">保存</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
@@ -266,7 +252,7 @@ onBeforeUnmount(() => {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
:global(html[data-platform="darwin"]) .top-bar {
|
||||
:global(html[data-platform='darwin']) .top-bar {
|
||||
left: 52px;
|
||||
right: auto;
|
||||
}
|
||||
@@ -374,7 +360,9 @@ onBeforeUnmount(() => {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
background: linear-gradient(135deg, #1677ff 0%, #4096ff 100%);
|
||||
box-shadow: 0 10px 22px rgba(22, 119, 255, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.35);
|
||||
box-shadow:
|
||||
0 10px 22px rgba(22, 119, 255, 0.28),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.35);
|
||||
}
|
||||
|
||||
.brand-core {
|
||||
@@ -387,7 +375,7 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
|
||||
.brand-core::after {
|
||||
content: "";
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 7px;
|
||||
border-radius: 3px;
|
||||
@@ -418,7 +406,9 @@ onBeforeUnmount(() => {
|
||||
font-size: 14px;
|
||||
color: #1f2937;
|
||||
box-shadow: 0 4px 12px rgba(31, 58, 112, 0.08);
|
||||
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
||||
transition:
|
||||
border-color 0.2s ease,
|
||||
box-shadow 0.2s ease;
|
||||
outline: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@@ -429,7 +419,9 @@ onBeforeUnmount(() => {
|
||||
|
||||
.field input:focus {
|
||||
border-color: #1677ff;
|
||||
box-shadow: 0 4px 14px rgba(31, 58, 112, 0.08), 0 0 0 3px rgba(22, 119, 255, 0.12);
|
||||
box-shadow:
|
||||
0 4px 14px rgba(31, 58, 112, 0.08),
|
||||
0 0 0 3px rgba(22, 119, 255, 0.12);
|
||||
}
|
||||
|
||||
.options-row {
|
||||
@@ -448,7 +440,7 @@ onBeforeUnmount(() => {
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.check-label input[type="checkbox"] {
|
||||
.check-label input[type='checkbox'] {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
accent-color: #1677ff;
|
||||
@@ -469,7 +461,9 @@ onBeforeUnmount(() => {
|
||||
padding-left: 0.4em;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 6px 16px rgba(22, 119, 255, 0.25);
|
||||
transition: background 0.2s ease, transform 0.1s ease;
|
||||
transition:
|
||||
background 0.2s ease,
|
||||
transform 0.1s ease;
|
||||
}
|
||||
|
||||
.submit-button:hover:not(:disabled) {
|
||||
@@ -572,7 +566,9 @@ onBeforeUnmount(() => {
|
||||
font-size: 14px;
|
||||
color: #1f2937;
|
||||
outline: none;
|
||||
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
||||
transition:
|
||||
border-color 0.2s ease,
|
||||
box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.dialog-field input:focus {
|
||||
@@ -601,7 +597,9 @@ onBeforeUnmount(() => {
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
transition: background 0.2s ease, border-color 0.2s ease;
|
||||
transition:
|
||||
background 0.2s ease,
|
||||
border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-ghost {
|
||||
|
||||
Reference in New Issue
Block a user