优化工具箱页面分类组件及交互功能

This commit is contained in:
wangqiao
2025-09-25 22:10:26 +08:00
parent 30fd03590c
commit ecf120221f
2 changed files with 127 additions and 83 deletions

View File

@ -0,0 +1,77 @@
<template>
<div class="box-border w-[100%] border border-[#EEEEEE] rounded-[12px] border-solid bg-[#FFFFFF] px-[20px] py-[26px]">
<div class="mb-[10px] flex items-start">
<div class="flex-shrink-0 text-[15px] text-[#333333] font-normal">软件分类</div>
<div class="ml-[30px] mt-[-6px] flex flex-wrap">
<div
v-for="(item, index) in projectTypeList"
:key="index"
class="mb-[8px] mr-[26px] cursor-pointer rounded-[15px] px-[15px] py-[6px] text-[14px] text-[#666666] font-normal"
:class="item.id === query ? '!bg-[#ebeefe] !text-[#1A65FF]' : ''"
@click="handleClick(item)"
>{{ item.name }}</div
>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import { parent } from '~/api/upnew/index'
import type { pageReq } from '~/api/upnew/types'
import { getDictTree } from '~/api/home/index'
import { ArrowRight } from '@element-plus/icons-vue'
const props = defineProps({
type: {
type: Number,
default: 1,
},
id: {
type: String,
default: '',
},
groundId: {
type: String,
default: '',
},
})
const query = defineModel<string | undefined>('modelValue', {
required: true,
})
// 服务端渲染兼容方案:顺序执行异步操作
// 1. 先获取面包屑数据已在上面通过useAsyncData获取
// 2. 顺序获取分类下拉框数据
// 创建一个函数来获取分类数据,确保服务端渲染时能获取到数据
const getProjectTypeList = async () => {
try {
// 获取分类数据
const res = await parent({
type: 3,
parentId: 0,
})
const all = [{ id: '-1', name: '全部' }]
return [...all, ...res.data]
} catch (error) {
return []
}
}
// 使用useAsyncData获取分类列表确保服务端渲染兼容性
const { data: projectTypeList } = await useAsyncData(
`projectType-draw-toolbox-${props.type}-${query.value}}`,
getProjectTypeList,
{ server: true } // 确保在服务端执行
)
const handleClick = (row: any) => {
query.value = row.id
}
const handleClickBread = (row: any, index: number) => {
query.value = row.id
}
</script>

View File

@ -2,33 +2,17 @@
<KlNavTab active="工具箱" />
<!-- 搜索 -->
<KlSearch @search="search"></KlSearch>
<div v-loading="loading" class="ma-auto mt-[20px] w-[1440px] flex justify-center gap-[60px]">
<div class="left w-[821px]">
<!-- <img src="~/assets/images/banner2.png" alt="" srcset="" class="h-[284px] w-[100%]" /> -->
<el-form ref="formRef" :model="pageReq" label-width="110px" size="large" inline>
<el-form-item label-width="110px" label="软件分类:" prop="categoryId" :rules="{ required: true, message: '请选择分类', trigger: ['blur', 'change'] }">
<!-- <el-select v-model="form.categoryId" placeholder="请选择软件分类" class="w-[361px]!" multiple>
<el-option v-for="(item, index) in projectTypeList" :key="index" :label="item.name" :value="item.id" />
</el-select> -->
<el-cascader
v-model="pageReq.categoryId"
class="w-[280px]!"
:options="projectTypeList"
:props="cascaderProps"
clearable
collapse-tags
@change="handleCurrentChange(1)"
/>
</el-form-item>
<el-form-item label-width="110px" label="分类:" prop="sourceType" :rules="{ required: true, message: '请选择', trigger: ['blur', 'change'] }">
<el-radio-group v-model="pageReq.sourceType" @change="handleCurrentChange(1)">
<el-radio :label="0">原创开发</el-radio>
<el-radio :label="1">转载分享</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div class="box-border border border-[#EEEEEE] rounded-[12px] border-solid bg-[#FFFFFF] px-[28px] py-[17px]">
<div @click="handleClick(item)" v-for="item in pageRes?.list" :key="item.id" class="mt-[20px] flex border-b-[1px] border-b-[#eee] border-b-solid pb-[20px] cursor-pointer">
<div v-loading="loading" class="ma-auto mt-[20px] w-[1440px] flex justify-between">
<div class="left w-[1000px]">
<KlWallpaperCategory v-model="pageReq.categoryId" />
<KlTabBar v-model="pageReq.sourceType" :data="tabBar" class="mt-[20px]" />
<div class="mt-[4px] box-border border border-[#EEEEEE] rounded-[12px] border-solid bg-[#FFFFFF] px-[28px] py-[17px]" v-loading="loading">
<div
@click="handleClick(item)"
v-for="item in pageRes?.list"
:key="item.id"
class="mt-[20px] flex border-b-[1px] border-b-[#eee] border-b-solid pb-[20px] cursor-pointer"
>
<div class="h-[142px] w-[200px] text-center">
<el-image :src="item.iconUrl" alt="" srcset="" class="max-w-[100%] rd-[4px]" fit="cover" />
</div>
@ -68,7 +52,7 @@
/>
</div>
</div>
<div class="right w-[398px]">
<div class="right w-[400px]">
<div class="box-border border border-[#EEEEEE] rounded-[10px] border-solid bg-[#FFFFFF] pa-[16px]">
<div class="flex items-center text-[14px] text-[#333333] font-normal">
<div class="mr-[14px] h-[16px] w-[4px] rounded-[1px] bg-[#1A65FF]"></div>
@ -76,36 +60,6 @@
</div>
<div v-for="item in recommendList" :key="item.id" class="mt-[20px] text-[14px] text-[#666] font-normal">{{ item.title }}</div>
</div>
<!-- -->
<!-- <div class="mt-20px box-border w-398px border border-[#EEEEEE] rounded-10px border-solid bg-[#FFFFFF] pa-20px">
<div class="mb-20px flex items-center text-16px text-[#333333] font-normal">
<div class="mr-14px h-24px w-4px rounded-1px bg-[#1A65FF]"></div>
标签列表
</div>
<div class="flex flex-wrap">
<div
v-for="item in 10"
:key="item"
class="mb-19px mr-26px box-border border border-[#D7D7D7] rounded-4px border-solid px-8px py-12px text-16px text-[#1A65FF] font-normal"
># 标签名称1</div
>
</div>
</div> -->
<!-- -->
<!-- <div class="mt-20px box-border w-398px border border-[#EEEEEE] rounded-10px border-solid bg-[#FFFFFF] pa-20px">
<div class="mb-20px flex items-center text-16px text-[#333333] font-normal">
<div class="mr-14px h-24px w-4px rounded-1px bg-[#1A65FF]"></div>
猜你喜欢
</div>
<div
v-for="item in 4"
:key="item"
class="mt-16px flex items-center border-b-1px border-b-[#eee] border-b-solid pb-16px text-16px text-[#333333] font-normal"
>
<img src="~/assets/images/aucad.png" alt="" srcset="" class="h-68px w-110px" />
<div class="ml-20px text-16px text-[#333333] font-normal">Stable Diffusion 商业变现与 绘画大模型多场景实战</div>
</div>
</div> -->
</div>
</div>
</template>
@ -113,14 +67,14 @@
<script setup lang="ts">
import KlNavTab from '~/components/kl-nav-tab/index.vue'
import { page } from '~/api/toolbox/index.js'
import type { TpageReq, TpageRes } from '~/api/toolbox/types'
import { reactive, ref } from 'vue'
import { reactive, ref, watch } from 'vue'
import KlSearch from '~/pages/toolbox/components/search.vue'
import { getRelationRecommend } from '~/api/drawe-detail/index'
import type { ProjectDrawPageRespVO } from '~/api/drawe-detail/types'
import { parent } from '~/api/upnew/index'
import emptyImg from '~/assets/images/empty.png'
import dayjs from 'dayjs'
import KlWallpaperCategory from '~/components/toolbox-components/kl-wallpaper-category.vue'
const cascaderProps = { multiple: false, label: 'name', value: 'id', emitPath: false }
@ -128,19 +82,44 @@
pageNo: 1,
pageSize: 10,
title: '',
categoryId: undefined,
sourceType: 0,
categoryId: '-1',
sourceType: -1,
})
// const pageRes = ref<TpageRes>({
// list: [],
// total: 0,
// })
const tabBar = ref([
{
label: '推荐工具',
value: -1,
},
{
label: '原创开发',
value: 0,
},
{
label: '转载分享',
value: 1,
},
])
const recommedComputed = computed(() => {
if (pageReq.sourceType === -1) {
return true
}
return false
})
const loading = ref(false)
const { data: pageRes, refresh: getPage } = await useAsyncData(
`draw-page-toobox-list`,
async () => {
const res = await page(pageReq)
loading.value = true
const res = await page({
...pageReq,
recommend: recommedComputed,
sourceType: pageReq.sourceType === -1 ? undefined : pageReq.sourceType,
categoryId: pageReq.categoryId === '-1' ? undefined : pageReq.categoryId,
})
loading.value = false
if (res.code === 0) {
return res.data
}
@ -154,22 +133,6 @@
}
)
const loading = ref(false)
// const getPage = () => {
// loading.value = true
// page(pageReq)
// .then((res) => {
// if (res.code === 0) {
// pageRes.value = res.data
// }
// })
// .finally(() => {
// loading.value = false
// })
// }
// getPage()
const handleCurrentChange = (page: number) => {
pageReq.pageNo = page
getPage()
@ -205,4 +168,8 @@
})
return res.data
})
watch([() => pageReq.sourceType, () => pageReq.categoryId], (val) => {
getPage()
})
</script>