开发产品详情页面,调试接口 90%
@ -70,4 +70,12 @@ export const prodOrNewsCatgApi = (catgId) => {
|
|||||||
**/
|
**/
|
||||||
export const prodPageApi = (params) => {
|
export const prodPageApi = (params) => {
|
||||||
return request.get('/web/prodPageList', {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>
|
<template>
|
||||||
<view class="pages">
|
<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>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onLoad } from '@dcloudio/uni-app';
|
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>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<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>
|
</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",
|
"viewmore": "view more",
|
||||||
"ProductLabel": "Product",
|
"ProductLabel": "Product",
|
||||||
"keywords": "keywords",
|
"keywords": "keywords",
|
||||||
"Quickcontact": "Quick contact"
|
"Quickcontact": "Quick contact",
|
||||||
|
"sending": "sending"
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"Home": "Home",
|
"Home": "Home",
|
||||||
|
@ -47,7 +47,8 @@
|
|||||||
"viewmore": "查看更多",
|
"viewmore": "查看更多",
|
||||||
"ProductLabel": "产品",
|
"ProductLabel": "产品",
|
||||||
"keywords": "关键字",
|
"keywords": "关键字",
|
||||||
"Quickcontact": "快速联系"
|
"Quickcontact": "快速联系",
|
||||||
|
"sending": "发送"
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"Home": "首页",
|
"Home": "首页",
|
||||||
|
@ -49,7 +49,8 @@
|
|||||||
"path": "product-details",
|
"path": "product-details",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "Product details",
|
"navigationBarTitleText": "Product details",
|
||||||
"enablePullDownRefresh": true
|
"enablePullDownRefresh": true,
|
||||||
|
"navigationStyle": "default"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
class="prod-item"
|
class="prod-item"
|
||||||
v-for="item in prodList"
|
v-for="item in prodList"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
|
@click="goProdDetails(item)"
|
||||||
>
|
>
|
||||||
<image :src="item.mainPic" mode="aspectFit"></image>
|
<image :src="item.mainPic" mode="aspectFit"></image>
|
||||||
<view class="text-ellipsis">
|
<view class="text-ellipsis">
|
||||||
@ -179,10 +180,10 @@
|
|||||||
|
|
||||||
const onlineModalShow = ref(false)
|
const onlineModalShow = ref(false)
|
||||||
const onlineModalRef = ref()
|
const onlineModalRef = ref()
|
||||||
const clickMsg = () => {
|
|
||||||
onlineModalShow.value = false
|
const goProdDetails = (row) => {
|
||||||
nextTick(() => {
|
uni.navigateTo({
|
||||||
|
url: `/application/product-details?id=${row.id}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|