chore(frontend): introduce prettier + eslint and prune unused code
Backend CI / Backend (push) Has been cancelled
Frontend CI / Frontend (push) Failing after 1m39s

- 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:
2026-05-01 20:39:09 +08:00
parent 21c7892ee4
commit 162abdc97c
258 changed files with 42261 additions and 37556 deletions
@@ -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 {