feat(ui): adopt Tailwind v4 design system and archive change
- Add tailwindcss v4 + @tailwindcss/vite to mall, shop-admin, admin - Add @vmall/shared/theme.css tokens with html[data-accent] presets - Add @vmall/ui kit (VBtn/VBadge/VField/VInput/VCard/VPanel/VTable/VPage, VAccentSwatch, useAccent) as a Nuxt module - Convert all three apps to kit + utilities; delete ui.css/mall.css and every <style scoped>; consoles get accent presets, mall locked to red - Fix VCard boolean prop default (padding) and PDP/store stale useAsyncData keys on param navigation - Archive adopt-tailwind-design-system; new frontend-ui capability spec
This commit is contained in:
+35
-49
@@ -36,7 +36,7 @@ function formatDate(value: string): string {
|
||||
return new Date(value).toLocaleString(locale.value === "zh" ? "zh-CN" : "en-US");
|
||||
}
|
||||
|
||||
function statusClass(status: Order["status"]): string {
|
||||
function statusClass(status: Order["status"]): "green" | "red" | "orange" | "blue" {
|
||||
if (status === "completed") return "green";
|
||||
if (status === "cancelled") return "red";
|
||||
if (status === "pending_payment") return "orange";
|
||||
@@ -76,53 +76,39 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page">
|
||||
<div class="page-head">
|
||||
<h1 class="page-title">{{ $t("nav.orders") }}</h1>
|
||||
<span v-if="!loading" class="muted">{{ $t("admin.pageOf", { page, total: totalPages }) }}</span>
|
||||
<VPage :title="$t('nav.orders')">
|
||||
<template #actions>
|
||||
<span v-if="!loading" class="text-sm text-muted">{{ $t("admin.pageOf", { page, total: totalPages }) }}</span>
|
||||
</template>
|
||||
<p v-if="loading" class="text-sm text-muted">{{ $t("common.loading") }}</p>
|
||||
<p v-else-if="errorMessage" class="my-2 text-sm text-danger" role="alert">{{ errorMessage }}</p>
|
||||
<VCard v-else-if="orders.length === 0" class="text-muted">{{ $t("common.empty") }}</VCard>
|
||||
<div v-else class="overflow-x-auto"><div class="min-w-[900px]"><VTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ $t("order.orderNo") }}</th>
|
||||
<th>{{ $t("admin.orderShop") }}</th>
|
||||
<th>{{ $t("admin.orderUser") }}</th>
|
||||
<th>{{ $t("admin.orderTotal") }}</th>
|
||||
<th>{{ $t("common.status") }}</th>
|
||||
<th>{{ $t("admin.created") }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="order in orders" :key="order.id">
|
||||
<td><strong>{{ order.order_no }}</strong></td>
|
||||
<td>{{ shopName(order.shop_id) }}</td>
|
||||
<td><code class="rounded bg-bg px-1.5 py-0.5" :title="order.user_id">{{ order.user_id.slice(0, 8) }}</code></td>
|
||||
<td>{{ formatTotal(order) }}</td>
|
||||
<td><VBadge :tone="statusClass(order.status)">{{ $t(`order.status.${order.status}`) }}</VBadge></td>
|
||||
<td>{{ formatDate(order.created_at) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</VTable></div></div>
|
||||
<div v-if="!loading && !errorMessage && orders.length > 0" class="mt-4 flex items-center justify-center gap-3">
|
||||
<VBtn size="sm" :disabled="page <= 1" @click="changePage(page - 1)">{{ $t("common.prev") }}</VBtn>
|
||||
<span class="text-sm text-muted">{{ page }} / {{ totalPages }}</span>
|
||||
<VBtn size="sm" :disabled="page >= totalPages" @click="changePage(page + 1)">{{ $t("common.next") }}</VBtn>
|
||||
</div>
|
||||
<p v-if="loading" class="muted">{{ $t("common.loading") }}</p>
|
||||
<p v-else-if="errorMessage" class="error-text" role="alert">{{ errorMessage }}</p>
|
||||
<div v-else-if="orders.length === 0" class="card muted">{{ $t("common.empty") }}</div>
|
||||
<div v-else class="table-wrap card">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ $t("order.orderNo") }}</th>
|
||||
<th>{{ $t("admin.orderShop") }}</th>
|
||||
<th>{{ $t("admin.orderUser") }}</th>
|
||||
<th>{{ $t("admin.orderTotal") }}</th>
|
||||
<th>{{ $t("common.status") }}</th>
|
||||
<th>{{ $t("admin.created") }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="order in orders" :key="order.id">
|
||||
<td><strong>{{ order.order_no }}</strong></td>
|
||||
<td>{{ shopName(order.shop_id) }}</td>
|
||||
<td><code :title="order.user_id">{{ order.user_id.slice(0, 8) }}</code></td>
|
||||
<td>{{ formatTotal(order) }}</td>
|
||||
<td><span class="badge" :class="statusClass(order.status)">{{ $t(`order.status.${order.status}`) }}</span></td>
|
||||
<td>{{ formatDate(order.created_at) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div v-if="!loading && !errorMessage && orders.length > 0" class="pagination">
|
||||
<button class="btn sm" type="button" :disabled="page <= 1" @click="changePage(page - 1)">
|
||||
{{ $t("common.prev") }}
|
||||
</button>
|
||||
<span class="muted">{{ page }} / {{ totalPages }}</span>
|
||||
<button class="btn sm" type="button" :disabled="page >= totalPages" @click="changePage(page + 1)">
|
||||
{{ $t("common.next") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</VPage>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.table-wrap { overflow-x: auto; padding: 0; }
|
||||
.table { min-width: 900px; }
|
||||
.pagination { align-items: center; display: flex; gap: 12px; justify-content: center; margin-top: 16px; }
|
||||
code { background: #f0f2f5; border-radius: 4px; padding: 2px 5px; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user