feat: 下单完成(下一步:订单列表)

This commit is contained in:
zc 2025-10-19 08:24:03 +08:00
parent 5f446bc97a
commit 25f9813687
14 changed files with 281 additions and 74 deletions

View File

@ -3,6 +3,14 @@
"Vue.volar", "Vue.volar",
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"EditorConfig.EditorConfig", "EditorConfig.EditorConfig",
"esbenp.prettier-vscode" "esbenp.prettier-vscode",
"zhuangtongfa.Material-theme",
"PKief.material-icon-theme",
"ms-vscode.vscode-typescript-next",
"pranaygp.vscode-css-peek",
"ecmel.vscode-html-css",
"formulahendry.auto-rename-tag",
"bradlc.vscode-tailwindcss",
"unocss.unocss"
] ]
} }

11
components.d.ts vendored
View File

@ -10,15 +10,22 @@ declare module 'vue' {
export interface GlobalComponents { export interface GlobalComponents {
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
VanArea: typeof import('vant/es')['Area']
VanButton: typeof import('vant/es')['Button'] VanButton: typeof import('vant/es')['Button']
VanCell: typeof import('vant/es')['Cell'] VanCell: typeof import('vant/es')['Cell']
VanCellGroup: typeof import('vant/es')['CellGroup'] VanCellGroup: typeof import('vant/es')['CellGroup']
VanField: typeof import('vant/es')['Field'] VanField: typeof import('vant/es')['Field']
VanForm: typeof import('vant/es')['Form']
VanIcon: typeof import('vant/es')['Icon'] VanIcon: typeof import('vant/es')['Icon']
VanRate: typeof import('vant/es')['Rate'] VanNoticeBar: typeof import('vant/es')['NoticeBar']
VanPopover: typeof import('vant/es')['Popover']
VanPopup: typeof import('vant/es')['Popup']
VanSearch: typeof import('vant/es')['Search'] VanSearch: typeof import('vant/es')['Search']
VanStepper: typeof import('vant/es')['Stepper']
VanSwipe: typeof import('vant/es')['Swipe']
VanSwipeItem: typeof import('vant/es')['SwipeItem']
VanSwitch: typeof import('vant/es')['Switch']
VanTab: typeof import('vant/es')['Tab'] VanTab: typeof import('vant/es')['Tab']
VanTabs: typeof import('vant/es')['Tabs'] VanTabs: typeof import('vant/es')['Tabs']
VanUploader: typeof import('vant/es')['Uploader']
} }
} }

View File

@ -1,6 +1,6 @@
import axios from '@/utils/axios' import axios from '@/utils/axios'
import user from './user' import user from './user'
import shop from './commodity' import shop from './shop'
import common from './common' import common from './common'
const totalApiConfig = { user, shop, common } const totalApiConfig = { user, shop, common }

View File

@ -1,8 +1,13 @@
// 商品维度接口 // 商品维度接口
const shop = { const shop = {
// 商品
searchCommodityList: ['/index/page/list'], // 获取商品列表接口 searchCommodityList: ['/index/page/list'], // 获取商品列表接口
getCommodityDetail: ['/index/product/detail'], // 获取商品详情 getCommodityDetail: ['/index/product/detail'], // 获取商品详情
getReviewList: ['/comment/list'], // 获取评价接口 getReviewList: ['/comment/list'], // 获取评价接口
addCart: ['/shipping/cart/addOrUpdate'], // 添加购物车接口
order: ['/order/add'], // 下单
// 订单
orderList: ['/order/list'], // 订单列表
} }
export default shop export default shop

View File

@ -1,4 +1,5 @@
$theme-color: #01cf24; $theme-color: #01cf24;
$theme-light-color: #e4fdea;
$theme-disabled-color: #cefad5; $theme-disabled-color: #cefad5;
.theme-bg-color { .theme-bg-color {

View File

@ -1,3 +1,4 @@
import api from '@/api'
import { closeToast, showLoadingToast, type ToastWrapperInstance } from 'vant' import { closeToast, showLoadingToast, type ToastWrapperInstance } from 'vant'
interface ApiType { interface ApiType {
@ -61,3 +62,8 @@ window.useTipDialog = (
tipDialogData.show = true tipDialogData.show = true
tipDialogData.callback = callback tipDialogData.callback = callback
} }
// 添加购物车
export const handleAddCart = async (skuId: number, num: number = 1) => {
await api.shop.addCart.post({ num, skuId })
}

View File

@ -11,24 +11,24 @@
</h4> </h4>
<div class="flex-1 overflow-y-scroll"> <div class="flex-1 overflow-y-scroll">
<van-cell-group class="address-list__container"> <van-cell-group class="address-list__container">
<van-cell :class="['address-list__item']" v-for="item in addressList" :key="item.id"> <van-cell :class="['address-list__item', { 'theme-color': chooseAddressData.id === item.id }]" v-for="item in addressList" :key="item.id" @click="chooseAddressData = item">
<template #title> <template #title>
<div class="item__info"> <div class="item__info">
<h6 class="text-[.1rem]">{{ item.area }}</h6> <h6 class="text-[.1rem]">{{ item.contry + item.province + item.city + item.district }}</h6>
<p class="item__info__detail">{{ item.detail }}</p> <p class="item__info__detail">{{ item.detail }}</p>
<p class="item__info__subtitle text-[.13rem]">{{ item.name }} {{ item.tel }}</p> <p class="item__info__subtitle text-[.13rem]">{{ item.buyerName }} {{ item.buyerPhone }}</p>
</div> </div>
</template> </template>
<template #value> <template #value>
<div class="item__editor text-base"> <div class="item__editor text-base">
<van-icon v-if="!isManage" name="edit" color="#999" @click="onAddOrEditAddress('edit', item.originData)" /> <van-icon v-if="!isManage" name="edit" color="#999" @click.stop="onAddOrEditAddress('edit', item.originData)" />
<van-icon v-else name="delete-o" /> <van-icon v-else name="delete-o" @click.stop="onDeleteAddress(item.id)" />
</div> </div>
</template> </template>
</van-cell> </van-cell>
</van-cell-group> </van-cell-group>
<div class="bg-white w-full h-12 p-2 box-border"> <div class="bg-white w-full h-12 p-2 box-border">
<button class="block w-full h-full border-none bg-red color-white rounded-[.04rem]">确定</button> <button class="block w-full h-full border-none bg-red color-white rounded-[.04rem]" @click="onSubmit">确定</button>
</div> </div>
</div> </div>
</van-popup> </van-popup>
@ -42,12 +42,15 @@ const model = defineModel<boolean>()
const addressFormType = defineModel<'add' | 'edit'>('addressFormType') const addressFormType = defineModel<'add' | 'edit'>('addressFormType')
const showAddAddressFormDialog = defineModel<boolean>('showAddAddressFormDialog') const showAddAddressFormDialog = defineModel<boolean>('showAddAddressFormDialog')
const isUpDateAddressList = defineModel<boolean>('isUpDateAddressList') const isUpDateAddressList = defineModel<boolean>('isUpDateAddressList')
const props = defineProps<{ curAddressData: Recordable<any> }>()
const addressList = ref([]) const addressList = ref([])
const chooseAddressData = ref({})
const emits = defineEmits(['edit', 'confirm']) const emits = defineEmits(['edit', 'confirm'])
watch(model, (val) => { watch(model, (val) => {
val && handleGetAddressData() val && handleGetAddressData()
val && (chooseAddressData.value = { ...props.curAddressData })
}) })
// //
@ -68,20 +71,26 @@ const onAddOrEditAddress = (type: 'edit' | 'add', data?: any) => {
const handleGetAddressData = () => { const handleGetAddressData = () => {
api.user.getAddressList.post<any>().then((res) => { api.user.getAddressList.post<any>().then((res) => {
addressList.value = res.data.rows.map((item) => { addressList.value = res.data.rows
const originData = { ...item } .filter((item) => item.status !== 'delete')
return { .map((item) => {
id: item.id, const originData = { ...item }
name: item.buyerName, return {
tel: item.buyerPhone, isDefault: item.status === 'default',
area: item.contry + item.province + item.city + item.district, ...originData,
detail: item.detail, }
isDefault: item.status === 'default', })
originData,
}
})
}) })
} }
const onDeleteAddress = async (id: number) => {
await api.user.updateAddress.post({ id, status: 'delete' })
handleGetAddressData()
}
const onSubmit = () => {
model.value = false
emits('confirm', chooseAddressData.value)
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@ -94,6 +103,9 @@ const handleGetAddressData = () => {
color: #666; color: #666;
} }
} }
.theme-color {
background: $theme-light-color;
}
:deep(.van-cell) { :deep(.van-cell) {
.van-cell__title { .van-cell__title {
width: 0; width: 0;

View File

@ -5,8 +5,8 @@
<li :class="['all-review__tab-li', { active: item.active }]" v-for="item in tabs" :key="item.value">{{ item.name }}</li> <li :class="['all-review__tab-li', { active: item.active }]" v-for="item in tabs" :key="item.value">{{ item.name }}</li>
</ul> </ul>
<ul class="all-review__contain flex-1 overflow-y-scroll"> <ul class="all-review__contain flex-1 overflow-y-scroll">
<li class="p-3" v-for="item in reviews" :key="item.id"> <li class="p-3" v-for="item in list" :key="item.id">
<review-single /> <review-single :data="item" />
</li> </li>
</ul> </ul>
</van-popup> </van-popup>
@ -16,13 +16,13 @@
import reviewSingle from './review-single.vue' import reviewSingle from './review-single.vue'
const model = defineModel<boolean>() const model = defineModel<boolean>()
defineProps<{ list: Recordable<any>[] }>()
const tabs = [ const tabs = [
{ name: '全部', value: 0, active: true }, { name: '全部', value: 0, active: true },
{ name: '最新评价', value: 3, active: false }, { name: '最新评价', value: 3, active: false },
{ name: '5/4星好评', value: 1, active: false }, { name: '5/4星好评', value: 1, active: false },
{ name: '图/视频', value: 2, active: false }, { name: '图/视频', value: 2, active: false },
] ]
const reviews = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 5 }]
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -3,21 +3,22 @@
<h3 class="flex items-center text-sm"> <h3 class="flex items-center text-sm">
<img class="w-8 h-8 rounded-full" src="" alt="" /> <img class="w-8 h-8 rounded-full" src="" alt="" />
<div class="ml-1"> <div class="ml-1">
<p class="">**</p> <p class="">{{ data.buyerName }}</p>
<p class="mt-0.5 text-xs color-[#666]">2025.08.23</p> <p class="mt-0.5 text-xs color-[#666]">{{ handleData.formatTime(data.createTime, 'YYYY.MM.DD') }}</p>
</div> </div>
</h3> </h3>
<div class="review-content mt-3"> <div class="review-content mt-3">
<p>公司大丰收东方闪电防守打法四大分三大胜多负少的</p> <p>{{ data.productComment }}</p>
<p class="flex items-center mt-2"> <p class="flex items-center mt-2">
<img class="w-16 h-16 mr-1 rounded-[4px]" src="" alt="" v-for="(item, index) in list" :key="index" /> <img class="w-16 h-16 mr-1 rounded-[4px]" :src="item.commentUrl" alt="" v-for="(item, index) in data.vvCommentDetailEntities" :key="index" />
</p> </p>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
const list = ref(['', '']) import { handleData } from 'lz-utils-lib'
withDefaults(defineProps<{ data: any }>(), { data: {} })
</script> </script>
<style></style> <style></style>

View File

@ -5,44 +5,113 @@
<div class="mb-8"> <div class="mb-8">
<div class="cart-wrap"> <div class="cart-wrap">
<p class="flex justify-between" @click="showAddressList = true"> <p class="flex justify-between" @click="showAddressList = true">
<van-icon name="location-o" class="mr-1" /><span class="max-w-12 mr-1">张四</span> <b class="font- flex-1">我的详细地址是什么东西的地方的好的么</b><van-icon name="arrow" /> <van-icon name="location-o" class="mr-1" /><span class="max-w-12 mr-1">{{ curAddressData.buyerName }}</span>
<b class="font- flex-1">{{ curAddressData.province + curAddressData.city + curAddressData.district + curAddressData.detail }}</b
><van-icon name="arrow" />
</p> </p>
</div> </div>
<div class="cart-wrap mt-2"> <div class="cart-wrap mt-2">
<div class="flex"> <div class="flex">
<img class="w-16 h-16 mr-4" style="border-radius: 0.04rem" src="" alt="" /> <img class="w-16 h-16 mr-4" style="border-radius: 0.04rem" :src="curPageData.imageUrl" alt="" />
<p>¥<span>29.9</span></p> <div>
<p>
¥<span>{{ curPageData.price }}</span>
</p>
<p>
<van-stepper v-model="formData.num" input-width=".4rem" button-size=".2rem" min="1" :max="curPageData.num" />
</p>
</div>
</div> </div>
<div class="cart-cagetory-wrap"> <div class="cart-cagetory-wrap">
<h4>更多系列</h4> <template v-for="(arr, key) in skuData" :key="key">
<div class="cagetory"> <h4>{{ key }}</h4>
<p>手表系列</p> <div class="cagetory">
<p>手表系列水</p> <p
<p>手表</p> v-for="item in arr"
<p>手表123</p> :key="item.propertyId"
<p>手表12</p> :class="{ 'theme-border-color theme-color': item.propertyId === curPropertyIds.find((it) => it.productPropertyName === key).id }"
</div> @click="onChooseProperty(item, key)"
<h4>颜色</h4> >
<div class="cagetory"> {{ item.label }}
<p>手表系列</p> </p>
<p>手表系列水</p> </div>
<p>手表</p> </template>
<p>手表123</p>
<p>手表12</p>
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="fixed bg-white w-full h-12 left-0 bottom-0 p-2 box-border"> <div class="fixed bg-white w-full h-12 left-0 bottom-0 p-2 box-border">
<button class="block w-full h-full border-none theme-bg-color color-white rounded-[.04rem]">确定</button> <button class="block w-full h-full border-none theme-bg-color color-white rounded-[.04rem]" @click="onSubmit">{{ scene === 'cart' ? '加入购物车' : '立即下单' }}</button>
</div> </div>
</div> </div>
</van-popup> </van-popup>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import api from '@/api'
const model = defineModel<boolean>() const model = defineModel<boolean>()
const showAddressList = defineModel<boolean>('showAddressList') const showAddressList = defineModel<boolean>('showAddressList')
const props = defineProps<{ list: any[]; curAddressData: Recordable<any>; scene: 'order' | 'cart' }>()
const skuData = ref({}) // skukeyvalue{ : [{ ''}]}
const commodityData = ref({}) // valueskuId(keyid)
const curPropertyIds = ref([]) // id[{ id: 1, name: ''},{id: 2, name: ''}] name
const curPageData = ref({ price: '', imageUrl: '', num: 0 }) //
const formData = ref({ skuId: NaN, num: 1 })
watch(model, (val) => {
if (val) {
const { result, commodityMap, firstShopIds } = handleGetSkuList(props.list)
skuData.value = result
commodityData.value = commodityMap
curPropertyIds.value = firstShopIds
const { pageData, skuId } = handleGetPageData(commodityData.value, curPropertyIds.value)
curPageData.value = pageData
formData.value = { skuId, num: 1 }
}
})
const handleGetSkuList = (list: any[]) => {
const result = {} as any // sku
const commodityMap = {} //
let firstShopIds = []
list.forEach((item, i) => {
const commodityValue = { id: item.id, imageUrl: item.imageUrl, salePrice: item.salePrice, price: item.promotionPrice, num: item.stock }
let commodityPropertyId = ''
if (i === 0) {
firstShopIds = item.vvSkuPropertyValueList.map((child) => ({ id: child.productPropertyValueId, productPropertyName: child.productPropertyName }))
}
item.vvSkuPropertyValueList.forEach((item2, index) => {
commodityPropertyId += item2.productPropertyValueId + (index < item.vvSkuPropertyValueList.length - 1 ? '_' : '')
if (!result[item2.productPropertyName]) result[item2.productPropertyName] = []
if (result[item2.productPropertyName].some((child) => child.propertyId === item2.productPropertyValueId)) return
result[item2.productPropertyName].push({ propertyId: item2.productPropertyValueId, label: item2.productPropertyValue })
})
commodityMap[commodityPropertyId] = commodityValue
})
return { result, commodityMap, firstShopIds }
}
const onChooseProperty = (item, categoryName) => {
curPropertyIds.value.find((it) => it.productPropertyName === categoryName).id = item.propertyId
const { pageData, skuId } = handleGetPageData(commodityData.value, curPropertyIds.value)
curPageData.value = pageData
formData.value = { skuId, num: 1 }
}
const handleGetPageData = (commodityData, curPropertyIds) => {
const data = commodityData[curPropertyIds.map((item) => item.id).join('_')]
return { pageData: { price: data.price, imageUrl: data.imageUrl, num: data.num }, skuId: data.id }
}
const onSubmit = async () => {
if (props.scene === 'cart') {
await api.shop.addCart.post(formData.value)
showToast('加入购物车成功')
} else {
await api.shop.order.post({ buyerAddressId: 2, vvTradeOrderLineDTOList: [formData.value] })
showToast('下单成功')
}
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -63,6 +132,8 @@ const showAddressList = defineModel<boolean>('showAddressList')
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
& > p { & > p {
border: 1px solid #f2f2f2;
box-sizing: border-box;
flex-shrink: 0; flex-shrink: 0;
height: 0.28rem; height: 0.28rem;
line-height: 0.28rem; line-height: 0.28rem;
@ -72,6 +143,9 @@ const showAddressList = defineModel<boolean>('showAddressList')
border-radius: 0.04rem; border-radius: 0.04rem;
margin-right: 0.08rem; margin-right: 0.08rem;
margin-bottom: 0.08rem; margin-bottom: 0.08rem;
&.theme-border-color {
background: #fff;
}
} }
} }
} }

View File

@ -1,27 +1,37 @@
<template> <template>
<div id="commodity-detail"> <div id="commodity-detail">
<header class="h-70 bg-[#aaa]"></header> <header class="h-70 bg-[#aaa]">
<van-swipe class="my-swipe" :autoplay="3000" indicator-color="white">
<van-swipe-item><img class="h-full w-full" :src="detail.mainImg" alt="" /></van-swipe-item>
<van-swipe-item v-if="detail.video">{{ detail.video }}</van-swipe-item>
<van-swipe-item v-for="img in detail.subImgs" :key="img">{{ img }}</van-swipe-item>
</van-swipe>
</header>
<main> <main>
<div class="detail-info wrap"> <div class="detail-info wrap">
<h2 class="text-2xl color-[#000]">陕西珍珠首饰项链</h2> <h2 class="text-2xl color-[#000]">{{ detail.title }}</h2>
<h4 class="mt-2 text-sm">副标题</h4> <!-- <h4 class="mt-2 text-sm">副标题</h4>
<ul class="detail-wrap"> <ul class="detail-wrap">
<li><span>配送</span> <em>立即下单预计最快今天23:00发货</em></li> <li><span>配送</span> <em>立即下单预计最快今天23:00发货</em></li>
<li><span>服务</span> <button>7天无理由退款</button></li> <li><span>服务</span> <button>7天无理由退款</button></li>
</ul> </ul> -->
</div> </div>
<div class="review-info wrap"> <div class="review-info wrap">
<h3 class="wrap-title"><b>用户评价(45.6+)</b><span @click="onShowAllReview">全部评价 ></span></h3> <h3 class="wrap-title">
<b>用户评价({{ reviews.length }}+)</b><span @click="onShowAllReview">全部评价 ></span>
</h3>
<div class="mt-5"> <div class="mt-5">
<review-single /> <review-single :data="reviews[0]" />
</div> </div>
</div> </div>
<div class="wrap"> <div class="wrap">
<h3 class="wrap-title"><b>商品详情</b><span>查看全部信息</span></h3> <h3 class="wrap-title">
<info-table class="mt-3" /> <b>商品详情</b>
<!-- <span>查看全部信息</span> -->
</h3>
<!-- <info-table class="mt-3" /> -->
<div class="imgs"> <div class="imgs">
<img class="w-full h-40" src="" alt="" /> <img v-for="img in detail.detailImgs" :src="img" alt="" class="w-full h-40" />
<img class="w-full h-40" src="" alt="" />
</div> </div>
</div> </div>
<div class="wrap"> <div class="wrap">
@ -46,17 +56,18 @@
</p> </p>
</div> </div>
<div class="flex-1 button-wrap"> <div class="flex-1 button-wrap">
<button class="bg-orange text-white w-30!">加入购物车</button> <button class="bg-orange text-white w-30!" @click="onSubmit('cart')">加入购物车</button>
<button class="theme-bg-color color-white" @click="onPayNowBtn">立即购买</button> <button class="theme-bg-color color-white" @click="onSubmit('order')">立即购买</button>
</div> </div>
</footer> </footer>
<shopping-cart v-model="showShopCart" v-model:showAddressList="showAddressList" v-model:curAddressData="curAddressData"></shopping-cart> <shopping-cart v-model="showShopCart" v-model:showAddressList="showAddressList" v-model:curAddressData="curAddressData" :list="skuList" :scene="cartType"></shopping-cart>
<all-review v-model="showAllReview"></all-review> <all-review v-model="showAllReview" :list="reviews"></all-review>
<address-list <address-list
v-model="showAddressList" v-model="showAddressList"
v-model:isUpDateAddressList="isUpDateAddressList" v-model:isUpDateAddressList="isUpDateAddressList"
v-model:showAddAddressFormDialog="showAddAddressFormDialog" v-model:showAddAddressFormDialog="showAddAddressFormDialog"
v-model:addressFormType="addressFormType" v-model:addressFormType="addressFormType"
:curAddressData="curAddressData"
@edit="(val) => (editAddressData = val)" @edit="(val) => (editAddressData = val)"
@confirm="(val) => (curAddressData = val)" @confirm="(val) => (curAddressData = val)"
></address-list> ></address-list>
@ -74,7 +85,16 @@ import shoppingCart from './components/shopping-cart.vue'
import addressList from './components/address-list.vue' import addressList from './components/address-list.vue'
import addressForm from './components/address-form.vue' import addressForm from './components/address-form.vue'
const detail = reactive({
mainImg: '',
video: '',
subImgs: [],
detailImgs: [],
title: '',
})
const showShopCart = ref(false) // const showShopCart = ref(false) //
const cartType = ref<'order' | 'cart'>('order')
const showAllReview = ref(false) // const showAllReview = ref(false) //
const showAddressList = ref(false) // const showAddressList = ref(false) //
const showAddAddressFormDialog = ref(false) // form const showAddAddressFormDialog = ref(false) // form
@ -85,7 +105,9 @@ const curAddressData = ref({}) // 当前选中的收货地址
const route = useRoute() const route = useRoute()
const init = () => { const init = () => {
handleGetCommodityDetail(+route.query.id)
handleGetReviews(+route.query.id) handleGetReviews(+route.query.id)
handleGetAddressList()
} }
// //
@ -93,13 +115,35 @@ const onShowAllReview = () => {
showAllReview.value = true showAllReview.value = true
} }
// //
const onPayNowBtn = () => { const onSubmit = (type: 'order' | 'cart') => {
cartType.value = type
showShopCart.value = true showShopCart.value = true
} }
//
const reviews = ref([])
const handleGetReviews = (productId: number) => { const handleGetReviews = (productId: number) => {
api.shop.getReviewList.post({ productId }).then((res) => { api.shop.getReviewList.post<any>({ productId }).then((res) => {
console.log(res) reviews.value = res.data
})
}
const skuList = ref([])
//
const handleGetCommodityDetail = (productId: number) => {
api.shop.getCommodityDetail.post<any>({ productId }).then((res) => {
detail.mainImg = res.data.mainImageUrl
detail.video = res.data.videoUrl
detail.subImgs = res.data.vvProductDetailList.filter((item) => item.type === 1)?.map((item) => item.testzc)
detail.detailImgs = res.data.vvProductDetailList.find((item) => item.type === 2)?.testzc
detail.title = res.data.title
skuList.value = res.data.vvSkuList
})
}
const handleGetAddressList = () => {
api.user.getAddressList.post<any>({}).then((res) => {
curAddressData.value = res.data.rows.find((item) => item.status === 'default')
}) })
} }
init() init()
@ -108,6 +152,9 @@ init()
<style scope lang="scss"> <style scope lang="scss">
#commodity-detail { #commodity-detail {
background: #f2f2f2; background: #f2f2f2;
.my-swipe {
height: 100%;
}
.wrap { .wrap {
margin: 0.08rem 0.12rem; margin: 0.08rem 0.12rem;
border-radius: 0.12rem; border-radius: 0.12rem;

View File

@ -9,7 +9,7 @@
<script setup lang="ts"> <script setup lang="ts">
const list = [ const list = [
{ title: '搜索结果', path: 'search-container' }, { title: '搜索结果', path: 'search-container' },
{ title: '商品详情', path: 'commodity-detail' }, { title: '商品详情', path: 'commodity-detail', query: { id: 4 } },
{ title: '我的订单', path: 'order' }, { title: '我的订单', path: 'order' },
{ title: '订单详情', path: 'order/detail' }, { title: '订单详情', path: 'order/detail' },
{ title: '评价中心', path: 'review/center' }, { title: '评价中心', path: 'review/center' },
@ -18,7 +18,7 @@ const list = [
const router = useRouter() const router = useRouter()
const onClick = (item: any) => { const onClick = (item: any) => {
router.push({ name: item.path }) router.push({ name: item.path, query: item.query })
} }
</script> </script>

View File

@ -58,6 +58,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import api from '@/api'
import { showToast } from 'vant' import { showToast } from 'vant'
const searchValue = ref('') const searchValue = ref('')
@ -122,6 +123,22 @@ const router = useRouter()
const goDetail = (id: number) => { const goDetail = (id: number) => {
router.push({ path: '/order/detail', query: { id } }) router.push({ path: '/order/detail', query: { id } })
} }
const init = () => {
handleGetList()
}
const handleGetList = () => {
api.shop.orderList.post().then((res) => {
orders.value = res.data.map((item) => ({
id: item.id,
storeName: item.title,
}))
console.warn('----- my data is res: ', res)
})
}
init()
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -4,13 +4,13 @@
<van-search class="flex-1 p-0!" background="#f2f2f2" v-model="searchValue" placeholder="请输入搜索关键词" @search="onSearch(searchValue)" /> <van-search class="flex-1 p-0!" background="#f2f2f2" v-model="searchValue" placeholder="请输入搜索关键词" @search="onSearch(searchValue)" />
<van-icon name="shopping-cart-o" size=".2rem" class="ml-2" /> <van-icon name="shopping-cart-o" size=".2rem" class="ml-2" />
</header> </header>
<van-tabs v-model:active="searchSort" sticky :color="appStore.themeColor" @change="onChangeSort"> <van-tabs v-model:active="searchSort" sticky :color="appStore.themeColor" @click="onChangeSort(searchSort)">
<van-tab title="综合" name="0"></van-tab> <van-tab title="综合" name="0"></van-tab>
<van-tab title="销量" name="1"></van-tab> <van-tab title="销量" name="1"></van-tab>
<van-tab title="价格" name="2"></van-tab> <van-tab title="价格" name="2"></van-tab>
</van-tabs> </van-tabs>
<ul class="search-condition bg-white pt-2 flex-1 overflow-y-scroll"> <ul class="search-condition bg-white pt-2 flex-1 overflow-y-scroll">
<li v-for="item in searchList" :key="item.id" class="flex item-center p-2 relative" @click="onGoDetail(item.id)"> <li v-for="item in searchList" :key="item.productId" class="flex item-center p-2 relative" @click="onGoDetail(item.productId)">
<img :src="item.mainImageUrl" alt="" class="w-24 h-24" /> <img :src="item.mainImageUrl" alt="" class="w-24 h-24" />
<div class="ml-2"> <div class="ml-2">
<h4 class="text-[.13rem]">{{ item.title }}</h4> <h4 class="text-[.13rem]">{{ item.title }}</h4>
@ -27,7 +27,18 @@
> >
</p> </p>
</div> </div>
<van-icon name="add" :color="appStore.themeColor" size=".2rem" class="absolute! right-3 bottom-6 h-5" /> <van-icon
name="add"
:color="appStore.themeColor"
size=".2rem"
class="absolute! right-3 bottom-6 h-5"
@click="
(e) => {
e.stopPropagation()
handleAddCart(item.skuId)
}
"
/>
</li> </li>
</ul> </ul>
</div> </div>
@ -35,10 +46,12 @@
<script setup lang="ts"> <script setup lang="ts">
import api from '@/api' import api from '@/api'
import { handleAddCart } from '@/utils/page'
import useAppStore from '@/stores/modules/app' import useAppStore from '@/stores/modules/app'
const route = useRoute() const route = useRoute()
const searchValue = ref(route.query.initValue as string) const searchValue = ref(route.query.initValue as string)
const searchSort = ref('0') const searchSort = ref('0')
const priceSort = ref('DESC')
const searchList = ref([]) const searchList = ref([])
@ -51,9 +64,25 @@ const onGoDetail = (id: number) => {
const onSearch = async (searchValue: string, sort = '0') => { const onSearch = async (searchValue: string, sort = '0') => {
searchSort.value = sort searchSort.value = sort
const result = await api.shop.searchCommodityList.post<any>({ productName: searchValue, frontPage: 0, isTest: 0, sort: searchSort.value }) // testzc let sortParams = {}
// ASC: , DESC:
if (sort === '0') {
//
priceSort.value = 'DESC'
sortParams = { createTimestampSort: 'DESC' }
} else if (sort === '1') {
//
priceSort.value = 'DESC'
sortParams = { salePriceSort: 'DESC' }
} else if (sort === '2') {
//
priceSort.value = priceSort.value === 'ASC' ? 'DESC' : 'ASC'
sortParams = { priceSort: priceSort.value }
}
const result = await api.shop.searchCommodityList.post<any>({ productName: searchValue, frontPage: 0, isTest: 0, ...sortParams }) // testzc
searchList.value = result.data.rows.map((item) => ({ searchList.value = result.data.rows.map((item) => ({
id: item.id, skuId: item.skuId,
productId: item.productId,
title: item.title, title: item.title,
mainImageUrl: item.mainImageUrl, mainImageUrl: item.mainImageUrl,
originPrice: String(item.showSalePrice), originPrice: String(item.showSalePrice),