hookehuyr

✨ feat(产品相关页面): 新增所有产品显示进行调整

...@@ -7,6 +7,8 @@ export {} ...@@ -7,6 +7,8 @@ export {}
7 /* prettier-ignore */ 7 /* prettier-ignore */
8 declare module 'vue' { 8 declare module 'vue' {
9 export interface GlobalComponents { 9 export interface GlobalComponents {
10 + Accordion: typeof import('./src/components/accordion/Accordion.vue')['default']
11 + AccordionItem: typeof import('./src/components/accordion/AccordionItem.vue')['default']
10 ElBreadcrumb: typeof import('element-ui/lib/breadcrumb')['default'] 12 ElBreadcrumb: typeof import('element-ui/lib/breadcrumb')['default']
11 ElBreadcrumbItem: typeof import('element-ui/lib/breadcrumb-item')['default'] 13 ElBreadcrumbItem: typeof import('element-ui/lib/breadcrumb-item')['default']
12 ElCarousel: typeof import('element-ui/lib/carousel')['default'] 14 ElCarousel: typeof import('element-ui/lib/carousel')['default']
......
1 +<!--
2 + * @Date: 2024-11-06 14:01:32
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2024-11-06 14:49:49
5 + * @FilePath: /hager/src/components/accordion/Accordion.vue
6 + * @Description: 文件描述
7 +-->
8 +<template>
9 + <div class="accordion">
10 + <AccordionItem v-for="item in items" :key="item.id" :item="item" style="border-bottom: 1px solid #EBEEF5;" />
11 + </div>
12 +</template>
13 +
14 +<script>
15 +import AccordionItem from './AccordionItem.vue';
16 +
17 +export default {
18 + name: 'Accordion',
19 + components: {
20 + AccordionItem
21 + },
22 + props: {
23 + items: {
24 + type: Array,
25 + required: true
26 + }
27 + }
28 +};
29 +</script>
30 +
31 +<style scoped>
32 +.accordion {
33 + width: 100%;
34 + max-width: 600px;
35 + margin: 0 auto;
36 +}
37 +</style>
1 +<template>
2 + <div class="accordion-item">
3 + <div v-if="hasChildren" class="accordion-header" @click="toggle" :style="item.style">
4 + {{ item.category_name }}
5 + <i v-if="!isOpen" class="el-icon-arrow-right"></i><i v-else class="el-icon-arrow-down"></i>
6 + </div>
7 + <div v-else class="list-item" @click="goToDetail(item)">
8 + {{ item.category_name }}
9 + </div>
10 + <el-collapse-transition>
11 + <div v-if="isOpen || !hasChildren" class="accordion-content">
12 + <p v-if="!hasChildren">{{ item.content }}</p>
13 + <AccordionItem v-for="child in item.children" :key="child.id" :item="child" />
14 + </div>
15 + </el-collapse-transition>
16 + </div>
17 +</template>
18 +
19 +<script>
20 +export default {
21 + name: 'AccordionItem',
22 + props: {
23 + item: {
24 + type: Object,
25 + required: true
26 + }
27 + },
28 + data() {
29 + return {
30 + isOpen: false
31 + };
32 + },
33 + computed: {
34 + hasChildren() {
35 + return this.item.children && this.item.children.length > 0;
36 + }
37 + },
38 + methods: {
39 + toggle() {
40 + if (this.hasChildren) {
41 + this.isOpen = !this.isOpen;
42 + }
43 + },
44 + goToDetail (v) { // 跳转产品详情
45 + this.$router.push({
46 + path: '/product/detail',
47 + query: {
48 + id: v.id,
49 + }
50 + });
51 + }
52 + }
53 +};
54 +</script>
55 +
56 +<style scoped>
57 +.accordion-item {
58 + /* border-bottom: 1px solid #ccc; */
59 +}
60 +.accordion-header {
61 + display: -webkit-box;
62 + display: -ms-flexbox;
63 + display: flex;
64 + -webkit-box-align: center;
65 + -ms-flex-align: center;
66 + align-items: center;
67 + justify-content: space-between;
68 + height: 3rem;
69 + line-height: 1;
70 + background-color: #FFF;
71 + color: #303133;
72 + cursor: pointer;
73 + /* border-bottom: 1px solid #EBEEF5; */
74 + font-size: 0.9rem;
75 + font-weight: 500;
76 + -webkit-transition: border-bottom-color .3s;
77 + transition: border-bottom-color .3s;
78 + outline: 0;
79 +}
80 +.list-item {
81 + font-size: 0.85rem;
82 + line-height: 2;
83 + /* padding: 10px; */
84 + /* background-color: #f0f0f0; */
85 + font-weight: normal;
86 + cursor: default;
87 + &:hover {
88 + text-decoration: underline;
89 + cursor: pointer;
90 + }
91 +}
92 +.accordion-content {
93 + padding-left: 0.5rem;
94 + background-color: #fff;
95 +}
96 +</style>
1 <!-- 1 <!--
2 * @Date: 2024-08-27 10:06:30 2 * @Date: 2024-08-27 10:06:30
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2024-11-04 17:41:28 4 + * @LastEditTime: 2024-11-06 15:04:05
5 * @FilePath: /hager/src/views/index.vue 5 * @FilePath: /hager/src/views/index.vue
6 * @Description: 首页 6 * @Description: 首页
7 --> 7 -->
...@@ -165,7 +165,7 @@ ...@@ -165,7 +165,7 @@
165 </el-row> 165 </el-row>
166 </div> 166 </div>
167 <div class="more-box" style="margin-top: 3rem;"> 167 <div class="more-box" style="margin-top: 3rem;">
168 - <hager-more></hager-more> 168 + <hager-more @click.native="goToNews"></hager-more>
169 </div> 169 </div>
170 </div> 170 </div>
171 <hager-box class="box-n"> 171 <hager-box class="box-n">
......
1 <!-- 1 <!--
2 * @Date: 2024-09-29 14:26:41 2 * @Date: 2024-09-29 14:26:41
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2024-11-05 10:34:50 4 + * @LastEditTime: 2024-11-06 15:34:53
5 * @FilePath: /hager/src/views/product/detail.vue 5 * @FilePath: /hager/src/views/product/detail.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
10 <hager-box> 10 <hager-box>
11 <div style="margin-top: 1.5rem;"> 11 <div style="margin-top: 1.5rem;">
12 <el-breadcrumb separator="/"> 12 <el-breadcrumb separator="/">
13 - <el-breadcrumb-item v-if="!is_xs">所有产品</el-breadcrumb-item> 13 + <el-breadcrumb-item v-if="!is_xs" :to="{ path: '/product/index' }">所有产品</el-breadcrumb-item>
14 <el-breadcrumb-item :to="{ path: productPath }">{{ info.parent_name }}</el-breadcrumb-item> 14 <el-breadcrumb-item :to="{ path: productPath }">{{ info.parent_name }}</el-breadcrumb-item>
15 <!-- <el-breadcrumb-item>{{ info.parent_name }}</el-breadcrumb-item> --> 15 <!-- <el-breadcrumb-item>{{ info.parent_name }}</el-breadcrumb-item> -->
16 <el-breadcrumb-item :to="{ path: categoryPath }">{{ info.category_name }}</el-breadcrumb-item> 16 <el-breadcrumb-item :to="{ path: categoryPath }">{{ info.category_name }}</el-breadcrumb-item>
...@@ -184,6 +184,12 @@ export default { ...@@ -184,6 +184,12 @@ export default {
184 async mounted () { 184 async mounted () {
185 this.getInfo(); 185 this.getInfo();
186 this.getUserInfo(); 186 this.getUserInfo();
187 + // 监听 popstate 事件
188 + window.addEventListener('popstate', this.handlePopState);
189 + },
190 + beforeDestroy() {
191 + // 移除事件监听器
192 + window.removeEventListener('popstate', this.handlePopState);
187 }, 193 },
188 watch: { 194 watch: {
189 // 监听路由参数变化时,更新输入框的值 195 // 监听路由参数变化时,更新输入框的值
...@@ -194,6 +200,17 @@ export default { ...@@ -194,6 +200,17 @@ export default {
194 } 200 }
195 }, 201 },
196 methods: { 202 methods: {
203 + goToMenu (evt) {
204 + // 阻止默认行为
205 + evt.preventDefault();
206 + },
207 + handlePopState(event) {
208 + // 自定义跳转逻辑
209 + console.log('popstate triggered', event);
210 +
211 + // 例如:跳转到指定路径
212 + // this.$router.push('/custom-page');
213 + },
197 async getInfo () { 214 async getInfo () {
198 this.download_list = [{ 215 this.download_list = [{
199 id: 1, 216 id: 1,
......
1 <!-- 1 <!--
2 * @Date: 2024-09-27 16:53:09 2 * @Date: 2024-09-27 16:53:09
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2024-11-04 17:34:49 4 + * @LastEditTime: 2024-11-06 15:52:49
5 * @FilePath: /hager/src/views/product/index.vue 5 * @FilePath: /hager/src/views/product/index.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
...@@ -9,11 +9,14 @@ ...@@ -9,11 +9,14 @@
9 <div class="product-index"> 9 <div class="product-index">
10 <hager-box> 10 <hager-box>
11 <div v-if="!is_search" style="margin-top: 1.5rem;"> 11 <div v-if="!is_search" style="margin-top: 1.5rem;">
12 - <el-breadcrumb separator="/"> 12 + <el-breadcrumb v-if="!is_all_cate" separator="/">
13 - <el-breadcrumb-item>所有产品</el-breadcrumb-item> 13 + <el-breadcrumb-item :to="{ path: allPath }">所有产品</el-breadcrumb-item>
14 <el-breadcrumb-item v-if="parent_name" :to="{ path: productPath }">{{ parent_name }}</el-breadcrumb-item> 14 <el-breadcrumb-item v-if="parent_name" :to="{ path: productPath }">{{ parent_name }}</el-breadcrumb-item>
15 <el-breadcrumb-item>{{ category_name }}</el-breadcrumb-item> 15 <el-breadcrumb-item>{{ category_name }}</el-breadcrumb-item>
16 </el-breadcrumb> 16 </el-breadcrumb>
17 + <el-breadcrumb v-else separator="/">
18 + <el-breadcrumb-item>所有产品</el-breadcrumb-item>
19 + </el-breadcrumb>
17 </div> 20 </div>
18 <hager-h1 v-if="!is_search" :title="category_name" :sub="category_name_en" style="margin: 2rem 0;"></hager-h1> 21 <hager-h1 v-if="!is_search" :title="category_name" :sub="category_name_en" style="margin: 2rem 0;"></hager-h1>
19 <hager-h1 v-else :title="'与“' + keyword + '”相关的搜索结果'" :sub="''" style="margin: 2rem 0;"></hager-h1> 22 <hager-h1 v-else :title="'与“' + keyword + '”相关的搜索结果'" :sub="''" style="margin: 2rem 0;"></hager-h1>
...@@ -22,11 +25,12 @@ ...@@ -22,11 +25,12 @@
22 <div class="product-nav-wrapper"> 25 <div class="product-nav-wrapper">
23 <div class="product-nav-title">按产品类别查找</div> 26 <div class="product-nav-title">按产品类别查找</div>
24 <el-input style="margin-bottom: 0.5rem;" placeholder="请输入产品" prefix-icon="el-icon-search" v-model="search_keyword" @change="goToSearch"></el-input> 27 <el-input style="margin-bottom: 0.5rem;" placeholder="请输入产品" prefix-icon="el-icon-search" v-model="search_keyword" @change="goToSearch"></el-input>
25 - <el-collapse v-model="activeNames" @change="handleChange"> 28 + <el-collapse v-if="!is_all_cate" v-model="activeNames" @change="handleChange">
26 <el-collapse-item v-for="(item, index) in cate_list" :key="index" :title="item.category_name" :name="item.category_name"> 29 <el-collapse-item v-for="(item, index) in cate_list" :key="index" :title="item.category_name" :name="item.category_name">
27 <div @click="goToDetail(c)" v-for="(c, idx) in item.list" :key="idx" class="p-item">{{ c.product_name }}</div> 30 <div @click="goToDetail(c)" v-for="(c, idx) in item.list" :key="idx" class="p-item">{{ c.product_name }}</div>
28 </el-collapse-item> 31 </el-collapse-item>
29 </el-collapse> 32 </el-collapse>
33 + <Accordion v-else :items="all_cate_list" />
30 </div> 34 </div>
31 </el-col> 35 </el-col>
32 <el-col :span="18"> 36 <el-col :span="18">
...@@ -58,10 +62,11 @@ ...@@ -58,10 +62,11 @@
58 import mixin from 'common/mixin'; 62 import mixin from 'common/mixin';
59 import hagerBox from '@/components/common/hagerBox'; 63 import hagerBox from '@/components/common/hagerBox';
60 import hagerH1 from '@/components/common/hagerH1.vue'; 64 import hagerH1 from '@/components/common/hagerH1.vue';
65 +import Accordion from '@/components/accordion/Accordion.vue';
61 import { getProductCateAPI, getProductSearchAPI } from "@/api/hager.js"; 66 import { getProductCateAPI, getProductSearchAPI } from "@/api/hager.js";
62 67
63 export default { 68 export default {
64 - components: { hagerBox, hagerH1 }, 69 + components: { hagerBox, hagerH1, Accordion },
65 mixins: [mixin.init], 70 mixins: [mixin.init],
66 data () { 71 data () {
67 return { 72 return {
...@@ -70,33 +75,54 @@ export default { ...@@ -70,33 +75,54 @@ export default {
70 activeNames: [], 75 activeNames: [],
71 cate_id: '', 76 cate_id: '',
72 parent_name: '', 77 parent_name: '',
73 - category_name: '', 78 + category_name: '所有产品',
74 - category_name_en: '', 79 + category_name_en: 'All Products',
75 cate_list: [], 80 cate_list: [],
76 product_list: [], 81 product_list: [],
77 no_product_img: 'https://cdn.ipadbiz.cn/hager/img/no-product-img.png', 82 no_product_img: 'https://cdn.ipadbiz.cn/hager/img/no-product-img.png',
78 is_search: false, 83 is_search: false,
84 + all_cate_list: [],
79 } 85 }
80 }, 86 },
81 async mounted () { 87 async mounted () {
88 + if (!this.is_all_cate) {
82 this.getMain(); 89 this.getMain();
90 + } else { // 没有ID显示所有产品
91 + this.getAllMain();
92 + }
83 }, 93 },
84 computed: { 94 computed: {
95 + allPath () {
96 + return `/product/index?timestamp=${Date.now()}`;
97 + },
85 productPath () { 98 productPath () {
86 return `/product/index?id=${this.cate_id}&timestamp=${Date.now()}`; 99 return `/product/index?id=${this.cate_id}&timestamp=${Date.now()}`;
87 }, 100 },
101 + is_all_cate () {
102 + return this.$route.query.id === undefined;
103 + }
88 }, 104 },
89 watch: { 105 watch: {
90 // 监听路由参数变化时,更新输入框的值 106 // 监听路由参数变化时,更新输入框的值
91 '$route.query.id' (val, old) { 107 '$route.query.id' (val, old) {
108 + if (val) {
92 if (old !== val) { 109 if (old !== val) {
93 this.is_search = false; 110 this.is_search = false;
94 this.getMain(); 111 this.getMain();
95 } 112 }
113 + } else {
114 + // 所有产品
115 + this.getAllMain();
116 + }
96 }, 117 },
97 '$route.query.timestamp' (val, old) { 118 '$route.query.timestamp' (val, old) {
98 this.is_search = false; 119 this.is_search = false;
120 + if (!this.is_all_cate) {
99 this.getMain(); 121 this.getMain();
122 + } else {
123 + // 所有产品
124 + this.getAllMain();
125 + }
100 }, 126 },
101 }, 127 },
102 methods: { 128 methods: {
...@@ -111,15 +137,29 @@ export default { ...@@ -111,15 +137,29 @@ export default {
111 } 137 }
112 }); 138 });
113 }, 139 },
140 + async getAllMain () { // 查询所有产品列表数据
141 + this.getCurrentCate();
142 + const { code, data } = await getProductCateAPI({ cid: 0 });
143 + if (code) {
144 + let info = data[0];
145 + this.category_name = '所有产品';
146 + this.category_name_en = 'All Products';
147 + this.product_list = info.list;
148 +
149 + this.search_keyword = '';
150 + // 设置页面标题
151 + document.title = '所有产品 | Hager China';
152 + }
153 + },
114 async getMain () { 154 async getMain () {
115 - const { code, data } = await getProductCateAPI( {cid: this.$route.query.id }); 155 + const { code, data } = await getProductCateAPI({cid: this.$route.query.id });
116 if (code) { 156 if (code) {
117 let info = data[0]; 157 let info = data[0];
118 this.parent_name = info.parent_name; 158 this.parent_name = info.parent_name;
119 this.category_name = info.category_name; 159 this.category_name = info.category_name;
120 this.category_name_en = info.category_name_en; 160 this.category_name_en = info.category_name_en;
121 this.product_list = info.list; 161 this.product_list = info.list;
122 - console.warn(info.list); 162 +
123 this.search_keyword = ''; 163 this.search_keyword = '';
124 // 获取当前类别的内容 164 // 获取当前类别的内容
125 this.cate_id = info.category_parent ? info.category_parent : info.id; // 同一个值,在不同层级下名字不一样 165 this.cate_id = info.category_parent ? info.category_parent : info.id; // 同一个值,在不同层级下名字不一样
...@@ -131,24 +171,43 @@ export default { ...@@ -131,24 +171,43 @@ export default {
131 async getCurrentCate (cate_id) { 171 async getCurrentCate (cate_id) {
132 const { code, data } = await getProductCateAPI(); 172 const { code, data } = await getProductCateAPI();
133 if (code) { 173 if (code) {
174 + if (cate_id) {
134 data.forEach((item) => { 175 data.forEach((item) => {
135 if (item.id === cate_id) { 176 if (item.id === cate_id) {
136 this.cate_list = item.children; 177 this.cate_list = item.children;
137 } 178 }
179 + });
180 + } else {
181 + // 所有分类列表
182 + this.all_cate_list = data;
183 + // 重构数据结构配合组件
184 + this.all_cate_list.forEach((item) => {
185 + item.children.forEach((c) => {
186 + c.children = c.list;
187 + c.style = {fontWeight: 'normal', height: '2.5rem'}
188 + c.children.forEach((d) => {
189 + d.category_name = d.product_name
190 + })
191 + })
138 }) 192 })
139 } 193 }
194 + }
140 }, 195 },
141 async goToSearch () { 196 async goToSearch () {
142 if (this.search_keyword) { // 产品有值时操作 197 if (this.search_keyword) { // 产品有值时操作
143 const { code, data } = await getProductSearchAPI({ keyword: this.search_keyword }); 198 const { code, data } = await getProductSearchAPI({ keyword: this.search_keyword });
144 if (code) { 199 if (code) {
145 - console.warn(data);
146 this.product_list = data; 200 this.product_list = data;
147 this.is_search = true; 201 this.is_search = true;
148 this.keyword = this.search_keyword; 202 this.keyword = this.search_keyword;
149 } 203 }
150 } else { // 清空搜索值,还原 204 } else { // 清空搜索值,还原
205 + if (!this.is_all_cate) {
151 this.getMain(); 206 this.getMain();
207 + } else {
208 + // 所有产品
209 + this.getAllMain();
210 + }
152 this.is_search = false; 211 this.is_search = false;
153 this.keyword = ''; 212 this.keyword = '';
154 } 213 }
......