This commit is contained in:
yangjianbo
2026-01-04 21:06:12 +08:00
183 changed files with 8275 additions and 3879 deletions

View File

@@ -216,7 +216,7 @@
</template>
<template #cell-status="{ row }">
<AccountStatusIndicator :account="row" />
<AccountStatusIndicator :account="row" @show-temp-unsched="handleShowTempUnsched" />
</template>
<template #cell-schedulable="{ row }">
@@ -400,6 +400,14 @@
<!-- Account Stats Modal -->
<AccountStatsModal :show="showStatsModal" :account="statsAccount" @close="closeStatsModal" />
<!-- Temp Unschedulable Status Modal -->
<TempUnschedStatusModal
:show="showTempUnschedModal"
:account="tempUnschedAccount"
@close="closeTempUnschedModal"
@reset="handleTempUnschedReset"
/>
<!-- Delete Confirmation Dialog -->
<ConfirmDialog
:show="showDeleteDialog"
@@ -512,6 +520,7 @@ import {
BulkEditAccountModal,
ReAuthAccountModal,
AccountStatsModal,
TempUnschedStatusModal,
SyncFromCrsModal
} from '@/components/account'
import AccountStatusIndicator from '@/components/account/AccountStatusIndicator.vue'
@@ -604,6 +613,7 @@ const showDeleteDialog = ref(false)
const showBulkDeleteDialog = ref(false)
const showTestModal = ref(false)
const showStatsModal = ref(false)
const showTempUnschedModal = ref(false)
const showCrsSyncModal = ref(false)
const showBulkEditModal = ref(false)
const editingAccount = ref<Account | null>(null)
@@ -611,6 +621,7 @@ const reAuthAccount = ref<Account | null>(null)
const deletingAccount = ref<Account | null>(null)
const testingAccount = ref<Account | null>(null)
const statsAccount = ref<Account | null>(null)
const tempUnschedAccount = ref<Account | null>(null)
const togglingSchedulable = ref<number | null>(null)
const bulkDeleting = ref(false)
@@ -775,6 +786,21 @@ const closeReAuthModal = () => {
reAuthAccount.value = null
}
// Temp unschedulable modal
const handleShowTempUnsched = (account: Account) => {
tempUnschedAccount.value = account
showTempUnschedModal.value = true
}
const closeTempUnschedModal = () => {
showTempUnschedModal.value = false
tempUnschedAccount.value = null
}
const handleTempUnschedReset = () => {
loadAccounts()
}
// Token refresh
const handleRefreshToken = async (account: Account) => {
try {

View File

@@ -240,7 +240,7 @@
href="https://dash.cloudflare.com/"
target="_blank"
class="text-primary-600 hover:text-primary-500"
>Cloudflare Dashboard</a
>{{ t('admin.settings.turnstile.cloudflareDashboard') }}</a
>
</p>
</div>

View File

@@ -303,12 +303,12 @@ function onTurnstileVerify(token: string): void {
function onTurnstileExpire(): void {
turnstileToken.value = ''
errors.turnstile = 'Verification expired, please try again'
errors.turnstile = t('auth.turnstileExpired')
}
function onTurnstileError(): void {
turnstileToken.value = ''
errors.turnstile = 'Verification failed, please try again'
errors.turnstile = t('auth.turnstileFailed')
}
// ==================== Validation ====================
@@ -323,25 +323,25 @@ function validateForm(): boolean {
// Email validation
if (!formData.email.trim()) {
errors.email = 'Email is required'
errors.email = t('auth.emailRequired')
isValid = false
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
errors.email = 'Please enter a valid email address'
errors.email = t('auth.invalidEmail')
isValid = false
}
// Password validation
if (!formData.password) {
errors.password = 'Password is required'
errors.password = t('auth.passwordRequired')
isValid = false
} else if (formData.password.length < 6) {
errors.password = 'Password must be at least 6 characters'
errors.password = t('auth.passwordMinLength')
isValid = false
}
// Turnstile validation
if (turnstileEnabled.value && !turnstileToken.value) {
errors.turnstile = 'Please complete the verification'
errors.turnstile = t('auth.completeVerification')
isValid = false
}
@@ -370,7 +370,7 @@ async function handleLogin(): Promise<void> {
})
// Show success toast
appStore.showSuccess('Login successful! Welcome back.')
appStore.showSuccess(t('auth.loginSuccess'))
// Redirect to dashboard or intended route
const redirectTo = (router.currentRoute.value.query.redirect as string) || '/dashboard'
@@ -390,7 +390,7 @@ async function handleLogin(): Promise<void> {
} else if (err.message) {
errorMessage.value = err.message
} else {
errorMessage.value = 'Login failed. Please check your credentials and try again.'
errorMessage.value = t('auth.loginFailed')
}
// Also show error toast

View File

@@ -340,12 +340,12 @@ function onTurnstileVerify(token: string): void {
function onTurnstileExpire(): void {
turnstileToken.value = ''
errors.turnstile = 'Verification expired, please try again'
errors.turnstile = t('auth.turnstileExpired')
}
function onTurnstileError(): void {
turnstileToken.value = ''
errors.turnstile = 'Verification failed, please try again'
errors.turnstile = t('auth.turnstileFailed')
}
// ==================== Validation ====================
@@ -365,25 +365,25 @@ function validateForm(): boolean {
// Email validation
if (!formData.email.trim()) {
errors.email = 'Email is required'
errors.email = t('auth.emailRequired')
isValid = false
} else if (!validateEmail(formData.email)) {
errors.email = 'Please enter a valid email address'
errors.email = t('auth.invalidEmail')
isValid = false
}
// Password validation
if (!formData.password) {
errors.password = 'Password is required'
errors.password = t('auth.passwordRequired')
isValid = false
} else if (formData.password.length < 6) {
errors.password = 'Password must be at least 6 characters'
errors.password = t('auth.passwordMinLength')
isValid = false
}
// Turnstile validation
if (turnstileEnabled.value && !turnstileToken.value) {
errors.turnstile = 'Please complete the verification'
errors.turnstile = t('auth.completeVerification')
isValid = false
}
@@ -429,7 +429,7 @@ async function handleRegister(): Promise<void> {
})
// Show success toast
appStore.showSuccess('Account created successfully! Welcome to ' + siteName.value + '.')
appStore.showSuccess(t('auth.accountCreatedSuccess', { siteName: siteName.value }))
// Redirect to dashboard
await router.push('/dashboard')
@@ -448,7 +448,7 @@ async function handleRegister(): Promise<void> {
} else if (err.message) {
errorMessage.value = err.message
} else {
errorMessage.value = 'Registration failed. Please try again.'
errorMessage.value = t('auth.registrationFailed')
}
// Also show error toast

View File

@@ -500,7 +500,7 @@ const getHistoryItemTitle = (item: RedeemHistoryItem) => {
} else if (item.type === 'subscription') {
return t('redeem.subscriptionAssigned')
}
return 'Unknown'
return t('common.unknown')
}
const formatHistoryValue = (item: RedeemHistoryItem) => {

View File

@@ -279,7 +279,7 @@ async function loadSubscriptions() {
subscriptions.value = await subscriptionsAPI.getMySubscriptions()
} catch (error) {
console.error('Failed to load subscriptions:', error)
appStore.showError('Failed to load subscriptions')
appStore.showError(t('userSubscriptions.failedToLoad'))
} finally {
loading.value = false
}