后期修改完善,上线版本
This commit is contained in:
@ -7,7 +7,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
async getToolsAsyncData() {
|
||||
const {data: res} = await this.$api.tool.getToolsList({isHot: 1, page: 1, limit: 6});
|
||||
const {data: res} = await this.$api.tool.getToolsList({isRecommend: 1, page: 1, limit: 6});
|
||||
const {code, data} = res;
|
||||
if (code === 0 && data.list) {
|
||||
this.pop_tools = data.list;
|
||||
@ -15,9 +15,9 @@ export default {
|
||||
},
|
||||
// 跳转工具详情页
|
||||
goToToolDetail(item) {
|
||||
if (item.slug && item.categorySlug) {
|
||||
if (item.slug && item.categoryName && item.categorySlug) {
|
||||
this.recordToolClick(item);
|
||||
this.$router.push(`/detail?tool_slug=${item.slug}&category_slug=${item.categorySlug}`);
|
||||
this.$router.push(`/detail?tool_slug=${item.slug}&category_slug=${item.categorySlug}&category_name=${item.categoryName}`);
|
||||
}
|
||||
},
|
||||
// 记录工具点击次数
|
||||
@ -36,7 +36,7 @@ export default {
|
||||
<template>
|
||||
<div>
|
||||
<div class="clearfix">
|
||||
<img src="/logo/hot.png" :style="{marginRight: '6px'}" alt=""/>
|
||||
<img src="/logo/hot.png" class="mr-6" alt=""/>
|
||||
Popular Tools
|
||||
</div>
|
||||
<div class="line" />
|
||||
@ -54,13 +54,16 @@ export default {
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mr-6 {
|
||||
margin-right: 6px;
|
||||
}
|
||||
.clearfix {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
font-size: $larg-font-size;
|
||||
font-weight: bold;
|
||||
font-family: 'Poppins-SemiBold', serif;
|
||||
font-family: 'Poppins-SemiBold';
|
||||
}
|
||||
|
||||
.img-box {
|
||||
@ -103,7 +106,7 @@ export default {
|
||||
}
|
||||
|
||||
.tool-name {
|
||||
font-family: 'Poppins-Medium', serif;
|
||||
font-family: 'Poppins-Medium';
|
||||
color: #64748B;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
|
||||
189
pages/Home/components/ToolItem.vue
Normal file
189
pages/Home/components/ToolItem.vue
Normal file
@ -0,0 +1,189 @@
|
||||
<template>
|
||||
<div class="tool-card" :class="{ 'checkedBg': item.active, 'hovered': isHover && !item.active }"
|
||||
@click="handleClick"
|
||||
@mouseenter="handleMouseEnter"
|
||||
@mouseleave="handleMouseLeave">
|
||||
<div class="content">
|
||||
<div class="icon-container">
|
||||
<img :src="iconBase64 || item.icon || ''" alt="" class="icon-base" />
|
||||
<img :src="iconSelectedBase64 || item.iconSelected || ''" alt="" class="icon-selected" />
|
||||
</div>
|
||||
<span class="text">{{ item.name || '' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
iconBase64: '',
|
||||
iconSelectedBase64: '',
|
||||
isHover: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 组件创建时预加载图标
|
||||
this.preloadIcons();
|
||||
},
|
||||
methods: {
|
||||
// 处理点击事件
|
||||
handleClick() {
|
||||
if (this.item.active) {
|
||||
this.$set(this.item, 'active', false);
|
||||
} else {
|
||||
// 先重置所有项,再激活当前项
|
||||
// 这里我们需要通知父组件来完成全局重置
|
||||
this.$emit('tool-selected', this.item);
|
||||
}
|
||||
},
|
||||
// 处理鼠标进入事件
|
||||
handleMouseEnter() {
|
||||
// 当项已激活时,不触发hover效果
|
||||
if (this.item.active) {
|
||||
return;
|
||||
}
|
||||
this.isHover = true;
|
||||
},
|
||||
// 处理鼠标离开事件
|
||||
handleMouseLeave() {
|
||||
// 当项已激活时,不触发hover效果
|
||||
if (this.item.active) {
|
||||
return;
|
||||
}
|
||||
this.isHover = false;
|
||||
},
|
||||
// 预加载图标并转换为base64
|
||||
async preloadIcons() {
|
||||
// 预加载普通图标
|
||||
if (this.item.icon && this.item.icon !== '') {
|
||||
try {
|
||||
this.iconBase64 = await this.convertToBase64(this.item.icon);
|
||||
} catch (error) {
|
||||
// console.warn('Failed to load icon:', this.item.icon, error);
|
||||
}
|
||||
}
|
||||
|
||||
// 预加载选中图标
|
||||
if (this.item.iconSelected && this.item.iconSelected !== '') {
|
||||
try {
|
||||
this.iconSelectedBase64 = await this.convertToBase64(this.item.iconSelected);
|
||||
} catch (error) {
|
||||
// console.warn('Failed to load iconSelected:', this.item.iconSelected, error);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 将图片URL转换为base64
|
||||
convertToBase64(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.crossOrigin = 'Anonymous'; // 处理跨域问题
|
||||
img.onload = () => {
|
||||
try {
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
ctx.drawImage(img, 0, 0);
|
||||
const dataURL = canvas.toDataURL('image/png');
|
||||
resolve(dataURL);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
};
|
||||
img.onerror = (error) => {
|
||||
reject(error);
|
||||
};
|
||||
img.src = url;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tool-card {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.05);
|
||||
border-radius: 12px;
|
||||
padding: 10px 16px;
|
||||
font-weight: 600;
|
||||
font-family: 'Poppins-SemiBold';
|
||||
cursor: pointer;
|
||||
width: fit-content;
|
||||
|
||||
.content {
|
||||
@include display-flex;
|
||||
white-space: nowrap;
|
||||
max-width: 220px;
|
||||
|
||||
.icon-container {
|
||||
position: relative;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.icon-base,
|
||||
.icon-selected {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
// 基础状态:显示普通图标,隐藏选中图标
|
||||
.icon-base {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.icon-selected {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 激活状态样式
|
||||
.checkedBg {
|
||||
color: $white;
|
||||
background: linear-gradient(90deg, $linear-gradient-start 22%, $linear-gradient-end 73%);
|
||||
.icon-container {
|
||||
.icon-base {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
.icon-selected {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 悬停状态样式(非激活时)
|
||||
.hovered {
|
||||
color: $white;
|
||||
background: linear-gradient(90deg, $linear-gradient-start 22%, $linear-gradient-end 73%);
|
||||
// 悬停状态(非激活时):显示选中图标,隐藏普通图标
|
||||
.icon-container {
|
||||
.icon-base {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
.icon-selected {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -15,9 +15,9 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
goToToolDetail() {
|
||||
if (this.config.slug && this.categorySlug) {
|
||||
if (this.config.slug && this.config.categoryName && this.categorySlug) {
|
||||
this.recordToolClick(this.config);
|
||||
this.$router.push(`/detail?tool_slug=${this.config.slug}&category_slug=${this.categorySlug}`);
|
||||
this.$router.push(`/detail?tool_slug=${this.config.slug}&category_slug=${this.categorySlug}&category_name=${this.config.categoryName}`);
|
||||
}
|
||||
},
|
||||
// 记录点击次数
|
||||
@ -109,7 +109,7 @@ export default {
|
||||
color: $main-font-color;
|
||||
font-size: $big-font-size;
|
||||
font-weight: 600;
|
||||
font-family: 'Poppins-SemiBold', serif;
|
||||
font-family: 'Poppins-SemiBold';
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@ -119,7 +119,7 @@ export default {
|
||||
|
||||
.text {
|
||||
color: $grey-color;
|
||||
font-family: 'Poppins-Regular', serif;
|
||||
font-family: 'Poppins-Regular';
|
||||
margin-top: 4px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
@ -1,83 +1,47 @@
|
||||
<template>
|
||||
<div class="list">
|
||||
<div v-for="item in list" class="tools" @click="checkTool(item)">
|
||||
<span class="tool-card" :class="item.active?'checkedBg':''">
|
||||
<span class="content">
|
||||
<img :src="item.icon || ''" alt="" />
|
||||
<span>{{ item.name || '' }}</span>
|
||||
</span>
|
||||
</span>
|
||||
<div v-for="(item, index) in list" class="tools">
|
||||
<ToolItem :item="item" @tool-selected="handleToolSelected" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['list'],
|
||||
data() {
|
||||
return {
|
||||
ischeck: 'check',
|
||||
}
|
||||
},
|
||||
created() {
|
||||
import ToolItem from './ToolItem.vue'
|
||||
export default {
|
||||
props: ['list'],
|
||||
components: {
|
||||
ToolItem
|
||||
},
|
||||
created() {
|
||||
this.list.forEach(item => {
|
||||
this.$set(item, 'active', false)
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
handleToolSelected(selectedItem) {
|
||||
// 重置所有项
|
||||
this.list.forEach(item => {
|
||||
this.$set(item, 'active', false)
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
checkTool(item) {
|
||||
if (item.active) {
|
||||
if (item !== selectedItem) {
|
||||
this.$set(item, 'active', false);
|
||||
} else {
|
||||
// 否则,先重置所有项,再激活当前项
|
||||
this.list.forEach(i => this.$set(i, 'active', false));
|
||||
this.$set(item, 'active', true);
|
||||
this.$emit('tool-selected', item.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
// 激活当前选中项
|
||||
this.$set(selectedItem, 'active', true);
|
||||
this.$emit('tool-selected', selectedItem.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr); // 4列布局
|
||||
gap: 20px; // 网格间距
|
||||
.list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr); // 4列布局
|
||||
gap: 20px; // 网格间距
|
||||
|
||||
.tools {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.tool-card {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.05);
|
||||
border-radius: 12px;
|
||||
padding: 10px 16px;
|
||||
display: inline-block;
|
||||
font-weight: 600;
|
||||
font-family: 'Poppins-SemiBold', serif;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: $white;
|
||||
background: linear-gradient(90deg, $linear-gradient-start 22%, $linear-gradient-end 73%);
|
||||
}
|
||||
|
||||
.content {
|
||||
@include display-flex;
|
||||
|
||||
img {
|
||||
margin-right: 5px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.tools .checkedBg {
|
||||
color: $white;
|
||||
background: linear-gradient(90deg, $linear-gradient-start 22%, $linear-gradient-end 73%);
|
||||
}
|
||||
.tools {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="bar-list">
|
||||
<div class="top-box">
|
||||
<div class="title-wrap">
|
||||
<img :src="category_icon || ''" alt="" />
|
||||
<img :src="tool.blueIcon || ''" alt="" />
|
||||
<span class="title-text gradient-color">
|
||||
{{tool.categoryName}}
|
||||
</span>
|
||||
@ -15,14 +15,24 @@
|
||||
<div v-if="tool.tagList && tool.tagList.length">
|
||||
<ScrollList>
|
||||
<div class="tags">
|
||||
<div class="tag-item" v-for="(item,index) in tool.tagList" :key="index">
|
||||
{{ item }}
|
||||
<div class="tag-item" @click="handleTagClick(item)" :class="{active: item.categorySlug === activeCategorySlug}" v-for="(item,index) in tool.tagList" :key="index">
|
||||
{{ item.categoryName }}
|
||||
</div>
|
||||
</div>
|
||||
</ScrollList>
|
||||
<div class="line"></div>
|
||||
<div v-if="activeSubCategories.length">
|
||||
<div class="more pointer" @click="tagGoToViewMore">
|
||||
View more<i class="el-icon-arrow-right"></i>
|
||||
</div>
|
||||
<div class="item-card">
|
||||
<div v-for="(item, index) in activeSubCategories" :key="index" class="item">
|
||||
<ToolItemCard :config="item" :categorySlug="item.categorySlug || ''" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div v-else>
|
||||
<div @click="goToViewMore" class="more pointer" v-if="tool.tagList && tool.tagList.length">
|
||||
View more<i class="el-icon-arrow-right"></i>
|
||||
</div>
|
||||
@ -57,23 +67,49 @@
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
category_icon: {
|
||||
type: String,
|
||||
default: '',
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeCategorySlug: '',
|
||||
activeCategoryName: '',
|
||||
activeSubCategories: [],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 查看更多
|
||||
goToViewMore() {
|
||||
if (this.categorySlug) {
|
||||
this.$router.push('/home/more?category_slug=' + this.categorySlug)
|
||||
if (this.categorySlug && this.tool.categoryName) {
|
||||
this.$router.push('/home/more?category_slug=' + this.categorySlug + '&tag_name=' + this.tool.categoryName);
|
||||
}
|
||||
},
|
||||
handleTagClick(item) {
|
||||
this.activeCategorySlug = item.categorySlug;
|
||||
// 设置二级分类列表
|
||||
this.activeSubCategories = item.tools || [];
|
||||
this.activeCategoryName = item.categoryName;
|
||||
},
|
||||
tagGoToViewMore() {
|
||||
if (this.activeCategorySlug && this.activeCategoryName) {
|
||||
this.$router.push('/home/more?category_slug=' + this.activeCategorySlug + '&tag_name=' + this.activeCategoryName);
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
tool: {
|
||||
handler(newTool) {
|
||||
// 检查 tool 中 tagList 是否存在且为数组长度不为0
|
||||
if (newTool &&
|
||||
newTool.tagList &&
|
||||
Array.isArray(newTool.tagList) &&
|
||||
newTool.tagList.length > 0) {
|
||||
this.activeCategorySlug = newTool.tagList[0].categorySlug || '';
|
||||
this.activeCategoryName = newTool.tagList[0].categoryName || '';
|
||||
this.activeSubCategories = newTool.tagList[0].tools || [];
|
||||
}
|
||||
},
|
||||
immediate: true // 立即执行,确保组件初始化时也会执行
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -100,7 +136,7 @@
|
||||
.title-text {
|
||||
font-weight: 600;
|
||||
font-size: $larg-font-size;
|
||||
font-family: 'Poppins-SemiBold', serif;
|
||||
font-family: 'Poppins-SemiBold';
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,10 +156,16 @@
|
||||
padding: 10px;
|
||||
@include gradient-border($linear-gradient-start, $linear-gradient-end);
|
||||
/* 显示抓取手势 */
|
||||
font-family: 'Poppins-SemiBold', sans-serif;
|
||||
font-family: 'Poppins-SemiBold';
|
||||
color: #64748B;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
|
||||
&.active {
|
||||
color: #fff;
|
||||
background: $header-backgroungd;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.more {
|
||||
@ -131,7 +173,7 @@
|
||||
text-align: right;
|
||||
color: $grey-color;
|
||||
font-size: $mid-font-size;
|
||||
font-family: 'Poppins-Regular', serif;
|
||||
font-family: 'Poppins-Regular';
|
||||
|
||||
&:active {
|
||||
opacity: 0.8;
|
||||
|
||||
@ -11,19 +11,21 @@
|
||||
<div class="third-text">
|
||||
It includes over a <a href="/" class="special">thousand global AI tools</a>, covering writing, images,
|
||||
videos, audio, programming,
|
||||
music, design, chatting, etc., and recommends learning platforms, frameworks and models
|
||||
music, design, chatting, etc, and recommends learning platforms, frameworks and models
|
||||
</div>
|
||||
<!-- 修改输入框容器 -->
|
||||
<div style="margin: 68px auto 62px">
|
||||
<div class="margin-62">
|
||||
<SearchSelectInput />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card flex">
|
||||
<div class="left-card card-box">
|
||||
<el-carousel :autoplay="false" height="354px" autoplay :interval="8000">
|
||||
<el-carousel :autoplay="false" autoplay :interval="8000">
|
||||
<el-carousel-item v-for="(item, i) in banner" :key="i">
|
||||
<img :src="item.imageUrl || ''" alt="" style="height: 354px; width: 100%; border-radius: 12px" />
|
||||
<div class="img-cover">
|
||||
<img :src="item.imageUrl || ''" alt="" class="img" />
|
||||
</div>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
@ -60,13 +62,31 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
},
|
||||
watch: {
|
||||
'$route'() {
|
||||
// 当路由变化时滚动到顶部
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('getBannerConfig');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped> #home-page {
|
||||
<style lang="scss" scoped>
|
||||
.img-cover {
|
||||
height: 100%; width: 100%; padding: 24px 20px 30px;
|
||||
}
|
||||
.img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-radius: 12px;
|
||||
}
|
||||
.margin-62 {
|
||||
margin: 40px auto 40px;
|
||||
}
|
||||
#home-page {
|
||||
flex: 1;
|
||||
overflow-y: auto; // 必须启用滚动
|
||||
position: relative; // 添加相对定位
|
||||
@ -89,26 +109,23 @@ export default {
|
||||
.first-text {
|
||||
line-height: 90px;
|
||||
font-size: $huge-font-size3;
|
||||
font-weight: 900;
|
||||
font-family: 'Poppins-Bold', serif;
|
||||
font-family: 'Poppins-ExtraBold';
|
||||
@include text-gradient(90deg, #2563eb, 22%, #7B61FF, 73%);
|
||||
}
|
||||
|
||||
.second-text {
|
||||
margin: 18px 0;
|
||||
font-family: 'Poppins-Bold', serif;
|
||||
font-family: 'Poppins-Bold';
|
||||
font-size: $huge-font-size2;
|
||||
font-weight: 900;
|
||||
line-height: 75px;
|
||||
}
|
||||
|
||||
.third-text {
|
||||
width: 716px;
|
||||
font-weight: 500;
|
||||
color: $grey-color;
|
||||
font-size: $normal-font-size;
|
||||
margin-top: 8px;
|
||||
font-family: 'Poppins-Medium', serif;
|
||||
font-family: 'Poppins-Medium';
|
||||
|
||||
.special {
|
||||
color: $main-color;
|
||||
@ -134,6 +151,9 @@ export default {
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
::v-deep .el-carousel {
|
||||
.el-carousel__container {
|
||||
height: 354px;
|
||||
}
|
||||
.el-carousel__arrow {
|
||||
opacity: 0 !important;
|
||||
transition: none !important;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
</div>
|
||||
<div class="line">
|
||||
</div>
|
||||
<div class="toolbar" v-for="tool in toolsGroup">
|
||||
<div class="toolbar" v-for="tool in processedToolsGroup" :key="tool.categoryId">
|
||||
<Toolbar :tool="tool" :id="`tool-${tool.categoryName}`" :category-slug="tool.categorySlug || ''"></Toolbar>
|
||||
</div>
|
||||
</div>
|
||||
@ -22,6 +22,14 @@ export default {
|
||||
fullscreenLoading: false,
|
||||
categoryList: [],
|
||||
toolsGroup: [],
|
||||
processedToolsGroup: [] // 处理后的工具列表
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 计算属性,用于获取处理后的工具列表
|
||||
getProcessedTools() {
|
||||
this.processData();
|
||||
return this.processedToolsGroup;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -48,6 +56,8 @@ export default {
|
||||
const {code, data} = res;
|
||||
if (code === 0 && data.list) {
|
||||
this.toolsGroup = data.list;
|
||||
// 数据获取完成后处理数据
|
||||
this.processData();
|
||||
}
|
||||
},
|
||||
async onLoad() {
|
||||
@ -55,6 +65,38 @@ export default {
|
||||
await this.getCategoryAsyncData();
|
||||
await this.getToolsGroupAsyncData();
|
||||
this.fullscreenLoading = false;
|
||||
},
|
||||
// 处理数据的核心逻辑
|
||||
processData() {
|
||||
// 确保工具列表已加载
|
||||
if (!this.toolsGroup.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 分离一级分类(parentId === 0)和二级分类(parentId !== 0)
|
||||
const mainTools = this.toolsGroup.filter(tool => tool.parentId === 0);
|
||||
const subTools = this.toolsGroup.filter(tool => tool.parentId !== 0);
|
||||
|
||||
// 2. 创建一个映射,方便快速查找一级分类
|
||||
const mainToolMap = {};
|
||||
mainTools.forEach(tool => {
|
||||
// 去除tools属性,添加tagList属性
|
||||
mainToolMap[tool.categoryId] = {
|
||||
...tool,
|
||||
tagList: [] // 初始化空的tagList
|
||||
};
|
||||
});
|
||||
|
||||
// 3. 将二级分类添加到对应的一级分类的tagList中
|
||||
subTools.forEach(subTool => {
|
||||
const parentTool = mainToolMap[subTool.parentId];
|
||||
if (parentTool) {
|
||||
parentTool.tagList.push(subTool);
|
||||
}
|
||||
});
|
||||
|
||||
// 4. 获取处理后的工具列表(值的数组)
|
||||
this.processedToolsGroup = Object.values(mainToolMap);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
@ -47,6 +47,7 @@ export default {
|
||||
const slug = to.query.category_slug;
|
||||
if (slug) {
|
||||
this.category_slug = slug;
|
||||
this.tagName = to.query.tag_name;
|
||||
this.getToolsByTag(slug);
|
||||
}
|
||||
}
|
||||
@ -54,9 +55,11 @@ export default {
|
||||
mounted() {
|
||||
// 组件挂载时也检查一次路由参数
|
||||
const slug = this.$route.query.category_slug;
|
||||
if (slug) {
|
||||
const tagName = this.$route.query.tag_name;
|
||||
if (slug && tagName) {
|
||||
this.category_slug = slug;
|
||||
this.getToolsByTag(slug);
|
||||
this.tagName = tagName;
|
||||
}
|
||||
},
|
||||
}
|
||||
@ -64,13 +67,13 @@ export default {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
padding-top: 60px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 100px;
|
||||
.tag-item {
|
||||
display: inline-block;
|
||||
padding: 10px;
|
||||
border-radius: 12px;
|
||||
font-family: 'Poppins-SemiBold', sans-serif;
|
||||
font-family: 'Poppins-SemiBold';
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
background: $header-backgroungd;
|
||||
|
||||
Reference in New Issue
Block a user