2025-12-18 13:50:39 +08:00
|
|
|
<template>
|
|
|
|
|
<AppLayout>
|
2025-12-27 10:50:25 +08:00
|
|
|
<TablePageLayout>
|
refactor(frontend): comprehensive split of large view files into modular components
- Split UsersView.vue into UserCreateModal, UserEditModal, UserApiKeysModal, etc.
- Split UsageView.vue into UsageStatsCards, UsageFilters, UsageTable, etc.
- Split DashboardView.vue into UserDashboardStats, UserDashboardCharts, etc.
- Split AccountsView.vue into AccountTableActions, AccountTableFilters, etc.
- Standardized TypeScript types across new components to resolve implicit 'any' and 'never[]' errors.
- Improved overall frontend maintainability and code clarity.
2026-01-04 22:17:27 +08:00
|
|
|
<template #actions><AccountTableActions :loading="loading" @refresh="load" @sync="showSync = true" @create="showCreate = true" /></template>
|
|
|
|
|
<template #filters><AccountTableFilters v-model:searchQuery="query" :filters="filters" @change="load" @update:searchQuery="handleSearch" /></template>
|
2025-12-27 10:50:25 +08:00
|
|
|
<template #table>
|
refactor(frontend): comprehensive split of large view files into modular components
- Split UsersView.vue into UserCreateModal, UserEditModal, UserApiKeysModal, etc.
- Split UsageView.vue into UsageStatsCards, UsageFilters, UsageTable, etc.
- Split DashboardView.vue into UserDashboardStats, UserDashboardCharts, etc.
- Split AccountsView.vue into AccountTableActions, AccountTableFilters, etc.
- Standardized TypeScript types across new components to resolve implicit 'any' and 'never[]' errors.
- Improved overall frontend maintainability and code clarity.
2026-01-04 22:17:27 +08:00
|
|
|
<AccountBulkActionsBar :selected-ids="selIds" @delete="handleBulkDelete" @edit="showBulkEdit = true" />
|
|
|
|
|
<DataTable :columns="cols" :data="accounts" :loading="loading">
|
|
|
|
|
<template #cell-select="{ row }"><input type="checkbox" :checked="selIds.includes(row.id)" @change="toggleSel(row.id)" /></template>
|
|
|
|
|
<template #cell-name="{ value }"><span class="font-medium text-gray-900 dark:text-white">{{ value }}</span></template>
|
|
|
|
|
<template #cell-status="{ row }"><AccountStatusIndicator :account="row" /></template>
|
|
|
|
|
<template #cell-actions="{ row }"><div class="flex gap-2"><button @click="handleEdit(row)" class="btn btn-sm btn-secondary">{{ t('common.edit') }}</button><button @click="openMenu(row, $event)" class="btn btn-sm btn-secondary">{{ t('common.more') }}</button></div></template>
|
2025-12-18 13:50:39 +08:00
|
|
|
</DataTable>
|
2025-12-27 10:50:25 +08:00
|
|
|
</template>
|
refactor(frontend): comprehensive split of large view files into modular components
- Split UsersView.vue into UserCreateModal, UserEditModal, UserApiKeysModal, etc.
- Split UsageView.vue into UsageStatsCards, UsageFilters, UsageTable, etc.
- Split DashboardView.vue into UserDashboardStats, UserDashboardCharts, etc.
- Split AccountsView.vue into AccountTableActions, AccountTableFilters, etc.
- Standardized TypeScript types across new components to resolve implicit 'any' and 'never[]' errors.
- Improved overall frontend maintainability and code clarity.
2026-01-04 22:17:27 +08:00
|
|
|
<template #pagination><Pagination v-if="page.total > 0" :page="page.page" :total="page.total" :page-size="page.size" @update:page="handlePage" /></template>
|
2025-12-27 10:50:25 +08:00
|
|
|
</TablePageLayout>
|
refactor(frontend): comprehensive split of large view files into modular components
- Split UsersView.vue into UserCreateModal, UserEditModal, UserApiKeysModal, etc.
- Split UsageView.vue into UsageStatsCards, UsageFilters, UsageTable, etc.
- Split DashboardView.vue into UserDashboardStats, UserDashboardCharts, etc.
- Split AccountsView.vue into AccountTableActions, AccountTableFilters, etc.
- Standardized TypeScript types across new components to resolve implicit 'any' and 'never[]' errors.
- Improved overall frontend maintainability and code clarity.
2026-01-04 22:17:27 +08:00
|
|
|
<CreateAccountModal :show="showCreate" :proxies="proxies" :groups="groups" @close="showCreate = false" @created="load" />
|
|
|
|
|
<EditAccountModal :show="showEdit" :account="edAcc" :proxies="proxies" :groups="groups" @close="showEdit = false" @updated="load" />
|
|
|
|
|
<AccountActionMenu :show="menu.show" :account="menu.acc" :position="menu.pos" @close="menu.show = false" @test="handleTest" @stats="handleStats" @reauth="handleReauth" @refresh-token="handleRefresh" />
|
|
|
|
|
<SyncFromCrsModal :show="showSync" @close="showSync = false" @synced="load" />
|
|
|
|
|
<BulkEditAccountModal :show="showBulkEdit" :account-ids="selIds" :proxies="proxies" :groups="groups" @close="showBulkEdit = false" @updated="handleBulkUpdated" />
|
2025-12-18 13:50:39 +08:00
|
|
|
</AppLayout>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
refactor(frontend): comprehensive split of large view files into modular components
- Split UsersView.vue into UserCreateModal, UserEditModal, UserApiKeysModal, etc.
- Split UsageView.vue into UsageStatsCards, UsageFilters, UsageTable, etc.
- Split DashboardView.vue into UserDashboardStats, UserDashboardCharts, etc.
- Split AccountsView.vue into AccountTableActions, AccountTableFilters, etc.
- Standardized TypeScript types across new components to resolve implicit 'any' and 'never[]' errors.
- Improved overall frontend maintainability and code clarity.
2026-01-04 22:17:27 +08:00
|
|
|
import { ref, reactive, onMounted } from 'vue'
|
|
|
|
|
import { useI18n } from 'vue-i18n'; import { useAppStore } from '@/stores/app'; import { adminAPI } from '@/api/admin'
|
|
|
|
|
import AppLayout from '@/components/layout/AppLayout.vue'; import TablePageLayout from '@/components/layout/TablePageLayout.vue'; import DataTable from '@/components/common/DataTable.vue'; import Pagination from '@/components/common/Pagination.vue'
|
|
|
|
|
import { CreateAccountModal, EditAccountModal, BulkEditAccountModal, SyncFromCrsModal } from '@/components/account'
|
|
|
|
|
import AccountTableActions from '@/components/admin/account/AccountTableActions.vue'; import AccountTableFilters from '@/components/admin/account/AccountTableFilters.vue'
|
|
|
|
|
import AccountBulkActionsBar from '@/components/admin/account/AccountBulkActionsBar.vue'; import AccountActionMenu from '@/components/admin/account/AccountActionMenu.vue'
|
2025-12-18 13:50:39 +08:00
|
|
|
import AccountStatusIndicator from '@/components/account/AccountStatusIndicator.vue'
|
refactor(frontend): comprehensive split of large view files into modular components
- Split UsersView.vue into UserCreateModal, UserEditModal, UserApiKeysModal, etc.
- Split UsageView.vue into UsageStatsCards, UsageFilters, UsageTable, etc.
- Split DashboardView.vue into UserDashboardStats, UserDashboardCharts, etc.
- Split AccountsView.vue into AccountTableActions, AccountTableFilters, etc.
- Standardized TypeScript types across new components to resolve implicit 'any' and 'never[]' errors.
- Improved overall frontend maintainability and code clarity.
2026-01-04 22:17:27 +08:00
|
|
|
import type { Account, Proxy, Group } from '@/types'
|
2025-12-24 16:56:48 -08:00
|
|
|
|
refactor(frontend): comprehensive split of large view files into modular components
- Split UsersView.vue into UserCreateModal, UserEditModal, UserApiKeysModal, etc.
- Split UsageView.vue into UsageStatsCards, UsageFilters, UsageTable, etc.
- Split DashboardView.vue into UserDashboardStats, UserDashboardCharts, etc.
- Split AccountsView.vue into AccountTableActions, AccountTableFilters, etc.
- Standardized TypeScript types across new components to resolve implicit 'any' and 'never[]' errors.
- Improved overall frontend maintainability and code clarity.
2026-01-04 22:17:27 +08:00
|
|
|
const { t } = useI18n(); const appStore = useAppStore()
|
|
|
|
|
const accounts = ref<Account[]>([]); const proxies = ref<Proxy[]>([]); const groups = ref<Group[]>([]); const loading = ref(false); const query = ref('')
|
|
|
|
|
const filters = reactive({ platform: '', status: '' }); const page = reactive({ page: 1, size: 20, total: 0 })
|
|
|
|
|
const selIds = ref<number[]>([]); const showCreate = ref(false); const showEdit = ref(false); const showSync = ref(false); const showBulkEdit = ref(false)
|
|
|
|
|
const edAcc = ref<Account | null>(null); const menu = reactive<{show:boolean, acc:Account|null, pos:{top:number, left:number}|null}>({ show: false, acc: null, pos: null })
|
|
|
|
|
let abort: any = null
|
2025-12-18 13:50:39 +08:00
|
|
|
|
refactor(frontend): comprehensive split of large view files into modular components
- Split UsersView.vue into UserCreateModal, UserEditModal, UserApiKeysModal, etc.
- Split UsageView.vue into UsageStatsCards, UsageFilters, UsageTable, etc.
- Split DashboardView.vue into UserDashboardStats, UserDashboardCharts, etc.
- Split AccountsView.vue into AccountTableActions, AccountTableFilters, etc.
- Standardized TypeScript types across new components to resolve implicit 'any' and 'never[]' errors.
- Improved overall frontend maintainability and code clarity.
2026-01-04 22:17:27 +08:00
|
|
|
const cols = [{ key: 'select', label: '' }, { key: 'name', label: t('admin.accounts.columns.name'), sortable: true }, { key: 'status', label: t('admin.accounts.columns.status') }, { key: 'actions', label: t('admin.accounts.columns.actions') }]
|
2025-12-23 10:01:58 +08:00
|
|
|
|
refactor(frontend): comprehensive split of large view files into modular components
- Split UsersView.vue into UserCreateModal, UserEditModal, UserApiKeysModal, etc.
- Split UsageView.vue into UsageStatsCards, UsageFilters, UsageTable, etc.
- Split DashboardView.vue into UserDashboardStats, UserDashboardCharts, etc.
- Split AccountsView.vue into AccountTableActions, AccountTableFilters, etc.
- Standardized TypeScript types across new components to resolve implicit 'any' and 'never[]' errors.
- Improved overall frontend maintainability and code clarity.
2026-01-04 22:17:27 +08:00
|
|
|
const load = async () => {
|
|
|
|
|
abort?.abort(); abort = new AbortController(); loading.value = true
|
2025-12-18 13:50:39 +08:00
|
|
|
try {
|
refactor(frontend): comprehensive split of large view files into modular components
- Split UsersView.vue into UserCreateModal, UserEditModal, UserApiKeysModal, etc.
- Split UsageView.vue into UsageStatsCards, UsageFilters, UsageTable, etc.
- Split DashboardView.vue into UserDashboardStats, UserDashboardCharts, etc.
- Split AccountsView.vue into AccountTableActions, AccountTableFilters, etc.
- Standardized TypeScript types across new components to resolve implicit 'any' and 'never[]' errors.
- Improved overall frontend maintainability and code clarity.
2026-01-04 22:17:27 +08:00
|
|
|
const res = await adminAPI.accounts.list(page.page, page.size, { platform: filters.platform || undefined, status: filters.status || undefined, search: query.value || undefined }, { signal: abort.signal })
|
|
|
|
|
if(!abort.signal.aborted) { accounts.value = res.items; page.total = res.total }
|
|
|
|
|
} catch {} finally { loading.value = false }
|
|
|
|
|
}
|
|
|
|
|
const handleSearch = (v: string) => { query.value = v; page.page = 1; load() }
|
|
|
|
|
const handlePage = (p: number) => { page.page = p; load() }
|
|
|
|
|
const handleEdit = (a: Account) => { edAcc.value = a; showEdit.value = true }
|
|
|
|
|
const openMenu = (a: Account, e: MouseEvent) => { menu.acc = a; menu.pos = { top: e.clientY, left: e.clientX - 200 }; menu.show = true }
|
|
|
|
|
const toggleSel = (id: number) => { const i = selIds.value.indexOf(id); if(i === -1) selIds.value.push(id); else selIds.value.splice(i, 1) }
|
|
|
|
|
const handleBulkDelete = async () => { if(!confirm(t('common.confirm'))) return; try { await Promise.all(selIds.value.map(id => adminAPI.accounts.delete(id))); selIds.value = []; load() } catch {} }
|
|
|
|
|
const handleBulkUpdated = () => { showBulkEdit.value = false; selIds.value = []; load() }
|
|
|
|
|
const handleTest = async (a: Account) => { try { await adminAPI.accounts.clearError(a.id); appStore.showSuccess(t('common.success')); load() } catch {} }
|
|
|
|
|
const handleStats = (a: Account) => appStore.showInfo('Stats for ' + a.name)
|
|
|
|
|
const handleReauth = (a: Account) => appStore.showInfo('Reauth for ' + a.name)
|
|
|
|
|
const handleRefresh = async (a: Account) => { try { await adminAPI.accounts.refreshCredentials(a.id); load() } catch {} }
|
|
|
|
|
|
|
|
|
|
onMounted(async () => { load(); try { const [p, g] = await Promise.all([adminAPI.proxies.getAll(), adminAPI.groups.getAll()]); proxies.value = p; groups.value = g } catch {} })
|
2025-12-18 13:50:39 +08:00
|
|
|
</script>
|