feat:修复移动端适配的部分问题

This commit is contained in:
liulong 2026-05-26 18:01:25 +08:00
parent 34c7cc4393
commit b7af8a9ce7
21 changed files with 527 additions and 136 deletions

View File

@ -1,4 +1,5 @@
<template>
<div class="portal-footer-shell">
<footer class="site-footer">
<div class="footer-main">
<div class="footer-main-inner">
@ -74,6 +75,7 @@
</div>
</div>
</footer>
</div>
</template>
<script>
@ -88,6 +90,13 @@ export default {
</script>
<style lang="less" scoped>
/* 门户统一页脚外壳(由 Main 布局固定在滚动区底部) */
.portal-footer-shell {
flex-shrink: 0;
width: 100%;
background: var(--page-footer-bg, #f0f7f2);
}
/* Figma 底部信息块:主区 #f0f7f2 padding 40/20/20版权条 #e2ede5 高 64px */
.site-footer {
display: block;

View File

@ -1,6 +1,10 @@
<template>
<!-- 顶部菜单栏 -->
<div v-show="!isIframeEmbedded" class="nav-box">
<div
v-show="!isIframeEmbedded"
class="nav-box"
:class="{ 'nav-box--mobile-menu-open': mobileMenuOpen }"
>
<div class="nav-inner page-nav-inner">
<div class="logo-box" @click="goHome">
<span class="logo-mark">
@ -125,7 +129,6 @@
<div class="mobile-auth-btn logout" @click="logoutHandler">退出登录</div>
</div>
<div v-else class="mobile-auth-btns">
<div class="mobile-auth-btn activate">激活</div>
<div class="mobile-auth-btn login" @click="gologin">登录</div>
</div>
</div>
@ -744,6 +747,12 @@ export default {
cursor: not-allowed !important;
}
/* 抽屉已有关闭钮时,隐藏顶部汉堡(避免与 header × 叠成两个叉) */
.nav-box--mobile-menu-open .hamburger-btn {
visibility: hidden;
pointer-events: none;
}
/* 汉堡菜单按钮 */
.hamburger-btn {
display: none;
@ -984,11 +993,6 @@ export default {
flex: 1;
}
.mobile-auth-btn.activate {
color: #333;
background: #f0f0f0;
}
.mobile-auth-btn.logout {
color: #666;
background: #fff;

View File

@ -29,6 +29,10 @@
box-sizing: border-box;
}
.content-wrap--portal {
background: #f6f7fa;
}
.page-content-wrap,
.page-nav-inner {
box-sizing: border-box;
@ -344,7 +348,9 @@
.fwsc-page .banner-section,
.fwsc-page .fwsc-main,
.fwsc-container .fwsc-main,
.fwsc-container .secondary-nav-content {
.fwsc-container .secondary-nav-content,
.xqsc-container .xqsc-main,
.xqsc-container .secondary-nav-content {
max-width: 100%;
overflow-x: hidden;
box-sizing: border-box;
@ -365,7 +371,9 @@
.fwsc-page .card-actions span,
.fwsc-container .nav-tab,
.fwsc-container .publish-btn,
.fwsc-container .card-actions span {
.fwsc-container .card-actions span,
.xqsc-container .nav-tab,
.xqsc-container .publish-btn {
min-height: 48px;
display: inline-flex;
align-items: center;

View File

@ -138,3 +138,56 @@
margin-left: calc(50% - 50vw);
margin-right: calc(50% - 50vw);
}
// =============================================================================
// 门户内页:唯一滚动容器为 .content-wrap页脚为滚动内容最后一项
// =============================================================================
@media screen and (min-width: 768px) {
html,
body {
height: 100%;
overflow: hidden;
}
#app,
.portal-app-root {
height: 100%;
overflow: hidden;
}
}
.content-wrap--portal {
background: #f6f7fa;
}
/* 短页:栈高度至少铺满滚动区,页脚贴底;长页:随内容增高,不在页脚后留白 */
.portal-page-stack {
display: flex;
flex-direction: column;
box-sizing: border-box;
width: 100%;
min-height: 100%;
}
.portal-page-stack .portal-route-outlet {
flex: 1 1 auto;
width: 100%;
min-height: auto;
}
.portal-page-stack .portal-layout-footer {
flex-shrink: 0;
width: 100%;
}
.portal-route-outlet-wrap {
width: 100%;
min-height: 100%;
}
.portal-page-shell {
display: block;
box-sizing: border-box;
width: 100%;
}

View File

@ -1,5 +1,5 @@
<template>
<div class="fwsc-container fwsc-page">
<div class="fwsc-container fwsc-page portal-page-shell">
<!-- 面包屑导航 -->
<!-- <BreadcrumbNav currentPage="碳服务市场" /> -->
@ -139,8 +139,6 @@
</div>
</main>
<Footer />
<!-- 发布服务抽屉 -->
<FwscPublish :visible.sync="publishVisible" @success="onPublishSuccess" />
@ -175,7 +173,6 @@
<script>
import { LocationIcon, SearchIcon } from 'tdesign-icons-vue';
import NewNav from '@/pages/index/components/new-nav/index.vue';
import Footer from '@/pages/index/components/footer/index.vue';
import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue';
import FwscPublish from './components/FwscPublish.vue';
import api from '@/pages/index/api/fwsc/index.js';
@ -186,7 +183,6 @@ export default {
name: 'FwscPage',
components: {
NewNav,
Footer,
BreadcrumbNav,
FwscPublish,
LocationIcon,
@ -491,7 +487,6 @@ export default {
<style lang="less" scoped>
.fwsc-container {
min-height: 100vh;
background: #f5f5f5;
}

View File

@ -1,5 +1,5 @@
<template>
<div class="fwsc-page">
<div class="fwsc-page portal-page-shell">
<div class="main-content">
<!-- 当前位置导航 -->
<!-- <div class="breadcrumb-box">
@ -89,19 +89,16 @@
</div>
</div>
<Footer />
</div>
</template>
<script>
import NewNav from '@/pages/index/components/new-nav/index.vue';
import Footer from '@/pages/index/components/footer/index.vue';
export default {
name: 'FwscIndex',
components: {
NewNav,
Footer
},
methods: {
goHome() {
@ -120,7 +117,6 @@ export default {
<style lang="less" scoped>
.fwsc-page {
min-height: 100vh;
background: #f5f7fa;
}

View File

@ -1,5 +1,5 @@
<template>
<div class="jrsc-page">
<div class="jrsc-page portal-page-shell">
<!-- 面包屑导航 -->
<!-- <BreadcrumbNav currentPage="碳金融市场" /> -->
@ -193,7 +193,6 @@
</div>
</main>
<Footer />
<!-- 产品详情弹窗 -->
<t-dialog
@ -326,14 +325,12 @@
<script>
import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue';
import Footer from '@/pages/index/components/footer/index.vue';
import api from '@/pages/index/api/fwsc/index.js';
export default {
name: 'JrscPage',
components: {
BreadcrumbNav,
Footer,
},
data() {
return {
@ -617,7 +614,6 @@ export default {
@bg-white: #fff;
.jrsc-page {
min-height: 100vh;
background: @bg-gray;
animation: fadeIn 0.3s ease;
}

View File

@ -1,5 +1,5 @@
<template>
<div class="sjlbc-page">
<div class="sjlbc-page portal-page-shell">
<!-- 面包屑导航 -->
<div class="breadcrumb-box">
<span class="breadcrumb-link" @click="$router.push('/view/mhzc/home')">首页</span>
@ -31,11 +31,10 @@
<div class="data-list">
<t-table
:data="sortedDataList"
:pagination="paginationConfig"
:pagination="null"
row-key="uuid"
hover
:columns="tableColumns"
@page-change="handlePageChange"
>
<template #td-type="{ row }">
<span class="type-tag" :class="row.type === '公共数据' ? 'tag-green' : 'tag-blue'">
@ -58,6 +57,20 @@
<t-button size="small" theme="primary" variant="outline" @click="showContactDialog(row)">获取联系方式</t-button>
</template>
</t-table>
<div v-if="pagination.total > 0" class="sjlbc-pagination">
<div class="sjlbc-pagination-total"> {{ pagination.total }} 条数据</div>
<t-pagination
v-model="pagination.pageNo"
:total="pagination.total"
:page-size.sync="pagination.pageSize"
:total-content="false"
:show-jumper="!isMobile"
:show-page-size="!isMobile"
:page-size-options="[10, 20, 30, 50]"
align="center"
@change="handlePaginationChange"
/>
</div>
</div>
</div>
@ -88,22 +101,19 @@
</div>
</t-dialog>
<!-- 底部 -->
<Footer />
</div>
</template>
<script>
import NewNav from '@/pages/index/components/new-nav/index.vue';
import Footer from '@/pages/index/components/footer/index.vue';
import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue';
import gxzxApi from '@/pages/index/api/gxzx/index.js';
import { isMobileViewport, watchDeviceClass } from '@/pages/index/utils/breakpoint';
export default {
name: 'SjlbcPage',
components: {
NewNav,
Footer,
BreadcrumbNav,
},
data() {
@ -155,19 +165,25 @@ export default {
title: '联系方式',
},
],
paginationConfig: {
current: 1,
pageSize: 10,
total: 0,
showJumper: true,
},
isMobile: false,
unwatchDevice: null,
};
},
mounted() {
this.isMobile = isMobileViewport();
this.unwatchDevice = watchDeviceClass(() => {
this.isMobile = isMobileViewport();
});
this.sjscUuid = this.$route.query.id || '';
this.loadSjscInfo();
this.loadData();
},
beforeDestroy() {
if (this.unwatchDevice) {
this.unwatchDevice();
this.unwatchDevice = null;
}
},
computed: {
totalPages() {
return Math.ceil(this.pagination.total / this.pagination.pageSize) || 1;
@ -244,9 +260,6 @@ export default {
jgDw: item.jgDw
}));
this.pagination.total = Number(res.data.total);
this.paginationConfig.total = Number(res.data.total);
this.paginationConfig.current = this.pagination.pageNo;
this.paginationConfig.pageSize = this.pagination.pageSize;
}
});
},
@ -280,7 +293,7 @@ export default {
this.contactDialogVisible = true;
});
},
handlePageChange(pageInfo) {
handlePaginationChange(pageInfo) {
this.pagination.pageNo = pageInfo.current;
this.pagination.pageSize = pageInfo.pageSize;
this.loadData();
@ -291,7 +304,6 @@ export default {
<style lang="less" scoped>
.sjlbc-page {
min-height: 100vh;
background: #f5f5f5;
}
@ -487,4 +499,119 @@ export default {
overflow-x: auto;
}
}
// hydt / xqsc
.sjlbc-pagination {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 20px 16px 24px;
border-top: 1px solid #f0f0f0;
}
.sjlbc-pagination-total {
flex: 0 0 auto;
font-size: 14px;
line-height: 22px;
color: #666;
white-space: nowrap;
}
.sjlbc-pagination ::v-deep .t-pagination {
flex: 1 1 auto;
justify-content: flex-end;
}
@media (max-width: 768px) {
.sjlbc-pagination {
flex-direction: column;
align-items: stretch;
gap: 12px;
padding: 16px 12px 28px;
}
.sjlbc-pagination-total {
width: 100%;
text-align: center;
font-size: 14px;
}
.sjlbc-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%;
row-gap: 12px;
column-gap: 8px;
}
.sjlbc-pagination ::v-deep .t-pagination__total {
display: none;
}
.sjlbc-pagination ::v-deep .t-pagination__btn-prev {
order: 1;
}
.sjlbc-pagination ::v-deep .t-pagination__pager {
order: 2;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 6px;
max-width: 100%;
}
.sjlbc-pagination ::v-deep .t-pagination__btn-next {
order: 3;
}
.sjlbc-pagination ::v-deep .t-pagination__jump {
display: none !important;
}
@sjlbc-mob-pagination-h: 36px;
.sjlbc-pagination ::v-deep .t-pagination__number {
min-width: @sjlbc-mob-pagination-h;
height: @sjlbc-mob-pagination-h;
line-height: @sjlbc-mob-pagination-h;
margin: 0;
box-sizing: border-box;
}
.sjlbc-pagination ::v-deep .t-pagination__btn {
min-width: @sjlbc-mob-pagination-h;
width: @sjlbc-mob-pagination-h;
height: @sjlbc-mob-pagination-h;
line-height: @sjlbc-mob-pagination-h;
}
}
@media (max-width: 480px) {
.sjlbc-pagination {
padding-bottom: 32px;
}
@sjlbc-mob-pagination-h-sm: 32px;
.sjlbc-pagination ::v-deep .t-pagination__number {
min-width: @sjlbc-mob-pagination-h-sm;
height: @sjlbc-mob-pagination-h-sm;
line-height: @sjlbc-mob-pagination-h-sm;
font-size: 14px;
}
.sjlbc-pagination ::v-deep .t-pagination__btn {
min-width: @sjlbc-mob-pagination-h-sm;
width: @sjlbc-mob-pagination-h-sm;
height: @sjlbc-mob-pagination-h-sm;
line-height: @sjlbc-mob-pagination-h-sm;
}
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<div class="sjsc-page">
<div class="sjsc-page portal-page-shell">
<div>
<!-- 面包屑导航 -->
<!-- <BreadcrumbNav currentPage="碳数据市场" /> -->
@ -85,13 +85,11 @@
</div>
</div>
<Footer />
</div>
</template>
<script>
import NewNav from '@/pages/index/components/new-nav/index.vue';
import Footer from '@/pages/index/components/footer/index.vue';
import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue';
import gxzxApi from '@/pages/index/api/gxzx/index.js';
@ -99,7 +97,6 @@ export default {
name: 'SjscPage',
components: {
NewNav,
Footer,
BreadcrumbNav,
},
data() {

View File

@ -1,5 +1,5 @@
<template>
<div class="xqsc-container">
<div class="xqsc-container portal-page-shell">
<!-- 面包屑导航 -->
<!-- <BreadcrumbNav currentPage="碳需求市场" /> -->
@ -143,8 +143,6 @@
</div>
</main>
<Footer />
<!-- 发布需求抽屉 -->
<XqscPublish
:visible.sync="publishVisible"
@ -205,7 +203,6 @@
<script>
import { SearchIcon } from 'tdesign-icons-vue';
import NewNav from '@/pages/index/components/new-nav/index.vue';
import Footer from '@/pages/index/components/footer/index.vue';
import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue';
import XqscPublish from './components/XqscPublish.vue';
import api from '@/pages/index/api/fwsc/index.js';
@ -215,7 +212,6 @@ export default {
name: 'XqscPage',
components: {
NewNav,
Footer,
BreadcrumbNav,
XqscPublish,
SearchIcon,
@ -452,7 +448,6 @@ export default {
<style lang="less" scoped>
.xqsc-container {
min-height: 100vh;
background: #f5f5f5;
}
@ -960,32 +955,83 @@ export default {
}
@media (max-width: 768px) {
.xqsc-container {
overflow-x: hidden;
}
.xqsc-main {
padding: 12px;
box-sizing: border-box;
}
.secondary-nav-content {
flex-direction: column;
align-items: stretch;
padding: 12px 16px;
gap: 12px;
box-sizing: border-box;
}
.nav-tabs {
display: flex;
flex-wrap: nowrap;
align-items: center;
width: 100%;
max-width: 100%;
height: auto;
min-height: 42px;
padding-bottom: 4px;
overflow-x: auto;
gap: 4px;
overflow-y: hidden;
gap: 8px;
scrollbar-width: none;
-webkit-overflow-scrolling: touch;
&::-webkit-scrollbar {
display: none;
width: 0;
height: 0;
}
}
.nav-tab {
flex-shrink: 0;
display: inline-flex;
align-items: center;
justify-content: center;
height: auto;
min-height: 40px;
padding: 10px 12px;
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;
}
.publish-btn {
width: 100%;
padding: 10px;
height: auto;
min-height: 44px;
padding: 10px 16px;
font-size: 15px;
line-height: 1.3;
box-sizing: border-box;
}
.content-area {

View File

@ -1,5 +1,5 @@
<template>
<div class="gxnlpt-page portal-page">
<div class="gxnlpt-page portal-page portal-page-shell">
<div
class="gxnlpt-shell page-content-wrap"
:class="{ 'gxnlpt-shell--stacked': stackedNavLayout }"
@ -230,12 +230,10 @@
</main>
</div>
</div>
<Footer />
</div>
</template>
<script>
import Footer from '@/pages/index/components/footer/index.vue';
import GxnlptCardTags from '@/pages/index/views/gxnlpt/components/GxnlptCardTags.vue';
import api from '@/pages/index/api/fwsc/index.js';
import {
@ -433,7 +431,7 @@ const SUBMIT_FORM_EMPTY = () => ({
export default {
name: 'GxnlptIndex',
components: { Footer, GxnlptCardTags },
components: { GxnlptCardTags },
data() {
return {
starOutline,

View File

@ -36,10 +36,14 @@
搜索
</div>
</div>
<div class="top-search-hot">
<div class="top-search-hot" v-if="hotSearchTags.length > 0">
<div class="hot-label">热门搜索: </div>
<div class="hot-tag" v-for="(tag, index) in hotSearchTags" :key="index" @click="handleHotSearch(tag)">{{
tag }}</div>
<div
class="hot-tag"
v-for="(tag, index) in hotSearchTags"
:key="index"
@click="handleHotSearch(tag)"
>{{ tag }}</div>
</div>
</div>
@ -332,6 +336,7 @@
import Footer from '@/pages/index/components/footer/index.vue';
import hydtApi from '@/pages/index/api/hydt';
import gxzxApi from '@/pages/index/api/gxzx/index.js';
import searchApi from '@/pages/index/api/search.js';
import { bindSectionWheelScroll } from '@/pages/index/utils/portal-scroll-mode';
export default {
@ -399,7 +404,7 @@ export default {
iconHeight: 183
}
],
hotSearchTags: ['电厂配额', '林业碳汇开发', 'CBAM 报告', '2025年度碳报告', '光伏发展'],
hotSearchTags: [],
//
overseas2List: [
{
@ -492,6 +497,7 @@ export default {
this.syncNewsTabFromRoute(this.$route.query.type);
this.syncBannerHeight();
window.addEventListener('resize', this.syncBannerHeight);
this.loadHotSearch();
this.fetchNewsData();
this.getTfwzxUrl();
this.$nextTick(() => {
@ -720,9 +726,19 @@ export default {
this.$router.push({ path: '/search', query: { keyword: this.inputValue } });
}
},
async loadHotSearch() {
try {
const res = await searchApi.getHotSearch();
if (res && res.data) {
this.hotSearchTags = res.data;
}
} catch (error) {
console.error('加载热门搜索失败', error);
}
},
//
handleHotSearch(keyword) {
this.$router.push({ path: '/search', query: { keyword: keyword } });
this.$router.push({ path: '/search', query: { keyword } });
},
//
handleOverseasClick(item) {

View File

@ -1,5 +1,5 @@
<template>
<div class="hydt-page portal-page">
<div class="hydt-page portal-page portal-page-shell">
<!-- Figma banner-bg 150622:19115背景 imageRef ec2e3dd -->
<section class="hydt-banner" aria-label="行业动态">
<div class="hydt-banner-bg" aria-hidden="true"></div>
@ -81,12 +81,10 @@
</div>
</section>
<Footer />
</div>
</template>
<script>
import Footer from '@/pages/index/components/footer/index.vue';
import hydtApi from '@/pages/index/api/hydt/index.js';
const NEWS_TABS = [
@ -97,7 +95,7 @@ const NEWS_TABS = [
export default {
name: 'HydtIndex',
components: { Footer },
components: {},
data() {
return {
newsTabs: NEWS_TABS,

View File

@ -1,5 +1,5 @@
<template>
<div class="hyzt-wrap">
<div class="hyzt-wrap portal-page-shell">
<!-- Figma 150581:4101 banner-bg / 150679:365 hyzt_banner 1 -->
<section class="banner-section" aria-label="行业专题">
<div class="banner-bg" aria-hidden="true"></div>
@ -34,19 +34,15 @@
</div>
</div>
<Footer />
</div>
</template>
<script>
import { mapState } from 'vuex';
import Footer from '@/pages/index/components/footer/index.vue';
export default {
name: 'hyzt',
components: {
Footer,
},
components: {},
data() {
return {
headerClassList: ['blue-header', 'green-header', 'purple-header'],
@ -74,7 +70,6 @@ export default {
@import '../../styles/home-figma-variables.less';
.hyzt-wrap {
min-height: 100%;
background: #f6f7fa;
}

View File

@ -203,4 +203,14 @@
.copyright {
display: none;
}
}
@media screen and (max-width: 768px) {
.item-container {
width: 100%;
max-width: 100%;
margin-right: 0;
margin-left: 0;
box-sizing: border-box;
}
}

View File

@ -27,10 +27,10 @@
<div class="login-content">
<t-tabs class="loginTabs" v-model="loginTab" size="large">
<t-tab-panel value="account" label="账号登录" :destroyOnHide="false">
<login v-if="type === 'login'" />
<zhuce v-if="type === 'created'" @zhucecg="typechange" />
<login />
</t-tab-panel>
<t-tab-panel v-if="MH_REGISTRATION_ENABLED" value="register" label="注册" :destroyOnHide="false">
<zhuce @zhucecg="onRegisterSuccess" />
</t-tab-panel>
<t-tab-panel value="qrcode" label="扫码登录" :destroyOnHide="false">
<div class="qrcode-login">
@ -112,7 +112,10 @@ export default {
},
countDown: 0,
captchaVerification:'',
intervalTimer: null,
intervalTimer: null,
pollTimer: null,
pollStopped: false,
pollToken: 0,
};
},
computed: {
@ -125,10 +128,37 @@ export default {
mounted() {
this.Getqrcode();
},
beforeDestroy() {
deactivated() {
this.stopPollLogin();
},
beforeDestroy() {
this.stopPollLogin();
clearInterval(this.intervalTimer);
this.intervalTimer = null;
},
beforeRouteLeave(to, from, next) {
this.stopPollLogin();
next();
},
methods: {
stopPollLogin() {
this.pollStopped = true;
this.pollToken += 1;
if (this.pollTimer) {
clearTimeout(this.pollTimer);
this.pollTimer = null;
}
},
schedulePollLogin(delay = 2000) {
if (this.pollStopped) return;
if (this.pollTimer) {
clearTimeout(this.pollTimer);
}
this.pollTimer = setTimeout(() => {
this.pollTimer = null;
this.pollLoginResult();
}, delay);
},
clearQRCode() {
// PC
if (this.$refs.qrcodePC) {
@ -193,6 +223,7 @@ export default {
this.delVisible=false;
this.form.sjhm='';
this.form.sms='';
this.pollStopped = false;
this.pollLoginResult();
},
async didBindPhone() {
@ -234,48 +265,52 @@ export default {
console.log('res', data);
} catch (error) {
console.error('数据加载失败', error);
}finally{
this.pollLoginResult();
} finally {
if (!this.pollStopped) {
this.pollLoginResult();
}
}
},
async pollLoginResult() {
try {
const { data } = await backresultlogin(this.reqId);
if (data.status == 3) {
//
// return
window.sessionStorage.setItem('sfdl', true);
window.location.href = `/view/mhzc/home`;
return; //
} else if (data.status == 4) {
//
console.log('登录状态为4停止轮询');
//
getVerify().then((res) => {
this.captchaVerification = res.data;
this.delVisible=true;
});
return; //
} else {
//
setTimeout(() => {
this.pollLoginResult();
}, 2000); // 2
if (this.pollStopped) return;
const token = this.pollToken;
try {
const { data } = await backresultlogin(this.reqId);
if (this.pollStopped || token !== this.pollToken) return;
if (data.status == 3) {
this.stopPollLogin();
window.sessionStorage.setItem('sfdl', true);
window.location.href = `/view/mhzc/home`;
return;
}
if (data.status == 4) {
this.stopPollLogin();
getVerify().then((res) => {
if (this.pollStopped) return;
this.captchaVerification = res.data;
this.delVisible = true;
});
return;
}
this.schedulePollLogin(2000);
} catch (error) {
console.error('数据加载失败', error);
if (token === this.pollToken && !this.pollStopped) {
this.schedulePollLogin(1500);
}
}
} catch (error) {
console.error('数据加载失败', error);
//
//
setTimeout(() => {
this.pollLoginResult();
}, 1500);
}
},
},
typechange(value) {
if (value) {
this.type = 'login';
}
},
onRegisterSuccess(value) {
if (value) {
this.type = 'login';
this.loginTab = 'account';
}
},
generateQRCode() {
try {
@ -484,7 +519,86 @@ export default {
}
.login-content {
width: 100%;
max-width: 100%;
box-sizing: border-box;
}
.mobile-layout ::v-deep .loginTabs {
width: 100%;
.t-tabs__nav-wrap {
width: 100%;
}
.t-tabs__nav-item {
padding: 0 10px;
font-size: 14px;
}
.t-tabs__content {
width: 100%;
padding: 12px 0 0;
box-sizing: border-box;
}
}
.mobile-layout ::v-deep .field {
width: 100%;
margin-top: 16px;
box-sizing: border-box;
}
.mobile-layout ::v-deep .item-container,
.mobile-layout ::v-deep form.login-box {
width: 100% !important;
max-width: 100%;
margin: 0 !important;
transform: none !important;
box-sizing: border-box;
}
.mobile-layout ::v-deep .t-form,
.mobile-layout ::v-deep .t-form__item,
.mobile-layout ::v-deep .t-form__controls,
.mobile-layout ::v-deep .t-form__controls-content {
width: 100%;
max-width: 100%;
box-sizing: border-box;
}
.mobile-layout ::v-deep .t-input__wrap,
.mobile-layout ::v-deep .t-input {
width: 100% !important;
max-width: 100%;
box-sizing: border-box;
}
.mobile-layout ::v-deep .captcha-wrapper {
display: flex;
align-items: center;
gap: 8px;
width: 100% !important;
max-width: 100%;
height: auto;
box-sizing: border-box;
}
.mobile-layout ::v-deep .captcha-wrapper .t-input__wrap {
flex: 1;
min-width: 0;
width: auto !important;
}
.mobile-layout ::v-deep .captcha-img {
flex-shrink: 0;
width: 100px;
height: 40px;
}
.mobile-layout ::v-deep .btn-container {
width: 100%;
margin-top: 16px;
}
.qrcode-login {

View File

@ -2,17 +2,21 @@
<div>
<Nav @gotoIfreamPage="gotoIfreamPage" @gotoPage="gotoPage" />
<div ref="contentWrap" class="content-wrap" :class="contentWrapClass" :style="contentWrapStyle">
<!-- <iframe v-if="iframeUrl" :src="iframeUrl" width="100%" height="100%" frameborder="0" scrolling="yes">
</iframe> -->
<keep-alive>
<router-view @gotoIfreamPage="gotoIfreamPage" @gotoPage="gotoPage" />
</keep-alive>
<div :class="showPortalFooter ? 'portal-page-stack' : 'portal-route-outlet-wrap'">
<div class="portal-route-outlet">
<keep-alive :exclude="keepAliveExclude">
<router-view @gotoIfreamPage="gotoIfreamPage" @gotoPage="gotoPage" />
</keep-alive>
</div>
<Footer v-if="showPortalFooter" class="portal-layout-footer" />
</div>
</div>
</div>
</template>
<script>
import Nav from "@/pages/index/components/nav/index2.vue";
import Footer from "@/pages/index/components/footer/index.vue";
import { hasLogin } from "@/pages/index/api/login";
import { isMobileViewport } from "@/pages/index/utils/breakpoint";
@ -23,10 +27,13 @@ export default {
iframeUrl: '',
documentClientHeight: 100,
isMobileViewport: false,
//
keepAliveExclude: ['LoginIndex'],
};
},
components: {
Nav,
Footer,
},
watch: {
$route() {
@ -38,10 +45,17 @@ export default {
isHomePage() {
return (this.$route.path === '/home' || this.$route.path === '/') && !this.iframeUrl;
},
isLoginPage() {
return this.$route.path === '/login' || this.$route.name === 'login';
},
showPortalFooter() {
return !this.isHomePage && !this.isLoginPage;
},
contentWrapClass() {
return {
'content-wrap--mobile': this.isMobileViewport,
'content-wrap--home': this.isHomePage,
'content-wrap--portal': !this.isHomePage && !this.isLoginPage,
};
},
contentWrapStyle() {
@ -177,12 +191,17 @@ export default {
scrollbar-width: none;
-ms-overflow-style: none;
box-sizing: border-box;
overscroll-behavior-y: contain;
}
.content-wrap--portal {
overscroll-behavior-y: contain;
}
.content-wrap--mobile {
position: relative;
-webkit-overflow-scrolling: touch;
overscroll-behavior-y: auto;
overscroll-behavior-y: contain;
}
.content-wrap::-webkit-scrollbar {

View File

@ -1,5 +1,5 @@
<template>
<div class="compliance-portal">
<div class="compliance-portal portal-page-shell">
<!-- 首屏标题区 + 三大专题入口 -->
<div id="section-landing" class="qych-snap-section qych-landing">
<div class="banner-section">
@ -264,21 +264,16 @@
</div>
</div>
</main>
<Footer />
</div>
</template>
<script>
import Footer from '@/pages/index/components/footer/index.vue'
import serviceCardIcon1 from '../../assets/qych/service-card-icon-1.png'
import serviceCardIcon2 from '../../assets/qych/service-card-icon-2.png'
export default {
name: 'CompliancePortal',
components: {
Footer,
},
components: {},
data() {
return {
serviceCardIcon1,
@ -310,7 +305,7 @@ export default {
{
cardTitle: '航运燃料',
cardDesc: 'LNG、绿甲醇、绿氨等多元低碳燃料转型政策与系统入口。',
btnText: '进入交易大厅',
btnText: '进入专题',
headerClass: 'purple-header',
sectionId: 'section2',
index: 2,
@ -443,6 +438,21 @@ export default {
if (!scrollRoot) return;
const direction = e.deltaY > 0 ? 1 : -1;
const maxScrollTop = scrollRoot.scrollHeight - scrollRoot.clientHeight;
const atBottom = maxScrollTop <= 0 || scrollRoot.scrollTop >= maxScrollTop - 12;
const atTop = scrollRoot.scrollTop <= 12;
//
if ((direction > 0 && atBottom) || (direction < 0 && atTop)) {
return;
}
const lastSectionEl = document.getElementById('section2');
if (lastSectionEl) {
const lastBottom = this.getSectionScrollTop(lastSectionEl, scrollRoot) + lastSectionEl.offsetHeight;
if (scrollRoot.scrollTop + scrollRoot.clientHeight * 0.35 > lastBottom) {
return;
}
}
const currentIndex = this.getCurrentSectionIndex(scrollRoot);
const currentEl = document.getElementById(this.sectionIds[currentIndex]);

View File

@ -1,5 +1,5 @@
<template>
<div class="search-page">
<div class="search-page portal-page-shell">
<!-- 搜索区域背景 -->
<div class="search-hero">
<div class="hero-bg-overlay"></div>
@ -157,13 +157,10 @@
</div>
</div>
<!-- 底部版权 -->
<Footer />
</div>
</template>
<script>
import Footer from '@/pages/index/components/footer/index.vue';
import searchApi from '@/pages/index/api/search.js';
export default {
@ -373,7 +370,6 @@ export default {
<style scoped lang="less">
.search-page {
min-height: 100vh;
background-color: #f5f7fa;
}

View File

@ -14,18 +14,16 @@
<div class="text-box">{{zxData.context}}</div>
</div>
</div>
<Footer />
</div>
</template>
<script>
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';
export default {
name: 'HomePage',
components: { Nav, Footer },
components: { Nav },
data() {
return {
type: '国家政策',

View File

@ -107,7 +107,13 @@ public class SearchServiceImpl implements SearchService {
@Override
public List<String> getHotSearchKeywords() {
return Arrays.asList("碳达峰", "碳核查", "ESG", "碳资产管理", "ISO 14067");
return Arrays.asList(
"电厂配额",
"林业碳汇开发",
"CBAM 报告",
"2025年度碳报告",
"光伏发展"
);
}
@Override