diff --git a/pages/DigitalIntelligenceDashboard/index.vue b/pages/DigitalIntelligenceDashboard/index.vue index 440f047..be13fee 100644 --- a/pages/DigitalIntelligenceDashboard/index.vue +++ b/pages/DigitalIntelligenceDashboard/index.vue @@ -14,21 +14,36 @@ - - - - 快速导航 - - + + + + + + 快速 + 导航 + + + × + + + + + + {{ (item.name) }} + + + + + + + TOP + - - - {{ item.name }} - - + + + 导航 @@ -211,39 +226,45 @@ export default { // 各个Tab对应的导航栏数据 navData: { business: [ - { id: 'overview-of-serviceArea', name: '服务区概况' }, - { id: 'trading-alert', name: '交易预警' }, - { id: 'trend-of-trafficFlow', name: '断面流量' }, - { id: 'vehicles-entering', name: '入区车流' }, - { id: 'vehicle-model-stay', name: '经营效益' }, + { id: 'overview-of-serviceArea', name: '概况' },// 服务区概况 + { id: 'trading-alert', name: '预警' },// 交易预警 + { id: 'trend-of-trafficFlow', name: '断面' },// 断面流量 + { id: 'vehicles-entering', name: '入区' },// 入区车流 + { id: 'vehicle-model-stay', name: '效益' },// 经营效益 ], customerProfile: [ - { id: 'customer-age-group', name: '年龄画像' }, - { id: 'gender-customer-group', name: '性别画像' }, - { id: 'preference-type', name: '偏好类型' }, - { id: 'customer-group', name: '客群特征' }, - { id: 'customer-consumption-preferences', name: '消费偏好' }, - { id: 'consumption-conversion', name: '消费转化率' }, - { id: 'consumption-level', name: '消费水平' }, - { id: 'consumption-period', name: '消费时段' }, - { id: 'brand-consumption-level', name: '品牌消费' }, + { id: 'customer-age-group', name: '年龄' },// 年龄画像 + { id: 'gender-customer-group', name: '性别' },// 性别画像 + { id: 'preference-type', name: '偏好' },// 偏好类型 + { id: 'customer-group', name: '特征' },// 客群特征 + { id: 'customer-consumption-preferences', name: '消费' },// 消费偏好 + { id: 'consumption-conversion', name: '转化率' },// 消费转化率 + { id: 'consumption-level', name: '水平' },// 消费水平 + { id: 'consumption-period', name: '时段' },// 消费时段 + { id: 'brand-consumption-level', name: '品牌' },// 品牌消费 ], businessRevenue: [ - { id: 'business-case', name: '营收特征' }, - { id: 'regional-revenue', name: '区域营收' }, - { id: 'business-structure', name: '业态结构' }, - { id: 'festival-revenue-sum-info', name: '节假日营收' }, + { id: 'business-case', name: '营收' },// 营收特征 + { id: 'regional-revenue', name: '区域' },// 区域营收 + { id: 'business-structure', name: '业态' },// 业态结构 + { id: 'festival-revenue-sum-info', name: '节假日' },// 节假日营收 ], mallOperation: [ - { id: 'member-mall', name: '会员商城' }, - { id: 'hot-product-list', name: '商品榜单' }, - { id: 'brand-detail', name: '商户类别' }, - { id: 'supplier-list-box', name: '供应商列表' }, - { id: 'mall-order-statistics', name: '商城订单统计' }, - { id: 'this-month-benefits', name: '福利金额度' }, - { id: 'analysis-of-member', name: '会员消费' }, + { id: 'member-mall', name: '商城' },// 会员商城 + { id: 'hot-product-list', name: '榜单' },// 商品榜单 + { id: 'brand-detail', name: '类别' },// 商户类别 + { id: 'supplier-list-box', name: '供应商' },// 供应商列表 + { id: 'mall-order-statistics', name: '订单' },// 商城订单统计 + { id: 'this-month-benefits', name: '福利金' },// 福利金额度 + { id: 'analysis-of-member', name: '会员' },// 会员消费 ] }, + navColorMap: { + business: '#6F86FF', + customerProfile: '#FF8F6F', + businessRevenue: '#38C9A4', + mallOperation: '#F1C84C' + }, // 当前活动的导航项 activeNavItem: '', // 导航栏是否收缩 @@ -266,6 +287,13 @@ export default { currentNavItems() { const currentTabKey = this.tabList[this.activeTab].key; return this.navData[currentTabKey] || []; + }, + currentTabKey() { + const current = this.tabList[this.activeTab]; + return current ? current.key : ''; + }, + navAccentColor() { + return this.navColorMap[this.currentTabKey] || '#6F86FF'; } }, onLoad() { @@ -325,6 +353,21 @@ export default { }, + scrollToTop() { + const tabKey = this.currentTabKey; + if (!tabKey) { + return; + } + this.scrollIntoViewMap[tabKey] = ''; + this.$nextTick(() => { + this.scrollIntoViewMap[tabKey] = `top-${tabKey}`; + }); + const navItems = this.navData[tabKey] || []; + if (navItems.length > 0) { + this.activeNavItem = navItems[0].id; + } + }, + resetScrollPosition(tabKey) { this.scrollIntoViewMap[tabKey] = `top-${tabKey}`; }, @@ -361,6 +404,19 @@ export default { if (navItems.length > 0) { this.activeNavItem = navItems[0].id; } + }, + + formatNavName(name = '') { + const trimmed = name.trim(); + return trimmed.length > 6 ? `${trimmed.slice(0, 6)}...` : trimmed; + }, + + getNavShortName(name = '') { + const trimmed = name.trim(); + if (trimmed.length <= 2) { + return trimmed || '--'; + } + return trimmed.slice(0, 2); } } } @@ -600,141 +656,221 @@ export default { .side-navigation { position: fixed; - right: 24rpx; + right: 12rpx; top: 50%; transform: translateY(-50%); z-index: 1000; - background: rgba(255, 255, 255, 0.95); - backdrop-filter: blur(10px); - border-radius: 16rpx; - box-shadow: @shadow; - border: 1rpx solid rgba(255, 255, 255, 0.2); - max-height: 70vh; - overflow-y: auto; transition: all 0.3s ease; - &::-webkit-scrollbar { - width: 4rpx; + .nav-rail { + width: 70rpx; + max-height: 70vh; + padding: 12rpx 10rpx; + border-radius: 999rpx; + background: rgba(8, 16, 40, 0.78); + backdrop-filter: blur(18rpx); + border: 1rpx solid rgba(255, 255, 255, 0.12); + display: flex; + flex-direction: column; + align-items: center; + box-shadow: 0 20rpx 48rpx rgba(6, 6, 34, 0.55); + overflow: hidden; + transform-origin: center; + transition: width 0.7s cubic-bezier(0.33, 1, 0.68, 1), height 0.7s cubic-bezier(0.33, 1, 0.68, 1), + padding 0.7s cubic-bezier(0.33, 1, 0.68, 1), border-radius 0.7s ease, box-shadow 0.7s ease, + transform 0.7s cubic-bezier(0.33, 1, 0.68, 1); + position: relative; } - &::-webkit-scrollbar-track { - background: rgba(0, 0, 0, 0.1); - border-radius: 2rpx; + .rail-body { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.33, 1, 0.68, 1); } - &::-webkit-scrollbar-thumb { - background: @primary-color; - border-radius: 2rpx; + .rail-body.hidden { + opacity: 0; + transform: translateY(12rpx) scale(0.9); + pointer-events: none; } - // 收缩状态 - &.collapsed { - min-width: auto; - max-width: auto; + .rail-header, + .rail-footer { + width: 100%; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + gap: 10rpx; + } - .nav-container { - padding: 0; + .rail-title { + color: #fff; + font-size: 20rpx; + line-height: 1.4; + opacity: 0.85; + text-align: center; + } + + .rail-toggle { + width: 56rpx; + height: 56rpx; + border-radius: 50%; + border: 1rpx solid rgba(255, 255, 255, 0.2); + display: flex; + align-items: center; + justify-content: center; + color: #fff; + background: rgba(255, 255, 255, 0.08); + } + + .toggle-icon { + font-size: 24rpx; + transition: transform 0.3s ease; + + &.rotated { + transform: rotate(180deg); } } - .nav-container { - padding: 0 16rpx; + .rail-track { + width: 100%; + flex: 1; + margin: 16rpx 0; + } - .nav-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 16rpx; - border-bottom: 1rpx solid #f0f0f0; - margin-bottom: 8rpx; - cursor: pointer; + .rail-track::-webkit-scrollbar { + width: 0; + height: 0; + } - .nav-title { - font-size: 24rpx; - font-weight: 600; - color: @text-primary; - } + .rail-item { + width: 100%; + display: flex; + justify-content: center; + padding: 8rpx 0; + cursor: pointer; + transition: transform 0.2s ease; - .nav-toggle { - .toggle-icon { - font-size: 20rpx; - color: @text-secondary; - transition: transform 0.3s ease; - - &.rotated { - transform: rotate(180deg); - } - } - } - - &:hover { - background: rgba(102, 126, 234, 0.05); - border-radius: 8rpx; - } + &:active { + transform: translateX(-3rpx); } - .nav-list { - .nav-item { - position: relative; - padding: 16rpx 20rpx; - margin-bottom: 8rpx; - border-radius: 12rpx; - cursor: pointer; - transition: all 0.3s ease; - display: flex; - align-items: center; - justify-content: space-between; + &.active .rail-dot::after { + opacity: 1; + } - &:hover { - background: rgba(102, 126, 234, 0.1); - transform: translateX(-4rpx); - } - - &.active { - background: linear-gradient(90deg, rgba(102, 126, 234, 0.15), rgba(118, 75, 162, 0.15)); - border-left: 4rpx solid @primary-color; - padding-left: 16rpx; - - .nav-text { - color: @primary-color; - font-weight: 600; - } - } - - .nav-text { - font-size: 22rpx; - color: @text-secondary; - line-height: 1.4; - flex: 1; - transition: all 0.3s ease; - } - - .nav-dot { - width: 8rpx; - height: 8rpx; - background: @primary-color; - border-radius: 50%; - animation: pulse 2s infinite; - } - } + &.active .rail-dot-text { + color: #fff; } } -} -@keyframes pulse { - 0% { + .rail-dot { + width: 60rpx; + height: 60rpx; + border-radius: 50%; + position: relative; + display: flex; + align-items: center; + justify-content: center; + background: rgba(255, 255, 255, 0.06); + border: 1rpx solid rgba(255, 255, 255, 0.2); + box-shadow: inset 0 0 12rpx rgba(255, 255, 255, 0.08); + + &::before { + content: ''; + position: absolute; + inset: 4rpx; + border-radius: 50%; + border: 1rpx solid rgba(255, 255, 255, 0.2); + } + + &::after { + content: ''; + position: absolute; + inset: 0; + border-radius: 50%; + background: linear-gradient(160deg, rgba(255, 255, 255, 0.18), rgba(0, 0, 0, 0.25)); + opacity: 0; + transition: opacity 0.3s ease; + z-index: 0; + } + } + + .rail-dot-text { + position: relative; + z-index: 1; + font-size: 20rpx; + letter-spacing: 1rpx; + color: rgba(255, 255, 255, 0.85); + font-weight: 400; + white-space: nowrap; + } + + .rail-footer { + padding-top: 8rpx; + } + + .rail-back { + width: 72rpx; + height: 72rpx; + border-radius: 50%; + border: 1rpx solid rgba(255, 255, 255, 0.25); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + color: #fff; + font-size: 20rpx; + gap: 4rpx; + background: rgba(255, 255, 255, 0.08); + line-height: 1.3; + } + + .nav-rail.compact { + width: 86rpx; + height: 86rpx; + padding: 0; + border-radius: 50%; + justify-content: center; + border-color: rgba(255, 255, 255, 0.2); + box-shadow: 0 14rpx 30rpx rgba(6, 6, 34, 0.4); + transform: translateY(0) scale(0.96); + } + + .rail-compact { + position: absolute; + inset: 0; + border-radius: 50%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + color: #fff; + gap: 4rpx; + cursor: pointer; + opacity: 0; + transform: scale(0.8); + pointer-events: none; + transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.33, 1, 0.68, 1); + } + + .rail-compact.visible { opacity: 1; transform: scale(1); + pointer-events: auto; } - 50% { - opacity: 0.6; - transform: scale(1.2); + .compact-icon { + font-size: 28rpx; + line-height: 1; } - 100% { - opacity: 1; - transform: scale(1); + .compact-text { + font-size: 18rpx; + letter-spacing: 2rpx; } }