修复bug

This commit is contained in:
2025-10-31 15:58:11 +08:00
parent d3375a347f
commit c54f9c9976
29 changed files with 823 additions and 218 deletions

View File

@ -11,12 +11,22 @@
<img src="/logo/bottom-logo.png" alt="" />
</div>
<div class="navigation-bottom">
<span v-for="item in first">
<span
v-for="item in first"
:key="item.name"
@click="goto(item.path)"
:class="{'special-color': isParentMatch(item)}"
>
{{item.name}}
</span>
</div>
<div class="navigation-bottom">
<span v-for="item in two" @click="goto(item.path)">
<span
v-for="item in two"
:key="item.name"
@click="goto(item.path)"
:class="{'special-color': isParentMatch(item)}"
>
{{item.name}}
</span>
</div>
@ -30,47 +40,104 @@
</template>
<script>
export default {
export default {
name: "Footer",
data() {
return {
first: [{
name: 'Home'
name: 'Home',
path: '/home/list',
meta: {
parent: 'Home',
},
},
{
name: 'AI Daily News'
name: 'AI Daily News',
path: '/dailyNews',
meta: {
parent: 'DailyNews',
},
},
{
name: 'AI Hub'
name: 'AI Hub',
meta: {
parent: 'Hub',
}
},
{
name: 'Learn'
name: 'Learn',
meta: {
parent: 'Learn',
}
},
{
name: 'About Us'
name: 'About Us',
path: '/about',
meta: {
parent: 'About',
}
}
],
two: [{
name: 'Privacy Policy',
path: '/privacy'
path: '/privacy',
meta: {
parent: 'Privacy',
}
},
{
name: 'Terms Of Service',
path: '/service'
path: '/service',
meta: {
parent: 'Service',
}
},
]
],
}
},
methods: {
goto(path) {
this.$router.push(path)
}
this.$router.push(path);
},
/**
* 判断当前导航项是否应该被选中
* @param {Object} item 导航项
* @returns {Boolean} 是否选中
*/
isParentMatch(item) {
// 首先检查路径匹配逻辑,保持向后兼容性
const pathMatch = item.path && item.path === this.$route.path;
if (pathMatch) return true;
// 获取当前路由的meta信息
const currentRouteMeta = this.$route.meta || {};
const currentParent = currentRouteMeta.parent;
// 如果当前路由没有parent属性直接返回false
if (!currentParent) return false;
// 获取当前导航项的meta信息
const navItemMeta = item.meta || {};
const navItemParent = navItemMeta.parent || '';
// 根据parent属性的类型进行判断
if (typeof currentParent === 'string') {
// parent是字符串时直接比较是否相等
return currentParent === navItemParent;
} else if (Array.isArray(currentParent)) {
// parent是数组时判断导航项的parent是否在数组中
return currentParent.includes(navItemParent);
}
// 其他情况返回false
return false;
}
}
}
</script>
<style lang="scss" scoped>
#footer-container {
#footer-container {
width: 100%;
height: $footerBarHeight;
@ -82,9 +149,9 @@
justify-content: space-between;
}
}
}
.left-container {
.left-container {
@include flex-center;
flex-direction: column;
@ -94,27 +161,38 @@
font-weight: bold;
font-family: 'Poppins-Bold', serif;
}
}
}
.right-container {
.right-container {
text-align: right;
img {
margin-bottom: 14px;
}
}
.bottom-span {
.bottom-span {
color: $grey-color;
font-family: 'Poppins-Regular', serif;
}
}
.navigation-bottom {
.navigation-bottom {
margin-bottom: 14px;
span {
display: inline-block;
padding: 14px;
font-family: 'Poppins-Medium', serif;
cursor: pointer;
margin-left: 30px;
&:hover {
color: #7B61FF;
}
}
span:last-child {
padding-right: 0;
}
}
}
.special-color {
color: #7B61FF;
}
</style>

View File

@ -10,7 +10,7 @@
<div class="navigation-item pointer" v-for="item in navRoutes" :key="item.path"
@click="handleParentClick(item)" @mouseenter="showSubmenu(item)" @mouseleave="hideSubmenu">
<span
:class="{ 'selected-navigation': $route.matched.some(record => record.path === item.path) }">{{
:class="{ 'selected-navigation': isParentMatch(item) }">{{
item.meta.navigationName }}
<i class="el-icon-arrow-down" v-if="item.meta.children"></i>
</span>
@ -84,6 +84,39 @@ export default {
hideSubmenu() {
this.activeMenu = null;
},
/**
* 判断当前导航项是否应该被选中
* @param {Object} item 导航项
* @returns {Boolean} 是否选中
*/
isParentMatch(item) {
// 首先检查原始的路径匹配逻辑,保持向后兼容性
const pathMatch = this.$route.matched.some(record => record.path === item.path);
if (pathMatch) return true;
// 获取当前路由的meta信息
const currentRouteMeta = this.$route.meta || {};
const currentParent = currentRouteMeta.parent;
// 如果当前路由没有parent属性直接返回false
if (!currentParent) return false;
// 获取当前导航项的meta信息
const navItemMeta = item.meta || {};
const navItemParent = navItemMeta.parent || '';
// 根据parent属性的类型进行判断
if (typeof currentParent === 'string') {
// parent是字符串时直接比较是否相等
return currentParent === navItemParent;
} else if (Array.isArray(currentParent)) {
// parent是数组时判断导航项的parent是否在数组中
return currentParent.includes(navItemParent);
}
// 其他情况返回false
return false;
}
}
};
</script>
@ -98,13 +131,13 @@ export default {
.navigation-container {
height: $navigationBarHeight;
display: flex;
font-weight: 500;
align-items: center;
justify-content: space-between;
.logo {
@include flex-center;
color: $white;
//font-family: 'Poppins-Bold', serif;
span {
font-size: $normal-font-size;
@ -115,6 +148,7 @@ export default {
margin-left: 20px;
padding: 10px;
position: relative;
//font-family: 'Poppins-Medium', serif;
span {
color: $grey;
@ -125,6 +159,8 @@ export default {
&.selected-navigation {
color: $white;
font-weight: 500;
//font-family: 'Poppins-Bold', serif;
}
}

View File

@ -0,0 +1,28 @@
<template>
<div v-show="isActive" class="my-tab-pane">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'MyTabPane',
props: {
label: String,
name: [String, Number],
disabled: Boolean,
closable: Boolean
},
computed: {
isActive() {
return this.$parent.activeName === this.name
}
},
mounted() {
this.$parent.registerPane(this)
},
beforeDestroy() {
this.$parent.unregisterPane(this)
}
}
</script>

View File

@ -0,0 +1,184 @@
<template>
<div class="my-tabs">
<!-- 导航栏 -->
<div class="my-tabs__nav">
<div
v-for="pane in panes"
:key="pane.name"
:class="{
'my-tabs__item': true,
'is-active': activeName === pane.name,
'is-disabled': pane.disabled
}"
@click="handleClick(pane)"
>
<!-- 标签文本 -->
<span>{{ pane.label }}</span>
<!-- 关闭按钮 -->
<i
v-if="pane.closable"
class="my-tabs__close"
@click.stop="handleClose(pane)"
>×</i>
</div>
<!-- 底部横线和滑块 -->
<div class="my-tabs__slider-wrapper">
<div class="my-tabs__slider-track"></div>
<div
class="my-tabs__slider"
ref="slider"
></div>
</div>
</div>
<!-- 内容区 -->
<div class="my-tabs__content">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: 'MyTabs',
model: {
prop: 'value',
event: 'input'
},
props: {
value: [String, Number], // 当前激活
type: { type: String, default: '' }, // 后期可扩展 card/border-card
closable: Boolean // 全局是否允许关闭
},
data() {
return {
panes: [] // 缓存所有 MyTabPane 实例
}
},
computed: {
activeName: {
get() { return this.value },
set(val) { this.$emit('input', val) }
}
},
watch: {
activeName() {
this.$nextTick(() => {
this.updateSliderPosition();
});
},
panes() {
this.$nextTick(() => {
this.updateSliderPosition();
});
}
},
mounted() {
this.$nextTick(() => {
this.updateSliderPosition();
});
},
methods: {
/* 收集子组件 */
registerPane(pane) {
this.panes.push(pane)
// 默认选中第一个
if (!this.activeName && this.panes.length === 1) {
this.activeName = pane.name
}
},
unregisterPane(pane) {
const idx = this.panes.indexOf(pane)
if (idx > -1) this.panes.splice(idx, 1)
},
/* 点击导航 */
handleClick(pane) {
if (pane.disabled) return
this.activeName = pane.name
this.$emit('tab-click', pane)
},
/* 关闭 */
handleClose(pane) {
this.$emit('edit', pane.name, 'remove')
// 业务层把 v-model 绑定的数组删掉即可
},
/* 更新滑块位置和宽度 */
updateSliderPosition() {
if (!this.activeName || !this.$refs.slider) return;
const activeTab = this.$el.querySelector(`.my-tabs__item.is-active`);
if (!activeTab) return;
const textElement = activeTab.querySelector('span');
if (!textElement) return;
const { width } = textElement.getBoundingClientRect();
const { left } = activeTab.getBoundingClientRect();
const navLeft = this.$el.querySelector('.my-tabs__nav').getBoundingClientRect().left;
this.$refs.slider.style.width = `${width}px`;
this.$refs.slider.style.left = `${left - navLeft + (activeTab.offsetWidth - width) / 2}px`;
}
}
}
</script>
<style scoped lang="scss">
.my-tabs__nav {
display: flex;
position: relative;
padding-bottom: 14px;
}
.my-tabs__item {
padding: 8px 16px;
cursor: pointer;
position: relative;
font-size: 20px;
&:hover {
opacity: 0.8;
}
}
.my-tabs__item.is-active {
color: #409eff;
background: linear-gradient(90deg, $linear-gradient-start 22%, $linear-gradient-end 73%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-weight: bold;
}
.my-tabs__item.is-disabled {
color: #1e293b;
cursor: not-allowed;
font-family: 'Poppins-Regular', serif;
}
.my-tabs__close { margin-left: 6px; color: #999; }
.my-tabs__close:hover { color: #f56c6c; }
.my-tabs__content { padding: 15px 0; }
/* 底部横线和滑块样式 */
.my-tabs__slider-wrapper {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 4px;
display: flex;
align-items: center;
}
.my-tabs__slider-track {
width: 100%;
height: 4px;
background-color: #e2e8f0;
}
.my-tabs__slider {
height: 4px;
background: $header-backgroungd;
border-radius: 4px;
position: absolute;
bottom: 0;
transition: all 0.3s ease;
}
</style>

View File

@ -12,20 +12,20 @@ export default {
},
data() {
return {
localValue: this.value, // 创建本地副本
localValue: this.value,
isInputFocused: false,
};
},
watch: {
value(newVal) {
this.localValue = newVal; // 监听外部 value 变化并同步到本地
this.localValue = newVal;
}
},
methods: {
handleInput(event) {
const newValue = event.target.value;
this.localValue = newValue;
this.$emit('input', newValue); // 触发 input 事件以支持 v-model
this.$emit('input', newValue);
},
// 新增:处理查询事件
handleSearch() {
@ -36,7 +36,7 @@ export default {
</script>
<template>
<div class="input-container" :class="{ focused: isInputFocused || localValue }">
<div class="input-container flex items-center" :class="{ focused: isInputFocused || localValue }">
<input
type="text"
:placeholder="placeholder"
@ -54,21 +54,24 @@ export default {
</div>
</template>
<style scoped lang="scss">
/* 添加输入框容器聚焦状态样式 */
.input-container {
position: relative;
input {
width: 100%;
height: 60px;
padding: 0 20px;
padding: 10px 20px;
border-radius: 12px;
border: 2px solid transparent;
background-color: #fff;
input {
outline: none;
font-size: $normal-font-size;
transition: border-color 0.3s ease;
color: #1e293b;
flex: 1;
background: #fff !important;
border: none;
padding: 0;
margin: 0;
box-shadow: none;
height: 40px;
&::placeholder {
color: #ccc;
@ -76,14 +79,12 @@ export default {
}
img {
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
position: relative;
right: 0;
width: 54px;
height: 40px;
pointer-events: none;
cursor: pointer;
margin-left: 10px;
}
&.focused {

View File

@ -126,6 +126,7 @@ export default {
border-radius: 6px;
gap: 12px;
color: #1E293B;
font-weight: 500;
img {
width: 28px;

View File

@ -63,7 +63,7 @@
</div>
<div class="bottom-line">
<div class="bottom-line-left"></div>
<div class="bottom-text gradient-color">
<div class="bottom-text">
Lets explore the future of AItogether
</div>
<div class="bottom-line-right"></div>
@ -157,6 +157,7 @@
font-weight: 600;
font-size: 28px;
font-family: 'Poppins-SemiBold', serif;
@include text-gradient(90deg, #2563eb, 22%, #7B61FF, 73%);
}
.bottom-line-left {
width: 120px;

View File

@ -91,6 +91,7 @@
font-size: 16px;
color: #7B61FF;
text-align: center;
margin-top: 20px;
}
.content {
margin-top: 75px;

View File

@ -70,6 +70,7 @@ export default {
background: #FFFFFF;
border-radius: 12px;
border: 1px solid #E2E8F0;
padding: 6px;
@include flex-center;
&:hover {
@ -78,6 +79,11 @@ export default {
@include gradient-border($linear-gradient-start, $linear-gradient-end);
box-shadow: 0 5px 7px 0 #00000014;
}
img {
width: 100%;
height: 100%;
}
}
.pop-item {

View File

@ -46,14 +46,13 @@ export default {
<template>
<div class="card-caontainer" @click="goToToolDetail">
<div class="title">
<div class="icon">
<img :src="config.iconUrl || '/'" alt="" />
<span style="font-size: 18px">
</div>
<span class="title-text">
{{ config.name || '' }}
</span>
</div>
<!--<div class="text"-->
<!-- v-if="config.memo && containsHtml(config.memo + '</p>')"-->
<!-- v-html="config.memo"></div>-->
<div class="text">
{{ config.memo ? config.memo : '' }}
</div>
@ -62,13 +61,13 @@ export default {
<style scoped lang="scss">
.card-caontainer {
width: 100%;
height: 100%;
background: #FFFFFF;
box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.05);
border-radius: 8px;
padding: 16px;
border: 1px solid #E2E8F0;
height: 100%;
box-sizing: border-box;
&:hover {
cursor: pointer;
@ -86,9 +85,24 @@ export default {
align-items: center;
gap: 10px;
img {
.title-text {
font-size: 18px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.icon {
width: 40px;
height: 40px;
border-radius: 6px;
background: #f9fafc;
padding: 6px;
img {
width: 28px;
height: 28px;
flex-shrink: 0;
}
}
span {
@ -96,6 +110,10 @@ export default {
font-size: $big-font-size;
font-weight: 600;
font-family: 'Poppins-SemiBold', serif;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}

View File

@ -3,8 +3,8 @@
<div v-for="item in list" class="tools" @click="checkTool(item)">
<span class="tool-card" :class="item.active?'checkedBg':''">
<span class="content">
<img :src="''" alt="" />
<span>{{ item.name }}</span>
<img :src="item.icon || ''" alt="" />
<span>{{ item.name || '' }}</span>
</span>
</span>
</div>
@ -57,6 +57,11 @@
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;

View File

@ -3,7 +3,7 @@
<div class="bar-list">
<div class="top-box">
<div class="title-wrap">
<img :src="`/logo/${tool.img}_check.png`" alt="" />
<img :src="category_icon || ''" alt="" />
<span class="title-text gradient-color">
{{tool.categoryName}}
</span>
@ -27,7 +27,7 @@
View more<i class="el-icon-arrow-right"></i>
</div>
<div class="item-card" v-if="tool.tools && tool.tools.length">
<div v-for="(item, index) in tool.tools" :key="index" style="min-height: 110px">
<div v-for="(item, index) in tool.tools" :key="index" class="item">
<ToolItemCard :config="item" :categorySlug="categorySlug" />
</div>
</div>
@ -56,6 +56,10 @@
categorySlug: {
type: String,
default: '',
},
category_icon: {
type: String,
default: '',
}
},
data() {
@ -78,6 +82,11 @@
display: flex;
align-items: center;
gap: 6px;
img {
width: 24px;
height: 24px;
}
}
.bar-list {
@ -115,10 +124,6 @@
color: #64748B;
font-weight: 600;
&:active {
// cursor: grabbing;
/* 抓取中状态 */
}
}
.more {
@ -138,5 +143,10 @@
gap: 20px;
grid-template-columns: repeat(4, 1fr);
margin-top: 30px;
.item {
min-height: 110px;
width: 100%;
overflow: hidden;
}
}
</style>

View File

@ -2,7 +2,7 @@
<div id="home-page">
<IntegratedLayout>
<div class="top-title">
<div class="first-text gradient-color">
<div class="first-text">
AIToolsFinder
</div>
<div class="second-text">
@ -91,6 +91,7 @@ export default {
font-size: $huge-font-size3;
font-weight: 900;
font-family: 'Poppins-Bold', serif;
@include text-gradient(90deg, #2563eb, 22%, #7B61FF, 73%);
}
.second-text {

View File

@ -3,8 +3,10 @@
<div class="tag-item" v-if="tagName">
{{tagName}}
</div>
<div class="item-card">
<ToolItemCard v-for="(item, index) in toolList" :key="index" :config="item" :category-slug="category_slug" />
<div class="item-card" v-if="toolList && toolList.length">
<div class="item" v-for="(item, index) in toolList" :key="index">
<ToolItemCard :config="item" :category-slug="category_slug" />
</div>
</div>
</div>
</template>
@ -79,30 +81,10 @@ export default {
grid-template-columns: repeat(4, 1fr);
margin-top: 30px;
.card-caontainer {
background: #FFFFFF;
box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.05);
border-radius: 8px;
padding: 16px;
border: 1px solid #E2E8F0;
.title {
display: flex;
align-items: center;
span {
color: $main-font-color;
font-size: $big-font-size;
font-weight: 600;
font-family: 'Poppins-SemiBold', serif;
}
}
.text {
color: $grey-color;
font-family: 'Poppins-Regular', serif;
// line-height: 30px;
}
.item {
min-height: 110px;
width: 100%;
overflow: hidden;
}
}
}

View File

@ -42,8 +42,8 @@ export default {
border-top: 2px solid #E2E8F0;
}
.finance-item {
padding-top: 35px;
padding-bottom: 35px;
padding-top: 20px;
padding-bottom: 20px;
cursor: pointer;
&:active {
opacity: 0.8;
@ -61,6 +61,7 @@ export default {
.title {
color: #aebadee6;
font-family: 'Poppins-Medium', serif;
margin-bottom: 12px;
}
.content-text {
color: #64748B;

View File

@ -66,10 +66,10 @@
<ProjectItem :item="{name: 'Facebook.com', iconUrl: '/launches/web/facebook.png'}" />
<ProjectItem :item="{name: 'Instagram.com', iconUrl: '/launches/web/instagram.png'}" />
<ProjectItem :item="{name: 'Twitter.com', iconUrl: '/launches/web/twitter.png'}" />
<!--<div class="more flex items-center justify-between" style="margin-top: 20px">-->
<!-- <div>A total of 8 projects were released</div>-->
<!-- <img src="/launches/detail/icon_arrow.png" alt="" />-->
<!--</div>-->
<div class="more flex items-center justify-between" style="margin-top: 20px">
<div>A total of 8 projects were released</div>
<img src="/launches/detail/icon_arrow.png" alt="" />
</div>
</div>
<div class="card" style="margin-top: 20px">
<div class="flex items-center" style="margin-top: 20px">
@ -80,12 +80,12 @@
<FinanceItem />
<FinanceItem />
<FinanceItem />
<!--<div class="flex justify-end" style="margin-top: 30px">-->
<!-- <div class="more flex items-center justify-between" style="width: 50%">-->
<!-- <div>View more</div>-->
<!-- <img src="/launches/detail/icon_arrow.png" alt="" />-->
<!-- </div>-->
<!--</div>-->
<div class="flex justify-end" style="margin-top: 30px">
<div class="more flex items-center justify-between" style="gap: 14px">
<div>View more</div>
<img src="/launches/detail/icon_arrow.png" alt="" />
</div>
</div>
</div>
</div>
</div>
@ -286,7 +286,6 @@ export default {
.diver-line {
margin-top: 20px;
border-top: 2px solid #E2E8F0;
margin-bottom: 20px;
}
.content-title {
@ -307,7 +306,6 @@ export default {
border-radius: 6px;
padding: 8px 15px;
border: 1px solid #e2e8f0;
gap: 16px;
font-family: 'Poppins-Regular', serif;
color: #64748B;
@ -334,7 +332,6 @@ export default {
border-radius: 6px;
padding: 8px 15px;
border: 1px solid #e2e8f0;
gap: 16px;
font-family: 'Poppins-Regular', serif;
color: #64748B;

View File

@ -0,0 +1,98 @@
<template>
<div class="special-finance-item flex">
<div class="dot"></div>
<div class="flex-1 container">
<div class="time">2025-2-1</div>
<div class="content">Koah participated in a $5 million seed round, led Forerunner, and participated in The Timeline Of Sketch Commons.</div>
<div class="tag-list flex flex-wrap">
<div v-for="(it, i) in tag" :key="i" class="tag-item flex items-center">
<img src="/" alt="" />
<span>{{ it.name }}</span>
<div class="lead" v-if="it.isLead">Lead</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
tag: [{
name: 'Mask Network',
isLead: true,
}, {
name: 'CatcherVC',
isLead: true,
}, {
name: 'CREDIT SCEND',
isLead: false,
}, {
name: 'Ribbit Capital',
isLead: false,
}],
}
},
methods: {},
}
</script>
<style scoped lang="scss">
.special-finance-item {
border-bottom: 1px solid #E2E8F0;
gap: 14px;
.dot {
width: 8px;
height: 8px;
background-color: #7B61FF;
border-radius: 50%;
margin-top: 8px;
}
.container {
padding-bottom: 50px;
.time {
font-size: 16px;
color: #7B61FF;
font-family: 'Poppins-Medium', serif;
margin-bottom: 22px;
}
.content {
color: #64748B;
font-size: 20px;
font-family: 'Poppins-Medium', serif;
margin-bottom: 20px;
}
.tag-list {
gap: 30px;
.tag-item {
position: relative;
border-radius: 12px;
border: 1px solid #E2E8F0;
padding: 10px;
gap: 4px;
img {
width: 12px;
height: 12px;
}
span {
font-size: 14px;
color: #64748B;
font-family: 'Poppins-Regular', serif;
line-height: 14px;
}
.lead {
padding: 0 4px;
border-radius: 8px;
background-color: #6ae7ee;
color: #ffffff;
position: absolute;
right: 0;
font-size: 9px;
top: -10px;
}
}
}
}
}
</style>

View File

@ -15,9 +15,11 @@
<span>Introduction: </span>
</div>
<div class="item-content">
<div style="padding-right: 70px">
{{ financeDetail.summary || '' }}
</div>
</div>
</div>
<div class="terms-item">
<div class="item-title">
<img src="/ToolDetail/icon_clock.png" alt="">
@ -37,7 +39,9 @@
</div>
<div class="diver"></div>
<div class="title">Special Financing</div>
<div class="card"></div>
<div class="card content-box">
<SpecialFinanceItem />
</div>
</div>
</IntegratedLayout>
</div>
@ -45,9 +49,10 @@
<script>
import CommentBtn from "@/pages/ToolDetail/components/CommentBtn.vue";
import SpecialFinanceItem from "@/pages/Launches/FinanceDetail/SpecialFinanceItem.vue";
export default {
components: {CommentBtn},
components: {CommentBtn, SpecialFinanceItem},
data() {
return {
commentCount: 0,
@ -99,6 +104,11 @@ export default {
.content {
padding-top: 180px;
padding-bottom: 100px;
.content-box {
padding: 50px 30px;
}
.diver {
margin-top: 20px;
border-top: 4px solid #E2E8F0;

View File

@ -6,6 +6,7 @@
<div v-if="mode === 'Daily'" class="daily-picker">
<HorizontalDateList>
<button
style="width: 36px"
v-for="day in dailyDays"
:key="day.dateStr"
:class="{ 'selected': day.dateStr === selectedDate }"
@ -18,6 +19,7 @@
<div v-else-if="mode === 'Weekly'" class="weekly-picker">
<HorizontalDateList>
<button
style="margin: 0 30px; width: 105px"
v-for="week in weeklyRanges"
:key="week.start"
:class="{ 'selected': week.start === selectedDate[0] && week.end === selectedDate[1] }"
@ -30,7 +32,7 @@
<div v-else class="monthly-picker">
<HorizontalDateList>
<button
style="margin: 0 15px"
style="margin: 0 9px; width: 55px"
v-for="(monthAbbr, index) in monthAbbrs"
:key="index"
:class="{ 'selected': (index + 1) === selectedMonth }"
@ -286,13 +288,16 @@ export default {
.daily-picker button,
.weekly-picker button,
.monthly-picker button {
padding: 6px 10px;
border: 1px solid #e5e7eb;
border-radius: 4px;
height: 36px;
text-align: center;
border: 1px solid #E2E8F0;
border-radius: 12px;
background: #fff;
cursor: pointer;
transition: all 0.2s;
font-size: 14px;
font-size: 18px;
line-height: 22px;
color: #506179;
&:active {
opacity: 0.8;
}
@ -307,8 +312,7 @@ export default {
.daily-picker button.selected,
.weekly-picker button.selected,
.monthly-picker button.selected {
background: #4f46e5;
color: #fff;
border-color: #4f46e5;
background: linear-gradient( 47deg, #2563EB 4%, #7B61FF 73%);
}
</style>

View File

@ -3,7 +3,7 @@
<div class="btn" @click="prevYear">
<img :src="prevIcon" alt="Previous Year" />
</div>
<div style="width: 60px;text-align: center">{{ monthName }}</div>
<div style="width: 60px;text-align: center; font-family: 'Poppins-Regular', serif">{{ monthName }}</div>
<div class="btn" @click="nextYear">
<img :src="nextIcon" :alt="isNextDisabled ? 'Next Year Disabled' : 'Next Year'" />
</div>

View File

@ -45,7 +45,7 @@ export default {
<div class="btn" @click="prevYear">
<img :src="prevIcon" alt="Previous Year" />
</div>
<div style="width: 60px;text-align: center">{{ year }}</div>
<div style="width: 60px;text-align: center; font-family: 'Poppins-Regular', serif">{{ year }}</div>
<div class="btn" @click="nextYear">
<img :src="nextIcon" :alt="isNextDisabled ? 'Next Year Disabled' : 'Next Year'" />
</div>

View File

@ -30,11 +30,23 @@
placeholder="Please express your opinions"
v-model="commentText"
:maxlength="1000"
show-word-limit
class="comment-textarea"
>
</el-input>
<div class="information-container flex-between-center">
<el-input v-model="nickName" placeholder="NickName" :maxlength="50" />
<el-input v-model="email" placeholder="Email" :maxlength="50" />
<el-input
v-model="nickName"
placeholder="NickName"
:maxlength="50"
class="nickname-input"
/>
<el-input
v-model="email"
placeholder="Email"
:maxlength="50"
class="email-input"
/>
</div>
<div class="submit-button flex-center" @click="submitComment">
<span>Submit</span>
@ -42,7 +54,7 @@
</div>
</div>
<!--评论列表-->
<div class="comment-list card">
<div class="comment-list card" v-if="commentList.length">
<div class="list-header flex-between-center">
<h2 class="content-title">All comments <span class="little-text">{{commentList.length}} comments</span></h2>
<div class="more pointer" v-if="!checkMore" @click="checkMore = true">
@ -250,6 +262,9 @@ export default {
border-color: #E2E8F0 !important;
padding: 30px !important;
height: 320px !important;
&::placeholder {
color: #E2E8F0 !important;
}
}
}
.information-container {
@ -258,6 +273,9 @@ export default {
::v-deep .el-input {
.el-input__inner {
border-color: #E2E8F0 !important;
&::placeholder {
color: #64748B !important;
}
}
}
}

View File

@ -5,7 +5,11 @@
<div v-html="tool_content || ''"></div>
</div>
<div class="law-text-box">
<div class="law-title"> Special Announcement </div>
<div class="law-title flex items-center justify-center">
<div style="width: 130px; height: 2px; border-top: 2px solid #1e293b"></div>
<span>Special Announcement</span>
<div style="width: 130px; height: 2px; border-top: 2px solid #1e293b"></div>
</div>
<p class="law-text">Without the explicit written permission of this platform, no unit or individual may copy, reprint, quote, modify, disseminate or use all or part of the content of this website in any way. It is strictly prohibited to establish a mirror image or conduct illegal collection on any unofficially authorized server. For any infringement, this platform will hold the offender legally responsible in accordance with the law.</p>
</div>
<!--其他相似导航-->
@ -176,6 +180,7 @@ export default {
font-family: 'Poppins-SemiBold', serif;
text-align: center;
margin-bottom: 22px;
gap: 22px;
}
.law-text {

View File

@ -9,17 +9,48 @@ export default {
data() {
return {
isActive: false,
isHovered: false,
}
},
computed: {
// 根据状态返回不同的图片路径
getImageSrc() {
// 如果已经点赞,显示选中的图片
if (this.isActive) {
return '/ToolDetail/icon_comment_selected.png';
}
// 如果鼠标悬停或点击,显示高亮的图片
if (this.isHovered) {
return '/ToolDetail/icon_comment_selected.png';
}
// 默认显示普通图片
return '/ToolDetail/icon_comment.png';
}
},
methods: {
// 鼠标悬停
onMouseEnter() {
this.isHovered = true;
},
// 鼠标离开
onMouseLeave() {
this.isHovered = false;
},
// 点击事件
onClick() {
const commentElement = document.querySelector('.comment-content');
if (commentElement) {
commentElement.scrollIntoView({ behavior: 'smooth' });
}
}
}
}
</script>
<template>
<div class="box flex flex-col items-center" :style="{background: !isActive && '#FFFFFF'}">
<img :src="isActive ? '/ToolDetail/icon_comment_selected.png' : '/ToolDetail/icon_comment.png'" alt="" />
<span :style="{color: isActive ? '#ffffffcc' : '#64748b'}">{{ commentCount }}</span>
<div class="box flex flex-col items-center" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave" @click="onClick">
<img :src="getImageSrc" alt="" />
<span>{{ commentCount }}</span>
</div>
</template>
@ -29,13 +60,30 @@ export default {
height: 48px;
border-radius: 12px;
box-shadow: 0 4px 6px 0 #0000000d;
background: $header-backgroungd;
background: #fff;
padding: 5px;
font-family: 'Poppins-Regular', serif;
font-size: 12px;
cursor: pointer;
img {
width: 20px;
height: 20px;
}
span {
color: #64748b;
}
&:hover {
background: linear-gradient(90deg, #2563EB 22%, #7B61FF 73%);
span {
color: #ffffffcc;
}
}
&:active {
background: linear-gradient(90deg, #2563EB 22%, #7B61FF 73%);
opacity: 0.8;
span {
color: #ffffffcc;
}
}
}
</style>

View File

@ -34,7 +34,9 @@ export default {
<template>
<div class="similar-card-container" @click="goToToolDetail">
<div class="title">
<img :src="config.iconUrl || ''" alt="" />
<div class="icon">
<img :src="config.iconUrl || '/'" alt="" />
</div>
<span style="font-size: 18px">
{{ config.name || '' }}
</span>
@ -67,10 +69,17 @@ export default {
display: flex;
align-items: center;
img {
.icon {
width: 40px;
height: 40px;
margin-right: 4px;
border-radius: 6px;
background: #f9fafc;
padding: 6px;
img {
width: 28px;
height: 28px;
flex-shrink: 0;
}
}
span {

View File

@ -18,6 +18,22 @@ export default {
return {
isActive: false,
throttleTimer: null,
isHovered: false,
}
},
computed: {
// 根据状态返回不同的图片路径
getImageSrc() {
// 如果已经点赞,显示选中的图片
if (this.isActive) {
return '/ToolDetail/icon_thumb_selected.png';
}
// 如果鼠标悬停或点击,显示高亮的图片
if (this.isHovered) {
return '/ToolDetail/icon_thumb_selected.png';
}
// 默认显示普通图片
return '/ToolDetail/icon_thumb.png';
}
},
methods: {
@ -63,15 +79,23 @@ export default {
this.throttleTimer = null;
}
}
},
// 鼠标悬停
onMouseEnter() {
this.isHovered = true;
},
// 鼠标离开
onMouseLeave() {
this.isHovered = false;
}
}
}
</script>
<template>
<div class="box flex flex-col items-center" :style="{background: !isActive && '#FFFFFF'}" @click="addLike">
<img :src="isActive ? '/ToolDetail/icon_thumb_selected.png' : '/ToolDetail/icon_thumb.png'" alt="" />
<span :style="{color: isActive ? '#ffffffcc' : '#64748b'}">{{ likeCount }}</span>
<div class="box flex flex-col items-center" @click="addLike" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave">
<img :src="getImageSrc" alt="" />
<span>{{ likeCount }}</span>
</div>
</template>
@ -81,7 +105,7 @@ export default {
height: 48px;
border-radius: 12px;
box-shadow: 0 4px 6px 0 #0000000d;
background: $header-backgroungd;
background: #fff;
padding: 5px;
font-family: 'Poppins-Regular', serif;
font-size: 12px;
@ -90,8 +114,21 @@ export default {
width: 20px;
height: 20px;
}
span {
color: #64748b;
}
&:hover {
background: linear-gradient(90deg, #2563EB 22%, #7B61FF 73%);
span {
color: #ffffffcc;
}
}
&:active {
background: linear-gradient(90deg, #2563EB 22%, #7B61FF 73%);
opacity: 0.8;
span {
color: #ffffffcc;
}
}
}
</style>

View File

@ -59,8 +59,8 @@
</div>
</div>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="Product information" name="product">
<MyTabs v-model="activeName" @tab-click="handleClick">
<MyTabPane label="Product information" name="product">
<Product
:other-tools="other_tools"
:tool-id="tool_detail.id || 0"
@ -68,9 +68,9 @@
:category-slug="category_slug || ''"
:tool_content="tool_detail.description || ''"
/>
</el-tab-pane>
<el-tab-pane label="Comment" name="comment"></el-tab-pane>
</el-tabs>
</MyTabPane>
<MyTabPane label="Comment" name="comment"></MyTabPane>
</MyTabs>
<Comment comment-type="tool" :id="tool_detail.id" @update:commentCount="handleCommentCountUpdate" />
</div>
@ -84,6 +84,8 @@ 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";
import MyTabs from '@/components/MyTabs/MyTabs.vue';
import MyTabPane from '@/components/MyTabs/MyTabPane.vue';
export default {
components: {
@ -92,6 +94,8 @@ export default {
ThumbBtn,
CommentBtn,
Rate,
MyTabs,
MyTabPane,
},
data() {
return {
@ -169,7 +173,7 @@ export default {
if (code === 0 && data.list) {
this.other_tools = data.list;
}
}
},
},
computed: {
tagList() {

View File

@ -2,15 +2,14 @@ import Vue from 'vue'
import VueRouter from 'vue-router'
// 引入页面组件
import Home from '@/pages/Home/index.vue'
import AboutIndex from '@/pages/About/index.vue'
// import Login from '@/pages/Login/index.vue'
import Privacy from '@/pages/About/Privacy.vue'
import About from '@/pages/About/About.vue'
import Service from '@/pages/About/Service.vue'
import AIHub from '@/pages/AIHub/index.vue'
import AITools from '@/pages/AIHub/AITools.vue'
import Frameworks from '@/pages/AIHub/Frameworks.vue'
import Home from '@/pages/Home/index.vue';
import AboutIndex from '@/pages/About/index.vue';
import Privacy from '@/pages/About/Privacy.vue';
import About from '@/pages/About/About.vue';
import Service from '@/pages/About/Service.vue';
import AIHub from '@/pages/AIHub/index.vue';
import AITools from '@/pages/AIHub/AITools.vue';
import Frameworks from '@/pages/AIHub/Frameworks.vue';
import ViewMore from "@/pages/Home/views/ViewMore.vue";
import List from "@/pages/Home/views/List.vue";
import Detail from "@/pages/ToolDetail/index.vue";
@ -21,7 +20,6 @@ import Learn from "@/pages/Learn/index.vue";
import Observer from "@/pages/Learn/Observer.vue";
import Depth from "@/pages/Learn/Depth.vue";
import Pioneer from "@/pages/Learn/Pioneer.vue";
// import NewsDetail from "@/pages/DailyNews/NewsDetailIndex/index.vue";
import LaunchesDetail from "@/pages/Launches/Detail/index.vue";
import FinanceDetail from "@/pages/Launches/FinanceDetail/index.vue";
@ -31,7 +29,10 @@ export const routes = [
{
path: '/',
name: 'home-redirect',
redirect: '/home'
redirect: '/home',
meta: {
parent: 'Home',
}
},{
path: '/home',
name: 'home',
@ -40,6 +41,7 @@ export const routes = [
meta: {
navigationName: "Home",
hidden: false,
parent: 'Home',
}, //navigationName显示在header组件里面导航按钮的名字 hidden是否在导航栏里面显示
children: [
{
@ -49,6 +51,7 @@ export const routes = [
meta: {
navigationName: 'List',
hidden: true,
parent: 'Home',
},
},
{
@ -58,6 +61,7 @@ export const routes = [
meta: {
navigationName: 'View More',
hidden: true,
parent: 'Home',
}
}
]
@ -69,6 +73,7 @@ export const routes = [
meta: {
navigationName: "Tool ToolDetail",
hidden: true,
parent: 'Home',
}
},
{
@ -77,7 +82,8 @@ export const routes = [
component: Launches,
meta: {
navigationName: "AI Launches",
hidden: false
hidden: false,
parent: 'Launches',
}
},
{
@ -87,6 +93,7 @@ export const routes = [
meta: {
navigationName: "AI Launches Detail",
hidden: true,
parent: 'Launches',
},
},
{
@ -96,6 +103,7 @@ export const routes = [
meta: {
navigationName: "Finance",
hidden: true,
parent: 'Launches',
}
},
{
@ -113,7 +121,8 @@ export const routes = [
component: AITools,
meta: {
icon: 'tools',
hidden: true // 隐藏于主导航,只在子菜单显示
hidden: true, // 隐藏于主导航,只在子菜单显示
parent: 'Hub'
}
},
{
@ -122,7 +131,8 @@ export const routes = [
component: Frameworks,
meta: {
icon: 'frameworks',
hidden: true
hidden: true,
parent: 'Hub',
}
},
]
@ -134,6 +144,7 @@ export const routes = [
meta: {
icon: 'tools',
hidden: true,
parent: ['Hub', 'DailyNews', 'Learn'],
}
},
{
@ -142,18 +153,10 @@ export const routes = [
component: DailyNews,
meta: {
navigationName: "AI Daily News",
hidden: false
hidden: false,
parent: 'DailyNews',
},
},
// {
// path: '/news-detail',
// name: 'News Detail',
// component: NewsDetail,
// meta: {
// navigationName: 'News ToolDetail',
// hidden: true
// }
// },
{
path: '/learn',
name: 'Learn',
@ -169,7 +172,8 @@ export const routes = [
component: Observer,
meta: {
icon: 'observer',
hidden: true
hidden: true,
parent: 'Learn',
}
},
{
@ -178,7 +182,8 @@ export const routes = [
component: Depth,
meta: {
icon: 'analysis',
hidden: true
hidden: true,
parent: 'Learn',
}
},
{
@ -187,7 +192,8 @@ export const routes = [
component: Pioneer,
meta: {
icon: 'pioneer',
hidden: true
hidden: true,
parent: 'Learn',
}
}
]
@ -204,21 +210,24 @@ export const routes = [
path: '/privacy',
component: Privacy,
meta: {
hidden: true
hidden: true,
parent: 'Privacy',
}
},
{
path: '/about',
component: About,
meta: {
hidden: true
hidden: true,
parent: 'About',
}
},
{
path: '/service',
component: Service,
meta: {
hidden: true
hidden: true,
parent: 'Service',
}
}
]
@ -227,7 +236,12 @@ export const routes = [
{
path: '*',
redirect: '/'
redirect: '/',
meta: {
navigationName: "404",
hidden: true,
parent: 'Home',
}
}
]

View File

@ -54,6 +54,14 @@
border: 1px solid transparent;
}
@mixin text-gradient($angle, $start-color, $start-percent, $end-color, $end-percent) {
background: linear-gradient($angle, $start-color $start-percent, $end-color $end-percent);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
display: inline-block;
}
@mixin scrollBar {
//滚动条轨道