对接数据
This commit is contained in:
343
pages/ToolDetail/index.vue
Normal file
343
pages/ToolDetail/index.vue
Normal file
@ -0,0 +1,343 @@
|
||||
<template>
|
||||
<div id="normal-container" class="tool-detail">
|
||||
<IntegratedLayout>
|
||||
<div class="content">
|
||||
<!--面包屑-->
|
||||
<div class="bread-menu">
|
||||
<span>Home</span>
|
||||
<i class="el-icon-arrow-right"></i>
|
||||
<span>{{ category_slug }}</span>
|
||||
<i class="el-icon-arrow-right"></i>
|
||||
<span class="crumbs gradient-color">{{ tool_detail.name || '' }}</span>
|
||||
</div>
|
||||
<!--标题-->
|
||||
<p class="title-text">{{ tool_detail.name || '' }}</p>
|
||||
<!--评分-->
|
||||
<div class="rate-box">
|
||||
<Rate v-model="tool_detail.rating" readonly />
|
||||
<div class="flex" style="gap: 20px">
|
||||
<ThumbBtn
|
||||
:like-count="tool_detail.likeCount || 0"
|
||||
:id="tool_detail.id"
|
||||
type="tool"
|
||||
@like-success="refreshToolDetail"
|
||||
/>
|
||||
<CommentBtn :comment-count="commentCount" />
|
||||
</div>
|
||||
</div>
|
||||
<!--工具内容-->
|
||||
<div class="tool-content">
|
||||
<div class="left-content flex flex-col">
|
||||
<div class="terms-item">
|
||||
<div class="item-title">
|
||||
<img src="/ToolDetail/icon_note.png" alt="">
|
||||
<span>Introduction: </span>
|
||||
</div>
|
||||
<div class="item-content">
|
||||
{{ tool_detail.memo || '' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="terms-item">
|
||||
<div class="item-title">
|
||||
<img src="/ToolDetail/icon_clock.png" alt="">
|
||||
<span>Data update: </span>
|
||||
</div>
|
||||
<div class="item-content">{{ tool_detail.updatedAt || '' }}</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
<div class="tag-item" v-for="(it, index) in tagList" :key="index">{{ it }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-content">
|
||||
<div class="card-website-view">
|
||||
<iframe :src="tool_detail.url || ''" style="width: 100%; height: 100%; pointer-events: none"></iframe>
|
||||
</div>
|
||||
<a :href="tool_detail.url || ''" class="link-button">
|
||||
<img src="/ToolDetail/icon_link.png" alt="" style="width: 16px; height: 16px" />
|
||||
<span>Visit website</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane label="Product information" name="product">
|
||||
<Product
|
||||
:other-tools="other_tools"
|
||||
:tool-id="tool_detail.id || 0"
|
||||
:tool-slug="tool_slug || ''"
|
||||
:category-slug="category_slug || ''"
|
||||
:tool_content="tool_detail.description || ''"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="Comment" name="comment"></el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<Comment comment-type="tool" :id="tool_detail.id" @update:commentCount="handleCommentCountUpdate" />
|
||||
</div>
|
||||
</IntegratedLayout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Product from "@/pages/ToolDetail/Product/index.vue";
|
||||
import Comment from "@/pages/ToolDetail/Comment/index.vue";
|
||||
import ThumbBtn from "@/pages/ToolDetail/components/ThumbBtn.vue";
|
||||
import CommentBtn from "@/pages/ToolDetail/components/CommentBtn.vue";
|
||||
import Rate from "@/components/Rate.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Product,
|
||||
Comment,
|
||||
ThumbBtn,
|
||||
CommentBtn,
|
||||
Rate,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeName: 'product',
|
||||
tool_slug: null,
|
||||
tool_detail: {},
|
||||
commentCount: 0,
|
||||
other_tools: [],
|
||||
category_slug: null,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.tool_slug = this.$route.query.tool_slug;
|
||||
this.category_slug = this.$route.query.category_slug;
|
||||
this.getAsyncToolDetailData();
|
||||
this.getAsyncOtherTools();
|
||||
},
|
||||
watch: {
|
||||
'$route'(to, from) {
|
||||
// 当路由参数发生变化时重新加载数据
|
||||
if (to.query.tool_slug !== from.query.tool_slug) {
|
||||
this.tool_slug = to.query.tool_slug;
|
||||
this.category_slug = to.query.category_slug;
|
||||
this.resetAndReloadData();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 刷新工具详情数据
|
||||
async refreshToolDetail() {
|
||||
await this.getAsyncToolDetailData();
|
||||
},
|
||||
// 获取详情数据
|
||||
async getAsyncToolDetailData() {
|
||||
if (this.tool_slug) {
|
||||
const {data: res} = await this.$api.tool.getToolDetailBySlug(this.tool_slug);
|
||||
const {code, data} = res;
|
||||
if (code === 0 && data) {
|
||||
this.tool_detail = {...data};
|
||||
}
|
||||
}
|
||||
},
|
||||
stringJsonToObject(str) {
|
||||
// 将json字符串转为对象,捕获错误,当str为空或者转对象失败时默认返回空数组
|
||||
try {
|
||||
return JSON.parse(str);
|
||||
} catch (e) {
|
||||
console.error('Error parsing JSON string:', e);
|
||||
return [];
|
||||
}
|
||||
},
|
||||
handleCommentCountUpdate(count) {
|
||||
this.commentCount = count;
|
||||
},
|
||||
handleClick() {},
|
||||
// 添加重置和重新加载数据的方法
|
||||
resetAndReloadData() {
|
||||
// 重置数据
|
||||
this.tool_detail = {};
|
||||
this.commentCount = 0;
|
||||
this.other_tools = [];
|
||||
|
||||
// 重新加载数据
|
||||
this.getAsyncToolDetailData();
|
||||
this.getAsyncOtherTools();
|
||||
},
|
||||
// 获取其他工具
|
||||
async getAsyncOtherTools() {
|
||||
if (!this.category_slug) {
|
||||
return false;
|
||||
}
|
||||
const params = {categorySlug: this.category_slug, page: 1, limit: 9};
|
||||
const {data: res} = await this.$api.tool.getToolsList(params);
|
||||
const {code, data} = res;
|
||||
if (code === 0 && data.list) {
|
||||
this.other_tools = data.list;
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
tagList() {
|
||||
return this.stringJsonToObject(this.tool_detail.tags || '[]');
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tool-detail {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
.content {
|
||||
padding-top: 100px;
|
||||
padding-bottom: 100px;
|
||||
min-height: 100vh;
|
||||
|
||||
.bread-menu {
|
||||
font-size: $mid-font-size;
|
||||
font-family: 'Poppins-Medium', serif;
|
||||
font-weight: 600;
|
||||
|
||||
.crumbs {
|
||||
font-family: 'Poppins-SemiBold', serif;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 34px;
|
||||
color: #1E293B;
|
||||
font-family: 'Poppins-SemiBold', serif;
|
||||
font-weight: 600;
|
||||
margin-top: 55px;
|
||||
}
|
||||
|
||||
.rate-box {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.btn-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-content {
|
||||
display: flex;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
gap: 50px;
|
||||
|
||||
.left-content {
|
||||
padding-top: 12px;
|
||||
gap: 50px;
|
||||
flex: 1;
|
||||
|
||||
.terms-item {
|
||||
margin-bottom: 30px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 7px;
|
||||
|
||||
.item-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: #1E293B;
|
||||
font-family: 'Poppins-Medium', serif;
|
||||
|
||||
img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.item-content {
|
||||
font-family: 'Poppins-Regular', serif;
|
||||
color: #64748B;
|
||||
}
|
||||
}
|
||||
|
||||
.tags {
|
||||
display: flex;
|
||||
overflow-x: auto;
|
||||
gap: 12px;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
user-select: none;
|
||||
flex-wrap: wrap;
|
||||
width: 80%;
|
||||
|
||||
.tag-item {
|
||||
flex-shrink: 0;
|
||||
padding: 4px 12px;
|
||||
border-radius: 12px;
|
||||
@include gradient-border($linear-gradient-start, $linear-gradient-end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.right-content {
|
||||
width: 450px;
|
||||
|
||||
.card-website-view {
|
||||
width: 100%;
|
||||
height: 268px;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 10px 30px 0 #0000000d;
|
||||
padding: 19px 25px;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.link-button {
|
||||
width: 280px;
|
||||
height: 44px;
|
||||
background: $header-backgroungd;
|
||||
border-radius: 12px;
|
||||
margin: auto;
|
||||
color: #fff;
|
||||
font-family: 'Poppins-SemiBold', serif;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
&:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-tabs) {
|
||||
.el-tabs__header {
|
||||
.el-tabs__nav-wrap::after {
|
||||
height: 4px !important;
|
||||
background-color: #E2E8F0 !important;
|
||||
}
|
||||
.el-tabs__item {
|
||||
font-weight: 700 !important;
|
||||
font-size: 20px !important;
|
||||
margin-bottom: 14px;
|
||||
|
||||
&.is-active {
|
||||
background: linear-gradient(90deg, $linear-gradient-start, $linear-gradient-end);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
}
|
||||
}
|
||||
.el-tabs__active-bar {
|
||||
height: 4px !important;
|
||||
background: linear-gradient(90deg, $linear-gradient-start, $linear-gradient-end) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user