开发产品详情页面,调试接口 90%
@ -70,4 +70,12 @@ export const prodOrNewsCatgApi = (catgId) => {
|
||||
**/
|
||||
export const prodPageApi = (params) => {
|
||||
return request.get('/web/prodPageList', {params})
|
||||
}
|
||||
|
||||
/**
|
||||
* @function 获取产品新闻详情
|
||||
* @param {string} id
|
||||
**/
|
||||
export const prodOrNewsInfoApi = (id) => {
|
||||
return request.get(`/web/prodNewsInfo?id=${id}`)
|
||||
}
|
@ -1,15 +1,381 @@
|
||||
<template>
|
||||
<view class="pages">
|
||||
产品详情
|
||||
<Tabs
|
||||
:list="tabsList"
|
||||
v-model:active="tabsActive"
|
||||
/>
|
||||
|
||||
<view class="container">
|
||||
<swiper
|
||||
class="swiper"
|
||||
circular
|
||||
:autoplay="true"
|
||||
:current="swiperCurrent"
|
||||
@change="swiperChange"
|
||||
>
|
||||
<swiper-item v-for="(item,index) in productsImages" :key="index">
|
||||
<view class="swiper-item">
|
||||
<image :src="item" mode="aspectFill"></image>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view class="siwper-number">
|
||||
{{ swiperCurrent + 1 }}/{{productsImages.length}}
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="title">
|
||||
{{info.title}}
|
||||
</view>
|
||||
<view class="rich-text" v-html="info.description"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="module">
|
||||
{{$t('products.productDetails')}}
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="container"
|
||||
style="padding: 18rpx 26rpx;"
|
||||
v-html="info.content"
|
||||
>
|
||||
</view>
|
||||
|
||||
<view class="module">
|
||||
{{$t('products.inquiry')}}
|
||||
</view>
|
||||
|
||||
<view class="container">
|
||||
<image class="inquiry-bg" src="@/assets/images/bg/Inquiry-bg.png"></image>
|
||||
<uni-forms
|
||||
ref="dataFormRef"
|
||||
class="form-box"
|
||||
:model="dataForm"
|
||||
:rules="dataFormRules"
|
||||
label-position="top"
|
||||
>
|
||||
<uni-forms-item name="name" v-if="formConfig.name">
|
||||
<template #label>
|
||||
<view class="label-box">
|
||||
<text v-if="formConfig.nameMust" class="required">*</text>
|
||||
<image
|
||||
class="label-icon"
|
||||
src="@/assets/images/icon/user.png"
|
||||
>
|
||||
</image>
|
||||
<label>{{$t('contactUs.name')}}</label>
|
||||
</view>
|
||||
</template>
|
||||
<uni-easyinput type="text" v-model="dataForm.name" :placeholder="$t('contactUs.name')" />
|
||||
</uni-forms-item>
|
||||
|
||||
<uni-forms-item name="title" v-if="formConfig.title">
|
||||
<template #label>
|
||||
<view class="label-box">
|
||||
<text v-if="formConfig.titleMust" class="required">*</text>
|
||||
<image
|
||||
class="label-icon"
|
||||
src="@/assets/images/icon/title.png"
|
||||
>
|
||||
</image>
|
||||
<label>{{$t('contactUs.title')}}</label>
|
||||
</view>
|
||||
</template>
|
||||
<uni-easyinput type="text" v-model="dataForm.title" :placeholder="$t('contactUs.title')" />
|
||||
</uni-forms-item>
|
||||
|
||||
<uni-forms-item name="company" v-if="formConfig.company">
|
||||
<template #label>
|
||||
<view class="label-box">
|
||||
<text v-if="formConfig.companyMust" class="required">*</text>
|
||||
<image
|
||||
class="label-icon"
|
||||
src="@/assets/images/icon/company.png"
|
||||
>
|
||||
</image>
|
||||
<label>{{$t('contactUs.company')}}</label>
|
||||
</view>
|
||||
</template>
|
||||
<uni-easyinput type="text" v-model="dataForm.company" :placeholder="$t('contactUs.company')" />
|
||||
</uni-forms-item>
|
||||
|
||||
<uni-forms-item name="email" v-if="formConfig.email">
|
||||
<template #label>
|
||||
<view class="label-box">
|
||||
<text v-if="formConfig.emailMust" class="required">*</text>
|
||||
<image
|
||||
class="label-icon"
|
||||
src="@/assets/images/icon/mail.png"
|
||||
>
|
||||
</image>
|
||||
<label>{{$t('contactUs.mail')}}</label>
|
||||
</view>
|
||||
</template>
|
||||
<uni-easyinput type="text" v-model="dataForm.email" :placeholder="$t('contactUs.mail')" />
|
||||
</uni-forms-item>
|
||||
|
||||
<uni-forms-item name="tel" v-if="formConfig.tel">
|
||||
<template #label>
|
||||
<view class="label-box">
|
||||
<text v-if="formConfig.telMust" class="required">*</text>
|
||||
<image
|
||||
class="label-icon"
|
||||
src="@/assets/images/icon/phone.png"
|
||||
>
|
||||
</image>
|
||||
<label>{{$t('contactUs.contactWay')}}</label>
|
||||
</view>
|
||||
</template>
|
||||
<uni-easyinput type="text" v-model="dataForm.tel" :placeholder="$t('contactUs.contactWay')" />
|
||||
</uni-forms-item>
|
||||
|
||||
<uni-forms-item name="content">
|
||||
<template #label>
|
||||
<view class="label-box">
|
||||
<image
|
||||
class="label-icon"
|
||||
src="@/assets/images/icon/msg.png"
|
||||
>
|
||||
</image>
|
||||
<label>{{$t('contactUs.desc')}}</label>
|
||||
</view>
|
||||
</template>
|
||||
<uni-easyinput type="textarea" v-model="dataForm.content" :placeholder="$t('contactUs.desc')" />
|
||||
</uni-forms-item>
|
||||
|
||||
<button class="submit-btn" @click="submit">{{$t('common.sending')}}</button>
|
||||
</uni-forms>
|
||||
</view>
|
||||
|
||||
<view class="module">
|
||||
{{$t('news.relatedProducts')}}
|
||||
</view>
|
||||
|
||||
<view class="container">
|
||||
<view class="product-list">
|
||||
<view
|
||||
class="product-item"
|
||||
v-for="item in relatedProducts"
|
||||
:key="item.id"
|
||||
>
|
||||
<image class="cover" :src="item.mainPic" mode="aspectFill"></image>
|
||||
<view class="text-ellipsis title">
|
||||
{{item.title}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref } from 'vue';
|
||||
import { ref, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import {
|
||||
prodOrNewsInfoApi,
|
||||
formOptionsApi,
|
||||
submitFormApi,
|
||||
} from '@/api/index.js';
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const tabsActive = ref(0)
|
||||
const tabsList = [
|
||||
t('menu.Products'),
|
||||
t('products.productDetails'),
|
||||
t('products.inquiry'),
|
||||
t('news.relatedProducts')
|
||||
]
|
||||
|
||||
const id = ref('')
|
||||
const info = ref({})
|
||||
const productsImages = ref([])
|
||||
const getInfo = () => {
|
||||
prodOrNewsInfoApi(id.value).then(({data:res}) => {
|
||||
info.value = res.data.busiProdNew
|
||||
let picsArr = res.data.busiProdNew.pics ? res.data.busiProdNew.pics.split(',') : [];
|
||||
productsImages.value = [
|
||||
res.data.busiProdNew.mainPic,
|
||||
...picsArr
|
||||
]
|
||||
uni.setNavigationBarTitle({
|
||||
title: res.data.busiProdNew.title
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const swiperCurrent = ref(0)
|
||||
const swiperChange = (e) => {
|
||||
swiperCurrent.value = e.detail.current
|
||||
}
|
||||
|
||||
const dataFormRef = ref()
|
||||
const dataForm = ref({
|
||||
name: '',
|
||||
title: '',
|
||||
company: '',
|
||||
email: '',
|
||||
tel: '',
|
||||
content: '',
|
||||
equipment: 'App'
|
||||
})
|
||||
const dataFormRules = computed(() => {
|
||||
let config = formConfig.value
|
||||
let rules = {
|
||||
name: {
|
||||
rules: [
|
||||
{ required: config.nameMust, errorMessage: t('contactUs.name') }
|
||||
]
|
||||
},
|
||||
title: {
|
||||
rules: [
|
||||
{ required: config.titleMust, errorMessage: t('contactUs.title') }
|
||||
]
|
||||
},
|
||||
company: {
|
||||
rules: [
|
||||
{ required: config.companyMust, errorMessage: t('contactUs.company') }
|
||||
]
|
||||
},
|
||||
email: {
|
||||
rules: [
|
||||
{ required: config.emailMust, errorMessage: t('contactUs.mail') }
|
||||
]
|
||||
},
|
||||
tel: {
|
||||
rules: [
|
||||
{ required: config.telMust, errorMessage: t('contactUs.desc') }
|
||||
]
|
||||
}
|
||||
}
|
||||
return rules
|
||||
})
|
||||
const formConfig = ref({})
|
||||
const getFormOptions = () => {
|
||||
formOptionsApi().then(({data:res}) => {
|
||||
formConfig.value = res.data
|
||||
})
|
||||
}
|
||||
const submit = () => {
|
||||
dataFormRef.value.validate().then(() => {
|
||||
submitFormApi(dataForm.value).then(() => {
|
||||
uni.$showTost(t('common.submitSuccess'))
|
||||
dataForm.value.name = ''
|
||||
dataForm.value.title = ''
|
||||
dataForm.value.company = ''
|
||||
dataForm.value.email = ''
|
||||
dataForm.value.tel = ''
|
||||
dataForm.value.content = ''
|
||||
dataFormRef.value.clearValidate()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const relatedProducts = ref([
|
||||
{id:123,title: 'SINOTRUK HOWO Tractor Truck Head',mainPic:'https://dianliang123.oss-cn-qingdao.aliyuncs.com/user/2025/07/09/55979a0deee24031a38e934c6b06ca20.jpg'},
|
||||
{id:121233,title: 'SINOTRUK HOWO Tractor Truck Head',mainPic:'https://dianliang123.oss-cn-qingdao.aliyuncs.com/user/2025/07/09/55979a0deee24031a38e934c6b06ca20.jpg'},
|
||||
{id:122221113,title: 'SINOTRUK HOWO Tractor Truck Head',mainPic:'https://dianliang123.oss-cn-qingdao.aliyuncs.com/user/2025/07/09/55979a0deee24031a38e934c6b06ca20.jpg'},
|
||||
{id:121113123,title: 'SINOTRUK HOWO Tractor Truck Head',mainPic:'https://dianliang123.oss-cn-qingdao.aliyuncs.com/user/2025/07/09/55979a0deee24031a38e934c6b06ca20.jpg'}
|
||||
])
|
||||
|
||||
onLoad((options) => {
|
||||
id.value = options.id
|
||||
getInfo()
|
||||
getFormOptions()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.pages {
|
||||
overflow: hidden;
|
||||
padding: 0 18rpx;
|
||||
::v-deep .tabs {
|
||||
justify-content: space-around;
|
||||
.tabs-item {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
.container {
|
||||
width: 100%;
|
||||
height: min-content;
|
||||
background-color: #ffffff;
|
||||
position: relative;
|
||||
border-radius: 20rpx;
|
||||
overflow-x: auto;
|
||||
word-break: break-all;
|
||||
.swiper {
|
||||
width: 100%;
|
||||
height: 714rpx;
|
||||
.swiper-item {
|
||||
width: 100%;
|
||||
height: 714rpx;
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.siwper-number {
|
||||
width: max-content;
|
||||
height: min-content;
|
||||
padding: 6rpx 30rpx;
|
||||
position: absolute;
|
||||
top: 650rpx;
|
||||
right: 28rpx;
|
||||
border-radius: 28rpx;
|
||||
color: #fff;
|
||||
background: rgba(0,0,0,0.31);
|
||||
z-index: 999;
|
||||
}
|
||||
.info {
|
||||
width: 100%;
|
||||
padding: 34rpx 20rpx;
|
||||
.title {
|
||||
margin-bottom: 40rpx;
|
||||
color: #292d2e;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.inquiry-bg {
|
||||
width: 100%;
|
||||
height: 411rpx;
|
||||
}
|
||||
::v-deep .form-box {
|
||||
padding: 0rpx 24rpx;
|
||||
position: relative;
|
||||
top: -150rpx;
|
||||
}
|
||||
.product-list {
|
||||
padding: 38rpx 12rpx;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
background-color: #fff;
|
||||
.product-item {
|
||||
width: 49%;
|
||||
height: 468rpx;
|
||||
margin-bottom: 14rpx;
|
||||
border: 2rpx solid #ebf3f7;
|
||||
border-radius: 8rpx;
|
||||
&:nth-child(2n) {
|
||||
margin-left: 2%;
|
||||
}
|
||||
.cover {
|
||||
width: 100%;
|
||||
height: 358rpx;
|
||||
}
|
||||
.title {
|
||||
padding: 16rpx 16rpx 0;
|
||||
color: #0d0e0e;
|
||||
border-top: 2rpx dashed #ebf3f7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.module {
|
||||
margin: 38rpx 0;
|
||||
color: #292d2e;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
BIN
src/assets/images/bg/Inquiry-bg.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/assets/images/icon/Google.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/images/icon/X.png
Normal file
After Width: | Height: | Size: 817 B |
BIN
src/assets/images/icon/YouTobe.png
Normal file
After Width: | Height: | Size: 596 B |
BIN
src/assets/images/icon/facebook.png
Normal file
After Width: | Height: | Size: 464 B |
BIN
src/assets/images/icon/in.png
Normal file
After Width: | Height: | Size: 543 B |
BIN
src/assets/images/icon/phoneApp.png
Normal file
After Width: | Height: | Size: 733 B |
@ -47,7 +47,8 @@
|
||||
"viewmore": "view more",
|
||||
"ProductLabel": "Product",
|
||||
"keywords": "keywords",
|
||||
"Quickcontact": "Quick contact"
|
||||
"Quickcontact": "Quick contact",
|
||||
"sending": "sending"
|
||||
},
|
||||
"menu": {
|
||||
"Home": "Home",
|
||||
|
@ -47,7 +47,8 @@
|
||||
"viewmore": "查看更多",
|
||||
"ProductLabel": "产品",
|
||||
"keywords": "关键字",
|
||||
"Quickcontact": "快速联系"
|
||||
"Quickcontact": "快速联系",
|
||||
"sending": "发送"
|
||||
},
|
||||
"menu": {
|
||||
"Home": "首页",
|
||||
|
@ -49,7 +49,8 @@
|
||||
"path": "product-details",
|
||||
"style": {
|
||||
"navigationBarTitleText": "Product details",
|
||||
"enablePullDownRefresh": true
|
||||
"enablePullDownRefresh": true,
|
||||
"navigationStyle": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -74,6 +74,7 @@
|
||||
class="prod-item"
|
||||
v-for="item in prodList"
|
||||
:key="item.id"
|
||||
@click="goProdDetails(item)"
|
||||
>
|
||||
<image :src="item.mainPic" mode="aspectFit"></image>
|
||||
<view class="text-ellipsis">
|
||||
@ -179,10 +180,10 @@
|
||||
|
||||
const onlineModalShow = ref(false)
|
||||
const onlineModalRef = ref()
|
||||
const clickMsg = () => {
|
||||
onlineModalShow.value = false
|
||||
nextTick(() => {
|
||||
|
||||
|
||||
const goProdDetails = (row) => {
|
||||
uni.navigateTo({
|
||||
url: `/application/product-details?id=${row.id}`
|
||||
})
|
||||
}
|
||||
|
||||
|