hookehuyr

产品详情页接口相关页面联调

/*
* @Date: 2024-09-26 13:36:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-10-23 13:47:59
* @LastEditTime: 2024-10-23 16:23:08
* @FilePath: /hager/src/api/hager.js
* @Description: 文件描述
*/
......@@ -13,6 +13,7 @@ const Api = {
NEWS_DETAIL: '/srv/?a=detail&type=news',
HOME: '/srv/?a=home',
PRODUCT_CATE: '/srv/?a=cate&type=product',
PRODUCT_INFO: '/srv/?a=detail&type=product',
};
export const honorAPI = (params) => fn(fetch.get(Api.HONOR, params));
......@@ -20,3 +21,4 @@ export const newsAPI = (params) => fn(fetch.get(Api.NEWS, params));
export const getNewsDetailAPI = (params) => fn(fetch.get(Api.NEWS_DETAIL, params));
export const getHomeAPI = (params) => fn(fetch.get(Api.HOME, params));
export const getProductCateAPI = (params) => fn(fetch.get(Api.PRODUCT_CATE, params));
export const getProductInfoAPI = (params) => fn(fetch.get(Api.PRODUCT_INFO, params));
......
<!--
* @Date: 2024-09-26 13:42:11
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-10-23 17:05:50
* @LastEditTime: 2024-10-23 17:08:32
* @FilePath: /hager/src/components/common/hagerHeader.vue
* @Description: 文件描述
-->
......@@ -222,7 +222,6 @@ export default {
for (let i = 0; i < product.list?.length; i += maxLength) {
listChunks.push(product.list.slice(i, i + maxLength));
}
console.warn(listChunks);
// 第一个块保留原有的 name,后续块 name 设为空
listChunks.forEach((chunk, index) => {
......@@ -242,7 +241,6 @@ export default {
});
}
});
console.warn('res', result);
return result;
},
......
<!--
* @Date: 2024-09-27 19:49:03
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-09-30 10:04:50
* @LastEditTime: 2024-10-23 17:25:41
* @FilePath: /hager/src/components/hagerCarousel.vue
* @Description: 文件描述
-->
......@@ -30,8 +30,8 @@
</div>
<!-- 右边大图区域 -->
<div class="main-image" :class="{ 'fade-out': isTransitioning, 'fade-in': !isTransitioning }">
<img :src="images[selectedImage]" alt="main image">
<div class="main-image" :class="{ 'fade-out': isTransitioning, 'fade-in': !isTransitioning }" :style="{ backgroundImage: `url(${images[selectedImage]})`}">
<!-- <img :src="images[selectedImage]" alt="main image"> -->
</div>
</div>
</div>
......@@ -163,18 +163,22 @@ export default {
}
.main-image {
width: 300px;
height: 300px;
width: 18rem;
height: 18rem;
position: relative;
transition: opacity 0.5s ease-in-out; /* 大图切换时的淡入淡出效果 */
opacity: 1;
background-position: center;
background-size: 80%;
background-repeat: no-repeat;
}
.main-image img {
width: 100%;
height: 100%;
width: 80%;
height: 80%;
object-fit: cover;
position: absolute;
top: 20%;
}
.main-image.fade-out {
......
<!--
* @Date: 2024-10-10 10:37:16
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-10-23 14:28:22
* @LastEditTime: 2024-10-23 16:39:02
* @FilePath: /hager/src/components/hagerMenu.vue
* @Description: 文件描述
-->
......@@ -27,7 +27,7 @@
:class="['menu-label', activeMenu === item.id ? 'active' : '']"
>
<div>
<el-image style="width: auto; height: 1rem" :src="item.cover" fit="fit"></el-image>
<el-image style="width: auto; height: 1rem" :src="item.icon" fit="fit"></el-image>
{{ item.category_name }}
</div>
<div>
......
/*
* @Date: 2024-08-26 10:42:15
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-10-21 09:59:04
* @LastEditTime: 2024-10-23 16:46:46
* @FilePath: /hager/src/route.js
* @Description: 文件描述
*/
......@@ -15,15 +15,6 @@ export default [{
},
children: []
}, {
path: '/product/category',
name: '产品类别',
component: () => import('@/views/product/category'),
meta: {
title: '海格电器',
tag: 'product'
},
children: []
}, {
path: '/product/index',
name: '二级目录',
component: () => import('@/views/product/index'),
......
<!--
* @Date: 2024-08-27 10:06:30
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-10-23 15:58:51
* @LastEditTime: 2024-10-23 16:32:21
* @FilePath: /hager/src/views/index.vue
* @Description: 首页
-->
......@@ -110,7 +110,7 @@
<!-- <div v-if="product_list.length <= productSlidesPerView" class="more-box" style="margin-top: 2rem;">
<hager-more></hager-more>
</div> -->
<div v-if="product_list.length > productSlidesPerView || is_xs" class="hager-product-center-more xs">
<div v-if="product_list.length > productSlidesPerView || is_xs || !isEnd" class="hager-product-center-more xs">
<!-- <hager-more></hager-more> -->
<div class="xs-control">
<div>
......@@ -306,6 +306,7 @@ export default {
reach_solution_end: false,
reach_product_end: false,
productSlidesPerView: 5,
isEnd: true,
}
},
async mounted () {
......@@ -314,10 +315,11 @@ export default {
console.warn(data);
this.product_list = data.product;
}
this.isEnd = this.$refs.myProductSwiper.$swiper.isEnd; // 是否全部显示出来
this.$nextTick(() => {
this.$refs.myProductSwiper.$swiper?.on('breakpoint', (swiper) => {
// breakpoint时 显示的条数
this.productSlidesPerView = swiper.slidesPerView
this.productSlidesPerView = swiper.slidesPerView;
});
});
},
......
<!--
* @Date: 2024-09-29 14:26:41
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-10-23 10:04:04
* @LastEditTime: 2024-10-23 18:29:36
* @FilePath: /hager/src/views/product/detail.vue
* @Description: 文件描述
-->
......@@ -11,40 +11,30 @@
<div style="margin-top: 1.5rem;">
<el-breadcrumb separator="/">
<el-breadcrumb-item v-if="!is_xs">所有产品</el-breadcrumb-item>
<el-breadcrumb-item>配电产品</el-breadcrumb-item>
<el-breadcrumb-item>低压主配电</el-breadcrumb-item>
<el-breadcrumb-item>HW+系列空气断路器</el-breadcrumb-item>
<el-breadcrumb-item>{{ info.parent_name }}</el-breadcrumb-item>
<el-breadcrumb-item>{{ info.category_name }}</el-breadcrumb-item>
<el-breadcrumb-item>{{ info.product_name }}</el-breadcrumb-item>
</el-breadcrumb>
</div>
</hager-box>
<hager-box class="box-n">
<el-row v-if="!is_xs" :gutter="10" style="margin-bottom: 3rem;">
<el-col :span="10">
<hager-carousel :images="images"></hager-carousel>
<el-col :span="8">
<hager-carousel :images="info_images"></hager-carousel>
</el-col>
<el-col :span="14">
<el-col :span="16">
<div class="product-detail-info">
<div class="product-title" style="">HW+系列空气断路器</div>
<div class="product-sub" style="margin: 1rem 0 2rem;">全新智能型hw+系列空气断路器,可搭载集通讯、自诊断、功能编程、维护预警、远程监控、测量、报警、保护功能于一体的Sentinel Energy控制器。</div>
<ul class="product-info-list">
<li>实现谐波测量,实时监测电能质量;</li>
<li>图文显示多电量参数,系统状态一目了然;</li>
<li>支持Modbus远程通讯协议,无线蓝牙连接等多种通讯方式,全方位提升客户的数字化体验。</li>
</ul>
<div class="product-title" style="">{{ info.product_name }}</div>
<div class="product-sub" style="margin: 1rem 0 2rem;" v-html="info.post_excerpt"></div>
</div>
</el-col>
</el-row>
<div v-else>
<div class="product-detail-info">
<div class="product-title" style="">HW+系列空气断路器</div>
<div class="product-sub" style="margin: 1rem 0 2rem;">全新智能型hw+系列空气断路器,可搭载集通讯、自诊断、功能编程、维护预警、远程监控、测量、报警、保护功能于一体的Sentinel Energy控制器。</div>
<ul class="product-info-list">
<li>实现谐波测量,实时监测电能质量;</li>
<li>图文显示多电量参数,系统状态一目了然;</li>
<li>支持Modbus远程通讯协议,无线蓝牙连接等多种通讯方式,全方位提升客户的数字化体验。</li>
</ul>
<div class="product-title" style="">{{ info.product_name }}</div>
<div class="product-sub" style="margin: 1rem 0 2rem;" v-html="info.post_excerpt"></div>
</div>
<div v-for="(item, index) in images" :key="index" class="product-item-img">
<div v-for="(item, index) in info_images" :key="index" class="product-item-img">
<el-image style="height: 14rem;" :src="item" fit="cover"></el-image>
</div>
</div>
......@@ -52,10 +42,9 @@
<hager-box class="box-2n">
<hager-h1 title="产品优势" sub="Product advantages"></hager-h1>
<div :class="['product-advantage', is_xs ? 'xs' : '']">
<div :class="['item', is_xs ? 'xs' : '']" v-for="(item, index) in 3" :key="index">
<el-row :gutter="0" v-for="(item, index) in 5" :key="index">
<el-col :span="6">极致的分断能力:</el-col>
<el-col :span="18">标配独立的故障指示触点、远程复位、ZSI保护功能</el-col>
<div :class="['item', is_xs ? 'xs' : '']" v-for="(item, index) in product_advantages" :key="index">
<el-row :gutter="0" v-for="(x, idx) in item" :key="idx">
<el-col :span="24">{{ x }}</el-col>
</el-row>
</div>
</div>
......@@ -64,15 +53,21 @@
<hager-h1 title="产品资料" sub="Product Information"></hager-h1>
<div class="product-info">
<div class="info-control">
<el-row :gutter="0">
<el-col :span="is_xs ? 24 : 19">
<div :class="['control-left', is_xs ? 'xs' : '']">
<div :class="['button', is_xs ? 'xs' : '', is_active === 0 ? 'active' : '']" @click="onClick(0)">产品样本</div>
<div :class="['button', is_xs ? 'xs' : '', is_active === 1 ? 'active' : '']" @click="onClick(1)">技术参数</div>
<div :class="['button', is_xs ? 'xs' : '', is_active === 2 ? 'active' : '']" @click="onClick(2)">产品说明书</div>
<div :class="['button', is_xs ? 'xs' : '', is_active === 3 ? 'active' : '']" @click="onClick(3)">安装教程</div>
<div v-if="product_sample" :class="['button', is_xs ? 'xs' : '', is_active === 0 ? 'active' : '']" @click="onClick(0, product_sample)">产品样本</div>
<div v-if="technical_parameter" :class="['button', is_xs ? 'xs' : '', is_active === 1 ? 'active' : '']" @click="onClick(1, technical_parameter)">技术参数</div>
<div v-if="product_manual" :class="['button', is_xs ? 'xs' : '', is_active === 2 ? 'active' : '']" @click="onClick(2, product_manual)">产品说明书</div>
<div v-if="installation_tutorial" :class="['button', is_xs ? 'xs' : '', is_active === 3 ? 'active' : '']" @click="onClick(3, installation_tutorial)">安装教程</div>
</div>
<div v-if="!is_xs">
</el-col>
<el-col v-if="!is_xs" :span="5">
<div>
<div @click="goToDownload" :class="['button', is_download_checked ? 'active' : '']">发送到邮箱</div>
</div>
</el-col>
</el-row>
</div>
<div>
<div class="mini-download-wrapper" v-if="is_xs">
......@@ -83,17 +78,34 @@
<div @click="goToDownload" :class="['button', is_download_checked ? 'active' : '']">发送到邮箱</div>
</div>
<div class="info-list" v-for="(item, index) in download_list" :key="index">
<el-row :gutter="0">
<el-col :span="18">
<div class="info-list-title">
<i v-if="item.checked" @click="item.checked = !item.checked" class="el-icon-folder-checked download-checked"></i>
<i v-else @click="item.checked = !item.checked" class="el-icon-folder download-unchecked"></i>
<i class="el-icon-document" style="font-size: 1.25rem; margin-left: 1rem;"></i>&nbsp;&nbsp;{{ item.name }}&nbsp;&nbsp;{{ item.size }}
<el-row :gutter="0">
<el-col :span="is_xs ? 4 : 2">
<i v-if="item.checked" @click="checkItem(item)" class="el-icon-folder-checked download-checked"></i>
<i v-else @click="checkItem(item)" class="el-icon-folder download-unchecked"></i>&nbsp;
</el-col>
<el-col :span="is_xs ? 20 : 22">
<i class="el-icon-document" style="font-size: 1.5rem;"></i>
{{ item.name }}{{ item.size }}
</el-col>
</el-row>
<!-- <i v-if="item.checked" @click="checkItem(item)" class="el-icon-folder-checked download-checked"></i>
<i v-else @click="checkItem(item)" class="el-icon-folder download-unchecked"></i>
<i class="el-icon-document" style="font-size: 1.25rem; margin-left: 1rem;"></i>
<p><span>{{ item.name }}</span><span>{{ item.size }}</span></p> -->
</div>
</el-col>
<el-col :span="6">
<div class="info-list-control">
<div @click="preview(item)">预览</div>
<div @click="sendEmail" class="icon-wrapper">
<img style="height: 1rem;" src="https://cdn.ipadbiz.cn/hager/icon/%E9%82%AE%E4%BB%B6@2x.png">
<img style="height: 1rem; width: auto;" src="https://cdn.ipadbiz.cn/hager/icon/%E9%82%AE%E4%BB%B6@2x.png">
</div>
</div>
</el-col>
</el-row>
</div>
</div>
</div>
......@@ -107,6 +119,7 @@ import hagerBox from '@/components/common/hagerBox';
import hagerCarousel from '@/components/hagerCarousel';
import hagerH1 from '@/components/common/hagerH1.vue';
import { MessageBox, Message } from 'element-ui';
import { getProductInfoAPI } from "@/api/hager.js";
export default {
components: { hagerBox, hagerCarousel, hagerH1 },
......@@ -114,23 +127,15 @@ export default {
data () {
return {
is_active: 0,
download_list: [{
id: '123',
name: '产品样本',
size: '123MB',
checked: false
}, {
id: '123',
name: '产品样本',
size: '123MB',
checked: false
}],
images: [
"https://cdn.ipadbiz.cn/hager/img/product/P11.jpg",
"https://cdn.ipadbiz.cn/hager/img/product/t01.jpg",
"https://cdn.ipadbiz.cn/hager/img/product/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20240920151453.png",
"https://cdn.ipadbiz.cn/hager/img/product/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20240920151457.png",
]
download_list: [],
images: [],
info: {},
info_images: [],
product_advantages: [],
product_sample: '',
technical_parameter: '',
product_manual: '',
installation_tutorial: '',
}
},
computed: {
......@@ -141,12 +146,46 @@ export default {
return this.download_list.filter(item => item.checked).length;
},
},
mounted () {
async mounted () {
this.getInfo();
},
watch: {
// 监听路由参数变化时,更新输入框的值
async '$route.query.id' (val, old) {
if (old !== val) {
this.getInfo();
}
}
},
methods: {
onClick (n) {
async getInfo () {
const { code, data } = await getProductInfoAPI( { id: this.$route.query.id });
if (code) {
this.info = data;
if (this.info.file?.img) {
this.info_images = this.info.file.img.map(item => item.value);
}
//
this.product_advantages = this.splitArrayIntoChunks(this.info.product_advantages);
//
this.product_sample = this.info.file?.yangben?.map(item => ({ ...item, checked: false }));// 产品样本
this.technical_parameter = this.info.file?.canshu?.map(item => ({ ...item, checked: false })); // 技术参数
this.product_manual = this.info.file?.shuomingshu?.map(item => ({ ...item, checked: false })); // 产品说明书
this.installation_tutorial = this.info.file?.jiaocheng?.map(item => ({ ...item, checked: false })); // 安装教程
let arr = [this.product_sample, this.technical_parameter, this.product_manual, this.installation_tutorial]
for (let index = 0; index < arr.length; index++) {
const element = arr[index];
if (element) {
this.download_list = element;
return;
}
}
}
},
onClick (n , item) {
this.is_active = n;
this.download_list = item;
this.download_list.forEach(item => item.checked = false);
},
goToDownload () {
if (this.is_download_checked) {
......@@ -168,8 +207,25 @@ export default {
});
},
preview (item) {
window.open(item, '_blank');
window.open(item.value, '_blank');
},
splitArrayIntoChunks(list) {
const productAdvantages = list;
const chunkSize = 5;
const result = [];
for (let i = 0; i < productAdvantages.length; i += chunkSize) {
// 使用 slice 方法按每组 5 个元素分割
const chunk = productAdvantages.slice(i, i + chunkSize);
result.push(chunk);
}
return result;
},
checkItem (item) {
item.checked = !item.checked;
// this.$forceUpdate();
},
}
}
</script>
......@@ -191,8 +247,8 @@ export default {
color: @secondary-color;
}
.product-sub {
margin: 1rem 0 2rem;
color: @text-color;
// margin: 1rem 0 2rem;
// color: @text-color;
}
.product-info-list {
padding: 0 1rem;
......@@ -206,16 +262,19 @@ export default {
margin-top: 1rem;
display: flex;
flex-wrap: wrap;
gap: 3rem;
// gap: 3rem;
.item {
flex: 0 1 calc(50% - 3rem); /* 每行2个元素,减去gap的宽度 */
box-sizing: border-box; /* 确保padding和border不会影响宽度计算 */
width: calc(50% - 3rem);
box-sizing: border-box;
margin-right: 3rem;
margin-bottom: 1rem;
padding-top: 1rem;
background-color: #f0f0f0;
border-top: 4px solid @primary-color;
line-height: 2;
&.xs {
padding-bottom: 1rem;
width: 100%;
}
}
&.xs {
......@@ -224,13 +283,13 @@ export default {
}
.product-info {
.info-control {
display: flex;
// display: flex;
border-bottom: 4px solid @primary-color;
padding-bottom: 1rem;
margin-top: 2rem;
.control-left {
display: flex;
flex: 1 0 0;
// flex: 1 0 0;
&.xs {
display: flex;
flex-wrap: nowrap; /* 禁止换行 */
......@@ -259,17 +318,18 @@ export default {
}
}
.info-list {
display: flex;
justify-content: space-between;
align-items: center;
// display: flex;
// justify-content: space-between;
// align-items: center;
padding-top: 2rem;
color: #6b6b6b;
.info-list-title {
display: flex; align-items: center;
// display: flex;
// align-items: center;
}
.info-list-control {
display: flex;
justify-content: center;
justify-content: flex-end;
align-items: center;
color: @primary-color;
div {
......