From 9d6651eb656acde97a7fc9fc4284645be3b898e3 Mon Sep 17 00:00:00 2001 From: Renyye <1457077123@qq.com> Date: Mon, 19 May 2025 14:37:08 +0800 Subject: [PATCH 01/16] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E3=80=81=E4=BA=A7=E5=93=81=E5=92=8C=E5=BA=97=E9=93=BA?= =?UTF-8?q?=E7=9A=84=20API=20=E6=8E=A5=E5=8F=A3=E5=8F=8A=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/api/category.ts | 18 ++ src/frontend/src/api/product.ts | 27 +++ src/frontend/src/api/shop.ts | 31 ++++ .../src/components/cards/product_card.vue | 57 ++++++ .../src/components/explore/FilterSidebar.vue | 145 ++++++++++++++++ .../src/components/explore/ProductGrid.vue | 29 ++++ .../src/components/home/CategoryList.vue | 27 ++- .../src/components/layout/NaviBar.vue | 23 ++- src/frontend/src/main.js | 12 ++ src/frontend/src/router/index.js | 37 +++- src/frontend/src/views/Explore.vue | 74 ++++++++ src/frontend/src/views/Login.vue | 48 ++++-- src/package-lock.json | 163 ++++++++++++++++++ 13 files changed, 653 insertions(+), 38 deletions(-) create mode 100644 src/frontend/src/api/category.ts create mode 100644 src/frontend/src/api/product.ts create mode 100644 src/frontend/src/api/shop.ts create mode 100644 src/frontend/src/components/cards/product_card.vue create mode 100644 src/frontend/src/components/explore/FilterSidebar.vue create mode 100644 src/frontend/src/components/explore/ProductGrid.vue create mode 100644 src/frontend/src/views/Explore.vue create mode 100644 src/package-lock.json diff --git a/src/frontend/src/api/category.ts b/src/frontend/src/api/category.ts new file mode 100644 index 0000000..b2829d1 --- /dev/null +++ b/src/frontend/src/api/category.ts @@ -0,0 +1,18 @@ +import axios from 'axios' + +/** 后端返回的分类结构 */ +export interface Category { + CategoryID: number + CategoryName: string + CategoryDescription?: string + ParentCategoryID?: number | null +} + +/** + * 获取分类列表 + * @param parent_id 父分类 ID;不传则取所有一级分类 + */ +export const fetchCategories = (parent_id?: number) => + axios.get('/category', { + params: parent_id ? { parent_id } : {} + }) diff --git a/src/frontend/src/api/product.ts b/src/frontend/src/api/product.ts new file mode 100644 index 0000000..da4e1c7 --- /dev/null +++ b/src/frontend/src/api/product.ts @@ -0,0 +1,27 @@ +import axios from 'axios' + +export interface Product { + ProductID: number + ProductName: string + ProductDescription: string + Price: string + CategoryID: number + StockQuantity: number + MainImageURL: string + StoreID: number + ProductStatus: string + CreationDate: string + LastUpdatedDate: string +} + +export interface ProductQuery { + store_id?: number + category_id?: number + search?: string + limit?: number + offset?: number + current_user_id?: number +} + +export const fetchProducts = (query: ProductQuery) => + axios.get('/product', { params: query }) diff --git a/src/frontend/src/api/shop.ts b/src/frontend/src/api/shop.ts new file mode 100644 index 0000000..504d2bd --- /dev/null +++ b/src/frontend/src/api/shop.ts @@ -0,0 +1,31 @@ +// Todo: align with backend API +// 写此文件时还缺少 get all shop 接口 +import axios from 'axios' + +/** 后端返回的店铺(Shop)结构 */ +export interface Shop { + StoreID: number + StoreName: string + StoreDescription?: string + StoreLogoURL?: string + // 可以根据后端实际扩展其他字段 +} + +/** + * 获取店铺列表(临时接口) + * 注意:后端实际路径可能是 `/store` 或 `/shop`,这里先用 `/shop` 协议 + * @param params 可选过滤条件,将被拼到 querystring + */ +export const fetchShops = (params?: { + // 未来可按地区、状态、关键字等筛选 + search?: string + limit?: number + offset?: number +}) => + axios.get('/shop', { + params: params ?? {} + }) + +// 示例: +// fetchShops({ search: 'Official', limit: 50, offset: 0 }) +// .then(res => console.log(res.data)) diff --git a/src/frontend/src/components/cards/product_card.vue b/src/frontend/src/components/cards/product_card.vue new file mode 100644 index 0000000..8192440 --- /dev/null +++ b/src/frontend/src/components/cards/product_card.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/src/frontend/src/components/explore/FilterSidebar.vue b/src/frontend/src/components/explore/FilterSidebar.vue new file mode 100644 index 0000000..d452e6e --- /dev/null +++ b/src/frontend/src/components/explore/FilterSidebar.vue @@ -0,0 +1,145 @@ + + + + + diff --git a/src/frontend/src/components/explore/ProductGrid.vue b/src/frontend/src/components/explore/ProductGrid.vue new file mode 100644 index 0000000..694564d --- /dev/null +++ b/src/frontend/src/components/explore/ProductGrid.vue @@ -0,0 +1,29 @@ + + + diff --git a/src/frontend/src/components/home/CategoryList.vue b/src/frontend/src/components/home/CategoryList.vue index 704092f..015a1db 100644 --- a/src/frontend/src/components/home/CategoryList.vue +++ b/src/frontend/src/components/home/CategoryList.vue @@ -1,14 +1,23 @@ diff --git a/src/frontend/src/components/cards/category_card.vue b/src/frontend/src/components/cards/category_card.vue index 2dfcec1..e1ccc43 100644 --- a/src/frontend/src/components/cards/category_card.vue +++ b/src/frontend/src/components/cards/category_card.vue @@ -1,5 +1,5 @@ @@ -90,4 +134,38 @@ .order-row:not(:last-child) { border-bottom: 1px solid #f0f0f0; } + .items-table { + margin: 16px 0; + } + .product-cell { + display: flex; + align-items: center; + gap: 10px; + } + .product-image { + width: 50px; + height: 50px; + border-radius: 4px; + } + .image-placeholder { + width: 50px; + height: 50px; + background: #f5f7fa; + display: flex; + align-items: center; + justify-content: center; + color: #909399; + font-size: 12px; + } + .order-total { + text-align: right; + margin-top: 16px; + font-weight: 500; + font-size: 16px; + } + .price { + color: #f56c6c; + font-size: 18px; + margin-left: 8px; + } \ No newline at end of file diff --git a/src/frontend/src/components/cards/product_card.vue b/src/frontend/src/components/cards/product_card.vue index 8192440..e25fb87 100644 --- a/src/frontend/src/components/cards/product_card.vue +++ b/src/frontend/src/components/cards/product_card.vue @@ -34,6 +34,7 @@ function goDetail() { height: 100%; display: flex; flex-direction: column; + border: 1px solid #e5e6eb; /* 新增边框 */ } .card:hover { box-shadow: 0 2px 12px rgb(0 0 0 / 8%); diff --git a/src/frontend/src/components/cards/shop_card.vue b/src/frontend/src/components/cards/shop_card.vue new file mode 100644 index 0000000..e69de29 diff --git a/src/frontend/src/components/cards/user_info.vue b/src/frontend/src/components/cards/user_info.vue index 787d18f..8f78d54 100644 --- a/src/frontend/src/components/cards/user_info.vue +++ b/src/frontend/src/components/cards/user_info.vue @@ -23,13 +23,13 @@ - + - \ No newline at end of file diff --git a/src/frontend/src/router/index.js b/src/frontend/src/router/index.js index 8650976..2292692 100644 --- a/src/frontend/src/router/index.js +++ b/src/frontend/src/router/index.js @@ -39,7 +39,12 @@ const router = createRouter({ path: '/explore', name: 'Explore', component: () => import('../views/Explore.vue') - } + }, + { + path: '/payment/:id', + name: 'Payment', + component: () => import('../views/Payment.vue') + }, ], }) diff --git a/src/frontend/src/views/Login.vue b/src/frontend/src/views/Login.vue index b84c133..2624ad8 100644 --- a/src/frontend/src/views/Login.vue +++ b/src/frontend/src/views/Login.vue @@ -97,8 +97,6 @@ import { ElMessage } from 'element-plus' import axios from 'axios' import { useRouter } from 'vue-router' -// 全局 baseURL(放最上面,只执行一次) -axios.defaults.baseURL = 'http://127.0.0.1:8000/api/v1' const router = useRouter() const activeTab = ref('login') diff --git a/src/frontend/src/views/Payment.vue b/src/frontend/src/views/Payment.vue new file mode 100644 index 0000000..7bae963 --- /dev/null +++ b/src/frontend/src/views/Payment.vue @@ -0,0 +1,214 @@ + + + + + diff --git a/src/frontend/src/views/ProductDetail.vue b/src/frontend/src/views/ProductDetail.vue index 4365588..fa09a13 100644 --- a/src/frontend/src/views/ProductDetail.vue +++ b/src/frontend/src/views/ProductDetail.vue @@ -10,7 +10,7 @@ const productId = route.params.product_id const product = ref(null) const loading = ref(true) const error = ref('') -axios.defaults.baseURL = 'http://127.0.1:8000/api/v1' + onMounted(async () => { try { @@ -77,6 +77,7 @@ const handleAddToCart = (qty: number) => { From ed0dcc9079ca638072bdae7b93a31553c969f762 Mon Sep 17 00:00:00 2001 From: Renyye <1457077123@qq.com> Date: Wed, 21 May 2025 12:33:43 +0800 Subject: [PATCH 06/16] =?UTF-8?q?feat(frontend):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=95=86=E5=BA=97=E5=88=97=E8=A1=A8=E3=80=81=E5=95=86=E5=BA=97?= =?UTF-8?q?=E8=AF=A6=E6=83=85=E5=92=8C=E5=95=86=E5=BA=97=E5=88=86=E7=B1=BB?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=9B=B4=E6=96=B0=E5=AF=BC=E8=88=AA?= =?UTF-8?q?=E5=92=8C=E5=95=86=E5=BA=97=E5=8D=A1=E7=89=87=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/api/store.ts | 25 ++ .../src/components/cards/store_card.vue | 130 +++++++++ .../src/components/layout/NaviBar.vue | 2 +- src/frontend/src/router/index.js | 6 + src/frontend/src/views/Stores.vue | 250 ++++++++++++++++++ 5 files changed, 412 insertions(+), 1 deletion(-) create mode 100644 src/frontend/src/api/store.ts create mode 100644 src/frontend/src/components/cards/store_card.vue create mode 100644 src/frontend/src/views/Stores.vue diff --git a/src/frontend/src/api/store.ts b/src/frontend/src/api/store.ts new file mode 100644 index 0000000..54e2211 --- /dev/null +++ b/src/frontend/src/api/store.ts @@ -0,0 +1,25 @@ +import axios from 'axios' + +interface StoreParams { + page?: number + pageSize?: number + category?: string + search?: string + sortBy?: string +} + +/** 获取商店列表 */ +export const fetchStores = (params: StoreParams = {}) => { + // 此处仅示意,实际API接口待实现 + return axios.get('/api/stores', { params }) +} + +/** 获取商店详情 */ +export const fetchStoreDetail = (storeId: number) => { + return axios.get(`/api/stores/${storeId}`) +} + +/** 获取商店分类 */ +export const fetchStoreCategories = () => { + return axios.get('/api/store-categories') +} diff --git a/src/frontend/src/components/cards/store_card.vue b/src/frontend/src/components/cards/store_card.vue new file mode 100644 index 0000000..768b450 --- /dev/null +++ b/src/frontend/src/components/cards/store_card.vue @@ -0,0 +1,130 @@ + + + + + diff --git a/src/frontend/src/components/layout/NaviBar.vue b/src/frontend/src/components/layout/NaviBar.vue index a965b27..65e4e47 100644 --- a/src/frontend/src/components/layout/NaviBar.vue +++ b/src/frontend/src/components/layout/NaviBar.vue @@ -37,7 +37,7 @@ const handleUserClick = () => {