feat:修复部分页面问题,新增共性能力后端接口

This commit is contained in:
liulong 2026-06-05 00:18:15 +08:00
parent 4d945002ae
commit 63eebcea09
25 changed files with 2744 additions and 207 deletions

14
.gitignore vendored
View File

@ -75,4 +75,16 @@ devops/docker-compose.override.yml
# graphify 临时分析产物(不提交,可随时删除)
**/graphify-out/
.mcp.json
.codex/
.codex/
# Office / WPS 临时锁文件(打开 Excel/Word/PowerPoint 时自动产生)
~$*.xlsx
~$*.xls
~$*.docx
~$*.doc
~$*.pptx
~$*.ppt
# Windows 缩略图缓存
Thumbs.db
Desktop.ini/

View File

@ -134,10 +134,12 @@ export function resetPassword(params) {
});
}
//获取验证码
// 登录页自身调用的公开接口401 时不弹"登录提示"(避免在 /login 路由上自己弹自己导致死循环)
export function Getqrcode() {
return fetchSso({
url: `${basurl}/sso/did/pub/login/qrcode`,
method: 'post',
__silent401: true,
});
}
@ -146,6 +148,7 @@ export function getCaptcha() {
return fetchSso({
url: `${basurl}/sso/verify/captcha`,
method: 'post',
__silent401: true,
});
}
//获取登录回调响应结果
@ -153,6 +156,7 @@ export function backresultlogin(params) {
return fetchSso({
url: `${basurl}/sso/did/pub/backresult/login?reqId=${params}`,
method: 'get',
__silent401: true,
});
}

View File

@ -118,15 +118,22 @@ export default {
.footer-columns {
display: flex;
align-items: flex-start;
/* 优化需求5 列内容均分布局(每列等宽、垂直等高、内容顶部对齐) */
align-items: stretch;
justify-content: space-between;
width: 100%;
gap: 24px;
box-sizing: border-box;
}
.footer-column {
flex: 0 1 auto;
flex: 1 1 0;
min-width: 0;
/* 优化需求:列内整体居中显示(标题+列表与列中心对齐) */
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
}
.footer-title {
@ -167,6 +174,7 @@ export default {
font-weight: 400;
line-height: 22px;
color: #556659;
text-align: center;
}
.footer-link {
@ -186,7 +194,9 @@ export default {
.footer-contact-row {
display: flex;
align-items: flex-start;
justify-content: center;
gap: 8px;
text-align: left;
}
.footer-contact-icon {
@ -232,18 +242,12 @@ export default {
@media screen and (max-width: 1279px) {
.footer-columns {
flex-wrap: wrap;
justify-content: flex-start;
gap: 28px 40px;
gap: 28px 24px;
}
.footer-column {
flex: 1 1 220px;
max-width: calc(50% - 20px);
}
.footer-column--contact {
flex: 1 1 100%;
max-width: none;
flex: 1 1 calc(33.333% - 16px);
min-width: 180px;
}
}
@ -259,7 +263,7 @@ export default {
.footer-column {
flex: none;
max-width: none;
width: 100%;
}
.footer-bar-inner {

View File

@ -0,0 +1,121 @@
// 21 条碳链接数据(实际 19 条)
// 数据来源:可信碳网站优化需求文档
// 三类:产品碳足迹 / 企业碳管理平台 / CBAM
const carbonLinks = [
{
"type": "产品碳足迹",
"name": "国家温室气体排放因子数据库",
"url": "https://data.ncsc.org.cn/factories/index",
"desc": "官方排放因子数据查询"
},
{
"type": "产品碳足迹",
"name": "钢铁全产业链EPD平台",
"url": "https://www.cisa-epd.com/",
"desc": "钢铁行业 EPD 公示"
},
{
"type": "产品碳足迹",
"name": "江苏省产品碳足迹公共服务平台",
"url": "https://jstzj.fzggw.jiangsu.gov.cn/portal/home/index",
"desc": "省级产品碳足迹核算服务"
},
{
"type": "产品碳足迹",
"name": "浙江省产品碳足迹公共服务平台",
"url": "https://ny.fzggw.zj.gov.cn/tzj/org/home/#/",
"desc": "省级产品碳足迹核算服务"
},
{
"type": "产品碳足迹",
"name": "山东省企业产品碳足迹一站式服务平台",
"url": "https://cfootprint.greendev.org.cn/user/login",
"desc": "省级产品碳足迹核算服务"
},
{
"type": "产品碳足迹",
"name": "上海市产品碳足迹背景数据库",
"url": "https://www.shlcd.org.cn/admin/portal/home",
"desc": "省级产品碳足迹背景数据"
},
{
"type": "产品碳足迹",
"name": "湖北省产品碳足迹公共服务平台",
"url": "https://hbcfp.hbets.com.cn/sso/#/home",
"desc": "省级产品碳足迹核算服务"
},
{
"type": "产品碳足迹",
"name": "粤港澳大湾区碳足迹标识认证公共服务平台",
"url": "https://www.smq.com.cn/gbalca/gateway/#/index",
"desc": "大湾区产品碳足迹认证"
},
{
"type": "产品碳足迹",
"name": "电力行业产品碳足迹与环境产品声明平台",
"url": "https://cfp-epd.cec.org.cn/carbon/#/",
"desc": "电力行业产品碳足迹公示"
},
{
"type": "产品碳足迹",
"name": "中国原材料工业产品碳足迹基础数据库",
"url": "http://3060service.com/prod/proddoor/carbon/index",
"desc": "原材料行业产品碳足迹"
},
{
"type": "产品碳足迹",
"name": "中国交通运输碳足迹公示平台",
"url": "http://transcarbon.cn/",
"desc": "交通运输碳足迹公示"
},
{
"type": "产品碳足迹",
"name": "中国汽车产业链碳公示平台",
"url": "https://www.auto-cpp.com/",
"desc": "汽车产业链碳足迹公示"
},
{
"type": "产品碳足迹",
"name": "锂电池碳足迹背景数据库",
"url": "https://www.ldchy.cn/#/",
"desc": "锂电池产品碳足迹背景数据"
},
{
"type": "企业碳管理平台",
"name": "京碳惠:新一代物流碳足迹管理系统",
"url": "https://bv.jdl.com/",
"desc": "物流行业碳足迹管理"
},
{
"type": "企业碳管理平台",
"name": "欧冶绿色低碳供应链公共服务平台",
"url": "https://www.greenscs.com/",
"desc": "供应链碳数据采集"
},
{
"type": "企业碳管理平台",
"name": "晓数绿景",
"url": "https://www.enemind.com/index.html",
"desc": "企业级碳管理 SaaS"
},
{
"type": "CBAM",
"name": "欧冶CBAM辅助核算系统",
"url": "https://www.ouyeel.com/cbam/login",
"desc": "出口企业 CBAM 核算"
},
{
"type": "CBAM",
"name": "欧盟碳边界调节机制CBAM填报系统",
"url": "https://cbamcf.com/login?redirect=/",
"desc": "CBAM 官方填报"
},
{
"type": "CBAM",
"name": "CBAM欧盟碳关税服务平台-擎天全税通",
"url": "https://www.chinackts.com/products/cbam.html",
"desc": "CBAM 关税合规服务"
}
];
export default carbonLinks;

File diff suppressed because it is too large Load Diff

View File

@ -927,7 +927,7 @@ html.portal-figma-scale-active.portal-market-figma-scale-active {
width: 100%;
flex: 1 1 auto;
min-height: var(--home-figma-visual-height, auto);
background: #f5f5f5 !important;
background: #F6F7FA !important;
}
.portal-market-figma-page .portal-figma-scale-stage {

View File

@ -0,0 +1,19 @@
// 全局“敬请期待”弹窗总线
// 各业务页面通过 showGlobalComingSoon(text) 触发,由 Main 布局统一挂载的 t-dialog 渲染。
import Vue from 'vue';
export const comingSoonBus = new Vue();
// 兼容旧的 this.$showComingSoon 调用:所有页面的 mixin / 方法都委托到这里。
Vue.prototype.$showComingSoon = function showComingSoon(text) {
if (comingSoonBus._locked) return;
comingSoonBus._locked = true;
comingSoonBus.$emit('open', text);
setTimeout(() => {
comingSoonBus._locked = false;
}, 500);
};
export function closeGlobalComingSoon() {
comingSoonBus.$emit('close');
}

View File

@ -9,13 +9,13 @@ export default {
* @message TDesign MessagePluginmain.js 里挂到 Vue.prototype.$message
* info() 返回 Promise<messageInstance>实例有 close()
*/
showComingSoon() {
showComingSoon(text = '敬请期待') {
const prev = this[COMING_SOON_INSTANCE]
if (prev) {
prev.close()
this[COMING_SOON_INSTANCE] = null
}
this.$message.info('敬请期待').then((instance) => {
this.$message.info(text).then((instance) => {
this[COMING_SOON_INSTANCE] = instance
})
},

View File

@ -496,7 +496,7 @@ export default {
@import '../../styles/home-figma-variables.less';
.fwsc-container {
background: #f5f5f5;
background: #F6F7FA;
.portal-figma-scale-page();
}
@ -544,7 +544,8 @@ export default {
color: #003B1A;
cursor: pointer;
background: transparent;
border-radius: 32px;
/* 优化需求:按钮线框统一为长方形+圆角(不再使用 32px 胶囊) */
border-radius: 6px;
transition: all 0.3s;
&:hover {
@ -910,13 +911,15 @@ export default {
box-sizing: border-box;
height: 32px;
padding: 6px 12px;
border-radius: 4px;
/* 优化需求:按钮线框统一为长方形+圆角 */
border-radius: 6px;
border: 1px solid #00b96b;
color: #00b96b;
font-size: 14px;
font-weight: 400;
flex-shrink: 0;
white-space: nowrap;
transition: all 0.2s ease;
&:hover {
background: rgba(0, 154, 41, 0.1);
@ -1005,6 +1008,12 @@ export default {
.t-pagination__select {
margin-right: 0;
}
/* 优化需求:分页按钮线框统一为长方形+圆角 */
.t-pagination__number,
.t-pagination__btn {
border-radius: 6px;
}
}
}

View File

@ -122,7 +122,7 @@ export default {
@import '../../styles/home-figma-variables.less';
@import '../../styles/portal-landing-cards.less';
.fwsc-page {
background: #f6f7fa;
background: #F6F7FA;
.portal-figma-scale-page();
}

View File

@ -622,7 +622,7 @@ export default {
@bg-white: #fff;
.jrsc-page {
background: @bg-gray;
background: #F6F7FA;
animation: fadeIn 0.3s ease;
.portal-figma-scale-page();
}

View File

@ -428,7 +428,7 @@ export default {
@import '../../styles/home-figma-variables.less';
.sjsc-container {
background: #f5f5f5;
background: #F6F7FA;
.portal-figma-scale-page();
}

View File

@ -457,7 +457,7 @@ export default {
@import '../../styles/home-figma-variables.less';
.xqsc-container {
background: #f5f5f5;
background: #F6F7FA;
.portal-figma-scale-page();
}

View File

@ -154,13 +154,16 @@
v-for="card in favoriteCards"
:key="card.gxUuid || card._demoId"
class="gxnlpt-card"
@click="handleCardClick(card)"
:class="{ 'gxnlpt-card--expired': card.yxzt === 'N' }"
@click="card.yxzt === 'N' ? null : handleCardClick(card)"
>
<div class="gxnlpt-card-body">
<div class="gxnlpt-card-info">
<div class="gxnlpt-card-name-row">
<h3 class="gxnlpt-card-name" :title="card.bt1">{{ card.bt1 }}</h3>
<span v-if="card.yxzt === 'N'" class="gxnlpt-card-expired-tag">已失效</span>
<button
v-else
type="button"
class="gxnlpt-card-star"
aria-label="取消收藏"
@ -229,6 +232,45 @@
</div>
</template>
</section>
<!-- 优化需求碳链接专区21 条精选外站链接 3 大类组织 -->
<section class="gxnlpt-block gxnlpt-carbon-links" aria-label="碳链接">
<header class="gxnlpt-block-head">
<img class="gxnlpt-block-icon" :src="getIconUrl('tanjl.svg')" alt="" />
<h2 class="gxnlpt-block-title">碳链接</h2>
<span class="gxnlpt-block-subtitle">产品碳足迹 · 企业碳管理平台 · CBAM</span>
</header>
<div
v-for="group in carbonLinkGroups"
:key="group.type"
class="gxnlpt-carbon-group"
>
<h3 class="gxnlpt-carbon-group-title">
<span class="gxnlpt-carbon-group-bar"></span>
<span>{{ group.type }}</span>
<span class="gxnlpt-carbon-group-count">{{ group.list.length }}</span>
</h3>
<ul class="gxnlpt-carbon-list">
<li
v-for="(item, idx) in group.list"
:key="`${group.type}-${idx}`"
class="gxnlpt-carbon-item"
>
<a
class="gxnlpt-carbon-link"
:href="item.url"
target="_blank"
rel="noopener noreferrer"
>
<span class="gxnlpt-carbon-name">{{ item.name }}</span>
<span v-if="item.desc" class="gxnlpt-carbon-desc">{{ item.desc }}</span>
</a>
<span class="gxnlpt-carbon-external" aria-hidden="true"></span>
</li>
</ul>
</div>
</section>
</template>
</main>
</div>
@ -241,6 +283,11 @@
<script>
import GxnlptCardTags from '@/pages/index/views/gxnlpt/components/GxnlptCardTags.vue';
import api from '@/pages/index/api/gxnl/index.js';
// 184 + 21 200+
// 5
import gxnlLinksByCategory from '@/pages/index/data/gxnl-links.js';
// 21 //CBAM
import carbonLinksData from '@/pages/index/data/carbon-links.js';
import {
isPortalLoggedIn,
isUnauthorizedError,
@ -338,61 +385,44 @@ function shouldInjectOverflowDemoTags(categoryId, index) {
return false;
}
/** 各分类碳相关演示数据bqjh 模拟后期 JSON 传输) */
const DEMO_BY_CATEGORY = {
'content-1': [
{ bt1: '企业温室气体盘查', qymc: '中国质量认证中心', bqjh: '["碳盘查","组织碳","ISO14064"]', scbz: 'N' },
{ bt1: '产品碳足迹核算', qymc: '中环联合认证中心', bqjh: '["产品碳足迹","LCA","PAS2050"]', scbz: 'Y' },
{ bt1: 'CBAM 碳排放申报', qymc: '深圳碳排放权交易所', bqjh: '["CBAM","欧盟碳关税","出口合规"]', scbz: 'N' },
{ bt1: '园区碳管理平台', qymc: '北京绿色交易所', bqjh: '["园区碳管理","能碳协同"]', scbz: 'N' },
{ bt1: '供应链碳数据核算', qymc: '上海环境能源交易所', bqjh: '["范围三","供应链","数据填报"]', scbz: 'N' },
{ bt1: '碳资产管理核算', qymc: '广州碳排放权交易中心', bqjh: '["碳资产","年度盘查","全国"]', scbz: 'Y' },
{ bt1: '组织碳核查数据填报', qymc: '中国标准化研究院', bqjh: '["组织碳","数据填报","MRV"]', scbz: 'N' },
{ bt1: '重点行业碳排放核算', qymc: '国家应对气候变化战略研究和国际合作中心', bqjh: '["重点行业","核算指南"]', scbz: 'N' },
{ bt1: '碳排放监测与核算平台', qymc: '生态环境部环境规划院', bqjh: '["在线监测","核算","平台"]', scbz: 'N' },
],
'content-2': [
{ bt1: '第三方碳核查服务', qymc: '中国船级社质量认证公司', bqjh: '["碳核查","第三方核查","重点排放单位"]', scbz: 'N' },
{ bt1: 'CCER 项目审定', qymc: '中国林业科学研究院', bqjh: '["CCER","项目审定","造林碳汇"]', scbz: 'N' },
{ bt1: '绿色项目认定', qymc: '联合征信有限公司', bqjh: '["绿色认定","全国"]', scbz: 'Y' },
{ bt1: '碳中和认证', qymc: '中国节能协会碳中和专业委员会', bqjh: '["碳中和","认证","抵消"]', scbz: 'N' },
{ bt1: '自愿减排项目验证', qymc: '中国电力企业联合会', bqjh: '["自愿减排","验证","MRV"]', scbz: 'N' },
{ bt1: '零碳工厂评价', qymc: '钛和认证(上海)有限公司', bqjh: '["零碳工厂","评价认证"]', scbz: 'N' },
{ bt1: '产品碳足迹认证', qymc: '中国质量认证中心', bqjh: '["产品碳足迹","认证"]', scbz: 'N' },
{ bt1: '绿色供应链认证', qymc: '中环联合认证中心', bqjh: '["供应链","绿色认证"]', scbz: 'N' },
],
'content-3': [
{ bt1: '全国碳配额交易', qymc: '上海环境能源交易所', bqjh: '["碳配额","全国碳市场","交易"]', scbz: 'N' },
{ bt1: 'CCER 挂牌交易', qymc: '北京绿色交易所', bqjh: '["CCER","挂牌","自愿减排"]', scbz: 'Y' },
{ bt1: '碳排放权回购', qymc: '广州碳排放权交易中心', bqjh: '["回购","流动性","碳金融"]', scbz: 'N' },
{ bt1: '区域试点配额转让', qymc: '深圳碳排放权交易所', bqjh: '["试点市场","配额转让"]', scbz: 'N' },
{ bt1: '碳资产托管服务', qymc: '湖北碳排放权交易中心', bqjh: '["托管","碳资产","履约"]', scbz: 'N' },
{ bt1: '国际 VCS 碳信用交易', qymc: '中金公司碳交易部', bqjh: '["VCS","国际碳信用","跨境"]', scbz: 'N' },
{ bt1: '碳配额大宗协议转让', qymc: '天津排放权交易所', bqjh: '["大宗交易","配额"]', scbz: 'N' },
{ bt1: '碳普惠交易服务', qymc: '重庆碳排放权交易中心', bqjh: '["碳普惠","交易"]', scbz: 'N' },
],
'content-4': [
{ bt1: '绿色信贷融资', qymc: '中国工商银行绿色金融部', bqjh: '["绿色信贷","融资","转型金融"]', scbz: 'N' },
{ bt1: '碳资产质押贷款', qymc: '中国建设银行碳金融创新中心', bqjh: '["质押","碳配额","贷款"]', scbz: 'Y' },
{ bt1: '碳收益权保险产品', qymc: '中国平安财产保险', bqjh: '["碳保险","收益权","风险"]', scbz: 'N' },
{ bt1: '碳基金投资管理', qymc: '华夏基金碳中和投资部', bqjh: '["碳基金","ESG","投资"]', scbz: 'N' },
{ bt1: '绿色债券发行顾问', qymc: '中信证券投行委员会', bqjh: '["绿色债券","发行","顾问"]', scbz: 'N' },
{ bt1: '企业碳配额回购融资', qymc: '国家开发银行行业一部', bqjh: '["回购融资","配额","全国"]', scbz: 'N' },
{ bt1: '转型金融贷款服务', qymc: '中国银行绿色金融事业部', bqjh: '["转型金融","贷款"]', scbz: 'N' },
{ bt1: '碳减排支持工具', qymc: '中国人民银行货币政策司', bqjh: '["碳减排","支持工具"]', scbz: 'N' },
],
'content-5': [
{ bt1: '企业碳达峰路径规划', qymc: '清华大学碳中和研究院', bqjh: '["碳达峰","路径规划","咨询"]', scbz: 'N' },
{ bt1: '重点行业减排技术评估', qymc: '中国环境科学研究院', bqjh: '["减排技术","评估","电力"]', scbz: 'Y' },
{ bt1: '碳管理体系建设', qymc: '中国标准化研究院', bqjh: '["管理体系","ISO14067","培训"]', scbz: 'N' },
{ bt1: '碳信息披露辅导', qymc: '普华永道气候变化与可持续发展部', bqjh: '["信息披露","CDP","ESG报告"]', scbz: 'N' },
{ bt1: '林业碳汇项目开发咨询', qymc: '北京林业大学碳汇研究中心', bqjh: '["林业碳汇","项目开发","CCER"]', scbz: 'N' },
{ bt1: '零碳园区规划咨询', qymc: '中国城市规划设计研究院', bqjh: '["零碳园区","规划","综合能源"]', scbz: 'N' },
{ bt1: '碳市场政策解读咨询', qymc: '国务院发展研究中心资源与环境政策研究所', bqjh: '["政策解读","碳市场"]', scbz: 'N' },
{ bt1: '企业 ESG 碳议题咨询', qymc: '德勤中国可持续发展服务部', bqjh: '["ESG","碳议题","咨询"]', scbz: 'N' },
],
/**
* 历史说明原先这里有 ORIGINAL_DEMO_BY_CATEGORY5×8=40 概念性占位数据
* 它们没有 lj 字段依赖数据库/接口不可用时显示但用户点击会触发敬请期待
* 体感为点击无反应现已全部清理
* 当前兜底数据源改为 gxnlLinksByCategorygxnl-links.js
* 184 条共性能力链接 + 21 条碳链接全部有真实外链
*/
// 5 id
const CATEGORY_ID_TO_TITLE = {
'content-1': '碳核算平台',
'content-2': '碳认证机构',
'content-3': '碳交易平台',
'content-4': '碳金融服务',
'content-5': '碳技术咨询',
};
/**
* 真实接口数据失败时页面会回退到本地的兜底数据
* 数据源已清理ORIGINAL_DEMO_BY_CATEGORY 早期 40 概念性占位数据
* 没有 lj 字段点击会走敬请期待分支造成点击无反应体感已全部清理
* 数据源gxnlLinksByCategory 来自可信碳网站优化需求文档整理的 184 条真实外链 + 21 条碳链接
*/
const DEMO_BY_CATEGORY = (() => {
const merged = {};
Object.entries(CATEGORY_ID_TO_TITLE).forEach(([id, title]) => {
const extra = (gxnlLinksByCategory && gxnlLinksByCategory[title]) || [];
merged[id] = extra.map((item) => ({
bt1: item.bt1,
qymc: item.qymc,
bqjh: item.bqjh,
lj: item.lj,
scbz: item.scbz || 'N',
}));
});
return merged;
})();
/** 各分类标签池(来自演示数据,供接口数据补标签) */
const CATEGORY_TAG_POOL = Object.keys(DEMO_BY_CATEGORY).reduce((pools, id) => {
const set = new Set();
@ -608,6 +638,15 @@ export default {
}
return this.categoryList.map((item, index) => ({ item, index }));
},
/* 碳链接:按 3 大类(产品碳足迹 / 企业碳管理平台 / CBAM分组 */
carbonLinkGroups() {
const order = ['产品碳足迹', '企业碳管理平台', 'CBAM'];
const groups = order.map((type) => ({
type,
list: (carbonLinksData || []).filter((x) => x.type === type),
}));
return groups.filter((g) => g.list.length > 0);
},
favoriteCards() {
if (this.favoriteList && this.favoriteList.length) {
return this.favoriteList;
@ -1402,12 +1441,14 @@ export default {
: '';
},
handleCardClick(card) {
if (this.useDemoData || !card.gxUuid) {
this.showComingSoon();
// 使 wzLj lj
const target = card.wzLj || card.lj;
if (target) {
window.open(target, '_blank', 'noopener,noreferrer');
return;
}
// this.$router.push({ path: '/tfwsc', query: { id: card.gxUuid } });
window.open(card.wzLj);
// lj
this.showComingSoon(card.bt1 ? `${card.bt1}(详情筹备中)` : '详情筹备中');
},
async handleCollect(card) {
const isAdd = card.scbz !== 'Y';
@ -1749,6 +1790,143 @@ html.portal-figma-scale-active .gxnlpt-page {
color: @home-color-primary-dark;
}
.gxnlpt-block-subtitle {
margin-left: auto;
font-size: 12px;
font-weight: 400;
line-height: 20px;
color: rgba(0, 59, 26, 0.6);
white-space: nowrap;
}
/* ========== 碳链接专区 ========== */
.gxnlpt-carbon-links {
margin-top: 36px;
}
.gxnlpt-carbon-group {
margin-top: 18px;
}
.gxnlpt-carbon-group-title {
display: flex;
align-items: center;
gap: 8px;
margin: 0 0 12px;
font-size: 14px;
font-weight: 600;
line-height: 22px;
color: @home-color-primary-dark;
}
.gxnlpt-carbon-group-bar {
display: inline-block;
width: 4px;
height: 16px;
background: linear-gradient(180deg, @home-color-primary-green 0%, @home-color-primary-green-dark 100%);
border-radius: 2px;
}
.gxnlpt-carbon-group-count {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 22px;
height: 18px;
padding: 0 6px;
font-size: 12px;
font-weight: 500;
line-height: 18px;
color: @home-color-primary-green-dark;
background: rgba(0, 185, 107, 0.12);
border-radius: 9px;
}
.gxnlpt-carbon-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 10px 12px;
margin: 0;
padding: 0;
list-style: none;
}
.gxnlpt-carbon-item {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
min-height: 56px;
padding: 10px 14px;
background: #ffffff;
border: 1px solid rgba(0, 185, 107, 0.2);
border-radius: 6px;
transition: all 0.25s ease;
box-sizing: border-box;
}
.gxnlpt-carbon-item:hover {
border-color: @home-color-primary-green;
background: rgba(0, 185, 107, 0.04);
box-shadow: 0 4px 12px rgba(0, 154, 41, 0.12);
}
.gxnlpt-carbon-link {
display: flex;
flex: 1;
flex-direction: column;
gap: 2px;
min-width: 0;
text-decoration: none;
color: @home-color-primary-dark;
}
.gxnlpt-carbon-name {
font-size: 14px;
font-weight: 500;
line-height: 22px;
color: @home-color-primary-dark;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.gxnlpt-carbon-desc {
font-size: 12px;
font-weight: 400;
line-height: 18px;
color: rgba(0, 59, 26, 0.6);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.gxnlpt-carbon-link:hover .gxnlpt-carbon-name {
color: @home-color-primary-green-dark;
}
.gxnlpt-carbon-external {
flex-shrink: 0;
font-size: 14px;
color: @home-color-primary-green;
opacity: 0.5;
transition: opacity 0.2s ease, transform 0.2s ease;
}
.gxnlpt-carbon-item:hover .gxnlpt-carbon-external {
opacity: 1;
transform: translate(2px, -2px);
}
@media (max-width: 640px) {
.gxnlpt-block-subtitle {
display: none;
}
.gxnlpt-carbon-list {
grid-template-columns: 1fr;
}
}
.gxnlpt-state {
padding: 32px 0;
font-size: 14px;
@ -1839,6 +2017,36 @@ html.portal-figma-scale-active .gxnlpt-page {
white-space: nowrap;
}
.gxnlpt-card--expired {
opacity: 0.55;
cursor: default;
pointer-events: none;
}
.gxnlpt-card--expired .gxnlpt-card-name {
color: #bbb;
}
.gxnlpt-card--expired .gxnlpt-card-org {
color: #ccc;
}
.gxnlpt-card--expired:hover {
border-color: fade(#000, 10%);
box-shadow: none;
}
.gxnlpt-card-expired-tag {
flex-shrink: 0;
padding: 1px 6px;
font-size: 11px;
line-height: 18px;
color: #999;
background: #f5f5f5;
border-radius: 3px;
pointer-events: auto;
}
.gxnlpt-card-star {
flex-shrink: 0;
width: 14px;

View File

@ -439,6 +439,8 @@ export default {
btnName: '申请服务',
sectionId: 'section2',
link: '',
/* 优化需求:航运燃料暂未建设完成,点击应弹"敬请期待" */
comingSoon: true,
desc: '从化石油基向LNG、绿甲醇、绿氨等多元低碳方向加速转型。',
icon: require('@/pages/index/assets/home-hyrl-icon.png'),
},
@ -785,6 +787,10 @@ export default {
},
//
handleOverseasClick(item) {
if (item && item.comingSoon) {
this.showComingSoon('航运燃料专题');
return;
}
if (!item || !item.sectionId) {
this.$router.push('/qych');
return;
@ -793,6 +799,10 @@ export default {
},
//
handleOverseasBtnClick(item) {
if (item && item.comingSoon) {
this.showComingSoon('航运燃料专题');
return;
}
if (item.link && /^https?:\/\//.test(item.link)) {
window.open(item.link, '_blank');
return;
@ -1073,8 +1083,20 @@ export default {
}
/* 核心驱动及以下:左缘与导航「可」字对齐(--home-section-px */
.portal-page .home-shelf--core,
.portal-page .home-shelf--capability,
.portal-page .home-shelf--core {
align-items: stretch;
min-height: var(--home-section-min-h);
padding: var(--home-section-pad-top) var(--home-section-px) var(--home-section-pb);
box-sizing: border-box;
}
.portal-page .home-shelf--capability {
align-items: stretch;
min-height: var(--home-section-min-h);
padding: var(--home-section-pad-top) var(--home-section-px) var(--home-section-pb);
box-sizing: border-box;
}
.portal-page .home-shelf--news {
align-items: stretch;
min-height: var(--home-section-min-h);
@ -1102,6 +1124,9 @@ export default {
.portal-page .home-shelf--capability {
gap: clamp(42px, 7vh, @home-ability-title-to-grid-gap);
/* 优化需求:六个快捷入口整体在 section 高度内居中(参考图 2中部略偏上 */
justify-content: center;
align-items: center;
}
.portal-page .home-shelf--overseas {
@ -1210,7 +1235,8 @@ export default {
border: 1px solid @home-color-white;
backdrop-filter: blur(@home-blur-sm);
box-shadow: @home-shadow-search;
border-radius: @home-radius-sm;
/* 优化需求:搜索框统一为长方形+圆角风格,圆角小一些更显政务正式 */
border-radius: 6px;
width: 100%;
padding: @home-search-box-padding;
box-sizing: border-box;
@ -1220,7 +1246,7 @@ export default {
background: @home-gradient-search-btn;
width: @home-search-btn-width;
height: @home-search-btn-height;
border-radius: @home-radius-xs;
border-radius: 6px;
flex-shrink: 0;
text-align: center;
color: @home-color-white;
@ -1267,7 +1293,7 @@ export default {
.hot-tag {
background: @home-search-tag-bg;
border-radius: @home-radius-pill;
border-radius: 7px;
padding: @home-search-tag-padding;
color: @home-color-primary-dark;
font-size: @home-font-size-14;
@ -1319,11 +1345,11 @@ export default {
.hero-card {
width: 100%;
border: 1px solid @home-color-white;
box-shadow: @home-shadow-card-blue;
backdrop-filter: blur(@home-blur-sm);
/* 优化需求:参考图 1 — 白底卡片 + 顶部绿色色块,整体扁平绿碳风格 */
border: 1px solid rgba(15, 97, 47, 0.18);
box-shadow: 0 4px 16px rgba(15, 97, 47, 0.06);
border-radius: @home-radius-lg;
transition: transform 0.3s ease, box-shadow 0.3s ease;
transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
display: flex;
flex-direction: column;
align-items: stretch;
@ -1331,23 +1357,42 @@ export default {
padding: 0 0 @home-space-24;
overflow: hidden;
box-sizing: border-box;
background: #ffffff;
position: relative;
}
.hero-card::before {
/* 顶部绿色色块:渐变蒙层 */
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 56px;
background: linear-gradient(135deg, rgba(15, 97, 47, 0.18) 0%, rgba(15, 97, 47, 0.06) 100%);
border-radius: @home-radius-lg @home-radius-lg 0 0;
pointer-events: none;
z-index: 0;
}
.hero-card:hover {
transform: translateY(-8px);
box-shadow: @home-shadow-card-blue-hover;
transform: translateY(-6px);
border-color: rgba(15, 97, 47, 0.45);
box-shadow: 0 12px 28px rgba(15, 97, 47, 0.18);
}
.hero-card .card-header {
position: relative;
z-index: 1;
width: 100%;
padding: @home-feature-card-header-padding-y 16px;
border-bottom: 1px solid @home-color-white;
border-bottom: 1px solid rgba(15, 97, 47, 0.15);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
box-shadow: none;
backdrop-filter: blur(@home-blur-sm);
background: transparent;
border-radius: @home-radius-lg @home-radius-lg 0 0;
box-sizing: border-box;
}
@ -1355,14 +1400,16 @@ export default {
.hero-card .card-title {
font-size: @home-feature-card-title-size;
font-weight: @home-font-weight-semibold;
color: var(--home-title-color);
color: #0f612f;
font-family: @home-font-family;
line-height: 1.2;
text-align: center;
text-shadow: @home-shadow-card-title;
text-shadow: none;
}
.hero-card .card-body {
position: relative;
z-index: 1;
flex: 1;
width: 100%;
padding: @home-space-24 @home-feature-card-body-padding-x 0;
@ -1371,6 +1418,7 @@ export default {
gap: @home-feature-card-body-gap;
align-content: start;
box-sizing: border-box;
background: #ffffff;
}
.hero-card .card-btn {
@ -1380,84 +1428,66 @@ export default {
display: flex;
align-items: center;
justify-content: center;
border-radius: @home-radius-sm;
border-radius: 6px;
font-size: @home-feature-card-btn-font-size;
font-weight: @home-font-weight-medium;
line-height: @home-line-height-26;
color: @home-color-text-dark;
color: #0f612f;
cursor: pointer;
transition: all 0.3s ease;
transition: all 0.25s ease;
box-sizing: border-box;
background: rgba(15, 97, 47, 0.06);
border: 1px solid rgba(15, 97, 47, 0.3);
}
.hero-card .card-btn:hover {
transform: scale(1.02);
box-shadow: @home-shadow-card-btn-blue;
}
.blue-card .card-btn:hover {
box-shadow: @home-shadow-card-btn-blue-strong;
}
.cyan-card .card-btn:hover {
box-shadow: @home-shadow-card-btn-chain;
}
.green-card .card-btn:hover {
box-shadow: @home-shadow-card-btn-green;
}
.blue-card {
background: @home-gradient-card-blue;
}
.blue-card .card-header {
background: @home-gradient-card-blue-header;
}
.blue-card .card-body {
background: transparent;
}
.blue-card .card-btn {
background: @home-color-card-blue-btn-secondary-bg;
border: 1px solid @home-color-card-blue-btn-secondary-border;
}
.cyan-card {
background: @home-color-card-chain-bg;
box-shadow: @home-shadow-card-green;
}
.cyan-card .card-header {
background: @home-gradient-card-chain-header;
}
.cyan-card .card-body {
background: transparent;
}
.cyan-card .card-btn {
background: @home-color-card-chain-btn-secondary-bg;
border: 1px solid @home-color-card-chain-btn-secondary-border;
transform: translateY(-2px);
color: #ffffff;
background: #0f612f;
border-color: #0f612f;
box-shadow: 0 6px 16px rgba(15, 97, 47, 0.3);
}
.blue-card,
.cyan-card,
.green-card {
background: @home-gradient-card-green;
box-shadow: @home-shadow-card-green;
/* 三张卡片去色板差异化:统一为白底 + 顶部绿色色块 */
background: #ffffff;
}
.blue-card::before,
.cyan-card::before,
.green-card::before {
background: linear-gradient(135deg, rgba(15, 97, 47, 0.18) 0%, rgba(15, 97, 47, 0.06) 100%);
}
.blue-card .card-header,
.cyan-card .card-header,
.green-card .card-header {
background: @home-gradient-card-green-header;
}
.green-card .card-body {
background: transparent;
}
.blue-card .card-body,
.cyan-card .card-body,
.green-card .card-body {
background: #ffffff;
}
.blue-card .card-btn,
.cyan-card .card-btn,
.green-card .card-btn {
background: @home-color-card-green-btn-secondary-bg;
border: 1px solid @home-color-card-green-btn-secondary-border;
background: rgba(15, 97, 47, 0.06);
border: 1px solid rgba(15, 97, 47, 0.3);
color: #0f612f;
}
.blue-card .card-btn:hover,
.cyan-card .card-btn:hover,
.green-card .card-btn:hover {
color: #ffffff;
background: #0f612f;
border-color: #0f612f;
box-shadow: 0 6px 16px rgba(15, 97, 47, 0.3);
}
/* ==================== 核心驱动模块 ==================== */
@ -1487,10 +1517,58 @@ export default {
@home-title-deco-width-em: 4.9375em;
@home-title-deco-height-em: 1.5625em;
.portal-page .core-section .section-title.core-title,
.portal-page .capability-section .capability-header,
.portal-page .overseas2-section .overseas2-header,
.portal-page .news-section .news-header,
.portal-page .core-section .section-title.core-title {
position: relative;
top: auto;
left: auto;
transform: none;
width: auto;
height: auto;
min-height: 58px;
padding: 0;
margin: 0;
flex-shrink: 0;
}
.portal-page .capability-section .capability-header {
position: relative;
top: auto;
left: auto;
transform: none;
width: auto;
height: auto;
min-height: 58px;
padding: 0;
margin: 0;
flex-shrink: 0;
}
.portal-page .overseas2-section .overseas2-header {
position: relative;
top: auto;
left: auto;
transform: none;
width: auto;
height: auto;
min-height: 58px;
padding: 0;
margin: 0;
flex-shrink: 0;
}
.portal-page .news-section .news-header {
position: relative;
top: auto;
left: auto;
transform: none;
width: auto;
height: auto;
min-height: 58px;
padding: 0;
margin: 0;
flex-shrink: 0;
}
.portal-page .partner-section .partner-title-area {
position: relative;
top: auto;
@ -1533,11 +1611,23 @@ export default {
width: 100%;
}
.portal-page .home-shelf--core .core-grid,
.portal-page .home-shelf--core .core-grid {
position: relative;
top: -11px;
left: 0px;
transform: none;
width: 100%;
max-width: none;
margin: 0;
box-sizing: border-box;
flex: 1;
min-height: 0;
}
.portal-page .home-shelf--capability .capability-grid {
position: relative;
top: auto;
left: auto;
top: -55px;
left: 0px;
transform: none;
width: 100%;
max-width: none;
@ -1589,9 +1679,33 @@ export default {
flex-shrink: 0;
}
.home-block-title-content,
.capability-title-content,
.overseas2-title-content,
.home-block-title-content {
position: relative;
display: inline-flex;
flex-direction: column;
align-items: flex-start;
font-size: var(--home-title-size);
isolation: isolate;
}
.capability-title-content {
position: relative;
display: inline-flex;
flex-direction: column;
align-items: flex-start;
font-size: var(--home-title-size);
isolation: isolate;
}
.overseas2-title-content {
position: relative;
display: inline-flex;
flex-direction: column;
align-items: flex-start;
font-size: var(--home-title-size);
isolation: isolate;
}
.news-title-content {
position: relative;
display: inline-flex;
@ -1601,9 +1715,39 @@ export default {
isolation: isolate;
}
.home-block-title-text,
.capability-title-text,
.overseas2-title-text,
.home-block-title-text {
position: relative;
z-index: 1;
font-family: @home-font-family;
font-size: inherit;
font-weight: var(--home-title-weight);
line-height: 1.4;
color: var(--home-title-color);
margin: 0;
}
.capability-title-text {
position: relative;
z-index: 1;
font-family: @home-font-family;
font-size: inherit;
font-weight: var(--home-title-weight);
line-height: 1.4;
color: var(--home-title-color);
margin: 0;
}
.overseas2-title-text {
position: relative;
z-index: 1;
font-family: @home-font-family;
font-size: inherit;
font-weight: var(--home-title-weight);
line-height: 1.4;
color: var(--home-title-color);
margin: 0;
}
.news-title-text {
position: relative;
z-index: 1;
@ -1654,10 +1798,70 @@ export default {
}
/* 标题下笔触装饰(透明底 PNG各区块共用同一套定位 */
.home-section-title-bar,
.home-block-title-bar,
.capability-title-bar,
.overseas2-title-bar,
.home-section-title-bar {
display: block;
position: absolute;
top: @home-title-deco-top-em;
left: @home-title-deco-left-em;
width: @home-title-deco-width-em;
height: @home-title-deco-height-em;
z-index: 0;
pointer-events: none;
background-color: transparent;
background-image: url('~@/pages/index/views/home2/assets/title-brush-bar.png');
background-repeat: no-repeat;
background-position: left center;
background-size: 100% 100%;
}
.home-block-title-bar {
display: block;
position: absolute;
top: @home-title-deco-top-em;
left: @home-title-deco-left-em;
width: @home-title-deco-width-em;
height: @home-title-deco-height-em;
z-index: 0;
pointer-events: none;
background-color: transparent;
background-image: url('~@/pages/index/views/home2/assets/title-brush-bar.png');
background-repeat: no-repeat;
background-position: left center;
background-size: 100% 100%;
}
.capability-title-bar {
display: block;
position: absolute;
top: @home-title-deco-top-em;
left: @home-title-deco-left-em;
width: @home-title-deco-width-em;
height: @home-title-deco-height-em;
z-index: 0;
pointer-events: none;
background-color: transparent;
background-image: url('~@/pages/index/views/home2/assets/title-brush-bar.png');
background-repeat: no-repeat;
background-position: left center;
background-size: 100% 100%;
}
.overseas2-title-bar {
display: block;
position: absolute;
top: @home-title-deco-top-em;
left: @home-title-deco-left-em;
width: @home-title-deco-width-em;
height: @home-title-deco-height-em;
z-index: 0;
pointer-events: none;
background-color: transparent;
background-image: url('~@/pages/index/views/home2/assets/title-brush-bar.png');
background-repeat: no-repeat;
background-position: left center;
background-size: 100% 100%;
}
.news-title-bar {
display: block;
position: absolute;
@ -1862,15 +2066,18 @@ export default {
/* Figma list 150605:36192×3 网格,列间距 13px行间距 70px容器高 330px */
.capability-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
/* 优化需求:六个快捷入口居中显示,不再拉伸到版心最大宽度 */
grid-template-columns: repeat(3, minmax(0, 420px));
column-gap: @home-ability-grid-col-gap;
row-gap: @home-ability-grid-row-gap;
width: 100%;
max-width: fit-content;
min-height: @home-ability-grid-min-height;
margin: 0;
margin: 0 auto;
box-sizing: border-box;
justify-content: center;
justify-items: stretch;
align-content: start;
align-content: center;
}
.capability-card {
@ -1879,7 +2086,7 @@ export default {
justify-content: space-between;
width: 100%;
min-height: 111px;
height: 111px;
height: 140px;
padding: @home-ability-card-padding;
box-sizing: border-box;
background: @home-gradient-ability-card;
@ -2867,21 +3074,48 @@ export default {
width: 100%;
}
.portal-page .home-shelf--core,
.portal-page .home-shelf--capability,
.portal-page .home-shelf--overseas,
.portal-page .home-shelf--news,
.portal-page .home-shelf--partner {
.portal-page .home-shelf--core {
justify-content: flex-start;
}
.portal-page .home-shelf--capability {
justify-content: flex-start;
}
.portal-page .home-shelf--overseas {
justify-content: flex-start;
}
.portal-page .home-shelf--news {
justify-content: flex-start;
min-height: var(--home-news-section-min-h, var(--home-section-min-h));
}
.portal-page .home-shelf--core .core-grid,
.portal-page .home-shelf--capability .capability-grid,
.portal-page .home-shelf--overseas .overseas2-grid,
.portal-page .home-shelf--partner {
justify-content: flex-start;
}
.portal-page .home-shelf--core .core-grid {
flex: 1 1 auto;
min-height: 0;
align-content: center;
align-self: stretch;
}
.portal-page .home-shelf--capability .capability-grid {
flex: 1 1 auto;
min-height: 0;
align-content: center;
align-self: stretch;
}
.portal-page .home-shelf--overseas .overseas2-grid {
flex: 1 1 auto;
min-height: 0;
align-content: center;
align-self: stretch;
}
.portal-page .home-shelf--news .news-grid {
flex: 1 1 auto;
min-height: 0;
@ -2889,10 +3123,22 @@ export default {
align-self: stretch;
}
.portal-page .home-shelf--core .section-title.core-title,
.portal-page .home-shelf--capability .capability-header,
.portal-page .home-shelf--overseas .overseas2-header,
.portal-page .home-shelf--news .news-header,
.portal-page .home-shelf--core .section-title.core-title {
flex-shrink: 0;
}
.portal-page .home-shelf--capability .capability-header {
flex-shrink: 0;
}
.portal-page .home-shelf--overseas .overseas2-header {
flex-shrink: 0;
}
.portal-page .home-shelf--news .news-header {
flex-shrink: 0;
}
.portal-page .home-shelf--partner .partner-title-area {
flex-shrink: 0;
}
@ -3082,9 +3328,18 @@ export default {
padding-right: var(--home-section-px);
}
.home-block-title-content,
.capability-title-content,
.overseas2-title-content,
.home-block-title-content {
font-size: @home-font-size-28;
}
.capability-title-content {
font-size: @home-font-size-28;
}
.overseas2-title-content {
font-size: @home-font-size-28;
}
.news-title-content {
font-size: @home-font-size-28;
}
@ -3098,19 +3353,54 @@ export default {
font-size: @home-font-size-28;
}
.core-section,
.capability-section,
.overseas2-section,
.news-section,
.core-section {
--home-section-pt: 40px;
--home-section-pb: 48px;
--home-section-min-h: auto;
}
.capability-section {
--home-section-pt: 40px;
--home-section-pb: 48px;
--home-section-min-h: auto;
}
.overseas2-section {
--home-section-pt: 40px;
--home-section-pb: 48px;
--home-section-min-h: auto;
}
.news-section {
--home-section-pt: 40px;
--home-section-pb: 48px;
--home-section-min-h: auto;
}
.partner-section {
--home-section-pt: 40px;
--home-section-pb: 48px;
--home-section-min-h: auto;
}
.portal-page .home-shelf--core,
.portal-page .home-shelf--capability,
.portal-page .home-shelf--overseas,
.portal-page .home-shelf--core {
min-height: auto;
padding-left: var(--home-section-px);
padding-right: var(--home-section-px);
}
.portal-page .home-shelf--capability {
min-height: auto;
padding-left: var(--home-section-px);
padding-right: var(--home-section-px);
}
.portal-page .home-shelf--overseas {
min-height: auto;
padding-left: var(--home-section-px);
padding-right: var(--home-section-px);
}
.portal-page .home-shelf--news {
min-height: auto;
padding-left: var(--home-section-px);

View File

@ -1,7 +1,11 @@
<template>
<div class="hydt-page portal-page portal-page-shell">
<!-- Figma banner-bg 150622:19115背景 imageRef ec2e3dd -->
<section class="hydt-banner" aria-label="行业动态">
<section
class="hydt-banner"
:class="{ 'hydt-banner--collapsed': bannerCollapsed }"
aria-label="行业动态"
>
<div class="hydt-banner-bg" aria-hidden="true"></div>
<div class="hydt-banner-inner page-content-wrap">
<p class="hydt-breadcrumb">
@ -101,6 +105,8 @@ export default {
newsTabs: NEWS_TABS,
activeTab: 0,
pageLoading: false,
/* 优化需求:点击 tab 后 banner 收起首页进入不收起tab 切换时收起 */
bannerCollapsed: false,
newsListByType: {
gjzc: [],
hyzx: [],
@ -149,11 +155,23 @@ export default {
if (index >= 0) this.activeTab = index;
},
switchTab(index) {
if (this.activeTab === index) {
// tab
if (this.bannerCollapsed) return;
}
this.activeTab = index;
this.bannerCollapsed = true;
const type = this.newsTabs[index]?.type;
if (this.$route.query.type !== type) {
this.$router.replace({ path: '/hydt', query: { type } });
}
//
this.$nextTick(() => {
const body = this.$el.querySelector('.hydt-body');
if (body) {
body.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
});
},
onPageChange() {
window.scrollTo({ top: 0, behavior: 'smooth' });
@ -225,6 +243,12 @@ export default {
overflow: hidden;
background: @home-color-page-bg;
box-sizing: border-box;
transition: height 0.45s cubic-bezier(0.4, 0, 0.2, 1), margin-bottom 0.45s cubic-bezier(0.4, 0, 0.2, 1);
}
/* 优化需求:点击 tab 后 banner 收起,仅保留扁平标题条 */
.hydt-banner--collapsed {
height: 88px;
}
/* Figma 150622:19115 画框背景 FILL1440×350 */
@ -249,6 +273,19 @@ export default {
padding-top: @hydt-banner-pad-top;
padding-bottom: @hydt-banner-pad-bottom;
box-sizing: border-box;
transition: gap 0.35s ease, padding 0.35s ease;
}
.hydt-banner--collapsed .hydt-banner-inner {
gap: 6px;
padding-top: 18px;
padding-bottom: 18px;
justify-content: center;
}
.hydt-banner--collapsed .hydt-banner-title {
font-size: 22px;
padding: 0;
}
.hydt-breadcrumb {

View File

@ -44,11 +44,12 @@
<script>
import { mapState } from 'vuex';
import portalFigmaScaleMixin from '@/pages/index/utils/portal-figma-scale-mixin';
import comingSoonMixin from '@/pages/index/utils/coming-soon-mixin';
// 线 mixin
import '@/pages/index/utils/coming-soon-dialog.js';
export default {
name: 'hyzt',
mixins: [portalFigmaScaleMixin, comingSoonMixin],
mixins: [portalFigmaScaleMixin],
components: {},
data() {
return {
@ -65,8 +66,13 @@ export default {
goToHref(href) {
if (href) {
window.open(href, '_blank');
} else if (typeof this.$showComingSoon === 'function') {
//
this.$showComingSoon('航运燃料专题');
} else {
this.showComingSoon();
// 退便
// eslint-disable-next-line no-alert
alert('航运燃料专题:敬请期待');
}
},
},

View File

@ -17,6 +17,33 @@
<Footer v-if="showPortalFooter" class="portal-layout-footer" />
</div>
</div>
<!-- 全局敬请期待弹窗居中显示政务绿主题 -->
<t-dialog
v-model="comingSoonVisible"
:header="false"
:footer="false"
:close-on-overlay-click="true"
:show-overlay="true"
width="420px"
placement="center"
:destroy-on-close="false"
class="coming-soon-global-dialog"
@close="handleComingSoonClose"
>
<div class="coming-soon-dialog-body">
<div class="coming-soon-dialog-icon" aria-hidden="true">
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="24" cy="24" r="22" fill="rgba(0, 185, 107, 0.12)"/>
<path d="M24 14v12" stroke="#00b96b" stroke-width="3" stroke-linecap="round"/>
<circle cx="24" cy="32" r="2" fill="#00b96b"/>
</svg>
</div>
<h3 class="coming-soon-dialog-title">{{ comingSoonText }}</h3>
<p class="coming-soon-dialog-desc">该功能正在建设中感谢您的关注与支持</p>
<button type="button" class="coming-soon-dialog-btn" @click="handleComingSoonClose">我知道了</button>
</div>
</t-dialog>
</div>
</template>
@ -31,6 +58,9 @@ import {
isPortalFigmaScalePage,
isPortalMarketPage,
} from "@/pages/index/utils/portal-figma-scale";
// 线 $showComingSoon Vue
import "@/pages/index/utils/coming-soon-dialog.js";
import { comingSoonBus } from "@/pages/index/utils/coming-soon-dialog.js";
export default {
name: "Main",
@ -41,6 +71,9 @@ export default {
isMobileViewport: false,
//
keepAliveExclude: ['LoginIndex'],
/* 全局“敬请期待”弹窗状态 */
comingSoonVisible: false,
comingSoonText: '敬请期待',
};
},
components: {
@ -148,6 +181,16 @@ export default {
});
this._docResizeObserver.observe(document.documentElement);
}
/* 监听全局"敬请期待"事件 */
this._comingSoonHandler = (text) => {
this.comingSoonText = text || '敬请期待';
this.comingSoonVisible = true;
};
this._comingSoonCloseHandler = () => {
this.comingSoonVisible = false;
};
comingSoonBus.$on('open', this._comingSoonHandler);
comingSoonBus.$on('close', this._comingSoonCloseHandler);
},
beforeDestroy() {
window.removeEventListener('resize', this.syncMobileViewport);
@ -160,6 +203,10 @@ export default {
this._docResizeObserver.disconnect();
this._docResizeObserver = null;
}
if (this._comingSoonHandler) {
comingSoonBus.$off('open', this._comingSoonHandler);
comingSoonBus.$off('close', this._comingSoonCloseHandler);
}
},
methods: {
syncMobileViewport() {
@ -203,6 +250,11 @@ export default {
// ""
handleComingSoonClose() {
this.comingSoonVisible = false;
},
// DevTools
resetDocumentClientHeight() {
const apply = () => {
@ -275,4 +327,100 @@ export default {
.content-wrap::-webkit-scrollbar {
display: none;
}
/* ---------- 全局“敬请期待”弹窗样式(居中、绿色主题) ---------- */
.coming-soon-global-dialog ::v-deep .t-dialog {
border-radius: 12px;
overflow: hidden;
box-shadow: 0 24px 60px rgba(0, 59, 26, 0.18);
}
.coming-soon-global-dialog ::v-deep .t-dialog__body {
padding: 0;
}
.coming-soon-global-dialog ::v-deep .t-dialog__close {
color: #ffffff;
background: rgba(0, 0, 0, 0.04);
border-radius: 50%;
transition: background 0.2s ease;
}
.coming-soon-global-dialog ::v-deep .t-dialog__close:hover {
background: rgba(0, 185, 107, 0.18);
color: #00b96b;
}
.coming-soon-dialog-body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 36px 32px 32px;
text-align: center;
font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
}
.coming-soon-dialog-icon {
display: flex;
align-items: center;
justify-content: center;
width: 72px;
height: 72px;
margin-bottom: 18px;
border-radius: 50%;
background: rgba(0, 185, 107, 0.08);
}
.coming-soon-dialog-icon svg {
width: 56px;
height: 56px;
}
.coming-soon-dialog-title {
margin: 0 0 8px;
font-size: 22px;
font-weight: 600;
line-height: 1.4;
color: #003b1a;
letter-spacing: 1px;
}
.coming-soon-dialog-desc {
margin: 0 0 24px;
font-size: 14px;
font-weight: 400;
line-height: 1.6;
color: #556659;
max-width: 320px;
}
.coming-soon-dialog-btn {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 140px;
height: 40px;
padding: 0 24px;
font-size: 14px;
font-weight: 500;
color: #ffffff;
background: linear-gradient(135deg, #00b96b 0%, #00a25d 100%);
border: none;
border-radius: 6px;
cursor: pointer;
transition: all 0.25s ease;
box-shadow: 0 6px 16px rgba(0, 154, 41, 0.25);
font-family: inherit;
}
.coming-soon-dialog-btn:hover {
transform: translateY(-1px);
box-shadow: 0 8px 20px rgba(0, 154, 41, 0.35);
}
.coming-soon-dialog-btn:active {
transform: translateY(0);
box-shadow: 0 4px 10px rgba(0, 154, 41, 0.25);
}
</style>

View File

@ -0,0 +1,92 @@
# 共性能力平台 · 测试环境数据导入说明
只需要 2 个 SQL 文件即可完成共性能力模块的部署。
---
## 文件清单
| # | 文件路径 | 作用 | 大小(约) |
|---|---|---|---|
| 1 | `txw-mhzc/sql/txw_mhzc_gxnl_slxxb_gxscb.sql` | 建表 DDL2 张表) | ~3KB |
| 2 | `txw-mhzc/sql/gxnl_wzxx_import_from_excel.sql` | 200 条共性能力数据导入 | ~25KB |
> ⚠️ **不需要** `fix_gxnl_slxxb_comments.sql` —— 该文件是早期排查 PowerShell 显示"乱码"时临时生成(实际是 PowerShell UTF-8 显示问题,数据库存储完全正常)。建表 DDL 已经用 `utf8mb4` + 中文 COMMENT无需再修复。
---
## 导入步骤
### 1. 连接测试环境 MySQL
```bash
# 假设测试库 = txw_mhzc
mysql -h <host> -P 3306 -u root -p txw_mhzc
```
### 2. 执行 DDL 建表
```bash
mysql --default-character-set=utf8mb4 -h <host> -P 3306 -u root -p txw_mhzc \
< txw-mhzc/sql/txw_mhzc_gxnl_slxxb_gxscb.sql
```
会创建 2 张表:
- `txw_mhzc_gxnl_slxxb` — 共性能力收录信息表30+ 字段)
- `txw_mhzc_gxnl_gxscb` — 共性能力收藏表6 字段)
### 3. 导入 200 条数据
```bash
mysql --default-character-set=utf8mb4 -h <host> -P 3306 -u root -p txw_mhzc \
< txw-mhzc/sql/gxnl_wzxx_import_from_excel.sql
```
---
## 验证
```sql
-- 1. 数据量
SELECT COUNT(*) FROM txw_mhzc_gxnl_slxxb; -- 期望 200
SELECT COUNT(*) FROM txw_mhzc_gxnl_gxscb; -- 期望 0收藏表由用户行为产生
-- 2. 各分类数量
SELECT gxnl_fl_mc, COUNT(*) AS cnt
FROM txw_mhzc_gxnl_slxxb
GROUP BY gxnl_fl_mc
ORDER BY cnt DESC;
-- 3. 全部已上架可访问
SELECT COUNT(*) FROM txw_mhzc_gxnl_slxxb
WHERE sjzt='Y' AND zt='2' AND yxbz='Y'; -- 期望 200
```
---
## 数据字段说明
`txw_mhzc_gxnl_slxxb` 关键字段(导入时已设置):
| 字段 | 含义 | 导入值 |
|---|---|---|
| `wz_uuid` | 唯一 UUID | 32 位 hex |
| `bt` | 网站名称 | 来自 Excel |
| `wz_lj` | 链接 URL | 来自 Excelhttp/https |
| `jj` | 简介(子类型) | 产品碳足迹/企业碳管理平台/CBAM/国家部委 等 |
| `gxnl_fl_dm` / `gxnl_fl_mc` | 分类代码 / 名称 | 01 碳核算平台 / 02 碳认证机构 / 03 碳交易平台 / 04 碳金融服务 / 05 碳技术咨询 |
| `bqjh` | 标签合集 | 英文逗号分隔 |
| `zt` | 业务状态 | `2` = 审核通过 |
| `sjzt` | 上架状态 | `Y` |
| `lyqd_dm` | 来源渠道 | `import` |
| `pxh` | 排序号 | 999 ~ 800倒序越大越靠前 |
| `yxbz` | 有效标志 | `Y` |
---
## 注意事项
1. **字符集**:执行 SQL 时务必加 `--default-character-set=utf8mb4`,避免历史乱码问题。
2. **重复导入**:所有 `wz_uuid` 是固定 UUID重复导入会因主键冲突报错`INSERT` 而非 `REPLACE`),符合预期;如需重导先 `TRUNCATE` 再导入。
3. **分类代码**:固定 5 个 (`01`~`05`),与前端 `CATEGORY_META` 严格对应。
4. **收藏表** `txw_mhzc_gxnl_gxscb` 不需要预置数据,由用户登录后的收藏行为产生。

View File

@ -0,0 +1,51 @@
-- ============================================================
-- 修复 txw_mhzc_gxnl_slxxb 表/字段注释乱码
-- 原因:建表时客户端连接字符集是 latin1中文被错误编码
-- 修复:逐列 ALTER 重新设置 COMMENT保留数据、保留索引、保留列定义
-- 执行mysql --default-character-set=utf8mb4 -u root txw_mhzc < fix_gxnl_slxxb_comments.sql
-- ============================================================
ALTER TABLE `txw_mhzc_gxnl_slxxb`
MODIFY COLUMN `wz_uuid` VARCHAR(50) NOT NULL COMMENT '网站信息UUID',
MODIFY COLUMN `bt` VARCHAR(200) NOT NULL COMMENT '名称1~200字符',
MODIFY COLUMN `wz_lj` VARCHAR(500) NOT NULL COMMENT '网站链接URL须http或https开头',
MODIFY COLUMN `jj` VARCHAR(40) DEFAULT NULL COMMENT '简介最多40字符用户收录必填',
MODIFY COLUMN `gxnl_fl_dm` CHAR(2) NOT NULL COMMENT '共性能力分类代码01碳核算 02碳认证 03碳交易 04碳金融 05碳咨询',
MODIFY COLUMN `gxnl_fl_mc` VARCHAR(50) DEFAULT NULL COMMENT '共性能力分类名称(服务端填充)',
MODIFY COLUMN `bqjh` VARCHAR(500) DEFAULT NULL COMMENT '标签合集英文逗号分隔最多10个单标签1~20字符',
MODIFY COLUMN `zt` CHAR(1) NOT NULL DEFAULT '1' COMMENT '业务状态0草稿 1待审核 2审核通过 3驳回 4已下架',
MODIFY COLUMN `sjzt` CHAR(1) NOT NULL DEFAULT 'N' COMMENT '上架状态Y已上架 N未上架仅zt=2时可Y',
MODIFY COLUMN `lyqd_dm` VARCHAR(20) NOT NULL DEFAULT 'user' COMMENT '来源渠道代码admin运营 user用户收录 import导入',
MODIFY COLUMN `tjr_nc` VARCHAR(50) DEFAULT NULL COMMENT '提交人昵称',
MODIFY COLUMN `tjr_lxdh` VARCHAR(20) DEFAULT NULL COMMENT '提交人联系方式(手机或座机)',
MODIFY COLUMN `yh_uuid` VARCHAR(50) DEFAULT NULL COMMENT '提交账号UUID登录用户游客为空',
MODIFY COLUMN `qyuuid` VARCHAR(50) DEFAULT NULL COMMENT '关联企业UUID',
MODIFY COLUMN `qymc` VARCHAR(200) DEFAULT NULL COMMENT '关联企业名称冗余',
MODIFY COLUMN `shyj` VARCHAR(500) DEFAULT NULL COMMENT '当前轮次审核意见(驳回必填)',
MODIFY COLUMN `shruuid` VARCHAR(50) DEFAULT NULL COMMENT '最后审核人UUID',
MODIFY COLUMN `shsj` DATETIME DEFAULT NULL COMMENT '最后审核时间Asia/Shanghai',
MODIFY COLUMN `shcs` INT NOT NULL DEFAULT 0 COMMENT '审核轮次',
MODIFY COLUMN `shls_j` TEXT DEFAULT NULL COMMENT '审核历史JSON多轮审核过渡期见设计文档8.2',
MODIFY COLUMN `pxh` INT NOT NULL DEFAULT 0 COMMENT '排序号(越大越靠前)',
MODIFY COLUMN `llcs` INT NOT NULL DEFAULT 0 COMMENT '浏览次数',
MODIFY COLUMN `sccs` INT NOT NULL DEFAULT 0 COMMENT '有效收藏数冗余yxbz=Y的gxscb计数',
MODIFY COLUMN `bbh` INT NOT NULL DEFAULT 0 COMMENT '版本号乐观锁更新时WHERE bbh匹配',
MODIFY COLUMN `lrruuid` VARCHAR(50) DEFAULT NULL COMMENT '录入人UUID门户提交或运营录入',
MODIFY COLUMN `lrrq` DATETIME DEFAULT NULL COMMENT '录入时间',
MODIFY COLUMN `xgruuid` VARCHAR(50) DEFAULT NULL COMMENT '最后修改人UUID',
MODIFY COLUMN `xgrq` DATETIME DEFAULT NULL COMMENT '最后修改时间',
MODIFY COLUMN `yxbz` CHAR(1) NOT NULL DEFAULT 'Y' COMMENT '有效标志Y有效 N逻辑删除',
COMMENT = '共性能力收录信息表';
-- ============================================================
-- 修复 txw_mhzc_gxnl_gxscb 表/字段注释乱码
-- ============================================================
ALTER TABLE `txw_mhzc_gxnl_gxscb`
MODIFY COLUMN `uuid` VARCHAR(50) NOT NULL COMMENT '收藏记录UUID',
MODIFY COLUMN `wz_uuid` VARCHAR(50) NOT NULL COMMENT '网站信息UUID',
MODIFY COLUMN `yh_uuid` VARCHAR(50) NOT NULL COMMENT '用户UUID',
MODIFY COLUMN `lrrq` DATETIME NOT NULL COMMENT '收藏时间',
MODIFY COLUMN `qxrq` DATETIME DEFAULT NULL COMMENT '取消收藏时间',
MODIFY COLUMN `yxbz` CHAR(1) NOT NULL DEFAULT 'Y' COMMENT '有效标志Y已收藏 N已取消',
COMMENT = '共性能力收藏表';

View File

@ -3,6 +3,7 @@ package com.css.txw.mhzc.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.css.ggzc.framework.common.pojo.CommonResult;
import com.css.txw.mhzc.pojo.vo.GxnlGxscToggleReqVO;
import com.css.txw.mhzc.pojo.vo.GxnlSlxxAuditReqVO;
import com.css.txw.mhzc.pojo.vo.GxnlSlxxSubmitReqVO;
import com.css.txw.mhzc.pojo.vo.GxnlWzxxListReqVO;
import com.css.txw.mhzc.pojo.vo.GxnlWzxxVO;
@ -45,6 +46,12 @@ public class GxnlController {
return CommonResult.success(gxnlService.submitSlxx(reqVO));
}
@PostMapping("/slxx/audit")
@Operation(summary = "共性能力收录审核(运营/管理员)")
public CommonResult<String> audit(@RequestBody GxnlSlxxAuditReqVO reqVO) {
return CommonResult.success(gxnlService.audit(reqVO));
}
@PostMapping("/gxsc/toggle")
@Operation(summary = "共性能力收藏切换")
public CommonResult<String> toggleGxsc(@RequestBody GxnlGxscToggleReqVO reqVO) {

View File

@ -34,4 +34,24 @@ public interface TxwMhzcGxnlSlxxbMapper extends BaseMapper<TxwMhzcGxnlSlxxbDO> {
.orderByDesc(TxwMhzcGxnlSlxxbDO::getLrrq);
return selectPage(page, wrapper);
}
/** 我的收藏列表:不过滤 zt/sjzt仅按 wzUuid 集合查询有效条目 */
default Page<TxwMhzcGxnlSlxxbDO> favoriteList(GxnlWzxxListReqVO reqVO, Set<String> scWzUuids) {
int pageNo = reqVO == null || reqVO.getPageNo() == null || reqVO.getPageNo() < 1 ? 1 : reqVO.getPageNo();
int pageSize = reqVO == null || reqVO.getPageSize() == null || reqVO.getPageSize() < 1 ? 10 : reqVO.getPageSize();
if (pageSize > 500) {
pageSize = 500;
}
Page<TxwMhzcGxnlSlxxbDO> page = new Page<>(pageNo, pageSize);
if (GyUtils.isNull(scWzUuids)) {
page.setRecords(new java.util.ArrayList<>());
return page;
}
QueryWrapperX<TxwMhzcGxnlSlxxbDO> wrapper = new QueryWrapperX<>();
wrapper.lambda()
.eq(TxwMhzcGxnlSlxxbDO::getYxbz, "Y")
.in(TxwMhzcGxnlSlxxbDO::getWzUuid, scWzUuids)
.orderByDesc(TxwMhzcGxnlSlxxbDO::getLrrq);
return selectPage(page, wrapper);
}
}

View File

@ -0,0 +1,21 @@
package com.css.txw.mhzc.pojo.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class GxnlSlxxAuditReqVO implements Serializable {
/** 网站信息 UUID */
private String wzUuid;
/** 审核结果2 通过 / 3 驳回 */
private String shjgDm;
/** 审核意见(驳回时必填) */
private String shyj;
/** 乐观锁版本号 */
private Integer bbh;
}

View File

@ -2,6 +2,7 @@ package com.css.txw.mhzc.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.css.txw.mhzc.pojo.vo.GxnlGxscToggleReqVO;
import com.css.txw.mhzc.pojo.vo.GxnlSlxxAuditReqVO;
import com.css.txw.mhzc.pojo.vo.GxnlSlxxSubmitReqVO;
import com.css.txw.mhzc.pojo.vo.GxnlWzxxListReqVO;
import com.css.txw.mhzc.pojo.vo.GxnlWzxxVO;
@ -12,6 +13,8 @@ public interface TxwMhzcGxnlService {
String submitSlxx(GxnlSlxxSubmitReqVO reqVO);
String audit(GxnlSlxxAuditReqVO reqVO);
String toggleGxsc(GxnlGxscToggleReqVO reqVO);
Page<GxnlWzxxVO> myFavoriteList(GxnlWzxxListReqVO reqVO);

View File

@ -11,6 +11,7 @@ import com.css.txw.mhzc.mapper.TxwMhzcGxnlSlxxbMapper;
import com.css.txw.mhzc.pojo.domain.TxwMhzcGxnlGxscbDO;
import com.css.txw.mhzc.pojo.domain.TxwMhzcGxnlSlxxbDO;
import com.css.txw.mhzc.pojo.vo.GxnlGxscToggleReqVO;
import com.css.txw.mhzc.pojo.vo.GxnlSlxxAuditReqVO;
import com.css.txw.mhzc.pojo.vo.GxnlSlxxSubmitReqVO;
import com.css.txw.mhzc.pojo.vo.GxnlWzxxListReqVO;
import com.css.txw.mhzc.pojo.vo.GxnlWzxxVO;
@ -73,6 +74,53 @@ public class TxwMhzcGxnlServiceImpl implements TxwMhzcGxnlService {
return "success";
}
@Override
@Transactional(rollbackFor = Exception.class)
public String audit(GxnlSlxxAuditReqVO reqVO) {
if (reqVO == null || GyUtils.isNull(reqVO.getWzUuid()) || GyUtils.isNull(reqVO.getShjgDm())) {
throw new IllegalArgumentException("参数不完整");
}
if (!"2".equals(reqVO.getShjgDm()) && !"3".equals(reqVO.getShjgDm())) {
throw new IllegalArgumentException("审核结果代码无效,仅支持 2(通过) 或 3(驳回)");
}
if ("3".equals(reqVO.getShjgDm()) && GyUtils.isNull(trim(reqVO.getShyj()))) {
throw new IllegalArgumentException("驳回时必须填写审核意见");
}
TxwMhzcGxnlSlxxbDO slxx = slxxbMapper.selectById(reqVO.getWzUuid());
if (slxx == null || !"Y".equals(slxx.getYxbz())) {
throw new IllegalStateException("条目不存在或已删除");
}
if (!"1".equals(slxx.getZt())) {
throw new IllegalStateException("当前状态不允许审核,仅待审核状态(zt=1)可审核");
}
if (reqVO.getBbh() != null && !reqVO.getBbh().equals(slxx.getBbh())) {
throw new IllegalStateException("数据已被修改,请刷新后重试");
}
String yhUuid = SessionUtils.getYhUuid();
Date now = new Date();
TxwMhzcGxnlSlxxbDO update = new TxwMhzcGxnlSlxxbDO();
update.setWzUuid(reqVO.getWzUuid());
update.setShyj(trim(reqVO.getShyj()));
update.setShruuid(yhUuid);
update.setShsj(now);
update.setShcs((slxx.getShcs() == null ? 0 : slxx.getShcs()) + 1);
update.setXgruuid(yhUuid);
update.setXgrq(now);
update.setBbh((slxx.getBbh() == null ? 0 : slxx.getBbh()) + 1);
if ("2".equals(reqVO.getShjgDm())) {
update.setZt("2");
update.setSjzt("Y");
} else {
update.setZt("3");
update.setSjzt("N");
}
int rows = slxxbMapper.updateById(update);
if (rows == 0) {
throw new IllegalStateException("审核更新失败,请重试");
}
return "success";
}
@Override
@Transactional(rollbackFor = Exception.class)
public String toggleGxsc(GxnlGxscToggleReqVO reqVO) {
@ -123,9 +171,13 @@ public class TxwMhzcGxnlServiceImpl implements TxwMhzcGxnlService {
@Override
public Page<GxnlWzxxVO> myFavoriteList(GxnlWzxxListReqVO reqVO) {
GxnlWzxxListReqVO query = reqVO == null ? new GxnlWzxxListReqVO() : reqVO;
query.setOnlySc(true);
return wzxxList(query);
Set<String> scWzUuids = loadScWzUuids(true);
if (GyUtils.isNull(scWzUuids)) {
return emptyPage(reqVO);
}
Page<TxwMhzcGxnlSlxxbDO> page = slxxbMapper.favoriteList(reqVO, scWzUuids);
Set<String> favoriteSet = new HashSet<>(scWzUuids);
return toVoPage(page, favoriteSet);
}
private void adjustSccs(TxwMhzcGxnlSlxxbDO slxx, int delta) {
@ -189,7 +241,8 @@ public class TxwMhzcGxnlServiceImpl implements TxwMhzcGxnlService {
GxnlWzxxVO vo = BeanUtils.toBean(item, GxnlWzxxVO.class);
vo.setBt1(item.getBt());
vo.setScbz(favoriteSet.contains(item.getWzUuid()) ? "Y" : "N");
vo.setYxzt("Y");
boolean valid = "Y".equals(item.getYxbz()) && "2".equals(item.getZt()) && "Y".equals(item.getSjzt());
vo.setYxzt(valid ? "Y" : "N");
return vo;
}