系统上线运行问题修改

This commit is contained in:
lSun 2025-09-22 11:14:30 +08:00
parent c06bc5fbbd
commit 79b9349598
5 changed files with 896 additions and 795 deletions

View File

@ -110,6 +110,7 @@ export const constantRoutes = [
component: () => component: () =>
import('@/views/publicService/productCenter/index.vue'), import('@/views/publicService/productCenter/index.vue'),
name: 'ProductCenter', name: 'ProductCenter',
meta: { showSearch: true } // 需要搜索框
}, },
// 产品中心 ---- 查看详情页面 // 产品中心 ---- 查看详情页面
@ -120,6 +121,7 @@ export const constantRoutes = [
'@/views/publicService/productCenter/product-detail.vue' '@/views/publicService/productCenter/product-detail.vue'
), ),
name: 'ProductDetail', name: 'ProductDetail',
meta: { showSearch: false } // 不需要搜索框
}, },
// 产品中心 ---- 查看案例页面 // 产品中心 ---- 查看案例页面
{ {
@ -129,6 +131,7 @@ export const constantRoutes = [
'@/views/publicService/productCenter/product-case-list.vue' '@/views/publicService/productCenter/product-case-list.vue'
), ),
name: 'ProductCaseList', name: 'ProductCaseList',
meta: { showSearch: false } // 不需要搜索框
}, },
// 公共组件 // 公共组件
{ {
@ -136,6 +139,7 @@ export const constantRoutes = [
component: () => component: () =>
import('@/views/publicService/commonCom/index.vue'), import('@/views/publicService/commonCom/index.vue'),
name: 'CommonCom', name: 'CommonCom',
meta: { showSearch: true } // 需要搜索框
}, },
// 宣传物料 // 宣传物料
{ {
@ -143,6 +147,7 @@ export const constantRoutes = [
component: () => component: () =>
import('@/views/publicService/proMaterials/index.vue'), import('@/views/publicService/proMaterials/index.vue'),
name: 'ProMaterials', name: 'ProMaterials',
meta: { showSearch: true } // 需要搜索框
}, },
// 文档中心 // 文档中心
{ {
@ -150,6 +155,7 @@ export const constantRoutes = [
component: () => component: () =>
import('@/views/publicService/docCenter/index.vue'), import('@/views/publicService/docCenter/index.vue'),
name: 'DocCenter', name: 'DocCenter',
meta: { showSearch: true } // 需要搜索框
}, },
], ],
}, },

View File

@ -1,377 +1,397 @@
<template> <template>
<div class="header_new"> <div class="header_new">
<div class="header-content"> <div class="header-content">
<div class="header-left"> <div class="header-left">
<!-- <div class="logo-section" @click="handleLogoClick">--> <!-- <div class="logo-section" @click="handleLogoClick">-->
<div class="logo-section" > <div class="logo-section">
<img <img
src="../../../assets/logo/logo.png" src="../../../assets/logo/logo.png"
alt="Logo" alt="Logo"
class="logo" class="logo"
/> />
<span class="platform-title">{{ platformTitle }}</span> <span class="platform-title">{{ platformTitle }}</span>
</div>
</div>
<div class="header-nav">
<div
class="nav-item"
:key="item.routePath"
v-for="item in navItems"
@click="handleNavClick(item)"
:class="{ active: activeNav === item.routePath }"
>
<img :src="item.icon" :alt="item.label" class="nav-icon" />
<span class="nav-text">{{ item.label }}</span>
</div>
</div>
<div v-if="showRightSection" class="header-right"> </div>
<el-dropdown
trigger="hover"
class="avatar-container right-menu-item hover-effect"
>
<div class="avatar-wrapper">
<img :src="avatar" class="user-avatar" />
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="handleLogoClick">
后台管理
</el-dropdown-item>
<el-dropdown-item divided @click.native="logout">
<span>退出登录</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div> </div>
</div>
<div class="header-nav">
<div
class="nav-item"
:key="item.routePath"
v-for="item in navItems"
@click="handleNavClick(item)"
:class="{ active: activeNav === item.routePath }"
>
<img :src="item.icon" :alt="item.label" class="nav-icon"/>
<span class="nav-text">{{ item.label }}</span>
</div>
</div>
<div v-if="showRightSection" class="header-right">
<div v-if="showSearch" class="search-box">
<input
v-model="internalSearchKeyword"
type="text"
placeholder="输入关键词搜索"
class="search-input"
@keyup.enter="handleSearch"
/>
<button class="search-btn" @click="handleSearch">
<i class="el-icon-search"></i>
</button>
</div>
</div>
<el-dropdown
trigger="hover"
class="avatar-container right-menu-item hover-effect"
>
<div class="avatar-wrapper">
<img :src="avatar" class="user-avatar"/>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="handleLogoClick">
后台管理
</el-dropdown-item>
<el-dropdown-item divided @click.native="logout">
<span>退出登录</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div> </div>
</div>
</template> </template>
<script> <script>
import { mapGetters } from 'vuex' import {mapGetters} from 'vuex'
import {getPermissions} from "../../../utils/auth"; import {getPermissions} from "../../../utils/auth";
export default { export default {
name: 'NavBar', name: 'NavBar',
props: { props: {
logoUrl: { logoUrl: {
type: String, type: String,
default: '/img/psp/productCenter/logo.png', default: '/img/psp/productCenter/logo.png',
},
platformTitle: {
type: String,
default: '公共服务平台',
},
showRightSection: {
type: Boolean,
default: true,
},
showSearch: {
type: Boolean,
default: true,
},
showUserAvatar: {
type: Boolean,
default: true,
},
userAvatar: {
type: String,
default: '',
},
searchKeyword: {
type: String,
default: '',
},
}, },
platformTitle: {
type: String,
default: '公共服务平台',
},
showRightSection: {
type: Boolean,
default: true,
},
showSearch: {
type: Boolean,
default: true,
},
showUserAvatar: {
type: Boolean,
default: true,
},
userAvatar: {
type: String,
default: '',
},
searchKeyword: {
type: String,
default: '',
},
},
computed: { computed: {
...mapGetters(['avatar']), ...mapGetters(['avatar']),
// activeNav // activeNav
activeNav() { activeNav() {
// //
const routeName = this.$route.name; const routeName = this.$route.name;
const routePath = this.$route.path; const routePath = this.$route.path;
// //
if (routeName) { if (routeName) {
const matchedItem = this.navItems.find(item => item.routePath === routeName); const matchedItem = this.navItems.find(item => item.routePath === routeName);
if (matchedItem) { if (matchedItem) {
return matchedItem.routePath; return matchedItem.routePath;
}
} }
}
// //
if (routePath) { if (routePath) {
const matchedItem = this.navItems.find(item => const matchedItem = this.navItems.find(item =>
routePath.includes(item.routePath.toLowerCase()) routePath.includes(item.routePath.toLowerCase())
); );
if (matchedItem) { if (matchedItem) {
return matchedItem.routePath; return matchedItem.routePath;
}
} }
}
// //
return 'ProductCenter'; return 'ProductCenter';
},
setting: {
get() {
return this.$store.state.settings.showSettings
}, },
setting: {
get() {
return this.$store.state.settings.showSettings
},
},
topNav: {
get() {
return this.$store.state.settings.topNav
},
},
}, },
data() { topNav: {
return { get() {
// activeNav: 'ProductCenter', // return this.$store.state.settings.topNav
userAvatarUrl: this.userAvatar,
internalSearchKeyword: this.searchKeyword,
permissions:getPermissions(),
navItems: [
{
label: '产品中心',
routePath: 'ProductCenter',
icon: require('../../../assets/images/productCenter/products.png'),
},
{
label: '公共组件',
routePath: 'CommonCom',
icon: require('../../../assets/images/productCenter/components.png'),
},
{
label: '宣传物料',
routePath: 'ProMaterials',
icon: require('../../../assets/images/productCenter/materials.png'),
},
{
label: '文档中心',
routePath: 'DocCenter',
icon: require('../../../assets/images/productCenter/docs.png'),
},
],
}
},
watch: {
'$route'() {
// activeNav
}, },
searchKeyword(newVal) {
this.internalSearchKeyword = newVal
},
userAvatar(newVal) {
this.userAvatarUrl = newVal
},
}, },
methods: { },
handleNavClick(item) { data() {
// this.activeNav = item.routePath return {
this.$router.push({ // activeNav: 'ProductCenter', //
name: item.routePath, userAvatarUrl: this.userAvatar,
}) internalSearchKeyword: this.searchKeyword,
permissions: getPermissions(),
navItems: [
{
label: '产品中心',
routePath: 'ProductCenter',
icon: require('../../../assets/images/productCenter/products.png'),
}, },
handleSearch() { {
// 使internalSearchKeyword label: '公共组件',
this.$emit('update:searchKeyword', this.internalSearchKeyword) routePath: 'CommonCom',
this.$emit('search', this.internalSearchKeyword) icon: require('../../../assets/images/productCenter/components.png'),
}, },
{
// label: '宣传物料',
handleLogoClick() { routePath: 'ProMaterials',
if(this.permissions.includes(2) ){ icon: require('../../../assets/images/productCenter/materials.png'),
this.$router.push('/')
}else{
//
this.$message.error('没有后台权限,请联系管理员')
}
}, },
{
logout() { label: '文档中心',
this.$confirm('确定注销并退出系统吗?', '提示', { routePath: 'DocCenter',
confirmButtonText: '确定', icon: require('../../../assets/images/productCenter/docs.png'),
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
this.$store.dispatch('LogOut').then(() => {
location.href =
process.env.VUE_APP_ENV === 'production'
? '/pubSerPlatform/index'
: '/index'
})
})
.catch(() => {})
}, },
],
}
},
watch: {
'$route'() {
// activeNav
}, },
searchKeyword(newVal) {
this.internalSearchKeyword = newVal
},
userAvatar(newVal) {
this.userAvatarUrl = newVal
},
internalSearchKeyword(newVal) {
//
this.$emit('update:searchKeyword', newVal)
}
},
methods: {
handleNavClick(item) {
// this.activeNav = item.routePath
this.$router.push({
name: item.routePath,
})
},
handleSearch() {
console.log('执行搜索:', this.internalSearchKeyword)
//
this.$emit('search', this.internalSearchKeyword.trim())
},
//
handleLogoClick() {
if (this.permissions.includes(2)) {
this.$router.push('/')
} else {
//
this.$message.error('没有后台权限,请联系管理员')
}
},
logout() {
this.$confirm('确定注销并退出系统吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
this.$store.dispatch('LogOut').then(() => {
location.href =
process.env.VUE_APP_ENV === 'production'
? '/pubSerPlatform/index'
: '/index'
})
})
.catch(() => {
})
},
},
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.header_new { .header_new {
background-image: url('../../../assets/images/productCenter/topbg.png'); background-image: url('../../../assets/images/productCenter/topbg.png');
color: white; color: white;
padding: 0; padding: 0;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
} }
.header-content { .header-content {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
max-width: 100vw; max-width: 100vw;
margin: 0 auto; margin: 0 auto;
padding: 12px 20px; padding: 12px 20px;
} }
.header-left { .header-left {
display: flex; display: flex;
align-items: center; align-items: center;
} }
.logo-section { .logo-section {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12px; gap: 12px;
//cursor: pointer; //cursor: pointer;
cursor: context-menu; cursor: context-menu;
} }
.logo { .logo {
width: 32px; width: 32px;
height: 32px; height: 32px;
border-radius: 6px; border-radius: 6px;
} }
.platform-title { .platform-title {
font-size: 18px; font-size: 18px;
font-weight: 600; font-weight: 600;
color: white; color: white;
} }
.header-nav { .header-nav {
display: flex; display: flex;
gap: 32px; gap: 32px;
justify-content: space-between; justify-content: space-between;
} }
.nav-item { .nav-item {
padding: 8px 16px; padding: 8px 16px;
cursor: pointer; cursor: pointer;
border-radius: 6px; border-radius: 6px;
transition: all 0.2s ease; transition: all 0.2s ease;
font-size: 14px; font-size: 14px;
display: flex; display: flex;
align-items: center; align-items: center;
} }
.nav-icon { .nav-icon {
width: 20px; width: 20px;
height: 20px; height: 20px;
object-fit: contain; object-fit: contain;
margin-right: 10px; margin-right: 10px;
flex-shrink: 0; flex-shrink: 0;
} }
.nav-text { .nav-text {
white-space: nowrap; white-space: nowrap;
} }
.nav-item:hover, .nav-item:hover,
.nav-item.active { .nav-item.active {
background-color: rgba(255, 255, 255, 0.15); background-color: rgba(255, 255, 255, 0.15);
} }
.header-right { .header-right {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 16px; gap: 16px;
} }
.search-box { .search-box {
display: flex; display: flex;
align-items: center; align-items: center;
background: rgba(255, 255, 255, 0.15); background: rgba(255, 255, 255, 0.15);
border-radius: 20px; border-radius: 20px;
padding: 6px 12px; padding: 6px 12px;
} }
.search-input { .search-input {
background: transparent; background: transparent;
border: none; border: none;
outline: none; outline: none;
color: white; color: white;
font-size: 14px; font-size: 14px;
width: 200px; width: 200px;
} }
.search-input::placeholder { .search-input::placeholder {
color: rgba(255, 255, 255, 0.7); color: rgba(255, 255, 255, 0.7);
} }
.search-btn { .search-btn {
background: none; background: none;
border: none; border: none;
color: white; color: white;
cursor: pointer; cursor: pointer;
padding: 4px; padding: 4px;
} }
.user-avatar img { .user-avatar img {
width: 32px; width: 32px;
height: 32px; height: 32px;
border-radius: 50%; border-radius: 50%;
border: 2px solid rgba(255, 255, 255, 0.3); border: 2px solid rgba(255, 255, 255, 0.3);
} }
/* 响应式设计 */ /* 响应式设计 */
@media (max-width: 768px) { @media (max-width: 768px) {
.header-content { .header-content {
flex-direction: column; flex-direction: column;
gap: 12px; gap: 12px;
padding: 16px; padding: 16px;
} }
.header-nav { .header-nav {
gap: 16px; gap: 16px;
} }
.search-input { .search-input {
width: 150px; width: 150px;
} }
} }
.avatar-container { .avatar-container {
margin-right: 0px; margin-right: 0px;
padding-right: 0px; padding-right: 0px;
.avatar-wrapper { .avatar-wrapper {
margin-top: 10px; margin-top: 10px;
position: relative; position: relative;
.user-avatar { .user-avatar {
cursor: pointer; cursor: pointer;
width: 30px; width: 30px;
height: 30px; height: 30px;
border-radius: 50%; border-radius: 50%;
}
.user-nickname {
position: relative;
bottom: 10px;
font-size: 14px;
font-weight: bold;
}
.el-icon-caret-bottom {
cursor: pointer;
position: absolute;
right: -20px;
top: 25px;
font-size: 12px;
}
} }
.user-nickname {
position: relative;
bottom: 10px;
font-size: 14px;
font-weight: bold;
}
.el-icon-caret-bottom {
cursor: pointer;
position: absolute;
right: -20px;
top: 25px;
font-size: 12px;
}
}
} }
</style> </style>

View File

@ -1,13 +1,17 @@
<template> <template>
<div class="platform-container"> <div class="platform-container">
<!-- 使用导航栏组件 --> <!-- 使用导航栏组件 -->
<NavBar /> <NavBar
@search="handleSearch"
:searchKeyword.sync="searchKeyword"
:showSearch="showSearch"
/>
<div class="main-content-1"> <div class="main-content-1">
<!-- 主体内容 --> <!-- 主体内容 -->
<router-view /> <router-view :search-keyword="searchKeyword"/>
</div>
</div> </div>
</div>
</template> </template>
<script> <script>
@ -15,25 +19,48 @@
import NavBar from './components/navBar.vue' import NavBar from './components/navBar.vue'
export default { export default {
name: 'PublicService', name: 'PublicService',
components: { components: {
NavBar, NavBar,
}, },
data() {
return {
searchKeyword: '' //
}
},
computed: {
//
showSearch() {
//
return this.$route.meta.showSearch !== false
}
},
methods: {
//
handleSearch(keyword) {
console.log('接收到搜索关键词:', keyword)
this.searchKeyword = keyword
//
//
this.$refs.currentView?.search(keyword)
}
}
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.platform-container { .platform-container {
height: 100%; height: 100%;
width: 100%; width: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.main-content-1 { .main-content-1 {
flex: 1; flex: 1;
width: 100%; width: 100%;
overflow: auto; overflow: auto;
} }
/* 顶部导航栏 */ /* 顶部导航栏 */
@ -45,273 +72,273 @@ export default {
// } // }
.header-content { .header-content {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
max-width: 100vw; max-width: 100vw;
margin: 0 auto; margin: 0 auto;
padding: 12px 20px; padding: 12px 20px;
} }
.header-left { .header-left {
display: flex; display: flex;
align-items: center; align-items: center;
} }
.logo-section { .logo-section {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12px; gap: 12px;
} }
.logo { .logo {
width: 32px; width: 32px;
height: 32px; height: 32px;
border-radius: 6px; border-radius: 6px;
} }
.platform-title { .platform-title {
font-size: 18px; font-size: 18px;
font-weight: 600; font-weight: 600;
color: white; color: white;
} }
.header-nav { .header-nav {
display: flex; display: flex;
gap: 32px; gap: 32px;
justify-content: space-between; justify-content: space-between;
} }
.nav-item { .nav-item {
padding: 8px 16px; padding: 8px 16px;
cursor: pointer; cursor: pointer;
border-radius: 6px; border-radius: 6px;
transition: all 0.2s ease; transition: all 0.2s ease;
font-size: 14px; font-size: 14px;
display: flex; display: flex;
align-items: center; align-items: center;
} }
.nav-icon { .nav-icon {
width: 20px; width: 20px;
height: 20px; height: 20px;
object-fit: contain; object-fit: contain;
margin-right: 10px; margin-right: 10px;
flex-shrink: 0; flex-shrink: 0;
} }
.nav-text { .nav-text {
white-space: nowrap; white-space: nowrap;
} }
.nav-item:hover, .nav-item:hover,
.nav-item.active { .nav-item.active {
background-color: rgba(255, 255, 255, 0.15); background-color: rgba(255, 255, 255, 0.15);
} }
.header-right { .header-right {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 16px; gap: 16px;
} }
.search-box { .search-box {
display: flex; display: flex;
align-items: center; align-items: center;
background: rgba(255, 255, 255, 0.15); background: rgba(255, 255, 255, 0.15);
border-radius: 20px; border-radius: 20px;
padding: 6px 12px; padding: 6px 12px;
} }
.search-input { .search-input {
background: transparent; background: transparent;
border: none; border: none;
outline: none; outline: none;
color: white; color: white;
font-size: 14px; font-size: 14px;
width: 200px; width: 200px;
} }
.search-input::placeholder { .search-input::placeholder {
color: rgba(255, 255, 255, 0.7); color: rgba(255, 255, 255, 0.7);
} }
.search-btn { .search-btn {
background: none; background: none;
border: none; border: none;
color: white; color: white;
cursor: pointer; cursor: pointer;
padding: 4px; padding: 4px;
} }
.user-avatar img { .user-avatar img {
width: 32px; width: 32px;
height: 32px; height: 32px;
border-radius: 50%; border-radius: 50%;
border: 2px solid rgba(255, 255, 255, 0.3); border: 2px solid rgba(255, 255, 255, 0.3);
} }
/* 主体内容 */ /* 主体内容 */
.main-content { .main-content {
display: flex; display: flex;
max-width: 95%; max-width: 95%;
margin: 0 auto; margin: 0 auto;
padding: 24px 20px; padding: 24px 20px;
gap: 24px; gap: 24px;
} }
/* 左侧分类菜单 */ /* 左侧分类菜单 */
.sidebar { .sidebar {
width: 160px; width: 160px;
flex-shrink: 0; flex-shrink: 0;
} }
.category-item { .category-item {
padding: 12px 16px; padding: 12px 16px;
margin-bottom: 8px; margin-bottom: 8px;
background: white; background: white;
border-radius: 8px; border-radius: 8px;
cursor: pointer; cursor: pointer;
transition: all 0.2s ease; transition: all 0.2s ease;
font-size: 14px; font-size: 14px;
color: #666; color: #666;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
} }
.category-item:hover { .category-item:hover {
background-color: #f0f7ff; background-color: #f0f7ff;
color: #4a90e2; color: #4a90e2;
} }
.category-item.active { .category-item.active {
background-color: #4a90e2; background-color: #4a90e2;
color: white; color: white;
} }
/* 服务卡片区域 */ /* 服务卡片区域 */
.content-area { .content-area {
flex: 1; flex: 1;
} }
.services-grid { .services-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 20px; gap: 20px;
} }
.service-card { .service-card {
background: white; background: white;
border-radius: 12px; border-radius: 12px;
overflow: hidden; overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease; transition: all 0.3s ease;
cursor: pointer; cursor: pointer;
height: 100%; /* 让卡片高度撑满 grid 单元格 */ height: 100%; /* 让卡片高度撑满 grid 单元格 */
} }
.service-card:hover { .service-card:hover {
transform: translateY(-4px); transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
} }
.card-image { .card-image {
height: 180px; /* 固定高度,可根据设计调整 */ height: 180px; /* 固定高度,可根据设计调整 */
overflow: hidden; overflow: hidden;
background-color: #f8f9fa; /* 图片加载前的占位背景 */ background-color: #f8f9fa; /* 图片加载前的占位背景 */
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.card-image img { .card-image img {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: contain; /* 关键:完整显示图片,不裁剪,保持比例 */ object-fit: contain; /* 关键:完整显示图片,不裁剪,保持比例 */
transition: transform 0.3s ease; transition: transform 0.3s ease;
} }
.service-card:hover .card-image img { .service-card:hover .card-image img {
transform: scale(1.05); transform: scale(1.05);
} }
.card-content { .card-content {
padding: 16px; padding: 16px;
} }
.card-title { .card-title {
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
color: #333; color: #333;
margin: 0 0 16px 0; margin: 0 0 16px 0;
line-height: 1.4; line-height: 1.4;
text-align: center; text-align: center;
} }
.card-actions { .card-actions {
display: flex; display: flex;
gap: 8px; gap: 8px;
} }
.btn { .btn {
padding: 8px 16px; padding: 8px 16px;
border-radius: 6px; border-radius: 6px;
font-size: 12px; font-size: 12px;
cursor: pointer; cursor: pointer;
transition: all 0.2s ease; transition: all 0.2s ease;
border: 1px solid transparent; border: 1px solid transparent;
flex: 1; flex: 1;
text-align: center; text-align: center;
} }
.btn-primary { .btn-primary {
background-color: #4a90e2; background-color: #4a90e2;
color: white; color: white;
border-color: #4a90e2; border-color: #4a90e2;
} }
.btn-primary:hover { .btn-primary:hover {
background-color: #357abd; background-color: #357abd;
border-color: #357abd; border-color: #357abd;
} }
.btn-outline { .btn-outline {
background-color: transparent; background-color: transparent;
color: #4a90e2; color: #4a90e2;
border-color: #4a90e2; border-color: #4a90e2;
} }
.btn-outline:hover { .btn-outline:hover {
background-color: #4a90e2; background-color: #4a90e2;
color: white; color: white;
} }
/* 响应式设计 */ /* 响应式设计 */
@media (max-width: 768px) { @media (max-width: 768px) {
.header-content { .header-content {
flex-direction: column; flex-direction: column;
gap: 12px; gap: 12px;
padding: 16px; padding: 16px;
} }
.header-nav { .header-nav {
gap: 16px; gap: 16px;
} }
.main-content { .main-content {
flex-direction: column; flex-direction: column;
padding: 16px; padding: 16px;
} }
.sidebar { .sidebar {
width: 100%; width: 100%;
} }
.services-grid { .services-grid {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
.search-input { .search-input {
width: 150px; width: 150px;
} }
} }
</style> </style>

View File

@ -68,7 +68,6 @@
<div <div
class="primary-btn" class="primary-btn"
@click="handleDownload(item)" @click="handleDownload(item)"
> >
@ -77,6 +76,7 @@
</div> </div>
</div> </div>
<DialogModel <DialogModel
:dialogConfig="dialogConfig" :dialogConfig="dialogConfig"
@closeDialogOuter="handleCloseDialogOuter" @closeDialogOuter="handleCloseDialogOuter"
@ -105,8 +105,6 @@
</div> </div>
</div> </div>
</div> </div>
</template> </template>
@ -124,6 +122,12 @@ export default {
DialogModel, DialogModel,
}, },
dicts: ['tb_product_type'], dicts: ['tb_product_type'],
props: {
searchKeyword: {
type: String,
default: ''
}
},
data() { data() {
return { return {
downloading: false, // downloading: false, //
@ -189,37 +193,6 @@ export default {
}, 300); }, 300);
}, },
//
// updateFilteredList() {
// let filtered = this.proMaterialsListAll;
//
// //
// if (this.activeTypeValue !== 'all') {
// filtered = filtered.filter(item => item.typeId === Number(this.activeTypeValue));
// }
//
// //
// if (this.selectedTypes.length > 0) {
// filtered = filtered.filter(item =>
// this.selectedTypes.includes(item.fileType.toString())
// );
// }
//
// this.showProMaterialsDuctList = filtered;
// },
//
updateFilteredList() {
this.currentPage = 1;
//
if (this.requestTimeout) {
clearTimeout(this.requestTimeout);
}
this.requestTimeout = setTimeout(() => {
this.getProductCenterListInScreenFun();
}, 300);
},
// //
getItemWidth() { getItemWidth() {
this.itemWidth = (this.$refs.servicesGrid?.clientWidth - 120) / 4 this.itemWidth = (this.$refs.servicesGrid?.clientWidth - 120) / 4
@ -245,7 +218,6 @@ export default {
} }
}, },
// //
//
async handleDownload(service) { async handleDownload(service) {
// //
@ -319,31 +291,32 @@ export default {
} }
this.executeGetProductList(); this.executeGetProductList();
}, },
// //
async executeGetProductList() { async executeGetProductList() {
try { try {
let fileType = ""; let fileType = "";
if (this.selectedTypes.length > 0 && this.selectedTypes.length < 2) { if (this.selectedTypes.length > 0 && this.selectedTypes.length < 2) {
fileType = this.selectedTypes.join(','); fileType = this.selectedTypes.join(',');
} }
// list // list
const requestParams = { const requestParams = {
pageNum: this.currentPage, pageNum: this.currentPage,
pageSize: this.pageSize, pageSize: this.pageSize,
typeId: this.activeTypeValue !== 'all' ? this.activeTypeValue : undefined, typeId: this.activeTypeValue !== 'all' ? this.activeTypeValue : undefined,
fileType: fileType fileType: fileType,
}; //
name: this.searchKeyword || undefined
};
const res = await getMaterialListAPI(requestParams); const res = await getMaterialListAPI(requestParams);
this.proMaterialsListAll = res.rows; this.proMaterialsListAll = res.rows;
this.total = res.total || 0; this.total = res.total || 0;
this.showProMaterialsDuctList = this.proMaterialsListAll; this.showProMaterialsDuctList = this.proMaterialsListAll;
} catch (error) { } catch (error) {
console.error('获取物料列表失败:', error); console.error('获取物料列表失败:', error);
} }
}, },
// //
@ -419,9 +392,22 @@ export default {
}, 300); }, 300);
}, },
//
filterMaterialsByKeyword(materials, keyword) {
if (!keyword) return materials
const lowerKeyword = keyword.toLowerCase()
return materials.filter(item =>
//
(item.name && item.name.toLowerCase().includes(lowerKeyword)) ||
(item.description && item.description.toLowerCase().includes(lowerKeyword)) ||
(item.version && item.version.toLowerCase().includes(lowerKeyword)) ||
(item.typeName && item.typeName.toLowerCase().includes(lowerKeyword))
)
}
}, },
// //
watch: { watch: {
activeTypeValue() { activeTypeValue() {
this.currentPage = 1; this.currentPage = 1;
@ -433,6 +419,29 @@ export default {
this.getProductCenterListInScreenFun(); this.getProductCenterListInScreenFun();
}, 300); }, 300);
}, },
//
searchKeyword(newVal) {
this.currentPage = 1;
//
if (this.requestTimeout) {
clearTimeout(this.requestTimeout);
}
this.requestTimeout = setTimeout(() => {
this.getProductCenterListInScreenFun();
}, 300);
},
selectedTypes() {
this.currentPage = 1;
//
if (this.requestTimeout) {
clearTimeout(this.requestTimeout);
}
this.requestTimeout = setTimeout(() => {
this.getProductCenterListInScreenFun();
}, 300);
}
}, },
beforeDestroy() { beforeDestroy() {
if (this.requestTimeout) { if (this.requestTimeout) {

View File

@ -1,296 +1,337 @@
<template> <template>
<!-- 产品中心 --> <!-- 产品中心 -->
<div class="product-center"> <div class="product-center">
<div class="sidebar"> <div class="sidebar">
<div <div
:key="item.value" :key="item.value"
class="category-item" class="category-item"
v-for="item in leftMenuList" v-for="item in leftMenuList"
@click="activeTypeValue = item.value" @click="activeTypeValue = item.value"
:class="{ active: activeTypeValue == item.value }" :class="{ active: activeTypeValue == item.value }"
> >
{{ item.label }} {{ item.label }}
</div> </div>
</div> </div>
<div class="content-area" <div class="content-area"
:class="{ 'compact-grid': showProductList.length >= 5 && showProductList.length <= 8 }" :class="{ 'compact-grid': showProductList.length >= 5 && showProductList.length <= 8 }"
ref="servicesGrid"> ref="servicesGrid">
<div <div
:key="item.id" :key="item.id"
class="services-grid" class="services-grid"
v-for="item in showProductList" v-for="item in showProductList"
> >
<div class="card-image"> <div class="card-image">
<ImagePreview <ImagePreview
:height="150" :height="150"
:borderRadius="10" :borderRadius="10"
:width="itemWidth" :width="itemWidth"
:src1="item.linkImage" :src1="item.linkImage"
:isShowMask="true" :isShowMask="true"
/> />
</div> </div>
<div <div
class="card-title" class="card-title"
:style="{ width: itemWidth - 40 + 'px' }" :style="{ width: itemWidth - 40 + 'px' }"
> >
{{ item.name }} {{ item.name }}
</div> </div>
<div class="card-actions"> <div class="card-actions">
<div <div
class="primary-btn" class="primary-btn"
:class="{ :class="{
isDisabled: item.isAccess == 0, isDisabled: item.isAccess == 0,
}" }"
@click="handleDemo(item)" @click="handleDemo(item)"
> >
访问演示 访问演示
</div> </div>
<div @click="handleDetail(item)"> 查看详情 </div> <div @click="handleDetail(item)"> 查看详情 </div>
</div>
</div>
</div> </div>
</div>
</div> </div>
</div>
</template> </template>
<script> <script>
import { getProductCenterListAPI } from '@/api/publicService/productCenter' import { getProductCenterListAPI } from '@/api/publicService/productCenter'
export default { export default {
name: 'ProductCenter', name: 'ProductCenter',
dicts: ['tb_product_type'], dicts: ['tb_product_type'],
data() { props: {
return { searchKeyword: {
activeTypeValue: 'all', // type: String,
leftMenuList: [ default: ''
{ }
label: '全部', },
value: 'all', data() {
}, return {
], // activeTypeValue: 'all', //
productListAll: [], // leftMenuList: [
showProductList: [], // {
itemWidth: 0, // label: '全部',
} value: 'all',
},
], //
productListAll: [], //
showProductList: [], //
itemWidth: 0, //
}
},
created() {
this.getProductCenterListInScreenFun()
},
mounted() {
//
this.$on('dictReady', (dict) => {
this.initLeftMenuList()
})
//
if (this.dict && this.dict.type && this.dict.type.tb_product_type) {
this.initLeftMenuList()
}
this.getItemWidth()
},
methods: {
//
getItemWidth() {
this.itemWidth = (this.$refs.servicesGrid?.clientWidth - 120) / 4
}, },
created() { //
this.getProductCenterListInScreenFun() initLeftMenuList() {
}, try {
mounted() { if (
// this.dict &&
this.$on('dictReady', (dict) => { this.dict.type &&
this.initLeftMenuList() this.dict.type.tb_product_type
}) ) {
//
// this.dict.type.tb_product_type.forEach((item) => {
if (this.dict && this.dict.type && this.dict.type.tb_product_type) { this.leftMenuList.push({
this.initLeftMenuList() label: item.label,
} value: item.value,
this.getItemWidth()
},
methods: {
//
getItemWidth() {
this.itemWidth = (this.$refs.servicesGrid?.clientWidth - 120) / 4
},
//
initLeftMenuList() {
try {
if (
this.dict &&
this.dict.type &&
this.dict.type.tb_product_type
) {
//
this.dict.type.tb_product_type.forEach((item) => {
this.leftMenuList.push({
label: item.label,
value: item.value,
})
})
}
} catch (error) {}
},
// 访
handleDemo(service) {
if (service.isAccess == 0) {
this.$modal.msgWarning('该产品不支持访问')
return
}
// URL
let url = service.linkUrl
// URL http:// https:// https://
if (!url.startsWith('http://') && !url.startsWith('https://')) {
// URL www. https://
if (url.startsWith('www.')) {
url = 'https://' + url
} else {
// https://
url = 'https://' + url
}
}
window.open(url, '_blank')
},
//
handleDetail(service) {
this.$router.push({
name: 'ProductDetail',
params: { id: service.id },
}) })
}, })
// }
handleCardHover(serviceId) { } catch (error) {}
this.hoveredCard = serviceId },
}, // 访
// handleDemo(service) {
handleCardLeave() { if (service.isAccess == 0) {
this.hoveredCard = null this.$modal.msgWarning('该产品不支持访问')
}, return
}
// // URL
async getProductCenterListInScreenFun() { let url = service.linkUrl
const res = await getProductCenterListAPI({}) // URL http:// https:// https://
this.productListAll = res.data if (!url.startsWith('http://') && !url.startsWith('https://')) {
this.showProductList = this.productListAll // URL www. https://
}, if (url.startsWith('www.')) {
url = 'https://' + url
} else {
// https://
url = 'https://' + url
}
}
window.open(url, '_blank')
},
//
handleDetail(service) {
this.$router.push({
name: 'ProductDetail',
params: { id: service.id },
})
},
//
handleCardHover(serviceId) {
this.hoveredCard = serviceId
},
//
handleCardLeave() {
this.hoveredCard = null
}, },
// //
watch: { async getProductCenterListInScreenFun() {
activeTypeValue(newVal) { const res = await getProductCenterListAPI({})
if (newVal === 'all') { this.productListAll = res.data
this.showProductList = this.productListAll this.showProductList = this.productListAll
} else {
this.showProductList = this.productListAll.filter(
(item) => item.typeId === newVal,
)
}
},
}, },
//
filterProductsByKeyword(products, keyword) {
if (!keyword) return products
const lowerKeyword = keyword.toLowerCase()
return products.filter(item =>
//
(item.name && item.name.toLowerCase().includes(lowerKeyword)) ||
(item.description && item.description.toLowerCase().includes(lowerKeyword)) ||
(item.typeName && item.typeName.toLowerCase().includes(lowerKeyword))
)
}
},
//
watch: {
activeTypeValue(newVal) {
let filteredProducts = []
if (newVal === 'all') {
filteredProducts = this.productListAll
} else {
filteredProducts = this.productListAll.filter(
(item) => item.typeId === newVal,
)
}
//
this.showProductList = this.filterProductsByKeyword(filteredProducts, this.searchKeyword)
},
//
searchKeyword(newVal) {
let filteredProducts = []
//
if (this.activeTypeValue === 'all') {
filteredProducts = this.productListAll
} else {
filteredProducts = this.productListAll.filter(
(item) => item.typeId === this.activeTypeValue,
)
}
//
this.showProductList = this.filterProductsByKeyword(filteredProducts, newVal)
}
},
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.product-center { .product-center {
width: 100%; width: 100%;
height: 100%; /* 设置视口高度 */ height: 100%; /* 设置视口高度 */
display: flex; display: flex;
margin: 0 auto; margin: 0 auto;
padding: 40px 20px 0; padding: 40px 20px 0;
gap: 24px; gap: 24px;
box-sizing: border-box; /* 确保padding包含在高度内 */ box-sizing: border-box; /* 确保padding包含在高度内 */
/* 左侧分类菜单 */ /* 左侧分类菜单 */
.sidebar { .sidebar {
width: 160px; width: 160px;
flex-shrink: 0; flex-shrink: 0;
}
.content-area {
flex: 1;
height: 100%;
padding-bottom: 20px;
padding-right: 12px;
padding-top: 2px;
max-height: calc(100vh - 80px); /* 减去顶部padding */
overflow-y: auto;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 33px;
.services-grid {
height: 260px; /* 给子元素设置固定高度以便测试滚动 */
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
border: 1px solid #d6d1d1;
border-radius: 10px;
align-content: flex-start;
justify-items: center;
// background-color: skyblue;
} }
.content-area { .card-image {
flex: 1; height: 165px;
height: 100%; border-top-left-radius: 10px;
padding-bottom: 20px; border-top-right-radius: 10px;
padding-right: 12px; width: 100%;
padding-top: 2px; display: flex;
max-height: calc(100vh - 80px); /* 减去顶部padding */ align-items: center;
overflow-y: auto; justify-content: center;
display: grid; box-sizing: border-box;
grid-template-columns: repeat(4, 1fr); border-bottom: 1px solid #d6d1d1;
gap: 33px;
.services-grid {
height: 260px; /* 给子元素设置固定高度以便测试滚动 */
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
border: 1px solid #d6d1d1;
border-radius: 10px;
align-content: flex-start;
justify-items: center;
// background-color: skyblue;
}
.card-image {
height: 165px;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
border-bottom: 1px solid #d6d1d1;
}
.services-grid:hover {
transform: translateY(-2px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}
.card-title {
color: #333;
font-size: 16px;
padding: 8px 0;
font-weight: bold;
font-family: 'PingFang SC', sans-serif;
letter-spacing: 1px;
text-align: center;
//
white-space: nowrap; /* 禁止文本换行 */
overflow: hidden; /* 超出容器部分隐藏 */
text-overflow: ellipsis; /* 溢出部分用省略号表示 */
}
.card-actions {
flex: 1;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
div {
padding: 4px 6px;
border-radius: 4px;
color: #000;
font-size: 12px;
cursor: pointer;
font-family: 'PingFang SC', sans-serif;
transition: all 0.3s ease;
box-sizing: border-box;
}
& div:hover {
transform: translateY(-1px);
box-shadow: 0 6px 20px rgba(74, 144, 226, 0.35);
}
.primary-btn {
color: white;
background: linear-gradient(180deg, #00c7ef 0%, #005eef 100%);
}
& div:last-child {
border: 1px solid #00c7ef;
}
.isDisabled {
border-color: #ccc !important;
cursor: not-allowed !important;
background-color: #ccc !important;
}
}
} }
.services-grid:hover {
transform: translateY(-2px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}
.card-title {
color: #333;
font-size: 16px;
padding: 8px 0;
font-weight: bold;
font-family: 'PingFang SC', sans-serif;
letter-spacing: 1px;
text-align: center;
//
white-space: nowrap; /* 禁止文本换行 */
overflow: hidden; /* 超出容器部分隐藏 */
text-overflow: ellipsis; /* 溢出部分用省略号表示 */
}
.card-actions {
flex: 1;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
div {
padding: 4px 6px;
border-radius: 4px;
color: #000;
font-size: 12px;
cursor: pointer;
font-family: 'PingFang SC', sans-serif;
transition: all 0.3s ease;
box-sizing: border-box;
}
& div:hover {
transform: translateY(-1px);
box-shadow: 0 6px 20px rgba(74, 144, 226, 0.35);
}
.primary-btn {
color: white;
background: linear-gradient(180deg, #00c7ef 0%, #005eef 100%);
}
& div:last-child {
border: 1px solid #00c7ef;
}
.isDisabled {
border-color: #ccc !important;
cursor: not-allowed !important;
background-color: #ccc !important;
}
}
}
.compact-grid { .compact-grid {
flex: 1; flex: 1;
height: 75%; height: 75%;
@ -391,36 +432,34 @@ export default {
} }
} }
} }
} }
.category-item { .category-item {
padding: 12px 16px; padding: 12px 16px;
margin-bottom: 8px; margin-bottom: 8px;
background: white; background: white;
border-radius: 8px; border-radius: 8px;
cursor: pointer; cursor: pointer;
transition: all 0.2s ease; transition: all 0.2s ease;
font-size: 14px; font-size: 14px;
color: #000; color: #000;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
transition: all 0.2s ease; transition: all 0.2s ease;
font-family: 'PingFang SC', sans-serif; font-family: 'PingFang SC', sans-serif;
text-align: center; text-align: center;
} }
.category-item:hover { .category-item:hover {
background-color: #f0f7ff; background-color: #f0f7ff;
color: #4a90e2; color: #4a90e2;
transform: translateY(-2px); transform: translateY(-2px);
} }
.category-item.active { .category-item.active {
// background-color: #4a90e2; // background-color: #4a90e2;
background: url('../../../assets/images/publicService/btn-sel.png') background: url('../../../assets/images/publicService/btn-sel.png')
no-repeat center center; no-repeat center center;
background-size: 100% 100%; background-size: 100% 100%;
color: white; color: white;
} }
</style> </style>