feat: 共性能力平台全面优化6项

① 空状态/加载态替换为 EmptyState + SkeletonCard 组件
② 列表顶部增加统计摘要 (收录链接/覆盖分类/我的收藏)
③ 卡片去灰色实线边框,改用阴影,与列表页统一
④ 卡片 hover 上浮 -3px + 绿色阴影
⑤ '查看更多'按钮升级:箭头图标+hover圆角边框+绿色反馈
⑥ 收藏空态加引导按钮'浏览链接'

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
liulujian 2026-07-04 23:41:07 +08:00
parent dc1fcb5134
commit 5bd0c81020

View File

@ -155,8 +155,15 @@
<span class="gxnlpt-favorites-star" aria-hidden="true"></span> <span class="gxnlpt-favorites-star" aria-hidden="true"></span>
<h2 class="gxnlpt-block-title">我的收藏</h2> <h2 class="gxnlpt-block-title">我的收藏</h2>
</header> </header>
<div v-if="favoritesLoading" class="gxnlpt-state">加载中...</div> <SkeletonCard v-if="favoritesLoading" :count="3" />
<div v-else-if="!favoriteCards.length" class="gxnlpt-state">暂无收藏</div> <EmptyState
v-else-if="!favoriteCards.length"
type="empty"
text="暂无收藏"
hint="浏览共性能力链接,收藏感兴趣的内容"
action-text="浏览链接"
@action="contentView = 'list'"
/>
<div v-else class="gxnlpt-card-grid"> <div v-else class="gxnlpt-card-grid">
<article <article
v-for="card in favoriteCards" v-for="card in favoriteCards"
@ -189,6 +196,10 @@
</section> </section>
<template v-else> <template v-else>
<!-- 统计摘要 -->
<StatsSummary v-if="!pageLoading" :items="statsItems" />
<!-- 加载骨架 -->
<SkeletonCard v-if="pageLoading" :count="6" />
<section <section
v-for="{ item, index } in listSections" v-for="{ item, index } in listSections"
:key="item.id" :key="item.id"
@ -201,8 +212,12 @@
<h2 class="gxnlpt-block-title">{{ item.title }}</h2> <h2 class="gxnlpt-block-title">{{ item.title }}</h2>
</header> </header>
<div v-if="pageLoading && index === 0" class="gxnlpt-state">加载中...</div> <div v-if="pageLoading && index === 0"></div>
<div v-else-if="!pageLoading && !item.displayList.length" class="gxnlpt-state">暂无相关服务</div> <EmptyState
v-else-if="!pageLoading && !item.displayList.length"
type="empty"
text="暂无相关服务"
/>
<template v-else-if="item.displayList.length"> <template v-else-if="item.displayList.length">
<div class="gxnlpt-card-grid"> <div class="gxnlpt-card-grid">
<article <article
@ -235,7 +250,8 @@
class="gxnlpt-more-wrap" class="gxnlpt-more-wrap"
> >
<button type="button" class="gxnlpt-more" @click="toggleViewMore(item)"> <button type="button" class="gxnlpt-more" @click="toggleViewMore(item)">
{{ item.visibleCount >= item.cardList.length ? '收起' : '查看更多>>' }} <span>{{ item.visibleCount >= item.cardList.length ? '收起' : '查看更多' }}</span>
<span class="gxnlpt-more-arrow" :class="{ 'is-reverse': item.visibleCount >= item.cardList.length }"></span>
</button> </button>
</div> </div>
</template> </template>
@ -290,6 +306,9 @@
<script> <script>
import GxnlptCardTags from '@/pages/index/views/gxnlpt/components/GxnlptCardTags.vue'; import GxnlptCardTags from '@/pages/index/views/gxnlpt/components/GxnlptCardTags.vue';
import EmptyState from '@/pages/index/components/EmptyState.vue';
import StatsSummary from '@/pages/index/components/StatsSummary.vue';
import SkeletonCard from '@/pages/index/components/SkeletonCard.vue';
// import api from '@/pages/index/api/gxnl/index.js'; // TODO // import api from '@/pages/index/api/gxnl/index.js'; // TODO
// 204 // 204
// .xlsx // .xlsx
@ -705,7 +724,7 @@ const SUBMIT_FORM_EMPTY = () => ({
export default { export default {
name: 'GxnlptIndex', name: 'GxnlptIndex',
mixins: [portalFigmaScaleMixin, comingSoonMixin], mixins: [portalFigmaScaleMixin, comingSoonMixin],
components: { GxnlptCardTags }, components: { GxnlptCardTags, EmptyState, StatsSummary, SkeletonCard },
data() { data() {
return { return {
starOutline, starOutline,
@ -764,6 +783,16 @@ export default {
}); });
return list; return list;
}, },
statsItems() {
const totalLinks = this.categoryList.reduce((s, c) => s + c.cardList.length, 0);
const totalCats = this.categoryList.filter((c) => c.cardList.length > 0).length;
const totalFavs = this.favoriteCards.length;
return [
{ label: '收录链接', value: totalLinks || 0 },
{ label: '覆盖分类', value: totalCats || '—' },
{ label: '我的收藏', value: totalFavs || 0 },
];
},
}, },
created() { created() {
this.stackedNavLayout = readStackedNavLayout(); this.stackedNavLayout = readStackedNavLayout();
@ -2454,15 +2483,16 @@ html.portal-figma-scale-active .gxnlpt-page {
min-height: @gxnlpt-card-min-height; min-height: @gxnlpt-card-min-height;
padding: @gxnlpt-card-padding-y @gxnlpt-card-padding-x; padding: @gxnlpt-card-padding-y @gxnlpt-card-padding-x;
background: #fff; background: #fff;
border: 1px solid fade(#000, 10%); border: none;
border-radius: @gxnlpt-card-radius; border-radius: @gxnlpt-card-radius;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
cursor: pointer; cursor: pointer;
transition: border-color 0.2s ease, box-shadow 0.2s ease, border-radius 0.2s ease; transition: transform 0.2s ease, box-shadow 0.2s ease, border-radius 0.2s ease;
&:hover { &:hover {
border-color: @home-color-primary-green; transform: translateY(-3px);
border-radius: @gxnlpt-card-radius-hover; border-radius: @gxnlpt-card-radius-hover;
box-shadow: @home-shadow-card-green; box-shadow: 0 8px 24px rgba(0, 154, 41, 0.12);
} }
} }
@ -2579,9 +2609,11 @@ html.portal-figma-scale-active .gxnlpt-page {
} }
.gxnlpt-more { .gxnlpt-more {
display: inline-block; display: inline-flex;
align-items: center;
gap: 4px;
margin: 0; margin: 0;
padding: 0; padding: 4px 12px;
font-family: @home-font-family; font-family: @home-font-family;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
@ -2592,19 +2624,31 @@ html.portal-figma-scale-active .gxnlpt-page {
cursor: pointer; cursor: pointer;
appearance: none; appearance: none;
background: transparent; background: transparent;
border: none; border: 1px solid transparent;
border-radius: 6px;
outline: none; outline: none;
transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
&:hover { &:hover {
opacity: 0.75; color: @home-color-primary-green;
border-color: fade(@home-color-primary-green, 30%);
background: fade(@home-color-primary-green, 4%);
} }
&:focus-visible { &:focus-visible {
box-shadow: 0 0 0 2px fade(@home-color-primary-dark, 25%); box-shadow: 0 0 0 2px fade(@home-color-primary-dark, 25%);
border-radius: 2px; border-radius: 6px;
} }
} }
.gxnlpt-more-arrow {
display: inline-block;
font-size: 18px;
line-height: 1;
transition: transform 0.2s ease;
&.is-reverse { transform: rotate(180deg); }
}
/* 收录表单 */ /* 收录表单 */
.gxnlpt-submit { .gxnlpt-submit {
display: flex; display: flex;