txw/txw-mhzc-web/src/pages/index/views/fwsc/sjlbc.vue
liulong 2084a27dec feat(mhzc-web): 入口文案/登录态/深链/混合首页多页调整
首页 home2:
- 「碳数字身份证」卡办证指南改为「开始办证」,点击改为 iframe 跳碳证中心
- 注释掉「共性能力」section 及其在 sectionIds 里的位置
- 顶 hero 第三张卡标题由「绿色服务」改为「绿色低碳服务」
- 「核心底座」文案去掉"基础底座上海枢纽"措辞,简化为「国家区块链网络」
- 「申请服务」openService 改为登录态判断:未登录跳 /view/mhzc/login,已登录 iframe 进碳证中心

服务中心 fwsc:
- 碳金融市场卡按钮「查看金融产品」→「走进绿金平台」,链接到 https://www.unionecredit.com/greenfinance/#/home
- goToPage 增加外链识别(/^https?:\/\// → window.open _blank),同时把按钮 theme 改为 primary 统一三卡样式

数据列表 sjlbc:
- 隐藏「浏览次数」统计块

行业专题 hyzt:
- 三张卡按钮文案硬编码为「进入专题」,不再读 item.btnText / defaultBtnText,绕开部署包数据未刷新的问题

企业出海 qych:
- 深链(?section=section0/1/2)时 v-if 隐藏 landing,配合 sectionIds 响应式 + watch.$route.query.section + activated 钩子
  解决「先跳到首页三卡再滚到目标 section」的闪屏,直接落在目标 section
- 航运燃料/低碳政策「国际航运碳足迹标识认证平台」立即访问改 showComingSoon()
- 引入 comingSoonMixin 修复 this.showComingSoon 未定义导致点击无响应的老 bug
- IMO/海事 一网通办卡改名为「国际海事组织(IMO)」,链接到 https://www.imo.org/en/
- #section2 国际航运碳足迹标识认证平台 h4 加 white-space: nowrap 避免标题换行

设置 settings:
- 行业专题 hyztList 航运燃料 btnText 由「进入交易大厅」改为「进入专题」

页脚 footer:
- 基础设施文案「国家区块链网络基础底座」→「国家区块链网络」

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 00:02:46 +08:00

627 lines
15 KiB
Vue

<template>
<div class="sjlbc-page portal-page-shell portal-market-figma-page">
<div class="portal-figma-scale-viewport">
<div class="portal-figma-scale-stage" ref="figmaStage">
<!-- 面包屑导航 -->
<div class="breadcrumb-box">
<span class="breadcrumb-link" @click="$router.push('/view/mhzc/home')">首页</span>
<span class="breadcrumb-separator">/</span>
<span class="breadcrumb-link" @click="$router.push('/fwsc')">服务中心</span>
<span class="breadcrumb-separator">/</span>
<span class="breadcrumb-link" @click="$router.push('/tsjsc')">碳数据市场</span>
<span class="breadcrumb-separator">/</span>
<span class="breadcrumb-current">{{ sjscInfo && sjscInfo.sjmc || '数据列表' }}</span>
</div>
<!-- 数据市场信息卡片 -->
<div class="sjsc-info-card" v-if="sjscInfo">
<div class="sjsc-info-main">
<h2 class="sjsc-name">{{ sjscInfo.sjmc || '数据市场' }}</h2>
<p class="sjsc-desc">{{ sjscInfo.sjms || '暂无描述' }}</p>
</div>
<div class="sjsc-info-stats" v-if="sjscInfo.llcs">
<!-- <div class="stat-item" v-if="sjscInfo.llcs">
<span class="stat-value">{{ sjscInfo.llcs }}</span>
<span class="stat-label">浏览次数</span>
</div> -->
</div>
</div>
<!-- 主内容区 -->
<div class="content-wrapper">
<!-- 右侧数据列表 -->
<div class="data-list">
<t-table
:data="sortedDataList"
:pagination="null"
row-key="uuid"
hover
:columns="tableColumns"
>
<template #td-type="{ row }">
<span class="type-tag" :class="row.type === '公共数据' ? 'tag-green' : 'tag-blue'">
{{ row.sjbt }}
</span>
</template>
<template #td-name="{ row }">
<span :title="row.name">{{ row.name }}</span>
</template>
<template #td-time="{ row }">
<span>{{ row.updateTime || row.publishTime }}</span>
</template>
<template #td-count="{ row }">
<span>{{ row.dataCount === '0' ? '/' : row.dataCount + '条' }}</span>
</template>
<template #td-desc="{ row }">
<span>{{ row.sjms || '-' }}</span>
</template>
<template #td-downloads="{ row }">
<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>
</div>
</div>
<!-- 联系方式弹窗 -->
<t-dialog
:closeOnOverlayClick="false"
header="联系方式"
:footer="false"
:visible.sync="contactDialogVisible"
width="400px"
>
<div class="contact-dialog-content">
<div v-if="currentContact" class="contact-info">
<div class="contact-item">
<span class="contact-label">联系人:</span>
<span class="contact-value">{{ currentContact.lxr || '-' }}</span>
</div>
<div class="contact-item">
<span class="contact-label">联系电话:</span>
<span class="contact-value">{{ currentContact.lxdh || '-' }}</span>
</div>
<div class="contact-item">
<span class="contact-label">联系邮箱:</span>
<span class="contact-value">{{ currentContact.lxyx || '-' }}</span>
</div>
</div>
<div v-else class="contact-empty">暂无联系方式</div>
</div>
</t-dialog>
</div>
</template>
<script>
import NewNav from '@/pages/index/components/new-nav/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';
import portalFigmaScaleMixin from '@/pages/index/utils/portal-figma-scale-mixin';
export default {
name: 'SjlbcPage',
mixins: [portalFigmaScaleMixin],
components: {
NewNav,
BreadcrumbNav,
},
data() {
return {
currentPageName: '数据列表',
sortField: '',
sortOrder: '',
dataList: [],
pagination: {
pageNo: 1,
pageSize: 10,
total: 0
},
sjscUuid: '',
sjscInfo: null,
// 联系方式弹窗
contactDialogVisible: false,
currentContact: null,
// 表格列配置
tableColumns: [
{
width: '120px',
colKey: 'td-type',
title: '数据类型',
},
{
colKey: 'td-name',
title: '名称',
},
{
colKey: 'td-desc',
title: '描述',
ellipsis: true,
tooltip: { theme: 'light', attachTo: () => document.querySelector('.td-desc-cell') },
},
{
width: '180px',
colKey: 'td-time',
title: '更新时间',
},
{
width: '120px',
colKey: 'td-count',
title: '数据条数',
},
{
width: '120px',
colKey: 'td-downloads',
title: '联系方式',
},
],
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;
},
visiblePages() {
const total = this.totalPages;
const current = this.pagination.pageNo;
const pages = [];
for (let i = Math.max(1, current - 2); i <= Math.min(total, current + 2); i++) {
pages.push(i);
}
return pages;
},
sortedDataList() {
if (!this.sortField) {
return this.dataList;
}
return [...this.dataList].sort((a, b) => {
let valA = a[this.sortField];
let valB = b[this.sortField];
// 如果是时间字段,转换为时间戳比较
if (this.sortField === 'time') {
valA = a.updateTime || a.publishTime;
valB = b.updateTime || b.publishTime;
}
// 移除逗号的数字字符串
if (this.sortField === 'count' || this.sortField === 'views' || this.sortField === 'downloads') {
valA = parseInt(valA.replace(/,/g, ''));
valB = parseInt(valB.replace(/,/g, ''));
}
if (valA < valB) {
return this.sortOrder === 'asc' ? -1 : 1;
}
if (valA > valB) {
return this.sortOrder === 'asc' ? 1 : -1;
}
return 0;
});
},
},
methods: {
loadSjscInfo() {
if (!this.sjscUuid) return;
gxzxApi.getSjsc({ uuid: this.sjscUuid }).then(res => {
if (res && res.data) {
this.sjscInfo = res.data;
}
});
},
loadData() {
const params = {
pageNo: this.pagination.pageNo,
pageSize: this.pagination.pageSize,
sjscUuid: this.sjscUuid,
};
gxzxApi.sjlbbList(params).then(res => {
if (res && res.data && res.data.records) {
this.dataList = res.data.records.map(item => ({
uuid: item.uuid,
name: item.sjmc,
type: item.sjlxDm,
sjbt: item.sjbt,
sjms: item.sjms,
email: item.emial,
publishTime: item.lrrq ? this.formatDate(item.lrrq) : '',
updateTime: item.xgrq ? this.formatDate(item.xgrq) : '',
dataCount: item.sjsl ? item.sjsl.toLocaleString() : '0',
views: item.llcs || 0,
downloads: item.xzcs || 0,
jg: item.jg,
jgDw: item.jgDw
}));
this.pagination.total = Number(res.data.total);
}
});
},
sortBy(field) {
if (this.sortField === field) {
this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc';
} else {
this.sortField = field;
this.sortOrder = 'desc';
}
},
formatDate(dateStr) {
if (!dateStr) return '';
const d = new Date(dateStr);
const year = d.getFullYear();
const month = String(d.getMonth() + 1).padStart(2, '0');
const day = String(d.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
},
showContactDialog(item) {
gxzxApi.getSjlbb({ uuid: item.uuid }).then(res => {
if (res && res.data) {
this.currentContact = {
lxr: res.data.lxr || '-',
lxdh: res.data.lxdh || '-',
lxyx: res.data.email || '-',
};
} else {
this.currentContact = null;
}
this.contactDialogVisible = true;
});
},
handlePaginationChange(pageInfo) {
this.pagination.pageNo = pageInfo.current;
this.pagination.pageSize = pageInfo.pageSize;
this.loadData();
},
},
};
</script>
<style lang="less" scoped>
@import '../../styles/home-figma-variables.less';
.sjlbc-page {
background: #f5f5f5;
.portal-figma-scale-page();
}
// 面包屑导航
.breadcrumb-box {
display: flex;
align-items: center;
width: 83%;
max-width: 1400px;
padding: 20px 20px 0;
margin: 0 auto;
box-sizing: border-box;
}
.breadcrumb-link {
font-size: 14px;
color: #009a29;
cursor: pointer;
transition: color 0.3s;
&:hover {
color: #007a1f;
}
}
.breadcrumb-separator {
margin: 0 8px;
font-size: 14px;
color: #999;
}
.breadcrumb-current {
font-size: 14px;
color: #333;
}
// 数据市场信息卡片
.sjsc-info-card {
display: flex;
align-items: flex-start;
justify-content: space-between;
width: 81%;
max-width: 1400px;
padding: 24px;
margin: 16px auto 0;
background: linear-gradient(135deg, #009a29 0%, #00c853 100%);
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 154, 41, 0.15);
color: #fff;
box-sizing: border-box;
}
.sjsc-info-main {
flex: 1;
}
.sjsc-name {
margin: 0 0 8px;
font-size: 22px;
font-weight: 600;
color: #fff;
}
.sjsc-desc {
margin: 0;
font-size: 14px;
line-height: 1.6;
opacity: 0.9;
}
.sjsc-info-stats {
display: flex;
gap: 32px;
flex-shrink: 0;
}
.stat-item {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.stat-value {
font-size: 24px;
font-weight: 700;
color: #fff;
}
.stat-label {
margin-top: 4px;
font-size: 12px;
opacity: 0.8;
}
@media (max-width: 768px) {
.sjsc-info-card {
flex-direction: column;
gap: 16px;
padding: 20px;
}
.sjsc-info-stats {
gap: 24px;
width: 100%;
justify-content: flex-start;
}
.stat-value {
font-size: 20px;
}
}
// 主内容区
.content-wrapper {
width: 100%;
max-width: 1400px;
padding: 20px;
margin: 0 auto;
box-sizing: border-box;
}
// 右侧数据列表
.data-list {
overflow: hidden;
background: #fff;
border-radius: 8px;
box-sizing: border-box;
}
// 联系方式弹窗样式
.contact-dialog-content {
padding: 16px 0;
}
.contact-info {
display: flex;
flex-direction: column;
gap: 16px;
}
.contact-item {
display: flex;
align-items: center;
.contact-label {
width: 80px;
color: #666;
font-size: 14px;
}
.contact-value {
color: #333;
font-size: 14px;
}
}
.contact-empty {
text-align: center;
color: #999;
padding: 20px 0;
}
// 数据类型标签
.type-tag {
padding: 4px 8px;
font-size: 12px;
border-radius: 4px;
&.tag-green {
color: #2e7d32;
background: #e8f5e9;
}
&.tag-blue {
color: #1565c0;
background: #e3f2fd;
}
}
@media (max-width: 768px) {
.breadcrumb-box {
padding: 12px 12px 0;
}
.content-wrapper {
flex-direction: column;
padding: 12px;
gap: 12px;
}
.data-list {
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>