feat: 商品详情开发完成

This commit is contained in:
zc 2025-11-30 19:36:08 +08:00
parent 1d41440d80
commit bcff31ba7f
9 changed files with 90 additions and 93 deletions

View File

@ -1,6 +1,6 @@
import request from '@/utils/request' import request from '@/utils/request'
import {httpRequest} from '@/utils/request/axios' import {httpRequest} from '@/utils/request/axios'
const baseUrl = 'https://api.1024api.com/api-interface' const baseUrl = 'https://api.1024api.com/api-interface/app'
// api地址 // api地址
const api = { const api = {
@ -46,3 +46,19 @@ export const apiGetCommodityList = (data) => {
); );
} }
// 获取商品详情
export const apiGetCommodityDetail = (data) => {
return httpRequest.post(
`${baseUrl}/index/product/detail`,
data
);
}
// 加入购物车
export const apiAddCart = (data) => {
return httpRequest.post(
`${baseUrl}/shipping/cart/addOrUpdate`,
data
);
}

View File

@ -801,6 +801,7 @@
let that = this; let that = this;
that.checkSelectComplete({ that.checkSelectComplete({
success: function(selectShop) { success: function(selectShop) {
console.warn('----- my data is : ', selectShop)
selectShop.buy_num = that.selectNum; selectShop.buy_num = that.selectNum;
that.$emit('buy-now', selectShop); that.$emit('buy-now', selectShop);
that.$emit('buy', selectShop); that.$emit('buy', selectShop);

View File

@ -139,13 +139,10 @@
"devServer" : { "devServer" : {
"port" : 8010, "port" : 8010,
"proxy" : { "proxy" : {
"/api" : { "/index.php" : {
"target" : "https://shop2.client.yiovo.com", "target" : "https://shop2.client.yiovo.com",
"changeOrigin" : true, "changeOrigin" : true,
"secure" : true, "secure" : true
"pathRewrite" : {
"^/api" : "/index.php?s=/api"
}
} }
} }
}, },

View File

@ -49,13 +49,16 @@
// //
showPopup: false, showPopup: false,
// //
list: [] list: [{
"name": "48小时发货",
"summary": "下单后48小时之内发货"
}]
} }
}, },
created() { created() {
// //
this.getServiceList() // this.getServiceList()
}, },
methods: { methods: {

View File

@ -7,9 +7,8 @@
</template> </template>
<script> <script>
import { setCartTotalNum } from '@/core/app'
import { hex2rgba } from '@/utils/color' import { hex2rgba } from '@/utils/color'
import * as CartApi from '@/api/cart' import * as GoodsApi from '@/api/goods'
import GoodsSkuPopup from '@/components/goods-sku-popup' import GoodsSkuPopup from '@/components/goods-sku-popup'
export default { export default {
@ -52,9 +51,9 @@
const app = this const app = this
const { goods } = app const { goods } = app
app.goodsInfo = { app.goodsInfo = {
_id: goods.goods_id, _id: goods.id,
name: goods.goods_name, name: goods.title,
goods_thumb: goods.goods_image, goods_thumb: goods.mainImageUrl,
sku_list: app.getSkuList(), sku_list: app.getSkuList(),
spec_list: app.getSpecList() spec_list: app.getSpecList()
} }
@ -71,60 +70,36 @@
// SKU // SKU
getSkuList() { getSkuList() {
const app = this const app = this
const { goods: { goods_name, goods_image, skuList } } = app const { goods: { id, title, mainImageUrl, skuList } } = app
const skuData = [] const skuData = [];
skuList.forEach(item => { (skuList || []).forEach(item => {
skuData.push({ skuData.push({
_id: item.id, _id: item.id,
goods_sku_id: item.goods_sku_id, goods_sku_id: item.id,
goods_id: item.goods_id, goods_id: id,
goods_name: goods_name, goods_name: title,
image: item.image_url ? item.image_url : goods_image, image: item.imageUrl ? item.imageUrl : mainImageUrl,
price: item.goods_price * 100, price: item.promotionPrice * 100,
stock: item.stock_num, stock: item.stock,
spec_value_ids: item.spec_value_ids, spec_value_ids: item.vvSkuPropertyValueList.map(item => item.id).join('_'),
sku_name_arr: app.getSkuNameArr(item.spec_value_ids) sku_name_arr: item.vvSkuPropertyValueList.map(item => item.productPropertyValue)
}) })
}) })
return skuData return skuData
}, },
// sku
getSkuNameArr(specValueIds) {
const app = this
const defaultData = ['默认']
const skuNameArr = []
if (specValueIds) {
specValueIds.forEach((valueId, groupIndex) => {
const specValueName = app.getSpecValueName(valueId, groupIndex)
skuNameArr.push(specValueName)
})
}
return skuNameArr.length ? skuNameArr : defaultData
},
//
getSpecValueName(valueId, groupIndex) {
const app = this
const { goods: { specList } } = app
const res = specList[groupIndex].valueList.find(specValue => {
return specValue.spec_value_id == valueId
})
return res.spec_value
},
// //
getSpecList() { getSpecList() {
const { goods: { specList } } = this const { goods: { productPropertyList } } = this
const defaultData = [{ name: '默认', list: [{ name: '默认' }] }] const defaultData = [{ name: '默认', list: [{ name: '默认' }] }]
const specData = [] const specData = [];
specList.forEach(group => { (productPropertyList || []).forEach(group => {
const children = [] const children = []
group.valueList.forEach(specValue => { group.vvProductPropertyValueList.forEach(specValue => {
children.push({ name: specValue.spec_value }) children.push({ name: specValue.productPropertyValue })
}) })
specData.push({ specData.push({
name: group.spec_name, name: group.productPropertyName,
list: children list: children
}) })
}) })
@ -150,18 +125,19 @@
addCart(selectShop) { addCart(selectShop) {
const app = this const app = this
const { goods_id, goods_sku_id, buy_num } = selectShop const { goods_id, goods_sku_id, buy_num } = selectShop
CartApi.add(goods_id, goods_sku_id, buy_num) // CartApi.add(goods_id, goods_sku_id, buy_num)
GoodsApi.apiAddCart({ num: buy_num, skuId: goods_sku_id })
.then(result => { .then(result => {
// //
app.$toast(result.message) app.$toast('添加成功')
// //
app.onChangeValue(false) app.onChangeValue(false)
// /* // 购物车商品总数
const cartTotal = result.data.cartTotal const cartTotal = result.data.cartTotal
// //
setCartTotalNum(cartTotal) setCartTotalNum(cartTotal)
// //
app.$emit('addCart', cartTotal) app.$emit('addCart', cartTotal) */
}) })
}, },

View File

@ -14,7 +14,7 @@
<!-- 轮播图片 --> <!-- 轮播图片 -->
<swiper-item v-for="(item, index) in images" :key="index" @click="onPreviewImages(index)"> <swiper-item v-for="(item, index) in images" :key="index" @click="onPreviewImages(index)">
<view class="slide-image"> <view class="slide-image">
<image class="image" :draggable="false" :src="item.preview_url"></image> <image class="image" :draggable="false" :src="item"></image>
</view> </view>
</swiper-item> </swiper-item>
</swiper> </swiper>
@ -77,7 +77,7 @@
const app = this const app = this
const imageUrls = [] const imageUrls = []
app.images.forEach(item => { app.images.forEach(item => {
imageUrls.push(item.preview_url); imageUrls.push(item);
}); });
uni.previewImage({ uni.previewImage({
current: imageUrls[index], current: imageUrls[index],

View File

@ -10,25 +10,25 @@
<view class="block-left dis-flex flex-y-center"> <view class="block-left dis-flex flex-y-center">
<!-- 商品售价 --> <!-- 商品售价 -->
<text class="floor-price__samll"></text> <text class="floor-price__samll"></text>
<text class="floor-price">{{ goods.goods_price_min }}</text> <text class="floor-price">{{ goods.showPromotionPrice }}</text>
<!-- 会员价标签 --> <!-- 会员价标签 -->
<view v-if="goods.is_user_grade" class="user-grade"> <view v-if="goods.is_user_grade" class="user-grade">
<text>会员价</text> <text>会员价</text>
</view> </view>
<!-- 划线价 --> <!-- 划线价 -->
<text v-if="goods.line_price_min > 0" class="original-price">{{ goods.line_price_min }}</text> <text v-if="goods.showSalePrice > 0" class="original-price">{{ goods.showSalePrice }}</text>
</view> </view>
<view class="block-right dis-flex"> <view class="block-right dis-flex">
<!-- 销量 --> <!-- 销量 -->
<view class="goods-sales"> <view class="goods-sales">
<text>已售{{ goods.goods_sales }}</text> <text>已售{{ goods.showSaleCount }}</text>
</view> </view>
</view> </view>
</view> </view>
<!-- 标题分享 --> <!-- 标题分享 -->
<view class="info-item info-item__name dis-flex flex-y-center"> <view class="info-item info-item__name dis-flex flex-y-center">
<view class="goods-name flex-box"> <view class="goods-name flex-box">
<text class="twoline-hide">{{ goods.goods_name }}</text> <text class="twoline-hide">{{ goods.title }}</text>
</view> </view>
<view class="goods-share__line"></view> <view class="goods-share__line"></view>
<view class="goods-share"> <view class="goods-share">
@ -45,11 +45,11 @@
</view> </view>
<!-- 选择商品规格 --> <!-- 选择商品规格 -->
<view v-if="goods.spec_type == 20" class="goods-choice m-top20 b-f" @click="onShowSkuPopup(1)"> <view class="goods-choice m-top20 b-f" @click="onShowSkuPopup(1)">
<view class="spec-list"> <view class="spec-list">
<view class="flex-box"> <view class="flex-box">
<text class="col-8">选择</text> <text class="col-8">选择</text>
<text class="spec-name" v-for="(item, index) in goods.specList" :key="index">{{ item.spec_name }}</text> <text class="spec-name" v-for="(item, index) in goods.productPropertyList" :key="index">{{ item.productPropertyName }}</text>
</view> </view>
<view class="f-26 col-9 t-r"> <view class="f-26 col-9 t-r">
<text class="iconfont icon-arrow-right"></text> <text class="iconfont icon-arrow-right"></text>
@ -71,8 +71,8 @@
<view class="item-title b-f"> <view class="item-title b-f">
<text>商品描述</text> <text>商品描述</text>
</view> </view>
<view v-if="goods.content != ''" class="goods-content__detail b-f"> <view v-if="goods.contentHtml != ''" class="goods-content__detail b-f">
<mp-html :content="goods.content" /> <mp-html :content="goods.contentHtml" />
</view> </view>
</view> </view>
@ -91,7 +91,7 @@
</view> </view>
</view> </view>
<!-- 客服 --> <!-- 客服 -->
<customer-btn v-if="isShowCustomerBtn" :showCard="true" :cardTitle="goods.goods_name" :cardImage="goods.goods_image" <customer-btn v-if="isShowCustomerBtn" :showCard="true" :cardTitle="goods.title" :cardImage="goods.goods_image"
:cardPath="pagePath"> :cardPath="pagePath">
<view class="fast-item"> <view class="fast-item">
<view class="fast-icon"> <view class="fast-icon">
@ -117,7 +117,7 @@
<!-- 操作按钮 --> <!-- 操作按钮 -->
<view class="foo-item-btn"> <view class="foo-item-btn">
<view class="btn-wrapper"> <view class="btn-wrapper">
<view v-if="isEnableCart" class="btn-item btn-item-deputy" @click="onShowSkuPopup(2)"> <view class="btn-item btn-item-deputy" @click="onShowSkuPopup(2)">
<text>加入购物车</text> <text>加入购物车</text>
</view> </view>
<view class="btn-item btn-item-main" @click="onShowSkuPopup(3)"> <view class="btn-item btn-item-main" @click="onShowSkuPopup(3)">
@ -132,7 +132,7 @@
<!-- <shortcut bottom="120" /> --> <!-- <shortcut bottom="120" /> -->
<!-- 分享菜单 --> <!-- 分享菜单 -->
<share-sheet v-model="showShareSheet" :shareTitle="goods.goods_name" :shareImageUrl="goods.goods_image" /> <share-sheet v-model="showShareSheet" :shareTitle="goods.title" :shareImageUrl="goods.goods_image" />
</view> </view>
</template> </template>
@ -141,7 +141,6 @@
import { getSceneData } from '@/core/app' import { getSceneData } from '@/core/app'
import * as GoodsApi from '@/api/goods' import * as GoodsApi from '@/api/goods'
import * as CartApi from '@/api/cart' import * as CartApi from '@/api/cart'
import SettingModel from '@/common/model/Setting'
import { GoodsTypeEnum } from '@/common/enum/goods' import { GoodsTypeEnum } from '@/common/enum/goods'
import ShareSheet from '@/components/share-sheet' import ShareSheet from '@/components/share-sheet'
import CustomerBtn from '@/components/customer-btn' import CustomerBtn from '@/components/customer-btn'
@ -175,10 +174,8 @@
skuMode: 1, skuMode: 1,
// / // /
showShareSheet: false, showShareSheet: false,
//
isEnableCart: false,
// 线 // 线
isShowCustomerBtn: false, isShowCustomerBtn: true,
} }
}, },
computed: { computed: {
@ -197,12 +194,9 @@
this.onRecordQuery(options) this.onRecordQuery(options)
// //
this.onRefreshPage() this.onRefreshPage()
// 线
this.isShowCustomerBtn = await SettingModel.isShowCustomerBtn()
}, },
methods: { methods: {
// query // query
onRecordQuery(query) { onRecordQuery(query) {
const scene = getSceneData(query) const scene = getSceneData(query)
@ -213,7 +207,8 @@
onRefreshPage() { onRefreshPage() {
const app = this const app = this
app.isLoading = true app.isLoading = true
Promise.all([app.getGoodsDetail(), app.getCartTotal()]) // Promise.all([app.getGoodsDetail(), app.getCartTotal()])
Promise.all([app.getGoodsDetail()])
.finally(() => app.isLoading = false) .finally(() => app.isLoading = false)
}, },
@ -221,12 +216,16 @@
getGoodsDetail() { getGoodsDetail() {
const app = this const app = this
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
GoodsApi.detail(app.goodsId) // GoodsApi.detail(app.goodsId)
GoodsApi.apiGetCommodityDetail({ productId: app.goodsId })
.then(result => { .then(result => {
app.goods = result.data.detail app.goods = result.data
if (app.goods.goods_type == GoodsTypeEnum.PHYSICAL.value) { app.goods.goods_images = result.data.vvProductDetailList.filter((item) => item.type === 1).map((item) => item.detail)
app.isEnableCart = true app.goods.goods_images.unshift(result.data.mainImageUrl)
} app.goods.video = result.data.videoUrl
app.goods.contentHtml = result.data.vvProductDetailList.find((item) => item.type === 2)?.detail
app.goods.productPropertyList = result.data.vvProductPropertyList
app.goods.skuList = result.data.vvSkuList
resolve(result) resolve(result)
}) })
.catch(reject) .catch(reject)
@ -248,7 +247,7 @@
// //
onAddCart(total) { onAddCart(total) {
this.cartTotal = total // this.cartTotal = total
}, },
/** /**
@ -257,11 +256,7 @@
*/ */
onShowSkuPopup(skuMode = 1) { onShowSkuPopup(skuMode = 1) {
const app = this const app = this
if (app.isEnableCart) { app.skuMode = skuMode
app.skuMode = skuMode
} else {
app.skuMode = 3
}
app.showSkuPopup = !app.showSkuPopup app.showSkuPopup = !app.showSkuPopup
}, },
@ -287,7 +282,7 @@
*/ */
onShareAppMessage() { onShareAppMessage() {
return { return {
title: this.goods.goods_name, title: this.goods.title,
path: this.pagePath path: this.pagePath
} }
}, },
@ -299,7 +294,7 @@
*/ */
onShareTimeline() { onShareTimeline() {
return { return {
title: this.goods.goods_name, title: this.goods.title,
path: this.pagePath path: this.pagePath
} }
} }

View File

@ -221,6 +221,7 @@
GoodsApi.detail(app.goodsId) GoodsApi.detail(app.goodsId)
.then(result => { .then(result => {
app.goods = result.data.detail app.goods = result.data.detail
console.warn('----- my data is app.goods: ', app.goods)
if (app.goods.goods_type == GoodsTypeEnum.PHYSICAL.value) { if (app.goods.goods_type == GoodsTypeEnum.PHYSICAL.value) {
app.isEnableCart = true app.isEnableCart = true
} }

View File

@ -62,7 +62,15 @@ class HttpRequest {
// 服务器接口请求 // 服务器接口请求
request(requestConfig) { request(requestConfig) {
const _this = this; const _this = this;
const user_info = uni.getStorageSync("user_info") || {}; // 兼容H5字符串和微信小程序对象场景
let user_info = uni.getStorageSync("user_info") || {};
if (typeof user_info === "string") {
try {
user_info = JSON.parse(user_info) || {};
} catch (e) {
user_info = {};
}
}
const reqData = Object.assign(requestConfig.data, { const reqData = Object.assign(requestConfig.data, {
buyerId: user_info.buyerId, buyerId: user_info.buyerId,
flag: user_info.flag, flag: user_info.flag,