feat(webui): add Tailwind build system and refactor frontend architecture

- Replace Tailwind CDN with local build (PostCSS + autoprefixer + daisyui)

- Add CSS build scripts with automatic prepare hook on npm install

- Create account-actions.js service layer with unified response format

- Extend ErrorHandler.withLoading() for automatic loading state management

- Add skeleton screens for initial load, silent refresh for subsequent updates

- Implement loading animations for async operations (buttons, modals)

- Improve empty states and add ARIA labels for accessibility

- Abstract component styles using @apply (buttons, badges, inputs)

- Add JSDoc documentation for Dashboard modules

- Update README and CLAUDE.md with development guidelines
This commit is contained in:
Wha1eChai
2026-01-11 02:11:35 +08:00
parent ee6d222e4d
commit a56bc06cc1
22 changed files with 2730 additions and 499 deletions

View File

@@ -20,9 +20,12 @@
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</div>
<input type="text" :placeholder="$store.global.t('searchPlaceholder')"
class="w-full h-full bg-space-800 border border-space-border text-gray-300 rounded-lg pl-10 pr-10 focus:outline-none focus:border-neon-purple focus:ring-1 focus:ring-neon-purple transition-all text-xs placeholder-gray-600"
x-model.debounce="$store.data.filters.search" @input="$store.data.computeQuotaRows()">
<input type="text"
:placeholder="$store.global.t('searchPlaceholder')"
:aria-label="$store.global.t('searchPlaceholder')"
class="input-search-sm pr-10"
x-model.debounce="$store.data.filters.search"
@input="$store.data.computeQuotaRows()">
<button x-show="$store.data.filters.search"
x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="opacity-0 scale-75"
@@ -237,11 +240,28 @@
</div>
</td>
</tr>
<!-- Empty -->
<tr x-show="!$store.data.loading && $store.data.quotaRows.length === 0">
<td colspan="6" class="h-64 text-center text-gray-600 font-mono text-xs"
x-text="$store.global.t('noSignal')">
NO SIGNAL DETECTED
<!-- Empty State -->
<tr x-show="!$store.data.initialLoad && $store.data.quotaRows.length === 0">
<td colspan="6" class="py-16 text-center">
<div class="flex flex-col items-center gap-4 max-w-lg mx-auto">
<svg class="w-20 h-20 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"
d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z" />
</svg>
<h3 class="text-xl font-semibold text-gray-400" x-text="$store.global.t('noSignal')">
NO SIGNAL DETECTED
</h3>
<p class="text-sm text-gray-600 max-w-md leading-relaxed">
No model data available. Add accounts to see available models and quota information.
</p>
<button class="btn bg-neon-purple hover:bg-purple-600 border-none text-white btn-sm gap-2 shadow-lg shadow-neon-purple/20"
@click="$store.global.activeTab = 'accounts'">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg>
<span x-text="$store.global.t('goToAccounts')">Go to Accounts</span>
</button>
</div>
</td>
</tr>
</tbody>