feat(mhzc-footer): 页脚按Figma精确还原 & 邮箱/友链文本去除hover

- 重构首页底部信息块为 Figma 150904:8642 精确对照版
- 邮箱、上海浦江数链数字科技有限公司改为普通文本(不可点击)
- hover 变绿效果仅作用于真实链接 a.footer-text
- main.vue 统一渲染 footer,各页面移除重复 Footer 组件
- home2 缩放容器不再包裹 footer,修复首页页脚宽度与样式问题

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
liulong 2026-06-08 23:28:05 +08:00
parent ec74735f94
commit 1beb24053f
15 changed files with 652 additions and 1051 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

View File

@ -1,89 +1,99 @@
<template> <template>
<!--
首页底部信息块完全对照 Figma 150897:8486 · 审核版本
节点150904:8642底部信息块
Group 29 (1440×144, #F0F7F2)
底部信息 (row · space-between · align center · padding 40 20)
Frame 235 (1200)
Frame 213 (column · gap 10)
Frame 208 (row) 标题"联系" 1px 底边 + "我们"
Frame 209 (row · gap 32) 邮箱 + 地址
Frame 212 (column · gap 16)
Frame 208 标题"友情" 1px 底边 + "链接"
Frame 209 (row · gap 32) 两个友链
版权 (1440×80, #E2EDE5)
Frame 219 (row · center · gap 20)
Frame 221 (1200 · column · center · gap 8 · padding 16 0)
Frame 210 指导单位行
Frame 1898 (row · gap 20) 版权行
-->
<div class="portal-footer-shell"> <div class="portal-footer-shell">
<footer class="site-footer"> <footer class="site-footer">
<!-- 上区底部信息1440×144 · #F0F7F2 -->
<div class="footer-main"> <div class="footer-main">
<div class="footer-main-inner"> <div class="footer-main-inner">
<div class="footer-columns">
<!-- 1品牌列与页头同款 logo + 名称 + 邮箱 + 地址 --> <!-- Frame 2351200 · row · space-between -->
<div class="footer-column footer-column--brand footer-column--divider-right"> <div class="footer-frame">
<div class="footer-brand-head">
<span class="footer-brand-logo" aria-hidden="true"> <!-- Frame 213联系我们列column · gap 10 -->
<img class="footer-brand-icon" :src="logoIconSrc" alt="可信碳信息网" /> <div class="footer-col footer-col--contact">
</span> <!-- Frame 208标题行 "联系"( 1px 下边框) + "我们" -->
<span class="footer-brand-name">可信碳信息网</span> <div class="footer-title-row">
<span class="footer-title-with-underline">联系</span>
<span class="footer-title">我们</span>
</div> </div>
<ul class="footer-contact-list"> <!-- Frame 209邮箱 + 地址row · gap 32 -->
<li class="footer-contact-row"> <div class="footer-contact-row">
<span class="footer-contact-icon footer-contact-icon--solid" aria-hidden="true"> <span class="footer-contact-item">
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <span class="footer-icon" aria-hidden="true">
<rect x="1.5" y="3.5" width="13" height="9" rx="1.2" fill="#0a7a4a"/> <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.5 4.5L8 8.8 13.5 4.5" stroke="#ffffff" stroke-width="1.2" stroke-linejoin="round" fill="none"/> <path d="M2 3.5C2 2.94772 2.44772 2.5 3 2.5H11C11.5523 2.5 12 2.94772 12 3.5V10.5C12 11.0523 11.5523 11.5 11 11.5H3C2.44772 11.5 2 11.0523 2 10.5V3.5Z" stroke="currentColor" stroke-width="1" stroke-linejoin="round"/>
<path d="M2.5 3.8L7 7.2L11.5 3.8" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"/>
</svg> </svg>
</span> </span>
<a class="footer-contact-text" :href="`mailto:${contact.email}`">{{ contact.email }}</a> <span class="footer-text">{{ contact.email }}</span>
</li> </span>
<li class="footer-contact-row"> <span class="footer-contact-item">
<span class="footer-contact-icon footer-contact-icon--solid" aria-hidden="true"> <span class="footer-icon" aria-hidden="true">
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 1.5c-3 0-5.5 2.4-5.5 5.4 0 4 5.5 8 5.5 8s5.5-4 5.5-8c0-3-2.5-5.4-5.5-5.4z" fill="#0a7a4a"/> <path d="M6 1.5C4.34315 1.5 3 2.84315 3 4.5C3 6.8 6 10.5 6 10.5C6 10.5 9 6.8 9 4.5C9 2.84315 7.65685 1.5 6 1.5Z" stroke="currentColor" stroke-width="1" stroke-linejoin="round"/>
<circle cx="8" cy="6.9" r="1.8" fill="#ffffff"/> <circle cx="6" cy="4.5" r="1.2" stroke="currentColor" stroke-width="1"/>
</svg> </svg>
</span> </span>
<span class="footer-contact-text">{{ contact.address }}</span> <span class="footer-text">{{ contact.address }}</span>
</li> </span>
</ul> </div>
</div> </div>
<!-- 2指导单位 --> <!-- Frame 212友情链接列column · gap 16 -->
<div class="footer-column footer-column--guide"> <div class="footer-col footer-col--links">
<h3 class="footer-title">指导单位</h3> <!-- 标题行 "友情"( 1px 下边框) + "链接" -->
<ul class="footer-list"> <div class="footer-title-row">
<li class="footer-text">上海市数据局</li> <span class="footer-title-with-underline">友情</span>
<li class="footer-text">宝山区政府</li> <span class="footer-title">链接</span>
</ul> </div>
<!-- Frame 209两个友链row · gap 32 -->
<div class="footer-links-row">
<a class="footer-text" href="https://segg.sh.gov.cn/" target="_blank" rel="noopener noreferrer">上海市企业走出去综合服务平台</a>
<span class="footer-text">上海浦江数链数字科技有限公司</span>
</div>
</div> </div>
<!-- 3运营单位 -->
<div class="footer-column footer-column--ops">
<h3 class="footer-title">运营单位</h3>
<ul class="footer-list">
<li class="footer-text">上海浦江数链数字科技有限公司</li>
</ul>
</div>
<!-- 4业务支持 -->
<div class="footer-column footer-column--support">
<h3 class="footer-title">业务支持</h3>
<ul class="footer-list">
<li class="footer-text">上海数字基础设施协会可信碳专委会</li>
</ul>
</div>
<!-- 5友情链接 -->
<div class="footer-column footer-column--links">
<h3 class="footer-title">友情链接</h3>
<ul class="footer-list">
<li>
<a
class="footer-link"
href="https://segg.sh.gov.cn/"
target="_blank"
rel="noopener noreferrer"
>上海市企业走出去综合服务平台</a>
</li>
</ul>
</div>
</div> </div>
</div> </div>
</div> </div>
<!-- 下区版权1440×80 · #E2EDE5 -->
<div class="footer-bar"> <div class="footer-bar">
<div class="footer-bar-inner"> <div class="footer-bar-inner">
<p class="footer-bar-line">© 2025 可信碳信息网 版权所有</p> <!-- Frame 210 · 指导单位行 -->
<p class="footer-bar-line">技术支持上海市宝山区大数据中心</p> <div class="footer-guide">
<p class="footer-bar-line">基础设施国家区块链网络基础底座</p> <span class="footer-guide-label">指导单位</span>
<span class="footer-guide-item">上海市数据局</span>
<span class="footer-guide-gap"></span>
<span class="footer-guide-item">宝山区政府</span>
</div>
<!-- Frame 1898 · 版权行 · gap 20 -->
<div class="footer-copyright">
<span class="footer-bar-line">©2025可信碳信息网版权所有</span>
<span class="footer-bar-line">技术支持上海市宝山区大数据中心</span>
<span class="footer-bar-line">基础设施国家区块链网络基础底座</span>
</div>
</div> </div>
</div> </div>
</footer> </footer>
</div> </div>
</template> </template>
@ -93,12 +103,6 @@ import { mapState } from 'vuex';
export default { export default {
name: 'Footer', name: 'Footer',
data() {
return {
// nav logo
logoIconSrc: require('../../assets/logo-figma-icon.png'),
};
},
computed: { computed: {
...mapState('settings', ['contact']), ...mapState('settings', ['contact']),
}, },
@ -107,25 +111,24 @@ export default {
<style lang="less" scoped> <style lang="less" scoped>
/* ============================================================================= /* =============================================================================
* 门户统一页脚完全按 Figma 页脚设计稿 · 品牌列 + 4 标题列 * 首页底部信息块Figma 150904:8642 · 审核版本精确对照
* 画布1440 · 版心 1200 · 5 · 主区 #f0f7f2 · 底栏 #e8f0ea * Group 291440 × 144 · #F0F7F2
* 1品牌logo 圆形 + 名称 + 邮箱 + 地址实心绿底白图标 * 版权块 1440 × 80 · #E2EDE5
* 2-5标题 + 文字列表标题 16px #003b1a + 左侧 4px 绿渐变竖条
* ============================================================================= */ * ============================================================================= */
.portal-footer-shell { .portal-footer-shell {
flex-shrink: 0; flex-shrink: 0;
width: 100%; width: 100%;
background: var(--page-footer-bg, #f0f7f2); background: #f0f7f2;
} }
/* 首页 footer 反向缩放规则已挪到 home2/index.vue 的 scoped 样式中(避免误命中内页 footer */
.site-footer { .site-footer {
display: block; display: block;
font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif; font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
} }
/* ── 上区:底部信息 ───────────────────────────── 1440×144 · #F0F7F2 ── */
.footer-main { .footer-main {
background: #f0f7f2; background: #f0f7f2;
} }
@ -133,189 +136,113 @@ export default {
.footer-main-inner { .footer-main-inner {
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
max-width: var(--page-content-max-width, 1200px); max-width: 1200px;
margin: 0 auto; margin: 0 auto;
padding: 40px 20px 20px; padding: 40px 20px; /* Figma 底部信息 padding */
} }
.footer-columns { .footer-frame {
display: flex; display: flex;
align-items: flex-start; align-items: center; /* Figma 底部信息 align-items: center */
justify-content: flex-start; justify-content: space-between; /* Figma Frame 235 justify-content: space-between */
width: 100%;
gap: 32px;
box-sizing: border-box; box-sizing: border-box;
width: 100%;
} }
.footer-column { /* ── 列通用样式 ── */
.footer-col {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: center; /* 列内内容居中 */
min-width: 0;
} }
/* 5 列宽Figma 比例 312 / 84 / 196 / 224 / 196去掉原联系我们列 → 由品牌列承担) */ /* Frame 213联系我们列 · column · gap 10 */
.footer-column--brand { flex: 0 0 312px; left: -41px;} .footer-col--contact {
.footer-column--guide { flex: 0 0 130px; } flex: 0 1 auto;
.footer-column--ops { flex: 0 0 196px; } row-gap: 10px;
.footer-column--support { flex: 0 0 224px; }
.footer-column--links { flex: 0 0 268px; }
/* Figma 设计:品牌列(可信碳信息网)右侧 1 道浅绿竖向分隔线(贯穿列高) */
.footer-column--divider-right {
position: relative;
&::after {
position: absolute;
top: 4px;
right: -16px;
bottom: 4px;
width: 1px;
background: rgba(0, 154, 41, 0.18);
content: '';
}
} }
/* 列 1品牌列 */ /* Frame 212友情链接列 · column · gap 16 */
.footer-brand-head { .footer-col--links {
flex: 0 1 auto;
row-gap: 10px;
}
/* ── 标题行Frame 208 ─ row ────────────────────── h:28 ── */
.footer-title-row {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px;
margin: 0 0 12px;
height: 22px;
font-size: 16px;
font-weight: 600;
line-height: 22px;
color: #003b1a;
}
.footer-brand-logo {
display: inline-flex;
align-items: center;
justify-content: center; justify-content: center;
width: 24px; padding: 0 0 6px; /* Figma Frame 1900 padding 0 0 6px */
height: 24px; font-size: 16px;
flex-shrink: 0; line-height: 22px;
padding: 1px; color: #000000;
background: #ffffff; margin-left: -10px;
border-radius: 100px;
box-sizing: border-box;
} }
.footer-brand-icon { .footer-title-with-underline {
display: block; font-weight: 600;
width: 22px; border-bottom: 1px solid #000000;
height: 22px; padding-bottom: 0;
border-radius: 50%; line-height: 22px;
} }
.footer-brand-name { .footer-title {
white-space: nowrap; font-weight: 600;
line-height: 22px;
} }
.footer-contact-list { /* ── Frame 209内容行 ────────────────────────────── h:14/20 ── */
display: flex;
flex-direction: column;
gap: 12px;
margin: 0;
padding: 0;
list-style: none;
}
/* 联系我们:邮箱 + 地址 · row · gap 32 */
.footer-contact-row { .footer-contact-row {
display: flex; display: flex;
align-items: flex-start;
gap: 8px;
text-align: left;
}
.footer-contact-icon {
display: inline-flex;
flex-shrink: 0;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 14px; column-gap: 32px;
min-height: 22px; font-size: 0;
color: #556659;
} }
.footer-contact-icon--solid { .footer-contact-item {
width: 16px; display: inline-flex;
height: 16px; align-items: center;
border-radius: 3px; column-gap: 4px;
margin-top: 3px;
overflow: hidden;
color: #ffffff;
svg {
display: block;
}
} }
.footer-contact-text { .footer-icon {
flex: 1 1 auto; display: inline-flex;
min-width: 0; align-items: center;
font-size: 14px; justify-content: center;
line-height: 22px; flex-shrink: 0;
color: #556659; color: #555555;
text-decoration: none; line-height: 0;
word-break: break-all;
transition: color 0.2s ease;
&:hover {
color: #00b96b;
}
} }
a.footer-contact-text { /* 友情链接:两个链接 · row · gap 32 */
cursor: pointer; .footer-links-row {
}
/* 列 2-5标题 + 列表 */
.footer-title {
position: relative;
margin: 0 0 12px;
padding-left: 12px;
font-size: 16px;
font-weight: 600;
line-height: 22px;
color: #003b1a;
white-space: nowrap;
&::before {
position: absolute;
top: 50%;
left: 0;
width: 4px;
height: 16px;
border-radius: 2px;
background: linear-gradient(180deg, #4caf50 0%, #2e7d32 100%);
content: '';
transform: translateY(-50%);
}
}
.footer-list {
display: flex; display: flex;
flex-direction: column; align-items: center;
gap: 8px; justify-content: center;
margin: 0; column-gap: 32px;
padding: 0; font-size: 0;
list-style: none;
} }
.footer-text, /* ── 文字通用样式 ── */
.footer-link {
.footer-text {
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
line-height: 22px; line-height: 20px;
color: #556659; color: #555555;
text-decoration: none;
white-space: nowrap;
vertical-align: middle;
} }
.footer-link { a.footer-text {
display: inline-block; cursor: pointer;
text-decoration: none;
word-break: break-all;
transition: color 0.2s ease; transition: color 0.2s ease;
&:hover { &:hover {
@ -323,77 +250,111 @@ a.footer-contact-text {
} }
} }
/* 版权底栏 */ /* ── 下区:版权 ────────────────────────────────── 1440×80 · #E2EDE5 ── */
.footer-bar { .footer-bar {
background: #e8f0ea; background: #e2ede5;
} }
.footer-bar-inner { .footer-bar-inner {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 10px 20px;
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
min-height: 64px; max-width: 1200px;
padding: 10px 20px; margin: 0 auto;
padding: 16px 0; /* Figma Frame 221 padding 16 0 */
display: flex;
flex-direction: column;
align-items: center;
row-gap: 8px; /* Figma gap 8 */
} }
.footer-bar-line { /* 指导单位行 · Frame 210 */
margin: 0; .footer-guide {
font-size: 12px; display: flex;
font-weight: 400; align-items: center;
justify-content: center;
font-size: 14px;
line-height: 20px; line-height: 20px;
color: #556659; color: #555555;
}
.footer-guide-label,
.footer-guide-item {
font-weight: 400;
}
.footer-guide-gap {
display: inline-block;
width: 10px;
flex-shrink: 0;
}
/* 版权行 · Frame 1898 · gap 20 */
.footer-copyright {
display: flex;
align-items: center;
justify-content: center;
column-gap: 20px; /* Figma gap 20 */
white-space: nowrap; white-space: nowrap;
} }
.footer-bar-line {
font-size: 14px; /* Figma style_ERXFUQ 14px */
font-weight: 400;
line-height: 20px;
color: #555555;
}
/* ── 响应式 ────────────────────────────────────────── */
@media screen and (max-width: 1279px) { @media screen and (max-width: 1279px) {
.footer-columns { .footer-frame {
flex-wrap: wrap; flex-direction: column;
row-gap: 28px; row-gap: 28px;
} }
.footer-column--brand, .footer-col--contact,
.footer-column--guide, .footer-col--links {
.footer-column--ops, width: 100%;
.footer-column--support,
.footer-column--links {
flex: 1 1 calc(50% - 16px);
min-width: 220px;
}
/* 响应式下不显示竖向分隔线 */
.footer-column--divider-right::after {
display: none;
} }
} }
@media screen and (max-width: 767px) { @media screen and (max-width: 767px) {
.footer-main-inner { .footer-main-inner {
padding: 32px 16px 20px; padding: 32px 16px;
} }
.footer-columns { .footer-frame {
flex-direction: column;
row-gap: 24px; row-gap: 24px;
} }
.footer-column--brand, .footer-contact-row {
.footer-column--guide, flex-direction: column;
.footer-column--ops, align-items: flex-start;
.footer-column--support, row-gap: 8px;
.footer-column--links { }
flex: none;
width: 100%; .footer-links-row {
flex-direction: column;
align-items: center;
row-gap: 8px;
} }
.footer-bar-inner { .footer-bar-inner {
padding: 12px 0;
}
.footer-guide {
flex-wrap: wrap;
}
.footer-guide-gap {
display: none;
}
.footer-copyright {
flex-direction: column; flex-direction: column;
gap: 4px; row-gap: 4px;
min-height: auto;
padding: 12px 16px;
} }
.footer-bar-line { .footer-bar-line {

View File

@ -1,7 +1,5 @@
<template> <template>
<div class="fwsc-page portal-page-shell portal-landing-figma-page"> <div class="fwsc-page">
<div class="portal-figma-scale-viewport">
<div class="portal-figma-scale-stage" ref="figmaStage">
<div class="main-content"> <div class="main-content">
<!-- 当前位置导航 --> <!-- 当前位置导航 -->
<!-- <div class="breadcrumb-box"> <!-- <div class="breadcrumb-box">
@ -14,7 +12,7 @@
<!-- Banner --> <!-- Banner -->
<div class="banner-section"> <div class="banner-section">
<div class="banner-content"> <div class="banner-content">
<h1 class="banner-title">服务中心</h1> <h1 class="banner-title">可信碳服务中心</h1>
<!-- <img src="@/pages/index/assets/home-top-title.png"> --> <!-- <img src="@/pages/index/assets/home-top-title.png"> -->
<p class="banner-subtitle">链接全球碳资产赋能绿色价值链一站式解决碳服务撮合绿色交易与金融对接需求</p> <p class="banner-subtitle">链接全球碳资产赋能绿色价值链一站式解决碳服务撮合绿色交易与金融对接需求</p>
</div> </div>
@ -90,19 +88,18 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
</div> </div>
</template> </template>
<script> <script>
import portalFigmaScaleMixin from '@/pages/index/utils/portal-figma-scale-mixin'; import NewNav from '@/pages/index/components/new-nav/index.vue';
import comingSoonMixin from '@/pages/index/utils/coming-soon-mixin';
export default { export default {
name: 'FwscIndex', name: 'FwscIndex',
mixins: [portalFigmaScaleMixin, comingSoonMixin], components: {
NewNav,
},
methods: { methods: {
goHome() { goHome() {
this.$router.push('/view/mhzc/home'); this.$router.push('/view/mhzc/home');
@ -111,7 +108,7 @@ export default {
if (path) { if (path) {
this.$router.push(path); this.$router.push(path);
} else { } else {
this.showComingSoon(); this.$message.info('敬请期待');
} }
} }
} }
@ -119,31 +116,57 @@ export default {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '../../styles/home-figma-variables.less';
@import '../../styles/portal-landing-cards.less';
.fwsc-page { .fwsc-page {
background: #F6F7FA; min-height: 100vh;
.portal-figma-scale-page(); background: #f5f7fa;
} }
/* gxnlpt portal-figma-scale-page() mounted nextTick .main-content {
时拿到的 stage 高度偏小卡片/v-for 还没装填导致
--home-figma-visual-height 被算小整页被 clamp 裁切
表现就是切换到 /fwsc 时只看到一片背景内容没渲染出来
这里直接重写 .fwsc-page 的高度为 auto不依赖 visualHeight */
html.portal-figma-scale-active.portal-landing-figma-scale-active .fwsc-page,
html.portal-figma-scale-active .fwsc-page {
height: auto !important;
max-height: none !important;
overflow: visible !important;
} }
// Banner 350px //
.breadcrumb-box {
display: flex;
align-items: center;
height: 48px;
padding: 0 var(--page-gutter-x);
background: #fff;
border-bottom: 1px solid #eee;
}
.breadcrumb-text {
font-size: 14px;
color: #666;
}
.breadcrumb-link {
font-size: 14px;
color: #009a29;
cursor: pointer;
transition: color 0.3s;
}
.breadcrumb-link:hover {
color: #007a1f;
}
.breadcrumb-separator {
margin: 0 8px;
font-size: 14px;
color: #999;
}
.breadcrumb-current {
font-size: 14px;
color: #333;
}
// Banner -
.banner-section { .banner-section {
position: relative; position: relative;
z-index: 1;
display: flex; display: flex;
height: @portal-landing-banner-height; // height: 400px;
height: 350px;
background: linear-gradient(135deg, #003B1A 0%, #009a29 40%, #00d87d 100%); background: linear-gradient(135deg, #003B1A 0%, #009a29 40%, #00d87d 100%);
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@ -152,18 +175,22 @@ html.portal-figma-scale-active .fwsc-page {
&::before { &::before {
content: ''; content: '';
position: absolute; position: absolute;
inset: 0; top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('~@/pages/index/assets/home-top-bg1.jpg') center/cover no-repeat; background: url('~@/pages/index/assets/home-top-bg1.jpg') center/cover no-repeat;
// opacity: 0.15;
} }
&::after { &::after {
content: ''; content: '';
position: absolute; position: absolute;
right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
height: @portal-landing-cards-overlap; right: 0;
background: linear-gradient(180deg, transparent, rgba(245, 247, 250, 0.85)); height: 120px;
background: linear-gradient(180deg, transparent, rgba(245, 247, 250, 0.8));
} }
} }
@ -195,12 +222,11 @@ html.portal-figma-scale-active .fwsc-page {
text-shadow: 0 0 1px #ffffff, 0 0 3px #ffffff, 0 0 6px #ffffff, 0 0 10px #ffffff; text-shadow: 0 0 1px #ffffff, 0 0 3px #ffffff, 0 0 6px #ffffff, 0 0 10px #ffffff;
} }
// margin Banner //
.services-section { .services-section {
padding: 60px 0 80px;
position: relative; position: relative;
z-index: 2; margin-top: -120px;
.portal-landing-card-shell();
} }
.section-header { .section-header {
@ -238,15 +264,14 @@ html.portal-figma-scale-active .fwsc-page {
.services-grid { .services-grid {
display: grid; display: grid;
width: 100%; width: 100%;
grid-template-columns: repeat(var(--portal-services-fwsc-cols, 4), minmax(0, 1fr)); grid-template-columns: repeat(4, minmax(0, 1fr));
gap: var(--portal-services-grid-gap, 24px); gap: var(--portal-services-grid-gap, 24px);
max-width: var(--portal-services-grid-max, var(--page-content-max-width, 1200px)); max-width: var(--portal-services-grid-max, 1300px);
margin: 0 auto; margin: 0 auto;
box-sizing: border-box;
align-items: stretch;
} }
.service-card { .service-card {
min-height: var(--portal-service-card-min-height, 268px);
cursor: pointer; cursor: pointer;
border-radius: 16px; border-radius: 16px;
overflow: hidden; overflow: hidden;
@ -261,10 +286,22 @@ html.portal-figma-scale-active .fwsc-page {
} }
} }
.service-card-inner {
display: flex;
flex-direction: column;
height: 100%;
min-height: var(--portal-service-card-min-height, 268px);
padding: 28px;
box-sizing: border-box;
}
.service-card-header { .service-card-header {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 16px; gap: 16px;
padding-bottom: 20px;
margin-bottom: 20px;
border-bottom: 1px solid #f0f0f0;
} }
.service-card-num { .service-card-num {
@ -276,18 +313,17 @@ html.portal-figma-scale-active .fwsc-page {
.service-card-title { .service-card-title {
font-size: 22px; font-size: 22px;
font-weight: 600; font-weight: 600;
line-height: 1.35;
color: #1a1a1a; color: #1a1a1a;
margin: 0; margin: 0;
} }
.service-card-desc { .service-card-desc {
position: relative;
z-index: 1;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
line-height: 1.8; line-height: 1.8;
color: #666; color: #666;
flex-grow: 1;
margin-bottom: 24px;
} }
.service-card-buttons { .service-card-buttons {
@ -297,7 +333,6 @@ html.portal-figma-scale-active .fwsc-page {
.t-button { .t-button {
width: 100%; width: 100%;
height: @hyzt-landing-card-btn-h;
} }
} }
@ -322,9 +357,31 @@ html.portal-figma-scale-active .fwsc-page {
border-bottom-color: rgba(114, 46, 209, 0.2); border-bottom-color: rgba(114, 46, 209, 0.2);
} }
@media (max-width: 1400px) {
.services-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 1200px) {
.services-section {
padding: 40px 0 60px;
}
}
@media (max-width: 900px) { @media (max-width: 900px) {
.services-section { .services-section {
.portal-landing-card-shell-reset(); padding: 30px 0 50px;
}
.services-grid {
grid-template-columns: minmax(0, 1fr);
gap: 16px;
}
.service-card,
.service-card-inner {
min-height: auto;
} }
.breadcrumb-box { .breadcrumb-box {
@ -351,19 +408,10 @@ html.portal-figma-scale-active .fwsc-page {
} }
.banner-section { .banner-section {
height: auto; height: 220px;
min-height: 200px;
padding: 32px 16px 56px;
box-sizing: border-box;
}
.banner-content {
max-width: 100%;
padding: 0;
} }
.banner-title { .banner-title {
margin-bottom: 12px;
font-size: 28px; font-size: 28px;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -374,9 +422,7 @@ html.portal-figma-scale-active .fwsc-page {
} }
.services-section { .services-section {
padding-left: var(--page-gutter-x, 16px); padding: 20px 16px 40px;
padding-right: var(--page-gutter-x, 16px);
.portal-landing-card-shell-reset();
} }
.section-header { .section-header {
@ -399,7 +445,12 @@ html.portal-figma-scale-active .fwsc-page {
} }
.services-grid { .services-grid {
gap: 16px; gap: 12px;
}
.service-card,
.service-card-inner {
min-height: auto;
} }
.service-card-inner { .service-card-inner {
@ -407,11 +458,9 @@ html.portal-figma-scale-active .fwsc-page {
} }
.service-card-header { .service-card-header {
flex-direction: column; padding-bottom: 14px;
align-items: flex-start; margin-bottom: 14px;
padding-bottom: 12px; gap: 12px;
margin-bottom: 12px;
gap: 8px;
} }
.service-card-num { .service-card-num {
@ -424,7 +473,7 @@ html.portal-figma-scale-active .fwsc-page {
.service-card-desc { .service-card-desc {
font-size: 13px; font-size: 13px;
margin: 0 0 16px; margin-bottom: 16px;
line-height: 1.6; line-height: 1.6;
} }
@ -435,8 +484,7 @@ html.portal-figma-scale-active .fwsc-page {
@media (max-width: 480px) { @media (max-width: 480px) {
.banner-section { .banner-section {
min-height: 180px; height: 180px;
padding: 28px 12px 48px;
} }
.banner-title { .banner-title {
@ -448,8 +496,7 @@ html.portal-figma-scale-active .fwsc-page {
} }
.services-section { .services-section {
padding: 0 12px 30px; padding: 16px 12px 30px;
margin-top: -24px;
} }
.service-card-inner { .service-card-inner {

View File

@ -1,7 +1,5 @@
<template> <template>
<div class="jrsc-page portal-page-shell portal-market-figma-page"> <div class="jrsc-page">
<div class="portal-figma-scale-viewport">
<div class="portal-figma-scale-stage" ref="figmaStage">
<!-- 面包屑导航 --> <!-- 面包屑导航 -->
<!-- <BreadcrumbNav currentPage="碳金融市场" /> --> <!-- <BreadcrumbNav currentPage="碳金融市场" /> -->
@ -194,9 +192,6 @@
</div> </div>
</div> </div>
</main> </main>
</div>
</div>
<!-- 产品详情弹窗 --> <!-- 产品详情弹窗 -->
<t-dialog <t-dialog
@ -330,11 +325,9 @@
<script> <script>
import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue'; import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue';
import api from '@/pages/index/api/fwsc/index.js'; import api from '@/pages/index/api/fwsc/index.js';
import portalFigmaScaleMixin from '@/pages/index/utils/portal-figma-scale-mixin';
export default { export default {
name: 'JrscPage', name: 'JrscPage',
mixins: [portalFigmaScaleMixin],
components: { components: {
BreadcrumbNav, BreadcrumbNav,
}, },
@ -607,8 +600,6 @@ export default {
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../styles/home-figma-variables.less';
// //
@primary-color: #009a29; @primary-color: #009a29;
@primary-light: #4caf50; @primary-light: #4caf50;
@ -622,9 +613,9 @@ export default {
@bg-white: #fff; @bg-white: #fff;
.jrsc-page { .jrsc-page {
background: #F6F7FA; min-height: 100vh;
background: @bg-gray;
animation: fadeIn 0.3s ease; animation: fadeIn 0.3s ease;
.portal-figma-scale-page();
} }
@keyframes fadeIn { @keyframes fadeIn {

View File

@ -1,7 +1,5 @@
<template> <template>
<div class="xqsc-container portal-page-shell portal-market-figma-page"> <div class="xqsc-container">
<div class="portal-figma-scale-viewport">
<div class="portal-figma-scale-stage" ref="figmaStage">
<!-- 面包屑导航 --> <!-- 面包屑导航 -->
<!-- <BreadcrumbNav currentPage="碳需求市场" /> --> <!-- <BreadcrumbNav currentPage="碳需求市场" /> -->
@ -144,8 +142,6 @@
/> />
</div> </div>
</main> </main>
</div>
</div>
<!-- 发布需求抽屉 --> <!-- 发布需求抽屉 -->
<XqscPublish <XqscPublish
@ -210,13 +206,9 @@ import NewNav from '@/pages/index/components/new-nav/index.vue';
import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue'; import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue';
import XqscPublish from './components/XqscPublish.vue'; import XqscPublish from './components/XqscPublish.vue';
import api from '@/pages/index/api/fwsc/index.js'; import api from '@/pages/index/api/fwsc/index.js';
import { scrollPortalContentToTop } from '@/pages/index/utils/portal-scroll-mode';
import portalFigmaScaleMixin from '@/pages/index/utils/portal-figma-scale-mixin';
import comingSoonMixin from '@/pages/index/utils/coming-soon-mixin';
export default { export default {
name: 'XqscPage', name: 'XqscPage',
mixins: [portalFigmaScaleMixin, comingSoonMixin],
components: { components: {
NewNav, NewNav,
BreadcrumbNav, BreadcrumbNav,
@ -368,7 +360,6 @@ export default {
onPageChange(pageInfo) { onPageChange(pageInfo) {
this.page.pageNo = pageInfo.current; this.page.pageNo = pageInfo.current;
this.page.pageSize = pageInfo.pageSize; this.page.pageSize = pageInfo.pageSize;
scrollPortalContentToTop();
this.searchList(); this.searchList();
}, },
// //
@ -420,7 +411,7 @@ export default {
}, },
goToTab({path, disable}) { goToTab({path, disable}) {
if (disable) { if (disable) {
this.showComingSoon(); this.$message.info('敬请期待');
return return
} }
this.$router.push(path); this.$router.push(path);
@ -454,11 +445,9 @@ export default {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '../../styles/home-figma-variables.less';
.xqsc-container { .xqsc-container {
background: #F6F7FA; min-height: 100vh;
.portal-figma-scale-page(); background: #f5f5f5;
} }
.xqsc-main { .xqsc-main {
@ -505,7 +494,7 @@ export default {
color: #003B1A; color: #003B1A;
cursor: pointer; cursor: pointer;
background: transparent; background: transparent;
border-radius: 6px; border-radius: 32px;
transition: all 0.3s; transition: all 0.3s;
&:hover { &:hover {
@ -915,30 +904,20 @@ export default {
.pagination-box { .pagination-box {
display: flex; display: flex;
flex-wrap: wrap;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding-top: 32px; padding-top: 32px;
gap: 16px; gap: 10px;
width: 100%;
box-sizing: border-box;
::v-deep .t-pagination { ::v-deep .t-pagination {
display: flex !important; display: flex !important;
flex-wrap: wrap;
align-items: center;
justify-content: center; justify-content: center;
width: auto; flex-wrap: wrap;
max-width: 100%; width: initial;
gap: 12px 16px;
.t-input.t-is-readonly { .t-input.t-is-readonly {
width: 110px; width: 110px;
} }
.t-pagination__select {
margin-right: 0;
}
} }
} }
@ -965,99 +944,41 @@ export default {
} }
@media (max-width: 768px) { @media (max-width: 768px) {
.xqsc-container {
overflow-x: hidden;
}
.xqsc-main { .xqsc-main {
padding: 12px; padding: 12px;
box-sizing: border-box;
} }
.secondary-nav-content { .secondary-nav-content {
flex-direction: column; flex-direction: column;
align-items: stretch;
padding: 12px 16px; padding: 12px 16px;
gap: 12px; gap: 12px;
box-sizing: border-box;
} }
.nav-tabs { .nav-tabs {
display: flex;
flex-wrap: nowrap;
align-items: center;
width: 100%; width: 100%;
max-width: 100%;
height: auto;
min-height: 42px;
padding-bottom: 4px; padding-bottom: 4px;
overflow-x: auto; overflow-x: auto;
overflow-y: hidden; gap: 4px;
gap: 8px;
scrollbar-width: none;
-webkit-overflow-scrolling: touch;
&::-webkit-scrollbar {
display: none;
width: 0;
height: 0;
}
} }
.nav-tab { .nav-tab {
flex-shrink: 0;
display: inline-flex;
align-items: center;
justify-content: center;
height: auto;
min-height: 40px;
padding: 10px 12px; padding: 10px 12px;
font-size: 13px; font-size: 13px;
line-height: 1.2;
white-space: nowrap;
box-sizing: border-box;
}
.nav-right {
display: flex;
flex-direction: column;
align-items: stretch;
gap: 8px;
width: 100%;
}
.list-count {
width: 100%;
font-size: 14px;
line-height: 22px;
text-align: center;
white-space: nowrap; white-space: nowrap;
} }
.publish-btn { .publish-btn {
width: 100%; width: 100%;
height: auto; padding: 10px;
min-height: 44px;
padding: 10px 16px;
font-size: 15px;
line-height: 1.3;
box-sizing: border-box;
} }
.content-area { .content-area {
flex-direction: column; flex-direction: column;
gap: 12px;
} }
.filter-sidebar { .filter-sidebar {
position: relative; position: relative;
top: 0; top: 0;
order: -1;
width: 100%;
}
.demand-list {
order: 0;
width: 100%; width: 100%;
} }
@ -1065,6 +986,10 @@ export default {
padding: 12px; padding: 12px;
} }
.demand-list {
width: 100%;
}
.demand-grid { .demand-grid {
grid-template-columns: 1fr; grid-template-columns: 1fr;
gap: 12px; gap: 12px;
@ -1093,121 +1018,7 @@ export default {
} }
.pagination-box { .pagination-box {
flex-direction: column; padding-top: 20px;
align-items: stretch;
padding-top: 16px;
padding-bottom: 32px;
gap: 12px;
}
.pagination-total {
width: 100%;
font-size: 14px;
line-height: 22px;
text-align: center;
white-space: nowrap;
}
.pagination-box ::v-deep .t-pagination {
display: flex !important;
flex-wrap: wrap !important;
align-items: center;
justify-content: center !important;
width: 100% !important;
max-width: 100%;
white-space: normal !important;
row-gap: 12px;
column-gap: 8px;
}
.pagination-box ::v-deep .t-pagination__total {
display: none;
}
.pagination-box ::v-deep .t-pagination__btn-prev {
order: 1;
}
.pagination-box ::v-deep .t-pagination__pager {
order: 2;
}
.pagination-box ::v-deep .t-pagination__btn-next {
order: 3;
}
.pagination-box ::v-deep .t-pagination__select {
order: 4;
flex: 0 0 auto;
width: auto;
max-width: none;
margin: 0 0 0 8px !important;
display: flex;
justify-content: center;
}
.pagination-box ::v-deep .t-pagination__select .t-select__wrap {
width: auto;
max-width: none;
}
.pagination-box ::v-deep .t-pagination__pager {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 6px;
max-width: 100%;
}
@mob-pagination-h: 32px;
.pagination-box ::v-deep .t-pagination__number {
min-width: @mob-pagination-h;
height: @mob-pagination-h;
line-height: @mob-pagination-h;
margin: 0;
box-sizing: border-box;
}
.pagination-box ::v-deep .t-pagination__btn {
min-width: @mob-pagination-h;
width: @mob-pagination-h;
height: @mob-pagination-h;
line-height: @mob-pagination-h;
}
.pagination-box ::v-deep .t-pagination__select {
height: @mob-pagination-h;
align-items: center;
}
.pagination-box ::v-deep .t-pagination__select .t-select__wrap,
.pagination-box ::v-deep .t-pagination__select .t-input__wrap,
.pagination-box ::v-deep .t-pagination__select .t-input {
height: @mob-pagination-h !important;
min-height: @mob-pagination-h !important;
box-sizing: border-box;
}
.pagination-box ::v-deep .t-pagination__select .t-input__inner {
height: @mob-pagination-h !important;
min-height: @mob-pagination-h !important;
line-height: @mob-pagination-h;
padding-top: 0;
padding-bottom: 0;
font-size: 13px;
box-sizing: border-box;
}
.pagination-box ::v-deep .t-pagination__jump {
display: none !important;
}
.pagination-box ::v-deep .t-input.t-is-readonly {
width: auto;
min-width: 96px;
max-width: none;
} }
} }
@ -1246,36 +1057,6 @@ export default {
.budget-value { .budget-value {
font-size: 18px; font-size: 18px;
} }
.pagination-box {
padding-bottom: 40px;
}
@mob-pagination-h-sm: 28px;
.pagination-box ::v-deep .t-pagination__number {
min-width: @mob-pagination-h-sm;
height: @mob-pagination-h-sm;
line-height: @mob-pagination-h-sm;
font-size: 13px;
}
.pagination-box ::v-deep .t-pagination__btn {
min-width: @mob-pagination-h-sm;
width: @mob-pagination-h-sm;
height: @mob-pagination-h-sm;
line-height: @mob-pagination-h-sm;
}
.pagination-box ::v-deep .t-pagination__select,
.pagination-box ::v-deep .t-pagination__select .t-select__wrap,
.pagination-box ::v-deep .t-pagination__select .t-input__wrap,
.pagination-box ::v-deep .t-pagination__select .t-input,
.pagination-box ::v-deep .t-pagination__select .t-input__inner {
height: @mob-pagination-h-sm !important;
min-height: @mob-pagination-h-sm !important;
line-height: @mob-pagination-h-sm;
}
} }
@keyframes highlight-pulse { @keyframes highlight-pulse {

View File

@ -88,7 +88,6 @@
<script> <script>
import Nav from '@/pages/index/components/nav/index.vue'; import Nav from '@/pages/index/components/nav/index.vue';
import Footer from '@/pages/index/components/footer/index.vue';
import axios from 'axios'; import axios from 'axios';
import { mapState, mapActions } from 'vuex'; import { mapState, mapActions } from 'vuex';
import { SearchIcon } from 'tdesign-icons-vue'; import { SearchIcon } from 'tdesign-icons-vue';

View File

@ -43,13 +43,11 @@
</div> </div>
</div> </div>
</div> </div>
<!-- <Footer /> -->
</div> </div>
</template> </template>
<script> <script>
import Nav from '@/pages/index/components/nav/index.vue'; import Nav from '@/pages/index/components/nav/index.vue';
import Footer from '@/pages/index/components/footer/index.vue';
import { menuList } from './config'; import { menuList } from './config';
import api from '../../api/yhzx/index'; import api from '../../api/yhzx/index';
import gxzxApi from '@/pages/index/api/gxzx/index.js'; import gxzxApi from '@/pages/index/api/gxzx/index.js';
@ -62,7 +60,6 @@ import lsjy from '../lsjy/lsjy.vue';
export default { export default {
components: { components: {
Nav, Nav,
Footer,
qyrz, qyrz,
qyrz1, qyrz1,
tfwgj, tfwgj,

View File

@ -249,8 +249,6 @@
</section> </section>
</main> </main>
<!-- 底部信息区 -->
<Footer />
</div> </div>
<div class="sqrz" @click="ewmzs" :style="khfwStyle1"> <div class="sqrz" @click="ewmzs" :style="khfwStyle1">
<img src="../../assets/kf.png" /> <img src="../../assets/kf.png" />
@ -264,7 +262,6 @@
<script> <script>
import Nav from '@/pages/index/components/nav/index.vue'; import Nav from '@/pages/index/components/nav/index.vue';
import Footer from '@/pages/index/components/footer/index.vue';
import api from '@/pages/index/api/gxzx/index.js'; import api from '@/pages/index/api/gxzx/index.js';
import { mapState } from 'vuex'; import { mapState } from 'vuex';
import { ArrowRightIcon } from 'tdesign-icons-vue'; import { ArrowRightIcon } from 'tdesign-icons-vue';
@ -275,7 +272,6 @@ export default {
name: 'HomePage', name: 'HomePage',
components: { components: {
Nav, Nav,
Footer,
CardLayout, CardLayout,
Hzhb, Hzhb,
ArrowRightIcon, ArrowRightIcon,

View File

@ -25,7 +25,6 @@
</iframe> </iframe>
<iframe ref="myIframe" v-if="iskxt" :src="iFrameSrc" style="height: calc(100vh - 76px)" class="iframe-container"> <iframe ref="myIframe" v-if="iskxt" :src="iFrameSrc" style="height: calc(100vh - 76px)" class="iframe-container">
</iframe> </iframe>
<Footer />
</div> </div>
<t-dialog <t-dialog
:closeOnOverlayClick="false" :closeOnOverlayClick="false"
@ -60,12 +59,10 @@
<script> <script>
import Nav from '@/pages/index/components/nav/index.vue'; import Nav from '@/pages/index/components/nav/index.vue';
import Footer from '@/pages/index/components/footer/index.vue';
import api from '@/pages/index/api/gxzx/index.js'; import api from '@/pages/index/api/gxzx/index.js';
export default { export default {
components: { components: {
Nav, Nav,
Footer,
}, },
props: {}, props: {},
data() { data() {

View File

@ -336,8 +336,6 @@
></button> ></button>
</div> </div>
<Footer style="width:100%" />
</div> </div>
</div> </div>
</div> </div>
@ -347,7 +345,6 @@
</template> </template>
<script> <script>
import Footer from '@/pages/index/components/footer/index.vue';
import hydtApi from '@/pages/index/api/hydt'; import hydtApi from '@/pages/index/api/hydt';
import gxzxApi from '@/pages/index/api/gxzx/index.js'; import gxzxApi from '@/pages/index/api/gxzx/index.js';
import searchApi from '@/pages/index/api/search.js'; import searchApi from '@/pages/index/api/search.js';
@ -505,7 +502,6 @@ export default {
}; };
}, },
components: { components: {
Footer,
}, },
activated() { activated() {
// keep-alive IntersectionObserver section // keep-alive IntersectionObserver section
@ -3074,10 +3070,6 @@ export default {
} }
} }
.bottom-box + :deep(.portal-footer-shell) {
margin-top: 0;
}
/* 按 1:1 还原整图时,关闭代码绘制的右侧文案层 */ /* 按 1:1 还原整图时,关闭代码绘制的右侧文案层 */
.bottom-box-inner, .bottom-box-inner,
.bottom-box-copy, .bottom-box-copy,
@ -4006,14 +3998,4 @@ export default {
} }
} }
/* =============================================================================
* 首页 footer 反向缩放footer .home-figma-scale-stage 内部会被 transform: scale 放大
* home2 内部生效scoped 限定不影响走 main.vue 的内页 footer
* transform 不改变 layout boxstage margin-bottom 补偿保持正确
* ============================================================================= */
.portal-footer-shell {
transform: scale(calc(1 / var(--home-figma-scale, 1)));
transform-origin: top center;
width: 100%;
}
</style> </style>

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="hydt-page portal-page portal-page-shell"> <div class="hydt-page portal-page">
<!-- Figma banner-bg 150622:19115背景 imageRef ec2e3dd --> <!-- Figma banner-bg 150622:19115背景 imageRef ec2e3dd -->
<section class="hydt-banner" aria-label="行业动态"> <section class="hydt-banner" aria-label="行业动态">
<div class="hydt-banner-bg" aria-hidden="true"></div> <div class="hydt-banner-bg" aria-hidden="true"></div>
@ -23,7 +23,7 @@
<section class="hydt-body"> <section class="hydt-body">
<div class="hydt-body-inner page-content-wrap"> <div class="hydt-body-inner page-content-wrap">
<div class="hydt-panel"> <div class="hydt-panel">
<div ref="tabsRef" class="hydt-tabs" role="tablist" aria-label="动态分类"> <div class="hydt-tabs" role="tablist" aria-label="动态分类">
<button <button
v-for="(tab, index) in newsTabs" v-for="(tab, index) in newsTabs"
:key="tab.type" :key="tab.type"
@ -41,7 +41,7 @@
<div v-if="pageLoading" class="hydt-state">加载中...</div> <div v-if="pageLoading" class="hydt-state">加载中...</div>
<div v-else-if="!filteredList.length" class="hydt-state">暂无相关动态</div> <div v-else-if="!filteredList.length" class="hydt-state">暂无相关动态</div>
<template v-else> <template v-else>
<div ref="listRef" class="hydt-list"> <div class="hydt-list">
<article <article
v-for="(item, index) in paginatedList" v-for="(item, index) in paginatedList"
:key="item.id || item.uuid || item.bt || index" :key="item.id || item.uuid || item.bt || index"
@ -95,7 +95,6 @@ const NEWS_TABS = [
export default { export default {
name: 'HydtIndex', name: 'HydtIndex',
components: {},
data() { data() {
return { return {
newsTabs: NEWS_TABS, newsTabs: NEWS_TABS,
@ -149,52 +148,14 @@ export default {
if (index >= 0) this.activeTab = index; if (index >= 0) this.activeTab = index;
}, },
switchTab(index) { switchTab(index) {
// tab no-op
if (this.activeTab === index) return;
this.activeTab = index; this.activeTab = index;
// list sticky tabs const type = this.newsTabs[index]?.type;
// if (this.$route.query.type !== type) {
this.$nextTick(() => { this.$router.replace({ path: '/hydt', query: { type } });
this.scrollToListTop();
});
},
onPageChange() {
// list
this.$nextTick(() => {
this.scrollToListTop();
});
},
/**
* 滚动到 list 顶部
*
* 注意点.hydt-tabs position: sticky; top: 0;
* 如果直接把 list 顶端对齐到视口顶会被 sticky tabs 遮住一部分
* 所以目标 top "减去"tabs 的实际高度动态读取避免硬编码样式变量
*/
scrollToListTop() {
const list = this.$refs.listRef;
if (!list) return;
const tabs = this.$refs.tabsRef;
// tabs padding 0
const tabsHeight = tabs ? tabs.getBoundingClientRect().height : 0;
const root = this.getScrollRoot();
const rootRect = root === window ? { top: 0 } : root.getBoundingClientRect();
// list tabs
const targetTop = (root === window ? window.scrollY : root.scrollTop)
+ (list.getBoundingClientRect().top - rootRect.top)
- tabsHeight;
const finalTop = Math.max(0, targetTop);
if (root === window) {
window.scrollTo({ top: finalTop, behavior: 'smooth' });
} else {
root.scrollTo({ top: finalTop, behavior: 'smooth' });
} }
}, },
getScrollRoot() { onPageChange() {
// .content-wrapmain.vue window window.scrollTo({ top: 0, behavior: 'smooth' });
const portalRoot = document.querySelector('.content-wrap');
if (portalRoot) return portalRoot;
return window;
}, },
handleNewsClick(item) { handleNewsClick(item) {
const link = item.yyLj || item.lj; const link = item.yyLj || item.lj;
@ -206,33 +167,24 @@ export default {
}, },
async fetchNewsData() { async fetchNewsData() {
this.pageLoading = true; this.pageLoading = true;
const [hydtResult, ptggResult] = await Promise.allSettled([ try {
hydtApi.getHydtGroupedList(), const [hydtRes, ptggRes] = await Promise.all([
hydtApi.getPtggList(), hydtApi.getHydtGroupedList(),
]); hydtApi.getPtggList(),
]);
if (hydtResult.status === 'fulfilled' && hydtResult.value && hydtResult.value.data) { if (hydtRes.data) {
this.newsListByType.gjzc = hydtResult.value.data.gjzc || []; this.newsListByType.gjzc = hydtRes.data.gjzc || [];
this.newsListByType.hyzx = hydtResult.value.data.hyzx || []; this.newsListByType.hyzx = hydtRes.data.hyzx || [];
} else { }
this.newsListByType.gjzc = []; if (ptggRes.data) {
this.newsListByType.hyzx = []; this.newsListByType.ptgg = ptggRes.data || [];
console.error('获取行业动态失败', hydtResult.status === 'rejected' ? hydtResult.reason : null); }
} } catch (e) {
console.error('获取行业动态失败', e);
if (ptggResult.status === 'fulfilled' && ptggResult.value && ptggResult.value.data) {
this.newsListByType.ptgg = ptggResult.value.data || [];
} else {
this.newsListByType.ptgg = [];
console.error('获取平台公告失败', ptggResult.status === 'rejected' ? ptggResult.reason : null);
}
const allFailed = hydtResult.status === 'rejected' && ptggResult.status === 'rejected';
if (allFailed) {
this.$message.warning('加载失败,请稍后重试'); this.$message.warning('加载失败,请稍后重试');
} finally {
this.pageLoading = false;
} }
this.pageLoading = false;
}, },
getDefaultPic(type) { getDefaultPic(type) {
const defaultPics = { const defaultPics = {
@ -346,7 +298,7 @@ export default {
} }
.hydt-body-inner { .hydt-body-inner {
padding: 24px 0 @hydt-body-pad-bottom; padding: @hydt-body-pad-top 0 @hydt-body-pad-bottom;
box-sizing: border-box; box-sizing: border-box;
} }
@ -362,10 +314,7 @@ export default {
flex-wrap: wrap; flex-wrap: wrap;
align-items: flex-end; align-items: flex-end;
gap: @home-news-tab-gap; gap: @home-news-tab-gap;
padding: @hydt-tabs-to-list-gap 4px; margin-bottom: @hydt-tabs-to-list-gap;
position: sticky;
top: 0;
background: white;
} }
.hydt-tab { .hydt-tab {
@ -408,7 +357,6 @@ export default {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: @hydt-list-gap; gap: @hydt-list-gap;
padding: 0 4px;
} }
.hydt-item { .hydt-item {
@ -510,10 +458,8 @@ export default {
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
gap: 16px; gap: 16px;
width: 100%;
padding-top: 16px; padding-top: 16px;
padding-bottom: 16px; padding-bottom: 16px;
box-sizing: border-box;
} }
.hydt-pagination-total { .hydt-pagination-total {
@ -528,8 +474,7 @@ export default {
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
gap: 12px 16px; gap: 16px;
max-width: 100%;
} }
.hydt-pagination ::v-deep .t-pagination__select { .hydt-pagination ::v-deep .t-pagination__select {
@ -589,147 +534,10 @@ export default {
.hydt-pagination { .hydt-pagination {
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
gap: 12px;
padding-top: 20px;
padding-bottom: 24px;
}
.hydt-pagination-total {
width: 100%;
font-size: 14px;
line-height: 22px;
text-align: center;
} }
.hydt-pagination ::v-deep .t-pagination { .hydt-pagination ::v-deep .t-pagination {
display: flex !important;
flex-wrap: wrap !important;
align-items: center;
justify-content: center !important;
width: 100% !important;
max-width: 100%;
white-space: normal !important;
row-gap: 12px;
column-gap: 8px;
}
.hydt-pagination ::v-deep .t-pagination__total {
display: none;
}
.hydt-pagination ::v-deep .t-pagination__btn-prev {
order: 1;
}
.hydt-pagination ::v-deep .t-pagination__pager {
order: 2;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center; justify-content: center;
gap: 6px;
max-width: 100%;
}
.hydt-pagination ::v-deep .t-pagination__btn-next {
order: 3;
}
.hydt-pagination ::v-deep .t-pagination__select {
order: 4;
flex: 0 0 auto;
width: auto;
max-width: none;
margin: 0 0 0 8px !important;
display: flex;
justify-content: center;
}
.hydt-pagination ::v-deep .t-pagination__select .t-select__wrap {
width: auto;
max-width: none;
}
@hydt-mob-pagination-h: 32px;
.hydt-pagination ::v-deep .t-pagination__number {
min-width: @hydt-mob-pagination-h;
height: @hydt-mob-pagination-h;
line-height: @hydt-mob-pagination-h;
margin: 0;
box-sizing: border-box;
}
.hydt-pagination ::v-deep .t-pagination__btn {
min-width: @hydt-mob-pagination-h;
width: @hydt-mob-pagination-h;
height: @hydt-mob-pagination-h;
line-height: @hydt-mob-pagination-h;
}
.hydt-pagination ::v-deep .t-pagination__select {
height: @hydt-mob-pagination-h;
align-items: center;
}
.hydt-pagination ::v-deep .t-pagination__select .t-select__wrap,
.hydt-pagination ::v-deep .t-pagination__select .t-input__wrap,
.hydt-pagination ::v-deep .t-pagination__select .t-input {
height: @hydt-mob-pagination-h !important;
min-height: @hydt-mob-pagination-h !important;
box-sizing: border-box;
}
.hydt-pagination ::v-deep .t-pagination__select .t-input__inner {
height: @hydt-mob-pagination-h !important;
min-height: @hydt-mob-pagination-h !important;
line-height: @hydt-mob-pagination-h;
padding-top: 0;
padding-bottom: 0;
font-size: 13px;
box-sizing: border-box;
}
.hydt-pagination ::v-deep .t-pagination__jump {
display: none !important;
}
.hydt-pagination ::v-deep .t-input.t-is-readonly {
width: auto;
min-width: 96px;
max-width: none;
}
}
@media screen and (max-width: 480px) {
.hydt-pagination {
padding-bottom: 32px;
}
@hydt-mob-pagination-h-sm: 28px;
.hydt-pagination ::v-deep .t-pagination__number {
min-width: @hydt-mob-pagination-h-sm;
height: @hydt-mob-pagination-h-sm;
line-height: @hydt-mob-pagination-h-sm;
font-size: 13px;
}
.hydt-pagination ::v-deep .t-pagination__btn {
min-width: @hydt-mob-pagination-h-sm;
width: @hydt-mob-pagination-h-sm;
height: @hydt-mob-pagination-h-sm;
line-height: @hydt-mob-pagination-h-sm;
}
.hydt-pagination ::v-deep .t-pagination__select,
.hydt-pagination ::v-deep .t-pagination__select .t-select__wrap,
.hydt-pagination ::v-deep .t-pagination__select .t-input__wrap,
.hydt-pagination ::v-deep .t-pagination__select .t-input,
.hydt-pagination ::v-deep .t-pagination__select .t-input__inner {
height: @hydt-mob-pagination-h-sm !important;
min-height: @hydt-mob-pagination-h-sm !important;
line-height: @hydt-mob-pagination-h-sm;
} }
} }
</style> </style>

View File

@ -1,7 +1,5 @@
<template> <template>
<div class="hyzt-wrap portal-page-shell portal-landing-figma-page"> <div class="hyzt-wrap">
<div class="portal-figma-scale-viewport">
<div class="portal-figma-scale-stage" ref="figmaStage">
<!-- Figma 150581:4101 banner-bg / 150679:365 hyzt_banner 1 --> <!-- Figma 150581:4101 banner-bg / 150679:365 hyzt_banner 1 -->
<section class="banner-section" aria-label="行业专题"> <section class="banner-section" aria-label="行业专题">
<div class="banner-bg" aria-hidden="true"></div> <div class="banner-bg" aria-hidden="true"></div>
@ -36,22 +34,14 @@
</div> </div>
</div> </div>
</div>
</div>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from 'vuex'; import { mapState } from 'vuex';
import portalFigmaScaleMixin from '@/pages/index/utils/portal-figma-scale-mixin';
import comingSoonMixin from '@/pages/index/utils/coming-soon-mixin';
// 线main.vue t-dialog 线
import '@/pages/index/utils/coming-soon-dialog.js';
export default { export default {
name: 'hyzt', name: 'hyzt',
mixins: [portalFigmaScaleMixin, comingSoonMixin],
components: {},
data() { data() {
return { return {
headerClassList: ['blue-header', 'green-header', 'purple-header'], headerClassList: ['blue-header', 'green-header', 'purple-header'],
@ -67,10 +57,9 @@ export default {
goToHref(href) { goToHref(href) {
if (href) { if (href) {
window.open(href, '_blank'); window.open(href, '_blank');
return; } else {
this.$message.info('敬请期待');
} }
// home2 使 mixin ""
this.showComingSoon();
}, },
}, },
}; };
@ -78,14 +67,22 @@ export default {
<style lang="less" scoped> <style lang="less" scoped>
@import '../../styles/home-figma-variables.less'; @import '../../styles/home-figma-variables.less';
@import '../../styles/portal-landing-cards.less';
.hyzt-wrap { .hyzt-wrap {
min-height: 100%;
background: #f6f7fa; background: #f6f7fa;
.portal-figma-scale-page();
} }
/* Figma 150581:4101 banner-bg — 1280×350背景仅在 Banner 区内(同企业出海) */ /* Figma 1440版心 1300 居中x:70 */
.hyzt-page-inner {
width: 100%;
max-width: @hyzt-landing-content-width;
margin-left: auto;
margin-right: auto;
box-sizing: border-box;
}
/* Figma 150581:4101 banner-bg — 1280×350背景 hyzt_banner 1280×548、top:-34 */
.banner-section { .banner-section {
position: relative; position: relative;
z-index: 1; z-index: 1;
@ -108,6 +105,7 @@ export default {
background-size: cover; background-size: cover;
} }
/* 与导航「可」字左缘对齐:使用 page-content-wrap--page-gutter-x勿用 1100 版心 + 60px */
.banner-inner { .banner-inner {
position: relative; position: relative;
z-index: 1; z-index: 1;
@ -146,19 +144,12 @@ export default {
vertical-align: baseline; vertical-align: baseline;
} }
/* Figma 1440版心 1300 居中x:70 */ /* Figma hyzt_content 150581:4199 — 1100×428padding 60/30/80与 Banner 重叠 93px */
.hyzt-page-inner {
width: 100%;
max-width: @hyzt-landing-content-width;
margin-left: auto;
margin-right: auto;
box-sizing: border-box;
}
/* Figma hyzt_content 150581:4199 — 与 Banner 重叠量同服务中心120px */
.services-section { .services-section {
position: relative; position: relative;
z-index: 2; z-index: 2;
margin-top: -@hyzt-landing-cards-overlap;
padding: @hyzt-landing-cards-pt @hyzt-landing-cards-px @hyzt-landing-cards-pb;
box-sizing: border-box; box-sizing: border-box;
.services-grid { .services-grid {
@ -169,8 +160,6 @@ export default {
align-items: stretch; align-items: stretch;
} }
.portal-landing-card-shell();
.service-card { .service-card {
width: 100%; width: 100%;
cursor: pointer; cursor: pointer;
@ -187,7 +176,20 @@ export default {
} }
} }
.service-card-inner {
display: flex;
flex-direction: column;
height: 100%;
min-height: 288px;
padding: @hyzt-landing-card-padding;
gap: @hyzt-landing-card-col-gap;
box-sizing: border-box;
}
.service-card-header { .service-card-header {
flex-shrink: 0;
padding-bottom: @hyzt-landing-card-header-pb;
margin-bottom: 0;
border-bottom-width: 1px; border-bottom-width: 1px;
border-bottom-style: solid; border-bottom-style: solid;
text-align: center; text-align: center;
@ -197,20 +199,27 @@ export default {
margin: 0; margin: 0;
font-size: @hyzt-landing-card-title-size; font-size: @hyzt-landing-card-title-size;
font-weight: @home-font-weight-semibold; font-weight: @home-font-weight-semibold;
line-height: 1.35; line-height: 1.4;
color: @home-color-black; color: @home-color-black;
text-align: center; text-align: center;
} }
.service-card-desc { .service-card-desc {
flex: 1;
margin: 0;
min-height: @hyzt-landing-card-desc-min-h;
padding-top: 0;
font-size: @hyzt-landing-card-desc-size; font-size: @hyzt-landing-card-desc-size;
font-weight: @home-font-weight-regular; font-weight: @home-font-weight-regular;
line-height: 1.8; line-height: 1.6;
color: @hyzt-landing-card-desc-color; color: @hyzt-landing-card-desc-color;
text-align: center; text-align: center;
} }
.service-card-buttons { .service-card-buttons {
flex-shrink: 0;
margin-top: auto;
/deep/ .t-button { /deep/ .t-button {
width: 100%; width: 100%;
height: @hyzt-landing-card-btn-h; height: @hyzt-landing-card-btn-h;
@ -244,9 +253,13 @@ export default {
} }
@media (max-width: 1200px) { @media (max-width: 1200px) {
.services-section .services-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.services-section { .services-section {
--portal-service-card-min-height: auto; padding-top: 40px;
.portal-landing-card-shell-reset(); padding-bottom: 60px;
} }
} }
@ -255,13 +268,19 @@ export default {
height: 280px; height: 280px;
} }
.services-section {
margin-top: -60px;
padding-top: 40px;
padding-bottom: 60px;
}
.services-section .services-grid { .services-section .services-grid {
grid-template-columns: 1fr; grid-template-columns: 1fr;
gap: 16px; gap: 16px;
} }
.services-section .service-card-desc { .services-section .service-card-inner {
font-size: 14px; min-height: auto;
} }
} }
@ -273,5 +292,10 @@ export default {
.services-section .service-card-title { .services-section .service-card-title {
font-size: 18px; font-size: 18px;
} }
.services-section .service-card-desc {
font-size: 14px;
min-height: auto;
}
} }
</style> </style>

View File

@ -72,13 +72,10 @@
</div> </div>
<!-- 短信验证码登录 --> <!-- 短信验证码登录 -->
<t-form-item class="btn-container"> <t-form-item class="btn-container forgot-password-form-item">
<t-button class="btn-container" block size="large" type="submit"> 登录</t-button> <t-button class="btn-container" block size="large" type="submit"> 登录</t-button>
<a class="forgot-password-link" @click="handleForgotPassword">忘记密码</a>
</t-form-item> </t-form-item>
<!-- <div class="check-container remember-pwd">
<t-checkbox>记住账号</t-checkbox>
<span v-show="loginForm.loginType === 'password'" class="tip">忘记密码</span>
</div> -->
</t-form> </t-form>
</div> </div>
</div> </div>
@ -332,6 +329,13 @@ export default {
this.loginForm.captchaCode = ''; this.loginForm.captchaCode = '';
}); });
}, },
//
handleForgotPassword() {
MessagePlugin.info({
content: '请联系运维管理员pjsl_service@chainable.com.cn',
duration: 4000,
});
},
}, },
mounted() { mounted() {
// === === // === ===
@ -424,6 +428,26 @@ export default {
width: 350px; width: 350px;
height: 40px; height: 40px;
} }
/* 忘记密码 */
.forgot-password-form-item {
margin-bottom: 0;
}
.forgot-password-form-item ::v-deep .t-form__controls-content {
display: flex;
flex-direction: column;
gap: 8px;
}
.forgot-password-link {
align-self: flex-end;
font-size: 14px;
color: #2E7D32;
cursor: pointer;
text-decoration: none;
user-select: none;
}
.forgot-password-link:hover {
text-decoration: underline;
}
.captcha-img { .captcha-img {
width: 120px; width: 120px;
height: 40px; height: 40px;

View File

@ -102,7 +102,8 @@ export default {
return this.$route.path === '/login' || this.$route.name === 'login'; return this.$route.path === '/login' || this.$route.name === 'login';
}, },
showPortalFooter() { showPortalFooter() {
return !this.isHomePage && !this.isLoginPage; // main.vue home2
return !this.isLoginPage;
}, },
isLandingHubPage() { isLandingHubPage() {
return !!(this.$route.meta && this.$route.meta.landingHubScrollFooter); return !!(this.$route.meta && this.$route.meta.landingHubScrollFooter);

View File

@ -1,7 +1,5 @@
<template> <template>
<div class="compliance-portal portal-page-shell portal-landing-figma-page"> <div class="compliance-portal">
<div class="portal-figma-scale-viewport">
<div class="portal-figma-scale-stage" ref="figmaStage">
<!-- 首屏标题区 + 三大专题入口 --> <!-- 首屏标题区 + 三大专题入口 -->
<div id="section-landing" class="qych-snap-section qych-landing"> <div id="section-landing" class="qych-snap-section qych-landing">
<div class="banner-section"> <div class="banner-section">
@ -49,10 +47,7 @@
<div class=""> <div class="">
<div class="content-wrapper2"> <div class="content-wrapper2">
<div class="text-section"> <div class="text-section">
<div class="text-section-head-row"> <div class="text-section-title">法案解读</div>
<div class="text-section-title">法案解读</div>
<div class="text-section-title-dcfa">申请服务</div>
</div>
<div class="text-section-content"> <div class="text-section-content">
<div class="content-item1"> <div class="content-item1">
<ul class="info-list"> <ul class="info-list">
@ -69,6 +64,7 @@
</div> </div>
<div class="content-item2"> <div class="content-item2">
<div class="service-section-dcfa"> <div class="service-section-dcfa">
<div class="text-section-title-dcfa">申请服务</div>
<div class="dcfa-cards-stack"> <div class="dcfa-cards-stack">
<div class="apply-service-card card1"> <div class="apply-service-card card1">
<div class="card-item1"> <div class="card-item1">
@ -118,10 +114,7 @@
<div class="content-wrapper2"> <div class="content-wrapper2">
<div class="text-section qych-policy-frame"> <div class="text-section qych-policy-frame">
<div class="text-section-head-row"> <div class="text-section-title">政策解读</div>
<div class="text-section-title">政策解读</div>
<div class="text-section-title-dcfa">CBAM试算</div>
</div>
<div class="text-section-content"> <div class="text-section-content">
<div class="content-item1"> <div class="content-item1">
<div class="info-list info-list--stacked"> <div class="info-list info-list--stacked">
@ -150,6 +143,7 @@
</div> </div>
<div class="content-item2"> <div class="content-item2">
<div class="service-section-dcfa"> <div class="service-section-dcfa">
<div class="text-section-title-dcfa">CBAM试算</div>
<div class="dcfa-cards-stack"> <div class="dcfa-cards-stack">
<div class="apply-service-card card1"> <div class="apply-service-card card1">
<div class="card-item1 card-item--cbam-primary"> <div class="card-item1 card-item--cbam-primary">
@ -200,10 +194,7 @@
<div class="content-wrapper2"> <div class="content-wrapper2">
<div class="text-section"> <div class="text-section">
<div class="text-section-head-row"> <div class="text-section-title">低碳政策</div>
<div class="text-section-title">低碳政策</div>
<div class="text-section-title-dcfa">申请服务</div>
</div>
<div class="text-section-content"> <div class="text-section-content">
<div class="content-item1"> <div class="content-item1">
<ul class="info-list"> <ul class="info-list">
@ -220,6 +211,7 @@
</div> </div>
<div class="content-item2"> <div class="content-item2">
<div class="service-section-dcfa"> <div class="service-section-dcfa">
<div class="text-section-title-dcfa">申请服务</div>
<div class="dcfa-cards-stack"> <div class="dcfa-cards-stack">
<div class="apply-service-card card1"> <div class="apply-service-card card1">
<div class="card-item1 card-item--with-action"> <div class="card-item1 card-item--with-action">
@ -266,26 +258,23 @@
</div> </div>
</div> </div>
</main> </main>
</div>
</div>
</div> </div>
</template> </template>
<script> <script>
import serviceCardIcon1 from '../../assets/qych/service-card-icon-1.png' import serviceCardIcon1 from '../../assets/qych/service-card-icon-1.png'
import serviceCardIcon2 from '../../assets/qych/service-card-icon-2.png' import serviceCardIcon2 from '../../assets/qych/service-card-icon-2.png'
import portalFigmaScaleMixin from '@/pages/index/utils/portal-figma-scale-mixin';
import fullpageScrollMixin from '@/pages/index/utils/fullpage-scroll-mixin';
import comingSoonMixin from '@/pages/index/utils/coming-soon-mixin';
export default { export default {
name: 'CompliancePortal', name: 'CompliancePortal',
mixins: [portalFigmaScaleMixin, fullpageScrollMixin, comingSoonMixin],
components: {},
data() { data() {
return { return {
serviceCardIcon1, serviceCardIcon1,
serviceCardIcon2, serviceCardIcon2,
isScrolling: false,
scrollThreshold: 1,
scrollRoot: null,
sectionIds: ['section-landing', 'section0', 'section1', 'section2'], sectionIds: ['section-landing', 'section0', 'section1', 'section2'],
navList: [ navList: [
{ {
@ -310,7 +299,7 @@ export default {
{ {
cardTitle: '航运燃料', cardTitle: '航运燃料',
cardDesc: 'LNG、绿甲醇、绿氨等多元低碳燃料转型政策与系统入口。', cardDesc: 'LNG、绿甲醇、绿氨等多元低碳燃料转型政策与系统入口。',
btnText: '进入专题', btnText: '进入交易大厅',
headerClass: 'purple-header', headerClass: 'purple-header',
sectionId: 'section2', sectionId: 'section2',
index: 2, index: 2,
@ -321,24 +310,24 @@ export default {
}, },
mounted() { mounted() {
this.$nextTick(() => { this.$nextTick(() => {
this.scrollRoot = document.querySelector('.content-wrap');
if (this.scrollRoot) {
this.scrollRoot.addEventListener('wheel', this.handleWheel, { passive: false });
}
this.scrollToSectionFromQuery(); this.scrollToSectionFromQuery();
}); });
}, },
watch: { beforeDestroy() {
// section if (this.scrollRoot) {
// query mounted this.scrollRoot.removeEventListener('wheel', this.handleWheel);
'$route.query.section': { }
handler() {
this.scrollToSectionFromQuery();
},
},
}, },
methods: { methods: {
goPage(url) { goPage(url) {
if (url) { if (url) {
window.open(url); window.open(url);
} else { } else {
this.showComingSoon() this.$message.info('敬请期待')
} }
}, },
handleCardBtnClick(item) { handleCardBtnClick(item) {
@ -389,23 +378,93 @@ export default {
return currentIndex; return currentIndex;
}, },
scrollRootToSection(sectionIndex, smooth = true) { scrollRootToSection(sectionIndex, smooth = true) {
this.fullPageScrollTo(sectionIndex); const scrollRoot = this.getScrollRoot();
const el = document.getElementById(this.sectionIds[sectionIndex]);
if (!scrollRoot || !el) return;
const top = this.getSectionScrollTop(el, scrollRoot);
scrollRoot.scrollTo({ top, behavior: smooth ? 'smooth' : 'auto' });
this.syncNavBySectionIndex(sectionIndex); this.syncNavBySectionIndex(sectionIndex);
}, },
/** 导航点跳到指定 section使用 fullpageScrollMixin 提供的 fullPageScrollTo */ /** 专题区 .module 内部先滚完,再翻页 */
/** 当前屏内容高于视口时,先在 .content-wrap 内滚完该屏 */
trySectionPageScroll(sectionEl, scrollRoot, direction, e, edgeGap = 8) {
if (!sectionEl || !scrollRoot) return false;
if (sectionEl.offsetHeight <= scrollRoot.clientHeight + edgeGap) {
return false;
}
const sectionTop = this.getSectionScrollTop(sectionEl, scrollRoot);
const sectionBottom = sectionTop + sectionEl.offsetHeight;
const viewTop = scrollRoot.scrollTop;
const viewBottom = viewTop + scrollRoot.clientHeight;
if (direction > 0 && viewBottom < sectionBottom - edgeGap) {
e.preventDefault();
scrollRoot.scrollTop += e.deltaY;
return true;
}
if (direction < 0 && viewTop > sectionTop + edgeGap) {
e.preventDefault();
scrollRoot.scrollTop += e.deltaY;
return true;
}
return false;
},
scrollToSection(item) { scrollToSection(item) {
const sectionIndex = this.sectionIds.indexOf(item.sectionId); const sectionIndex = this.sectionIds.indexOf(item.sectionId);
if (sectionIndex < 0) return; if (sectionIndex < 0) return;
this.setNavActive(item.index); this.setNavActive(item.index);
this.fullPageScrollTo(sectionIndex); this.isScrolling = true;
this.scrollRootToSection(sectionIndex, true);
setTimeout(() => {
this.isScrolling = false;
}, 800);
}, },
syncNavBySectionIndex(sectionIndex) { syncNavBySectionIndex(sectionIndex) {
if (sectionIndex >= 1 && sectionIndex <= 3) { if (sectionIndex >= 1 && sectionIndex <= 3) {
this.setNavActive(sectionIndex - 1); this.setNavActive(sectionIndex - 1);
} }
}, },
onFullPageSectionChange(newIndex /*, fromIndex, sectionEl */) { handleWheel(e) {
this.syncNavBySectionIndex(newIndex); if (this.isScrolling) return;
const delta = Math.abs(e.deltaY);
if (delta < this.scrollThreshold) return;
const scrollRoot = this.getScrollRoot();
if (!scrollRoot) return;
const direction = e.deltaY > 0 ? 1 : -1;
const currentIndex = this.getCurrentSectionIndex(scrollRoot);
const currentEl = document.getElementById(this.sectionIds[currentIndex]);
if (currentEl && this.trySectionPageScroll(currentEl, scrollRoot, direction, e)) {
return;
}
let targetIndex;
if (direction > 0) {
targetIndex = Math.min(currentIndex + 1, this.sectionIds.length - 1);
} else {
targetIndex = Math.max(currentIndex - 1, 0);
}
if (targetIndex === currentIndex) {
const top = this.getSectionScrollTop(currentEl, scrollRoot);
if (Math.abs(scrollRoot.scrollTop - top) > 6) {
e.preventDefault();
this.isScrolling = true;
this.scrollRootToSection(currentIndex, true);
setTimeout(() => {
this.isScrolling = false;
}, 800);
}
return;
}
e.preventDefault();
this.isScrolling = true;
this.scrollRootToSection(targetIndex, true);
setTimeout(() => {
this.isScrolling = false;
}, 800);
}, },
}, },
}; };
@ -413,7 +472,6 @@ export default {
<style scoped lang="less"> <style scoped lang="less">
@import '../../styles/home-figma-variables.less'; @import '../../styles/home-figma-variables.less';
@import '../../styles/portal-landing-cards.less';
/* 基础样式重置 */ /* 基础样式重置 */
* { * {
@ -434,14 +492,18 @@ body {
} }
/* 全屏分页:高度对齐 main.vue 的 .content-wrap非首页 = 100vh - 顶栏) */ /* 全屏分页:高度对齐 main.vue 的 .content-wrap非首页 = 100vh - 顶栏) */
@qych-viewport-h: var(--portal-scroll-height, calc(100vh - var(--page-offset-top, 64px))); @qych-viewport-h: calc(100vh - var(--page-offset-top, 64px));
.qych-snap-section { .qych-snap-section {
min-height: @qych-viewport-h; min-height: @qych-viewport-h;
box-sizing: border-box; box-sizing: border-box;
} }
/* 首屏布局见 page-layout.less.qych-landing */ .qych-landing {
min-height: @qych-viewport-h;
background: #f6f7fa;
overflow: hidden;
}
/* Figma 1440 画布:内容区宽 1300左右各 70px 居中 */ /* Figma 1440 画布:内容区宽 1300左右各 70px 居中 */
.qych-page-inner { .qych-page-inner {
@ -455,7 +517,6 @@ body {
/* 主容器 */ /* 主容器 */
.compliance-portal { .compliance-portal {
background-color: #f6f7fa; background-color: #f6f7fa;
.portal-figma-scale-page();
} }
/* 首屏 BannerFigma 150581:2709 — 1440×350背景图 1440×371 */ /* 首屏 BannerFigma 150581:2709 — 1440×350背景图 1440×371 */
@ -539,8 +600,12 @@ body {
.content { .content {
} }
/* 专题入口:卡片区样式;首屏布局与 padding 见 page-layout.less */ /* 专题入口:Figma 150581:2808 — 1300×428padding 60/30/80y:321 与 Banner 重叠 93px */
.qych-landing .services-section { .qych-landing .services-section {
position: relative;
z-index: 2;
margin-top: -@qych-landing-cards-overlap;
padding: @qych-landing-cards-pt @qych-landing-cards-px @qych-landing-cards-pb;
box-sizing: border-box; box-sizing: border-box;
.services-grid { .services-grid {
@ -551,8 +616,6 @@ body {
align-items: stretch; align-items: stretch;
} }
.portal-landing-card-shell();
.service-card { .service-card {
width: 100%; width: 100%;
cursor: pointer; cursor: pointer;
@ -573,7 +636,20 @@ body {
box-shadow: 0 12px 32px rgba(0, 154, 41, 0.15); box-shadow: 0 12px 32px rgba(0, 154, 41, 0.15);
} }
.service-card-inner {
display: flex;
flex-direction: column;
height: 100%;
min-height: 288px;
padding: @qych-landing-card-padding;
gap: @qych-landing-card-col-gap;
box-sizing: border-box;
}
.service-card-header { .service-card-header {
flex-shrink: 0;
padding-bottom: @qych-landing-card-header-pb;
margin-bottom: 0;
border-bottom-width: 1px; border-bottom-width: 1px;
border-bottom-style: solid; border-bottom-style: solid;
text-align: center; text-align: center;
@ -583,21 +659,27 @@ body {
margin: 0; margin: 0;
font-size: @qych-landing-card-title-size; font-size: @qych-landing-card-title-size;
font-weight: @home-font-weight-semibold; font-weight: @home-font-weight-semibold;
line-height: 1.35; line-height: 1.4;
color: @home-color-black; color: @home-color-black;
text-align: center; text-align: center;
word-break: keep-all;
} }
.service-card-desc { .service-card-desc {
flex: 1;
margin: 0;
min-height: @qych-landing-card-desc-min-h;
padding-top: @qych-landing-card-desc-pt;
font-size: @qych-landing-card-desc-size; font-size: @qych-landing-card-desc-size;
font-weight: @home-font-weight-regular; font-weight: @home-font-weight-regular;
line-height: 1.8; line-height: 1.6;
color: @qych-landing-card-desc-color; color: @qych-landing-card-desc-color;
text-align: center; text-align: center;
} }
.service-card-buttons { .service-card-buttons {
flex-shrink: 0;
margin-top: auto;
/deep/ .t-button { /deep/ .t-button {
width: 100%; width: 100%;
height: @qych-landing-card-btn-h; height: @qych-landing-card-btn-h;
@ -668,18 +750,6 @@ body {
box-shadow: none; box-shadow: none;
} }
.text-section-head-row {
display: grid;
grid-template-columns: minmax(0, 1fr) @qych-policy-sidebar-width;
column-gap: @qych-policy-content-gap;
align-items: start;
padding: 0 @qych-policy-content-px;
box-sizing: border-box;
border-top-left-radius: @qych-policy-card-radius;
border-top-right-radius: @qych-policy-card-radius;
overflow: hidden;
}
.text-section-title { .text-section-title {
height: auto; height: auto;
padding: @qych-policy-section-title-py @qych-policy-section-title-px @qych-policy-section-title-pb; padding: @qych-policy-section-title-py @qych-policy-section-title-px @qych-policy-section-title-pb;
@ -689,25 +759,16 @@ body {
line-height: normal; line-height: normal;
letter-spacing: 0; letter-spacing: 0;
color: @qych-policy-label-color; color: @qych-policy-label-color;
background: transparent; border-top-left-radius: @qych-policy-card-radius;
} border-top-right-radius: @qych-policy-card-radius;
.text-section-head-row .text-section-title-dcfa {
align-self: start;
padding: @qych-policy-section-title-py 0 @qych-policy-section-title-pb;
margin: 0;
line-height: normal;
background: transparent;
} }
.text-section-content { .text-section-content {
display: flex; display: flex;
flex: 1 1 auto;
flex-direction: row; flex-direction: row;
align-items: flex-start; align-items: flex-start;
gap: @qych-policy-content-gap; gap: @qych-policy-content-gap;
padding: 0 @qych-policy-content-px; padding: 0 @qych-policy-content-px;
min-height: 0;
background: transparent; background: transparent;
} }
@ -721,8 +782,11 @@ body {
display: flex; display: flex;
flex: 1 1 auto; flex: 1 1 auto;
flex-direction: column; flex-direction: column;
align-self: flex-start;
min-width: 0; min-width: 0;
max-height: 328px; height: @qych-policy-panel-height;
min-height: @qych-policy-panel-height;
max-height: @qych-policy-panel-height;
padding: @qych-policy-panel-padding; padding: @qych-policy-panel-padding;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
@ -735,7 +799,7 @@ body {
display: flex; display: flex;
flex: 0 0 @qych-policy-sidebar-width; flex: 0 0 @qych-policy-sidebar-width;
flex-direction: column; flex-direction: column;
align-self: flex-start; align-self: stretch;
width: @qych-policy-sidebar-width; width: @qych-policy-sidebar-width;
min-width: @qych-policy-sidebar-width; min-width: @qych-policy-sidebar-width;
height: auto; height: auto;
@ -743,13 +807,12 @@ body {
.service-section-dcfa { .service-section-dcfa {
display: flex; display: flex;
flex: 0 0 auto; flex: 1 1 auto;
flex-direction: column; flex-direction: column;
gap: 0; gap: @qych-policy-content-gap;
min-height: 0; min-height: 0;
height: auto; height: 100%;
align-self: flex-start; align-self: stretch;
width: 100%;
padding-left: @qych-policy-panel-padding; padding-left: @qych-policy-panel-padding;
background: @home-color-white; background: @home-color-white;
border-left: 1px solid @qych-policy-panel-bg; border-left: 1px solid @qych-policy-panel-bg;
@ -769,11 +832,10 @@ body {
.dcfa-cards-stack { .dcfa-cards-stack {
display: flex; display: flex;
flex: 0 0 auto; flex: 1 1 auto;
flex-direction: column; flex-direction: column;
gap: 12px; gap: @qych-policy-card-gap;
min-height: 0; min-height: 0;
width: 100%;
padding-left: 0; padding-left: 0;
} }
@ -784,7 +846,7 @@ body {
.apply-service-card { .apply-service-card {
display: flex; display: flex;
flex: 0 0 auto; flex: 1 1 0;
flex-direction: column; flex-direction: column;
height: auto; height: auto;
min-height: 0; min-height: 0;
@ -812,14 +874,14 @@ body {
.card-item2 { .card-item2 {
position: relative; position: relative;
display: flex; display: flex;
flex: 0 0 auto; flex: 1 1 0;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
justify-content: flex-start; justify-content: flex-start;
gap: 6px; gap: 6px;
min-height: 160px; min-height: @qych-policy-card-min-height;
height: auto; height: auto;
padding: 20px @qych-policy-card-padding-x 16px; padding: @qych-policy-card-padding-y @qych-policy-card-padding-x @qych-policy-card-padding-bottom;
border-radius: @qych-policy-card-radius-inner; border-radius: @qych-policy-card-radius-inner;
overflow: hidden; overflow: hidden;
cursor: default; cursor: default;
@ -827,7 +889,7 @@ body {
} }
.card-item--with-action { .card-item--with-action {
padding-top: 20px; padding-top: 24px;
} }
.card-body { .card-body {
@ -918,28 +980,16 @@ body {
min-height: 0; min-height: 0;
} }
#section0 .text-section, #section0 .text-section {
#section1 .text-section.qych-policy-frame, gap: @qych-policy-card-inner-gap-battery;
#section2 .text-section {
gap: @qych-policy-card-inner-gap;
} }
#section0 .text-section-head-row .text-section-title, #section0 .text-section-title {
#section1 .text-section-head-row .text-section-title,
#section2 .text-section-head-row .text-section-title {
padding-top: 16px; padding-top: 16px;
padding-bottom: 16px; padding-bottom: 16px;
}
#section0 .text-section-head-row {
background: @qych-policy-header-gradient-battery; background: @qych-policy-header-gradient-battery;
} }
#section0 .text-section-head-row .text-section-title-dcfa {
padding-top: 16px;
padding-bottom: 16px;
}
#section0 .apply-service-card .card-item1 { #section0 .apply-service-card .card-item1 {
background-image: @qych-policy-card-gradient-battery-1; background-image: @qych-policy-card-gradient-battery-1;
} }
@ -953,7 +1003,7 @@ body {
.banner2 .text-section.qych-policy-frame { .banner2 .text-section.qych-policy-frame {
min-height: @qych-policy-card-height; min-height: @qych-policy-card-height;
height: @qych-policy-card-height; height: @qych-policy-card-height;
gap: @qych-policy-card-inner-gap; gap: @qych-policy-card-inner-gap-battery;
} }
#section1 .text-section.qych-policy-frame .text-section-content, #section1 .text-section.qych-policy-frame .text-section-content,
@ -963,21 +1013,21 @@ body {
min-height: 0; min-height: 0;
} }
#section1 .text-section.qych-policy-frame .text-section-title,
.banner2 .text-section.qych-policy-frame .text-section-title {
padding-top: @qych-policy-section-title-py;
padding-bottom: @qych-policy-section-title-py;
}
#section1 .text-section.qych-policy-frame .apply-service-card h4 { #section1 .text-section.qych-policy-frame .apply-service-card h4 {
margin: 0; margin: 0;
} }
#section1 .text-section-head-row, #section1 .text-section.qych-policy-frame .text-section-title,
.banner2 .text-section-head-row { .banner2 .text-section.qych-policy-frame .text-section-title {
background: @qych-policy-header-gradient-cbam; background: @qych-policy-header-gradient-cbam;
} }
#section1 .text-section-head-row .text-section-title-dcfa,
.banner2 .text-section-head-row .text-section-title-dcfa {
padding-top: @qych-policy-section-title-py;
padding-bottom: @qych-policy-section-title-py;
}
#section1 .apply-service-card .card-item1, #section1 .apply-service-card .card-item1,
.banner2 .apply-service-card .card-item1 { .banner2 .apply-service-card .card-item1 {
background-image: @qych-policy-card-gradient-cbam-1; background-image: @qych-policy-card-gradient-cbam-1;
@ -1002,17 +1052,11 @@ body {
align-items: flex-start; align-items: flex-start;
} }
#section2 .text-section-head-row, #section2 .text-section-title,
.banner3 .text-section-head-row { .banner3 .text-section-title {
background: @qych-policy-header-gradient-shipping; background: @qych-policy-header-gradient-shipping;
} }
#section2 .text-section-head-row .text-section-title-dcfa,
.banner3 .text-section-head-row .text-section-title-dcfa {
padding-top: @qych-policy-section-title-py;
padding-bottom: @qych-policy-section-title-py;
}
#section2 .apply-service-card .card-item1, #section2 .apply-service-card .card-item1,
.banner3 .apply-service-card .card-item1 { .banner3 .apply-service-card .card-item1 {
background-image: @qych-policy-card-gradient-shipping-1; background-image: @qych-policy-card-gradient-shipping-1;
@ -1025,7 +1069,7 @@ body {
#section2 .apply-service-card .card-item1, #section2 .apply-service-card .card-item1,
#section2 .apply-service-card .card-item2 { #section2 .apply-service-card .card-item2 {
padding-top: 20px; padding-top: 24px;
} }
.banner1.qych-snap-section { .banner1.qych-snap-section {
@ -1288,77 +1332,16 @@ body {
text-align: center; text-align: center;
} }
@media (max-width: 1200px) { @media (max-width: 1400px) {
.qych-snap-section.qych-landing { .qych-landing .services-section .services-grid {
min-height: auto; grid-template-columns: repeat(2, minmax(0, 1fr));
}
.qych-landing .services-section {
--portal-service-card-min-height: auto;
.portal-landing-card-shell-reset();
}
#anchor-container .banner.qych-snap-section .text-section-head-row {
grid-template-columns: minmax(0, 1fr) 260px;
}
#anchor-container .banner.qych-snap-section .content-item2 {
flex: 0 0 260px;
width: 260px;
min-width: 260px;
} }
} }
@media (max-width: 1024px) { @media (max-width: 1200px) {
#section0 .text-section, .qych-landing .services-section {
#section1 .text-section.qych-policy-frame, padding-top: 40px;
#section2 .text-section { padding-bottom: 60px;
height: auto;
min-height: 0;
overflow: visible;
}
#anchor-container .banner.qych-snap-section .text-section {
overflow: visible;
}
#anchor-container .banner.qych-snap-section .text-section-head-row {
grid-template-columns: 1fr;
row-gap: 4px;
}
#anchor-container .banner.qych-snap-section .text-section-content {
flex-direction: column;
align-items: stretch;
flex: none;
min-height: 0;
}
#anchor-container .banner.qych-snap-section .content-item1 {
flex: none;
width: 100%;
height: auto;
min-height: 200px;
max-height: 360px;
}
#anchor-container .banner.qych-snap-section .content-item2 {
display: flex;
flex: none;
width: 100%;
min-width: 0;
}
#anchor-container .banner.qych-snap-section .service-section-dcfa {
width: 100%;
padding-left: 0;
border-left: none;
background: transparent;
}
#anchor-container .banner.qych-snap-section .card-item1,
#anchor-container .banner.qych-snap-section .card-item2 {
min-height: 120px;
} }
} }
@ -1378,13 +1361,18 @@ body {
} }
.qych-landing .services-section { .qych-landing .services-section {
.portal-landing-card-shell-reset(); margin-top: -60px;
padding: 40px var(--page-gutter-x, 20px) 60px;
} }
.qych-landing .services-section .services-grid { .qych-landing .services-section .services-grid {
grid-template-columns: 1fr; grid-template-columns: 1fr;
gap: 16px; gap: 16px;
} }
.qych-landing .services-section .service-card-inner {
min-height: auto;
}
} }
@media (max-width: 768px) { @media (max-width: 768px) {
@ -1393,6 +1381,10 @@ body {
padding-bottom: 16px; padding-bottom: 16px;
} }
.qych-landing .services-section {
padding: 24px var(--page-gutter-x, 16px) 40px;
}
.qych-landing .services-section .service-card-inner { .qych-landing .services-section .service-card-inner {
padding: 20px; padding: 20px;
} }
@ -1403,6 +1395,7 @@ body {
.qych-landing .services-section .service-card-desc { .qych-landing .services-section .service-card-desc {
font-size: 14px; font-size: 14px;
min-height: auto;
} }
} }
</style> </style>