674 lines
19 KiB
Vue
674 lines
19 KiB
Vue
<template>
|
||
<div class="product-service-page">
|
||
|
||
<!-- 产品分类导航 -->
|
||
<div class="category-nav">
|
||
<div v-for="category in panelData"
|
||
:key="category.firTitle"
|
||
class="nav-item"
|
||
:class="{ active: activeCategory === category.firTitle }"
|
||
@click="switchCategory(category)">
|
||
{{ category.firTitle }}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 产品内容区域 -->
|
||
<div class="product-content">
|
||
<!-- 左侧菜单区域(只有有二级或三级菜单时才显示) -->
|
||
<div v-if="hasMenuSidebar" class="menu-sidebar">
|
||
<!-- 二级菜单 -->
|
||
<div v-if="hasSecondLevel" class="subcategory-section">
|
||
<div class="subcategory-list">
|
||
<div v-for="subItem in currentSubcategories"
|
||
:key="getSubItemKey(subItem)"
|
||
class="subcategory-item"
|
||
:class="{ active: activeSubId === getSubItemKey(subItem) }"
|
||
@click="switchSubcategory(subItem)">
|
||
<span class="subcategory-name">{{ subItem.secTitle }}</span>
|
||
<span v-if="getProductCount(subItem)" class="product-count">
|
||
{{ getProductCount(subItem) }}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 三级菜单(如果有且不是算/网分类) -->
|
||
<div v-if="hasThirdLevel && !isSpecialCategory" class="third-level-section">
|
||
<div class="third-level-list">
|
||
<div v-for="thirdItem in thirdLevelData"
|
||
:key="getThirdItemKey(thirdItem)"
|
||
class="third-level-item"
|
||
:class="{ active: activeThirdId === getThirdItemKey(thirdItem) }"
|
||
@click="switchThirdLevel(thirdItem)">
|
||
{{ thirdItem.thrTitle }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 主内容区 -->
|
||
<div class="main-content" :class="{ 'full-width': !hasMenuSidebar }">
|
||
<!-- 产品网格 -->
|
||
<div class="product-grid">
|
||
<div v-for="product in currentProducts"
|
||
:key="product.id"
|
||
class="product-card"
|
||
@click="handleProductClick(product)">
|
||
<div class="product-header">
|
||
<h3 class="product-name">{{ product.name }}</h3>
|
||
<span v-if="product.discount" class="discount-badge">
|
||
{{ product.discount }}折
|
||
</span>
|
||
</div>
|
||
<div class="product-desc">
|
||
{{ getProductDescription(product) }}
|
||
</div>
|
||
<div class="product-footer">
|
||
<span class="product-type">{{ product.type }}</span>
|
||
<button class="detail-btn">查看详情</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 空状态 -->
|
||
<div v-if="!hasProducts" class="empty-state">
|
||
<div class="empty-icon">📦</div>
|
||
<p class="empty-text">暂无产品数据</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { reqNavList, reqNewHomeSync, reqNewHomeFestival } from "@/api/newHome";
|
||
|
||
export default {
|
||
name: "ProductServicePage",
|
||
data() {
|
||
return {
|
||
panelData: [],
|
||
activeCategory: '',
|
||
activeSubId: null,
|
||
activeThirdId: null,
|
||
currentProducts: []
|
||
};
|
||
},
|
||
computed: {
|
||
currentSubcategories() {
|
||
if (!this.activeCategory || !this.panelData.length) return [];
|
||
const category = this.panelData.find(item => item.firTitle === this.activeCategory);
|
||
return category ? category.secMenu : [];
|
||
},
|
||
hasSecondLevel() {
|
||
return this.currentSubcategories && this.currentSubcategories.length > 0;
|
||
},
|
||
hasThirdLevel() {
|
||
return this.thirdLevelData && this.thirdLevelData.length > 0;
|
||
},
|
||
hasProducts() {
|
||
return this.currentProducts && this.currentProducts.length > 0;
|
||
},
|
||
hasMenuSidebar() {
|
||
return this.hasSecondLevel || this.hasThirdLevel;
|
||
},
|
||
isSpecialCategory() {
|
||
return this.activeCategory === '算' || this.activeCategory === '网';
|
||
},
|
||
thirdLevelData() {
|
||
if (!this.activeSubId || !this.currentSubcategories.length) return [];
|
||
|
||
// 从activeSubId中提取真实的subItem id
|
||
const realSubId = this.activeSubId.split('_')[0];
|
||
const subItem = this.currentSubcategories.find(item =>
|
||
item.id === realSubId || item.id?.toString() === realSubId
|
||
);
|
||
|
||
return subItem && subItem.thrMenu ? subItem.thrMenu : [];
|
||
},
|
||
// 检查是否登录
|
||
loginState() {
|
||
const userId = sessionStorage.getItem('userId');
|
||
return userId !== null && userId !== 'null' && userId !== '';
|
||
}
|
||
},
|
||
async mounted() {
|
||
await this.loadNavData();
|
||
this.initializeDefaultData();
|
||
},
|
||
methods: {
|
||
// 生成唯一的二级菜单项key
|
||
getSubItemKey(subItem) {
|
||
return `${subItem.id}_${this.activeCategory}_${subItem.secTitle}`;
|
||
},
|
||
|
||
// 生成唯一的三级菜单项key
|
||
getThirdItemKey(thirdItem) {
|
||
return `${thirdItem.id}_${this.activeSubId}_${thirdItem.thrTitle}`;
|
||
},
|
||
|
||
// 加载导航数据
|
||
async loadNavData() {
|
||
try {
|
||
const response = await reqNavList({ url_link: window.location.href });
|
||
if (response.status && response.data.product_service) {
|
||
this.panelData = this.processNavData(response.data.product_service);
|
||
}
|
||
} catch (error) {
|
||
console.error("加载产品数据失败:", error);
|
||
this.panelData = [];
|
||
}
|
||
},
|
||
|
||
// 处理导航数据 - 修复数据结构
|
||
processNavData(data) {
|
||
return data.map((category, categoryIndex) => {
|
||
// 确保一级分类有唯一标识
|
||
if (!category.uniqueId) {
|
||
category.uniqueId = `category_${categoryIndex}_${category.firTitle}`;
|
||
}
|
||
|
||
if (category.secMenu) {
|
||
category.secMenu.forEach((secItem, secIndex) => {
|
||
// 确保二级菜单项有唯一标识
|
||
if (!secItem.id) {
|
||
secItem.id = `sec_${categoryIndex}_${secIndex}`;
|
||
}
|
||
|
||
if (secItem.thrMenu) {
|
||
secItem.thrMenu.forEach((thrItem, thrIndex) => {
|
||
// 确保三级菜单项有唯一标识
|
||
if (!thrItem.id) {
|
||
thrItem.id = `thr_${categoryIndex}_${secIndex}_${thrIndex}`;
|
||
}
|
||
|
||
if (thrItem.value) {
|
||
thrItem.value.forEach(product => {
|
||
product.type = secItem.secTitle;
|
||
// 确保产品有唯一ID
|
||
if (!product.id) {
|
||
product.id = `product_${categoryIndex}_${secIndex}_${thrIndex}_${Math.random().toString(36).substr(2, 9)}`;
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
return category;
|
||
});
|
||
},
|
||
|
||
// 初始化默认数据
|
||
initializeDefaultData() {
|
||
if (this.panelData.length > 0) {
|
||
const firstCategory = this.panelData[0];
|
||
this.activeCategory = firstCategory.firTitle;
|
||
this.setDefaultSubcategory(firstCategory);
|
||
}
|
||
},
|
||
|
||
// 根据分类设置默认二级菜单
|
||
setDefaultSubcategory(category) {
|
||
if (category.secMenu && category.secMenu.length > 0) {
|
||
let defaultSubItem = category.secMenu[0];
|
||
|
||
if (category.firTitle === '算') {
|
||
const zhishuanItem = category.secMenu.find(item =>
|
||
item.secTitle && item.secTitle.includes('智算')
|
||
);
|
||
if (zhishuanItem) defaultSubItem = zhishuanItem;
|
||
} else if (category.firTitle === '网') {
|
||
const networkItem = category.secMenu.find(item =>
|
||
item.secTitle && item.secTitle.includes('算力网络')
|
||
);
|
||
if (networkItem) defaultSubItem = networkItem;
|
||
}
|
||
|
||
this.activeSubId = this.getSubItemKey(defaultSubItem);
|
||
this.updateProductList(defaultSubItem);
|
||
} else {
|
||
this.activeSubId = null;
|
||
this.activeThirdId = null;
|
||
this.currentProducts = this.getAllProductsFromCategory(category);
|
||
}
|
||
},
|
||
|
||
// 获取分类下的所有产品
|
||
getAllProductsFromCategory(category) {
|
||
let allProducts = [];
|
||
if (category.secMenu) {
|
||
category.secMenu.forEach(secItem => {
|
||
if (secItem.thrMenu) {
|
||
secItem.thrMenu.forEach(thrItem => {
|
||
if (thrItem.value) {
|
||
allProducts = allProducts.concat(thrItem.value);
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
return allProducts;
|
||
},
|
||
|
||
// 切换分类
|
||
switchCategory(category) {
|
||
this.activeCategory = category.firTitle;
|
||
this.activeSubId = null;
|
||
this.activeThirdId = null;
|
||
this.setDefaultSubcategory(category);
|
||
},
|
||
|
||
// 切换二级分类
|
||
switchSubcategory(subItem) {
|
||
this.activeSubId = this.getSubItemKey(subItem);
|
||
this.activeThirdId = null;
|
||
this.updateProductList(subItem);
|
||
},
|
||
|
||
// 切换三级分类
|
||
switchThirdLevel(thirdItem) {
|
||
this.activeThirdId = this.getThirdItemKey(thirdItem);
|
||
this.currentProducts = thirdItem.value || [];
|
||
},
|
||
|
||
// 更新产品列表
|
||
updateProductList(subItem) {
|
||
if (this.isSpecialCategory) {
|
||
this.currentProducts = this.getAllProductsFromSubcategory(subItem);
|
||
return;
|
||
}
|
||
|
||
if (subItem.thrMenu && subItem.thrMenu.length > 0) {
|
||
this.activeThirdId = null;
|
||
this.currentProducts = this.getAllProductsFromSubcategory(subItem);
|
||
} else {
|
||
this.activeThirdId = null;
|
||
this.currentProducts = [];
|
||
}
|
||
},
|
||
|
||
// 获取二级分类下的所有产品
|
||
getAllProductsFromSubcategory(subItem) {
|
||
let allProducts = [];
|
||
if (subItem.thrMenu) {
|
||
subItem.thrMenu.forEach(thrItem => {
|
||
if (thrItem.value) {
|
||
allProducts = allProducts.concat(thrItem.value);
|
||
}
|
||
});
|
||
}
|
||
return allProducts;
|
||
},
|
||
|
||
// 获取产品数量
|
||
getProductCount(subItem) {
|
||
if (!subItem.thrMenu) return 0;
|
||
return subItem.thrMenu.reduce((total, thirdItem) => {
|
||
return total + (thirdItem.value ? thirdItem.value.length : 0);
|
||
}, 0);
|
||
},
|
||
|
||
// 获取产品描述
|
||
getProductDescription(product) {
|
||
const descriptions = {
|
||
'云服务器_GPU': '高性能GPU云服务器,适合AI训练、科学计算等场景',
|
||
'云服务器_BCC': '平衡型云服务器,满足大多数业务需求',
|
||
'专属服务器': '独享物理服务器,提供更高性能和安全隔离',
|
||
'轻量应用服务器': '轻量级应用部署,简单易用',
|
||
'专线接入': '高速稳定的专线网络接入服务',
|
||
'文字识别': '高精度文字识别,支持多种场景和语言',
|
||
'AI能力引擎': '强大的AI能力引擎,赋能各种智能应用',
|
||
'大数据平台': '全面的大数据处理和分析平台',
|
||
'云服务平台': '一站式云服务平台,便捷高效',
|
||
'智能内容科技': '智能内容生成与处理技术',
|
||
'SME企业服务': '中小企业专属服务解决方案',
|
||
'视频云平台': '专业的视频云处理与分发平台',
|
||
'智能短信': '智能化短信服务和营销解决方案'
|
||
};
|
||
return descriptions[product.name] || '专业的云服务产品,提供稳定可靠的服务';
|
||
},
|
||
|
||
// 修复阿里云跳转逻辑
|
||
async handleAliyunProductClick() {
|
||
try {
|
||
// 第一步:同步请求
|
||
const syncResponse = await reqNewHomeSync();
|
||
|
||
if (!syncResponse.status) {
|
||
this.$message.warning(syncResponse.msg || '同步失败,请稍后重试');
|
||
return;
|
||
}
|
||
|
||
// 第二步:获取跳转链接
|
||
const festivalResponse = await reqNewHomeFestival();
|
||
|
||
if (festivalResponse.status && festivalResponse.data) {
|
||
window.open(festivalResponse.data);
|
||
} else {
|
||
this.$message.warning(festivalResponse.msg || '获取跳转链接失败');
|
||
}
|
||
} catch (error) {
|
||
console.error('阿里云跳转失败:', error);
|
||
this.$message.error('网络错误,请稍后重试');
|
||
}
|
||
},
|
||
|
||
// 点击产品
|
||
async handleProductClick(product) {
|
||
console.log('点击产品:', product);
|
||
|
||
const userId = sessionStorage.getItem('userId');
|
||
|
||
if (product.type === '百度云') {
|
||
if (userId) {
|
||
localStorage.setItem('redirectUrl', product.url);
|
||
localStorage.setItem('userRescourseUrl', product.listUrl);
|
||
this.$router.push({
|
||
name: 'baiduProductShow',
|
||
params: {
|
||
listUrl: product.listUrl,
|
||
url: product.url
|
||
}
|
||
});
|
||
} else {
|
||
this.$router.push({
|
||
path: "/login",
|
||
query: {
|
||
fromPath: 'productService',
|
||
type: 'bd',
|
||
listUrl: product.listUrl,
|
||
url: product.url
|
||
}
|
||
});
|
||
}
|
||
} else if (product.type === '阿里云') {
|
||
|
||
if (userId) {
|
||
await this.handleAliyunProductClick();
|
||
} else {
|
||
this.$router.push({
|
||
path: "/login",
|
||
query: {
|
||
fromPath: 'productService',
|
||
type: 'ali',
|
||
}
|
||
});
|
||
}
|
||
} else if (product.type === '智算' || product.type === '算力网络') {
|
||
if (product.name === '容器云') {
|
||
if (userId) {
|
||
this.$router.push('/product/productHome/k8s/createK8s');
|
||
} else {
|
||
this.$router.push({
|
||
path: "/login",
|
||
query: {
|
||
fromPath: 'productService',
|
||
type: 'rqy',
|
||
}
|
||
});
|
||
}
|
||
} else {
|
||
this.$router.push({
|
||
path: '/homePage/detail',
|
||
query: {
|
||
id: product.id,
|
||
}
|
||
});
|
||
}
|
||
} else if (product.name === '灵医智能体') {
|
||
this.$router.push('/homePage/hospital');
|
||
} else if (product.name === '客悦·智能客服') {
|
||
this.$router.push('/homePage/customerService');
|
||
}
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="less" scoped>
|
||
.product-service-page {
|
||
margin: 0 auto;
|
||
padding: 24px;
|
||
background: #fff;
|
||
min-height: calc(100vh - 100px);
|
||
|
||
.category-nav {
|
||
display: flex;
|
||
justify-content: space-around;
|
||
margin-bottom: 32px;
|
||
border-bottom: 1px solid #f0f0f0;
|
||
|
||
.nav-item {
|
||
padding: 12px 24px;
|
||
font-size: 16px;
|
||
color: #666;
|
||
cursor: pointer;
|
||
border-bottom: 2px solid transparent;
|
||
transition: all 0.3s;
|
||
|
||
&:hover {
|
||
color: #1E6FFF;
|
||
}
|
||
|
||
&.active {
|
||
color: #1E6FFF;
|
||
border-bottom-color: #1E6FFF;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
}
|
||
|
||
.product-content {
|
||
display: flex;
|
||
gap: 24px;
|
||
|
||
.menu-sidebar {
|
||
width: 280px;
|
||
background: #f8f9fa;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
flex-shrink: 0;
|
||
|
||
.section-title {
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: #1a1a1a;
|
||
margin-bottom: 16px;
|
||
padding-bottom: 8px;
|
||
border-bottom: 1px solid #e8e8e8;
|
||
}
|
||
|
||
.subcategory-section {
|
||
margin-bottom: 24px;
|
||
}
|
||
|
||
.subcategory-list,
|
||
.third-level-list {
|
||
.subcategory-item,
|
||
.third-level-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 10px 12px;
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
border-radius: 6px;
|
||
margin-bottom: 4px;
|
||
|
||
&:hover {
|
||
background: rgba(30, 111, 255, 0.05);
|
||
color: #1E6FFF;
|
||
}
|
||
|
||
&.active {
|
||
background: rgba(30, 111, 255, 0.1);
|
||
color: #1E6FFF;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.subcategory-name {
|
||
font-size: 14px;
|
||
}
|
||
|
||
.product-count {
|
||
background: #e8f4ff;
|
||
color: #1E6FFF;
|
||
font-size: 12px;
|
||
padding: 2px 8px;
|
||
border-radius: 10px;
|
||
min-width: 20px;
|
||
text-align: center;
|
||
}
|
||
}
|
||
}
|
||
|
||
.third-level-list {
|
||
.third-level-item {
|
||
padding-left: 20px;
|
||
font-size: 13px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.main-content {
|
||
flex: 1;
|
||
|
||
&.full-width {
|
||
flex: 1;
|
||
margin-left: 0;
|
||
}
|
||
|
||
.product-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||
gap: 20px;
|
||
|
||
.product-card {
|
||
background: #fff;
|
||
border: 1px solid #f0f0f0;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||
|
||
&:hover {
|
||
transform: translateY(-4px);
|
||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
||
border-color: #1E6FFF;
|
||
}
|
||
|
||
.product-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
margin-bottom: 12px;
|
||
|
||
.product-name {
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: #1a1a1a;
|
||
margin: 0;
|
||
flex: 1;
|
||
}
|
||
|
||
.discount-badge {
|
||
background: linear-gradient(135deg, #ff6b6b, #ff4757);
|
||
color: #fff;
|
||
font-size: 12px;
|
||
padding: 4px 8px;
|
||
border-radius: 4px;
|
||
font-weight: 600;
|
||
margin-left: 8px;
|
||
}
|
||
}
|
||
|
||
.product-desc {
|
||
font-size: 14px;
|
||
color: #666;
|
||
line-height: 1.5;
|
||
margin-bottom: 16px;
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.product-footer {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
.product-type {
|
||
font-size: 12px;
|
||
color: #999;
|
||
background: #f8f9fa;
|
||
padding: 4px 8px;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.detail-btn {
|
||
background: #1E6FFF;
|
||
color: #fff;
|
||
border: none;
|
||
padding: 6px 12px;
|
||
border-radius: 4px;
|
||
font-size: 12px;
|
||
cursor: pointer;
|
||
transition: background 0.3s;
|
||
|
||
&:hover {
|
||
background: #0d5ae0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.empty-state {
|
||
text-align: center;
|
||
padding: 60px 20px;
|
||
|
||
.empty-icon {
|
||
font-size: 48px;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.empty-text {
|
||
color: #999;
|
||
font-size: 14px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.product-service-page {
|
||
padding: 16px;
|
||
|
||
.product-content {
|
||
flex-direction: column;
|
||
|
||
.menu-sidebar {
|
||
width: 100%;
|
||
order: 2;
|
||
}
|
||
|
||
.main-content {
|
||
order: 1;
|
||
|
||
&.full-width {
|
||
margin-left: 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
.product-grid {
|
||
grid-template-columns: 1fr !important;
|
||
}
|
||
}
|
||
}
|
||
</style>
|