소스 검색

longwei_user-2025-07-24 08:37:37

genlitex 1 주 전
부모
커밋
c5853c9cfd
6개의 변경된 파일414개의 추가작업 그리고 2개의 파일을 삭제
  1. 0 0
      dist/assets/index-4owCqU6i.css
  2. 0 0
      dist/assets/index-BpH87opT.css
  3. 0 0
      dist/assets/index-Cf3abjqg.js
  4. 2 2
      dist/index.html
  5. 5 0
      src/router/index.js
  6. 407 0
      src/views/ProductManagement.vue

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
dist/assets/index-4owCqU6i.css


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
dist/assets/index-BpH87opT.css


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
dist/assets/index-Cf3abjqg.js


+ 2 - 2
dist/index.html

@@ -5,8 +5,8 @@
     <link rel="icon" type="image/svg+xml" href="/vite.svg" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>Vite + Vue</title>
-    <script type="module" crossorigin src="/ide/proxy/6002/assets/index-C_m0F2Qf.js"></script>
-    <link rel="stylesheet" crossorigin href="/ide/proxy/6002/assets/index-4owCqU6i.css">
+    <script type="module" crossorigin src="/ide/proxy/6009/assets/index-Cf3abjqg.js"></script>
+    <link rel="stylesheet" crossorigin href="/ide/proxy/6009/assets/index-BpH87opT.css">
   </head>
   <body>
     <div id="app"></div>

+ 5 - 0
src/router/index.js

@@ -160,6 +160,11 @@ const routes = [
   {
     path: '/:pathMatch(.*)*',
     redirect: '/'
+  },
+  {
+    path: '/product-management',
+    name: 'product-management',
+    component: ProductManagement
   }
 ]
 

+ 407 - 0
src/views/ProductManagement.vue

@@ -0,0 +1,407 @@
+<template>
+  <div class="min-h-screen bg-pink-100 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-pink-500 dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex items-center">
+            <h1 class="text-xl font-bold text-white dark:text-white">商品管理</h1>
+          </div>
+          <div class="flex items-center">
+            <button 
+              @click="showAddProductModal = true"
+              class="ml-4 inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-pink-600 hover:bg-pink-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-pink-500"
+            >
+              <PlusIcon class="h-4 w-4 mr-2" />
+              新增
+            </button>
+            <button 
+              @click="showQueryModal = true"
+              class="ml-4 inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-pink-600 hover:bg-pink-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-pink-500"
+            >
+              <SearchIcon class="h-4 w-4 mr-2" />
+              查询
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <main class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
+      <!-- 搜索区域 -->
+      <div class="mb-6 bg-white dark:bg-gray-800 shadow rounded-lg p-4">
+        <div class="relative">
+          <input
+            v-model="searchText"
+            type="text"
+            class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-pink-500 dark:bg-gray-700 dark:text-white"
+            placeholder="搜索商品名称"
+          />
+          <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
+            <SearchIcon class="h-5 w-5 text-gray-400" />
+          </div>
+        </div>
+      </div>
+
+      <!-- 商品列表 -->
+      <div class="bg-white dark:bg-gray-800 shadow rounded-lg overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-pink-50 dark:bg-gray-700">
+            <tr>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                商品ID
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                商品名称
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                商品价格
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                商品库存
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                供应商信息
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                操作
+              </th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="product in filteredProducts" :key="product.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                {{ product.id }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                {{ product.name }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                ¥{{ product.price }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                {{ product.stock }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                {{ product.supplier }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button 
+                  @click="editProduct(product)"
+                  class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 mr-4"
+                >
+                  编辑
+                </button>
+                <button 
+                  @click="deleteProduct(product)"
+                  class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300"
+                >
+                  删除
+                </button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+
+      <!-- 分页 -->
+      <div class="mt-4 flex justify-between items-center">
+        <div class="text-sm text-gray-700 dark:text-gray-300">
+          显示 {{ (currentPage - 1) * pageSize + 1 }} 到 {{ Math.min(currentPage * pageSize, totalProducts) }} 条,共 {{ totalProducts }} 条
+        </div>
+        <div class="flex space-x-2">
+          <button 
+            @click="prevPage"
+            :disabled="currentPage === 1"
+            class="px-3 py-1 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700"
+          >
+            上一页
+          </button>
+          <button 
+            @click="nextPage"
+            :disabled="currentPage * pageSize >= totalProducts"
+            class="px-3 py-1 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700"
+          >
+            下一页
+          </button>
+        </div>
+      </div>
+    </main>
+
+    <!-- 新增/编辑商品弹窗 -->
+    <div v-if="showAddProductModal || showEditProductModal" class="fixed inset-0 z-50 overflow-y-auto">
+      <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
+        <div class="fixed inset-0 transition-opacity" aria-hidden="true">
+          <div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
+        </div>
+        <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
+        <div class="inline-block align-bottom bg-white dark:bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-2xl sm:w-full">
+          <div class="bg-white dark:bg-gray-800 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
+            <div class="sm:flex sm:items-start">
+              <div class="mt-3 text-center sm:mt-0 sm:text-left w-full">
+                <div class="flex justify-between items-center mb-4">
+                  <h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-white">
+                    {{ isEditing ? '编辑商品' : '新增商品' }}
+                  </h3>
+                  <button @click="closeModal" class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300">
+                    <XIcon class="h-6 w-6" />
+                  </button>
+                </div>
+                <form @submit.prevent="saveProduct" class="space-y-4">
+                  <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
+                    <div>
+                      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品名称</label>
+                      <input
+                        v-model="productForm.name"
+                        type="text"
+                        required
+                        class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-pink-500 focus:border-pink-500 dark:bg-gray-700 dark:text-white"
+                      />
+                    </div>
+                    <div>
+                      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品价格</label>
+                      <input
+                        v-model.number="productForm.price"
+                        type="number"
+                        min="0"
+                        step="0.01"
+                        required
+                        class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-pink-500 focus:border-pink-500 dark:bg-gray-700 dark:text-white"
+                      />
+                    </div>
+                    <div>
+                      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品库存</label>
+                      <input
+                        v-model.number="productForm.stock"
+                        type="number"
+                        min="0"
+                        required
+                        class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-pink-500 focus:border-pink-500 dark:bg-gray-700 dark:text-white"
+                      />
+                    </div>
+                    <div>
+                      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">供应商信息</label>
+                      <input
+                        v-model="productForm.supplier"
+                        type="text"
+                        required
+                        class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-pink-500 focus:border-pink-500 dark:bg-gray-700 dark:text-white"
+                      />
+                    </div>
+                  </div>
+                  <div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
+                    <button
+                      type="submit"
+                      class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-pink-600 text-base font-medium text-white hover:bg-pink-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-pink-500 sm:ml-3 sm:w-auto sm:text-sm"
+                    >
+                      保存
+                    </button>
+                    <button
+                      type="button"
+                      @click="closeModal"
+                      class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 dark:border-gray-600 shadow-sm px-4 py-2 bg-white dark:bg-gray-700 text-base font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-pink-500 sm:mt-0 sm:w-auto sm:text-sm"
+                    >
+                      取消
+                    </button>
+                  </div>
+                </form>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 查询弹窗 -->
+    <div v-if="showQueryModal" class="fixed inset-0 z-50 overflow-y-auto">
+      <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
+        <div class="fixed inset-0 transition-opacity" aria-hidden="true">
+          <div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
+        </div>
+        <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
+        <div class="inline-block align-bottom bg-white dark:bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-2xl sm:w-full">
+          <div class="bg-white dark:bg-gray-800 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
+            <div class="sm:flex sm:items-start">
+              <div class="mt-3 text-center sm:mt-0 sm:text-left w-full">
+                <div class="flex justify-between items-center mb-4">
+                  <h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-white">
+                    查询商品
+                  </h3>
+                  <button @click="showQueryModal = false" class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300">
+                    <XIcon class="h-6 w-6" />
+                  </button>
+                </div>
+                <form @submit.prevent="applyQuery" class="space-y-4">
+                  <div>
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品名称</label>
+                    <input
+                      v-model="queryForm.name"
+                      type="text"
+                      class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-pink-500 focus:border-pink-500 dark:bg-gray-700 dark:text-white"
+                    />
+                  </div>
+                  <div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
+                    <button
+                      type="submit"
+                      class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-pink-600 text-base font-medium text-white hover:bg-pink-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-pink-500 sm:ml-3 sm:w-auto sm:text-sm"
+                    >
+                      查询
+                    </button>
+                    <button
+                      type="button"
+                      @click="showQueryModal = false"
+                      class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 dark:border-gray-600 shadow-sm px-4 py-2 bg-white dark:bg-gray-700 text-base font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-pink-500 sm:mt-0 sm:w-auto sm:text-sm"
+                    >
+                      取消
+                    </button>
+                  </div>
+                </form>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+import { SearchIcon, PlusIcon, XIcon } from 'lucide-vue-next'
+
+// 商品表单相关状态
+const showAddProductModal = ref(false)
+const showEditProductModal = ref(false)
+const isEditing = ref(false)
+const productForm = ref({
+  id: '',
+  name: '',
+  price: 0,
+  stock: 0,
+  supplier: ''
+})
+
+// 查询表单相关状态
+const showQueryModal = ref(false)
+const queryForm = ref({
+  name: ''
+})
+
+// 模拟商品数据
+const products = ref([
+  {
+    id: 'P1001',
+    name: 'iPhone 13 Pro',
+    price: 7999,
+    stock: 100,
+    supplier: 'Apple'
+  },
+  {
+    id: 'P1002',
+    name: 'MacBook Pro',
+    price: 12999,
+    stock: 50,
+    supplier: 'Apple'
+  },
+  {
+    id: 'P1003',
+    name: 'AirPods Pro',
+    price: 1999,
+    stock: 0,
+    supplier: 'Apple'
+  }
+])
+
+// 当前页码和每页显示数量
+const currentPage = ref(1)
+const pageSize = ref(10)
+const totalProducts = ref(products.value.length)
+
+// 计算过滤后的商品列表
+const filteredProducts = computed(() => {
+  let result = [...products.value]
+  
+  // 名称筛选
+  if (queryForm.value.name) {
+    result = result.filter(p => p.name.toLowerCase().includes(queryForm.value.name.toLowerCase()))
+  }
+  
+  // 分页
+  const start = (currentPage.value - 1) * pageSize.value
+  const end = start + pageSize.value
+  return result.slice(start, end)
+})
+
+// 处理新增商品按钮点击
+const addProduct = () => {
+  isEditing.value = false
+  productForm.value = {
+    id: '',
+    name: '',
+    price: 0,
+    stock: 0,
+    supplier: ''
+  }
+  showAddProductModal.value = true
+}
+
+// 处理编辑商品按钮点击
+const editProduct = (product) => {
+  isEditing.value = true
+  productForm.value = { ...product }
+  showEditProductModal.value = true
+}
+
+// 处理保存商品
+const saveProduct = () => {
+  if (isEditing.value) {
+    // 更新商品
+    const index = products.value.findIndex(p => p.id === productForm.value.id)
+    if (index !== -1) {
+      products.value[index] = { ...productForm.value }
+    }
+  } else {
+    // 添加新商品
+    productForm.value.id = Date.now().toString()
+    products.value.push({ ...productForm.value })
+    totalProducts.value = products.value.length
+  }
+  closeModal()
+}
+
+// 处理删除商品
+const deleteProduct = (product) => {
+  const index = products.value.findIndex(p => p.id === product.id)
+  if (index !== -1) {
+    products.value.splice(index, 1)
+    totalProducts.value = products.value.length
+  }
+}
+
+// 处理查询提交
+const applyQuery = () => {
+  currentPage.value = 1
+  showQueryModal.value = false
+}
+
+// 处理关闭模态框
+const closeModal = () => {
+  showAddProductModal.value = false
+  showEditProductModal.value = false
+}
+
+// 处理上一页
+const prevPage = () => {
+  if (currentPage.value > 1) {
+    currentPage.value--
+  }
+}
+
+// 处理下一页
+const nextPage = () => {
+  if (currentPage.value * pageSize.value < totalProducts.value) {
+    currentPage.value++
+  }
+}
+</script>

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.