consumer模块完成度95%,安卓端大部分页面能正常获取数据,页面样式显示基本正常,逐渐完善;消费者端的积分、余额、评价、优惠券等小模块正在完善

This commit is contained in:
cyh666666
2026-03-02 17:21:19 +08:00
parent df84fd8642
commit 7e74b88e1e
34 changed files with 17088 additions and 1751 deletions

View File

@@ -25,19 +25,24 @@
</view>
</view>
<!-- 导航栏占位 - 修复只使用44px高度因为search-bar的paddingTop已处理statusBarHeight -->
<view class="navbar-placeholder" :style="{ height: '44px' }"></view>
<!-- 导航栏占位 - 需要包含statusBarHeight + 搜索框高度44px -->
<view class="navbar-placeholder" :style="{ height: (statusBarHeight + 44) + 'px' }"></view>
<!-- 分类内容区 -->
<view class="category-content">
<!-- 左侧一级分类 -->
<scroll-view scroll-y class="primary-category">
<scroll-view
:scroll-y="true"
class="primary-category"
:scroll-top="scrollTop"
:scroll-with-animation="true"
>
<view
v-for="item in primaryCategories"
:key="item.id"
:class="['primary-item', { active: activePrimary === item.id }]"
:class="['primary-item', { active: isPrimaryActive(item.id) }]"
@click="selectPrimaryCategory(item.id)"
:style="{ backgroundColor: activePrimary === item.id ? item.color : 'transparent' }"
:style="{ backgroundColor: getPrimaryItemBgColor(item) }"
>
<text class="primary-icon">{{ item.icon }}</text>
<text class="primary-name">{{ item.name }}</text>
@@ -46,7 +51,7 @@
<!-- 右侧商品列表 -->
<scroll-view
scroll-y
:scroll-y="true"
class="product-content"
@scrolltolower="loadMore"
:lower-threshold="50"
@@ -57,6 +62,21 @@
<text class="category-desc">{{ currentCategoryDesc }}</text>
</view>
<!-- 二级分类 -->
<view v-if="subCategories.length > 0" class="sub-category-section">
<view class="sub-category-list">
<view
v-for="sub in subCategories"
:key="sub.id"
:class="['sub-category-item', { active: isSubActive(sub.id) }]"
@click="selectSubCategory(sub.id)"
>
<text class="sub-category-icon">{{ sub.icon }}</text>
<text class="sub-category-name">{{ sub.name }}</text>
</view>
</view>
</view>
<!-- 商品网格 -->
<view v-if="productList.length > 0" class="product-grid">
<view
@@ -98,6 +118,7 @@
<script setup lang="uts">
import { ref, onMounted } from 'vue'
import { onLoad, onShow } from '@dcloudio/uni-app'
import supabaseService from '@/utils/supabaseService.uts'
import type { Product } from '@/utils/supabaseService.uts'
@@ -111,15 +132,20 @@ type LocalCategory = {
// 响应式数据
const statusBarHeight = ref(0)
const headerHeight = ref(44) // 默认头部高度
const headerHeight = ref(44)
const primaryCategories = ref<LocalCategory[]>([])
const subCategories = ref<LocalCategory[]>([]) // 二级分类列表
const productList = ref<Product[]>([])
const activePrimary = ref<string>('')
const activeSubCategory = ref<string>('') // 当前选中的二级分类
const selectedParentId = ref<string>('') // 当前选中的一级分类ID用于高亮显示
const cartCount = ref(3)
const hasMore = ref(true)
const hasLoadedFromParams = ref(false) // 标记是否已通过参数加载
const hasLoadedFromParams = ref(false)
const currentPage = ref(1)
const loading = ref(false)
const scrollTop = ref(0)
const pendingCategoryId = ref('') // 待处理的分类ID从其他页面跳转过来时暂存
// 获取当前分类信息
const currentCategoryName = ref('')
@@ -147,7 +173,7 @@ async function loadProducts(): Promise<void> {
page: currentPage.value
})
if (currentPage.value === 1) {
if (currentPage.value == 1) {
productList.value = response.data
} else {
productList.value.push(...response.data)
@@ -155,75 +181,303 @@ async function loadProducts(): Promise<void> {
hasMore.value = response.hasmore
// 更新当前分类信息
const category = primaryCategories.value.find((cat: LocalCategory): boolean => cat.id === activePrimary.value)
if (category != null) {
currentCategoryName.value = category.name
currentCategoryDesc.value = category.description
// 更新当前分类信息 - 先在一级分类中查找,再在二级分类中查找
let foundCat: LocalCategory | null = null
for (let i = 0; i < primaryCategories.value.length; i++) {
if (primaryCategories.value[i].id == activePrimary.value) {
foundCat = primaryCategories.value[i]
break
}
}
if (foundCat == null) {
for (let i = 0; i < subCategories.value.length; i++) {
if (subCategories.value[i].id == activePrimary.value) {
foundCat = subCategories.value[i]
break
}
}
}
if (foundCat != null) {
currentCategoryName.value = foundCat.name
currentCategoryDesc.value = foundCat.description
}
console.log('商品列表加载完成,当前总数量:', productList.value.length)
} catch (error) {
console.error('加载商品数据失败:', error)
if (currentPage.value === 1) {
if (currentPage.value == 1) {
productList.value = []
}
} finally {
loading.value = false
loading.value = false
}
}
// 加载二级分类
async function loadSubCategories(parentId: string): Promise<void> {
console.log('加载二级分类父级ID:', parentId)
try {
const subCats = await supabaseService.getSubCategories(parentId)
console.log('获取到二级分类数量:', subCats.length)
const categories: LocalCategory[] = []
for (let i = 0; i < subCats.length; i++) {
const cat = subCats[i]
categories.push({
id: cat.id,
name: cat.name,
icon: cat.icon,
description: cat.description,
color: cat.color
})
}
subCategories.value = categories
} catch (e) {
console.error('加载二级分类失败:', e)
subCategories.value = []
}
}
// 判断一级分类是否选中
function isPrimaryActive(categoryId: string): boolean {
return selectedParentId.value == categoryId
}
// 判断二级分类是否选中
function isSubActive(subCategoryId: string): boolean {
return activeSubCategory.value == subCategoryId || activePrimary.value == subCategoryId
}
// 获取一级分类的背景色
function getPrimaryItemBgColor(item: LocalCategory): string {
if (isPrimaryActive(item.id)) {
return item.color
}
return 'transparent'
}
// 选择二级分类
async function selectSubCategory(subCategoryId: string): Promise<void> {
console.log('选择二级分类:', subCategoryId)
activeSubCategory.value = subCategoryId
// 使用二级分类ID加载商品
currentPage.value = 1
hasMore.value = true
activePrimary.value = subCategoryId // 临时设置为二级分类ID用于加载商品
await loadProducts()
}
// 选择一级分类 - 必须在 loadCategories 之前定义
// originalCategoryId: 可能是一级分类ID也可能是二级分类ID
async function selectPrimaryCategory(originalCategoryId: string): Promise<void> {
console.log('=== selectPrimaryCategory函数开始执行 ===')
console.log('传入的categoryId:', originalCategoryId)
if (originalCategoryId == '') {
console.error('categoryId为空尝试使用第一个分类')
if (primaryCategories.value.length > 0) {
originalCategoryId = primaryCategories.value[0].id
} else {
console.error('没有可用的分类')
return
}
}
// 检查传入的是否是一级分类ID
let targetParentId = originalCategoryId
let targetSubId = ''
console.log('当前一级分类列表长度:', primaryCategories.value.length)
let foundInPrimary: LocalCategory | null = null
for (let i = 0; i < primaryCategories.value.length; i++) {
if (primaryCategories.value[i].id == originalCategoryId) {
foundInPrimary = primaryCategories.value[i]
break
}
}
console.log('在一级分类中查找结果:', foundInPrimary != null)
if (foundInPrimary == null) {
// 传入的可能是二级分类ID需要查找其父级分类
console.log('传入的ID不在一级分类中可能是二级分类ID尝试查找父级分类')
// 从服务器获取分类信息以确定父级
try {
const categoryInfo = await supabaseService.getCategoryById(originalCategoryId)
if (categoryInfo != null && categoryInfo.parent_id != null && categoryInfo.parent_id != '') {
console.log('找到父级分类ID:', categoryInfo.parent_id)
// 检查父级分类ID是否在一级分类列表中
console.log('查找父级分类ID:', categoryInfo.parent_id)
let parentInPrimary: LocalCategory | null = null
for (let i = 0; i < primaryCategories.value.length; i++) {
if (primaryCategories.value[i].id == categoryInfo.parent_id) {
parentInPrimary = primaryCategories.value[i]
break
}
}
console.log('父级分类查找结果:', parentInPrimary != null)
if (parentInPrimary != null) {
console.log('父级分类在列表中找到:', parentInPrimary.name)
targetParentId = categoryInfo.parent_id!
targetSubId = originalCategoryId // 记住要选中的二级分类
} else {
console.log('父级分类不在列表中,使用第一个分类')
// 打印当前列表中的所有分类ID
for (let i = 0; i < primaryCategories.value.length; i++) {
console.log('列表中的分类:', primaryCategories.value[i].id, primaryCategories.value[i].name)
}
if (primaryCategories.value.length > 0) {
targetParentId = primaryCategories.value[0].id
}
}
} else {
console.log('未找到父级分类,使用第一个分类')
if (primaryCategories.value.length > 0) {
targetParentId = primaryCategories.value[0].id
}
}
} catch (e) {
console.error('获取分类信息失败:', e)
if (primaryCategories.value.length > 0) {
targetParentId = primaryCategories.value[0].id
}
}
}
console.log('最终选中的一级分类ID:', targetParentId)
console.log('需要选中的二级分类ID:', targetSubId)
// 设置一级分类高亮
selectedParentId.value = targetParentId
activePrimary.value = targetParentId
// 加载二级分类
await loadSubCategories(targetParentId)
// 如果有要选中的二级分类
if (targetSubId != '') {
activeSubCategory.value = targetSubId
} else {
// 如果没有指定二级分类,但有二级分类列表,默认选中第一个
if (subCategories.value.length > 0) {
activeSubCategory.value = subCategories.value[0].id
targetSubId = subCategories.value[0].id
console.log('默认选中第一个二级分类:', subCategories.value[0].name)
} else {
activeSubCategory.value = ''
}
}
// 自动滚动到选中位置
let foundIndex = -1
for (let i = 0; i < primaryCategories.value.length; i++) {
if (primaryCategories.value[i].id == targetParentId) {
foundIndex = i
break
}
}
if (foundIndex != -1) {
// 获取系统信息
const systemInfo = uni.getSystemInfoSync()
let itemHeight = 70
if (systemInfo.windowWidth > 1025) {
itemHeight = 80
}
const scrollViewHeight = systemInfo.windowHeight - systemInfo.statusBarHeight - 44
const targetScrollTop = (foundIndex * itemHeight) - (scrollViewHeight / 2) + (itemHeight / 2)
scrollTop.value = Math.max(0, targetScrollTop)
console.log(`滚动左侧菜单: index=${foundIndex}, target=${scrollTop.value}`)
}
// 查找分类信息
let foundCategory: LocalCategory | null = null
for (let i = 0; i < primaryCategories.value.length; i++) {
if (primaryCategories.value[i].id == targetParentId) {
foundCategory = primaryCategories.value[i]
break
}
}
if (foundCategory != null) {
currentCategoryName.value = foundCategory.name
currentCategoryDesc.value = foundCategory.description
} else {
console.log('分类信息未找到,使用第一个分类的信息')
if (primaryCategories.value.length > 0) {
const firstCategory = primaryCategories.value[0]
currentCategoryName.value = firstCategory.name
currentCategoryDesc.value = firstCategory.description
}
}
currentPage.value = 1
hasMore.value = true
// 如果有选中的二级分类使用二级分类ID加载商品否则使用一级分类ID
const categoryIdForProducts = (targetSubId != '') ? targetSubId : targetParentId
activePrimary.value = categoryIdForProducts // 临时设置为要加载的分类ID
await loadProducts()
}
async function loadCategories(): Promise<void> {
try {
const categoriesData = await supabaseService.getCategories()
console.log('加载分类数据成功,数量:', categoriesData.length)
// 只获取一级分类parent_id 为 null 的分类)
const categoriesData = await supabaseService.getParentCategories()
console.log('加载一级分类数据成功,数量:', categoriesData.length)
// 映射数据并添加默认颜色,防止选中时背景透明导致文字看不清
// 过滤掉医药健康相关分类
const categories: LocalCategory[] = []
const rawList = categoriesData as any[]
for (let i = 0; i < rawList.length; i++) {
const raw = rawList[i]
const catObj = (raw instanceof UTSJSONObject) ? (raw as UTSJSONObject) : (JSON.parse(JSON.stringify(raw)) as UTSJSONObject)
const name = catObj.getString('name') ?? ''
for (let i = 0; i < categoriesData.length; i++) {
const cat = categoriesData[i]
const name = cat.name
console.log('一级分类:', cat.id, name)
if (name.includes('医药') || name.includes('健康')) {
console.log('过滤掉分类:', name)
continue
}
const id = catObj.getString('id') ?? ''
const description = catObj.getString('description') ?? ''
const icon = catObj.getString('icon') ?? catObj.getString('icon_url') ?? '📦'
const color = catObj.getString('color') ?? '#4CAF50'
categories.push({
id,
name,
icon,
description,
color
id: cat.id,
name: cat.name,
icon: cat.icon,
description: cat.description,
color: cat.color
})
}
console.log('最终一级分类列表数量:', categories.length)
if (categories.length > 0) {
primaryCategories.value = categories
// 如果没有通过参数设置分类,则设置默认选中一个分类
if (activePrimary.value == '') {
// 优先查找"厨具"相关的分类作为默认
const defaultCategory = categories.find((c: LocalCategory): boolean => c.name.includes('厨具')) ?? categories[0]
activePrimary.value = defaultCategory.id
console.log('设置默认分类为:', defaultCategory.name, 'ID:', defaultCategory.id)
currentCategoryName.value = defaultCategory.name
currentCategoryDesc.value = defaultCategory.description
} else {
// 如果已经选中了分类可能来自Storage更新显示信息
const current = categories.find((c: LocalCategory): boolean => c.id == activePrimary.value)
if (current != null) {
currentCategoryName.value = current.name
currentCategoryDesc.value = current.description
// 如果此时没有商品列表(且没有正在加载),可能需要加载
if (productList.value.length === 0 && !loading.value) {
loadProducts()
}
}
// 检查是否有待处理的分类ID从其他页面跳转过来时暂存
if (pendingCategoryId.value != '') {
console.log('发现待处理的分类ID:', pendingCategoryId.value)
// 直接调用 selectPrimaryCategory它会处理一级或二级分类ID
const idToSelect = pendingCategoryId.value
pendingCategoryId.value = '' // 清除暂存
selectPrimaryCategory(idToSelect)
return
}
// 检查是否有预设的分类ID
if (activePrimary.value != '') {
console.log('有预设的分类ID:', activePrimary.value)
const target = categories.find((c: LocalCategory): boolean => c.id == activePrimary.value)
if (target != null) {
console.log('找到目标分类,执行选中:', target.name)
selectPrimaryCategory(activePrimary.value)
return
}
}
// 默认选中第一个分类或"厨具"分类
const defaultCategory = categories.find((c: LocalCategory): boolean => c.name.includes('厨具')) ?? categories[0]
if (defaultCategory != null) {
console.log('设置默认分类:', defaultCategory.name)
selectPrimaryCategory(defaultCategory.id)
}
} else {
console.warn('从Supabase获取的分类数据为空')
@@ -241,71 +495,6 @@ function loadMore(): void {
}
}
// 选择一级分类
async function selectPrimaryCategory(categoryId: string): Promise<void> {
console.log('=== selectPrimaryCategory函数开始执行 ===')
console.log('传入的categoryId:', categoryId)
console.log('当前时间:', Date.now())
// 验证categoryId是否有效
if (categoryId == '') {
console.error('categoryId为空尝试使用第一个分类')
if (primaryCategories.value.length > 0) {
categoryId = primaryCategories.value[0].id
} else {
console.error('没有可用的分类')
return
}
}
console.log('验证后的categoryId:', categoryId)
console.log('当前activePrimary的值:', activePrimary.value)
// 更新活动分类
activePrimary.value = categoryId
console.log('更新后的activePrimary:', activePrimary.value)
// 更新当前分类信息
const category = primaryCategories.value.find((cat: LocalCategory): boolean => cat.id === categoryId)
if (category != null) {
currentCategoryName.value = category.name
currentCategoryDesc.value = category.description
console.log('✅ 找到分类:', category.name, '描述:', category.description)
} else {
console.error('❌ 未找到分类ID:', categoryId, ',使用第一个分类')
// 如果找不到对应的分类,使用第一个分类
if (primaryCategories.value.length > 0) {
const firstCategory = primaryCategories.value[0]
currentCategoryName.value = firstCategory.name
currentCategoryDesc.value = firstCategory.description
activePrimary.value = firstCategory.id
categoryId = firstCategory.id
console.log('使用默认分类:', firstCategory.name)
}
}
console.log('准备加载商品数据...')
// 重置分页并加载
currentPage.value = 1
hasMore.value = true
await loadProducts()
console.log('✅ 加载商品数据成功')
console.log('分类:', categoryId)
console.log('商品数量:', productList.value.length)
console.log('商品列表:', productList.value)
// 验证数据是否已正确更新
console.log('数据更新验证:')
console.log('activePrimary:', activePrimary.value)
console.log('currentCategoryName:', currentCategoryName.value)
console.log('currentCategoryDesc:', currentCategoryDesc.value)
console.log('productList长度:', productList.value.length)
console.log('=== selectPrimaryCategory函数执行完成 ===')
}
// 生命周期
onMounted(() => {
loadCategories().then(() => {
@@ -317,12 +506,42 @@ onMounted(() => {
})
})
// 页面加载时处理参数 - 这是处理分类切换的主要入口
// 页面显示时检查是否有参数传递过来
onShow(() => {
console.log('=== category页面onShow被调用 ===')
// 检查是否有存储的分类选择
const savedCategoryId = uni.getStorageSync('selectedCategory')
console.log('onShow检查Storage:', savedCategoryId)
if (savedCategoryId != null && savedCategoryId != '') {
const targetId = savedCategoryId as string
console.log('onShow发现存储的分类ID:', targetId)
// 清除存储,避免下次进入默认选中
uni.removeStorageSync('selectedCategory')
// 确保分类数据已加载
if (primaryCategories.value.length > 0) {
// 如果当前未选中或选中的不是目标分类,则切换
if (activePrimary.value != targetId) {
console.log('onShow执行切换分类:', targetId)
selectPrimaryCategory(targetId)
} else {
console.log('当前已是目标分类:', targetId)
}
} else {
// 如果分类数据未加载暂存ID等待loadCategories完成后处理
console.log('分类数据尚未加载暂存ID等待加载')
pendingCategoryId.value = targetId
}
}
})
// 页面加载时处理参数 - 这是处理分类切换的主要入口
onLoad((options: any) => {
console.log('=== category页面onLoad被调用 ===')
console.log('页面加载时间:', Date.now())
console.log('传入的options参数:', options)
console.log('当前活动分类:', activePrimary.value)
const systemInfo = uni.getSystemInfoSync()
statusBarHeight.value = systemInfo.statusBarHeight
console.log('=== category页面onLoad被调用 ===')
let categoryId = ''
let categoryName = ''
@@ -381,72 +600,6 @@ onLoad((options: any) => {
console.log('=== category页面onLoad执行完成 ===')
})
// 页面显示时也检查参数,确保从其他页面返回时能正确显示
onShow(() => {
console.log('=== category页面onShow被调用 ===')
console.log('页面显示时间:', Date.now())
console.log('当前活动分类:', activePrimary.value)
// 1. 优先检查 Storage 中的参数 (由首页传入)
const storageCategoryId = (uni.getStorageSync('selectedCategory') as string) ?? ''
if (storageCategoryId !== '') {
console.log('✅ onShow中找到Storage分类参数:', storageCategoryId)
hasLoadedFromParams.value = true
// 清除Storage防止下次误读
uni.removeStorageSync('selectedCategory')
if (activePrimary.value !== storageCategoryId) {
selectPrimaryCategory(storageCategoryId)
}
// 如果分类还没加载完这里设置了ID等loadCategories完成后会自动匹配信息
return
}
// 在onShow中我们也需要检查是否有新的参数
// 因为当从主页再次点击分类跳转过来时可能不会触发onLoad
// 而是触发onShow
// 获取当前页面实例和参数
const pages = getCurrentPages()
if (pages.length > 0) {
const currentPage = pages[pages.length - 1]
const rawPageOptions = currentPage.options ?? {}
console.log('onShow中获取参数:', rawPageOptions)
const pageOptObj = (rawPageOptions instanceof UTSJSONObject) ? (rawPageOptions as UTSJSONObject) : (JSON.parse(JSON.stringify(rawPageOptions)) as UTSJSONObject)
// 检查是否有分类参数
const pageCategoryId = pageOptObj.getString('categoryId') ?? ''
if (pageCategoryId !== '') {
hasLoadedFromParams.value = true
const categoryId = pageCategoryId
const categoryName = pageOptObj.getString('name') ?? ''
console.log('✅ onShow中找到分类参数:', categoryId, categoryName)
console.log('URL中的时间戳参数:', pageOptObj.getString('timestamp') ?? '')
console.log('URL中的随机参数:', pageOptObj.getString('random') ?? '')
// 检查是否需要更新分类
if (activePrimary.value !== categoryId) {
console.log('当前分类:', activePrimary.value, '与目标分类:', categoryId, '不同,需要更新')
console.log('准备调用selectPrimaryCategory函数...')
selectPrimaryCategory(categoryId)
} else {
console.log('当前分类已经是目标分类,但可能用户想要刷新页面')
console.log('当前分类:', activePrimary.value, '目标分类:', categoryId)
// 即使分类相同,也重新加载数据,确保数据是最新的
// 添加一个小的延迟,确保页面完全显示后再更新数据
setTimeout(() => {
selectPrimaryCategory(categoryId)
}, 100)
}
} else {
console.log('⚠️ onShow中未找到分类参数')
}
}
console.log('=== category页面onShow执行完成 ===')
})
// 添加到购物车
async function addToCart(product: Product): Promise<void> {
@@ -574,7 +727,7 @@ function onScan(): void {
top: 0;
left: 0;
right: 0;
background: linear-gradient(135deg, #4CAF50 0%, #2E7D32 100%);
background-color: #4CAF50;
z-index: 1000;
box-shadow: 0 2px 12px rgba(76, 175, 80, 0.15);
}
@@ -714,32 +867,31 @@ function onScan(): void {
/* 左侧一级分类 */
.primary-category {
width: 120px;
height: 100%; /* 占满父容器高度 */
margin-right: 20px; /* gap replacement */
width: 63px;
height: 100%;
margin-right: 6px;
background: white;
border-radius: 12px;
padding: 12px 0;
border-radius: 8px;
padding: 6px 0;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
flex-shrink: 0;
}
.primary-item {
display: flex;
flex-direction: column; /* 图标和文字垂直排列 */
flex-direction: column;
align-items: center;
justify-content: center;
padding: 12px 8px;
margin: 4px 8px;
padding: 12px 4px;
margin: 4px 6px;
border-radius: 8px;
/* cursor: pointer; removed for uniapp-x support */
transition: all 0.2s ease;
color: #666;
text-align: center;
}
.primary-item:hover {
transform: translateY(-2px); /* 悬停时向上浮动 */
transform: translateY(-2px);
}
.primary-item.active {
@@ -748,24 +900,22 @@ function onScan(): void {
}
.primary-icon {
font-size: 24px;
margin-bottom: 6px;
margin-right: 0; /* 移除右边距 */
font-size: 20px;
margin-bottom: 4px;
margin-right: 0;
text-align: center;
/* display: block; removed for uniapp-x support */
}
.primary-name {
font-size: 13px;
line-height: 1.4;
/* display: block; removed for uniapp-x support */
font-size: 11px;
line-height: 1.25;
}
/* 右侧内容区 */
.product-content {
flex: 1;
height: 100%; /* 占满父容器高度 */
padding: 0; /* 移除内边距,交给内部元素 */
height: 100%;
padding: 0;
}
.category-header {
@@ -789,6 +939,56 @@ function onScan(): void {
color: #666;
}
/* 二级分类 */
.sub-category-section {
padding: 8px 8px;
background: white;
margin-bottom: 8px;
}
.sub-category-list {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
width: 100%;
justify-content: space-between;
}
.sub-category-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 8px 4px;
background: #f5f5f5;
border-radius: 8px;
flex: 1;
min-width: 50px;
}
.sub-category-item.active {
background: #4CAF50;
}
.sub-category-item.active .sub-category-name {
color: white;
}
.sub-category-icon {
font-size: 16px;
margin-bottom: 4px;
}
.sub-category-name {
font-size: 11px;
color: #333;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: center;
width: 100%;
}
/* 商品网格 */
.product-grid {
display: flex;
@@ -954,52 +1154,47 @@ function onScan(): void {
}
.category-content {
padding: 0 8px;
padding: 0 4px;
}
.primary-category {
width: 80px; /* 减小宽度 */
/* display: flex; 移除flex布局保持默认 */
/* flex-wrap: wrap; 移除换行 */
padding: 8px 0;
margin-right: 10px; /* Gap replacement */
width: 56px;
padding: 4px 0;
margin-right: 4px;
border-radius: 8px;
}
.primary-item {
/* width: calc(25% - 8px); 移除百分比宽度 */
width: auto; /* 恢复自动宽度 */
margin: 4px;
padding: 8px 4px;
/* text-align: center; 已经在通用样式中设置 */
margin: 2px 2px;
padding: 4px 2px;
border-radius: 6px;
}
.primary-icon {
margin-right: 0;
margin-bottom: 4px;
font-size: 20px;
margin-bottom: 2px;
font-size: 16px;
}
.primary-name {
font-size: 11px;
font-size: 9px;
line-height: 1.1;
}
.product-grid {
/* grid-template-columns: repeat(2, 1fr); REMOVED */
/* gap: 8px; REMOVED */
padding: 0 4px 20px 4px; /* 增加底部内边距 */
padding: 0 4px 20px 4px;
}
.product-card {
width: 48%; /* 2 columns for mobile */
width: 48%;
margin: 1%;
}
/* 手机端商品卡片极简模式 - 仿照主页样式 */
.product-spec,
.manufacturer,
.original-price,
.sales-info,
.product-badge { /* 分类页也隐藏角标,保持整洁 */
.product-badge {
display: none;
}
@@ -1008,7 +1203,7 @@ function onScan(): void {
}
.product-image {
height: 100px; /* 由于分类页右侧空间更窄,图片高度设得更小一点 */
height: 100px;
}
.product-name {
@@ -1018,10 +1213,7 @@ function onScan(): void {
margin-bottom: 2px;
overflow: hidden;
text-overflow: ellipsis;
/* display: -webkit-box; REMOVED for support */
/* -webkit-line-clamp: 2; REMOVED for support */
/* -webkit-box-orient: vertical; REMOVED for support */
lines: 2; /* UTS text truncation */
lines: 2;
}
.price-section {
@@ -1040,30 +1232,52 @@ function onScan(): void {
}
.product-meta {
display: none; /* 隐藏整个元数据行 */
}
.search-container {
padding: 0 12px;
height: 44px;
}
.search-box {
padding: 8px 16px;
display: none;
}
.category-header {
padding: 12px 4px 0 4px;
padding: 8px 4px 0 4px;
}
.category-title {
font-size: 14px;
}
.category-desc {
font-size: 11px;
}
}
/* 中屏手机/小平板 (415px-768px) */
/* 中屏手机 (415px-768px) */
@media screen and (min-width: 415px) and (max-width: 768px) {
.search-container {
padding: 0 16px;
height: 44px;
}
.primary-category {
width: 62px;
padding: 6px 0;
margin-right: 6px;
border-radius: 8px;
}
.primary-item {
margin: 2px 2px;
padding: 5px 2px;
border-radius: 6px;
}
.primary-icon {
font-size: 18px;
margin-bottom: 3px;
}
.primary-name {
font-size: 10px;
line-height: 1.1;
}
.product-card {
width: 46%;
margin: 2%;
@@ -1077,6 +1291,26 @@ function onScan(): void {
height: 44px;
}
.primary-category {
width: 100px;
padding: 10px 0;
margin-right: 16px;
}
.primary-item {
margin: 4px 4px;
padding: 10px 6px;
}
.primary-icon {
font-size: 22px;
margin-bottom: 5px;
}
.primary-name {
font-size: 12px;
}
.product-card {
width: 30%;
margin: 1.5%;
@@ -1097,7 +1331,7 @@ function onScan(): void {
.primary-category {
width: 160px;
padding: 16px 0;
margin-right: 30px; /* Gap replacement */
margin-right: 30px;
}
.primary-item {
@@ -1132,14 +1366,9 @@ function onScan(): void {
font-size: 15px;
}
.product-grid {
/* grid-template-columns: repeat(4, 1fr); REMOVED */
/* gap: 24px; REMOVED */
}
.product-card {
border-radius: 14px;
width: 22%; /* 4 columns */
width: 22%;
margin: 1.5%;
}
@@ -1164,12 +1393,11 @@ function onScan(): void {
@media screen and (min-width: 1400px) {
.category-content {
max-width: 1600px;
/* gap: 40px; REMOVED */
padding: 0 32px;
}
.primary-category {
margin-right: 40px; /* Gap replacement */
margin-right: 40px;
}
.primary-category {
@@ -1209,14 +1437,9 @@ function onScan(): void {
font-size: 16px;
}
.product-grid {
/* grid-template-columns: repeat(5, 1fr); REMOVED */
/* gap: 28px; REMOVED */
}
.product-card {
border-radius: 16px;
width: 17%; /* 5 columns */
width: 17%;
margin: 1.5%;
}