Vue3 + Tailwind CSS 后臺管理系統教程

Vue3 搭配 Tailwind CSS 是構建現代后臺管理系統的絕佳組合。Vue3 提供了高效的響應式框架,而 Tailwind CSS 則讓樣式編寫變得快速且靈活。下面我將分步驟教你如何創建一個功能完整的后臺管理系統。

第 1 步:創建項目

首先,我們需要使用 Vite 創建一個 Vue3 項目,并安裝 Tailwind CSS、路由、?Font Awesome:

npm init vite@latest admin-system -- --template vue
cd admin-system
npm install
npm install -D tailwindcss@3.4.1 postcss autoprefixer
npx tailwindcss init -p
npm install vue-router@4
npm install font-awesome

第 2 步:配置 Tailwind CSS

創建?tailwind.config.js?文件并配置:

/** @type {import('tailwindcss').Config} */
module.exports = {content: ["./index.html","./src/**/*.{vue,js,ts,jsx,tsx}",],theme: {extend: {colors: {primary: '#165DFF',secondary: '#36CFC9',success: '#52C41A',warning: '#FAAD14',danger: '#F5222D',info: '#86909C',light: '#F2F3F5',dark: '#1D2129',},fontFamily: {inter: ['Inter', 'sans-serif'],},},},plugins: [],
}

在?src/index.css?中引入 Tailwind CSS:

@tailwind base;
@tailwind components;
@tailwind utilities;@layer utilities {.content-auto {content-visibility: auto;}.sidebar-item-active {@apply bg-primary/10 text-primary border-l-4 border-primary;}
}

第 4 步:創建布局組件

<template><div class="min-h-screen flex flex-col bg-gray-50"><!-- 頂部導航欄 --><header class="bg-white shadow-sm"><div class="flex items-center justify-between px-4 py-3"><div class="flex items-center"><button @click="toggleSidebar" class="md:hidden text-gray-500 focus:outline-none"><i class="fa fa-bars text-xl"></i></button><div class="ml-4 text-xl font-bold text-primary">管理系統</div></div><div class="flex items-center"><div class="relative mr-4"><input type="text" placeholder="搜索..." class="pl-8 pr-4 py-2 rounded-lg border border-gray-200 focus:outline-none focus:ring-2 focus:ring-primary/50"><i class="fa fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"></i></div><div class="relative ml-4"><button class="relative text-gray-500 focus:outline-none"><i class="fa fa-bell text-xl"></i><span class="absolute top-0 right-0 h-4 w-4 bg-red-500 rounded-full flex items-center justify-center text-white text-xs">3</span></button></div><div class="relative ml-6"><button @click="toggleDropdown" class="flex items-center focus:outline-none"><img src="https://picsum.photos/id/1005/40/40" alt="用戶頭像" class="w-8 h-8 rounded-full object-cover"><span class="ml-2 text-sm font-medium">管理員</span><i class="fa fa-angle-down ml-1 text-gray-500"></i></button><div v-show="dropdownVisible" class="absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg py-1 z-10"><a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"><i class="fa fa-user mr-2"></i>個人信息</a><a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"><i class="fa fa-cog mr-2"></i>設置</a><div class="border-t border-gray-100 my-1"></div><a href="#" @click="logout" class="block px-4 py-2 text-sm text-red-600 hover:bg-gray-100"><i class="fa fa-sign-out mr-2"></i>退出登錄</a></div></div></div></div></header><div class="flex flex-1 overflow-hidden"><!-- 側邊欄導航 --><aside :class="sidebarVisible ? 'translate-x-0' : '-translate-x-full'" class="fixed md:relative z-20 w-64 bg-white shadow-lg h-full transition-transform duration-300 ease-in-out"><nav class="py-4"><div class="px-4 mb-6"><div class="flex items-center"><img src="https://picsum.photos/id/1005/40/40" alt="用戶頭像" class="w-10 h-10 rounded-full object-cover"><div class="ml-3"><div class="text-sm font-medium text-gray-900">管理員</div><div class="text-xs text-gray-500">系統管理員</div></div></div></div><div class="px-2 space-y-1"><a href="/dashboard" class="flex items-center px-4 py-3 text-gray-600 rounded-lg sidebar-item-active"><i class="fa fa-tachometer mr-3"></i><span>儀表盤</span></a><a href="/users" class="flex items-center px-4 py-3 text-gray-600 rounded-lg hover:bg-gray-100 transition-colors duration-200"><i class="fa fa-users mr-3"></i><span>用戶管理</span></a><a href="/products" class="flex items-center px-4 py-3 text-gray-600 rounded-lg hover:bg-gray-100 transition-colors duration-200"><i class="fa fa-shopping-bag mr-3"></i><span>產品管理</span></a><a href="#" class="flex items-center px-4 py-3 text-gray-600 rounded-lg hover:bg-gray-100 transition-colors duration-200"><i class="fa fa-bar-chart mr-3"></i><span>數據分析</span></a><a href="#" class="flex items-center px-4 py-3 text-gray-600 rounded-lg hover:bg-gray-100 transition-colors duration-200"><i class="fa fa-cog mr-3"></i><span>系統設置</span></a></div><div class="px-4 py-4 mt-6 border-t border-gray-100"><div class="text-xs font-medium text-gray-500 uppercase tracking-wider">幫助</div><a href="#" class="flex items-center px-4 py-2 mt-2 text-gray-600 rounded-lg hover:bg-gray-100 transition-colors duration-200"><i class="fa fa-question-circle mr-3"></i><span>幫助中心</span></a><a href="#" class="flex items-center px-4 py-2 text-gray-600 rounded-lg hover:bg-gray-100 transition-colors duration-200"><i class="fa fa-life-ring mr-3"></i><span>聯系支持</span></a></div></nav></aside><!-- 主內容區 --><main class="flex-1 overflow-y-auto p-6 bg-gray-50"><div class="mb-6"><h1 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold text-gray-900">儀表盤</h1><p class="mt-1 text-gray-500">歡迎使用管理系統</p></div><div class="mb-6 flex flex-col md:flex-row md:space-x-4 space-y-4 md:space-y-0"><div class="bg-white rounded-xl shadow-sm p-6 flex-1"><div class="flex items-center justify-between"><div><p class="text-sm font-medium text-gray-500">用戶總數</p><h3 class="text-3xl font-bold text-gray-900 mt-1">1,284</h3><p class="text-xs text-green-500 mt-2"><i class="fa fa-arrow-up"></i> 12% 較上月</p></div><div class="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center"><i class="fa fa-users text-primary text-xl"></i></div></div></div><div class="bg-white rounded-xl shadow-sm p-6 flex-1"><div class="flex items-center justify-between"><div><p class="text-sm font-medium text-gray-500">產品總數</p><h3 class="text-3xl font-bold text-gray-900 mt-1">528</h3><p class="text-xs text-green-500 mt-2"><i class="fa fa-arrow-up"></i> 8% 較上月</p></div><div class="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center"><i class="fa fa-shopping-bag text-green-600 text-xl"></i></div></div></div><div class="bg-white rounded-xl shadow-sm p-6 flex-1"><div class="flex items-center justify-between"><div><p class="text-sm font-medium text-gray-500">訂單總數</p><h3 class="text-3xl font-bold text-gray-900 mt-1">2,451</h3><p class="text-xs text-green-500 mt-2"><i class="fa fa-arrow-up"></i> 16% 較上月</p></div><div class="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center"><i class="fa fa-file-text text-purple-600 text-xl"></i></div></div></div><div class="bg-white rounded-xl shadow-sm p-6 flex-1"><div class="flex items-center justify-between"><div><p class="text-sm font-medium text-gray-500">銷售額</p><h3 class="text-3xl font-bold text-gray-900 mt-1">¥156,284</h3><p class="text-xs text-green-500 mt-2"><i class="fa fa-arrow-up"></i> 23% 較上月</p></div><div class="w-12 h-12 rounded-full bg-yellow-100 flex items-center justify-center"><i class="fa fa-line-chart text-yellow-600 text-xl"></i></div></div></div></div><div class="grid grid-cols-1 lg:grid-cols-3 gap-6"><div class="lg:col-span-2 bg-white rounded-xl shadow-sm p-6"><div class="flex items-center justify-between mb-6"><h2 class="text-lg font-semibold text-gray-900">銷售趨勢</h2><div class="flex space-x-2"><button class="px-3 py-1 text-xs rounded-full bg-gray-100 text-gray-600">日</button><button class="px-3 py-1 text-xs rounded-full bg-primary text-white">周</button><button class="px-3 py-1 text-xs rounded-full bg-gray-100 text-gray-600">月</button></div></div><div class="h-80"><!-- 這里可以放置圖表組件 --><div class="w-full h-full flex items-center justify-center"><p class="text-gray-400">銷售趨勢圖表將顯示在這里</p></div></div></div><div class="bg-white rounded-xl shadow-sm p-6"><div class="flex items-center justify-between mb-6"><h2 class="text-lg font-semibold text-gray-900">銷售分布</h2><button class="text-primary text-sm">查看全部</button></div><div class="h-80"><!-- 這里可以放置圖表組件 --><div class="w-full h-full flex items-center justify-center"><p class="text-gray-400">銷售分布圖表將顯示在這里</p></div></div></div></div><div class="mt-6 bg-white rounded-xl shadow-sm p-6"><div class="flex items-center justify-between mb-6"><h2 class="text-lg font-semibold text-gray-900">最近訂單</h2><button class="text-primary text-sm">查看全部</button></div><div class="overflow-x-auto"><table class="min-w-full divide-y divide-gray-200"><thead><tr><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">訂單ID</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">客戶</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">產品</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">金額</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">狀態</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">操作</th></tr></thead><tbody class="bg-white divide-y divide-gray-200"><tr><td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">#ORD-12345</td><td class="px-6 py-4 whitespace-nowrap"><div class="flex items-center"><div class="flex-shrink-0 h-10 w-10"><img class="h-10 w-10 rounded-full" src="https://picsum.photos/id/1001/40/40" alt="用戶頭像"></div><div class="ml-4"><div class="text-sm font-medium text-gray-900">張三</div><div class="text-sm text-gray-500">zhangsan@example.com</div></div></div></td><td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">電子產品</td><td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">¥1,299.00</td><td class="px-6 py-4 whitespace-nowrap"><span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">已完成</span></td><td class="px-6 py-4 whitespace-nowrap text-sm text-primary"><button>查看詳情</button></td></tr><tr><td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">#ORD-12346</td><td class="px-6 py-4 whitespace-nowrap"><div class="flex items-center"><div class="flex-shrink-0 h-10 w-10"><img class="h-10 w-10 rounded-full" src="https://picsum.photos/id/1002/40/40" alt="用戶頭像"></div><div class="ml-4"><div class="text-sm font-medium text-gray-900">李四</div><div class="text-sm text-gray-500">lisi@example.com</div></div></div></td><td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">家居用品</td><td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">¥499.00</td><td class="px-6 py-4 whitespace-nowrap"><span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-yellow-100 text-yellow-800">處理中</span></td><td class="px-6 py-4 whitespace-nowrap text-sm text-primary"><button>查看詳情</button></td></tr><tr><td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">#ORD-12347</td><td class="px-6 py-4 whitespace-nowrap"><div class="flex items-center"><div class="flex-shrink-0 h-10 w-10"><img class="h-10 w-10 rounded-full" src="https://picsum.photos/id/1003/40/40" alt="用戶頭像"></div><div class="ml-4"><div class="text-sm font-medium text-gray-900">王五</div><div class="text-sm text-gray-500">wangwu@example.com</div></div></div></td><td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">圖書音像</td><td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">¥299.00</td><td class="px-6 py-4 whitespace-nowrap"><span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800">已發貨</span></td><td class="px-6 py-4 whitespace-nowrap text-sm text-primary"><button>查看詳情</button></td></tr></tbody></table></div></div></main></div></div>
</template><script setup>
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'const router = useRouter()const sidebarVisible = ref(true)
const dropdownVisible = ref(false)const toggleSidebar = () => {sidebarVisible.value = !sidebarVisible.value
}const toggleDropdown = () => {dropdownVisible.value = !dropdownVisible.value
}const logout = () => {localStorage.removeItem('token')router.push('/login')
}onMounted(() => {// 檢查登錄狀態if (!localStorage.getItem('token')) {router.push('/login')}
})
</script><style scoped>
/* 移動端適配 */
@media (max-width: 768px) {.sidebar {position: fixed;z-index: 100;transform: translateX(-100%);transition: transform 0.3s ease-in-out;}.sidebar-visible {transform: translateX(0);}.overlay {position: fixed;top: 0;left: 0;right: 0;bottom: 0;background-color: rgba(0, 0, 0, 0.5);z-index: 99;display: none;}.sidebar-visible + .overlay {display: block;}
}
</style>

第 5 步:創建登錄頁面

創建登錄頁面?src/views/Login.vue

<template><div class="min-h-screen bg-gray-50 flex items-center justify-center p-4"><div class="max-w-md w-full bg-white rounded-xl shadow-lg overflow-hidden"><div class="p-6 sm:p-8"><div class="text-center mb-8"><h1 class="text-2xl font-bold text-gray-900">管理系統登錄</h1><p class="mt-1 text-sm text-gray-500">請輸入賬號密碼登錄</p></div><form @submit.prevent="handleLogin"><div class="space-y-4"><div><label for="email" class="block text-sm font-medium text-gray-700">郵箱</label><div class="mt-1 relative"><div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"><i class="fa fa-envelope text-gray-400"></i></div><input type="email" id="email" v-model="form.email" class="pl-10 block w-full rounded-md border-gray-300 shadow-sm focus:ring-primary focus:border-primary" placeholder="your@email.com"></div></div><div><label for="password" class="block text-sm font-medium text-gray-700">密碼</label><div class="mt-1 relative"><div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"><i class="fa fa-lock text-gray-400"></i></div><input type="password" id="password" v-model="form.password" class="pl-10 block w-full rounded-md border-gray-300 shadow-sm focus:ring-primary focus:border-primary" placeholder="????????"></div></div><div class="flex items-center justify-between"><div class="flex items-center"><input id="remember-me" name="remember-me" type="checkbox" class="h-4 w-4 text-primary focus:ring-primary border-gray-300 rounded"><label for="remember-me" class="ml-2 block text-sm text-gray-900">記住我</label></div><div class="text-sm"><a href="#" class="font-medium text-primary hover:text-primary/80">忘記密碼?</a></div></div><div><button type="submit" class="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-primary hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary">登錄</button></div></div></form><div class="mt-6 relative"><div class="absolute inset-0 flex items-center"><div class="w-full border-t border-gray-300"></div></div><div class="relative flex justify-center text-sm"><span class="px-2 bg-white text-gray-500">其他登錄方式</span></div></div><div class="mt-6 grid grid-cols-3 gap-3"><button type="button" class="inline-flex justify-center py-2 px-4 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50"><i class="fa fa-weixin text-green-600"></i></button><button type="button" class="inline-flex justify-center py-2 px-4 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50"><i class="fa fa-qq text-blue-500"></i></button><button type="button" class="inline-flex justify-center py-2 px-4 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50"><i class="fa fa-github text-gray-800"></i></button></div></div><div class="bg-gray-50 px-6 py-4 text-center"><p class="text-sm text-gray-600">還沒有賬號? <a href="#" class="font-medium text-primary hover:text-primary/80">注冊</a></p></div></div></div>
</template><script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'const router = useRouter()const form = ref({email: '',password: ''
})const handleLogin = () => {// 模擬登錄驗證if (form.value.email && form.value.password) {localStorage.setItem('token', 'fake_token')router.push('/dashboard')} else {alert('請輸入郵箱和密碼')}
}
</script>

第 6 步:創建用戶管理頁面

創建用戶管理頁面?src/views/Users.vue

<template><div class="bg-white rounded-xl shadow-sm p-6"><div class="flex flex-col md:flex-row md:items-center md:justify-between mb-6"><div><h2 class="text-xl font-bold text-gray-900">用戶管理</h2><p class="mt-1 text-sm text-gray-500">管理系統用戶信息</p></div><div class="mt-4 md:mt-0 flex flex-col sm:flex-row space-y-2 sm:space-y-0 sm:space-x-3"><div class="relative"><input type="text" v-model="searchQuery" placeholder="搜索用戶..." class="pl-10 pr-4 py-2 rounded-lg border border-gray-200 focus:outline-none focus:ring-2 focus:ring-primary/50 w-full sm:w-64"><i class="fa fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"></i></div><button @click="handleCreateUser" class="inline-flex items-center px-4 py-2 border border-transparent rounded-lg shadow-sm text-sm font-medium text-white bg-primary hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary"><i class="fa fa-plus mr-2"></i>創建用戶</button></div></div><div class="overflow-x-auto"><table class="min-w-full divide-y divide-gray-200"><thead class="bg-gray-50"><tr><th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">ID</th><th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">用戶信息</th><th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">角色</th><th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">狀態</th><th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">創建時間</th><th scope="col" class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">操作</th></tr></thead><tbody class="bg-white divide-y divide-gray-200"><tr v-for="user in users" :key="user.id"><td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{{ user.id }}</td><td class="px-6 py-4 whitespace-nowrap"><div class="flex items-center"><div class="flex-shrink-0 h-10 w-10"><img class="h-10 w-10 rounded-full" :src="user.avatar" alt="用戶頭像"></div><div class="ml-4"><div class="text-sm font-medium text-gray-900">{{ user.name }}</div><div class="text-sm text-gray-500">{{ user.email }}</div></div></div></td><td class="px-6 py-4 whitespace-nowrap"><span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800">{{ user.role }}</span></td><td class="px-6 py-4 whitespace-nowrap"><span :class="user.status === 'active' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">{{ user.status === 'active' ? '活躍' : '禁用' }}</span></td><td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ user.createdAt }}</td><td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"><button class="text-indigo-600 hover:text-indigo-900 mr-3" @click="handleEditUser(user)">編輯</button><button class="text-red-600 hover:text-red-900" @click="handleDeleteUser(user)">刪除</button></td></tr></tbody></table></div><div class="mt-6 flex items-center justify-between"><div class="flex-1 flex justify-between sm:hidden"><button class="relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">上一頁</button><button class="ml-3 relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">下一頁</button></div><div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between"><div><p class="text-sm text-gray-700">顯示第 <span class="font-medium">{{ (currentPage - 1) * pageSize + 1 }}</span> 至 <span class="font-medium">{{ Math.min(currentPage * pageSize, totalUsers) }}</span> 條,共 <span class="font-medium">{{ totalUsers }}</span> 條記錄</p></div><div><nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination"><button :disabled="currentPage === 1" @click="currentPage--" class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50"><span class="sr-only">上一頁</span><i class="fa fa-chevron-left h-5 w-5"></i></button><button v-for="page in totalPages" :key="page" :class="page === currentPage ? 'z-10 bg-primary text-white' : 'bg-white text-gray-700'" :aria-current="page === currentPage ? 'page' : undefined" @click="currentPage = page" class="relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium">{{ page }}</button><button :disabled="currentPage === totalPages" @click="currentPage++" class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50"><span class="sr-only">下一頁</span><i class="fa fa-chevron-right h-5 w-5"></i></button></nav></div></div></div></div>
</template><script setup>
import { ref, computed, onMounted } from 'vue'const searchQuery = ref('')
const currentPage = ref(1)
const pageSize = ref(10)
const totalUsers = ref(124)const totalPages = computed(() => {return Math.ceil(totalUsers.value / pageSize.value)
})const users = ref([{id: 1,name: '張三',email: 'zhangsan@example.com',role: '管理員',status: 'active',avatar: 'https://picsum.photos/id/1001/40/40',createdAt: '2023-01-15'},{id: 2,name: '李四',email: 'lisi@example.com',role: '編輯',status: 'active',avatar: 'https://picsum.photos/id/1002/40/40',createdAt: '2023-02-20'},{id: 3,name: '王五',email: 'wangwu@example.com',role: '普通用戶',status: 'disabled',avatar: 'https://picsum.photos/id/1003/40/40',createdAt: '2023-03-10'},{id: 4,name: '趙六',email: 'zhaoliu@example.com',role: '普通用戶',status: 'active',avatar: 'https://picsum.photos/id/1004/40/40',createdAt: '2023-04-05'},{id: 5,name: '錢七',email: 'qianqi@example.com',role: '編輯',status: 'active',avatar: 'https://picsum.photos/id/1005/40/40',createdAt: '2023-05-12'}
])const handleCreateUser = () => {console.log('創建用戶')// 打開創建用戶模態框
}const handleEditUser = (user) => {console.log('編輯用戶', user)// 打開編輯用戶模態框
}const handleDeleteUser = (user) => {if (confirm(`確定要刪除用戶 ${user.name} 嗎?`)) {console.log('刪除用戶', user)// 調用API刪除用戶}
}onMounted(() => {// 加載用戶數據
})
</script>

第 7 步:創建產品管理頁面

創建產品管理頁面?src/views/Products.vue

<template><div class="bg-white rounded-xl shadow-sm p-6"><div class="flex flex-col md:flex-row md:items-center md:justify-between mb-6"><div><h2 class="text-xl font-bold text-gray-900">產品管理</h2><p class="mt-1 text-sm text-gray-500">管理系統產品信息</p></div><div class="mt-4 md:mt-0 flex flex-col sm:flex-row space-y-2 sm:space-y-0 sm:space-x-3"><div class="relative"><input type="text" v-model="searchQuery" placeholder="搜索產品..." class="pl-10 pr-4 py-2 rounded-lg border border-gray-200 focus:outline-none focus:ring-2 focus:ring-primary/50 w-full sm:w-64"><i class="fa fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"></i></div><div class="relative"><select v-model="categoryFilter" class="pl-4 pr-10 py-2 rounded-lg border border-gray-200 focus:outline-none focus:ring-2 focus:ring-primary/50 appearance-none bg-white"><option value="">全部分類</option><option value="electronics">電子產品</option><option value="clothing">服裝</option><option value="home">家居用品</option><option value="books">圖書音像</option></select><i class="fa fa-chevron-down absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 pointer-events-none"></i></div><button @click="handleCreateProduct" class="inline-flex items-center px-4 py-2 border border-transparent rounded-lg shadow-sm text-sm font-medium text-white bg-primary hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary"><i class="fa fa-plus mr-2"></i>創建產品</button></div></div><div class="overflow-x-auto"><table class="min-w-full divide-y divide-gray-200"><thead class="bg-gray-50"><tr><th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">ID</th><th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">產品信息</th><th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">分類</th><th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">價格</th><th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">庫存</th><th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">狀態</th><th scope="col" class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">操作</th></tr></thead><tbody class="bg-white divide-y divide-gray-200"><tr v-for="product in products" :key="product.id"><td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{{ product.id }}</td><td class="px-6 py-4 whitespace-nowrap"><div class="flex items-center"><div class="flex-shrink-0 h-12 w-12"><img class="h-12 w-12 rounded-md object-cover" :src="product.image" alt="產品圖片"></div><div class="ml-4"><div class="text-sm font-medium text-gray-900">{{ product.name }}</div><div class="text-sm text-gray-500">{{ product.description }}</div></div></div></td><td class="px-6 py-4 whitespace-nowrap"><span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-purple-100 text-purple-800">{{ product.category }}</span></td><td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">¥{{ product.price.toFixed(2) }}</td><td class="px-6 py-4 whitespace-nowrap"><span :class="product.stock < 10 ? 'text-red-600' : 'text-gray-900'" class="text-sm font-medium">{{ product.stock }}</span></td><td class="px-6 py-4 whitespace-nowrap"><span :class="product.status === 'active' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">{{ product.status === 'active' ? '上架' : '下架' }}</span></td><td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"><button class="text-indigo-600 hover:text-indigo-900 mr-3" @click="handleEditProduct(product)">編輯</button><button class="text-red-600 hover:text-red-900" @click="handleDeleteProduct(product)">刪除</button></td></tr></tbody></table></div><div class="mt-6 flex items-center justify-between"><div class="flex-1 flex justify-between sm:hidden"><button class="relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">上一頁</button><button class="ml-3 relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">下一頁</button></div><div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between"><div><p class="text-sm text-gray-700">顯示第 <span class="font-medium">{{ (currentPage - 1) * pageSize + 1 }}</span> 至 <span class="font-medium">{{ Math.min(currentPage * pageSize, totalProducts) }}</span> 條,共 <span class="font-medium">{{ totalProducts }}</span> 條記錄</p></div><div><nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination"><button :disabled="currentPage === 1" @click="currentPage--" class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50"><span class="sr-only">上一頁</span><i class="fa fa-chevron-left h-5 w-5"></i></button><button v-for="page in totalPages" :key="page" :class="page === currentPage ? 'z-10 bg-primary text-white' : 'bg-white text-gray-700'" :aria-current="page === currentPage ? 'page' : undefined" @click="currentPage = page" class="relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium">{{ page }}</button><button :disabled="currentPage === totalPages" @click="currentPage++" class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50"><span class="sr-only">下一頁</span><i class="fa fa-chevron-right h-5 w-5"></i></button></nav></div></div></div></div>
</template><script setup>
import { ref, computed, onMounted } from 'vue'const searchQuery = ref('')
const categoryFilter = ref('')
const currentPage = ref(1)
const pageSize = ref(10)
const totalProducts = ref(86)const totalPages = computed(() => {return Math.ceil(totalProducts.value / pageSize.value)
})const products = ref([{id: 1,name: '智能手表',description: '多功能智能手表,支持心率監測、睡眠分析等功能',category: '電子產品',price: 1299.99,stock: 56,status: 'active',image: 'https://picsum.photos/id/1/80/80'},{id: 2,name: '無線耳機',description: '主動降噪無線耳機,提供沉浸式音樂體驗',category: '電子產品',price: 899.99,stock: 32,status: 'active',image: 'https://picsum.photos/id/2/80/80'},{id: 3,name: '純棉T恤',description: '舒適純棉T恤,多種顏色可選',category: '服裝',price: 99.99,stock: 87,status: 'active',image: 'https://picsum.photos/id/3/80/80'},{id: 4,name: '家用咖啡機',description: '全自動家用咖啡機,一鍵制作美味咖啡',category: '家居用品',price: 1999.99,stock: 12,status: 'active',image: 'https://picsum.photos/id/4/80/80'},{id: 5,name: '前端開發實戰',description: '全面講解前端開發技術,從入門到精通',category: '圖書音像',price: 89.99,stock: 5,status: 'active',image: 'https://picsum.photos/id/5/80/80'}
])const handleCreateProduct = () => {console.log('創建產品')// 打開創建產品模態框
}const handleEditProduct = (product) => {console.log('編輯產品', product)// 打開編輯產品模態框
}const handleDeleteProduct = (product) => {if (confirm(`確定要刪除產品 ${product.name} 嗎?`)) {console.log('刪除產品', product)// 調用API刪除產品}
}onMounted(() => {// 加載產品數據
})
</script>

第 8 步:配置主應用

修改?src/main.js?來配置主應用:

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import './index.css'
import 'font-awesome/css/font-awesome.min.css'const app = createApp(App)app.use(router)app.mount('#app')

第 9 步:創建主應用組件

修改?src/App.vue

<template><router-view />
</template><script setup>
// 主應用邏輯
</script><style>
/* 全局樣式 */
body {margin: 0;padding: 0;font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
</style>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/85825.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/85825.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/85825.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ComfyUI遭“Pickai“C++后門攻擊,全球700余臺AI圖像生成服務器淪陷

大規模AI基礎設施遭遇定向攻擊 網絡安全研究機構XLab近日發現針對ComfyUI框架的活躍攻擊活動。ComfyUI是當前廣泛用于部署大型AI圖像生成模型的開源框架。攻擊者通過該框架漏洞植入名為Pickai的C后門程序&#xff0c;已導致全球近700臺服務器失陷。中國國家網絡安全通報中心于…

Unity_VR_如何用鍵鼠模擬VR輸入_PICO項目配置

文章目錄 [TOC] 一、創建項目1.直接創建VR核心模板&#xff08;簡單&#xff09;2.創建3D核心模板導入XR包&#xff08;并配置pico&#xff09;&#xff08;1&#xff09;創建項目&#xff08;2&#xff09;導入PICO的SDK&#xff08;3&#xff09;啟用 PICO XR 插件&#xff0…

站點天下--網站在線和SSL過期監控的可靠助手

簡介 網站突然訪問不了、HTTPS證書到期&#xff0c;如果不能及時發現&#xff0c;將蒙受損失~ 站點天下提供應用在線狀態監控和SSL證書到期監控&#xff1a; 若訪問不了或SSL證書即將到期&#xff0c;則立即發郵件通知&#xff01;可以在線查看應用的在線狀態和SSL證書到期時…

React setState原理

異步更新 原因 1設置為異步提升性能 如果setState每次調用直接執行&#xff0c;會造成 render 函數被頻繁執行 &#xff0c;頁面重新被渲染 解決&#xff1a;異步批處理 2如果render函數未執行時&#xff0c;保證props和state一致性 拿到最新state的方法 法一:setState&…

漢代大模型:歷史鏡像與智能重構的深度對話

引言&#xff1a;當歷史遇見人工智能 一件漢代陶俑的三維模型正通過增強現實技術向觀眾演繹農耕場景。這個看似尋常的文物活化案例&#xff0c;實則蘊含著人工智能與歷史學交叉領域的前沿探索——漢代大模型。作為連接過去與未來的智能載體&#xff0c;漢代大模型不僅重構了我…

es向量檢索里的efSearchc參數是干嘛用的

在Elasticsearch的向量檢索中&#xff0c;ef_search&#xff08;或efSearch&#xff09;是控制HNSW近似最近鄰&#xff08;ANN&#xff09;搜索精度與性能平衡的關鍵參數&#xff0c;其作用機制和影響如下&#xff1a; &#x1f6e0;? 一、核心作用 ef_search 限制底層圖遍歷…

Mac SSH終端操作工具 SecureCRT

SecureCRT Mac 是一款SSH終端工具&#xff0c;為計算專業人士提供高級會話管理工具。 也是一個功能強大且值得信賴的基于GUI的SHH和Telnet客戶端&#xff0c;以及旨在提高工作效率并簡化重復任務的終端仿真器。 借助SecureCRT mac版的幫助&#xff0c;您可以通過對ANSI&#…

UE5關卡快照

關卡快照&#xff08;Level Snapshots&#xff09; 使你能夠在關卡的 世界大綱視圖&#xff08;World Outliner&#xff09; 中保存 Actors 的特定配置&#xff0c;并立即將場景恢復到該狀態。這樣可以大幅簡化復雜的設置&#xff0c;并避免對不同場景同一關卡的多個變體進行復…

Maven 或 Gradle 下載和添加 jar 文件的步驟

使用 Maven 或 Gradle 來自動下載和添加 jar 文件是管理 Java 項目依賴的最佳方式。 以下是如何使用 Maven 和 Gradle 來自動下載和添加 jar 文件的步驟&#xff1a; 使用 Maven # 創建一個 Maven 項目&#xff1a; mvn archetype:generate -DgroupIdcom.example -Dartifact…

JVM對象創建全流程解析

一、JVM對象創建流程 Ⅰ、類加載檢查——JVM創建對象時先檢查類是否加載 在虛擬機遇到new指令時&#xff0c;比如new關鍵字、對象克隆、對象序列化時&#xff0c;如下字節碼 0: new #2 // class com/example/demo/Calculate檢查指令的參數&#x…

深度學習從入門到精通:PyTorch實戰與核心原理詳解

掌握深度學習核心概念&#xff0c;玩轉PyTorch框架&#xff0c;從理論到實戰一站式學習指南 &#x1f680; 一、深度學習全景圖 &#x1f31f; 人工智能金字塔 &#x1f50d; 深度學習核心優勢 ??優勢????劣勢????適用場景??自動特征提取依賴大數據圖像識別&…

計算機網絡期末 物理層

目錄 數據通信基礎(理解) 傳輸介質(熟悉) 基帶傳輸(熟悉) 數字編碼(熟悉) 頻帶傳輸與調制解調(理解) 多路復用技術(了解) 物理層設備與極限速率(掌握) 數據通信基礎(理解) 一堆概念 通信的類型 同步技術 傳輸介質(熟悉) 有線介質 同軸電纜 雙絞線 光纖 無線介質 無線電…

力扣-139.單詞拆分

題目描述 給你一個字符串 s 和一個字符串列表 wordDict 作為字典。如果可以利用字典中出現的一個或多個單詞拼接出 s 則返回 true。 注意&#xff1a;不要求字典中出現的單詞全部都使用&#xff0c;并且字典中的單詞可以重復使用。 class Solution {public boolean wordBrea…

LeetCode-1679. K 和數對的最大數目

給你一個整數數組 nums 和一個整數 k 。 每一步操作中&#xff0c;你需要從數組中選出和為 k 的兩個整數&#xff0c;并將它們移出數組。 返回你可以對數組執行的最大操作數。 地址&#xff1a;https://leetcode.cn/problems/max-number-of-k-sum-pairs/description/?envTyp…

相機camera開發之差異對比核查四:測試機和對比機的Camera動態參數差異對比及關鍵字

【關注我,后續持續新增專題博文,謝謝!!!】 上一篇我們講了: 這一篇我們開始講: 目錄 一、背景 二、:Camera動態參數差異 2.1:動態參數差異核查項 2.2 :動態參數差異核查關鍵字 2.3 :前置普通拍照動態參數 2.4 :后置普通拍照動態參數 2.5 :后置人像模式…

ModbusTCP轉Profibus網關在配料系統中的配置實踐

在現代飼料企業的生產過程中&#xff0c;自動化技術的應用日益廣泛。其中&#xff0c;ModbusTCP和Profibus是兩種常見的工業通信協議&#xff0c;它們在數據采集和設備控制方面發揮著重要作用。然而&#xff0c;由于這兩種協議在技術上的差異&#xff0c;直接互通往往存在困難。…

雙饋風機分段控制策略的一次調頻模型深度解析

雙饋風機分段控制策略的一次調頻模型深度解析 摘要 隨著風電滲透率的急劇攀升,電力系統慣性降低與一次調頻能力弱化問題日益凸顯。雙饋感應發電機(DFIG)憑借其優越的性能已成為主流機型,但其常規控制策略使其自然不具備響應系統頻率變化的能力。本文深入探討基于分段控制策…

JMeter 高階玩法:分布式壓測的技術核心技術要點

在2025年的數字化浪潮中&#xff0c;網站和應用的性能直接決定用戶體驗和業務成敗&#xff01;想象一下&#xff0c;雙十一促銷期間&#xff0c;你的電商平臺因無法承受高并發而崩潰&#xff0c;或者金融系統在高峰期響應遲緩——這不僅是技術問題&#xff0c;更是商業災難&…

在 Windows 和 Linux 下使用 C/C++ 連接 MySQL 的詳細指南

前言 MySQL 是一種流行的關系型數據庫管理系統&#xff0c;廣泛應用于各種應用程序中。C/C 作為高性能編程語言&#xff0c;常被用于需要與數據庫交互的開發中。下面詳細講解如何在 Windows 和 Linux 平臺下使用 C/C 連接 MySQL 數據庫&#xff0c;幫助你快速上手。 準備工作 …

【人工智能基礎】初識神經網絡

初識神經網絡 本章通過戰勝人類圍棋世界冠軍的AlphaGo案例,介紹神經網絡的基本概念,并闡明其與人工智能、機器學習的關系。 1. AlphaGo與圍棋:神經網絡的實力展示 傳統圍棋程序:基于固定規則 早期的計算機程序依賴人類專家預先設定的策略(“如果A情況發生,則執行B步驟”…