feat:新增移动端适配

This commit is contained in:
liulong 2026-05-26 15:38:01 +08:00
parent 5147a55915
commit 34c7cc4393
24 changed files with 3272 additions and 376 deletions

View File

@ -0,0 +1,415 @@
# 门户全终端自适应技术实现方案
> 项目:`txw-mhzc-web`Vue 2.6 + vue-cli 4 + TDesign Vue + Less
> 目标:移动端重新排版 + 平板/桌面/超宽屏统一自适应,兼顾视觉一致性与可用性
> 参考站点:[上海市企业走出去综合服务平台](https://segg.sh.gov.cn/)(固定版心 + 断点响应,非整页 scale
> 版本v1.0 | 2026-05-26
---
## 一、方案总览与原则
### 1.1 技术路线(推荐)
采用 **「CSS 设计令牌 + 断点媒体查询 + 流式布局」** 为主、**「路由级 scale 画布」** 为辅的 **混合方案**
| 场景 | 策略 | 说明 |
|------|------|------|
| 门户主站home2、fwsc、gxnlpt、qych 等) | 响应式重排 | 与 [segg.sh.gov.cn](https://segg.sh.gov.cn/) 同类政务门户一致 |
| 固定画布子系统iframe 大屏、部分 mhNewMain | 可选 `scale` | 仅 `meta.fixedCanvas === true` 的路由启用 |
| 禁止 | 全站整页 `transform: scale` | 手机端字糊、触控区缩小、弹层错位 |
**视觉一致性** 指:品牌色、版心对齐关系、模块层级、间距节奏在各断点可预测变化,而非「桌面缩小版像素级一致」。
### 1.2 与现有代码的关系
仓库内已具备基础能力,实施时 **优先激活与统一**,避免重复引入重型框架:
| 资产 | 路径 | 状态 |
|------|------|------|
| 断点常量 | `src/pages/index/styles/breakpoints.less` | 已定义 |
| 版心 / 栅格变量 | `src/pages/index/styles/page-layout.less` | 已定义 |
| 移动端全局样式 | `src/pages/index/styles/mobile-adaptation.less` | **需在 `main.js` 引入** |
| 验证清单 | `docs/test-reports/mobile-adaptation-checklist.md` | 已存在 |
| 大屏 scale 试验 | `app.vue` / `mhNewMain.vue` | 与门户主流程隔离 |
---
## 二、开源方案调研与对比(第一部分交付)
### 2.1 筛选标准
- 持续维护(近 12 个月有 release 或活跃 commit
- 社区文档完善、Issue 可检索
- 兼容 iOS 12+、Android 8+、Chrome / Safari / Edge 近两代
- 轻量化:不强制替换 Vue 技术栈
- 集成成本低:与 Vue CLI 4、Less、TDesign 共存
### 2.2 方案分类说明
自适应实现分四类,**门户类项目通常只需 A + 少量 D**
- **A. CSS 响应式体系**断点、Grid/Flex、CSS 变量)— 主推
- **B. 构建期单位转换**px→vw/rem— 活动页/H5 子模块可选
- **C. 运行时整页 scale**autofit、v-scale-screen— 仅大屏/数据可视化
- **D. JS 能力增强**断点检测、懒加载、resize 节流)— 辅助
以下 **不推荐** 作为门户主方案全量引入Bootstrap 全量、Element UI 第二套组件库、整站 rem flexibleamfe-flexible— 与现有 TDesign + Less 变量体系冲突且收益低。
### 2.3 对比清单
| 方案 | 类型 | 维护 / 生态 | 核心特性 | 适用场景 | 集成流程(概要) | 优点 | 缺点 |
|------|------|-------------|----------|----------|------------------|------|------|
| **原生 CSS + 项目令牌**`page-layout` / `breakpoints` | A | 标准、零依赖 | 变量、@media、Grid、clamp | **门户全站(首选)** | 已有;补 `main.js` 引入 `mobile-adaptation.less` | 可控、无运行时开销、与 Figma 1440 对齐 | 需逐页改样式 |
| **TDesign Vue Row/Col + 断点** | A | 腾讯维护 | 24 栅格、`xs/sm/md/lg` | 表单、列表、后台区块 | 已依赖,按文档包一层 | 与组件库一致 | 需熟悉 TDesign 断点 API |
| **Tailwind CSS**(项目已部分引入) | A | 活跃 | 工具类、响应式前缀 `md:` | 局部快速排版 | `vue.config` 配 PostCSS避免与 Less 变量双主源 | 开发快 | 与 Less 混用易混乱,需约束使用范围 |
| **postcss-px-to-viewport-modern** | B | 活跃 fork | 设计稿 px 自动转 vw | 375 宽 H5 活动页 | `vue.config.js``css.loaderOptions.postcss` | 一稿多宽省事 | 不适合 1200 版心门户;与变量体系冲突 |
| **postcss-pxtorem** + lib-flexible | B | 经典但大屏少用 | rem 等比 | 老 H5 | flexible 脚本 + postcss | 移动端成熟 | Vue2 门户性价比低 |
| **autofit.js** | C | 活跃 | 整页 scale、ignore 节点 | 1920 固定画布大屏 | `mounted``autofit.init({ dw, dh, el })` | 接入极简 | 门户手机不可用 |
| **v-scale-screen@1.x** | C | 活跃 | Vue 2.6 组件包裹 scale | 可视化大屏页 | `Vue.use` + 包一层 template | 与 Vue 集成好 | 仅适合大屏路由 |
| **@fit-screen/vue** | C | 中等 | Vue2/3 scale 封装 | 同上 | 需 `@vue/composition-api` | 类型友好 | Vue 2.6 多一层依赖 |
| **@vueuse/core` `useBreakpoints`** | D | 极活跃 | `matchMedia` 响应式 | 需 JS 切换布局时 | Vue 2.7+ 原生2.6 用 composition-api | API 优雅 | Vue 2.6 需额外插件 |
| **vue-mq / vue-screen** | D | 一般 | 断点 inject | 少量组件切换 | 注册插件 + `$mq` | 简单 | 维护不如 VueUse |
| **Container Queries**(原生 CSS | A | 浏览器已普及 | 按父容器宽度适配卡片 | 卡片、侧栏模块 | `@container` + `container-type` | 比纯 vw 稳 | 需 postcss 插件做旧版兜底(可选) |
### 2.4 本项目推荐组合(集成成本最低)
```
主路径page-layout.less + breakpoints.less + mobile-adaptation.less + 各页 @media
组件层TDesign Grid / Drawer移动菜单
增强层v-lazy已有清单+ resize 节流 + ECharts resize
隔离路径meta.fixedCanvas 路由 → autofit 或 v-scale-screen可选
```
**不引入** 新的 UI 框架;**不** 全站 postcss-px-to-viewport**不** 全站 scale。
---
## 三、断点设计规范
### 3.1 断点表(与 Figma / 现有 Less 对齐)
| 令牌 | 范围 | 设备 | 版心 / 列数策略 |
|------|------|------|-----------------|
| `xs` | 0 359px | 小屏手机 | 100% 宽gutter 12px栅格 1 列 |
| `sm` | 360 480px | 常规手机 | 100% 宽gutter 16px栅格 1 列 |
| `md` | 481 767px | 大屏手机 / 小平板竖屏 | 100% 宽gutter 1636px栅格 12 列 |
| `lg` | 768 1023px | 平板 | max-width 100%,部分 2 列 |
| `xl` | 1024 1279px | 小桌面 | 版心可 100% 或保留 padding 40px |
| `2xl` | 1280 1439px | 标准桌面Figma 1440 画布) | `--page-content-max-width: 1200px` |
| `3xl` | 1440 1919px | 宽桌面 | 版心 1200 居中,两侧留白随屏宽增加 |
| `4xl` | ≥ 1920px | 超宽屏 | 版心仍 1200**禁止** 无限制拉伸内容区 |
Less 常量(已有,建议扩展):
```less
// breakpoints.less
@mq-mobile-xs-max: 360px;
@mq-mobile-sm-max: 480px;
@mq-mobile-max: 767px;
@mq-tablet-max: 1023px;
@mq-desktop-sm-max: 1279px;
@mq-desktop-max: 1439px;
@mq-ultrawide-min: 1920px;
```
### 3.2 媒体查询书写约定
1. **移动优先(推荐新代码)**:默认手机样式 → `min-width` 逐级增强。
2. **桌面优先(兼容旧代码)**:保持现有 `max-width` 块,逐步迁移。
3. **禁止** 同一属性在多个断点反复覆盖且无变量来源。
4. 断点内只改 **CSS 变量****布局模式**列数、flex-direction避免魔法数字散落。
### 3.3 设计令牌扩展(`:root`
`page-layout.less` 按断点扩展(示例):
```less
// 平板
@media (min-width: 768px) and (max-width: 1023px) {
:root {
--portal-services-fwsc-cols: 2;
--page-section-padding-y: 48px;
}
}
// 超宽屏:版心不变,仅增大「出血背景」感知
@media (min-width: 1920px) {
:root {
--page-content-max-width: 1200px; /* 保持 */
}
}
```
---
## 四、流式布局适配逻辑
### 4.1 版心模型(与 segg 类门户一致)
```
┌──────────────────────────────────────────── viewport ────┐
│ margin-auto │
│ ┌──────────────── page-content-max 1200 ─────────────┐ │
│ │ gutter │ content aligned to nav logo │ │
│ └────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
```
- 容器:`.page-content-wrap` / `.page-nav-inner`(已有)
- 宽度:`width: 100%` + `max-width: var(--page-content-max-width)`
- 小屏:`--page-content-max-width: 100%``mobile-adaptation.less` 已定义)
### 4.2 栅格与模块列数
| 模块 | ≥1280 | 7681279 | 481767 | ≤480 |
|------|-------|----------|---------|------|
| 服务中心四宫格 | 4 列 | 2 列 | 2 列 | 1 列 |
| 共性能力卡片 | 34 列 | 2 列 | 2 列 | 1 列 |
| 页脚链接组 | 横排 | 横排/折行 | 纵排 | 纵排 |
| 首页 Hero 搜索 | 横排 | 横排 | 纵排 | 纵排home2 已部分实现) |
实现方式:
```less
.portal-services-grid {
display: grid;
grid-template-columns: repeat(var(--portal-services-fwsc-cols, 4), minmax(0, 1fr));
gap: var(--portal-services-grid-gap, 24px);
}
```
### 4.3 超宽屏策略
- **内容区不随 4K 变宽**:保持 1200px 版心,避免行长过长。
- **全宽背景** 使用 `.home-section-bleed()`(已有 mixin铺满视口。
- **装饰性大图** 使用 `max-width: 100%` + 居中,而非拉伸版心。
### 4.4 大屏固定画布(可选子路由)
`route.meta.layout === 'fixed-canvas'`
```js
scale = Math.min(innerWidth / DESIGN_W, innerHeight / DESIGN_H)
```
与门户响应式 **路由级隔离**,避免 `app.vue` 全局 scale 影响主站。
---
## 五、弹性图片与媒体资源
### 5.1 图片
| 策略 | 实现 |
|------|------|
| 响应式尺寸 | `max-width: 100%; height: auto;`mobile-adaptation 已有) |
| 分辨率适配 | `<img srcset="..." sizes="(max-width: 768px) 100vw, 1200px">` 对 Banner/大图 |
| 懒加载 | `loading="lazy"``v-lazy`(见 checklist |
| 格式 | 优先 WebP构建或 CDNPNG 用于透明图标 |
| 艺术方向 | 窄屏可选裁切图(`picture` + `source media` |
### 5.2 视频 / 背景
- 首页 Banner 视频:窄屏降低 `preload`,必要时 `poster` 静帧。
- CSS 背景:`background-size: cover; background-position: center;`
- 避免固定 `1920px` 背景宽导致小屏横向滚动(参考政务站仅背景层用 1920 的情况)。
### 5.3 图标与 SVG
- 图标优先 SVG / iconfont随字号 `em` 缩放。
- Font Awesome 已引入,控制只打包使用子集(长期优化)。
---
## 六、响应式交互适配策略
### 6.1 导航
| 断点 | 行为 |
|------|------|
| ≥768px | 横排菜单(`new-nav` / `nav/index2` |
| <768px | 隐藏横菜单汉堡 + Drawer/侧滑`mobile-menu-item` 样式已有 |
### 6.2 触控与表单WCAG 2.5 目标尺寸)
- 可点击区域 **≥ 48×48px**`mobile-adaptation.less`
- 输入框 `font-size: 16px` 防止 iOS 聚焦放大
- `touch-action: pan-y` 于主滚动容器,减少误触横向滑动
### 6.3 弹层与固定元素
- TDesign `Dialog` / `Drawer`:窄屏优先 `placement` 全屏或底部抽屉。
- **避免** 在带 `transform` 的 scale 祖先内挂 `position: fixed` 弹层。
- 返回顶部、悬浮客服:小屏抬高 `bottom`,避开安全区:
```css
padding-bottom: env(safe-area-inset-bottom, 0);
```
### 6.4 JS 辅助(按需)
```js
// utils/breakpoint.js
export const BP = { mobile: 768, tablet: 1024, desktop: 1280 }
export function getDeviceClass() {
const w = window.innerWidth
if (w < BP.mobile) return 'is-mobile'
if (w < BP.tablet) return 'is-tablet'
if (w < BP.desktop) return 'is-desktop-sm'
return 'is-desktop'
}
```
用于ECharts `resize`、是否加载重动画、Tab 横滑 vs 下拉。
### 6.5 图表ECharts
```js
window.addEventListener('resize', throttle(() => chart.resize(), 200))
```
移动端 legend 改底部、减小 `grid` 边距,在 `@media``getDeviceClass()` 分支配置 option。
---
## 七、性能优化措施
| 项 | 措施 |
|----|------|
| CSS | 断点样式集中在 `mobile-adaptation.less`,避免每组件重复 `@media` |
| 图片 | 懒加载 + 合适尺寸,首屏 LCP 图不用 lazy |
| JS | `resize` / `scroll` 监听必须 throttle200300ms |
| 字体 | 子集化或系统字体栈回退,减少 FOUT |
| 长列表 | 虚拟滚动TDesign Table 大数据)或分页 |
| 动画 | `prefers-reduced-motion: reduce` 关闭非必要动效 |
| 构建 | 路由懒加载(已有 vue-router按页拆分 CSS |
---
## 八、落地实施路线图
### 阶段 0基线1 天)
- [ ] `main.js` 增加:`import './styles/mobile-adaptation.less'`
- [ ] 确认 `public/index.html` viewport`width=device-width, initial-scale=1`
- [ ] 移除或路由隔离 `app.vue` 未使用的全局 scale 逻辑
- [ ] 统一断点:新代码引用 `breakpoints.less` 变量
### 阶段 1全局与导航23 天)
- [ ] 导航:移动 Drawer + 桌面横栏双态完整联调
- [ ] `page-layout.less`:补齐 tablet / ultrawide 变量
- [ ] 页脚、面包屑窄屏折行
### 阶段 2核心页面重排58 天)
按 checklist 顺序:
1. `home2/index.vue` — 合并零散 `@media` 到变量驱动
2. `fwsc` — 四宫格 + 列表筛选堆叠
3. `gxnlpt` — 侧栏置顶 + 卡片单列
4. `qych` — 法案区块与卡片
每页完成即在 `mobile-adaptation-checklist.md` 打勾。
### 阶段 3大屏与回归2 天)
- [ ] ≥1280 / 1920 / 2560 版心居中与背景出血
- [ ] 固定画布子路由(若有)单独测 scale
- [ ] 桌面回归:与改版前 1280 对齐
### 阶段 4验收
- 真机iOS Safari、Android Chrome宽度 320 / 390 / 414
- 桌面1280、1440、1920、2560
- 工具Chrome DevTools + Lighthouse 移动端评分
---
## 九、目录与文件规范(建议)
```
src/pages/index/styles/
breakpoints.less # 断点常量(唯一来源)
page-layout.less # 版心、间距令牌
mobile-adaptation.less # 全局移动端 @media
mixins/
responsive.less # .respond-to(@bp) 等 mixin可选新建
src/pages/index/utils/
breakpoint.js # 设备类名 / matchMedia可选
docs/
responsive-adaptation-implementation-plan.md # 本文档
test-reports/mobile-adaptation-checklist.md # 验收清单
```
### Less mixin 示例(可选)
```less
.respond-to(@max) when (default()) {
@media screen and (max-width: @max) {
@content();
}
}
// 使用
.respond-to(@mq-mobile-max) {
.foo { flex-direction: column; }
}
```
---
## 十、风险与决策记录
| 风险 | 缓解 |
|------|------|
| 双轨样式(桌面 scale + 移动重排)冲突 | 路由 meta 明确 `layout: portal \| fixed-canvas` |
| TDesign 组件窄屏溢出 | 表格外包 `.table-scroll-x { overflow-x: auto }` |
| 旧页大量魔法 `@media` | 逐页迁移,不一次性重写 |
| 超宽屏内容过宽 | 严格 max-width 1200不改用 scale 撑满 |
---
## 十一、附录:快速集成示例
### A. 启用全局移动端样式
```js
// main.js
import './styles/page-layout.less';
import './styles/mobile-adaptation.less';
```
### B. 页面内仅补结构差异
```vue
<template>
<div class="page-content-wrap portal-page">
<section class="portal-services-grid">...</section>
</div>
</template>
```
列数由 `--portal-services-fwsc-cols` 控制,不在组件内写死 `width: 280px`
### C. 可选大屏路由autofit
```js
// 仅 fixed-canvas 布局的 mounted
import autofit from 'autofit.js'
autofit.init({ dw: 1920, dh: 1080, el: '#fixed-canvas-root', resize: true })
```
---
## 十二、结论
- **移动端重新排版**:依赖 **CSS 变量 + 断点 + Grid/Flex**,激活并扩展现有 `mobile-adaptation.less`,逐页改造核心视图。
- **大屏/超宽屏****版心锁定 + 背景出血**,与 [segg.sh.gov.cn](https://segg.sh.gov.cn/) 同类,**不用** 整站 scale。
- **开源框架**:不新增重型 UI 框架;可选 **autofit / v-scale-screen** 仅服务固定画布子系统;主站以 **原生响应式 + TDesign** 为准。
本文档为实施依据,具体排期可与 `mobile-adaptation-checklist.md` 联合跟踪。

View File

@ -0,0 +1,626 @@
[
{
"id": "2355260636636434388",
"created_at": "2026-05-19T11:00:47Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/checkpoints/nvH/BPp/NhTJiA621TV7ZTzC/tn.png?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=HXjjQ~MPHME0Rzokq8RJAzmWnsOmKsaQhMJUrYHAqyYh1kq~dpYOSM7AdopdB-EtcFFocSQdtjfotLh2yJ9obVjPiLTDjYC-ZS8d0NWhy2u5CSCgnDRgK-RRj3tGCoJL-0QF3ecAjE98RwgW1kphzJyoy~5b3ea3VwiW-URo5LUtir6v5x~BQQByOSmFQ4UXyn7yk9DEIu5CHyKr9ZMysIrE4xc6SmokRc8d7WAYaIp65kK4gTea-YybSTXiD6SGbtIcX40l73mAVYGEZVTv0dCOT2Yfm1iJN0lHgAOrYLoZH~5BEGnRQxrNIOYnjk~3sYdbqXsb4-6uc77btROV4g__"
},
{
"id": "2355255569673109515",
"created_at": "2026-05-19T11:07:53Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/c4b16d6a-6ef2-4a47-afef-527e713eb46f?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=VOViiA5TyYCtbt3fqQ8XC3pCJHrYKrc4bU5-9lHkSGYTySwPPXGPqL8StQEdqp91xOHieU42ACFhMI1rorAHhlSwPlaEy5EjpDWptr5pSLvZJrapx-QnzGY7RdzfowAnBAD1siXSY0KtgQXMhiLYCeoLzYWpCwG4FktDUFWkIK~vcg9k5Q4j1l9IkfcJ1TWu~Tzume9B57gx-JeKaIDfuJWR5MijhZzeHXGn0jGfIveKufVHIM4QUJ8lEMbMAY32eXa~a8W7HTJjfx-VddF8JMZgRLdBTbYmlrxj6d-RBk6WC3aPclRfkSfjg~CjxGk5VH6oU6apDcSYzE1hK7RIiA__"
},
{
"id": "2355262114657813884",
"created_at": "2026-05-19T11:38:29Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/cc6a9199-c9a6-4982-a89b-37b88bbaa182?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=HlVL9q2LA3eaJzF1t-NSCNn3FTPVDjhCgJxZp~e07B7FbT2yy3cSzu-h3eSZ1Ljw~l-Kz5mXlgVaMd0fPTB7C3VN-LfdZpL~5ERi3QK97CLCmtZSHh6fFWWGDMi9PpszksULpMjnzKW46vSP29izcTVtyJkSWDX4ahr83a9odcLJ5wkt6RvwX4yyfphBhh8h25SSr-OBcu1SsGyYtbrE5d2E7v9A5gdv2awYLG~UQTEXlhzTLV~nADMxcdeBrJn6yQe1MsTu~spQ8XjeNrsA89x5mOTMkEEl9i8PhZmqWvE~3wLgWjomegm5kAYcDG3OM-4naIPP9ulm9mWCmM4AVQ__"
},
{
"id": "2355299584538351293",
"created_at": "2026-05-19T13:57:21Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/c506808e-14c7-4711-a099-62026239312e?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Y2ac5nrfQQTaTvc~aZccN-OaHxekz9c6Txe8H-SDEoVoXPXrntO7UzygoqjQrzs2bBh7nwHWmMKx~rV5vWoPc40foXs-34YYBO4jFCcjg9RWSD1YKxiJy40wkYvTqjSWYVCdcOOvrpDjolyGjWw2em~2uneDd5LILAQxiPXO~LSGCZ2cCMN~9L53j68UqZIilAZH~l3ky00iesYfTMI~we2UfHq6ieUfa4x6YWT4MwGaCIdVEYKnQxgZW96moiGumQDD8RRJ94VA65~dTYKJ5NAJS~OVD7HtHVwdojQmarZy2NxqdyyYUgt7XPOI48PTYngv3gjF~ZAXbJSDJgMwQA__"
},
{
"id": "2355510870589810408",
"created_at": "2026-05-20T03:30:18Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/c14eef10-494d-46b6-8d4d-c2fe2196be16?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=KD9pdBusn6~mstR4-P~HY1RAwsrig1hQ2jd6UHy9tNucR3ICaD-Jl8WKO1g9xqxC4f76JurXgPoygWWoOBFaO7UmTdIQx1yZdxCCbE4f~PjJmAHSv1tlc~~rPLqFtsVjmhYJQDB949DAm36tMDnSAMROpe8Ej8Yfyhp0EBNRHhvudG5VTeKJ2lHVfAxPLgLKv~k62HjwkS08WGrWNZ-ZLpkyKkM6mEUzRw3wJzsnAZFrpxjvuzmzQBNj63x304WQc9TiFooJHsd87kWGKlhA-v2MAVGAaqJ84owaQ-4KcAm~E0nllyDT0MPLTuGCw46JS3Tswx7JXl~9iIOthK3-hw__"
},
{
"id": "2355506357117193298",
"created_at": "2026-05-20T04:02:08Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/4ceda7ab-6b0f-41a8-96a5-d45a14268a25?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=nSloVkhvZQY5RtaljqMB8fOT2TNGJK9hnE2kQ9mnvScY90oDDlv0U92Iwu7spu-9hCZCKdUtBgIemMx0w29BiXVTLYo3xTaoHvVhFBtTO6KwXri9Lg2Vzo8415U2D4TDD3SkJYL4vXHUjM0gL5Q1nJACwPZcX9mJFECiahoO1rKOA4cLiOYruc9VRn6Lxnko9MNVa63E5LWOgWpBQyl14LoGM6pQ1XzZd-mGZ5w8gQEsJmjt4rDU5nY~Ly3hz~zO0XlKr8tg-2LUMvwwucjnflvsu-MlLSTJjE3B-ooM5XzMN1dkRP1qOKOOL6A-IHLR2OTtMSy9eF6BrCzDhdqt~A__"
},
{
"id": "2355536258141853319",
"created_at": "2026-05-20T05:53:28Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/be955594-2a5f-46b8-9d86-8a3da96777fb?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=jhgZbLnJer3llgC8Gd8f3ebOY9cO7G-wcIQr9wmHvdeX3JdWeiAYNj5M24XP7fflrOIkobFdRH2nMUDA94Lvt80D1nEfKCZCgRlqIrUzjjSLGa1RMIcMDmRMpcWHfxi11MnM22v6XHHpg9fMDTOfL93FKn~aldkfUuLP3steAMz~KrMxcnHD-3BM4XRPOjFbuRfhR80G-EL63KYVidfsL4dlyP1ECPCd9KngcTqDlpZtL0eLwsJsRVhkTwgswSvxJQ4jb~ziAg84HV8p3-ZFztuNSwd2cweJkW0FJ4qlpP8PmFuOFj0DM4BwJP7cqye7oJhE1-EsLQUE1B4XfbhPrg__"
},
{
"id": "2355550148052434269",
"created_at": "2026-05-20T06:27:08Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/77a6e826-b443-4d7a-b219-a9777973cf67?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=kpMJ~CsOl9Gt428zuk2Clh6oVXGGhfg~I92z57bd01g585615tkSCBlGVrGmexnTz4HIuoTUIOrEfX~pJb-3jtAoX5T9IQT9~s5blNBjFk9pGo9EEU~zlG6RYLnot8zOcI6C6YNfZ6Wzet0Q2wXRjgwvojREMizEspo5N~PUM-S59SnfzGITLrbMNpqNvORLiKQYbkXk2K4sRej6UJtEd3w0K0LzaxDi8CsaskZWBC9Z4gxWDVwblIwTW2-rTzFFoH~pCN1zcx5zMbBddsG62MdonV18-tzPQe5uEvtGjWn50PfYVuluyebqaWb~7jipZFQpU-jJ7v1pocSRXjvIOA__"
},
{
"id": "2355560821059382582",
"created_at": "2026-05-20T07:00:26Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/ceba4813-27b6-44f5-a611-b80c894269e5?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=JxssDFpk0ssfUC7hovHfOQivHw0QpywG95OA2IkEQewBvQApWeGyNBM7LRRLzt6-w2QVfcsYxxxNRUZIDnx2C~uGonYwIGo8F~9592YeH-DSm9NF6yNQo9V6LoC7AkEGDEnv7qhnbPA5ilMTKeEbizvVxJtjWCQwNF64c2OneR09TB5YdK89V1sQmHVuCSjepYXPBS7FnfZzC5Pmx08B33JDmX~xf-LQEmPRwmwSj~deV5LzKjtJWVO3FtoVB-9Arkan~AYgzrOzPhm8El7eCBYpcp5pBimciul2A~xbCWXeF70teMHAxQq3T~u-JsWWrFzNkkUU9XjgN-4fQM~39Q__"
},
{
"id": "2355570755831192899",
"created_at": "2026-05-20T07:31:35Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/5353120d-3317-4cb8-9fc5-7201b65c4da6?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=RJdhpxGwLUpqjSyGaM5~8nkkZ7bR7fiUxZHuHa~ZbNYuKPQYqIvvB3MUrswGAdt65GZ3Inp52EmAqzFNs9K~ocDSeMvHr~igCAUDDBvGuQguJGDbaib7nLhDgIpyvm8U13HCh9NdMpUv1nJqHZckCOC8w2~UffdmHpjA35JjnAc-bSF9PER1uGYovB1UyBMWprpFJYQwlbSka~RXN~Ljxlo6lIM146ElGRWN7moihA93GJh7by1C5nozZ6x9EIpTqPlmjQgk-larHZA9IS9V-DibNQb~zgp9y~gdAAd3oCo36~-~mFcVUtp4sV-S4a9EtM0FSm~0fmVqGwojLEyQuA__"
},
{
"id": "2355581947450351023",
"created_at": "2026-05-20T08:07:09Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/78bb25da-aa85-41c0-997c-13e70f125f4a?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=CkYnQtH0-gnBMAPSQkG58lhCFduiqtSsbAC6XLQKy~lZBIw~y-y9~n6MWkjXa5Rg1f~98vvSWhvjdUryD29Fbyh4MOsCrc6HfqjIAAMrFMVd-aBrbR1hs1FTmH4f6lazlpBt29T~lADK9dRtAGTRj1ry5LO0sc9MHtcpPLpx8krcsCjuKEDfVZQsV6gnnD0QGNiOv27RhnixKgXo8sDDTZ3FH5BI3pxuANUrDRAUcLldl1hLEUxYaD5e~X~WdLsOuzZ4WblEQ0FdNnLnIgo0s~PDOLYwlmY6BPCscbrosvrSjDCL4endt9ztKyVfg7jQDZuv31k8Ks2zeClts7Vq-w__"
},
{
"id": "2355591357743672104",
"created_at": "2026-05-20T08:45:24Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/287d5f1d-7586-40a8-9287-a4db0b2864e1?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=I5ilPX9JemPRPg4VgXkDbFVf7tnWTMf47a4hjGSgW7It0och0XqHLPIjQzHkjtpIDkinB6yHgEN3bGqNA55-G3jIbl-W4ZZMllwQ~~TXhCC-r5bq9RuaBt~Cdho6SFEjs5wNID7MUqfBrkDbntptamWabvzHfzE3cidp11CiSqNMEbSZOOHGF~DiAssQ5y3A39fhKC92KUaVWsPssh9tctyPqGRZ9aUTfLInFc0rMKpNf2BEs5IeoNtl105J6-K6MYdD3unYOBiCt-FDYvVC2uSJF80xE5v7VlxtkwOEUyVJwtVxkwgcIa7koJNQHi3nzSCCnG4LUDrKOigl6k5TLg__"
},
{
"id": "2355599359232534094",
"created_at": "2026-05-20T09:16:00Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/bf5e16ab-9350-4131-858e-5d8e72df8c91?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=U~poGb0HEp7uwXG0UOR~7HokGLoPtRtYrKq7K1PxIJIlWWASQBZN0JsbPCA1Qllvzrb2MIsuhlHeRb8CaZQqcSKFssltcMsGbOqqMODpNnZxO5YtXehfBQLEgbM-g-sUQXIUZP85JTEwqlv9nVM02zHcav1iKCNIGt4i8~jT-PrRMoIxyO4FhCMb4r45al7Hs-1ahzxXTpQW-mHwnpciV~ghSgcEeZ7I~FFPemotZhfmak9LRuAOqCpy7Dkbq~0DSCUSJ2zU4WYwDo69Tb0mzpzODRs-gDgpGrZqRIiQyFDZOcylA1Z0AvLKzWGSbKpdUOQVBNBR0GYbZ2FjPzZjjA__"
},
{
"id": "2355602095685777953",
"created_at": "2026-05-20T09:51:47Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/7bd4d8b5-d9b0-4656-a479-77c5051d5c43?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=aACKhCkpXcLp0kKOEHHide8DPNAWjpG5bYmBjdGkGV~XvKt-tXimcyNHdtS3tKqsDCOHpiem7oKr0BVLiDLiL~DDlI6pILKKzz2O~pOUKKHgkd1NyPCTcgHnkdK-0gplLJ7ECuu-vCcVh~hTiTmTsZLdjEvhW7XKOwufj7hbWp7pl81FBu3Qo1Vw9yQ3L0jB7nekYCzDu8pcvuVx~TAoiWHtW5BQuzHyV8ED915wX~jCAB~-4pCy8frWEIJA0H2wNoKVTVw5gRTYlS92qkbscrxqpTrzmb0liXU1d3XNmTaqr-l1fNnsaiCg3NvX-kNfEKBJ7UD80j2nocWBA9Ibpw__"
},
{
"id": "2355616045718237851",
"created_at": "2026-05-20T10:22:04Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/f98a393a-e296-427f-9698-d9899d0b292d?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=YHZbApVs3Kuq4DpFuh-NUTgK4oVgxFB18d2NxuSX2nFZiq5qxlGnObKAhbVle0tw6V1QZd36Ir8M3wCGfYs-ZETFuRKg0akDkG6SimBqbWQB-RRQGJNRshwzAFMVBf4dmdmagfVWoxable7DHW6jcaa1zLxkViKeRuzjiZmXomzOe3vFhR3bqRkrBAlga6NYi7yJtJir~6U0NK3tRw4KoMVyoSw9JPc6wjUi97cbDkmQ9pevZc4NWFBECEEWahccR8scerJKWbZ-0p2LNsFXWvmF8yFxozSr6qQI1oRZlsUBIlMHc~tqAdtUHdQ3LAZJaul63ESNW~RN9SBx~AJhJg__"
},
{
"id": "2355624639408198423",
"created_at": "2026-05-20T10:55:48Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/9982ab47-acee-4830-839e-83604eb6186c?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=EMz1NP4VNn3c8R9U2XwKyiKKLxs9GBIxybd2roobRhEgTlnsLFN2DvzlwKsS2eJBpdOUT3zavzgCRUUw7b1bmi32AieV6fHKP3I8jTMVmxKX7hLE0LjRdy-91swS95e1jwz37ZMwJ9dsExcQGtbDFFdyUjAYIiwZunwnrWwFGoOuj~UriQI7ck1TOtoeO4b0A5Tq~9G~~YIat8byW0jpfAQ-crBful0-Y8tR~hC6AedzpIGgqWGA~0FPIqnuBT16DGyGFwLFq0uxJ3esrS6-Gk9yL-BgMltSU1twO2tGn9YuWKQNG6RC7pSmPtl69A1RadxRfDj6LyDrjpvWpqAjOQ__"
},
{
"id": "2355640669337271830",
"created_at": "2026-05-20T12:07:08Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/734eb56c-1b4d-40e3-9792-cebf1ad469ed?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=TP6BM0t0rEmbFtYpK~kEJnHa6EZ8RWtGSio~y9geCKFUarmlGxBTAFh7~Zh-cHHp6Ruk4P2dJUHshLc4LqZYQntgvWNMYyXYk1JCChuXj1QGPqLHnqN4BDkyaT8GJ-csyR9SEPscyaDYrYyfQYe-VcegNAxk6ojxXAlcO~YXrQLZnom2iDSZAyMJBpVuI3iqUJz-8cH-u-f06AtVItSmUwiIfb6mbFgj3yh26TuD290pi2qL8T5C2OjG9mJLb-NOrEtSefyXf-~39O6VbhAacT8fu0MwisQ9GojZRG1Ne6GhipsqTcUOTQ7yCwqiMRRbmDyUVb5DIl1oR0j9tBdlZw__"
},
{
"id": "2355649310243722920",
"created_at": "2026-05-20T12:37:34Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/ff0fbfbd-8e40-40ef-80b3-703618a9b182?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=fWNexgx~DcGnT1QCqBKS9Eo6b6QBeXUpjpvInp3hFB0cc9CQvpNeb-7GoyL9T~oK10cRYHnxWiE4dzllzo70n4nNZ7US8qtngOOwvlLGCsiFDYj8sDNSqqr3PGzVoNkJ6UJ4iVaOFVZ1iGtEcmKcpGpncFE4Vl1r6W5WI30t9uH5pvUQ8wNBH1f1BK--Lqa20vAm4qZuGfYgnsQY5mWxvZkwDQ6ZhEzT5lOSANgWC~v~UQLpl-2cwLYIfIR0z9O5WSrG609DgczWpP4ODLeKKT4pTR1zknACGt7DU4x-xWjMvlUv066~AKfq9NZlF5CM0TLmFz-kQF~miUfJnF1-cw__"
},
{
"id": "2355852942721862988",
"created_at": "2026-05-21T02:41:20Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/6174292f-ddb1-4dff-908f-a17226eb45bd?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=JKUI-M6cp57iarOlOV~0w~Shc8waPSF4TekPry4G6b72-Exv3NMwAyw3QUZqu7mG77ZfzW8m-FqV~iNMwX5iQSxwrax1D-ZavnWrfrZ6QRH4Npg0~sSfdX9H1GpOPTXweE5iZiuQOiHZPnR1yXujueqf9LUKoNAvwVWWfa6hqGffH4HVwP1R~5FpKym4sFRHLbB1PnWXs~c4tp7alBUvQvP3FaokmmoYwLfvCou--sZNzqKkb37yTw17BTsqLCBwIdsOFee3YXmBfB3LHO0B4aMFaRV687MuPtB8vmKhgx11TNyFjXshAqydst93bUE9rX1EYX4FfFkf-dJVr0nyRQ__"
},
{
"id": "2355867283620247565",
"created_at": "2026-05-21T03:12:12Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/bc0dc91a-e7f1-4f06-a7d1-bddbbaea28b9?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=m2z5Muei1ZsXvF0MA3glqg1~u4be4l8SljwldASmmDSKs45lDdODTSEZjfOkoO3GjfqE8l-NI~VNPsEWsIeGYfhPzfJfLhJ~6~qO01iH1yeMbYKrt-gYzgDFbE2a7QHmc5d9Z0l6Qn~dOQsFf4LB~L~BK7c5sOXIPsosVXYnEMpG9Xlo65sqlMvlD9nSpYZNtdBnNv9hpRkTDf642WY24f1drvIqd0gsrnRaJC6v5e50cjB33HqKp5Rl4A5y2lI9bGDAIuEj~5p11g8CFSjpM4njcacbYXodMbdL7r87eW90vB1K5a2HN3lt5hAelqKEsOIioSG99LgYezCCSvfQuA__"
},
{
"id": "2355874860984036900",
"created_at": "2026-05-21T03:46:39Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/f2032136-ff70-48bf-8727-b6cc6b7d2741?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=k~ZkKz5uUxTQXcEPA9PAp33j4UO6~Ju5BYU0Or85D1~zwQKCyks-FDER68kkH1UeWky0Ae3NL9JSvlyFmP7Z8jAeBAMfoCM-2wCu5Si6Lt3gvY~jKy3ugBkqHiNgr7NWJ2ByfcHRtoh~vwV9V0CJZveMLnYy-0xiHrbeXPYRzF~FqP~tJeye29BrPoxfe4Iak7IanTpHPoy8VaCoTHmnovjG8MHm-1pRhsvHzc0B1QwDvWILzCMfr~5v37pVVlIancA~GChS6di2tQfM1hzTKS7Pq3S74VoJgXG7M8jLJ6MWYL~BATTfP35SQhbEUqpy1WKrk9Xe51~c3GC6y--Scw__"
},
{
"id": "2355914890102682223",
"created_at": "2026-05-21T06:11:49Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/d1b9e227-d1fd-43c2-830f-b675c36caab1?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=SPW7FDyPh48DFeUda7dJ-kBrxQYC7AbbIRmG7zUC2L-8i2biCxoqQNi5quQ05cblZWBPn~E06fgwtTWp6nhgBp-WsfQ0xPGxvO3qkw1A~LjC8FBQukwHBokUDv1DVDCwtvkeiNFfAaNFCC2qBBkDpWUjMhd-T3N0hyKopxs67TrSBN7Ii4gWT~s3J9YOyEe7JNtUGl37kNgcxJ8TUDB02Q~B435lMf7HHx5awGkfrQCGUzn-j-oS-mhd5vdoubcw2DS-z0cN-f-ENWJPPHStJmrz5Ajx3W7anwByjjqNKqA8oVgxyifQLRJqcpE0nSx4rmZWtXI2ATKA8JnTSoSOJg__"
},
{
"id": "2355926971298794153",
"created_at": "2026-05-21T06:42:25Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/03ab39c1-188e-4325-acee-cfb585599e27?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=nTmtSLTLn3kyL2ISAltgsNgv7CJai8k~B2jqzWr~XgilfrMkNzbUt8ejtucUkcR9E2~XvqxabF1~kE3~XWLFsnZPerdmG7GZH514t39FOkModP0-pLoEh9xf1DfrVrmRnelVXyMFagCb7wKgIe7TyoOlmIC4ZBZ3ZqHAPeq3PltUnevjXTdi8YArEgtjisAxGGx1M6fFvHxl~GyZ5Nl9jSqJrh1FQYkyX7jG3RN2RzxsDR4ZYaAeDy7Vo7djoUFXrMppBMSyvVuHQOhBFcB664quHNsRCMk~oKDYRTLjkxZIUb0eOIPkdNOS3NzWfkQw7Jjt~lZJFAqawNBWz34s-w__"
},
{
"id": "2355936110990016106",
"created_at": "2026-05-21T07:16:24Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/bb984cea-7797-4b74-af82-db366b9df319?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=CC9aeHQmISuNWq~cJcDWMqEqC5xcRb02p17H36sx-HEg639YF~QNA9gZvaefE0-yKmahqWEa9HN9QKXj2iF-P8Kmx~Tz8FNmkuZJ1So6GjaXkQYb~uXN0C-nW5NL~mdEI-sNZdj72ykrSEDChYVyUPQdda7aDdRtpktS4NqlI1RPcitsMsJFczU~QPvyt1uwn1lJEi0dpxgnFaWiseYXFDAqgbFdn4h0DmsHvhm7uACLQFtQJoHm7BazaovK3IOZh2~k1~L50QDNuNAxDjWLtf2BGIAwTgEZH9F7LYe1ODsU~y7jTAPAh76WZ7gZGzXF7ydjS5PI-4LQTKWlJls7gw__"
},
{
"id": "2355943643825898185",
"created_at": "2026-05-21T07:49:34Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/d6e8c235-42c6-4bbc-abd8-ba4489f48a5b?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=sJlq~62ArUtEK7QCzmZYcv45bWXX2Tx-Ct20-qIcfXAAfrU-dOI0q8pZWH-hgLDk6oZqVUnOQKv0s6a1I~oO6GakCnb3aVONwnXzRGdEmNcMi-4pkFeJDuC5Q7owi4by3BnWxSbRktTacQZpBr7fUmYZGpzvkopTTAf5ls0YmsbPannrstxgXI7vxJ77ZNHlgyvmvp2TJu8~ovm1Xx2QK19Gly9hE9m~cgKRm4~dOWE1jz7IZReTKogONjF2LCpqXzIGUcgxnW1X9dzG9QGMuruEV9VfzgY2euiup00Ia1~ropHFsdkbfEQbaDiuXxgG~8cUegRisBZACqdidfRPBg__"
},
{
"id": "2355957658315518921",
"created_at": "2026-05-21T08:29:15Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/8c77580a-5746-4869-8c8a-ff979e300188?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=j5P~15jTe-52-sBVLF1XY3EvPK4ikYK5s~2po0OQ2QrJ0Xum6jXGLO8UwVlBXFH8CPkSDksJglCGFbrK~77s8qxzApU65dhawtHfW-Zp9NIuYIiMjH-NiBoN-jUFAnzHIg7fVN3lU2I~GX~UDxveeCYW78Thir9O28CIflAtZNFGpAQqTyIAgS~~2u87egRdMfmjJPiM5dKfQqWoIHTzSzKnbzXAnOK-lpO~e5Cvp2pkc3sa9pfqtQ4drUGSH9uhEZNexpM2eNd2rm7EwxiCdHkBY5Zmh~GhxlUUCSuX6cxxabr7V-9q6sZnW2ZLcGCLzjQ5A-zbAr37T4Ez3Mxl-g__"
},
{
"id": "2355964694015349173",
"created_at": "2026-05-21T08:59:44Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/fb962a30-e4bf-498d-ae8d-fc2e4c0a87c1?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Gus-3GhfhfyLGShUDT8G9QYR-IQA-fnwCiEt87pJE4cglg~5iReIeIbjv8uiFJn-v-fWtovS7g9mHlIDoVbcXEjGy8EwKZG0NSblq5NyAzj2skByoQ1PIkpdw8ZwESM75~i9hEGsUxxngrGqgRC5NoXNFJa1OqFdBf229-S9oTRkU8WIDfKgc6d2BVxJsR3YFRz4Ie2qBk6rnGwFOcqS7h93AsR68WYGafGY8~wkExoQ~bWmfY~kOuJqtmQ2cqlMUqkxDDaKddTmohRMtaD1TPyGPpXdN4ysKljvcf0pLiRBIhe8T4LSx~a3jQm7J8PH5lGr~mgo9etKLZj1NpBVdA__"
},
{
"id": "2355973360704949811",
"created_at": "2026-05-21T09:30:11Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/d10a00b1-3625-430e-8ca4-dcc282abca16?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Kf91-wTFXZgQ3Ofesa~7IBlCrSJbGGwFNg-1JRrILkPSN8HfF2cjnrr4xghoDJKgWXPZmtAN~Kw-QqDpeEj9f1QEW26RhTt~BNdB6W2UbHzSefxx7he0dT6vy1nr3B4qsUdnjKvbeRmCYW6Y5VXjNVCMi8Hv~Vl1MFDBiIlKH5vD0YMJEvwGZqpIvc0A~k7QyGwhEANaDN31lJ~PCzhLzQ48K~qgLt1usk7zr2HF0ASRhTNluXfEAkxRtxmzxDhFHe0eZmyqiXA5oz~arEJs6Iedh9q5AQ8j5H1DKjsmRaA1JGe0mdk54UxgsXZukH15kn-GwNs1Sty7uZXMX-XIEQ__"
},
{
"id": "2356328061638257635",
"created_at": "2026-05-22T08:38:54Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/b2e59a5a-963f-45b0-9757-4cc15b0b4952?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=AIrftMnDxby1Cvdco-ICkFGDBgN-F47-~V7U3jdk3CRxVVHYIMY5Hr0CN2q~lMpin-QcAi-UeDQGJCfY1K-tHBOsB9vps0YP62AOVdNl2Ls4VzBv3xeEUc0eyxQdlGL8c-SuVg8TXeh4o4V1Er3lsX8N5VXqwR202necMUuC8SHIie9KQnYzfWtf7JutJthDBr619V~ZCPzQZE9zWGLb05H3GQV34h~vU2TPuBP06qrGxF2Yr7lSobadTOp8KOAzX9Q8i7x-UIdE2bsrOKPRuvujrc9s36IDUm~5JxfPCl29fSWEcui-m~wtWR7StfjzH5JZ~gNEObsdmGrZ-kHqRw__"
},
{
"id": "2356339417030736389",
"created_at": "2026-05-22T09:11:35Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/6cf861a2-6252-4050-a443-6bec5ed5442c?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=kN3C84p8eVYcyXeHxOM9JHh8pC1pULOWYkkF3QCDh8e9ZRWQRBUpodSirNglnBHmIitc0R4aaSWQqomZ0eGx~jTbfkqjW6hdap2jmGVIsUCG4tQSqPB6iakKRLtfClMH51F26ClMbym387bFS-ioEjwxVMycyUHnKvOUUzlS4eLWJHQ5tqTir8hC~sqNL2F4d17qZzXcm~PO8DrxTXoJS4UufI2sNDWoTDlGY~UPUbLDoifgmgnc1sGqaGtoFM1AALa9UU-MZM0lCvA14I0yLquhuG9tO3F0h0rWPhZZMweeJf3n~S6xvS3nBWeRjssX24b5vFuOXMZ4G85W6cKyGA__"
},
{
"id": "2356347354652557329",
"created_at": "2026-05-22T09:44:35Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/6efee131-44f3-4313-bec3-149490877fef?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=ERAWMmECgmV-mwNTptQMXgHywkf~fFl~CalfFClfOxtrgVZBiXhuH4UnN7L5TeQ7nuuHR5TXEO8Pja9~ww7YgFmA~iPmyeXqb8xgygOQ0YxZUXOZEl1UuV~AuMjj1TWM4M-y6~1zt8y7n6gb12jpqSYo13o2Z1TByGBqcLDZYbKWf5jP36uG4s9BCLAHfJqU93HJPcW6pdcjeB7xmVRn6fZJV8EF2Qcl2q-AQUTkQ0FzE7qHDeTuzy91nMqsj8o2mG7q9LSGWHTw9EufSdVocie0a7OmM39N96vM8IPB074plGYdweL-yWPq2jKFVvdwKwJl3VlOvjhWSqjpNjAa8Q__"
},
{
"id": "2356354359748155015",
"created_at": "2026-05-22T10:15:57Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/0fdffc87-552f-4333-92ec-cc6df52cf1d7?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=gRXCQ1p6P5TTGZaOY78S0zru8i3teoPcXvsKpje~UWUwC7hLB6I0iTfzm~bjWkPUpubChsiYXN8ujRn2K44fD6Gc-rU8DDJq9vYGF-PwM-Sumq7L8oYRsmNT5Mpw~TG7pqOSNXtXDgOsRGQQN-aRFBBe0SmsLw02MqSQCMnUg~QVbfbDRGTVI9GMMzJQZPJl1OA99b9sPn0pogKCJv3FQUe~hSkIJOzHGX-oyEZUPK0L0fkVsHllaaaWEK8cGU1UCUA2fEhDJd5qhkIfOk1riqI3zgyHKyznWqCUJT8tEwYSFNZ3mipgf2PhIbNKeUSUsCTLHWSb5VPAm~Ef42G3Qw__"
},
{
"id": "2356363794700140143",
"created_at": "2026-05-22T10:51:09Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/37958cf1-241f-464b-8a21-e3903254eeda?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=Q4ypvJqm33q5cFIxL93hBbrWvDNJLPaJ6jwCiryYsyXvi91Y8F-tDt-id8LCXPLG9CK3j1aD0or3pIVgihQOnE4kt936Su7YDokRkDusmRyAdxM6~SSxD7r8pFt2vJPJPZb6XaoqP8c0dN64uBiLxCyWGpfwSq1zAYB0dZoCD9pFwcwVRVfQiyJPtdVXknP-~dSEDD3z77VlIQVKuQSfzZwqHzgrMTXOVSaeigR5Pf5LELT6Vr3HPiRoAOD5LmyLNJ65mykNcAQ1o-EkDyvF9UPZc-sOg72shrPHE0YlDtQOnrNE-ykywrwUvYVXWwFR3jxz9RFFsVT4X47STiAGqg__"
},
{
"id": "2356371663107623324",
"created_at": "2026-05-22T11:26:26Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/e2a2f200-8c55-4e29-920a-229dc832af0c?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=nrzp5lLdaRaa7ykhnW2OBQEbE-yphyjgwMur103SDsiGpFVGsbw1PnhllbdY~~WpRq07lVhRPnkCUzfCWqQvMaXjWuPgq9LWKaZfLQznSEbY52gilwdw4uysVI9ai3a~uii7Poypd7AzswkSmdVFK1Vf3L8URFg6bUzTKg74D1wkKjQOmaNgJpsb5GvALl0~klxQL~plmONk2dywUFSSAXm6vcoSlsrvqvPHUSdgyvLT~xf0q8Y~DMW8N~yAdmHp-Pu0zGftDiyiJbRn5opseqQxw7rXaBNxNMQQOE6klPLyh5~4at1KkjhNkrGg2fLONQIvm94sGdhhbdoB2BH~qw__"
},
{
"id": "2356379141694004294",
"created_at": "2026-05-22T12:00:06Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/33848740-0cb6-457f-9ab9-53ef0eae97ee?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=bdy9ncSwvK1B-PhOpY0oYRNheaq8vHCG5iMZLDiD6-kd~Rp7sa57tmMk-w6NtR3kMvnhZvWINoA9VCGTLGB5VQmys1BNacDIrtuSLSljFHs1uDLncRZ~dmbrfXhupR7kxDE~wIpxX-lF-NYlTERtLqsyicl-txMcO53pOU1dEOGm6aLa67RlSWOw8DFYHx1yj7TOfLtQysA33phmeSwdO7UJAYLxtXBgg-USKJKLyJ-9VfW60M7jEqT7uMBAuiEeiJdOs5jwovrVypQW29twc35RHAX9LlUV1~wcGM9uv8kbCPzuzU2AdQbMzOFpJxqmB6K~n56mUUhJvFWYT4lvXQ__"
},
{
"id": "2356385480552410542",
"created_at": "2026-05-22T12:31:43Z",
"label": null,
"description": null,
"user": {
"handle": "刘龙",
"img_url": "https://s3-alpha.figma.com/profile/ea2d6d17-43d5-4ed7-9fc2-f6f9f8b4efd0",
"id": "1632266898713403386"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/c3ba6625-1a2b-462e-980d-5069001dc9fc?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=S~lWlw4o5qA4Yc058pM0ki3Ppzt791Pkk-HK0ePU7au-mMR2vyqQdJz7xc4IAhAuyRoALiXnCzys~pYs0PHv9jCeYjuMfTlL8Nx3eE~30ZsVqE-1ode6iineLFSW4FGhRVXTUP3K-9PV1Ai0aaEfJ1hgy6C196NgtX9MynC~K5UQ7ieuTDKaw2ARg-kfsH6YZ6uMkreExiqMc91gNkM0xicVeLqKpu~2Zumf5p-0u92pdxjFdhiUsVwmvRzUJGFadqXTqq~gkejm8QmIBNPgG~omv-QNFyW3kI1p3bDoeg9Dbw2z-EEZXpjf2o-xT1kJb18YLRfIuvJarl5BgLPFew__"
},
{
"id": "2356394277154688710",
"created_at": "2026-05-22T13:02:04Z",
"label": null,
"description": null,
"user": {
"handle": "刘龙",
"img_url": "https://s3-alpha.figma.com/profile/ea2d6d17-43d5-4ed7-9fc2-f6f9f8b4efd0",
"id": "1632266898713403386"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/221db71b-2d65-4b99-a5e4-fe1d3452d5f7?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=fWIo7mST~-UPHfdwtP~dA6jO8QbK-wiKo5~GiR98rGRZHVOdJtKwK5Lj1ECUHJH3JDHIa0cC1k9noNGjcUFGVKzgRPki9DyOYvhBCTP7pH4sLWkjy7T51tpwkTNCqGgWnajD3QozNM9RkrY96xild729k6kDOdMvsE3mPhlyn5oBIDsN7EtRoBISyRXYPePzSed6f6eZ4NzO74d6boVuOUdQ3S1xFPoxUCTipqkVPndhfRt2MySQuKB7GUA9-InsvGPsP8izdvWoYJMs1IO8nrgR-HTul0MNVhWvZnT73qMALnt5Jny9bi1lr4-eA9tAj55k2CU1MIkgUljeYcMoWA__"
},
{
"id": "2356566999289339741",
"created_at": "2026-05-23T01:36:58Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/f882440a-ef6f-4f4a-8535-989412c2f238?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=ZlcQ-CZs1ApkdQZnzpZffLL5MTJ9CgPDSIpXOTF0AshwTJM4CLvbgE3GeSIyZ4TuSGZtU8JFg8Phbdt-W2quRzEZAud5vlKrBDYRfKReyrfdNoZNh0oy6d-PuvA3SyEAftCaknLV4ML8~ONWvXZahiOquzgZCDsYkw9pA-sdClb-uFU36fcuwUYsDMC2g29p31HS4EVD3qm90AD04fZySIwFmHvSFWBJD~JuB9fR3Ov3oEpyWhIo64uV-GJZUvoiV44HKYrHYGuoJTYuTFY92k4-5huiEdINs-qDG19BUyM2UPKroMrlCZN88CdrPMvrZwuC5s5yttWV5E-AjGOBcg__"
},
{
"id": "2356556072866806876",
"created_at": "2026-05-23T02:18:28Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/93666cce-95ab-400f-8829-01adc94209b2?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=G8qnOjBqnS7xePWoGI4nK~lJxttN99k5G6I7~z5Anw34kuVpvDopqNp-Ct19QQweg-fkBSXz1pll37KcAuNW~xMxd0S2ApCwPGnXEV~VyhHVQ6zulW-eE4USye2ZUn14Jt9uwTunEwAZRcMNfrZww-8GSBlkMmTpj~elYxoYaw4kPwYPOfaFCQcxuNOlQ6rbUFyaqyw-ZHcFEJgIGhJ8w9SFDF6lfu8KA78efwWZNZs1~CD6HQQYzWPihhb49l0p61bqN0LLnaUel~E~i8aPM3fRQ9z8veJHI~miMa~ZEcq8LW3me2k3Gg4cL8QmHqBhY4~vM6LJ2S7NMufpe-Owtw__"
},
{
"id": "2356571821464095137",
"created_at": "2026-05-23T02:50:06Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/2f437ee4-a344-40a4-a28a-70d33f237b84?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=K~NoTAD2LGTkCP8p0ohB~2CmG51Xvtm2K2eCnfDlhN1dntXapvhhPHv5xMUuQOand7tCYUwL3vbzww99LQ35YS6S-D2Ve~4YhJfd8qeRqF0CIU0qWgdRNTg96A2IvEgjOU3K7DnjH8ZvXcrmYHdHXFmbTmxsJ2sKosfVWO8WFIr9zNRR75LBOdeks~fSfQk0FHIHNZnQE7jDnqPUfb5YOjFRv1FapRnkbgD8qDEsbWfiQosiYdpuvkgJlje6erESfgr8ESZuEMxriUAE-mn1pwbEBD4ev91s7NkXjKDuD9DhZXjbgzy2PqAiEmtHh~47sDd8Gj0FFyMW9x8zICgIhg__"
},
{
"id": "2356619568609568401",
"created_at": "2026-05-23T03:20:27Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/e90f81e2-bf69-4b19-a899-8b022d8ed407?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=PXpH7d4rJqRsKSSb8DYFTICaaHgc9QoUZCipWSxTpexART5kkbKQWNUQa5qajrxbAcmTz4iHL~1sl8HcPRTwd1J4UriOwQYgFjmlQlc1kvR5RK-q6Vu4j7oYKBqcmnJfWalFUdDnnZkVgXRNnUekDZf3WXxZR40FjgifctJnRHGJSPCNBIAxgvBOdjyUs~ZcK7DFK0jhSz23QNsErOuiB1c6VvN5TYXR2Bz3K9S9J47okoE6xa9I0TMlo~raR6bKKIefzIYbpMBYfncA0fX5evp4KDGNcQpDJ4dkUZyvVYzGzadwr~d95jAOqeduS0Ip0ZNK9HBCt1fqmI1tmfCErw__"
},
{
"id": "2356569640125830480",
"created_at": "2026-05-23T03:50:54Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/0e33c41f-c4b5-46e6-8414-dedc4391609c?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=LTC3POpE6M7HmlbwMA3WeSG99qgwLElqxOtQVC6jkLQTzXlZELAXkrUF-ida5Nygur0hV8afR54ChF8fT7CQTLGUGlGmBys8iha6rDB-OdxjMEgovCzAUfRaDNmU45U3M9ZWCLF-4F0Ht3YBProJk2LQ-58GcYTN-7mj1eCiUo8KBUT8x0pcWMjjxHT0~rRIUJ5dVS~RMj0oQlg8B04ud-qlKbNFGxv6bdn3DY~trgjnrbRhU7rSwmbtSfPYd1fW6RMJ89YpiqCHkuZKLYtl2wQS9TgKglc7xz239wE9r1j8kS37nZJ3S8ka9uzlzOgo72aQwAkwzPQ3lAq6JGmYjw__"
},
{
"id": "2356585311926125350",
"created_at": "2026-05-23T04:22:44Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/d5ccc843-2905-44b6-8074-0388c0f5ac22?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=jIiST9RWyNgTSF4NFms7ekdpXoctOW6d0pWSzjDrgmbQulrTlkK49VTnZv3qgIauR6R-Nh2ijskXzAdHmoOFS0Aug~bUt6OC9b6goy79ABXoqZxBm~xC9MkseaFZi1Q23S-09OiO5tIHhNfalCt7YgEUfaTXIfAg5VfkzIlZ3zCzfhWlBA6yKw3qd5FZFZaBuciaH-sCpt6V1ODGK9i3qGS5zMv1LxlwCvXn0j7P1F2wm66vVVzgq5JrZ3D27xAPf5ea3FcKaxL6NfyOWmbt5OeFu04yNManr9SrrqzHRpb2CzGxo5ZX2D7EsRDlm57mXItkfnxg0~GwXK6AGDz7-w__"
},
{
"id": "2356601263433008428",
"created_at": "2026-05-23T04:54:10Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/ee147e08-47ff-4d8a-aec6-37d0888751a4?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=VCQUqORGJBnD9Bks0xKZT2F3pJEGGgW0vfbFXIvzWSXo27IxDm3-okSZCclzXq4bt1G0AS8IVQp-pvd1adIFa6IMt-avIeU6rIyss5PrluJj2ZEdyAOO3azAO52yXhN2Mu7L78foVW-qkNuoIByVul4NRAq8y9SRK5qjcDDs3rt0bVPPbcTY0ZyOGiksU6z7oYnDX3JL3bQ2viVKjj78e9SRHdyqeUazn4CglO6AoFJWJpT7tgvYRWQpTGPUpsvgff6170rIMTUCNvEJBV~7FHABWZDRUWGBtDo5UC2hqspaAdyHuHAzTvBQUvEMFLmRjdeFna~BPhKozOpnpC8z0g__"
},
{
"id": "2356635688675420393",
"created_at": "2026-05-23T05:28:56Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/6fdc95e4-5e59-47cb-9287-da179beffb92?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=dJcFYhrQV4FN5ob4YNnrMx3aBDcJy1YdKFbsxNG1Tly9GpoBlhecW2nAoB-heYl10ierHBxlj1ObGJIrqUAfBBipHcF69-LNhEQneOTrjvTjgPchoJjG~AwUkl~FtIXelM2gDo8LajLWWpBoFCViJdVZmDWwxeH7M80OMV-izY5SRCAvN63BAVUq6zE8XZt57HqN4SIuoPhADk72cwkAR-esePYtKsn2-657faQM2c9SRZP-7UbLJYCxofwxVOomFkyyAei8Mvd1U02thr-X9urelybP8Q-AmeN3lMTg2-TDeizcF1IUzMOWHqxOfgrNycaaF0rLx7aWyfQyMO8DvA__"
},
{
"id": "2356620471070189642",
"created_at": "2026-05-23T06:09:19Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/e8d55eea-7e54-4a4b-9612-ba8d9e92a27b?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=WBXOQLyQYUFy8toEWyRUhXVyZcXG-qFQmiRTB8IBCgFGC8-WcrJ~vLfz4rZGbbxlWvFMe05peibToUpQ~4qxVTijLvgR6B84PBal9g~OjV3-JgKFATwRnoy6ZfYLCpUUkFXaOTfC5IUdZjYfGw3BMT8b1rZbhH~7pxnCmXULx9rvYDRxavgiCvWsyw-E63KvdEM5X5a1q0iO3A2EaQdlXga4dNCP14MIVdUsVbVL3uQMYksQJ25oamwQaPtIpbOyOpmmcawWaMsqjzbGd4p3ZujXSPxdbu2G748Na2raP8XWNqhTcOBWhdjK8nxERhmJJjLvdTeRLXrSefV5avSr8A__"
},
{
"id": "2356642564393732308",
"created_at": "2026-05-23T06:46:54Z",
"label": "Ready for dev",
"description": "",
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/227df0ab-1133-4cf0-8bae-dfdd8e090e2e?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=igkh~kudGbnsRxjc3~A3v0CZjb~SJoF-bpBHBviosJwWsvHhIQUcuA2kC5I4pje1KF48RFgu8wXCGPJ1uEHuLfSpPFKqnDQff~W-Z009ECyacYKsj3CMlGSTJWO4sqtKAl8k2UiALIGyKcsj7OVBQw8CV5hd6ydf9grJT79cJ2JGHrjIXoZx4caxoDGbPUvo1793FZnwFZLS1KTwznrTmLdDRCa~sQX~kpEv1wIoKfEdk-wIKM9~bHyhVWJq5kEloG3hY9DQagxtFwU-yyTF6njd8eX6pKHwdwfbOmrx0PRWcBBP3h8w6em5XW0yq-EcKrVAa2D8rwBHrSWalfGqwg__"
},
{
"id": "2356674072796598379",
"created_at": "2026-05-23T07:21:10Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/ea8c8503-2135-488e-a26a-dd5052b45cc5?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=dSCXHKGshtSgiVeYsNI6kDCQPhUoxzXVetxRxm-KEqgvxo95teezzOK51VH7Amwt7S8CaG-ZdtMiDyWSQfUmbnshUyFRi0Ujai0vvZ-jyirwRpvlP9a20u4iBjNl0-y3TB5zGY~YPOY~~SSZivyVakjGGV3j~JnPL6hRU6eq07DW2xNx1KhrjpUe~0Z4w58xos1QoG7W3Vi-cw5miorDcJtPV0C7sWB8qJ2vA34J-~MViu6Xd5rfg0I2TyEA3A7BoLlGYmjwuZH-NR03sUiQywl0ZWajs8Ng8EFM3zYs96XnD~DV2eLqDS4u8BL~-0W~FQHljy2qkI68eiBtOpxIFw__"
},
{
"id": "2356685170470014770",
"created_at": "2026-05-23T07:53:01Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/7c4ed272-b38c-45e2-941e-41abdcf9abad?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=f~6gumx3cMeBXZPqx1hr8vixexS5Y8ez-ZTxlNkbseGpvKXHyLmn1K2qT4iF2ysshNi5k6Xxane-krZKL2FecDk41SoEKkJVBZB6sC26Xzi4Y2jVxT1Xwub~8K2avoKfAvz-FDB4T8tQRtoUOiUwUh-~2fMpgxcNkIhLELjrLRG14MlFXEG~qNUy~YyUSVdo0y9L1RvDRnaVey9YIdVlV8UxugIKyatnOtlaiMsQBqJYMEY022sVWFiS1y~CLL4xzxP5hfGdV52IDyvTWZGOfd5KPJHZkwfjYNhGFRFW9yQ1L35eX~DdGomfMyr-hjnEB32SPfGLn1AzKraaRFG0ng__"
},
{
"id": "2356668682120898694",
"created_at": "2026-05-23T08:26:02Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/d6c47b22-a260-42ff-a9bb-966403afad02?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=STVy-lB2eh7I0vvlbZ2sD12AvSqyrP9nushbW4silvjB0eToDTVUwp7YFEVIun4mLE2PIXlGvkIesxwa29QxYBmsPKhnSB7gIbpkWXxGvGWlkn7-3ywww5o~KIvDnCHNsPoZtClqs3mDa6mmnmVp2nVNpisfapS3~L427UQv7UoDEksMMeqjH~ZQ9WbhqmHjEoeco01FzNc9cBJISP1udgVgz20-pXHkfE-1~4yysu2GdBkAfaMkuLYqD5TMOBfasJKfu3eaPVWkzWaW8vleFIuxUL7tJV5C51CHNAt8dJoGST-weqFUn7trk3VhMcPDmnVKaKtOx~xSWq5Oip8crg__"
},
{
"id": "2356689414432110171",
"created_at": "2026-05-23T08:57:43Z",
"label": null,
"description": null,
"user": {
"handle": "Ashlyn",
"img_url": "https://www.gravatar.com/avatar/98269fd11e1198fd8becc337ddbd52b6?size=240\u0026default=https%3A%2F%2Fs3-alpha.figma.com%2Fstatic%2Fuser_a_v2.png",
"id": "932910663765323341"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/dec6131e-a08f-4b14-80b2-359746860610?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=e0Pi~tUlyz-1OSxT~Hi2djSJGbxoLMbJlDwvP2iw-9RVNAnbCRNq2wFi-Zsh20mOLf6r~a758FS~25y38VMHrRPbefy2dTmP1Onj8pIOQUB0UnfjgLIxG7dJ1oQTYVNj0lD7r1yHkWQjHT6uDjZ71Cb-73fE0WwmObgumf0B0KhHxUTeNGqdKLRt9wqgp0ofMUtrRIi547fy1FcbLfetpwN8NH1-MAKZlZFMUBIMPmfrs5vAzgEAxm0jcbRlvrNSDTYPxA1ZeiJmDXHYGK0QYskKbVEwywWLdBAsZqtVsZUczydcpI1bxxnE9pSx9WnyEWz8RwCFdywoh3BbwMS-QQ__"
},
{
"id": "2356712417208056783",
"created_at": "2026-05-23T10:49:08Z",
"label": null,
"description": null,
"user": {
"handle": "刘龙",
"img_url": "https://s3-alpha.figma.com/profile/ea2d6d17-43d5-4ed7-9fc2-f6f9f8b4efd0",
"id": "1632266898713403386"
},
"thumbnail_url": "https://s3-alpha-sig.figma.com/thumbnails/61f20188-408f-4871-98c7-92cf0c72d7d6?Expires=1780876800\u0026Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ\u0026Signature=ppaDsX5z-SCgVwlHupsMIDiDKTvE7wgfDyrLmmC7jKunGpdsDCXVXcGO6~CZ~ri2ew4Qry8KpNRIPA1vFRVQDpDHiblzsFN06IoX0gP-xNDY03Elp61gHaTk0LkwFN~CYdHjevCNMb7J8NSTCP6eX6IwNnR8bwC0w0VbEFCmA-Vd46MFRcQkObP-pDcAGlcXi2z9EaPWeGl5AgGHg26s13v1OLz49FA89zeQXCrhhHVHzoh5~3dCP5RUTx~8v~9tHt4y6H9Gu1NrWk8FFjEWhAGLFMbDz7xdBfNmbtMgBJdRFiBt1VSKL0K377CO1IBu3DkaCMpRJ9zSq50Jt~uojQ__"
}
]

View File

@ -0,0 +1,56 @@
# 门户移动端适配验证清单
## 覆盖范围
- 全局:`styles/mobile-adaptation.less`、`styles/breakpoints.less`、`styles/page-layout.less`
- 入口:`main.js``mobile-adaptation.less` + `v-lazy` + `utils/breakpoint.js`
- 布局:`main.vue` 移动端 `content-wrap` 高度策略、`app.vue` 移除全局 scale
- 视口:`public/index.html`
- 主要页面:首页 home2、服务中心 fwsc、共性能力 gxnlpt、企业出海 qych
## 建议模拟尺寸(至少 3 种)
| 设备参考 | 宽度 | 高度(示例) |
|----------|------|----------------|
| iPhone SE | 320px | 568px |
| iPhone 14 | 390px | 844px |
| 大屏 Android | 414px | 896px |
| 上限区间 | 480px | 854px |
Chrome DevToolsToggle device toolbar → 分别设置上述宽度刷新。
## 验证项
### 布局
- [ ] 无横向滚动条(除刻意横向滚动的 Tab 条)
- [ ] 导航汉堡菜单可打开/关闭,菜单项可点击
- [ ] 页脚链接可点击且不重叠
### 交互
- [ ] 主要按钮、链接触控区域 ≥ 48×48px
- [ ] 表单输入聚焦时页面不异常缩放iOS
- [ ] 共性能力收录表单可完整填写并提交
### 功能页面
- [ ] 首页各区块纵向可读,无内容被裁切
- [ ] 服务中心四宫格在 ≤480px 为单列
- [ ] 碳服务市场列表与筛选在窄屏上下堆叠
- [ ] 共性能力侧栏与卡片单列展示
- [ ] 企业出海三法案区块标题与卡片正常
### 性能
- [ ] 首屏外图片使用 `v-lazy``loading="lazy"` 时不阻塞首屏
- [ ] 弱网下列表页可正常滚动
### 桌面回归
- [ ] 宽度 ≥1280px 时导航横栏、版心 1200px 布局与改版前一致
- [ ] 无多余留白或组件错位
## 备注
移动端样式通过独立 LESS 文件以媒体查询注入,桌面端默认样式优先级保持不变。

View File

@ -9,7 +9,7 @@
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover">
<link rel="icon" href="<%= VUE_APP_CDN_PATH%>/favicon.ico">
<!-- <link rel="stylesheet" type="text/css" href="znhd-sdk/v1/znhd-sdk.min.css"/>-->
<!-- <script src="znhd-sdk/v1/znhd-sdk.web.min.js"></script>-->

View File

@ -1,33 +1,20 @@
<template>
<div>
<div>
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
</div>
<div :class="['portal-app-root', deviceClass]">
<keep-alive>
<router-view v-if="$route.meta.keepAlive" />
</keep-alive>
<router-view v-if="!$route.meta.keepAlive" />
</div>
</template>
<script>
// import { GLayout } from '@gtff/tdesign-gt-vue';
import { getClientHeight } from '@gtff/tdesign-gt-vue';
import { getDeviceClass, watchDeviceClass } from './utils/breakpoint';
export default {
data() {
return {
publicPath: window.STATIC_ENV_CONFIG.RESOURCE_PREFIX,
containerHeight: 0,
business: '',
businessId: '',
iframeUrl: '',
containerStyle: {
width: '1895px',
height: '953px',
transform: 'scale(1)',
transformOrigin: '0 0',
},
khfwStyle: '',
deviceClass: 'is-desktop',
unwatchDevice: null,
};
},
watch: {
@ -40,55 +27,27 @@ export default {
appName() {
return this.$store.state.settings.APP_NAME;
},
type() {
if (this.$route?.meta?.isShowSideBar) {
return 'widthScreen';
}
return '';
},
},
mounted() {
this.setTopbarActive();
this.updateScreenCompatibility();
window.addEventListener('resize', () => {
this.updateScreenCompatibility();
this.unwatchDevice = watchDeviceClass((tier) => {
this.deviceClass = tier;
document.documentElement.setAttribute('data-device', tier);
});
},
beforeDestroy() {
window.removeEventListener('resize', this.updateScreenCompatibility);
if (this.unwatchDevice) this.unwatchDevice();
document.documentElement.removeAttribute('data-device');
},
created() {
this.getHeight();
this.$EventBus.$on('changeBread', (data) => {
if (data) {
if (data && this.$refs.gtbread) {
this.$refs.gtbread.meta = data;
}
});
this.breadInit();
},
methods: {
updateScreenCompatibility() {
const targetWidth = 1895;
const targetHeight = 953; // 1080;
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
const scale = Math.min(viewportWidth / targetWidth, viewportHeight / targetHeight);
this.containerStyle = {
width: `${targetWidth}px`,
height: `${targetHeight}px`,
transform: `scale(${scale})`,
transformOrigin: '50% 0',
};
this.khfwStyle = {
transform: `scale(${scale})`,
transformOrigin: '50% 0',
position: 'fixed',
top: `40%`,
right: `0.8%`,
};
},
breadInit() {
let mhMeta = window.localStorage.getItem('mhMeta');
if (mhMeta) {
@ -106,14 +65,10 @@ export default {
breandCrumbs[breandCrumbs.length - 1].path = breadcrumb;
}
}
if (this.meta) {
// eventBus emitEvent
if (this.meta && this.$refs.gtbread) {
this.$refs.gtbread.meta = this.meta;
}
},
getHeight() {
this.containerHeight = getClientHeight() - 164;
},
changeRoute(route) {
const isShowSideBar = typeof route.meta.isShowSideBar === 'undefined' ? true : route.meta.isShowSideBar;
this.$store.commit(`global/${this.$storeGlobalTypes.SET_SIDEBAR_STATUS}`, isShowSideBar);
@ -133,56 +88,50 @@ export default {
@import './assets/css/tailwindcss.css';
html {
font-size: 20px; /* 将基准值从12px改为20px */
font-size: 20px;
scroll-behavior: smooth;
}
@media screen and (max-width: 767px) {
html {
font-size: 16px;
}
html a {
font-size: inherit;
}
}
a {
font-size: 20px;
color: #9ca3af;
text-decoration: none;
}
/* .cxssb-content {
.portal-app-root {
width: 100%;
height: 100vh;
} */
/* 增强版隐藏滚动条方案 */
.cxssb-content {
width: 100%;
height: 100vh;
overflow-x: hidden !important;
overflow-y: auto !important; /* 使用 !important 提高优先级 */
flex-shrink: 0;
scrollbar-width: none !important; /* Firefox */
-ms-overflow-style: none !important; /* IE 10+ */
min-height: 100vh;
min-height: 100dvh;
}
/* iframe 嵌入子页 */
.cxssb-content {
width: 100%;
height: 100vh;
height: 100dvh;
overflow-x: hidden !important;
overflow-y: auto !important;
flex-shrink: 0;
scrollbar-width: none !important;
-ms-overflow-style: none !important;
}
/* Chrome, Safari, Edge, Opera */
.cxssb-content::-webkit-scrollbar {
display: none !important;
width: 0 !important;
height: 0 !important;
}
.cxssb-content::-webkit-scrollbar-track {
background: transparent !important;
}
.cxssb-content::-webkit-scrollbar-thumb {
background: transparent !important;
border: none !important;
}
/* 针对 IE 和 Edge 的额外处理 */
@supports (-ms-ime-align: auto) {
.cxssb-content {
-ms-overflow-style: none;
overflow: -moz-scrollbars-none;
}
}
/* 针对老版本 Safari */
@supports (-webkit-overflow-scrolling: touch) {
.cxssb-content {
-webkit-overflow-scrolling: touch;

View File

@ -68,19 +68,54 @@
</div>
<div class="mobile-menu-list">
<div v-for="(menu, index) in menuOptions" :key="index">
<!-- 有子菜单的项 -->
<t-dropdown v-if="menu.child" trigger="click" :options="menu.child" @click="handleMobileDropdownClick">
<div class="mobile-menu-item" :class="{'active': curPage == menu.name}">
<img v-if="menu.icon" :src="menu.icon" width="20px" height="20px">
<span>{{ menu.title }}</span>
<img class="arrow" src="@/pages/index/assets/home-arrow-right.png" width="16px" height="16px">
<!-- 有子菜单移动端不用 t-dropdown易被抽屉遮挡改手风琴子项 -->
<div v-if="menu.child" class="mobile-menu-group">
<div
class="mobile-menu-item"
:class="{ active: curPage === menu.name }"
@click="toggleMobileSubmenu(menu.name)"
>
<img v-if="menu.icon" :src="menu.icon" width="20px" height="20px" alt="">
<span class="mobile-menu-item-label">{{ menu.title }}</span>
<img
class="arrow"
:class="{ 'arrow--open': expandedMobileMenu === menu.name }"
src="@/pages/index/assets/home-arrow-right.png"
width="16px"
height="16px"
alt=""
>
</div>
</t-dropdown>
<div v-show="expandedMobileMenu === menu.name" class="mobile-submenu">
<button
v-if="hasMobileParentLink(menu)"
type="button"
class="mobile-submenu-item mobile-submenu-item--parent"
@click="gotoMobileParentPage(menu)"
>
{{ menu.name === 'fwsc' ? '服务中心首页' : `${menu.title}首页` }}
</button>
<button
v-for="(child, ci) in menu.child"
:key="`${menu.name}-${ci}`"
type="button"
class="mobile-submenu-item"
@click="handleMobileDropdownClick(child)"
>
{{ child.title || child.content }}
</button>
</div>
</div>
<!-- 无子菜单的项 -->
<div v-else class="mobile-menu-item" :class="{'active': curPage == menu.name, 'disable': menu.disable}" @click="gotoIfreamPage(menu)">
<img v-if="menu.icon" :src="menu.icon" width="20px" height="20px">
<span>{{ menu.title }}</span>
<img class="arrow" src="@/pages/index/assets/home-arrow-right.png" width="16px" height="16px">
<div
v-else
class="mobile-menu-item"
:class="{ active: curPage === menu.name, disable: menu.disable }"
@click="gotoIfreamPage(menu)"
>
<img v-if="menu.icon" :src="menu.icon" width="20px" height="20px" alt="">
<span class="mobile-menu-item-label">{{ menu.title }}</span>
<img class="arrow" src="@/pages/index/assets/home-arrow-right.png" width="16px" height="16px" alt="">
</div>
</div>
</div>
@ -114,6 +149,7 @@ export default {
curPage: "home",
loginFlag: false, //
mobileMenuOpen: false, //
expandedMobileMenu: null, // name
isIframeEmbedded: window.self !== window.top,
//
routeToMenuMap: {
@ -308,8 +344,27 @@ export default {
//
closeMobileMenu() {
this.mobileMenuOpen = false;
this.expandedMobileMenu = null;
document.body.style.overflow = '';
},
toggleMobileSubmenu(name) {
this.expandedMobileMenu = this.expandedMobileMenu === name ? null : name;
},
hasMobileParentLink(menu) {
if (!menu || !menu.child) return false;
if (menu.name === 'fwsc') return true;
return Boolean(menu.path || menu.iframeUrl);
},
gotoMobileParentPage(menu) {
if (menu.disable) return;
this.curPage = menu.name;
this.closeMobileMenu();
if (menu.iframeUrl) {
this.$emit('gotoIfreamPage', menu.iframeUrl);
return;
}
this.$emit('gotoPage', menu.name);
},
//
goHome() {
this.$router.push('/home');
@ -843,9 +898,58 @@ export default {
height: 20px;
}
.mobile-menu-item-label {
flex: 1;
min-width: 0;
}
.mobile-menu-item .arrow {
margin-left: auto;
opacity: 0.5;
transition: transform 0.2s ease;
}
.mobile-menu-item .arrow--open {
transform: rotate(90deg);
opacity: 0.85;
}
.mobile-menu-group {
border-bottom: 1px solid #f0f0f0;
}
.mobile-submenu {
padding: 0 0 8px;
background: #f8faf9;
}
.mobile-submenu-item {
display: flex;
align-items: center;
width: 100%;
min-height: 48px;
padding: 12px 20px 12px 40px;
font-size: 14px;
color: #333;
text-align: left;
cursor: pointer;
background: transparent;
border: none;
border-bottom: 1px solid #eef2ef;
box-sizing: border-box;
}
.mobile-submenu-item:last-child {
border-bottom: none;
}
.mobile-submenu-item--parent {
font-weight: 600;
color: #009a29;
}
.mobile-submenu-item:active {
background: #eef8f0;
}
.mobile-menu-item.active {
@ -898,10 +1002,6 @@ export default {
background: #fff;
}
.logo-title {
display: none;
}
.nav-inner {
min-height: var(--page-nav-height);
}
@ -968,8 +1068,13 @@ export default {
}
.logo-title {
font-size: 20px;
line-height: 24px;
display: block;
overflow: hidden;
max-width: calc(100vw - 96px);
font-size: 18px;
line-height: 1.2;
text-overflow: ellipsis;
white-space: nowrap;
}
.logo-icon {

View File

@ -0,0 +1,49 @@
/**
* 图片懒加载进入视口后再设置 src降低首屏请求量
* 用法<img v-lazy="url" /> <img v-lazy data-src="url" />
*/
function applySrc(el, value) {
const src = value || el.dataset.src;
if (src && el.getAttribute('src') !== src) {
el.setAttribute('src', src);
}
}
export default {
inserted(el, binding) {
if (el.tagName !== 'IMG') return;
const load = () => applySrc(el, binding.value);
if (typeof IntersectionObserver === 'undefined') {
load();
return;
}
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
load();
observer.unobserve(el);
}
});
},
{ rootMargin: '120px 0px', threshold: 0.01 },
);
observer.observe(el);
el._lazyLoadObserver = observer;
},
update(el, binding) {
if (binding.value !== binding.oldValue && el.getAttribute('src')) {
applySrc(el, binding.value);
}
},
unbind(el) {
if (el._lazyLoadObserver) {
el._lazyLoadObserver.disconnect();
delete el._lazyLoadObserver;
}
},
};

View File

@ -13,6 +13,13 @@ import { topbarConfig, sideBarConfig } from './config';
import '@fortawesome/fontawesome-free/css/all.min.css';
import './assets/css/theme.css';
import './styles/page-layout.less';
import './styles/mobile-adaptation.less';
import lazyLoad from './directives/lazy-load';
import { getDeviceClass, isMobileViewport, watchDeviceClass } from './utils/breakpoint';
Vue.directive('lazy', lazyLoad);
Vue.prototype.$isMobileViewport = isMobileViewport;
Vue.prototype.$getDeviceClass = getDeviceClass;
const storeGlobalTypes = Vue.prototype.$storeGlobalTypes;

View File

@ -0,0 +1,12 @@
// 门户响应式断点(与 utils/breakpoint.js 数值一致)
@mq-mobile-xs-max: 360px;
@mq-mobile-sm-max: 480px;
@mq-mobile-max: 767px;
@mq-tablet-max: 1023px;
@mq-desktop-sm-max: 1279px;
@mq-desktop-max: 1439px;
@mq-ultrawide-min: 1920px;
@mq-mobile-min: 768px;
@mq-tablet-min: 1024px;
@mq-desktop-sm-min: 1280px;

View File

@ -0,0 +1,512 @@
@import './breakpoints.less';
// =============================================================================
// 全局:防横向滚动、触控尺寸、表单与图片
// =============================================================================
@media screen and (max-width: @mq-mobile-max) {
html {
height: 100%;
overflow: hidden;
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
}
body,
#app,
.portal-app-root {
height: 100%;
overflow: hidden;
max-width: 100vw;
}
.content-wrap {
overflow-x: hidden;
overflow-y: auto !important;
-webkit-overflow-scrolling: touch;
overscroll-behavior-y: auto;
touch-action: pan-y;
box-sizing: border-box;
}
.page-content-wrap,
.page-nav-inner {
box-sizing: border-box;
max-width: 100%;
}
img,
video {
max-width: 100%;
height: auto;
}
img[loading='lazy'] {
content-visibility: auto;
}
// iOS 输入框聚焦不自动放大:字号 >= 16px
input,
textarea,
select,
.t-input__inner,
.t-textarea__inner {
font-size: 16px !important;
}
.t-input,
.t-textarea,
.t-select .t-input,
input[type='text'],
input[type='password'],
input[type='number'],
input[type='tel'],
input[type='email'],
input[type='search'],
textarea,
select {
min-height: 48px;
}
button,
.t-button,
a.footer-link,
.auth-link,
.open-page,
.gxnlpt-side-action,
.gxnlpt-card-star,
.gxnlpt-more,
.mobile-menu-item,
.mobile-auth-btn {
min-height: 48px;
}
.hamburger-btn {
display: inline-flex !important;
align-items: center;
justify-content: center;
min-width: 48px;
min-height: 48px;
padding: 12px;
}
.gxnlpt-card-star {
min-width: 48px;
padding: 8px;
box-sizing: border-box;
}
// 首页全宽出血区块在窄屏改为 100% 宽,避免横向滚动
.home-section-bleed,
.qych-snap-section,
.compliance-portal,
.portal-page,
.fwsc-page,
.fwsc-container,
.gxnlpt-page {
max-width: 100%;
overflow-x: hidden;
}
.portal-page .top-box {
overflow: visible;
}
.portal-page .top-banner-swiper,
.portal-page .top-box ::v-deep .t-swiper {
max-width: 100%;
}
}
@media screen and (max-width: @mq-mobile-sm-max) {
.page-content-wrap {
padding-left: 16px;
padding-right: 16px;
}
}
// =============================================================================
// 导航
// =============================================================================
@media screen and (max-width: @mq-mobile-max) {
.nav-box {
display: flex;
align-items: center;
justify-content: space-between;
padding-right: 4px;
box-sizing: border-box;
}
.nav-box .nav-inner {
flex: 1;
min-width: 0;
padding-right: 8px;
}
.nav-box .logo-box {
min-height: 48px;
padding: 4px 0;
min-width: 0;
}
.nav-box .logo-title {
display: block;
overflow: hidden;
max-width: calc(100vw - 96px);
font-size: 18px;
line-height: 1.2;
text-overflow: ellipsis;
white-space: nowrap;
}
.nav-box .hamburger-btn {
position: relative;
z-index: 10001;
flex-shrink: 0;
}
.mobile-menu-item {
display: flex;
align-items: center;
min-height: 48px;
padding: 12px 20px;
}
.mobile-auth-btn {
display: flex;
align-items: center;
justify-content: center;
min-height: 48px;
}
.close-btn {
min-width: 48px;
min-height: 48px;
line-height: 48px;
text-align: center;
}
}
// =============================================================================
// 共性能力 gxnlpt
// =============================================================================
@media screen and (max-width: @mq-mobile-max) {
/* 窄屏顶栏子导航由 .gxnlpt-shell--stacked 全宽灰底,此处不再加 shell 左右内边距 */
/* 保持垂直子导航(与图二一致),勿改为横向 Pill */
.gxnlpt-layout--stacked .gxnlpt-side-item {
min-height: 48px;
}
.gxnlpt-layout--stacked .gxnlpt-side-actions {
flex-direction: column;
gap: 8px;
}
.gxnlpt-layout--stacked .gxnlpt-side-action {
flex: none;
width: 100%;
}
.gxnlpt-submit-form .gxnlpt-input,
.gxnlpt-submit-form .gxnlpt-textarea,
.gxnlpt-submit-form .gxnlpt-select,
.gxnlpt-submit-btn {
min-height: 48px;
}
.gxnlpt-submit-btn {
width: 100%;
}
}
@media screen and (max-width: @mq-mobile-sm-max) {
.gxnlpt-card-grid {
grid-template-columns: 1fr !important;
gap: 12px;
}
.gxnlpt-content {
padding: 12px !important;
}
}
// =============================================================================
// 企业出海 qych
// =============================================================================
@media screen and (max-width: @mq-mobile-max) {
.compliance-portal {
min-height: auto !important;
overflow: visible !important;
}
.compliance-portal .qych-snap-section {
min-height: auto !important;
height: auto !important;
}
}
@media screen and (max-width: @mq-tablet-max) {
/* 窄屏改为上下布局后,取消 490px 固定高度,避免「申请服务」侧栏被 overflow 裁掉 */
#anchor-container .banner.qych-snap-section .text-section {
height: auto !important;
min-height: 0 !important;
overflow: visible !important;
}
#section0 .text-section,
#section1 .text-section.qych-policy-frame,
#section2 .text-section {
height: auto !important;
min-height: 0 !important;
}
#section0 .text-section-content,
#section1 .text-section.qych-policy-frame .text-section-content,
#section2 .text-section-content {
flex: none !important;
min-height: 0 !important;
}
#anchor-container .banner.qych-snap-section .text-section-head-row {
grid-template-columns: 1fr;
row-gap: 4px;
padding-left: 12px;
padding-right: 12px;
}
#anchor-container .banner.qych-snap-section .text-section-content {
flex-direction: column;
align-items: stretch;
padding-left: 12px;
padding-right: 12px;
padding-bottom: 16px;
gap: 12px;
}
#anchor-container .banner.qych-snap-section .content-item1 {
flex: none !important;
width: 100%;
max-height: 320px;
min-height: 200px;
height: auto;
}
#anchor-container .banner.qych-snap-section .content-item2 {
display: flex !important;
flex: none !important;
width: 100%;
min-width: 0;
order: 0;
}
#anchor-container .banner.qych-snap-section .service-section-dcfa {
width: 100%;
padding-left: 0;
border-left: none;
background: transparent;
}
#anchor-container .banner.qych-snap-section .dcfa-cards-stack {
width: 100%;
}
#anchor-container .banner.qych-snap-section .card-item1,
#anchor-container .banner.qych-snap-section .card-item2 {
min-height: 112px;
}
}
@media screen and (max-width: @mq-mobile-sm-max) {
.qych-landing .banner-section {
height: auto;
min-height: 200px;
}
.qych-landing .banner-title {
font-size: 28px;
line-height: 1.25;
}
.qych-landing .services-section .services-grid {
grid-template-columns: 1fr;
}
}
// =============================================================================
// 碳服务 / 列表页
// =============================================================================
@media screen and (max-width: @mq-mobile-sm-max) {
.fwsc-page .banner-section,
.fwsc-page .fwsc-main,
.fwsc-container .fwsc-main,
.fwsc-container .secondary-nav-content {
max-width: 100%;
overflow-x: hidden;
box-sizing: border-box;
}
.fwsc-page .filter-sidebar,
.fwsc-page .card-list,
.fwsc-page .content-area,
.fwsc-container .filter-sidebar,
.fwsc-container .card-list,
.fwsc-container .content-area {
width: 100%;
max-width: 100%;
}
.fwsc-page .nav-tab,
.fwsc-page .publish-btn,
.fwsc-page .card-actions span,
.fwsc-container .nav-tab,
.fwsc-container .publish-btn,
.fwsc-container .card-actions span {
min-height: 48px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.fwsc-page .service-grid,
.fwsc-container .service-grid {
grid-template-columns: 1fr !important;
}
.fwsc-page .pagination-box,
.fwsc-container .pagination-box {
padding-bottom: 32px;
}
.fwsc-page .site-footer,
.fwsc-container .site-footer {
margin-top: 0;
}
.sjsc-page .page-body {
flex-direction: column;
}
.sjsc-page .service-grid {
grid-template-columns: 1fr !important;
}
.sjsc-page .service-card {
width: 100%;
max-width: 100%;
}
}
// =============================================================================
// 页脚
// =============================================================================
@media screen and (max-width: @mq-mobile-max) {
.site-footer .footer-columns {
flex-direction: column;
gap: 20px;
}
.site-footer .footer-link {
display: inline-flex;
align-items: center;
min-height: 48px;
padding: 4px 0;
}
}
// =============================================================================
// 首页 home2移动端原生纵向滚动关闭分屏锁高
// =============================================================================
@media screen and (max-width: @mq-mobile-max) {
.portal-page > .container {
min-height: auto;
}
.portal-page .bottom-box {
height: auto !important;
min-height: 280px !important;
overflow: visible !important;
}
.portal-page .bottom-box-inner {
min-height: 300px;
height: auto;
padding: 40px var(--page-gutter-x, 16px) 48px;
box-sizing: border-box;
}
.portal-page .bottom-box-bg {
left: 0 !important;
top: 0 !important;
width: 100% !important;
height: 100% !important;
object-fit: cover;
object-position: center center;
}
.portal-page .bottom-box-copy {
align-items: center;
padding-left: 0;
padding-right: 0;
}
.portal-page .bottom-box-content-title,
.portal-page .bottom-box-desc {
text-align: center;
}
.portal-page .core-section,
.portal-page .capability-section,
.portal-page .overseas2-section,
.portal-page .news-section,
.portal-page .partner-section {
min-height: auto !important;
}
}
// =============================================================================
// 企业出海:移动端取消全屏分块锁高
// =============================================================================
@media screen and (max-width: @mq-mobile-max) {
.qych-snap-section,
.qych-landing {
min-height: auto !important;
overflow: visible !important;
}
.qych-landing .banner-section {
height: auto;
min-height: 200px;
}
}
// =============================================================================
// 首页 home2 触控补强(与页面内 767 断点叠加,不覆盖桌面)
// =============================================================================
@media screen and (max-width: @mq-mobile-max) {
.portal-page .search-btn,
.portal-page .option-item-box,
.portal-page .hero-card .btn,
.portal-page .core-item,
.portal-page .capability-card {
min-height: 48px;
}
.portal-page .search-btn {
height: 48px;
}
.portal-page .partner-icon,
.portal-page .capability-icon,
.portal-page .overseas2-icon {
max-width: 100%;
}
}

View File

@ -65,13 +65,49 @@
}
}
@media screen and (min-width: 768px) and (max-width: 1023px) {
:root {
--portal-services-fwsc-cols: 2;
--portal-services-grid-gap: 20px;
--page-section-padding-y: 48px;
}
}
@media screen and (max-width: 767px) {
:root {
--page-nav-padding-left: 36px;
--page-nav-padding-left: 16px;
--page-gutter-x: 16px;
--page-content-align-x: 16px;
--page-section-title-padding-left: 16px;
--page-content-max-width: 100%;
--page-section-padding-y: 40px;
--page-nav-height: 56px;
--page-hero-title-offset-top: 72px;
--page-section-title-top: 72px;
--portal-services-fwsc-cols: 1;
--portal-services-grid-gap: 12px;
}
}
@media screen and (max-width: 480px) {
:root {
--page-gutter-x: 16px;
--page-nav-padding-left: 16px;
--page-hero-title-offset-top: 56px;
--page-section-title-top: 56px;
}
}
@media screen and (max-width: 360px) {
:root {
--page-gutter-x: 12px;
--page-nav-padding-left: 12px;
}
}
@media screen and (min-width: 1920px) {
:root {
--page-content-max-width: 1200px;
}
}

View File

@ -0,0 +1,22 @@
@import './breakpoints.less';
// 移动优先max-width 断点包裹
.respond-max(@max, @rules) {
@media screen and (max-width: @max) {
@rules();
}
}
// 桌面增强min-width 断点包裹
.respond-min(@min, @rules) {
@media screen and (min-width: @min) {
@rules();
}
}
// 区间断点
.respond-between(@min, @max, @rules) {
@media screen and (min-width: @min) and (max-width: @max) {
@rules();
}
}

View File

@ -0,0 +1,54 @@
/** 门户响应式断点(与 styles/breakpoints.less 保持一致) */
export const BP = {
mobileXs: 360,
mobileSm: 480,
mobile: 768,
tablet: 1024,
desktopSm: 1280,
desktop: 1440,
ultrawide: 1920,
};
export const MQ = {
mobileMax: `(max-width: ${BP.mobile - 1}px)`,
mobileSmMax: `(max-width: ${BP.mobileSm}px)`,
tabletMax: `(max-width: ${BP.tablet - 1}px)`,
desktopSmMax: `(max-width: ${BP.desktopSm - 1}px)`,
};
export function isMobileViewport() {
if (typeof window === 'undefined') return false;
return window.matchMedia(MQ.mobileMax).matches;
}
export function isTabletViewport() {
if (typeof window === 'undefined') return false;
return window.matchMedia(`(min-width: ${BP.mobile}px) and (max-width: ${BP.tablet - 1}px)`).matches;
}
export function getDeviceClass() {
if (typeof window === 'undefined') return 'is-desktop';
const w = window.innerWidth;
if (w < BP.mobile) return 'is-mobile';
if (w < BP.tablet) return 'is-tablet';
if (w < BP.desktopSm) return 'is-desktop-sm';
return 'is-desktop';
}
/**
* 监听视口档位变化
* @param {(tier: string) => void} callback
* @returns {() => void}
*/
export function watchDeviceClass(callback) {
if (typeof window === 'undefined') return () => {};
const mq = window.matchMedia(MQ.mobileMax);
const run = () => callback(getDeviceClass());
run();
if (typeof mq.addEventListener === 'function') {
mq.addEventListener('change', run);
return () => mq.removeEventListener('change', run);
}
mq.addListener(run);
return () => mq.removeListener(run);
}

View File

@ -0,0 +1,58 @@
/**
* 桌面端全屏分屏滚轮移动端/触控设备使用原生滚动
*/
export function shouldUseSectionWheelScroll() {
if (typeof window === 'undefined') return true;
return !window.matchMedia('(max-width: 767px), (pointer: coarse)').matches;
}
/**
* 按视口动态绑定/解绑 wheel 分屏逻辑
* @param {HTMLElement} root
* @param {(e: WheelEvent) => void} handler
* @returns {() => void} cleanup
*/
export function bindSectionWheelScroll(root, handler) {
if (!root || !handler) return () => {};
const mq = window.matchMedia('(max-width: 767px), (pointer: coarse)');
const sync = () => {
root.removeEventListener('wheel', handler);
if (shouldUseSectionWheelScroll()) {
root.addEventListener('wheel', handler, { passive: false });
}
};
sync();
if (typeof mq.addEventListener === 'function') {
mq.addEventListener('change', sync);
} else if (typeof mq.addListener === 'function') {
mq.addListener(sync);
}
return () => {
root.removeEventListener('wheel', handler);
if (typeof mq.removeEventListener === 'function') {
mq.removeEventListener('change', sync);
} else if (typeof mq.removeListener === 'function') {
mq.removeListener(sync);
}
};
}
/**
* 门户主内容区滚回顶部分页筛选等页内操作
* @param {{ smooth?: boolean, selector?: string }} [options]
*/
export function scrollPortalContentToTop(options = {}) {
if (typeof window === 'undefined') return;
const { smooth = true, selector = '.content-wrap' } = options;
const root = document.querySelector(selector);
const behavior = smooth ? 'smooth' : 'auto';
if (root) {
root.scrollTo({ top: 0, behavior });
return;
}
window.scrollTo({ top: 0, behavior });
}

View File

@ -1,5 +1,5 @@
<template>
<div class="fwsc-container">
<div class="fwsc-container fwsc-page">
<!-- 面包屑导航 -->
<!-- <BreadcrumbNav currentPage="碳服务市场" /> -->
@ -180,6 +180,7 @@ import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue';
import FwscPublish from './components/FwscPublish.vue';
import api from '@/pages/index/api/fwsc/index.js';
import { hasLogin } from '@/pages/index/api/login';
import { scrollPortalContentToTop } from '@/pages/index/utils/portal-scroll-mode';
export default {
name: 'FwscPage',
@ -481,6 +482,7 @@ export default {
},
//
onPageChange() {
scrollPortalContentToTop();
this.searchList();
},
},
@ -754,8 +756,10 @@ export default {
.card-header {
position: relative;
box-sizing: border-box;
padding: 16px;
height: 70px;
min-height: 70px;
height: auto;
&::after {
position: absolute;
@ -840,14 +844,16 @@ export default {
}
.card-desc {
display: block;
height: 70px;
display: -webkit-box;
min-height: 44px;
max-height: 70px;
overflow: hidden;
font-size: 14px;
line-height: 1.6;
color: #666;
text-overflow: ellipsis;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
.card-tags {
@ -867,11 +873,14 @@ export default {
.card-footer {
position: relative;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 16px;
height: 64px;
min-height: 64px;
height: auto;
flex-shrink: 0;
&::before {
position: absolute;
@ -890,7 +899,10 @@ export default {
}
.card-actions {
display: flex;
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
height: 32px;
padding: 6px 12px;
border-radius: 4px;
@ -898,7 +910,9 @@ export default {
color: #00b96b;
font-size: 14px;
font-weight: 400;
flex-shrink: 0;
white-space: nowrap;
&:hover {
background: rgba(0, 154, 41, 0.1);
cursor: pointer;
@ -962,20 +976,30 @@ export default {
.pagination-box {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
padding-top: 32px;
gap: 10px;
gap: 16px;
width: 100%;
box-sizing: border-box;
::v-deep .t-pagination {
display: flex !important;
justify-content: center;
flex-wrap: wrap;
width: initial;
align-items: center;
justify-content: center;
width: auto;
max-width: 100%;
gap: 12px 16px;
.t-input.t-is-readonly {
width: 110px;
}
.t-pagination__select {
margin-right: 0;
}
}
}
@ -996,52 +1020,79 @@ export default {
}
@media (max-width: 1200px) {
.service-card {
width: calc((100% - 20px) / 2);
.service-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16px;
}
}
@media (max-width: 768px) {
.fwsc-main {
padding: 12px;
box-sizing: border-box;
}
.secondary-nav-content {
flex-direction: column;
align-items: stretch;
padding: 12px 16px;
gap: 12px;
}
.nav-tabs {
width: 100%;
max-width: 100%;
height: auto;
min-height: 42px;
padding-bottom: 4px;
overflow-x: auto;
gap: 4px;
overflow-y: hidden;
gap: 8px;
flex-wrap: nowrap;
scrollbar-width: none;
-webkit-overflow-scrolling: touch;
&::-webkit-scrollbar {
display: none;
}
}
.nav-tab {
flex-shrink: 0;
padding: 10px 12px;
font-size: 13px;
white-space: nowrap;
}
.nav-right {
width: 100%;
flex-direction: column;
align-items: stretch;
gap: 8px;
}
.publish-btn {
width: 100%;
padding: 10px;
box-sizing: border-box;
}
.content-area {
flex-direction: column;
gap: 12px;
}
.filter-sidebar {
position: relative;
top: 0;
order: -1;
width: 100%;
}
.card-list {
order: 0;
width: 100%;
min-width: 0;
}
.list-header {
@ -1057,28 +1108,176 @@ export default {
.service-card {
width: 100%;
max-width: 100%;
}
.card-header {
padding: 12px;
min-height: 0;
padding: 12px 12px 14px;
}
.card-title-sub {
flex-direction: column;
align-items: flex-start;
gap: 6px;
}
.card-company,
.location {
max-width: 100%;
}
.company-name {
white-space: normal;
}
.card-content {
padding: 12px;
}
.card-desc {
min-height: 0;
max-height: none;
height: auto;
}
.card-footer {
min-height: 0;
padding: 12px;
flex-direction: column;
flex-direction: row;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.card-price-info {
flex: 1;
min-width: 0;
}
.card-actions {
width: 100%
width: auto;
min-width: 96px;
height: 40px;
padding: 8px 14px;
}
.pagination-box {
padding-top: 20px;
flex-direction: column;
align-items: stretch;
padding-top: 16px;
padding-bottom: 32px;
gap: 12px;
}
.pagination-total {
width: 100%;
font-size: 14px;
line-height: 22px;
text-align: center;
white-space: nowrap;
}
.pagination-box ::v-deep .t-pagination {
display: flex !important;
flex-wrap: wrap !important;
align-items: center;
justify-content: center !important;
width: 100% !important;
max-width: 100%;
white-space: normal !important;
row-gap: 12px;
column-gap: 8px;
}
.pagination-box ::v-deep .t-pagination__total {
display: none;
}
.pagination-box ::v-deep .t-pagination__btn-prev {
order: 1;
}
.pagination-box ::v-deep .t-pagination__pager {
order: 2;
}
.pagination-box ::v-deep .t-pagination__btn-next {
order: 3;
}
.pagination-box ::v-deep .t-pagination__select {
order: 4;
flex: 0 0 auto;
width: auto;
max-width: none;
margin: 0 0 0 8px !important;
display: flex;
justify-content: center;
}
.pagination-box ::v-deep .t-pagination__select .t-select__wrap {
width: auto;
max-width: none;
}
.pagination-box ::v-deep .t-pagination__pager {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 6px;
max-width: 100%;
}
@mob-pagination-h: 32px;
.pagination-box ::v-deep .t-pagination__number {
min-width: @mob-pagination-h;
height: @mob-pagination-h;
line-height: @mob-pagination-h;
margin: 0;
box-sizing: border-box;
}
.pagination-box ::v-deep .t-pagination__btn {
min-width: @mob-pagination-h;
width: @mob-pagination-h;
height: @mob-pagination-h;
line-height: @mob-pagination-h;
}
.pagination-box ::v-deep .t-pagination__select {
height: @mob-pagination-h;
align-items: center;
}
.pagination-box ::v-deep .t-pagination__select .t-select__wrap,
.pagination-box ::v-deep .t-pagination__select .t-input__wrap,
.pagination-box ::v-deep .t-pagination__select .t-input {
height: @mob-pagination-h !important;
min-height: @mob-pagination-h !important;
box-sizing: border-box;
}
.pagination-box ::v-deep .t-pagination__select .t-input__inner {
height: @mob-pagination-h !important;
min-height: @mob-pagination-h !important;
line-height: @mob-pagination-h;
padding-top: 0;
padding-bottom: 0;
font-size: 13px;
box-sizing: border-box;
}
.pagination-box ::v-deep .t-pagination__jump {
display: none !important;
}
.pagination-box ::v-deep .t-input.t-is-readonly {
width: auto;
min-width: 96px;
max-width: none;
}
}
@ -1121,6 +1320,36 @@ export default {
.price-value {
font-size: 18px;
}
.pagination-box {
padding-bottom: 40px;
}
@mob-pagination-h-sm: 28px;
.pagination-box ::v-deep .t-pagination__number {
min-width: @mob-pagination-h-sm;
height: @mob-pagination-h-sm;
line-height: @mob-pagination-h-sm;
font-size: 13px;
}
.pagination-box ::v-deep .t-pagination__btn {
min-width: @mob-pagination-h-sm;
width: @mob-pagination-h-sm;
height: @mob-pagination-h-sm;
line-height: @mob-pagination-h-sm;
}
.pagination-box ::v-deep .t-pagination__select,
.pagination-box ::v-deep .t-pagination__select .t-select__wrap,
.pagination-box ::v-deep .t-pagination__select .t-input__wrap,
.pagination-box ::v-deep .t-pagination__select .t-input,
.pagination-box ::v-deep .t-pagination__select .t-input__inner {
height: @mob-pagination-h-sm !important;
min-height: @mob-pagination-h-sm !important;
line-height: @mob-pagination-h-sm;
}
}
@keyframes highlight-pulse {

View File

@ -167,6 +167,7 @@ export default {
// Banner -
.banner-section {
position: relative;
z-index: 1;
display: flex;
// height: 400px;
height: 350px;
@ -225,10 +226,11 @@ export default {
text-shadow: 0 0 1px #ffffff, 0 0 3px #ffffff, 0 0 6px #ffffff, 0 0 10px #ffffff;
}
//
// margin Banner
.services-section {
padding: 60px 0 80px;
position: relative;
z-index: 2;
margin-top: -120px;
}
@ -267,10 +269,11 @@ export default {
.services-grid {
display: grid;
width: 100%;
grid-template-columns: repeat(4, minmax(0, 1fr));
grid-template-columns: repeat(var(--portal-services-fwsc-cols, 4), minmax(0, 1fr));
gap: var(--portal-services-grid-gap, 24px);
max-width: var(--portal-services-grid-max, 1300px);
max-width: var(--portal-services-grid-max, var(--page-content-max-width, 1200px));
margin: 0 auto;
box-sizing: border-box;
}
.service-card {
@ -300,6 +303,7 @@ export default {
.service-card-header {
display: flex;
flex-shrink: 0;
align-items: center;
gap: 16px;
padding-bottom: 20px;
@ -316,17 +320,21 @@ export default {
.service-card-title {
font-size: 22px;
font-weight: 600;
line-height: 1.35;
color: #1a1a1a;
margin: 0;
}
.service-card-desc {
position: relative;
z-index: 1;
font-size: 14px;
font-weight: 400;
line-height: 1.8;
color: #666;
flex: 1 1 auto;
flex-grow: 1;
margin-bottom: 24px;
margin: 0 0 24px;
}
.service-card-buttons {
@ -360,12 +368,6 @@ export default {
border-bottom-color: rgba(114, 46, 209, 0.2);
}
@media (max-width: 1400px) {
.services-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 1200px) {
.services-section {
padding: 40px 0 60px;
@ -375,11 +377,7 @@ export default {
@media (max-width: 900px) {
.services-section {
padding: 30px 0 50px;
}
.services-grid {
grid-template-columns: minmax(0, 1fr);
gap: 16px;
margin-top: -72px;
}
.service-card,
@ -411,10 +409,19 @@ export default {
}
.banner-section {
height: 220px;
height: auto;
min-height: 200px;
padding: 32px 16px 56px;
box-sizing: border-box;
}
.banner-content {
max-width: 100%;
padding: 0;
}
.banner-title {
margin-bottom: 12px;
font-size: 28px;
letter-spacing: 1px;
}
@ -425,7 +432,8 @@ export default {
}
.services-section {
padding: 20px 16px 40px;
padding: 0 16px 40px;
margin-top: -32px;
}
.section-header {
@ -448,7 +456,7 @@ export default {
}
.services-grid {
gap: 12px;
gap: 16px;
}
.service-card,
@ -461,9 +469,11 @@ export default {
}
.service-card-header {
padding-bottom: 14px;
margin-bottom: 14px;
gap: 12px;
flex-direction: column;
align-items: flex-start;
padding-bottom: 12px;
margin-bottom: 12px;
gap: 8px;
}
.service-card-num {
@ -476,7 +486,7 @@ export default {
.service-card-desc {
font-size: 13px;
margin-bottom: 16px;
margin: 0 0 16px;
line-height: 1.6;
}
@ -487,7 +497,8 @@ export default {
@media (max-width: 480px) {
.banner-section {
height: 180px;
min-height: 180px;
padding: 28px 12px 48px;
}
.banner-title {
@ -499,7 +510,8 @@ export default {
}
.services-section {
padding: 16px 12px 30px;
padding: 0 12px 30px;
margin-top: -24px;
}
.service-card-inner {

View File

@ -632,9 +632,16 @@ export default {
.nav-tabs {
width: 100%;
height: auto;
padding-bottom: 4px;
overflow-x: auto;
gap: 4px;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
}
.nav-tab {
@ -651,27 +658,71 @@ export default {
.sidebar {
position: relative;
top: 0;
order: -1;
width: 100%;
min-width: auto;
min-width: 0;
}
.content-area {
.card-list {
order: 0;
width: 100%;
min-width: 0;
}
.card-grid {
.service-grid {
grid-template-columns: 1fr;
gap: 12px;
}
.card-footer {
flex-direction: column;
gap: 12px;
align-items: flex-start;
.service-card {
width: 100%;
max-width: 100%;
}
.card-footer .t-button {
width: 100%;
.card-header {
height: auto;
min-height: 0;
padding: 12px 12px 14px;
}
.card-title-sub {
flex-direction: column;
align-items: flex-start;
gap: 6px;
}
.card-content {
padding: 12px;
}
.card-desc {
height: auto;
min-height: 0;
max-height: none;
}
.card-footer {
flex-direction: row;
align-items: center;
justify-content: space-between;
height: auto;
min-height: 0;
padding: 12px;
gap: 12px;
}
.card-price-info {
flex: 1;
min-width: 0;
}
.card-actions {
flex-shrink: 0;
width: auto;
min-width: 96px;
height: 40px;
padding: 8px 14px;
box-sizing: border-box;
}
}
@ -694,7 +745,7 @@ export default {
font-size: 13px;
}
.sidebar {
.sidebar-content {
padding: 12px;
}
@ -702,17 +753,16 @@ export default {
font-size: 13px;
}
.database-card {
padding: 16px;
}
.card-title {
font-size: 16px;
.card-title-main {
font-size: 14px;
}
.card-desc {
margin-bottom: 12px;
font-size: 13px;
}
.price-value {
font-size: 18px;
}
}
</style>

View File

@ -209,6 +209,7 @@ 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';
import { scrollPortalContentToTop } from '@/pages/index/utils/portal-scroll-mode';
export default {
name: 'XqscPage',
@ -364,6 +365,7 @@ export default {
onPageChange(pageInfo) {
this.page.pageNo = pageInfo.current;
this.page.pageSize = pageInfo.pageSize;
scrollPortalContentToTop();
this.searchList();
},
//
@ -908,20 +910,30 @@ export default {
.pagination-box {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
padding-top: 32px;
gap: 10px;
gap: 16px;
width: 100%;
box-sizing: border-box;
::v-deep .t-pagination {
display: flex !important;
justify-content: center;
flex-wrap: wrap;
width: initial;
align-items: center;
justify-content: center;
width: auto;
max-width: 100%;
gap: 12px 16px;
.t-input.t-is-readonly {
width: 110px;
}
.t-pagination__select {
margin-right: 0;
}
}
}
@ -978,11 +990,18 @@ export default {
.content-area {
flex-direction: column;
gap: 12px;
}
.filter-sidebar {
position: relative;
top: 0;
order: -1;
width: 100%;
}
.demand-list {
order: 0;
width: 100%;
}
@ -990,10 +1009,6 @@ export default {
padding: 12px;
}
.demand-list {
width: 100%;
}
.demand-grid {
grid-template-columns: 1fr;
gap: 12px;
@ -1022,7 +1037,121 @@ export default {
}
.pagination-box {
padding-top: 20px;
flex-direction: column;
align-items: stretch;
padding-top: 16px;
padding-bottom: 32px;
gap: 12px;
}
.pagination-total {
width: 100%;
font-size: 14px;
line-height: 22px;
text-align: center;
white-space: nowrap;
}
.pagination-box ::v-deep .t-pagination {
display: flex !important;
flex-wrap: wrap !important;
align-items: center;
justify-content: center !important;
width: 100% !important;
max-width: 100%;
white-space: normal !important;
row-gap: 12px;
column-gap: 8px;
}
.pagination-box ::v-deep .t-pagination__total {
display: none;
}
.pagination-box ::v-deep .t-pagination__btn-prev {
order: 1;
}
.pagination-box ::v-deep .t-pagination__pager {
order: 2;
}
.pagination-box ::v-deep .t-pagination__btn-next {
order: 3;
}
.pagination-box ::v-deep .t-pagination__select {
order: 4;
flex: 0 0 auto;
width: auto;
max-width: none;
margin: 0 0 0 8px !important;
display: flex;
justify-content: center;
}
.pagination-box ::v-deep .t-pagination__select .t-select__wrap {
width: auto;
max-width: none;
}
.pagination-box ::v-deep .t-pagination__pager {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 6px;
max-width: 100%;
}
@mob-pagination-h: 32px;
.pagination-box ::v-deep .t-pagination__number {
min-width: @mob-pagination-h;
height: @mob-pagination-h;
line-height: @mob-pagination-h;
margin: 0;
box-sizing: border-box;
}
.pagination-box ::v-deep .t-pagination__btn {
min-width: @mob-pagination-h;
width: @mob-pagination-h;
height: @mob-pagination-h;
line-height: @mob-pagination-h;
}
.pagination-box ::v-deep .t-pagination__select {
height: @mob-pagination-h;
align-items: center;
}
.pagination-box ::v-deep .t-pagination__select .t-select__wrap,
.pagination-box ::v-deep .t-pagination__select .t-input__wrap,
.pagination-box ::v-deep .t-pagination__select .t-input {
height: @mob-pagination-h !important;
min-height: @mob-pagination-h !important;
box-sizing: border-box;
}
.pagination-box ::v-deep .t-pagination__select .t-input__inner {
height: @mob-pagination-h !important;
min-height: @mob-pagination-h !important;
line-height: @mob-pagination-h;
padding-top: 0;
padding-bottom: 0;
font-size: 13px;
box-sizing: border-box;
}
.pagination-box ::v-deep .t-pagination__jump {
display: none !important;
}
.pagination-box ::v-deep .t-input.t-is-readonly {
width: auto;
min-width: 96px;
max-width: none;
}
}
@ -1061,6 +1190,36 @@ export default {
.budget-value {
font-size: 18px;
}
.pagination-box {
padding-bottom: 40px;
}
@mob-pagination-h-sm: 28px;
.pagination-box ::v-deep .t-pagination__number {
min-width: @mob-pagination-h-sm;
height: @mob-pagination-h-sm;
line-height: @mob-pagination-h-sm;
font-size: 13px;
}
.pagination-box ::v-deep .t-pagination__btn {
min-width: @mob-pagination-h-sm;
width: @mob-pagination-h-sm;
height: @mob-pagination-h-sm;
line-height: @mob-pagination-h-sm;
}
.pagination-box ::v-deep .t-pagination__select,
.pagination-box ::v-deep .t-pagination__select .t-select__wrap,
.pagination-box ::v-deep .t-pagination__select .t-input__wrap,
.pagination-box ::v-deep .t-pagination__select .t-input,
.pagination-box ::v-deep .t-pagination__select .t-input__inner {
height: @mob-pagination-h-sm !important;
min-height: @mob-pagination-h-sm !important;
line-height: @mob-pagination-h-sm;
}
}
@keyframes highlight-pulse {

View File

@ -1,32 +1,31 @@
<template>
<div v-if="tags.length" ref="root" class="gxnlpt-card-tags">
<t-tooltip
v-if="hasOverflow"
:disabled="!hasOverflow"
:content="overflowTooltip"
theme="light"
placement="top"
:show-arrow="true"
>
<div ref="track" class="gxnlpt-tag-track gxnlpt-tag-track--interactive">
<div
ref="track"
class="gxnlpt-tag-track"
:class="{ 'gxnlpt-tag-track--interactive': hasOverflow }"
>
<span
v-for="(tag, ti) in visibleTags"
:key="`visible-${ti}-${tag}`"
class="gxnlpt-tag"
:title="tag"
>{{ tag }}</span>
<span class="gxnlpt-tag-ellipsis" aria-label="更多标签"></span>
<span
v-if="hasOverflow"
class="gxnlpt-tag gxnlpt-tag-ellipsis"
aria-hidden="true"
>...</span>
</div>
</t-tooltip>
<div v-else ref="track" class="gxnlpt-tag-track">
<span
v-for="(tag, ti) in visibleTags"
:key="`visible-${ti}-${tag}`"
class="gxnlpt-tag"
:title="tag"
>{{ tag }}</span>
</div>
<!-- 离屏测量与可见标签同款式用于计算溢出 -->
<div class="gxnlpt-tag-measure" aria-hidden="true">
<span
v-for="(tag, ti) in tags"
@ -34,7 +33,7 @@
ref="measureTag"
class="gxnlpt-tag"
>{{ tag }}</span>
<span ref="measureEllipsis" class="gxnlpt-tag-ellipsis"></span>
<span ref="measureEllipsis" class="gxnlpt-tag gxnlpt-tag-ellipsis">...</span>
</div>
</div>
</template>
@ -45,7 +44,7 @@ import {
formatHiddenTagsTooltip,
} from '@/pages/index/utils/gxnlpt-tag-overflow.js';
const TAG_GAP = 4;
const TAG_GAP = 8;
export default {
name: 'GxnlptCardTags',
@ -61,6 +60,7 @@ export default {
hasOverflow: false,
resizeObserver: null,
measureRaf: null,
measureRetry: 0,
};
},
computed: {
@ -85,17 +85,13 @@ export default {
watch: {
tags: {
handler() {
this.scheduleMeasure();
this.resetAndMeasure();
},
deep: true,
},
hasOverflow() {
this.$nextTick(() => this.scheduleMeasure());
},
},
mounted() {
this.visibleCount = this.normalizedTags.length;
this.scheduleMeasure();
this.resetAndMeasure();
this.bindResizeObserver();
},
beforeDestroy() {
@ -106,8 +102,37 @@ export default {
}
},
methods: {
getTrackEl() {
return this.$refs.track || this.$el.querySelector('.gxnlpt-tag-track');
resetAndMeasure() {
const n = this.normalizedTags.length;
//
if (n > 2) {
this.visibleCount = 2;
this.hasOverflow = true;
} else {
this.visibleCount = n;
this.hasOverflow = false;
}
this.measureRetry = 0;
this.scheduleMeasure();
setTimeout(() => this.scheduleMeasure(), 0);
setTimeout(() => this.scheduleMeasure(), 150);
},
/** 以卡片内容区宽度为准,避免 track 被标签撑开后误判为「未溢出」 */
getContainerWidth() {
const root = this.$refs.root;
if (!root) return 0;
const anchor =
root.closest('.gxnlpt-card-body') ||
root.closest('.gxnlpt-card') ||
root.parentElement;
if (anchor) {
const width = anchor.getBoundingClientRect().width;
if (width > 0) return Math.floor(width);
}
return 0;
},
scheduleMeasure() {
if (this.measureRaf) cancelAnimationFrame(this.measureRaf);
@ -116,6 +141,16 @@ export default {
this.$nextTick(() => this.measure());
});
},
applyFallbackLayout() {
const n = this.normalizedTags.length;
if (n <= 2) {
this.visibleCount = n;
this.hasOverflow = false;
return;
}
this.visibleCount = 2;
this.hasOverflow = true;
},
measure() {
const tags = this.normalizedTags;
if (!tags.length) {
@ -124,7 +159,18 @@ export default {
return;
}
const track = this.getTrackEl();
const maxWidth = this.getContainerWidth();
if (maxWidth <= 0) {
if (this.measureRetry < 12) {
this.measureRetry += 1;
setTimeout(() => this.scheduleMeasure(), 60);
return;
}
this.applyFallbackLayout();
return;
}
this.measureRetry = 0;
const measureTags = this.$refs.measureTag;
const measureTagEls = Array.isArray(measureTags)
? measureTags
@ -132,35 +178,39 @@ export default {
? [measureTags]
: [];
if (!track || measureTagEls.length !== tags.length) {
this.visibleCount = tags.length;
this.hasOverflow = false;
if (measureTagEls.length !== tags.length) {
this.$nextTick(() => this.scheduleMeasure());
return;
}
const maxWidth = track.clientWidth;
const tagWidths = measureTagEls.map((el) => el.offsetWidth);
const tagWidths = measureTagEls.map((el) => el.getBoundingClientRect().width);
const ellipsisEl = this.$refs.measureEllipsis;
const ellipsisWidth = ellipsisEl ? ellipsisEl.offsetWidth : 14;
const ellipsisWidth = ellipsisEl
? Math.ceil(ellipsisEl.getBoundingClientRect().width)
: 24;
const { visible, overflow } = calcTagOverflowLayout(tagWidths, maxWidth, {
gap: TAG_GAP,
ellipsisWidth,
});
this.visibleCount = visible;
this.visibleCount = Math.max(visible, overflow ? 1 : 0);
this.hasOverflow = overflow;
},
bindResizeObserver() {
const onResize = () => this.scheduleMeasure();
if (typeof ResizeObserver === 'undefined') {
window.addEventListener('resize', this.scheduleMeasure);
window.addEventListener('resize', onResize);
this._onWindowResize = onResize;
return;
}
this.resizeObserver = new ResizeObserver(() => {
this.scheduleMeasure();
});
this.resizeObserver = new ResizeObserver(onResize);
this.$nextTick(() => {
if (this.$refs.root) this.resizeObserver.observe(this.$refs.root);
const root = this.$refs.root;
if (!root) return;
this.resizeObserver.observe(root);
const anchor = root.closest('.gxnlpt-card-body') || root.closest('.gxnlpt-card');
if (anchor) this.resizeObserver.observe(anchor);
});
},
unbindResizeObserver() {
@ -168,7 +218,10 @@ export default {
this.resizeObserver.disconnect();
this.resizeObserver = null;
}
window.removeEventListener('resize', this.scheduleMeasure);
if (this._onWindowResize) {
window.removeEventListener('resize', this._onWindowResize);
this._onWindowResize = null;
}
},
},
};
@ -179,65 +232,78 @@ export default {
.gxnlpt-card-tags {
position: relative;
display: block;
width: 100%;
min-width: 0;
min-height: 20px;
max-width: 100%;
overflow: hidden;
box-sizing: border-box;
}
.gxnlpt-card-tags ::v-deep .t-tooltip {
display: block;
width: 100%;
max-width: 100%;
}
.gxnlpt-card-tags ::v-deep .t-tooltip__trigger {
display: block !important;
width: 100% !important;
max-width: 100% !important;
}
.gxnlpt-tag-track {
display: flex;
flex-wrap: nowrap;
gap: 4px;
align-items: center;
gap: 8px;
width: 100%;
max-width: 100%;
min-width: 0;
overflow: hidden;
box-sizing: border-box;
}
.gxnlpt-tag-track--interactive {
cursor: default;
}
/* 与图二 / 碳服务市场列表标签一致 */
.gxnlpt-tag {
display: inline-flex;
flex-shrink: 0;
align-items: center;
max-width: 120px;
padding: 2px 6px;
overflow: hidden;
padding: 2px 8px;
font-family: @home-font-family;
font-size: 11px;
font-size: 13px;
font-weight: 400;
line-height: 16px;
color: @home-color-primary-green;
text-overflow: ellipsis;
line-height: 20px;
color: #00b96b;
white-space: nowrap;
background: #eefae2;
border: none;
border-radius: 2px;
border-radius: 4px;
box-sizing: border-box;
}
.gxnlpt-tag-ellipsis {
flex-shrink: 0;
padding: 0 2px;
font-family: @home-font-family;
font-size: 11px;
font-weight: 500;
line-height: 16px;
color: @home-color-primary-green;
letter-spacing: 0.5px;
}
.gxnlpt-tag-measure {
position: absolute;
top: 0;
left: 0;
z-index: -1;
visibility: hidden;
pointer-events: none;
display: flex;
flex-wrap: nowrap;
gap: 4px;
height: 0;
overflow: hidden;
gap: 8px;
width: max-content;
height: auto;
overflow: visible;
}
</style>

View File

@ -1,9 +1,12 @@
<template>
<div class="gxnlpt-page portal-page">
<div class="gxnlpt-shell page-content-wrap">
<div class="gxnlpt-layout">
<!-- Figma Frame_left 280px -->
<aside class="gxnlpt-sidebar">
<div
class="gxnlpt-shell page-content-wrap"
:class="{ 'gxnlpt-shell--stacked': stackedNavLayout }"
>
<div class="gxnlpt-layout" :class="{ 'gxnlpt-layout--stacked': stackedNavLayout }">
<!-- Figma Frame_left 280px窄屏为服务中心式子导航面板 -->
<aside class="gxnlpt-sidebar" :class="{ 'gxnlpt-sidebar--panel': stackedNavLayout }">
<div class="gxnlpt-sidebar-sticky">
<div class="gxnlpt-side-nav-wrap">
<nav class="gxnlpt-side-nav" role="tablist" aria-label="共性能力分类">
@ -173,7 +176,7 @@
<template v-else>
<section
v-for="(item, index) in categoryList"
v-for="{ item, index } in listSections"
:key="item.id"
:id="item.id"
class="gxnlpt-block"
@ -240,12 +243,21 @@ import {
isUnauthorizedError,
showLoginGuide,
} from '@/pages/index/utils/auth-guard';
import { BP } from '@/pages/index/utils/breakpoint.js';
const starOutline = require('@/pages/index/assets/fwsc/wsc.svg');
const starFilled = require('@/pages/index/assets/fwsc/ysc.svg');
const PREVIEW_SIZE = 6;
/** 与 breakpoints.less @mq-desktop-sm-max 一致 */
const STACKED_NAV_MEDIA = `(max-width: ${BP.desktopSm - 1}px)`;
function readStackedNavLayout() {
if (typeof window === 'undefined') return false;
return window.matchMedia(STACKED_NAV_MEDIA).matches;
}
/** 临时开启:优先展示分类假数据,接口就绪后改为 false */
const FORCE_DEMO_PREVIEW = true;
@ -253,7 +265,8 @@ const FORCE_DEMO_PREVIEW = true;
* 演示标签溢出省略 UI 测试需与 FORCE_DEMO_PREVIEW 同时为 true
* 关闭后恢复每卡 23 个短标签的正常展示
*/
const DEMO_TAG_OVERFLOW_PREVIEW = true;
/** 关闭后卡片仅展示接口/演示数据中的 23 个短标签,与图二设计稿一致 */
const DEMO_TAG_OVERFLOW_PREVIEW = false;
/** 按分类注入的碳领域长标签(仅溢出 UI 测试用) */
const DEMO_TAG_OVERFLOW_BY_CATEGORY = {
@ -436,9 +449,22 @@ export default {
submitTouched: {},
submitErrors: {},
submitAttempted: false,
stackedNavLayout: readStackedNavLayout(),
_stackedNavMq: null,
};
},
computed: {
isStackedNavMode() {
return this.stackedNavLayout;
},
listSections() {
if (this.isStackedNavMode) {
const item = this.categoryList[this.activeTabIndex];
if (!item) return [];
return [{ item, index: this.activeTabIndex }];
}
return this.categoryList.map((item, index) => ({ item, index }));
},
favoriteCards() {
const list = [];
this.categoryList.forEach((cat) => {
@ -451,10 +477,21 @@ export default {
return list;
},
},
created() {
this.stackedNavLayout = readStackedNavLayout();
},
mounted() {
this.bindStackedNavMedia();
this.bootstrap();
},
activated() {
this.syncStackedNavLayout();
if (this.contentView === 'list' && !this.stackedNavLayout) {
this.$nextTick(() => this.initScrollSpy());
}
},
beforeDestroy() {
this.unbindStackedNavMedia();
this.clearScrollUnlock();
this.destroyScrollSpy();
},
@ -475,12 +512,19 @@ export default {
this.applyDemoFallback();
}
this.$nextTick(() => {
this.initScrollSpy();
const anchor = this.$route.query.anchor || this.$route.params.anchor;
if (anchor) {
const index = this.categoryList.findIndex((item) => item.id === anchor);
this.scrollToSection(anchor, index >= 0 ? index : 0);
const tabIndex = index >= 0 ? index : 0;
if (this.isStackedNavMode) {
this.activeTabIndex = tabIndex;
} else {
this.initScrollSpy();
this.scrollToSection(anchor, tabIndex);
}
return;
}
this.initScrollSpy();
});
},
getIconUrl(iconName) {
@ -492,6 +536,57 @@ export default {
}
return this.getIconUrl(iconName);
},
bindStackedNavMedia() {
if (typeof window === 'undefined' || !window.matchMedia) return;
this._stackedNavMq = window.matchMedia(STACKED_NAV_MEDIA);
this._onStackedNavMqChange = () => this.syncStackedNavLayout();
if (typeof this._stackedNavMq.addEventListener === 'function') {
this._stackedNavMq.addEventListener('change', this._onStackedNavMqChange);
} else if (typeof this._stackedNavMq.addListener === 'function') {
this._stackedNavMq.addListener(this._onStackedNavMqChange);
}
this.syncStackedNavLayout();
},
unbindStackedNavMedia() {
if (!this._stackedNavMq || !this._onStackedNavMqChange) return;
if (typeof this._stackedNavMq.removeEventListener === 'function') {
this._stackedNavMq.removeEventListener('change', this._onStackedNavMqChange);
} else if (typeof this._stackedNavMq.removeListener === 'function') {
this._stackedNavMq.removeListener(this._onStackedNavMqChange);
}
this._stackedNavMq = null;
this._onStackedNavMqChange = null;
},
syncStackedNavLayout() {
const next = readStackedNavLayout();
const prev = this.stackedNavLayout;
this.stackedNavLayout = next;
if (prev === next) return;
this.$nextTick(() => {
if (this.contentView !== 'list') return;
if (next) {
this.destroyScrollSpy();
} else {
this.initScrollSpy();
}
});
},
scrollListContentToTop() {
const scrollRoot = this.getScrollRoot();
const contentEl = this.$el && this.$el.querySelector('.gxnlpt-content');
if (scrollRoot && contentEl) {
const rootRect = scrollRoot.getBoundingClientRect();
const contentRect = contentEl.getBoundingClientRect();
const targetTop = scrollRoot.scrollTop + (contentRect.top - rootRect.top);
scrollRoot.scrollTo({ top: Math.max(0, targetTop), behavior: 'smooth' });
return;
}
if (scrollRoot) {
scrollRoot.scrollTo({ top: 0, behavior: 'smooth' });
return;
}
window.scrollTo({ top: 0, behavior: 'smooth' });
},
/**
* 解析后端标签支持 JSON 数组对象数组逗号分隔字符串
* '["全国","碳核查"]' | '[{"name":"全国"}]' | '全国,碳核查'
@ -698,11 +793,21 @@ export default {
if (this.contentView !== 'list') {
this.contentView = 'list';
this.$nextTick(() => {
this.initScrollSpy();
this.scrollToSection(sectionId, tabIndex);
this.handleCategoryNav(sectionId, tabIndex);
});
return;
}
this.handleCategoryNav(sectionId, tabIndex);
},
handleCategoryNav(sectionId, tabIndex) {
if (typeof tabIndex === 'number' && !Number.isNaN(tabIndex)) {
this.activeTabIndex = tabIndex;
}
if (this.isStackedNavMode) {
this.$nextTick(() => this.scrollListContentToTop());
return;
}
this.initScrollSpy();
this.scrollToSection(sectionId, tabIndex);
},
openSubmitView() {
@ -830,7 +935,7 @@ export default {
},
initScrollSpy() {
this.destroyScrollSpy();
if (this.contentView !== 'list') return;
if (this.isStackedNavMode || this.contentView !== 'list') return;
const scrollRoot = this.getScrollRoot();
if (!scrollRoot) return;
this.scrollRootEl = scrollRoot;
@ -892,6 +997,7 @@ export default {
</script>
<style lang="less" scoped>
@import '../../styles/breakpoints.less';
@import '../../styles/home-figma-variables.less';
/* Figma 150605:2210 共性能力 */
@ -1191,14 +1297,22 @@ export default {
flex-direction: column;
gap: 8px;
width: 100%;
min-width: 0;
overflow: hidden;
}
.gxnlpt-card-body .gxnlpt-card-tags {
flex-shrink: 0;
margin-top: 2px;
}
.gxnlpt-card-info {
display: flex;
flex-shrink: 0;
flex-direction: column;
gap: 8px;
gap: 4px;
width: 100%;
min-width: 0;
}
.gxnlpt-card-name-row {
@ -1463,44 +1577,123 @@ export default {
center / contain no-repeat;
}
@media screen and (max-width: 1279px) {
/* 窄屏:顶部分类子导航 + 下方单块内容(对齐图二 / 服务中心子项) */
.gxnlpt-shell--stacked {
padding-top: 0;
padding-left: 0;
padding-right: 0;
padding-bottom: 24px;
}
.gxnlpt-layout--stacked {
grid-template-columns: 1fr;
gap: 0;
}
.gxnlpt-sidebar--panel {
width: 100%;
min-height: 0;
padding: 12px 16px 16px;
background: @gxnlpt-page-bg;
border-radius: 0;
box-shadow: none;
}
.gxnlpt-sidebar--panel .gxnlpt-side-item:not(.is-active):hover {
background: fade(#fff, 72%);
}
.gxnlpt-layout--stacked .gxnlpt-sidebar-sticky {
position: sticky;
top: 0;
z-index: 30;
max-height: none;
background: @gxnlpt-page-bg;
}
/* JS 未就绪时仍保证 H5 布局与导航可点(与 STACKED_NAV_MEDIA 一致) */
@media screen and (max-width: @mq-desktop-sm-max) {
.gxnlpt-layout {
grid-template-columns: 1fr;
gap: 0;
}
.gxnlpt-sidebar {
width: 100%;
min-height: 0;
background: @gxnlpt-page-bg;
border-radius: 0;
box-shadow: none;
}
.gxnlpt-sidebar-sticky {
position: static;
top: auto;
max-height: none;
position: sticky;
top: 0;
z-index: 30;
background: @gxnlpt-page-bg;
}
.gxnlpt-side-nav-wrap {
max-height: 280px;
.gxnlpt-shell.page-content-wrap {
padding-top: 0;
padding-left: 0;
padding-right: 0;
}
.gxnlpt-side-nav {
flex-direction: column;
flex-wrap: nowrap;
}
.gxnlpt-side-item {
flex: none;
width: 100%;
min-width: 0;
}
.gxnlpt-sidebar-tail {
display: none;
}
}
.gxnlpt-side-nav {
flex-direction: row;
flex-wrap: wrap;
}
.gxnlpt-layout--stacked .gxnlpt-side-nav-wrap {
max-height: none;
overflow: visible;
}
.gxnlpt-side-item {
flex: 1 1 calc(50% - 5px);
min-width: 200px;
}
.gxnlpt-layout--stacked .gxnlpt-sidebar-tail {
display: none;
}
.gxnlpt-content {
min-height: 0;
}
.gxnlpt-layout--stacked .gxnlpt-side-nav {
flex-direction: column;
flex-wrap: nowrap;
gap: @gxnlpt-side-nav-gap;
}
.gxnlpt-layout--stacked .gxnlpt-side-item {
flex: none;
width: 100%;
min-width: 0;
}
.gxnlpt-layout--stacked .gxnlpt-side-actions {
flex-direction: row;
gap: 12px;
}
.gxnlpt-layout--stacked .gxnlpt-side-action {
flex: 1 1 0;
min-width: 0;
}
.gxnlpt-shell--stacked .gxnlpt-content {
min-height: 0;
margin-left: 12px;
margin-right: 12px;
margin-top: 12px;
}
@media screen and (max-width: 1279px) {
.gxnlpt-card-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
@ -1516,7 +1709,9 @@ export default {
}
@media screen and (max-width: 767px) {
.gxnlpt-content {
.gxnlpt-shell--stacked .gxnlpt-content {
margin-left: 12px;
margin-right: 12px;
padding: 16px;
}

View File

@ -89,7 +89,7 @@
<div class="section-title core-title">
<div class="home-block-title-content">
<h3 class="home-block-title-text">核心驱动</h3>
<span class="home-block-title-bar"></span>
<span class="home-section-title-bar home-block-title-bar"></span>
</div>
</div>
@ -128,7 +128,7 @@
<div class="capability-title-group">
<div class="capability-title-content">
<h3 class="capability-title-text">共性能力</h3>
<span class="capability-title-bar"></span>
<span class="home-section-title-bar capability-title-bar"></span>
</div>
<!-- <p class="capability-desc">五大核心能力全面支撑企业绿色转型</p> -->
</div>
@ -155,7 +155,7 @@
<!-- <i class="overseas2-title-icon"></i> -->
<div class="overseas2-title-content">
<h3 class="overseas2-title-text">企业出海</h3>
<span class="overseas2-title-bar"></span>
<span class="home-section-title-bar overseas2-title-bar"></span>
</div>
<!-- <p class="overseas2-desc">政策要求合规指引案例分享一站式信息与系统入口</p> -->
</div>
@ -193,20 +193,22 @@
<div class="news-title-group">
<div class="news-title-content">
<h3 class="news-title-text">行业动态</h3>
<span class="news-title-bar"></span>
<span class="home-section-title-bar news-title-bar"></span>
</div>
</div>
</div>
<div class="news-grid">
<div class="news-tabs-row">
<div class="news-tabs">
<div class="news-tab" :class="{ 'news-tab-active': activeTab === index }" v-for="(tab, index) in newsTabs"
:key="index" @click="activeTab = index">
{{ tab.name }}
<div class="news-tabs-main">
<div class="news-tabs">
<div class="news-tab" :class="{ 'news-tab-active': activeTab === index }" v-for="(tab, index) in newsTabs"
:key="index" @click="activeTab = index">
{{ tab.name }}
</div>
</div>
<button type="button" class="news-more" @click="handleNewsMore">查看更多&gt;&gt;</button>
</div>
<button type="button" class="news-more" @click="handleNewsMore">查看更多&gt;&gt;</button>
</div>
<!-- 骨架屏 -->
@ -330,6 +332,8 @@
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 { bindSectionWheelScroll } from '@/pages/index/utils/portal-scroll-mode';
export default {
data() {
return {
@ -340,6 +344,7 @@ export default {
isScrolling: false,
scrollThreshold: 1,
scrollRoot: null,
unbindSectionWheel: null,
sectionOffsets: [],
sectionIds: ['section-hero', 'section-core', 'section-capability', 'section-overseas', 'section-news', 'section-partner', 'section-bottom'],
coreSelectedIndex: 3,
@ -492,7 +497,7 @@ export default {
this.$nextTick(() => {
this.scrollRoot = document.querySelector('.content-wrap');
if (this.scrollRoot) {
this.scrollRoot.addEventListener('wheel', this.handleWheel, { passive: false });
this.unbindSectionWheel = bindSectionWheelScroll(this.scrollRoot, this.handleWheel);
this.refreshSectionOffsets();
}
this.ensureBannerVideosPlay();
@ -501,8 +506,9 @@ export default {
},
beforeDestroy() {
window.removeEventListener('resize', this.syncBannerHeight);
if (this.scrollRoot) {
this.scrollRoot.removeEventListener('wheel', this.handleWheel);
if (this.unbindSectionWheel) {
this.unbindSectionWheel();
this.unbindSectionWheel = null;
}
},
methods: {
@ -1000,7 +1006,7 @@ export default {
}
.portal-page .home-shelf--overseas {
align-items: center;
align-items: stretch;
gap: @home-export-title-to-list-gap;
min-height: auto;
padding-bottom: var(--home-news-section-pb, @home-section-padding-bottom);
@ -1371,16 +1377,11 @@ export default {
box-sizing: border-box;
}
.portal-page .core-section,
.portal-page .capability-section,
.portal-page .overseas2-section,
.portal-page .news-section,
.portal-page .partner-section {
--block-title-bar-top: var(--home-title-bar-top);
--block-title-bar-left: var(--home-title-bar-left);
--block-title-bar-width: var(--home-title-bar-width);
--block-title-bar-height: var(--home-title-bar-height);
}
/* 笔触相对标题字号定位各区块统一Figma 32px 标题left 13 / top 8 / 158×50 */
@home-title-deco-left-em: 0.40625em;
@home-title-deco-top-em: 0.25em;
@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,
@ -1408,11 +1409,19 @@ export default {
.portal-page .overseas2-section .overseas2-header,
.portal-page .news-section .news-header {
display: flex;
align-items: flex-start;
justify-content: flex-start;
margin-bottom: 0;
width: 100%;
}
.portal-page .capability-title-group,
.portal-page .overseas2-title-group,
.portal-page .news-title-group {
align-items: flex-start;
justify-content: flex-start;
}
.portal-page .partner-section .partner-title-area {
display: flex;
justify-content: center;
@ -1481,17 +1490,21 @@ export default {
.overseas2-title-content,
.news-title-content {
position: relative;
display: flex;
display: inline-flex;
flex-direction: column;
align-items: flex-start;
font-size: var(--home-title-size);
isolation: isolate;
}
.home-block-title-text,
.capability-title-text,
.overseas2-title-text,
.news-title-text {
position: relative;
z-index: 1;
font-family: @home-font-family;
font-size: var(--home-title-size);
font-size: inherit;
font-weight: var(--home-title-weight);
line-height: 1.4;
color: var(--home-title-color);
@ -1536,18 +1549,20 @@ export default {
position: relative;
}
/* 标题下笔触装饰(透明底 PNG与共性能力一致 */
/* 标题下笔触装饰(透明底 PNG各区块共用同一套定位 */
.home-section-title-bar,
.home-block-title-bar,
.capability-title-bar,
.overseas2-title-bar,
.news-title-bar {
display: block;
position: absolute;
top: var(--block-title-bar-top);
left: var(--block-title-bar-left);
width: var(--block-title-bar-width);
height: var(--block-title-bar-height);
z-index: -1;
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;
@ -1707,6 +1722,9 @@ export default {
}
.capability-header {
display: flex;
align-items: flex-start;
justify-content: flex-start;
margin: 0;
width: 100%;
}
@ -1714,6 +1732,7 @@ export default {
.capability-title-group {
display: flex;
align-items: flex-start;
justify-content: flex-start;
gap: 0;
width: 100%;
}
@ -1823,6 +1842,9 @@ export default {
}
.overseas2-header {
display: flex;
align-items: flex-start;
justify-content: flex-start;
margin: 0;
width: 100%;
}
@ -1830,6 +1852,7 @@ export default {
.overseas2-title-group {
display: flex;
align-items: flex-start;
justify-content: flex-start;
gap: 0;
width: 100%;
}
@ -2010,13 +2033,20 @@ export default {
.news-tabs-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: @home-space-16;
align-items: flex-start;
justify-content: flex-start;
width: 100%;
margin: 0 0 @home-news-tabs-to-list-gap;
}
.news-tabs-main {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 10px;
max-width: 100%;
}
.news-tabs {
display: flex;
justify-content: flex-start;
@ -2772,14 +2802,11 @@ export default {
padding-right: var(--home-section-px);
}
.section-title.core-title {
background-size: 28px 28px;
padding-left: 36px;
}
.section-title.core-title::after {
top: var(--block-title-bar-top);
left: var(--block-title-bar-left);
.home-block-title-content,
.capability-title-content,
.overseas2-title-content,
.news-title-content {
font-size: @home-font-size-28;
}
.section-title .title-bar {
@ -2867,7 +2894,7 @@ export default {
.capability-title-group {
flex-direction: column;
align-items: center;
align-items: flex-start;
gap: @home-search-tag-gap;
}
@ -2880,11 +2907,6 @@ export default {
font-size: @home-font-size-28;
}
.capability-title-bar {
margin-top: 0;
}
.capability-grid {
grid-template-columns: 1fr;
gap: @home-search-tag-gap;
@ -2971,53 +2993,68 @@ export default {
padding: 12px;
}
/* 底部 CTA移动端仍保持一屏高度 */
/* 底部 CTA移动端内容居中,背景不左偏裁切 */
.bottom-box {
min-height: 100vh;
min-height: 100dvh;
height: 100vh;
height: 100dvh;
min-height: 300px;
height: auto;
overflow: hidden;
}
.bottom-box-bg {
left: -10%;
top: -6%;
width: 120%;
height: 120%;
object-position: center bottom;
left: 0;
top: 0;
width: 100%;
height: 100%;
object-fit: cover;
object-position: center center;
}
.bottom-box-inner {
align-items: center;
justify-content: center;
min-height: inherit;
padding: 0;
min-height: 300px;
height: auto;
padding: 40px var(--home-section-px, 16px) 48px;
box-sizing: border-box;
}
.bottom-box-copy {
width: 100%;
max-width: none;
padding: 48px var(--home-section-px, 16px);
gap: 24px;
max-width: 100%;
padding: 0;
gap: 20px;
align-items: center;
}
.bottom-box-head {
align-items: center;
gap: 12px;
}
.bottom-box-content-title {
width: 100%;
font-size: @home-font-size-24;
line-height: 1.4;
text-align: center;
white-space: normal;
}
.bottom-box-desc {
width: 100%;
font-size: @home-font-size-14;
line-height: 1.6;
max-width: none;
text-align: center;
max-width: 320px;
}
.bottom-box-btn {
width: 100%;
max-width: 280px;
height: 48px;
font-size: @home-font-size-16;
line-height: 48px;
padding: 0 16px;
box-sizing: border-box;
&:hover {
transform: none;
@ -3080,7 +3117,7 @@ export default {
.overseas2-title-group {
flex-direction: column;
align-items: center;
align-items: flex-start;
gap: @home-search-tag-gap;
}
@ -3093,10 +3130,6 @@ export default {
font-size: @home-font-size-28;
}
.overseas2-title-bar {
margin-top: 0;
}
.overseas2-desc {
font-size: @home-font-size-16;
line-height: 24px;
@ -3186,21 +3219,20 @@ export default {
}
.news-title-text {
font-size: @home-font-size-28;
font-size: inherit;
}
.news-title-bar {
width: 100px;
height: 32px;
margin-top: -22px;
.news-tabs-main {
gap: 8px;
width: 100%;
}
.news-tabs {
gap: @home-search-tag-gap;
flex-wrap: wrap;
justify-content: flex-start;
margin-top: 0;
margin-bottom: 24px;
margin: 0;
width: 100%;
}
.news-tab {
@ -3208,6 +3240,76 @@ export default {
font-size: @home-font-size-14;
}
.news-more {
padding: 0;
margin-left: 0;
line-height: 22px;
}
.portal-page .home-shelf--news .news-list .news-item,
.news-item {
flex-direction: column;
align-items: stretch;
height: auto;
min-height: 0;
max-height: none;
padding: 14px;
gap: 12px;
overflow: visible;
}
.portal-page .home-shelf--news .news-list .news-pic,
.news-pic {
flex: none;
width: 100%;
height: 140px;
max-height: none;
align-self: stretch;
}
.portal-page .home-shelf--news .news-list .news-content,
.news-content {
justify-content: flex-start;
gap: 10px;
min-width: 0;
width: 100%;
}
.news-item-title {
font-size: @home-font-size-16;
white-space: normal;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.news-meta {
flex-wrap: wrap;
align-items: center;
gap: 6px 10px;
min-height: 0;
overflow: visible;
width: 100%;
}
.news-date {
flex-shrink: 0;
}
.news-remark {
flex: 1 1 100%;
white-space: normal;
word-break: break-word;
overflow: visible;
text-overflow: unset;
line-height: 1.5;
}
.news-summary {
font-size: 13px;
-webkit-line-clamp: 2;
}
.news-list {
height: auto;
max-height: none;
@ -3215,42 +3317,11 @@ export default {
padding: 0;
}
.news-item {
flex-direction: column;
height: auto;
min-height: 0;
max-height: none;
padding: 12px;
gap: @home-search-tag-gap;
}
.news-pic {
width: 100%;
height: 140px;
}
.news-item-title {
font-size: @home-font-size-16;
}
.news-meta {
gap: 6px 10px;
}
.news-summary {
font-size: 13px;
-webkit-line-clamp: 2;
}
.news-list-footer {
justify-content: center;
margin-top: 16px;
}
.news-more {
padding: 0;
}
/* 合作伙伴移动端隐藏(动画在移动端影响性能) */
.partner-section {
display: none;

View File

@ -461,8 +461,10 @@ export default {
align-items: center;
justify-content: flex-end;
gap: 16px;
width: 100%;
padding-top: 16px;
padding-bottom: 16px;
box-sizing: border-box;
}
.hydt-pagination-total {
@ -477,7 +479,8 @@ export default {
flex-wrap: wrap;
align-items: center;
justify-content: flex-end;
gap: 16px;
gap: 12px 16px;
max-width: 100%;
}
.hydt-pagination ::v-deep .t-pagination__select {
@ -537,10 +540,147 @@ export default {
.hydt-pagination {
flex-direction: column;
align-items: stretch;
gap: 12px;
padding-top: 20px;
padding-bottom: 24px;
}
.hydt-pagination-total {
width: 100%;
font-size: 14px;
line-height: 22px;
text-align: center;
}
.hydt-pagination ::v-deep .t-pagination {
display: flex !important;
flex-wrap: wrap !important;
align-items: center;
justify-content: center !important;
width: 100% !important;
max-width: 100%;
white-space: normal !important;
row-gap: 12px;
column-gap: 8px;
}
.hydt-pagination ::v-deep .t-pagination__total {
display: none;
}
.hydt-pagination ::v-deep .t-pagination__btn-prev {
order: 1;
}
.hydt-pagination ::v-deep .t-pagination__pager {
order: 2;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 6px;
max-width: 100%;
}
.hydt-pagination ::v-deep .t-pagination__btn-next {
order: 3;
}
.hydt-pagination ::v-deep .t-pagination__select {
order: 4;
flex: 0 0 auto;
width: auto;
max-width: none;
margin: 0 0 0 8px !important;
display: flex;
justify-content: center;
}
.hydt-pagination ::v-deep .t-pagination__select .t-select__wrap {
width: auto;
max-width: none;
}
@hydt-mob-pagination-h: 32px;
.hydt-pagination ::v-deep .t-pagination__number {
min-width: @hydt-mob-pagination-h;
height: @hydt-mob-pagination-h;
line-height: @hydt-mob-pagination-h;
margin: 0;
box-sizing: border-box;
}
.hydt-pagination ::v-deep .t-pagination__btn {
min-width: @hydt-mob-pagination-h;
width: @hydt-mob-pagination-h;
height: @hydt-mob-pagination-h;
line-height: @hydt-mob-pagination-h;
}
.hydt-pagination ::v-deep .t-pagination__select {
height: @hydt-mob-pagination-h;
align-items: center;
}
.hydt-pagination ::v-deep .t-pagination__select .t-select__wrap,
.hydt-pagination ::v-deep .t-pagination__select .t-input__wrap,
.hydt-pagination ::v-deep .t-pagination__select .t-input {
height: @hydt-mob-pagination-h !important;
min-height: @hydt-mob-pagination-h !important;
box-sizing: border-box;
}
.hydt-pagination ::v-deep .t-pagination__select .t-input__inner {
height: @hydt-mob-pagination-h !important;
min-height: @hydt-mob-pagination-h !important;
line-height: @hydt-mob-pagination-h;
padding-top: 0;
padding-bottom: 0;
font-size: 13px;
box-sizing: border-box;
}
.hydt-pagination ::v-deep .t-pagination__jump {
display: none !important;
}
.hydt-pagination ::v-deep .t-input.t-is-readonly {
width: auto;
min-width: 96px;
max-width: none;
}
}
@media screen and (max-width: 480px) {
.hydt-pagination {
padding-bottom: 32px;
}
@hydt-mob-pagination-h-sm: 28px;
.hydt-pagination ::v-deep .t-pagination__number {
min-width: @hydt-mob-pagination-h-sm;
height: @hydt-mob-pagination-h-sm;
line-height: @hydt-mob-pagination-h-sm;
font-size: 13px;
}
.hydt-pagination ::v-deep .t-pagination__btn {
min-width: @hydt-mob-pagination-h-sm;
width: @hydt-mob-pagination-h-sm;
height: @hydt-mob-pagination-h-sm;
line-height: @hydt-mob-pagination-h-sm;
}
.hydt-pagination ::v-deep .t-pagination__select,
.hydt-pagination ::v-deep .t-pagination__select .t-select__wrap,
.hydt-pagination ::v-deep .t-pagination__select .t-input__wrap,
.hydt-pagination ::v-deep .t-pagination__select .t-input,
.hydt-pagination ::v-deep .t-pagination__select .t-input__inner {
height: @hydt-mob-pagination-h-sm !important;
min-height: @hydt-mob-pagination-h-sm !important;
line-height: @hydt-mob-pagination-h-sm;
}
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<div>
<Nav @gotoIfreamPage="gotoIfreamPage" @gotoPage="gotoPage" />
<div ref="contentWrap" class="content-wrap" :style="isHomePage ? { height: documentClientHeight + 'px', marginTop: '0' } : { height: 'calc(' + documentClientHeight + 'px - var(--page-offset-top))', marginTop: 'var(--page-offset-top)' }">
<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>
@ -14,12 +14,15 @@
<script>
import Nav from "@/pages/index/components/nav/index2.vue";
import { hasLogin } from "@/pages/index/api/login";
import { isMobileViewport } from "@/pages/index/utils/breakpoint";
export default {
name: "Main",
data() {
return {
iframeUrl: '',
documentClientHeight: 100
documentClientHeight: 100,
isMobileViewport: false,
};
},
components: {
@ -35,6 +38,32 @@ export default {
isHomePage() {
return (this.$route.path === '/home' || this.$route.path === '/') && !this.iframeUrl;
},
contentWrapClass() {
return {
'content-wrap--mobile': this.isMobileViewport,
'content-wrap--home': this.isHomePage,
};
},
contentWrapStyle() {
// height:auto 使
if (this.isMobileViewport) {
if (this.isHomePage) {
return { marginTop: '0', height: '100dvh', maxHeight: '100dvh' };
}
return {
marginTop: 'var(--page-offset-top)',
height: 'calc(100dvh - var(--page-offset-top))',
maxHeight: 'calc(100dvh - var(--page-offset-top))',
};
}
if (this.isHomePage) {
return { height: `${this.documentClientHeight}px`, marginTop: '0' };
}
return {
height: `calc(${this.documentClientHeight}px - var(--page-offset-top))`,
marginTop: 'var(--page-offset-top)',
};
},
// documentClientHeight: {
// get() {
// return this.$store.state.common.documentClientHeight;
@ -56,8 +85,16 @@ export default {
},
mounted() {
this.resetDocumentClientHeight();
this.syncMobileViewport();
window.addEventListener('resize', this.syncMobileViewport);
},
beforeDestroy() {
window.removeEventListener('resize', this.syncMobileViewport);
},
methods: {
syncMobileViewport() {
this.isMobileViewport = isMobileViewport();
},
gotoPage(name) {
this.iframeUrl = "";
this.$nextTick(() => {
@ -87,10 +124,12 @@ export default {
//
resetDocumentClientHeight() {
this.documentClientHeight = document.documentElement["clientHeight"];
window.onresize = () => {
this.documentClientHeight = document.documentElement["clientHeight"];
const apply = () => {
this.documentClientHeight = document.documentElement.clientHeight;
this.syncMobileViewport();
};
apply();
window.addEventListener('resize', apply);
},
//
// getUserInfo() {
@ -134,9 +173,18 @@ export default {
<style scoped>
.content-wrap {
overflow-y: auto;
overflow-x: hidden;
scrollbar-width: none;
-ms-overflow-style: none;
box-sizing: border-box;
}
.content-wrap--mobile {
position: relative;
-webkit-overflow-scrolling: touch;
overscroll-behavior-y: auto;
}
.content-wrap::-webkit-scrollbar {
display: none;
}

View File

@ -1406,6 +1406,18 @@ body {
}
@media (max-width: 1024px) {
#section0 .text-section,
#section1 .text-section.qych-policy-frame,
#section2 .text-section {
height: auto;
min-height: 0;
overflow: visible;
}
#anchor-container .banner.qych-snap-section .text-section {
overflow: visible;
}
#anchor-container .banner.qych-snap-section .text-section-head-row {
grid-template-columns: 1fr;
row-gap: 4px;
@ -1414,17 +1426,30 @@ body {
#anchor-container .banner.qych-snap-section .text-section-content {
flex-direction: column;
align-items: stretch;
flex: none;
min-height: 0;
}
#anchor-container .banner.qych-snap-section .content-item1 {
flex: none;
width: 100%;
height: auto;
min-height: 200px;
max-height: 360px;
}
#anchor-container .banner.qych-snap-section .content-item2 {
flex: 1 1 auto;
display: flex;
flex: none;
width: 100%;
min-width: 0;
}
#anchor-container .banner.qych-snap-section .service-section-dcfa {
width: 100%;
padding-left: 0;
border-left: none;
background: transparent;
}
#anchor-container .banner.qych-snap-section .card-item1,