feat(store): 新增门店商品管理及订单图片修复
- 门店商品页新增商品新增功能,包括名称、分类、图片、价格、库存等信息录入 - 支持新增商品轮播图上传、删除及表单校验 - 获取当前登录店员门店ID并绑定新增商品,实现门店商品的创建 - 门店订单页修复商品图片字段,调整字段名为模型匹配的image、spec和totalNum - 订单页商品图片添加压缩处理,优化图片展示尺寸与加载速度
This commit is contained in:
@@ -132,6 +132,8 @@ export interface ShopGoods {
|
||||
activityType?: number;
|
||||
// 配送方式:0送上门 1限自提
|
||||
deliveryMode?: number;
|
||||
// 门店ID
|
||||
storeId?: number;
|
||||
}
|
||||
|
||||
export interface BathSet {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import React, { useState, useEffect, useCallback, useRef } from 'react'
|
||||
import { View, Text, Image, ScrollView, Input, Textarea } from '@tarojs/components'
|
||||
import Taro, { useDidShow } from '@tarojs/taro'
|
||||
import { pageShopGoods, updateShopGoods } from '@/api/shop/shopGoods'
|
||||
import { pageShopGoods, updateShopGoods, addShopGoods } from '@/api/shop/shopGoods'
|
||||
import { listShopGoodsCategory } from '@/api/shop/shopGoodsCategory'
|
||||
import { getMyClerk } from '@/api/shop/shopStoreUser'
|
||||
import { uploadFile } from '@/api/system/file'
|
||||
import type { ShopGoods, ShopGoodsParam } from '@/api/shop/shopGoods/model'
|
||||
import type { ShopGoodsCategory } from '@/api/shop/shopGoodsCategory/model'
|
||||
@@ -66,6 +67,28 @@ export default function StoreGoodsPage() {
|
||||
const [uploadingImage, setUploadingImage] = useState(false)
|
||||
const [uploadingBanner, setUploadingBanner] = useState(false)
|
||||
|
||||
// 当前登录店员的门店ID
|
||||
const [storeId, setStoreId] = useState<number | undefined>(undefined)
|
||||
|
||||
// 新增商品弹窗
|
||||
const [showAddModal, setShowAddModal] = useState(false)
|
||||
const [addForm, setAddForm] = useState({
|
||||
name: '',
|
||||
categoryId: undefined as number | undefined,
|
||||
image: '',
|
||||
price: '',
|
||||
salePrice: '',
|
||||
dealerPrice: '',
|
||||
stock: '',
|
||||
sortNumber: '',
|
||||
comments: '',
|
||||
files: [] as Array<{ uid?: number; url: string; status?: string }>,
|
||||
})
|
||||
const [addSubmitting, setAddSubmitting] = useState(false)
|
||||
const [addUploadingImage, setAddUploadingImage] = useState(false)
|
||||
const [addUploadingBanner, setAddUploadingBanner] = useState(false)
|
||||
const [showAddCategoryPicker, setShowAddCategoryPicker] = useState(false)
|
||||
|
||||
const pageSize = 10
|
||||
const loadingRef = useRef(false)
|
||||
|
||||
@@ -113,6 +136,15 @@ export default function StoreGoodsPage() {
|
||||
.catch(() => {})
|
||||
}, [])
|
||||
|
||||
// 获取当前登录店员的门店ID
|
||||
useEffect(() => {
|
||||
getMyClerk()
|
||||
.then(data => {
|
||||
if (data?.storeId) setStoreId(data.storeId)
|
||||
})
|
||||
.catch(() => {})
|
||||
}, [])
|
||||
|
||||
// 切换 tab 时重新加载
|
||||
useEffect(() => {
|
||||
loadGoods(activeTab, 1)
|
||||
@@ -306,6 +338,131 @@ export default function StoreGoodsPage() {
|
||||
}
|
||||
}
|
||||
|
||||
// ─── 新增商品相关 ──────────────────────────────────────────────
|
||||
|
||||
/** 打开新增弹窗 */
|
||||
const openAddModal = () => {
|
||||
setAddForm({
|
||||
name: '',
|
||||
categoryId: undefined,
|
||||
image: '',
|
||||
price: '',
|
||||
salePrice: '',
|
||||
dealerPrice: '',
|
||||
stock: '',
|
||||
sortNumber: '',
|
||||
comments: '',
|
||||
files: [],
|
||||
})
|
||||
setShowAddModal(true)
|
||||
}
|
||||
|
||||
/** 关闭新增弹窗 */
|
||||
const closeAddModal = () => {
|
||||
setShowAddModal(false)
|
||||
}
|
||||
|
||||
/** 上传商品图片(新增) */
|
||||
const handleAddUploadImage = async () => {
|
||||
if (addUploadingImage) return
|
||||
setAddUploadingImage(true)
|
||||
try {
|
||||
const res = await uploadFile()
|
||||
const imageUrl = res.path || ''
|
||||
if (imageUrl) {
|
||||
setAddForm(prev => ({ ...prev, image: imageUrl }))
|
||||
Taro.showToast({ title: '上传成功', icon: 'success' })
|
||||
}
|
||||
} catch (e: any) {
|
||||
Taro.showToast({ title: e.message || '上传失败', icon: 'none' })
|
||||
} finally {
|
||||
setAddUploadingImage(false)
|
||||
}
|
||||
}
|
||||
|
||||
/** 上传轮播图(新增) */
|
||||
const handleAddBanner = async () => {
|
||||
if (addUploadingBanner) return
|
||||
setAddUploadingBanner(true)
|
||||
try {
|
||||
const res = await uploadFile()
|
||||
const imageUrl = res.path || ''
|
||||
if (imageUrl) {
|
||||
setAddForm(prev => ({
|
||||
...prev,
|
||||
files: [...prev.files, { uid: res.id, url: imageUrl, status: 'done' }],
|
||||
}))
|
||||
Taro.showToast({ title: '上传成功', icon: 'success' })
|
||||
}
|
||||
} catch (e: any) {
|
||||
Taro.showToast({ title: e.message || '上传失败', icon: 'none' })
|
||||
} finally {
|
||||
setAddUploadingBanner(false)
|
||||
}
|
||||
}
|
||||
|
||||
/** 删除轮播图(新增) */
|
||||
const handleAddRemoveBanner = (index: number) => {
|
||||
setAddForm(prev => ({
|
||||
...prev,
|
||||
files: prev.files.filter((_, i) => i !== index),
|
||||
}))
|
||||
}
|
||||
|
||||
/** 提交新增商品 */
|
||||
const submitAdd = async () => {
|
||||
if (!addForm.name.trim()) {
|
||||
Taro.showToast({ title: '请输入商品名称', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (!addForm.image) {
|
||||
Taro.showToast({ title: '请上传商品图片', icon: 'none' })
|
||||
return
|
||||
}
|
||||
const price = parseFloat(addForm.price)
|
||||
if (isNaN(price) || price < 0) {
|
||||
Taro.showToast({ title: '请输入有效的到手价', icon: 'none' })
|
||||
return
|
||||
}
|
||||
const stock = parseInt(addForm.stock, 10)
|
||||
if (isNaN(stock) || stock < 0) {
|
||||
Taro.showToast({ title: '请输入有效的库存', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
if (!storeId) {
|
||||
Taro.showToast({ title: '未获取到门店信息,请重试', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
setAddSubmitting(true)
|
||||
try {
|
||||
await addShopGoods({
|
||||
name: addForm.name.trim(),
|
||||
categoryId: addForm.categoryId,
|
||||
image: addForm.image,
|
||||
price: addForm.price,
|
||||
salePrice: addForm.salePrice || undefined,
|
||||
dealerPrice: addForm.dealerPrice || undefined,
|
||||
stock,
|
||||
sortNumber: parseInt(addForm.sortNumber, 10) || 0,
|
||||
comments: addForm.comments || undefined,
|
||||
files: JSON.stringify(addForm.files),
|
||||
storeId,
|
||||
status: 1, // 新增默认待上架
|
||||
recommend: 0,
|
||||
type: 1, // 实物商品
|
||||
})
|
||||
Taro.showToast({ title: '添加成功', icon: 'success' })
|
||||
closeAddModal()
|
||||
loadGoods(activeTab, 1)
|
||||
} catch (e: any) {
|
||||
Taro.showToast({ title: e.message || '添加失败', icon: 'none' })
|
||||
} finally {
|
||||
setAddSubmitting(false)
|
||||
}
|
||||
}
|
||||
|
||||
/** 渲染单个商品卡片 */
|
||||
const renderGoodsCard = (goods: ShopGoods) => {
|
||||
const isSoldOut = (goods.stock ?? 0) <= 0
|
||||
@@ -493,9 +650,18 @@ export default function StoreGoodsPage() {
|
||||
<Text className='text-gray-300 text-xs'>没有更多了</Text>
|
||||
</View>
|
||||
)}
|
||||
<View className='h-6' />
|
||||
<View className='h-20' />
|
||||
</ScrollView>
|
||||
|
||||
{/* 新增商品浮动按钮 */}
|
||||
<View
|
||||
className='fixed right-4 bottom-8 w-14 h-14 rounded-full bg-cyan-500 flex items-center justify-center active:opacity-80'
|
||||
style={{ boxShadow: '0 4px 12px rgba(8, 145, 178, 0.4)' }}
|
||||
onClick={openAddModal}
|
||||
>
|
||||
<Text className='text-white text-3xl leading-none' style={{ marginTop: '-2px' }}>+</Text>
|
||||
</View>
|
||||
|
||||
{/* 分类选择弹窗 */}
|
||||
{showCategoryPicker && (
|
||||
<View className='fixed inset-0 z-50' onClick={() => setShowCategoryPicker(false)}>
|
||||
@@ -672,6 +838,217 @@ export default function StoreGoodsPage() {
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* 新增商品弹窗 */}
|
||||
{showAddModal && (
|
||||
<View className='fixed inset-0 z-50 flex items-end justify-center'>
|
||||
<View className='absolute inset-0 bg-black/50' onClick={closeAddModal} />
|
||||
<View className='relative bg-white rounded-t-2xl w-full px-5 pt-6 pb-10 max-h-[85vh] overflow-y-auto'>
|
||||
<Text className='text-lg font-medium text-gray-800 text-center mb-5 block'>新增商品</Text>
|
||||
|
||||
{/* 商品图片 */}
|
||||
<View className='mb-4'>
|
||||
<Text className='text-sm text-gray-600 mb-2 block'>商品图片 <Text className='text-red-500'>*</Text></Text>
|
||||
<View className='relative w-20 h-20' onClick={handleAddUploadImage}>
|
||||
{addForm.image ? (
|
||||
<Image className='w-20 h-20 rounded-lg' src={getCompressedImageUrl(addForm.image)} mode='aspectFill' />
|
||||
) : (
|
||||
<View className='w-20 h-20 rounded-lg bg-gray-100 flex items-center justify-center'>
|
||||
<Text className='text-2xl text-gray-300'>📷</Text>
|
||||
</View>
|
||||
)}
|
||||
<View className='absolute inset-0 rounded-lg bg-black/30 flex items-center justify-center'>
|
||||
<Text className='text-white text-xs'>
|
||||
{addUploadingImage ? '上传中...' : '上传'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 商品名称 */}
|
||||
<View className='mb-4'>
|
||||
<Text className='text-sm text-gray-600 mb-2 block'>商品名称 <Text className='text-red-500'>*</Text></Text>
|
||||
<Input
|
||||
className='bg-gray-50 rounded-lg px-4 py-3 text-sm'
|
||||
placeholder='请输入商品名称'
|
||||
value={addForm.name}
|
||||
onInput={(e) => setAddForm(prev => ({ ...prev, name: e.detail.value }))}
|
||||
maxlength={100}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* 商品分类 */}
|
||||
<View className='mb-4'>
|
||||
<Text className='text-sm text-gray-600 mb-2 block'>商品分类</Text>
|
||||
<View
|
||||
className='bg-gray-50 rounded-lg px-4 py-3 flex items-center justify-between'
|
||||
onClick={() => setShowAddCategoryPicker(true)}
|
||||
>
|
||||
<Text className={`text-sm ${addForm.categoryId ? 'text-gray-800' : 'text-gray-400'}`}>
|
||||
{addForm.categoryId
|
||||
? categories.find(c => c.categoryId === addForm.categoryId)?.title || '选择分类'
|
||||
: '选择分类(选填)'}
|
||||
</Text>
|
||||
<Text className='text-gray-400 text-xs'>▾</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 轮播图 */}
|
||||
<View className='mb-5'>
|
||||
<Text className='text-sm text-gray-600 mb-2 block'>轮播图</Text>
|
||||
<View className='flex flex-wrap gap-3'>
|
||||
{addForm.files.map((file, index) => (
|
||||
<View key={file.url + index} className='relative w-20 h-20'>
|
||||
<Image className='w-20 h-20 rounded-lg bg-gray-100' src={getCompressedImageUrl(file.url)} mode='aspectFill' />
|
||||
<View
|
||||
className='absolute -top-1.5 -right-1.5 w-5 h-5 bg-red-500 rounded-full flex items-center justify-center'
|
||||
onClick={() => handleAddRemoveBanner(index)}
|
||||
>
|
||||
<Text className='text-white text-xs'>×</Text>
|
||||
</View>
|
||||
</View>
|
||||
))}
|
||||
<View
|
||||
className='w-20 h-20 rounded-lg border border-dashed border-gray-300 flex flex-col items-center justify-center'
|
||||
onClick={handleAddBanner}
|
||||
>
|
||||
<Text className='text-2xl text-gray-300 mb-0.5'>{addUploadingBanner ? '...' : '+'}</Text>
|
||||
<Text className='text-xs text-gray-400'>{addUploadingBanner ? '上传中' : '上传'}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 到手价 */}
|
||||
<View className='mb-4'>
|
||||
<Text className='text-sm text-gray-600 mb-2 block'>到手价 (¥) <Text className='text-red-500'>*</Text></Text>
|
||||
<Input
|
||||
className='bg-gray-50 rounded-lg px-4 py-3 text-sm'
|
||||
type='digit'
|
||||
placeholder='请输入价格'
|
||||
value={addForm.price}
|
||||
onInput={(e) => setAddForm(prev => ({ ...prev, price: e.detail.value }))}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* 市场价 */}
|
||||
<View className='mb-4'>
|
||||
<Text className='text-sm text-gray-600 mb-2 block'>市场价 (¥)</Text>
|
||||
<Input
|
||||
className='bg-gray-50 rounded-lg px-4 py-3 text-sm'
|
||||
type='digit'
|
||||
placeholder='选填,划线价'
|
||||
value={addForm.salePrice}
|
||||
onInput={(e) => setAddForm(prev => ({ ...prev, salePrice: e.detail.value }))}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* 会员价 */}
|
||||
<View className='mb-4'>
|
||||
<Text className='text-sm text-gray-600 mb-2 block'>会员价 (¥)</Text>
|
||||
<Input
|
||||
className='bg-gray-50 rounded-lg px-4 py-3 text-sm'
|
||||
type='digit'
|
||||
placeholder='VIP/经销商专享价'
|
||||
value={addForm.dealerPrice}
|
||||
onInput={(e) => setAddForm(prev => ({ ...prev, dealerPrice: e.detail.value }))}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* 库存 */}
|
||||
<View className='mb-4'>
|
||||
<Text className='text-sm text-gray-600 mb-2 block'>库存 <Text className='text-red-500'>*</Text></Text>
|
||||
<Input
|
||||
className='bg-gray-50 rounded-lg px-4 py-3 text-sm'
|
||||
type='number'
|
||||
placeholder='请输入库存数量'
|
||||
value={addForm.stock}
|
||||
onInput={(e) => setAddForm(prev => ({ ...prev, stock: e.detail.value }))}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* 排序号 */}
|
||||
<View className='mb-4'>
|
||||
<Text className='text-sm text-gray-600 mb-2 block'>排序号</Text>
|
||||
<Input
|
||||
className='bg-gray-50 rounded-lg px-4 py-3 text-sm'
|
||||
type='number'
|
||||
placeholder='数字越小越靠前'
|
||||
value={addForm.sortNumber}
|
||||
onInput={(e) => setAddForm(prev => ({ ...prev, sortNumber: e.detail.value }))}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* 备注 */}
|
||||
<View className='mb-6'>
|
||||
<Text className='text-sm text-gray-600 mb-2 block'>备注</Text>
|
||||
<Textarea
|
||||
className='bg-gray-50 rounded-lg px-4 py-3 text-sm w-full'
|
||||
placeholder='选填'
|
||||
value={addForm.comments}
|
||||
onInput={(e) => setAddForm(prev => ({ ...prev, comments: e.detail.value }))}
|
||||
maxlength={200}
|
||||
style={{ minHeight: '60px' }}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* 操作按钮 */}
|
||||
<View className='flex gap-3'>
|
||||
<View className='flex-1 py-3 rounded-xl bg-gray-100 text-center' onClick={closeAddModal}>
|
||||
<Text className='text-sm text-gray-600'>取消</Text>
|
||||
</View>
|
||||
<View
|
||||
className='flex-1 py-3 rounded-xl bg-cyan-500 text-center'
|
||||
onClick={addSubmitting ? undefined : submitAdd}
|
||||
>
|
||||
<Text className='text-sm text-white'>
|
||||
{addSubmitting ? '添加中...' : '添加'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* 新增商品分类选择弹窗 */}
|
||||
{showAddCategoryPicker && (
|
||||
<View className='fixed inset-0 z-[60]' onClick={() => setShowAddCategoryPicker(false)}>
|
||||
<View className='absolute inset-0 bg-black/50' />
|
||||
<View
|
||||
className='absolute bottom-0 left-0 right-0 bg-white rounded-t-2xl max-h-[60vh] overflow-y-auto'
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<View className='sticky top-0 bg-white border-b border-gray-50 px-5 py-4 flex justify-between items-center'>
|
||||
<Text className='text-base font-medium text-gray-800'>选择分类</Text>
|
||||
<Text className='text-gray-400 text-lg' onClick={() => setShowAddCategoryPicker(false)}>×</Text>
|
||||
</View>
|
||||
<View
|
||||
className='px-5 py-3.5 border-b border-gray-50'
|
||||
onClick={() => {
|
||||
setAddForm(prev => ({ ...prev, categoryId: undefined }))
|
||||
setShowAddCategoryPicker(false)
|
||||
}}
|
||||
>
|
||||
<Text className='text-sm text-gray-600'>不选分类</Text>
|
||||
</View>
|
||||
{categories.map(cat => (
|
||||
<View
|
||||
key={cat.categoryId}
|
||||
className='px-5 py-3.5 border-b border-gray-50 flex justify-between items-center'
|
||||
onClick={() => {
|
||||
setAddForm(prev => ({ ...prev, categoryId: cat.categoryId }))
|
||||
setShowAddCategoryPicker(false)
|
||||
}}
|
||||
>
|
||||
<Text className='text-sm text-gray-700'>{cat.title}</Text>
|
||||
{addForm.categoryId === cat.categoryId && (
|
||||
<Text className='text-cyan-500'>✓</Text>
|
||||
)}
|
||||
</View>
|
||||
))}
|
||||
<View className='h-8' />
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -29,6 +29,23 @@ function formatDistance(km: number) {
|
||||
return km < 1 ? `${Math.round(km * 1000)}m` : `${km.toFixed(1)}km`
|
||||
}
|
||||
|
||||
/** 解析 lngAndLat 字符串,自动识别 "lat,lng" / "lng,lat" 两种格式 */
|
||||
function parseLngLat(str: string): { lat: number; lng: number } | null {
|
||||
const parts = str.split(',')
|
||||
if (parts.length !== 2) return null
|
||||
const a = parseFloat(parts[0])
|
||||
const b = parseFloat(parts[1])
|
||||
if (isNaN(a) || isNaN(b)) return null
|
||||
// 纬度范围 -90~90,经度范围 -180~180,通过值域区分两者
|
||||
if (Math.abs(a) <= 90 && Math.abs(b) <= 180) {
|
||||
return { lat: a, lng: b } // "lat,lng"
|
||||
}
|
||||
if (Math.abs(b) <= 90 && Math.abs(a) <= 180) {
|
||||
return { lat: b, lng: a } // "lng,lat"
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const StoreListPage: React.FC = () => {
|
||||
const params = Taro.getCurrentInstance().router?.params || {}
|
||||
// selectMode=1 时表示从预约页跳来,选中后回传
|
||||
@@ -110,13 +127,9 @@ const StoreListPage: React.FC = () => {
|
||||
list = list
|
||||
.map((store) => {
|
||||
if (store.lngAndLat) {
|
||||
const parts = store.lngAndLat.split(',')
|
||||
if (parts.length === 2) {
|
||||
const sLng = parseFloat(parts[0])
|
||||
const sLat = parseFloat(parts[1])
|
||||
if (sLat && sLng) {
|
||||
return { ...store, distance: calcDistance(userLat, userLng, sLat, sLng) }
|
||||
}
|
||||
const parsed = parseLngLat(store.lngAndLat)
|
||||
if (parsed) {
|
||||
return { ...store, distance: calcDistance(userLat, userLng, parsed.lat, parsed.lng) }
|
||||
}
|
||||
}
|
||||
return store
|
||||
@@ -163,20 +176,14 @@ const StoreListPage: React.FC = () => {
|
||||
Taro.showToast({ title: '暂无位置信息', icon: 'none' })
|
||||
return
|
||||
}
|
||||
const parts = store.lngAndLat.split(',')
|
||||
if (parts.length !== 2) {
|
||||
const parsed = parseLngLat(store.lngAndLat)
|
||||
if (!parsed) {
|
||||
Taro.showToast({ title: '位置信息格式有误', icon: 'none' })
|
||||
return
|
||||
}
|
||||
const longitude = parseFloat(parts[0])
|
||||
const latitude = parseFloat(parts[1])
|
||||
if (!latitude || !longitude) {
|
||||
Taro.showToast({ title: '暂无位置信息', icon: 'none' })
|
||||
return
|
||||
}
|
||||
Taro.openLocation({
|
||||
latitude,
|
||||
longitude,
|
||||
latitude: parsed.lat,
|
||||
longitude: parsed.lng,
|
||||
name: store.name || '',
|
||||
address: store.address || '',
|
||||
})
|
||||
|
||||
@@ -363,18 +363,18 @@ export default function StoreOrdersPage() {
|
||||
{/* 商品列表 */}
|
||||
{orderGoods.map((goods: any, idx: number) => (
|
||||
<View key={idx} className='flex items-center gap-3 mb-3'>
|
||||
{goods.coverImage && (
|
||||
<Image className='w-16 h-16 rounded-lg bg-gray-50' src={getCompressedImageUrl(goods.coverImage)}
|
||||
{goods.image && (
|
||||
<Image className='w-16 h-16 rounded-lg bg-gray-50' src={getCompressedImageUrl(goods.image, { width: 80 })}
|
||||
mode='aspectFill'/>
|
||||
)}
|
||||
<View className='flex-1'>
|
||||
<Text className='text-sm text-gray-800 block'>{goods.goodsName}</Text>
|
||||
{goods.specInfo && (
|
||||
<Text className='text-xs text-gray-400 mt-1 block'>{goods.specInfo}</Text>
|
||||
{goods.spec && (
|
||||
<Text className='text-xs text-gray-400 mt-1 block'>{goods.spec}</Text>
|
||||
)}
|
||||
<View className='flex justify-between items-center mt-1'>
|
||||
<Text className='text-sm text-red-500 font-medium'>¥{goods.price}</Text>
|
||||
<Text className='text-xs text-gray-400'>x{goods.quantity}</Text>
|
||||
<Text className='text-xs text-gray-400'>x{goods.totalNum}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -60,7 +60,7 @@ const AboutPage: React.FC = () => {
|
||||
<Text className='text-base font-medium text-gray-800 mb-3 block'>联系我们</Text>
|
||||
<View className='flex flex-col gap-2'>
|
||||
{[
|
||||
{ label: '经营部名称', value: '玉林市玉州区鑫龙家电经营部' },
|
||||
{ label: '经营部名称', value: '鑫龙商贸电器' },
|
||||
{ label: '经营地址', value: '大新里南718号' },
|
||||
{ label: '联系电话', value: '18269229683' },
|
||||
{ label: '营业时间', value: '9:00 ~ 18:00' },
|
||||
|
||||
Reference in New Issue
Block a user