Compare commits

...

8 Commits

Author SHA1 Message Date
4f2a8c4aac feat: 服务中心前端界面 2026-04-03 20:28:59 +08:00
76f2b947f8 fix: 修复服务中心引导页缺失图片,改用emoji图标 2026-04-03 16:41:37 +08:00
4d13ed6f9f feat: 完善服务中心页面路由配置 2026-04-03 16:36:14 +08:00
ca7b1a0013 feat: 创建碳金融市场页面
- 创建 jrsc.vue 页面,包含左侧筛选栏和右侧金融产品卡片列表
- 实现服务类型筛选(全部、绿色信贷、绿色保险)
- 实现服务企业筛选(全部、9家银行)
- 实现关键词搜索功能
- 实现6个金融产品卡片的Mock数据展示
- 添加 /fwsc/jrsc 路由配置

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 16:33:58 +08:00
b286a17ed4 feat: 创建数据列表页面(sjlbc)
- 添加数据列表页面,包含顶部导航、左侧筛选栏、右侧数据表格
- 实现价格区间和有效期筛选功能
- 实现表格排序功能(按数据类型、发布时间、数据条数、浏览量、下载量)
- 添加数据类型标签(公共数据-绿色、社会性数据-蓝色)
- 添加奇偶行颜色区分和分页组件

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 16:31:10 +08:00
25f6982fd2 feat: 创建碳数据市场页面
- 实现左侧筛选栏(数据类型:全部、公共数据、因子库、社会性数据)
- 实现右侧数据库卡片列表(2列Grid布局)
- 数据类型标签颜色区分:公共数据/公益数据(绿色)、社会性数据(蓝色)、商业数据(灰色)
- 价格标签:免费(绿色)、付费(橙色)
- 使用NewNav和Footer组件

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 16:31:06 +08:00
0de9cb3a3f feat: 创建服务中心引导页
创建 src/pages/index/views/fwsc/index.vue,实现:
- 使用 NewNav 组件作为顶部导航
- 当前位置导航:首页 / 服务中心
- Banner 区:大标题 + 副标题
- 四大服务入口卡片(2x2 Grid 布局)
- 使用 Footer 组件
- 实现路由跳转到各子市场

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 16:29:25 +08:00
af2a4e822d feat: 创建 NewNav 导航组件
从 home2/index.vue 抽取顶部导航栏为独立组件,支持:
- Logo 区域和菜单栏(首页、碳证中心、服务中心等)
- 服务中心下拉菜单(碳服务市场、碳需求市场、碳金融市场、碳数据市场)
- 右侧操作区(工作台、登录/注册、用户头像下拉)
- 登录状态判断和用户信息获取逻辑
- hover 显示下拉菜单

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 16:25:14 +08:00
18 changed files with 3651 additions and 150 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
prd/

View File

@ -0,0 +1,310 @@
# 碳信网服务中心页面开发实现计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 将6个PRD原型页面还原为Vue组件并抽取新版首页导航为公共组件。
**Architecture:**
- 新导航组件 `new-nav/index.vue``home2/index.vue` 抽取,复用原有 `nav/index.vue` 的登录状态和用户信息逻辑
- 6个页面组件放在 `views/fwsc/` 目录下
- 路由使用父子路由结构,`/fwsc` 为引导页下设4个子页面路由
**Tech Stack:** Vue2 + TDesign + less
---
## 文件变更总览
| 操作 | 文件路径 |
|------|---------|
| 创建 | `src/pages/index/components/new-nav/index.vue` |
| 创建 | `src/pages/index/views/fwsc/index.vue` |
| 创建 | `src/pages/index/views/fwsc/fwsc.vue` |
| 创建 | `src/pages/index/views/fwsc/xqsc.vue` |
| 创建 | `src/pages/index/views/fwsc/jrsc.vue` |
| 创建 | `src/pages/index/views/fwsc/sjsc.vue` |
| 创建 | `src/pages/index/views/fwsc/sjlbc.vue` |
| 修改 | `src/pages/index/router/routes.js` |
---
## Task 1: 创建 NewNav 导航组件
**文件:**
- 创建: `src/pages/index/components/new-nav/index.vue`
- [ ] **Step 1: 创建 new-nav 目录和组件文件**
`home2/index.vue``.nav-box` 抽取导航栏代码,新建 `src/pages/index/components/new-nav/index.vue`
关键功能点:
- Logo + 菜单栏(首页、碳证中心、服务中心[下拉]、共性能力、企业出海、行业专题)
- 服务中心下拉:碳服务市场、碳需求市场、碳金融市场、碳数据市场
- 右侧:工作台、登录/注册、用户头像下拉菜单
- 登录状态判断复用原有 nav 的 `sessionStorage.getItem('sfdl')` 逻辑
- 用户信息获取复用 `sessionStorage.getItem('yhxx')` 逻辑
- 工作台跳转 `/view/mhzc/yhzx`
- 登录跳转 `/view/mhzc/login`
- 用户下拉:用户中心、退出登录
下拉菜单使用 `position: absolute` + `z-index` 实现hover 显示。
---
## Task 2: 创建服务中心引导页
**文件:**
- 创建: `src/pages/index/views/fwsc/index.vue`
- [ ] **Step 1: 创建 views/fwsc 目录和 index.vue**
根据 `prd/介绍.html` 实现引导页:
- 顶部NewNav 导航栏
- Banner区大标题"可信碳服务中心",副标题"链接全球碳资产,赋能绿色价值链..."
- 四大服务入口卡片2x2 Grid
- 碳服务市场 → `/fwsc/fwsc`
- 碳需求市场 → `/fwsc/xqsc`
- 碳金融市场 → `/fwsc/jrsc`
- 碳数据市场 → `/fwsc/sjsc`
- 交易流程指引(注册认证 → 发布信息 → 在线撮合)
- 底部Footer
卡片样式白色背景、圆角、hover放大效果`transform: scale(1.02)`
配色:绿色主题 #009a29
---
## Task 3: 创建碳服务市场页面
**文件:**
- 创建: `src/pages/index/views/fwsc/fwsc.vue`
- [ ] **Step 1: 根据 prd/供需大厅.html 创建碳服务市场页面**
布局:
- NewNav + 当前位置"首页 / 服务中心"
- 左侧筛选栏220px宽sticky
- 右侧服务卡片列表2列Grid
左侧筛选栏:
- 服务类型全部、碳核查服务、碳足迹核算、碳减排技术服务、碳资产管理服务、ESG报告编制、碳交易咨询
- 服务企业(全部、欧冶云商、上海企源科技、上海零数科技、上海链坤数字科技)
- 关键词搜索输入框 + 搜索按钮
右侧卡片字段(根据原型):
- 标题:"本司提供碳相关服务寻找有需求的企业客户"
- 企业:"上海链坤数字科技有限公司 · 辽宁省"
- 标签ESG报告编制、碳减排技术服务
- 价格:"¥ 10,000.00 /次"(橙色强调色 #D25F00
- 描述:"我们为参与碳市场的企业提供全方位的交易策略与风险管理咨询..."
- 按钮:联系服务商(主按钮)、收藏(次按钮)
卡片底部有分隔线。使用 `t-button` 组件。
---
## Task 4: 创建碳需求市场页面
**文件:**
- 创建: `src/pages/index/views/fwsc/xqsc.vue`
- [ ] **Step 1: 根据 prd/需求.html 创建碳需求市场页面**
布局与碳服务市场基本一致,筛选栏相同。
右侧卡片字段:
- 标题:"碳核查服务需求" 或 "【碳服务需求!急急急!】"
- 企业:"上海链坤数字科技有限公司"
- 标签ESG报告编制、碳减排技术服务
- 预算:"¥ 50-100 万元"(橙色 #D25F00
- 描述
- 有效期至2026-04-24
- 按钮:联系服务
注意:部分卡片标题带有"急"字标记,用不同颜色或样式突出。
---
## Task 5: 创建碳金融市场页面
**文件:**
- 创建: `src/pages/index/views/fwsc/jrsc.vue`
- [ ] **Step 1: 根据 prd/金融.html 创建碳金融市场页面**
左侧筛选栏:
- 服务类型(全部、绿色信贷、绿色保险)
- 服务企业(全部、中国银行、工商银行、农业银行、建设银行、招商银行、中信银行、北京银行、兴业银行、邮政储蓄银行)
右侧金融产品卡片2列Grid
- 机构名称 + Logo
- 产品名称(如"云南昭通信贷业务"
- 额度:"¥ 50,000.00"
- 期限:"1-3年"
- 利率:"3.6%~4.2%"(绿色 #00B42A
- 产品标签(如"绿色项目贷款"
- 按钮:立即申请(主)、查看详情(次)
---
## Task 6: 创建碳数据市场页面
**文件:**
- 创建: `src/pages/index/views/fwsc/sjsc.vue`
- [ ] **Step 1: 根据 prd/数据.html 创建碳数据市场页面**
左侧筛选栏:
- 数据类型(全部、公共数据、因子库、社会性数据)
右侧数据库卡片2列Grid
- 数据库名称:"宝山绿色低碳数据创新实验室"、"HiQLCD数据库"、"天工数据库"、"ecoinvent数据库"
- 描述
- 标签:公共数据/社会性数据/商业数据、免费/付费
- 按钮:查看数据库
---
## Task 7: 创建数据列表页面
**文件:**
- 创建: `src/pages/index/views/fwsc/sjlbc.vue`
- [ ] **Step 1: 根据 prd/数据列表.html 创建数据列表页面**
左侧筛选栏:
- 价格区间(最低 - 最高)
- 有效期(日期选择器)
右侧数据列表(表格形式):
- 列:数据类型、名称、发布时间/更新时间、数据条数、浏览量、下载量
- 数据示例:
- 全球多源高分辨温室气体及大气污染物排放清单 / 社会性数据 / 45,000条 / 475次浏览 / 18次下载
- 国家温室气体排放因子数据库 / 公共数据 / ...
- 碳排放数据库 / ...
列表顶部有排序图标(三角形)和浏览量/下载量指示。
---
## Task 8: 配置路由
**文件:**
- 修改: `src/pages/index/router/routes.js`
- [ ] **Step 1: 添加6个路由**
在 routes.js 顶部添加 lazy-load 导入函数:
```javascript
function fwscIndex() {
return import(/* webpackChunkName: "fwsc" */ '@/pages/index/views/fwsc/index.vue');
}
function fwscFwsc() {
return import(/* webpackChunkName: "fwsc" */ '@/pages/index/views/fwsc/fwsc.vue');
}
function fwscXqsc() {
return import(/* webpackChunkName: "fwsc" */ '@/pages/index/views/fwsc/xqsc.vue');
}
function fwscJrsc() {
return import(/* webpackChunkName: "fwsc" */ '@/pages/index/views/fwsc/jrsc.vue');
}
function fwscSjsc() {
return import(/* webpackChunkName: "fwsc" */ '@/pages/index/views/fwsc/sjsc.vue');
}
function fwscSjlbc() {
return import(/* webpackChunkName: "fwsc" */ '@/pages/index/views/fwsc/sjlbc.vue');
}
```
在 routes 数组末尾添加:
```javascript
{
name: 'fwsc',
path: '/fwsc',
component: fwscIndex,
meta: {
title: '服务中心',
isShowSideBar: false,
hasHome: true,
breadCrumbs: [{ title: '首页', to: '/home' }, { title: '服务中心', to: '/fwsc' }],
disableBack: true,
},
},
{
name: 'fwsc-fwsc',
path: '/fwsc/fwsc',
component: fwscFwsc,
meta: {
title: '碳服务市场',
isShowSideBar: false,
hasHome: true,
breadCrumbs: [{ title: '首页', to: '/home' }, { title: '服务中心', to: '/fwsc' }, { title: '碳服务市场', to: '/fwsc/fwsc' }],
disableBack: true,
},
},
{
name: 'fwsc-xqsc',
path: '/fwsc/xqsc',
component: fwscXqsc,
meta: {
title: '碳需求市场',
isShowSideBar: false,
hasHome: true,
breadCrumbs: [{ title: '首页', to: '/home' }, { title: '服务中心', to: '/fwsc' }, { title: '碳需求市场', to: '/fwsc/xqsc' }],
disableBack: true,
},
},
{
name: 'fwsc-jrsc',
path: '/fwsc/jrsc',
component: fwscJrsc,
meta: {
title: '碳金融市场',
isShowSideBar: false,
hasHome: true,
breadCrumbs: [{ title: '首页', to: '/home' }, { title: '服务中心', to: '/fwsc' }, { title: '碳金融市场', to: '/fwsc/jrsc' }],
disableBack: true,
},
},
{
name: 'fwsc-sjsc',
path: '/fwsc/sjsc',
component: fwscSjsc,
meta: {
title: '碳数据市场',
isShowSideBar: false,
hasHome: true,
breadCrumbs: [{ title: '首页', to: '/home' }, { title: '服务中心', to: '/fwsc' }, { title: '碳数据市场', to: '/fwsc/sjsc' }],
disableBack: true,
},
},
{
name: 'fwsc-sjlbc',
path: '/fwsc/sjlbc',
component: fwscSjlbc,
meta: {
title: '数据列表',
isShowSideBar: false,
hasHome: true,
breadCrumbs: [{ title: '首页', to: '/home' }, { title: '服务中心', to: '/fwsc' }, { title: '碳数据市场', to: '/fwsc/sjsc' }, { title: '数据列表', to: '/fwsc/sjlbc' }],
disableBack: true,
},
}
```
---
## 依赖关系
```
Task 1 (NewNav) ← 无依赖,可最先完成
Task 2 (fwsc引导页) ← 依赖 Task 1
Task 3 (fwsc) ← 依赖 Task 1
Task 4 (xqsc) ← 依赖 Task 1
Task 5 (jrsc) ← 依赖 Task 1
Task 6 (sjsc) ← 依赖 Task 1
Task 7 (sjlbc) ← 依赖 Task 1
Task 8 (路由) ← 依赖 Task 2-7
```
**建议执行顺序:** Task 1 → Task 2-7 并行 → Task 8

View File

@ -0,0 +1,243 @@
# 碳信网服务中心页面开发设计
## 1. 概述
### 1.1 项目背景
`prd/` 目录下的6个Axure原型HTML页面还原为Vue组件集成到 `txw-mhzc-web` 项目中。同时抽取 `home2/index.vue` 中的顶部导航栏为独立公共组件。
### 1.2 页面映射关系
| 页面 | 文件 | 路由 | 说明 |
|------|------|------|------|
| 服务中心 | `views/fwsc/index.vue` | `/fwsc` | 引导页含4个子入口 |
| 碳服务市场 | `views/fwsc/fwsc.vue` | `/fwsc/fwsc` | 对应供需大厅.html |
| 碳需求市场 | `views/fwsc/xqsc.vue` | `/fwsc/xqsc` | 对应需求.html |
| 碳金融市场 | `views/fwsc/jrsc.vue` | `/fwsc/jrsc` | 对应金融.html |
| 碳数据市场 | `views/fwsc/sjsc.vue` | `/fwsc/sjsc` | 对应数据.html |
| 数据列表 | `views/fwsc/sjlbc.vue` | `/fwsc/sjlbc` | 对应数据列表.html |
---
## 2. 新导航组件设计
### 2.1 组件路径
`src/pages/index/components/new-nav/index.vue`
### 2.2 抽取内容
`home2/index.vue``.nav-box` 抽取为独立组件。
### 2.3 功能逻辑(复用原有 nav 的逻辑)
**状态判断:**
- 登录状态:`sessionStorage.getItem('sfdl')`
- 用户信息:`sessionStorage.getItem('yhxx')`
**交互功能:**
- 工作台跳转 → `/view/mhzc/yhzx`
- 登录/注册按钮 → `/view/mhzc/login`
- 用户头像 hover 显示下拉菜单(用户中心、退出登录)
- 消息中心入口
### 2.4 "服务中心"菜单 — 二级下拉结构
```
首页 / 碳证中心 / 服务中心(二级菜单) / 共性能力 / 企业出海 / 行业专题
```
服务中心下拉:
- 碳服务市场 → `/fwsc/fwsc`
- 碳需求市场 → `/fwsc/xqsc`
- 碳金融市场 → `/fwsc/jrsc`
- 碳数据市场 → `/fwsc/sjsc`
---
## 3. 页面设计
### 3.1 服务中心(引导页)`views/fwsc/index.vue`
**布局:**
- 顶部NewNav 导航栏
- Banner区大标题 + 副标题
- 四大服务入口卡片(碳服务市场、碳需求市场、碳金融市场、碳数据市场)
- 底部Footer
**交互:**
- 点击卡片跳转对应二级页面
- 卡片hover有放大效果
### 3.2 碳服务市场 `views/fwsc/fwsc.vue`
**对应原型:** `prd/供需大厅.html`
**布局:**
- 左侧筛选栏(服务类型、服务企业)
- 右侧服务卡片列表2列Grid
- 顶部NewNav + 当前位置导航
- 底部Footer
**卡片内容:**
- 服务标题
- 发布企业 + 地区
- 服务类型标签
- 价格
- 描述
- 操作按钮(联系服务商、收藏)
**筛选功能:**
- 服务类型全部、碳核查服务、碳足迹核算、碳减排技术服务、碳资产管理服务、ESG报告编制、碳交易咨询
- 服务企业:全部、欧冶云商、上海企源科技、上海零数科技、上海链坤数字科技
- 关键词搜索
### 3.3 碳需求市场 `views/fwsc/xqsc.vue`
**对应原型:** `prd/需求.html`
**布局:** 与碳服务市场一致
**卡片内容:**
- 需求标题
- 发布企业
- 需求类型标签
- 预算范围
- 描述
- 操作按钮(联系服务)
- 有效期
### 3.4 碳金融市场 `views/fwsc/jrsc.vue`
**对应原型:** `prd/金融.html`
**布局:**
- 左侧筛选栏(服务类型、服务机构)
- 右侧金融产品卡片2列Grid
**卡片内容:**
- 机构名称Logo
- 产品名称
- 额度、期限、利率
- 操作按钮(立即申请、查看详情)
**筛选功能:**
- 服务类型:全部、绿色信贷、绿色保险
- 服务企业:全部、中国银行、工商银行、农业银行、建设银行、招商银行、中信银行、北京银行、兴业银行、邮政储蓄银行
### 3.5 碳数据市场 `views/fwsc/sjsc.vue`
**对应原型:** `prd/数据.html`
**布局:**
- 左侧筛选栏(数据类型)
- 右侧数据库卡片2列Grid
**卡片内容:**
- 数据库名称
- 描述
- 数据类型标签(公共数据、社会性数据、商业数据)
- 价格标签(免费/付费)
- 操作按钮(查看数据库)
**数据类型筛选:**
- 全部、公共数据、因子库、社会性数据
### 3.6 数据列表 `views/fwsc/sjlbc.vue`
**对应原型:** `prd/数据列表.html`
**布局:**
- 左侧筛选栏
- 右侧数据列表(表格形式)
**列表字段:**
- 数据名称
- 数据类型(公共数据、社会性数据)
- 发布时间/更新时间
- 数据条数
- 浏览量
- 下载量
**筛选项:**
- 价格区间
- 有效期
---
## 4. 路由设计
```javascript
// routes.js 新增
{
name: 'fwsc',
path: '/fwsc',
component: () => import('@/pages/index/views/fwsc/index.vue'),
meta: { title: '服务中心', isShowSideBar: false, hasHome: true }
},
{
name: 'fwsc-fwsc',
path: '/fwsc/fwsc',
component: () => import('@/pages/index/views/fwsc/fwsc.vue'),
meta: { title: '碳服务市场', isShowSideBar: false, hasHome: true }
},
{
name: 'fwsc-xqsc',
path: '/fwsc/xqsc',
component: () => import('@/pages/index/views/fwsc/xqsc.vue'),
meta: { title: '碳需求市场', isShowSideBar: false, hasHome: true }
},
{
name: 'fwsc-jrsc',
path: '/fwsc/jrsc',
component: () => import('@/pages/index/views/fwsc/jrsc.vue'),
meta: { title: '碳金融市场', isShowSideBar: false, hasHome: true }
},
{
name: 'fwsc-sjsc',
path: '/fwsc/sjsc',
component: () => import('@/pages/index/views/fwsc/sjsc.vue'),
meta: { title: '碳数据市场', isShowSideBar: false, hasHome: true }
},
{
name: 'fwsc-sjlbc',
path: '/fwsc/sjlbc',
component: () => import('@/pages/index/views/fwsc/sjlbc.vue'),
meta: { title: '数据列表', isShowSideBar: false, hasHome: true }
}
```
---
## 5. 目录结构
```
src/pages/index/
├── components/
│ └── new-nav/
│ └── index.vue # 新导航组件
└── views/
└── fwsc/
├── index.vue # 服务中心(引导页)
├── fwsc.vue # 碳服务市场
├── xqsc.vue # 碳需求市场
├── jrsc.vue # 碳金融市场
├── sjsc.vue # 碳数据市场
└── sjlbc.vue # 数据列表
```
---
## 6. 技术实现要点
### 6.1 公共组件
- NewNav 组件:复用原有 Nav 的登录状态判断、用户信息获取逻辑
- Footer 组件:直接使用现有 `@/pages/index/components/footer/index.vue`
### 6.2 样式规范
- 使用 TDesign 组件库(`t-button`、`t-input`、`t-select` 等)
- 布局使用 `t-row`、`t-col` 栅格系统
- 卡片hover效果使用 `transform: scale(1.02)` 过渡动画
- 颜色使用项目现有配色(绿色主题 #009a29
### 6.3 筛选栏
- 服务类型、服务企业等筛选项,使用 `t-select` 组件
- 左侧筛选栏宽度固定 220px使用 `position: sticky` 固定
### 6.4 卡片列表
- 使用 CSS Grid 两列布局:`grid-template-columns: repeat(2, 1fr)`
- 卡片间距24px

View File

@ -0,0 +1,35 @@
#!/bin/bash
# 复制 git 变更文件到 change 目录,保留原文件相对路径
set -e
TARGET_DIR="change"
# 创建目标目录
mkdir -p "$TARGET_DIR"
# 获取所有变更文件(包含未跟踪文件)
files=$(git status --porcelain | awk '{print $2}')
if [ -z "$files" ]; then
echo "没有变更文件"
exit 0
fi
count=0
for f in $files; do
# 跳过目录(如 docs/
if [ -d "$f" ]; then
mkdir -p "$TARGET_DIR/$f"
cp -r "$f" "$TARGET_DIR/$f"
echo "$f/"
elif [ -f "$f" ]; then
mkdir -p "$TARGET_DIR/$(dirname "$f")"
cp "$f" "$TARGET_DIR/$f"
echo "$f"
((count++))
fi
done
echo ""
echo "已完成,复制了 $count 个文件到 $TARGET_DIR 目录"

View File

@ -0,0 +1,85 @@
<template>
<div class="breadcrumb-box">
<span class="breadcrumb-text">当前位置</span>
<span class="breadcrumb-link" @click="goHome">首页</span>
<span class="breadcrumb-separator">/</span>
<span class="breadcrumb-link" @click="goService">服务中心</span>
<span v-if="secondPage" class="breadcrumb-separator">/</span>
<span v-if="secondPage" :class="secondLink ? 'breadcrumb-link' : 'breadcrumb-current'" @click="secondLink && goSecond()">
{{ secondPage }}
</span>
<span class="breadcrumb-separator">/</span>
<span class="breadcrumb-current">{{ currentPage }}</span>
</div>
</template>
<script>
export default {
name: 'BreadcrumbNav',
props: {
currentPage: {
type: String,
default: ''
},
secondPage: {
type: String,
default: ''
},
secondLink: {
type: String,
default: ''
}
},
methods: {
goHome() {
this.$router.push('/view/mhzc/home');
},
goService() {
this.$router.push('/fwsc');
},
goSecond() {
if (this.secondLink) {
this.$router.push(this.secondLink);
}
}
}
};
</script>
<style lang="less" scoped>
.breadcrumb-box {
display: flex;
align-items: center;
height: 48px;
padding: 0 20px;
background: #fff;
border-bottom: 1px solid #eee;
}
.breadcrumb-text {
font-size: 14px;
color: #666;
}
.breadcrumb-link {
font-size: 14px;
color: #009a29;
cursor: pointer;
transition: color 0.3s;
&:hover {
color: #007a1f;
}
}
.breadcrumb-separator {
margin: 0 8px;
font-size: 14px;
color: #999;
}
.breadcrumb-current {
font-size: 14px;
color: #333;
}
</style>

View File

@ -12,7 +12,7 @@ export default {
props: {
// logopx40
size: {
type: Number,
type: [Number, String],
default: 35,
},
},

View File

@ -0,0 +1,321 @@
<template>
<div>
<div class="nav-box-placeholder"></div>
<div class="nav-box">
<!-- Logo 区域 -->
<div class="logo-box">
<img src="@/pages/index/assets/logo-name.png" @click="goHome" style="cursor: pointer;">
</div>
<!-- 菜单栏 -->
<div class="menu-box">
<!-- 首页 -->
<div class="menu-title meun-title-active" @click="goPage('/view/mhzc/home')">
<img src="@/pages/index/assets/nav-home.png" width="24px" height="24px">
<span> &nbsp;&nbsp;首页</span>
</div>
<!-- 碳证中心 -->
<div class="menu-title" @click="goPage('/view/mhzc/yhzx')">碳证中心</div>
<!-- 服务中心 - 带下拉 -->
<div class="menu-title service-center" @mouseenter="showServiceDropdown = true" @mouseleave="showServiceDropdown = false">
<span @click.stop="goPage('/fwsc')">服务中心</span>
<!-- 下拉菜单 -->
<div class="dropdown-menu service-dropdown" v-show="showServiceDropdown">
<div class="dropdown-item" @click.stop="goPage('/fwsc/fwsc')">碳服务市场</div>
<div class="dropdown-item" @click.stop="goPage('/fwsc/xqsc')">碳需求市场</div>
<div class="dropdown-item" @click.stop="goPage('/fwsc/jrsc')">碳金融市场</div>
<div class="dropdown-item" @click.stop="goPage('/fwsc/sjsc')">碳数据市场</div>
</div>
</div>
<!-- 共性能力 -->
<div class="menu-title" @click="goPage('/view/gxzx/gxnlpt')">共性能力</div>
<!-- 企业出海 -->
<div class="menu-title" @click="goPage('/view/mhzc/qych')">企业出海</div>
<!-- 行业专题 -->
<div class="menu-title" @click="goPage('/view/mhzc/hyzt')">行业专题</div>
</div>
<!-- 右侧操作区 -->
<div class="option-box">
<!-- 工作台 -->
<div class="gzt" @click="goPage('/view/mhzc/yhzx')">
<img src="@/pages/index/assets/home-gzt-icon.png" />
<span> 工作台</span>
</div>
<!-- 已登录状态 -->
<template v-if="isdlwc">
<!-- 用户头像下拉 -->
<div class="user-avatar-box" @mouseenter="showUserDropdown = true" @mouseleave="showUserDropdown = false">
<img class="user-avatar" :src="userAvatar" alt="用户头像">
<div class="dropdown-menu user-dropdown" v-show="showUserDropdown">
<div class="dropdown-item" @click.stop="goUserCenter">用户中心</div>
<div class="dropdown-item" @click.stop="handleLogout">退出登录</div>
</div>
</div>
</template>
<!-- 未登录状态 -->
<template v-else>
<div style="margin-left:20px; cursor: pointer;">激活</div>
<div>|</div>
<div style="cursor: pointer;" @click="goLogin">登录</div>
</template>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'NewNav',
data() {
return {
isdlwc: false,
showServiceDropdown: false,
showUserDropdown: false,
userAvatar: 'data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAA8AAD/4QNxaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjMtYzAxMSA2Ni4xNDU2NjEsIDIwMTIvMDIvMDYtMTQ6NTY6MjcgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6NkYxNDI1RjU0MjIwNjgxMTgwODM4RjQyOEIzQ0M4MUUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDY1QzI5QzczQUVDMTFFNEIzM0U4Q0I5MkNEOTVGMkMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDY1QzI5QzYzQUVDMTFFNEIzM0U4Q0I5MkNEOTVGMkMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkJDRTc1MDAyMzEyMDY4MTE4MDgzOUE3MjIxRTIwQTNGIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjZGMTQyNUY1NDIyMDY4MTE4MDgzOEY0MjhCM0NDODFFIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwv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'
}
},
mounted() {
this.checkLoginStatus()
},
methods: {
//
checkLoginStatus() {
const sfdl = window.sessionStorage.getItem('sfdl')
if (sfdl) {
this.isdlwc = true
} else {
this.isdlwc = false
}
},
//
goPage(path) {
const sfdl = window.sessionStorage.getItem('sfdl')
// 访
if (!sfdl && path !== '/view/mhzc/home' && path !== '/view/mhzc/login') {
window.location.href = '/view/mhzc/login'
return
}
window.location.href = path
},
//
goHome() {
window.location.href = '/view/mhzc/home'
},
//
goLogin() {
window.location.href = '/view/mhzc/login'
},
//
goUserCenter() {
window.location.href = '/view/mhzc/yhzx'
},
// 退
handleLogout() {
sessionStorage.removeItem('sfdl')
sessionStorage.removeItem('yhxx')
window.location.href = '/view/mhzc/login'
}
}
}
</script>
<style scoped lang="less">
.nav-box-placeholder {
width: 100%;
height: 64px;
}
.nav-box {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
display: flex;
width: 100%;
height: 64px;
max-width: 100%;
padding: 0 20px;
margin: 0 auto;
overflow: visible;
color: #fff;
background: #009a29;
box-sizing: border-box;
justify-content: space-between;
align-items: center;
}
.logo-box {
flex: 0 0 auto;
}
.option-box {
display: flex;
flex: 0 0 auto;
font-family: PingFang SC;
font-size: 16px;
font-style: regular;
font-weight: 400;
letter-spacing: 0%;
text-align: center;
justify-content: center;
align-items: center;
gap: 10px;
leading-trim: none;
}
.option-box .gzt {
display: flex;
padding: 10px;
text-align: center;
cursor: pointer;
background: rgba(255, 255, 255, 0.3);
border-radius: 6px;
justify-content: space-around;
align-items: center;
gap: 10px;
}
.menu-box {
display: flex;
overflow: hidden;
font-size: 16px;
text-align: center;
flex: 1;
justify-content: center;
gap: 10px;
}
.menu-title {
position: relative;
display: flex;
height: 64px;
min-width: 80px;
padding: 0 8px;
overflow: visible;
line-height: 24px;
text-align: center;
cursor: pointer;
flex: 0 0 auto;
justify-content: center;
align-items: center;
}
.meun-title-active {
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.15) 100%);
border-bottom: 2px solid #fff;
}
//
.service-center {
.dropdown-arrow {
margin-left: 4px;
font-size: 10px;
}
}
//
.dropdown-menu {
position: absolute;
top: 64px;
left: 50%;
z-index: 1000;
min-width: 140px;
overflow: hidden;
background: #fff;
border-radius: 4px;
transform: translateX(-50%);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.dropdown-item {
width: 100%;
height: 40px;
font-size: 14px;
line-height: 40px;
color: #333;
text-align: center;
cursor: pointer;
transition: background 0.3s;
}
.dropdown-item:hover {
color: #009a29;
background: #e8f5e9;
}
//
.user-avatar-box {
position: relative;
margin-left: 20px;
.user-avatar {
width: 36px;
height: 36px;
cursor: pointer;
border-radius: 50%;
}
.user-dropdown {
right: 0;
left: auto;
min-width: 130px;
transform: none;
}
}
//
@media screen and (max-width: 1200px) {
.nav-box {
padding: 0 10px;
}
.menu-box {
gap: 5px;
}
.menu-title {
min-width: 70px;
padding: 0 5px;
font-size: 14px;
}
}
@media screen and (max-width: 992px) {
.menu-title {
min-width: 60px;
font-size: 13px;
}
.option-box .gzt {
padding: 8px;
font-size: 14px;
}
}
@media screen and (max-width: 768px) {
.nav-box {
justify-content: space-between;
padding: 0 10px;
}
.menu-box {
display: none;
}
.option-box .gzt span {
display: none;
}
}
</style>

View File

@ -18,6 +18,9 @@ const router = new VueRouter({
mode: 'history',
base: `${window.STATIC_ENV_CONFIG.ROUTER_PREFIX}/`,
routes: [...routes],
scrollBehavior(_to, _from, _savedPosition) {
return { x: 0, y: 0 };
},
});
router.beforeEach((to, from, next) => {

View File

@ -36,6 +36,36 @@ function gxnlpt() {
function newsCenter() {
return import(/* webpackChunkName: "sbfdemo" */ '@/pages/index/views/ggwhglHtgl/index.vue');
}
//碳服务市场
function fwsc() {
return import(/* webpackChunkName: "sbfdemo" */ '@/pages/index/views/fwsc/fwsc.vue');
}
//碳金融市场
function jrsc() {
return import(/* webpackChunkName: "sbfdemo" */ '@/pages/index/views/fwsc/jrsc.vue');
}
//碳需求市场
function xqsc() {
return import(/* webpackChunkName: "fwsc" */ '@/pages/index/views/fwsc/xqsc.vue');
}
//碳数据市场
function sjsc() {
return import(/* webpackChunkName: "fwsc" */ '@/pages/index/views/fwsc/sjsc.vue');
}
//数据列表
function sjlbc() {
return import(/* webpackChunkName: "fwsc" */ '@/pages/index/views/fwsc/sjlbc.vue');
}
//服务中心引导页
function fwscIndex() {
return import(/* webpackChunkName: "fwsc" */ '@/pages/index/views/fwsc/index.vue');
}
export default [
{
name: 'login',
@ -136,4 +166,76 @@ export default [
path: '/hyzt',
component: hyzt,
},
{
name: 'fwsc-fwsc',
path: '/fwsc/fwsc',
component: fwsc,
meta: {
title: '碳服务市场',
isShowSideBar: false,
hasHome: true,
breadCrumbs: [{ title: '首页', to: '/home' }, { title: '服务中心', to: '' }, { title: '碳服务市场', to: '/fwsc/fwsc' }],
disableBack: true,
},
},
{
name: 'jrsc',
path: '/fwsc/jrsc',
component: jrsc,
meta: {
title: '碳金融市场',
isShowSideBar: false,
hasHome: true,
breadCrumbs: [{ title: '首页', to: '/home' }, { title: '服务中心', to: '' }, { title: '碳金融市场', to: '/fwsc/jrsc' }],
disableBack: true,
},
},
{
name: 'xqsc',
path: '/fwsc/xqsc',
component: xqsc,
meta: {
title: '碳需求市场',
isShowSideBar: false,
hasHome: true,
breadCrumbs: [{ title: '首页', to: '/home' }, { title: '服务中心', to: '' }, { title: '碳需求市场', to: '/fwsc/xqsc' }],
disableBack: true,
},
},
{
name: 'fwsc-sjsc',
path: '/fwsc/sjsc',
component: sjsc,
meta: {
title: '碳数据市场',
isShowSideBar: false,
hasHome: true,
breadCrumbs: [{ title: '首页', to: '/home' }, { title: '服务中心', to: '' }, { title: '碳数据市场', to: '/fwsc/sjsc' }],
disableBack: true,
},
},
{
name: 'fwsc-sjlbc',
path: '/fwsc/sjlbc',
component: sjlbc,
meta: {
title: '数据列表',
isShowSideBar: false,
hasHome: true,
breadCrumbs: [{ title: '首页', to: '/home' }, { title: '服务中心', to: '' }, { title: '碳数据市场', to: '/fwsc/sjsc' }, { title: '数据列表', to: '/fwsc/sjlbc' }],
disableBack: true,
},
},
{
name: 'fwsc',
path: '/fwsc',
component: fwscIndex,
meta: {
title: '服务中心',
isShowSideBar: false,
hasHome: true,
breadCrumbs: [{ title: '首页', to: '/home' }, { title: '服务中心', to: '/fwsc' }],
disableBack: true,
},
},
];

View File

@ -0,0 +1,289 @@
<template>
<div class="fwsc-container">
<NewNav />
<!-- 面包屑导航 -->
<BreadcrumbNav currentPage="碳服务市场" />
<main class="fwsc-main">
<div class="内容区域">
<!-- 左侧筛选栏 -->
<aside class="筛选栏">
<div class="筛选栏内容">
<!-- 服务类型 -->
<div class="筛选项">
<div class="筛选标签">服务类型</div>
<t-select v-model="筛选.服务类型" :options="服务类型选项" placeholder="请选择服务类型" clearable />
</div>
<!-- 服务企业 -->
<div class="筛选项">
<div class="筛选标签">服务企业</div>
<t-select v-model="筛选.服务企业" :options="服务企业选项" placeholder="请选择服务企业" clearable />
</div>
<!-- 关键词搜索 -->
<div class="筛选项">
<div class="筛选标签">关键词</div>
<t-input v-model="筛选.关键词" placeholder="请输入关键词" />
</div>
<t-button theme="primary" class="搜索按钮" @click="搜索">搜索</t-button>
</div>
</aside>
<!-- 右侧服务卡片列表 -->
<div class="卡片列表">
<div
v-for="(card, index) in 卡片数据"
:key="index"
class="服务卡片"
>
<!-- 卡片内容 -->
<div class="卡片头部">
<h3 class="卡片标题">{{ card.标题 }}</h3>
<p class="卡片企业">{{ card.企业 }}</p>
</div>
<div class="卡片标签">
<span v-for="(tag, tagIndex) in card.标签" :key="tagIndex" class="标签">
{{ tag }}
</span>
</div>
<div class="卡片价格" :style="{ color: '#D25F00' }">
{{ card.价格 }}
</div>
<p class="卡片描述">{{ card.描述 }}</p>
<div class="卡片操作">
<t-button theme="primary" class="操作按钮">联系服务商</t-button>
<t-button variant="outline" class="操作按钮">收藏</t-button>
</div>
<!-- 分隔线 -->
<div v-if="index < 卡片数据.length - 1" class="卡片分隔线"></div>
</div>
</div>
</div>
</main>
<Footer />
</div>
</template>
<script>
import NewNav from '@/pages/index/components/new-nav/index.vue';
import Footer from '@/pages/index/components/footer/index.vue';
import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue';
export default {
name: 'FwscPage',
components: {
NewNav,
Footer,
BreadcrumbNav,
},
data() {
return {
筛选: {
服务类型: '',
服务企业: '',
关键词: '',
},
服务类型选项: [
{ label: '全部', value: '' },
{ label: '碳核查服务', value: '碳核查服务' },
{ label: '碳足迹核算', value: '碳足迹核算' },
{ label: '碳减排技术服务', value: '碳减排技术服务' },
{ label: '碳资产管理服务', value: '碳资产管理服务' },
{ label: 'ESG报告编制', value: 'ESG报告编制' },
{ label: '碳交易咨询', value: '碳交易咨询' },
],
服务企业选项: [
{ label: '全部', value: '' },
{ label: '欧冶云商', value: '欧冶云商' },
{ label: '上海企源科技', value: '上海企源科技' },
{ label: '上海零数科技', value: '上海零数科技' },
{ label: '上海链坤数字科技', value: '上海链坤数字科技' },
],
卡片数据: [
{
标题: '本司提供碳相关服务寻找有需求的企业客户',
企业: '上海链坤数字科技有限公司 · 辽宁省',
标签: ['ESG报告编制', '碳减排技术服务'],
价格: '¥ 10,000.00 /次',
描述: '我们为参与碳市场的企业提供全方位的交易策略与风险管理咨询。服务内容包括解读碳市场政策规则、分析碳价走势、制定交易策略助…',
},
{
标题: '为碳超标企业提供中和方案',
企业: '上海零数科技有限公司 · 全国',
标签: ['碳核查服务', '碳足迹核算'],
价格: '¥ 5,000,000.00 /年',
描述: '本服务依据国际国内标准如ISO 14064-1对企业的温室气体排放报告进行独立的第三方审定与核查。我们通过文件评审、现场访…',
},
{
标题: '',
企业: '欧冶云商 · 北京市',
标签: ['ESG报告编制'],
价格: '¥ 1,500.00 /年',
描述: '我们协助企业系统梳理其在环境、社会和治理ESG领域的表现并按照GRI、SASB、TCFD等主流框架编制专业的ESG报告。服…',
},
{
标题: '碳足迹核算、碳减排技术供给',
企业: '上海企源科技股份有限公司 · 全国',
标签: ['碳减排技术服务', '碳足迹核算'],
价格: '面议',
描述: '本服务依据国际国内标准如ISO 14064-1对企业的温室气体排放报告进行独立的第三方审定与核查。我们通过文件评审、现场访…',
},
],
};
},
methods: {
搜索() {
console.log('搜索条件:', this.筛选);
},
},
};
</script>
<style scoped>
.fwsc-container {
min-height: 100vh;
background: #f5f5f5;
}
.fwsc-main {
width: 100%;
max-width: 1400px;
padding: 20px;
margin: 0 auto;
}
.内容区域 {
display: flex;
gap: 20px;
}
/* 左侧筛选栏 */
.筛选栏 {
position: sticky;
top: 104px;
width: 220px;
height: fit-content;
flex-shrink: 0;
}
.筛选栏内容 {
padding: 20px;
background: #fff;
border-radius: 8px;
}
.筛选项 {
margin-bottom: 20px;
}
.筛选标签 {
margin-bottom: 8px;
font-size: 14px;
font-weight: 500;
color: #333;
}
.搜索按钮 {
width: 100%;
margin-top: 10px;
}
/* 右侧卡片列表 */
.卡片列表 {
flex: 1;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
.服务卡片 {
position: relative;
padding: 20px;
background: #fff;
border-radius: 8px;
transition: transform 0.2s;
}
.服务卡片:hover {
transform: scale(1.02);
}
.卡片头部 {
margin-bottom: 12px;
}
.卡片标题 {
margin: 0 0 8px;
font-size: 16px;
font-weight: 600;
line-height: 1.4;
color: #333;
}
.卡片企业 {
margin: 0;
font-size: 13px;
color: #666;
}
.卡片标签 {
display: flex;
gap: 8px;
margin-bottom: 12px;
flex-wrap: wrap;
}
.标签 {
display: inline-block;
padding: 4px 12px;
font-size: 12px;
color: #0052d9;
background: #f0f5ff;
border-radius: 4px;
}
.卡片价格 {
margin-bottom: 12px;
font-size: 20px;
font-weight: 700;
}
.卡片描述 {
display: box;
margin-bottom: 16px;
overflow: hidden;
font-size: 13px;
line-height: 1.6;
color: #666;
text-overflow: ellipsis;
box-orient: vertical;
-webkit-line-clamp: 2;
}
.卡片操作 {
display: flex;
gap: 12px;
}
.操作按钮 {
flex: 1;
}
.卡片分隔线 {
position: absolute;
right: 20px;
bottom: 0;
left: 20px;
height: 1px;
background: #eee;
}
</style>

View File

@ -0,0 +1,254 @@
<template>
<div class="fwsc-page">
<NewNav />
<div class="main-content">
<!-- 当前位置导航 -->
<div class="breadcrumb-box">
<span class="breadcrumb-text">当前位置</span>
<span class="breadcrumb-link" @click="goHome">首页</span>
<span class="breadcrumb-separator">/</span>
<span class="breadcrumb-current">服务中心</span>
</div>
<!-- Banner -->
<div class="banner-section">
<div class="banner-content">
<h1 class="banner-title">可信碳服务中心</h1>
<p class="banner-subtitle">链接全球碳资产赋能绿色价值链一站式解决碳服务撮合绿色交易与金融对接需求</p>
</div>
</div>
<!-- 四大服务入口卡片 -->
<div class="services-section">
<div class="services-grid">
<!-- 碳服务市场 -->
<div class="service-card" @click="goToPage('/fwsc/fwsc')">
<div class="service-card-icon">
<span style="font-size: 48px">🌐</span>
</div>
<h3 class="service-card-title">碳服务市场</h3>
<p class="service-card-desc">汇聚全国优质第三方服务机构提供从核算到认证的全链条专业服务</p>
<div class="service-card-buttons">
<t-button theme="primary" variant="outline" @click.stop="goToPage('/fwsc/fwsc')">浏览供给信息</t-button>
<t-button theme="primary" @click.stop="goToPage('/fwsc/fwsc')">我要入驻</t-button>
</div>
</div>
<!-- 碳需求市场 -->
<div class="service-card" @click="goToPage('/fwsc/xqsc')">
<div class="service-card-icon">
<span style="font-size: 48px">📋</span>
</div>
<h3 class="service-card-title">碳需求市场</h3>
<p class="service-card-desc">企业发布真实服务采购需求智能匹配靠谱服务商杜绝中间商差价</p>
<div class="service-card-buttons">
<t-button theme="primary" variant="outline" @click.stop="goToPage('/fwsc/xqsc')">浏览求购信息</t-button>
<t-button theme="primary" @click.stop="goToPage('/fwsc/xqsc')">我要发布需求</t-button>
</div>
</div>
<!-- 碳金融市场 -->
<div class="service-card" @click="goToPage('/fwsc/jrsc')">
<div class="service-card-icon">
<span style="font-size: 48px">💰</span>
</div>
<h3 class="service-card-title">碳金融市场</h3>
<p class="service-card-desc">打通"碳""钱"的通道提供碳质押碳回购绿色信贷及碳基金对接服务</p>
<div class="service-card-buttons">
<t-button theme="primary" variant="outline" @click.stop="goToPage('/fwsc/jrsc')">查看金融产品</t-button>
<t-button theme="primary" @click.stop="goToPage('/fwsc/jrsc')">金融机构入驻</t-button>
</div>
</div>
<!-- 碳数据市场 -->
<div class="service-card" @click="goToPage('/fwsc/sjsc')">
<div class="service-card-icon">
<span style="font-size: 48px">📊</span>
</div>
<h3 class="service-card-title">碳数据市场</h3>
<p class="service-card-desc">合规高效的碳数据流转平台包括公共数据社会性数据因子库等多类数据库</p>
<div class="service-card-buttons">
<t-button theme="primary" variant="outline" @click.stop="goToPage('/fwsc/sjsc')">进入交易大厅</t-button>
<t-button theme="primary" @click.stop="goToPage('/fwsc/sjsc')">我要卖碳</t-button>
</div>
</div>
</div>
</div>
</div>
<Footer />
</div>
</template>
<script>
import NewNav from '@/pages/index/components/new-nav/index.vue';
import Footer from '@/pages/index/components/footer/index.vue';
export default {
name: 'FwscIndex',
components: {
NewNav,
Footer
},
methods: {
goHome() {
this.$router.push('/view/mhzc/home');
},
goToPage(path) {
this.$router.push(path);
}
}
};
</script>
<style lang="less" scoped>
.fwsc-page {
min-height: 100vh;
background: #f5f5f5;
}
.main-content {
// padding-top: 64px;
}
//
.breadcrumb-box {
display: flex;
align-items: center;
height: 48px;
padding: 0 200px;
background: #fff;
border-bottom: 1px solid #eee;
}
.breadcrumb-text {
font-size: 14px;
color: #666;
}
.breadcrumb-link {
font-size: 14px;
color: #009a29;
cursor: pointer;
transition: color 0.3s;
}
.breadcrumb-link:hover {
color: #007a1f;
}
.breadcrumb-separator {
margin: 0 8px;
font-size: 14px;
color: #999;
}
.breadcrumb-current {
font-size: 14px;
color: #333;
}
// Banner
.banner-section {
display: flex;
height: 280px;
text-align: center;
background: linear-gradient(135deg, #009a29 0%, #4caf50 100%);
align-items: center;
justify-content: center;
}
.banner-content {
max-width: 800px;
padding: 0 20px;
}
.banner-title {
margin-bottom: 16px;
font-size: 48px;
font-weight: 600;
line-height: 64px;
letter-spacing: 0;
color: #fff;
}
.banner-subtitle {
font-size: 18px;
font-weight: 400;
line-height: 28px;
letter-spacing: 0;
color: rgba(255, 255, 255, 0.9);
}
//
.services-section {
padding: 60px 200px;
}
.services-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 24px;
max-width: 1200px;
margin: 0 auto;
}
.service-card {
display: flex;
padding: 32px;
cursor: pointer;
background: #fff;
border-radius: 12px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
flex-direction: column;
&:hover {
transform: scale(1.02);
box-shadow: 0 8px 24px rgba(0, 154, 41, 0.15);
}
}
.service-card-icon {
display: flex;
width: 64px;
height: 64px;
margin-bottom: 20px;
align-items: center;
justify-content: center;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.service-card-title {
margin-bottom: 12px;
font-size: 24px;
font-weight: 600;
line-height: 32px;
letter-spacing: 0;
color: #1a1a1a;
}
.service-card-desc {
margin-bottom: 24px;
font-size: 14px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0;
color: #666;
flex-grow: 1;
}
.service-card-buttons {
display: flex;
gap: 12px;
.t-button {
flex: 1;
}
}
</style>

View File

@ -0,0 +1,561 @@
<template>
<div class="jrsc-page">
<!-- 顶部导航 -->
<new-nav />
<!-- 面包屑导航 -->
<BreadcrumbNav currentPage="碳金融市场" />
<!-- 页面主体 -->
<div class="jrsc-main">
<!-- 内容区域 -->
<div class="content-wrapper">
<!-- 左侧筛选栏 -->
<div class="sidebar">
<!-- 服务类型 -->
<div class="filter-section">
<div class="filter-title">服务类型</div>
<div class="filter-options">
<span
v-for="item in serviceTypes"
:key="item.value"
:class="['filter-item', { active: selectedServiceType === item.value }]"
@click="selectedServiceType = item.value"
>
{{ item.label }}
</span>
</div>
</div>
<!-- 服务企业 -->
<div class="filter-section">
<div class="filter-title">服务企业</div>
<div class="filter-options enterprise-options">
<span
v-for="item in enterprises"
:key="item.value"
:class="['filter-item', { active: selectedEnterprise === item.value }]"
@click="selectedEnterprise = item.value"
>
{{ item.label }}
</span>
</div>
</div>
<!-- 关键词搜索 -->
<div class="filter-section">
<div class="filter-title">关键词搜索</div>
<div class="search-box">
<input
v-model="searchKeyword"
type="text"
placeholder="请输入关键词"
class="search-input"
/>
<button class="search-btn" @click="handleSearch">搜索</button>
</div>
</div>
</div>
<!-- 右侧金融产品列表 -->
<div class="product-list">
<div class="product-grid">
<div
v-for="card in filteredProducts"
:key="card.id"
class="product-card"
>
<!-- 卡片头部机构名称 + Logo -->
<div class="card-header">
<span class="org-name">{{ card.orgName }}</span>
<div class="org-logo">
<img v-if="card.logo" :src="card.logo" :alt="card.orgName" />
<div v-else class="logo-placeholder"></div>
</div>
</div>
<!-- 产品名称 -->
<div class="product-name">{{ card.productName }}</div>
<!-- 产品标签 -->
<div class="product-tags">
<span class="tag">{{ card.tag }}</span>
</div>
<!-- 产品信息额度期限利率 -->
<div class="product-info">
<div class="info-item">
<div class="info-label">额度</div>
<div class="info-value amount">{{ card.amount }}</div>
</div>
<div class="info-item">
<div class="info-label">期限</div>
<div class="info-value">{{ card.term }}</div>
</div>
<div class="info-item">
<div class="info-label">利率</div>
<div class="info-value rate">{{ card.rate }}</div>
</div>
</div>
<!-- 操作按钮 -->
<div class="card-actions">
<button class="btn-primary">立即申请</button>
<button class="btn-secondary">查看详情</button>
</div>
</div>
</div>
<!-- 分页 -->
<div class="pagination">
<span class="page-item active">1</span>
<span class="page-item">2</span>
<span class="page-item">3</span>
<span class="page-item">4</span>
<span class="page-item">5</span>
<span class="page-item">下一页</span>
</div>
</div>
</div>
</div>
<!-- 底部 -->
<footer-component />
</div>
</template>
<script>
import NewNav from '@/pages/index/components/new-nav/index.vue';
import FooterComponent from '@/pages/index/components/footer/index.vue';
import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue';
export default {
name: 'JrscPage',
components: {
NewNav,
FooterComponent,
BreadcrumbNav,
},
data() {
return {
//
selectedServiceType: '全部',
//
selectedEnterprise: '全部',
//
searchKeyword: '',
//
serviceTypes: [
{ label: '全部', value: '全部' },
{ label: '绿色信贷', value: '绿色信贷' },
{ label: '绿色保险', value: '绿色保险' },
],
//
enterprises: [
{ label: '全部', value: '全部' },
{ label: '中国银行', value: '中国银行' },
{ label: '工商银行', value: '工商银行' },
{ label: '农业银行', value: '农业银行' },
{ label: '建设银行', value: '建设银行' },
{ label: '招商银行', value: '招商银行' },
{ label: '中信银行', value: '中信银行' },
{ label: '北京银行', value: '北京银行' },
{ label: '兴业银行', value: '兴业银行' },
{ label: '邮政储蓄银行', value: '邮政储蓄银行' },
],
//
products: [
{
id: 1,
orgName: '中国邮政储蓄银行',
productName: '云南昭通信贷业务',
tag: '绿色项目贷款',
amount: '¥ 50,000.00',
term: '1-3年',
rate: '3.6%~4.2%',
logo: '',
},
{
id: 2,
orgName: '中国建设银行',
productName: '低碳企业帮扶贷款',
tag: '低碳企业贷款',
amount: '¥ 50,000.00',
term: '1-3年',
rate: '3.6%~4.2%',
logo: '',
},
{
id: 3,
orgName: '中国邮政储蓄银行',
productName: '云南昭通信贷业务',
tag: '绿色项目贷款',
amount: '¥ 50,000.00',
term: '1-3年',
rate: '3.6%~4.2%',
logo: '',
},
{
id: 4,
orgName: '中国建设银行',
productName: '低碳企业帮扶贷款',
tag: '低碳企业贷款',
amount: '¥ 50,000.00',
term: '1-3年',
rate: '3.6%~4.2%',
logo: '',
},
{
id: 5,
orgName: '中国邮政储蓄银行',
productName: '云南昭通信贷业务',
tag: '绿色项目贷款',
amount: '¥ 50,000.00',
term: '1-3年',
rate: '3.6%~4.2%',
logo: '',
},
{
id: 6,
orgName: '中国建设银行',
productName: '低碳企业帮扶贷款',
tag: '低碳企业贷款',
amount: '¥ 50,000.00',
term: '1-3年',
rate: '3.6%~4.2%',
logo: '',
},
],
};
},
computed: {
//
filteredProducts() {
let result = this.products;
if (this.selectedServiceType !== '全部') {
result = result.filter((p) => p.tag.includes(this.selectedServiceType));
}
if (this.selectedEnterprise !== '全部') {
result = result.filter((p) => p.orgName.includes(this.selectedEnterprise));
}
if (this.searchKeyword) {
const keyword = this.searchKeyword.toLowerCase();
result = result.filter(
(p) =>
p.productName.toLowerCase().includes(keyword) ||
p.orgName.toLowerCase().includes(keyword) ||
p.tag.toLowerCase().includes(keyword)
);
}
return result;
},
},
methods: {
handleSearch() {
//
console.log('搜索关键词:', this.searchKeyword);
},
},
};
</script>
<style scoped lang="less">
.jrsc-page {
min-height: 100vh;
background-color: #f5f7fa;
}
.jrsc-main {
max-width: 1400px;
padding: 20px;
margin: 0 auto;
}
//
.content-wrapper {
display: flex;
gap: 20px;
}
//
.sidebar {
position: sticky;
top: 104px;
width: 220px;
height: fit-content;
padding: 20px;
background: #fff;
border-radius: 8px;
flex-shrink: 0;
}
.filter-section {
margin-bottom: 24px;
&:last-child {
margin-bottom: 0;
}
}
.filter-title {
margin-bottom: 12px;
font-size: 16px;
font-weight: 600;
color: #333;
}
.filter-options {
display: flex;
flex-wrap: wrap;
gap: 8px;
.filter-item {
padding: 6px 12px;
font-size: 14px;
color: #666;
cursor: pointer;
background: #f5f7fa;
border-radius: 4px;
transition: all 0.3s;
&:hover {
color: #009a29;
background: #e8f5e9;
}
&.active {
color: #fff;
background: #009a29;
}
}
}
.enterprise-options {
flex-direction: column;
gap: 6px;
.filter-item {
padding: 8px 12px;
text-align: left;
}
}
//
.search-box {
display: flex;
gap: 8px;
}
.search-input {
flex: 1;
padding: 8px 12px;
font-size: 14px;
border: 1px solid #ddd;
border-radius: 4px;
outline: none;
&:focus {
border-color: #009a29;
}
}
.search-btn {
padding: 8px 16px;
font-size: 14px;
color: #fff;
cursor: pointer;
background: #009a29;
border: none;
border-radius: 4px;
transition: background 0.3s;
&:hover {
background: #007a20;
}
}
//
.product-list {
flex: 1;
}
.product-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
//
.product-card {
padding: 20px;
background: #fff;
border-radius: 8px;
transition: transform 0.3s, box-shadow 0.3s;
&:hover {
transform: scale(1.02);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.org-name {
font-size: 16px;
font-weight: 600;
color: #333;
}
.org-logo {
width: 48px;
height: 48px;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
.logo-placeholder {
width: 100%;
height: 100%;
background: #f0f0f0;
border-radius: 4px;
}
}
.product-name {
margin-bottom: 12px;
font-size: 18px;
font-weight: 500;
color: #1a1a1a;
}
.product-tags {
margin-bottom: 16px;
.tag {
display: inline-block;
padding: 4px 12px;
font-size: 12px;
color: #009a29;
background: #e8f5e9;
border-radius: 4px;
}
}
.product-info {
display: flex;
padding: 16px 0;
margin-bottom: 16px;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
justify-content: space-between;
}
.info-item {
text-align: center;
flex: 1;
}
.info-label {
margin-bottom: 8px;
font-size: 13px;
color: #999;
}
.info-value {
font-size: 16px;
font-weight: 600;
color: #333;
&.amount {
color: #d25f00;
}
&.rate {
color: #00b42a;
}
}
.card-actions {
display: flex;
gap: 12px;
}
.btn-primary {
padding: 10px 0;
font-size: 14px;
font-weight: 500;
color: #fff;
cursor: pointer;
background: #009a29;
border: none;
border-radius: 4px;
transition: background 0.3s;
flex: 1;
&:hover {
background: #007a20;
}
}
.btn-secondary {
padding: 10px 0;
font-size: 14px;
font-weight: 500;
color: #666;
cursor: pointer;
background: #f5f7fa;
border: 1px solid #ddd;
border-radius: 4px;
transition: all 0.3s;
flex: 1;
&:hover {
color: #009a29;
background: #e8f5e9;
border-color: #009a29;
}
}
//
.pagination {
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
margin-top: 30px;
}
.page-item {
padding: 8px 14px;
font-size: 14px;
color: #666;
cursor: pointer;
background: #fff;
border: 1px solid #ddd;
border-radius: 4px;
transition: all 0.3s;
&:hover {
color: #009a29;
border-color: #009a29;
}
&.active {
color: #fff;
background: #009a29;
border-color: #009a29;
}
}
</style>

View File

@ -0,0 +1,594 @@
<template>
<div class="sjlbc-page">
<!-- 顶部导航 -->
<NewNav />
<!-- 面包屑导航 -->
<BreadcrumbNav
:currentPage="currentPageName"
secondPage="碳数据市场"
secondLink="/fwsc/sjsc"
/>
<!-- 主内容区 -->
<div class="content-wrapper">
<!-- 左侧筛选栏 -->
<div class="filter-sidebar">
<div class="filter-box">
<!-- 价格区间 -->
<div class="filter-section">
<div class="filter-title">价格区间</div>
<div class="price-range">
<input type="text" v-model="filterParams.priceMin" placeholder="最低" class="price-input price-min" />
<span class="price-separator">-</span>
<input type="text" v-model="filterParams.priceMax" placeholder="最高" class="price-input price-max" />
</div>
</div>
<!-- 有效期 -->
<div class="filter-section">
<div class="filter-title">有效期</div>
<div class="date-picker-box">
<input type="date" v-model="filterParams.validDate" class="date-input" />
</div>
</div>
<!-- 筛选按钮 -->
<div class="filter-buttons">
<button class="btn-reset" @click="resetFilter">重置</button>
<button class="btn-confirm" @click="confirmFilter">确定</button>
</div>
</div>
</div>
<!-- 右侧数据列表 -->
<div class="data-list">
<!-- 表头 -->
<div class="table-header">
<div class="th th-type" @click="sortBy('type')">
数据类型
<span class="sort-icon">
<span class="sort-up" :class="{ active: sortField === 'type' && sortOrder === 'asc' }"></span>
<span class="sort-down" :class="{ active: sortField === 'type' && sortOrder === 'desc' }"></span>
</span>
</div>
<div class="th th-name">名称</div>
<div class="th th-time" @click="sortBy('time')">
发布时间/更新时间
<span class="sort-icon">
<span class="sort-up" :class="{ active: sortField === 'time' && sortOrder === 'asc' }"></span>
<span class="sort-down" :class="{ active: sortField === 'time' && sortOrder === 'desc' }"></span>
</span>
</div>
<div class="th th-count" @click="sortBy('count')">
数据条数
<span class="sort-icon">
<span class="sort-up" :class="{ active: sortField === 'count' && sortOrder === 'asc' }"></span>
<span class="sort-down" :class="{ active: sortField === 'count' && sortOrder === 'desc' }"></span>
</span>
</div>
<div class="th th-views" @click="sortBy('views')">
浏览量
<span class="sort-icon">
<span class="sort-up" :class="{ active: sortField === 'views' && sortOrder === 'asc' }"></span>
<span class="sort-down" :class="{ active: sortField === 'views' && sortOrder === 'desc' }"></span>
</span>
</div>
<div class="th th-downloads" @click="sortBy('downloads')">
下载量
<span class="sort-icon">
<span class="sort-up" :class="{ active: sortField === 'downloads' && sortOrder === 'asc' }"></span>
<span class="sort-down" :class="{ active: sortField === 'downloads' && sortOrder === 'desc' }"></span>
</span>
</div>
</div>
<!-- 表格数据 -->
<div class="table-body">
<div
v-for="(item, index) in sortedDataList"
:key="index"
class="table-row"
:class="{ 'row-even': index % 2 === 1 }"
>
<div class="td td-type">
<span class="type-tag" :class="item.type === '公共数据' ? 'tag-green' : 'tag-blue'">
{{ item.type }}
</span>
</div>
<div class="td td-name" :title="item.name">{{ item.name }}</div>
<div class="td td-time">
<div class="time-info">
<span>发布时间{{ item.publishTime }}</span>
<span v-if="item.updateTime">更新时间{{ item.updateTime }}</span>
</div>
</div>
<div class="td td-count">{{ item.dataCount }}</div>
<div class="td td-views">{{ item.views }}次浏览</div>
<div class="td td-downloads">{{ item.downloads }}次下载</div>
</div>
</div>
</div>
</div>
<!-- 分页 -->
<div class="pagination">
<span class="page-btn">上一页</span>
<span class="page-btn active">1</span>
<span class="page-btn">2</span>
<span class="page-btn">3</span>
<span class="page-btn">4</span>
<span class="page-btn">5</span>
<span class="page-btn">下一页</span>
</div>
<!-- 底部 -->
<Footer />
</div>
</template>
<script>
import NewNav from '@/pages/index/components/new-nav/index.vue';
import Footer from '@/pages/index/components/footer/index.vue';
import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue';
export default {
name: 'SjlbcPage',
components: {
NewNav,
Footer,
BreadcrumbNav,
},
data() {
return {
currentPageName: '数据列表',
marketId: '',
filterParams: {
priceMin: '',
priceMax: '',
validDate: '',
},
sortField: '',
sortOrder: '',
dataList: [
{
name: '全球多源高分辨温室气体及大气污染物排放清单',
type: '社会性数据',
publishTime: '2026-03-30 10:00',
updateTime: '2026-03-30 10:00',
dataCount: '45,000',
views: '475',
downloads: '18',
},
{
name: '国家温室气体排放因子数据库',
type: '公共数据',
publishTime: '2026-03-30 10:00',
updateTime: '',
dataCount: '45,000',
views: '475',
downloads: '18',
},
{
name: '碳排放数据库',
type: '公共数据',
publishTime: '2026-03-30 10:00',
updateTime: '',
dataCount: '45,000',
views: '475',
downloads: '18',
},
{
name: '全球多源高分辨温室气体及大气污染物排放清单',
type: '社会性数据',
publishTime: '2026-03-30 10:00',
updateTime: '2026-03-30 10:00',
dataCount: '45,000',
views: '475',
downloads: '18',
},
{
name: '国家温室气体排放因子数据库',
type: '公共数据',
publishTime: '2026-03-30 10:00',
updateTime: '',
dataCount: '45,000',
views: '475',
downloads: '18',
},
{
name: '碳排放数据库',
type: '公共数据',
publishTime: '2026-03-30 10:00',
updateTime: '',
dataCount: '45,000',
views: '475',
downloads: '18',
},
{
name: '全球多源高分辨温室气体及大气污染物排放清单',
type: '社会性数据',
publishTime: '2026-03-30 10:00',
updateTime: '2026-03-30 10:00',
dataCount: '45,000',
views: '475',
downloads: '18',
},
{
name: '国家温室气体排放因子数据库',
type: '公共数据',
publishTime: '2026-03-30 10:00',
updateTime: '',
dataCount: '45,000',
views: '475',
downloads: '18',
},
],
};
},
created() {
this.marketId = this.$route.query.id || '';
},
computed: {
sortedDataList() {
if (!this.sortField) {
return this.dataList;
}
return [...this.dataList].sort((a, b) => {
let valA = a[this.sortField];
let valB = b[this.sortField];
//
if (this.sortField === 'time') {
valA = a.updateTime || a.publishTime;
valB = b.updateTime || b.publishTime;
}
//
if (this.sortField === 'count' || this.sortField === 'views' || this.sortField === 'downloads') {
valA = parseInt(valA.replace(/,/g, ''));
valB = parseInt(valB.replace(/,/g, ''));
}
if (valA < valB) {
return this.sortOrder === 'asc' ? -1 : 1;
}
if (valA > valB) {
return this.sortOrder === 'asc' ? 1 : -1;
}
return 0;
});
},
},
methods: {
sortBy(field) {
if (this.sortField === field) {
this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc';
} else {
this.sortField = field;
this.sortOrder = 'desc';
}
},
resetFilter() {
this.filterParams = {
priceMin: '',
priceMax: '',
validDate: '',
};
},
confirmFilter() {
console.log('筛选条件:', this.filterParams);
},
},
};
</script>
<style lang="less" scoped>
.sjlbc-page {
min-height: 100vh;
background: #f5f5f5;
}
//
.content-wrapper {
display: flex;
max-width: 1400px;
padding: 20px;
margin: 0 auto;
gap: 20px;
}
//
.filter-sidebar {
width: 200px;
flex-shrink: 0;
}
.filter-box {
position: sticky;
top: 104px;
padding: 16px;
background: #fff;
border-radius: 8px;
}
.filter-section {
margin-bottom: 20px;
}
.filter-title {
margin-bottom: 12px;
font-size: 14px;
font-weight: 600;
color: #333;
}
.price-range {
display: flex;
align-items: center;
gap: 6px;
}
.price-input {
height: 32px;
padding: 0 6px;
border: 1px solid #ddd;
border-radius: 4px;
outline: none;
box-sizing: border-box;
&:focus {
border-color: #009a29;
}
}
.price-min,
.price-max {
width: 80px;
}
.price-separator {
flex-shrink: 0;
color: #999;
}
.date-picker-box {
.date-input {
width: 100%;
height: 32px;
padding: 0 8px;
border: 1px solid #ddd;
border-radius: 4px;
outline: none;
box-sizing: border-box;
&:focus {
border-color: #009a29;
}
}
}
.filter-buttons {
display: flex;
gap: 12px;
.btn-reset,
.btn-confirm {
height: 36px;
font-size: 14px;
cursor: pointer;
border: none;
border-radius: 4px;
flex: 1;
}
.btn-reset {
color: #666;
background: #f5f5f5;
border: 1px solid #ddd;
&:hover {
background: #eee;
}
}
.btn-confirm {
color: #fff;
background: #009a29;
&:hover {
background: #008f26;
}
}
}
//
.data-list {
overflow: hidden;
background: #fff;
border-radius: 8px;
flex: 1;
}
//
.table-header {
display: flex;
height: 48px;
background: #f5f5f5;
border-bottom: 1px solid #eee;
}
.th {
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
padding: 0 12px;
font-size: 14px;
font-weight: 600;
color: #333;
cursor: pointer;
&:hover {
background: #eee;
}
}
.th-type {
width: 120px;
}
.th-name {
flex: 1;
justify-content: flex-start;
}
.th-time {
width: 180px;
}
.th-count {
width: 100px;
}
.th-views {
width: 100px;
}
.th-downloads {
width: 100px;
}
.sort-icon {
display: flex;
flex-direction: column;
gap: 1px;
font-size: 8px;
color: #ccc;
.sort-up,
.sort-down {
&.active {
color: #009a29;
}
}
.sort-down {
transform: rotate(180deg);
}
}
//
.table-body {
.table-row {
display: flex;
min-height: 72px;
border-bottom: 1px solid #eee;
&:hover {
background: #f9f9f9;
}
&.row-even {
background: #fafafa;
}
}
}
.td {
display: flex;
align-items: center;
justify-content: center;
padding: 0 12px;
font-size: 14px;
color: #666;
}
.td-type {
width: 120px;
}
.td-name {
flex: 1;
justify-content: flex-start;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.td-time {
width: 180px;
flex-direction: column;
justify-content: center;
gap: 4px;
.time-info {
display: flex;
flex-direction: column;
font-size: 12px;
color: #999;
}
}
.td-count {
width: 100px;
}
.td-views {
width: 100px;
}
.td-downloads {
width: 100px;
}
//
.type-tag {
padding: 4px 8px;
font-size: 12px;
border-radius: 4px;
&.tag-green {
color: #2e7d32;
background: #e8f5e9;
}
&.tag-blue {
color: #1565c0;
background: #e3f2fd;
}
}
//
.pagination {
display: flex;
justify-content: center;
align-items: center;
padding: 24px 0;
gap: 8px;
.page-btn {
height: 36px;
min-width: 40px;
padding: 0 12px;
line-height: 36px;
color: #666;
text-align: center;
cursor: pointer;
background: #fff;
border: 1px solid #ddd;
border-radius: 4px;
&:hover {
color: #009a29;
border-color: #009a29;
}
&.active {
color: #fff;
background: #009a29;
border-color: #009a29;
}
}
}
</style>

View File

@ -0,0 +1,337 @@
<template>
<div class="sjsc-page">
<NewNav />
<!-- 面包屑导航 -->
<BreadcrumbNav currentPage="碳数据市场" />
<!-- 页面主体 -->
<div class="page-body">
<!-- 左侧筛选栏 -->
<div class="sidebar">
<div class="sidebar-title">数据类型</div>
<div class="filter-list">
<div
v-for="item in dataTypeList"
:key="item.value"
class="filter-item"
:class="{ active: selectedType === item.value }"
@click="handleTypeChange(item.value)"
>
{{ item.label }}
</div>
</div>
</div>
<!-- 右侧数据库卡片列表 -->
<div class="content-area">
<div class="card-grid">
<div
v-for="card in filteredCards"
:key="card.id"
class="database-card"
>
<div class="card-header">
<h3 class="card-title">{{ card.name }}</h3>
<div class="card-tags">
<span
v-for="tag in card.tags"
:key="tag"
class="tag"
:class="getTagClass(tag)"
>
{{ tag }}
</span>
</div>
</div>
<p class="card-desc">{{ card.description }}</p>
<div class="card-footer">
<span class="price-tag" :class="card.price === '免费' ? 'free' : 'paid'">
{{ card.price }}
</span>
<t-button theme="primary" size="small" variant="outline" @click="goToDataList(card.id)">
查看数据库
</t-button>
</div>
</div>
</div>
</div>
</div>
<Footer />
</div>
</template>
<script>
import NewNav from '@/pages/index/components/new-nav/index.vue';
import Footer from '@/pages/index/components/footer/index.vue';
import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue';
export default {
name: 'SjscPage',
components: {
NewNav,
Footer,
BreadcrumbNav,
},
data() {
return {
selectedType: 'all',
dataTypeList: [
{ label: '全部', value: 'all' },
{ label: '公共数据', value: 'public' },
{ label: '因子库', value: 'factor' },
{ label: '社会性数据', value: 'social' }
],
cardList: [
{
id: 1,
name: '宝山绿色低碳数据创新实验室',
description: '汇聚全国优质第三方服务机构,提供从核算到认证的全链条专业服务。',
tags: ['公共数据', '社会性数据'],
price: '免费'
},
{
id: 2,
name: 'HiQLCD数据库',
description: '汇聚全国优质第三方服务机构,提供从核算到认证的全链条专业服务。',
tags: ['商业数据'],
price: '付费'
},
{
id: 3,
name: '天工数据库',
description: '汇聚全国优质第三方服务机构,提供从核算到认证的全链条专业服务。',
tags: ['公益数据'],
price: '免费'
},
{
id: 4,
name: 'ecoinvent数据库',
description: '汇聚全国优质第三方服务机构,提供从核算到认证的全链条专业服务。',
tags: ['商业数据'],
price: '付费'
},
{
id: 5,
name: 'ecoinvent数据库',
description: '汇聚全国优质第三方服务机构,提供从核算到认证的全链条专业服务。',
tags: ['商业数据'],
price: '付费'
},
{
id: 6,
name: '天工数据库',
description: '汇聚全国优质第三方服务机构,提供从核算到认证的全链条专业服务。',
tags: ['公益数据'],
price: '免费'
}
]
};
},
computed: {
filteredCards() {
if (this.selectedType === 'all') {
return this.cardList;
}
const typeMap = {
'public': '公共数据',
'factor': '因子库',
'social': '社会性数据'
};
const targetTag = typeMap[this.selectedType];
return this.cardList.filter(card => card.tags.includes(targetTag));
}
},
methods: {
handleTypeChange(value) {
this.selectedType = value;
},
goToDataList(id) {
this.$router.push({ path: '/fwsc/sjlbc', query: { id } });
},
getTagClass(tag) {
const classMap = {
'公共数据': 'tag-green',
'社会性数据': 'tag-blue',
'商业数据': 'tag-gray',
'公益数据': 'tag-green'
};
return classMap[tag] || 'tag-gray';
}
}
};
</script>
<style lang="less" scoped>
.sjsc-page {
min-height: 100vh;
background: #f5f5f5;
}
//
.page-body {
display: flex;
max-width: 1400px;
padding: 20px;
margin: 0 auto;
gap: 20px;
}
//
.sidebar {
position: sticky;
top: 104px;
width: 220px;
height: fit-content;
min-width: 220px;
padding: 20px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.sidebar-title {
padding-bottom: 12px;
margin-bottom: 16px;
font-size: 16px;
font-weight: 600;
color: #333;
border-bottom: 1px solid #eee;
}
.filter-list {
display: flex;
flex-direction: column;
gap: 4px;
}
.filter-item {
padding: 10px 16px;
font-size: 14px;
color: #666;
cursor: pointer;
border-radius: 6px;
transition: all 0.3s;
&:hover {
color: #009a29;
background: #f0f9f0;
}
&.active {
color: #fff;
background: #009a29;
&:hover {
color: #fff;
background: #007a1f;
}
}
}
//
.content-area {
flex: 1;
min-width: 0;
}
//
.card-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
.database-card {
display: flex;
flex-direction: column;
padding: 24px;
background: #fff;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
transition: all 0.3s;
&:hover {
transform: translateY(-2px);
box-shadow: 0 8px 24px rgba(0, 154, 41, 0.12);
}
}
.card-header {
margin-bottom: 12px;
}
.card-title {
margin-bottom: 12px;
font-size: 18px;
font-weight: 600;
line-height: 1.4;
color: #1a1a1a;
}
.card-tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.tag {
display: inline-block;
padding: 4px 10px;
font-size: 12px;
font-weight: 500;
border-radius: 4px;
}
.tag-green {
color: #2e7d32;
background: #e8f5e9;
}
.tag-blue {
color: #1565c0;
background: #e3f2fd;
}
.tag-gray {
color: #666;
background: #f5f5f5;
}
.tag-orange {
color: #e65100;
background: #fff3e0;
}
.card-desc {
margin-bottom: 20px;
font-size: 14px;
line-height: 1.6;
color: #666;
flex: 1;
}
.card-footer {
display: flex;
align-items: center;
justify-content: space-between;
}
.price-tag {
padding: 4px 12px;
font-size: 14px;
font-weight: 600;
border-radius: 4px;
&.free {
color: #2e7d32;
background: #e8f5e9;
}
&.paid {
color: #e65100;
background: #fff3e0;
}
}
</style>

View File

@ -0,0 +1,462 @@
<!--
* @Descripttion: 碳需求市场页面
* @Version: 1.0
* @Author: cby
* @Date: 2026-04-03
-->
<template>
<div>
<NewNav />
<div class="xqsc-page">
<!-- 面包屑导航 -->
<BreadcrumbNav currentPage="碳需求市场" />
<!-- 主内容区 -->
<div class="content-wrapper">
<!-- 左侧筛选栏 -->
<div class="filter-sidebar">
<!-- 搜索框 -->
<div class="filter-search">
<t-input v-model="searchKeyword" placeholder="请输入关键词" @enter="handleSearch"></t-input>
<t-button theme="primary" @click="handleSearch">搜索</t-button>
</div>
<!-- 服务类型 -->
<div class="filter-section">
<div class="filter-title">服务类型</div>
<div class="filter-options">
<div
v-for="item in serviceTypeList"
:key="item.value"
:class="['filter-option', { active: selectedServiceType === item.value }]"
@click="handleServiceTypeSelect(item.value)"
>
{{ item.label }}
</div>
</div>
</div>
<!-- 服务企业 -->
<div class="filter-section">
<div class="filter-title">服务企业</div>
<div class="filter-options">
<div
v-for="item in companyList"
:key="item.value"
:class="['filter-option', { active: selectedCompany === item.value }]"
@click="handleCompanySelect(item.value)"
>
{{ item.label }}
</div>
</div>
</div>
</div>
<!-- 右侧需求卡片列表 -->
<div class="demand-list">
<div class="list-header">
<span class="list-title">碳需求市场</span>
<span class="list-count"> {{ demandList.length }} 条需求</span>
</div>
<div class="demand-grid">
<div
v-for="(item, index) in demandList"
:key="index"
class="demand-card"
>
<!-- 卡片头部 - 标题 -->
<div :class="['demand-title', { 'urgent': item.urgent }]">
{{ item.title }}
</div>
<!-- 发布企业 -->
<div class="demand-company">
{{ item.company }}
</div>
<!-- 标签 -->
<div class="demand-tags">
<span v-for="(tag, tagIndex) in item.tags" :key="tagIndex" class="demand-tag">
{{ tag }}
</span>
</div>
<!-- 预算 -->
<div class="demand-budget">
<span class="budget-label">预算</span>
<span class="budget-value">{{ item.budget }}</span>
</div>
<!-- 描述 -->
<div class="demand-desc">
{{ item.desc }}
</div>
<!-- 有效期 -->
<div class="demand-validity" v-if="item.validity">
<svg class="calendar-icon" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.5V3.5C13.5 3.22386 13.2761 3 13 3H12.5V1.5C12.5 1.22386 12.2761 1 12 1C11.7239 1 11.5 1.22386 11.5 1.5V3H4.5V1.5C4.5 1.22386 4.27614 1 4 1C3.72386 1 3.5 1.22386 3.5 1.5V3H3C2.72386 3 2.5 3.22386 2.5 3.5V13.5C2.5 13.7761 2.72386 14 3 14H13C13.2761 14 13.5 13.7761 13.5 13.5V13.5" stroke="#666" stroke-width="1.2"/>
<path d="M5.5 6H10.5M5.5 8.5H10.5M5.5 11H8.5" stroke="#666" stroke-width="1.2" stroke-linecap="round"/>
</svg>
<span>有效期至{{ item.validity }}</span>
</div>
<!-- 操作按钮 -->
<div class="demand-action">
<t-button theme="primary" @click="handleContact(item)">联系服务</t-button>
</div>
</div>
</div>
</div>
</div>
<!-- 联系服务弹窗 -->
<t-dialog
:closeOnOverlayClick="false"
header="联系服务"
:visible.sync="contactDialogVisible"
@confirm="handleConfirm"
@cancel="handleCancel"
:onClose="handleClose"
class="global-dialog"
attach="body"
>
<div class="dialog-line">
<div class="dialog-line-title">联系人</div>
<div class="dialog-line-text">{{ contactData.lxr }}</div>
</div>
<div class="dialog-line">
<div class="dialog-line-title">联系电话</div>
<div class="dialog-line-text">{{ contactData.lxdh }}</div>
</div>
<div class="dialog-line">
<div class="dialog-line-title">电子邮箱</div>
<div class="dialog-line-text">{{ contactData.email }}</div>
</div>
<div class="dialog-line">
<div class="dialog-line-title" style="width:95px">留言内容</div>
<t-textarea v-model="messageContent" :autosize="{ minRows: 3 }"></t-textarea>
</div>
</t-dialog>
<Footer />
</div>
</div>
</template>
<script>
import NewNav from '@/pages/index/components/new-nav/index.vue';
import Footer from '@/pages/index/components/footer/index.vue';
import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue';
export default {
name: 'Xqsc',
components: {
NewNav,
Footer,
BreadcrumbNav,
},
data() {
return {
searchKeyword: '',
selectedServiceType: '',
selectedCompany: '',
contactDialogVisible: false,
contactData: {
lxr: '张经理',
lxdh: '021-12345678',
email: 'service@example.com'
},
messageContent: '',
serviceTypeList: [
{ label: '全部', value: '' },
{ label: '碳核查服务', value: 'carbon_check' },
{ label: '碳足迹核算', value: 'carbon_footprint' },
{ label: '碳减排技术服务', value: 'carbon_reduction' },
{ label: '碳资产管理服务', value: 'carbon_asset' },
{ label: 'ESG报告编制', value: 'esg_report' },
{ label: '碳交易咨询', value: 'carbon_trade' }
],
companyList: [
{ label: '全部', value: '' },
{ label: '欧冶云商', value: 'ouye' },
{ label: '上海企源科技股份有限公司', value: 'qiyuan' },
{ label: '上海零数科技有限公司', value: 'lingshu' },
{ label: '上海链坤数字科技有限公司', value: 'linkun' }
],
demandList: [
{
title: '碳核查服务需求',
company: '上海链坤数字科技有限公司',
tags: ['ESG报告编制', '碳减排技术服务'],
budget: '¥ 50-100 万元',
desc: '我们为参与碳市场的企业提供全方位的交易策略与风险管理咨询。服务内容包括解读碳市场政策规则、分析碳价走势、制定交易策略...',
validity: '2026-04-24',
urgent: false
},
{
title: '【碳服务需求!急急急!】',
company: '上海零数科技有限公司',
tags: ['碳核查服务', '碳足迹核算'],
budget: '¥ 50-100 万元',
desc: '本服务依据国际国内标准如ISO 14064-1对企业的温室气体排放报告进行独立的第三方审定与核查。我们通过文件评审、现场访...',
validity: '2026-04-24',
urgent: true
},
{
title: '减碳中和需求',
company: '上海链坤数字科技有限公司',
tags: ['ESG报告编制', '碳减排技术服务'],
budget: '¥ 50-100 万元',
desc: '我们为参与碳市场的企业提供全方位的交易策略与风险管理咨询。服务内容包括解读碳市场政策规则、分析碳价走势、制定交易策略...',
validity: '',
urgent: false
},
{
title: '碳足迹核算需求',
company: '欧冶云商',
tags: ['碳核查服务', '碳足迹核算'],
budget: '¥ 50-100 万元',
desc: '本服务依据国际国内标准如ISO 14064-1对企业的温室气体排放报告进行独立的第三方审定与核查。我们通过文件评审、现场访...',
validity: '',
urgent: false
}
]
};
},
methods: {
handleSearch() {
console.log('搜索关键词:', this.searchKeyword);
},
handleServiceTypeSelect(value) {
this.selectedServiceType = value;
},
handleCompanySelect(value) {
this.selectedCompany = value;
},
handleContact(item) {
this.contactDialogVisible = true;
this.messageContent = '';
},
handleConfirm() {
console.log('提交留言:', this.messageContent);
this.$message.success('留言发布成功!');
this.contactDialogVisible = false;
},
handleCancel() {
this.contactDialogVisible = false;
},
handleClose() {
this.contactDialogVisible = false;
}
}
};
</script>
<style lang="less" scoped>
.xqsc-page {
min-height: 100vh;
background: #efefef;
}
//
.content-wrapper {
display: flex;
max-width: 1400px;
padding: 20px;
margin: 0 auto;
gap: 20px;
}
//
.filter-sidebar {
position: sticky;
top: 104px;
width: 220px;
flex-shrink: 0;
height: fit-content;
padding: 20px;
background: #fff;
border-radius: 8px;
}
.filter-search {
display: flex;
gap: 8px;
margin-bottom: 24px;
}
.filter-section {
margin-bottom: 20px;
}
.filter-title {
margin-bottom: 12px;
font-size: 16px;
font-weight: 600;
color: #333;
}
.filter-options {
display: flex;
flex-direction: column;
gap: 8px;
}
.filter-option {
padding: 8px 12px;
font-size: 14px;
color: #666;
cursor: pointer;
background: #f5f5f5;
border-radius: 4px;
transition: all 0.3s;
&:hover {
color: #009a29;
background: #e8f5e9;
}
&.active {
color: #fff;
background: #009a29;
}
}
//
.demand-list {
flex: 1;
min-width: 0;
}
.list-header {
display: flex;
padding: 0 8px;
margin-bottom: 16px;
justify-content: space-between;
align-items: center;
}
.list-title {
font-size: 20px;
font-weight: 600;
color: #333;
}
.list-count {
font-size: 14px;
color: #999;
}
//
.demand-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
.demand-card {
display: flex;
flex-direction: column;
padding: 20px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.demand-title {
margin-bottom: 8px;
font-size: 18px;
font-weight: 600;
line-height: 1.4;
color: #333;
&.urgent {
color: #d25f00;
}
}
.demand-company {
margin-bottom: 12px;
font-size: 14px;
color: #666;
}
.demand-tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 12px;
}
.demand-tag {
padding: 4px 8px;
font-size: 12px;
color: #2e7d32;
background: #e4f4e6;
border-radius: 2px;
}
.demand-budget {
display: flex;
align-items: center;
margin-bottom: 12px;
}
.budget-label {
margin-right: 8px;
font-size: 14px;
color: #666;
}
.budget-value {
font-size: 20px;
font-weight: 700;
color: #D25F00;
}
.demand-desc {
margin-bottom: 16px;
font-size: 14px;
line-height: 1.6;
color: #666;
flex-grow: 1;
}
.demand-validity {
display: flex;
margin-bottom: 16px;
font-size: 14px;
color: #999;
align-items: center;
gap: 6px;
}
.calendar-icon {
width: 16px;
height: 16px;
}
.demand-action {
.t-button {
width: 100%;
}
}
//
.dialog-line {
display: flex;
margin-bottom: 16px;
}
.dialog-line-title {
margin-right: 8px;
color: #333;
}
.dialog-line-text {
color: #666;
}
</style>

View File

@ -1,34 +1,11 @@
<template>
<div class="page-box">
<!-- 顶部菜单栏 -->
<div class="nav-box">
<div class="logo-box">
<img src="@/pages/index/assets/logo-name.png">
</div>
<div class="menu-box">
<div class="menu-title meun-title-active">
<img src="@/pages/index/assets/nav-home.png" width="24px" height="24px">
<span> &nbsp;&nbsp;首页</span>
</div>
<div class="menu-title">碳证中心</div>
<div class="menu-title">服务中心</div>
<div class="menu-title">共性能力</div>
<div class="menu-title">企业出海</div>
<div class="menu-title">行业专题</div>
</div>
<div class="option-box">
<div class="gzt">
<img src="@/pages/index/assets/home-gzt-icon.png" />
<span> 工作台</span>
</div>
<div style="margin-left:20px; cursor: pointer;">激活</div>
<div>|</div>
<div style="cursor: pointer;">登录</div>
</div>
</div>
<NewNav />
<!-- 主页面 -->
<div class="container">
<div>asdf</div>
<!-- 顶部风力发电机图片 -->
<div class="top-box">
<div class="top-title">
@ -245,9 +222,11 @@
<script>
import Footer from '@/pages/index/components/footer/index.vue';
import NewNav from '@/pages/index/components/new-nav/index.vue';
export default {
components: {
Footer,
NewNav,
},
}
</script>
@ -257,81 +236,6 @@ export default {
background: #f5f5f7;
}
.nav-box {
position: fixed;
top: 0;
z-index: 9999;
display: flex;
width: 100%;
height: 64px;
min-width: 1920px;
margin: 0 auto;
color: #fff;
background: #009a29;
justify-content: space-around;
align-items: center;
}
.logo-box {
width: 25%;
text-align: center;
}
.option-box {
display: flex;
width: 25%;
font-family: PingFang SC;
font-size: 16px;
font-style: regular;
font-weight: 400;
letter-spacing: 0%;
text-align: center;
justify-content: center;
align-items: center;
gap: 10px;
leading-trim: none;
}
.option-box .gzt {
display: flex;
padding: 10px;
text-align: center;
background: rgba(255, 255, 255, 0.3);
border-radius: 6px;
justify-content: space-around;
align-items: center;
gap: 10px;
}
.menu-box {
display: flex;
width: 50%;
font-size: 16px;
text-align: center;
justify-content: center;
gap: 10px;
}
.menu-title {
display: flex;
width: 96px;
height: 64px;
line-height: 24px;
text-align: center;
cursor: pointer;
justify-content: center;
align-items: center;
}
.meun-title-active {
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.15) 100%);
border-bottom: 2px solid #fff;
}
.top-box {
position: relative;

View File

@ -95,54 +95,54 @@ const configureWebpackPlugin = [];
/**
* 本地开发启用hard-source-webpack-plugin
*/
if (LOCAL_DEV) {
console.log('====>> 启动本地开发缓存');
configureWebpackPlugin.push(
new HardSourceWebpackPlugin({
// 缓存目录,支持相对目录或绝对目录
// 如果有设置VUE_APP_HARD_SOURCE_FOLDER目录则使用设置值
// 一般在coding流水线编译使用把缓存设置到`/data/npm/`中,不会丢失
cacheDirectory: `${
(process.env.VUE_APP_HARD_SOURCE_FOLDER && path.join(process.env.VUE_APP_HARD_SOURCE_FOLDER, '/')) ||
path.join(process.cwd(), 'node_modules', '/')
}.cache/hard-source/[confighash]`,
// 基于package.json中的name来生成不同的hash串用于cacheDirectory的目录
// @param webpackConfig
configHash(webpackConfig) {
return require('node-object-hash')({ sort: false }).hash({ packageName, ...webpackConfig });
},
// 根据目录中的lock文件来决定是否重设缓存如果设置false则需要手动删除
environmentHash: {
root: process.cwd(),
directories: [],
files: ['package-lock.json', 'yarn.lock'],
},
info: {
// 'none' or 'test'.
mode: 'none',
// 'debug', 'log', 'info', 'warn', or 'error'.
level: 'debug',
},
// 自动清除过期、过大缓存
cachePrune: {
// 缓存时间默认7天
maxAge: 7 * 24 * 60 * 60 * 1000,
// 超过该处设置的阈值默认500MB则自动删除缓存
sizeThreshold: 500 * 1024 * 1024,
},
}),
new HardSourceWebpackPlugin.ExcludeModulePlugin([
{
// HardSource works with mini-css-extract-plugin but due to how
// mini-css emits assets, assets are not emitted on repeated builds with
// mini-css and hard-source together. Ignoring the mini-css loader
// modules, but not the other css loader modules, excludes the modules
// that mini-css needs rebuilt to output assets every time.
test: /mini-css-extract-plugin[\\/]dist[\\/]loader/,
},
]),
);
}
// if (LOCAL_DEV) {
// console.log('====>> 启动本地开发缓存');
// configureWebpackPlugin.push(
// new HardSourceWebpackPlugin({
// // 缓存目录,支持相对目录或绝对目录
// // 如果有设置VUE_APP_HARD_SOURCE_FOLDER目录则使用设置值
// // 一般在coding流水线编译使用把缓存设置到`/data/npm/`中,不会丢失
// cacheDirectory: `${
// (process.env.VUE_APP_HARD_SOURCE_FOLDER && path.join(process.env.VUE_APP_HARD_SOURCE_FOLDER, '/')) ||
// path.join(process.cwd(), 'node_modules', '/')
// }.cache/hard-source/[confighash]`,
// // 基于package.json中的name来生成不同的hash串用于cacheDirectory的目录
// // @param webpackConfig
// configHash(webpackConfig) {
// return require('node-object-hash')({ sort: false }).hash({ packageName, ...webpackConfig });
// },
// // 根据目录中的lock文件来决定是否重设缓存如果设置false则需要手动删除
// environmentHash: {
// root: process.cwd(),
// directories: [],
// files: ['package-lock.json', 'yarn.lock'],
// },
// info: {
// // 'none' or 'test'.
// mode: 'none',
// // 'debug', 'log', 'info', 'warn', or 'error'.
// level: 'debug',
// },
// // 自动清除过期、过大缓存
// cachePrune: {
// // 缓存时间默认7天
// maxAge: 7 * 24 * 60 * 60 * 1000,
// // 超过该处设置的阈值默认500MB则自动删除缓存
// sizeThreshold: 500 * 1024 * 1024,
// },
// }),
// new HardSourceWebpackPlugin.ExcludeModulePlugin([
// {
// // HardSource works with mini-css-extract-plugin but due to how
// // mini-css emits assets, assets are not emitted on repeated builds with
// // mini-css and hard-source together. Ignoring the mini-css loader
// // modules, but not the other css loader modules, excludes the modules
// // that mini-css needs rebuilt to output assets every time.
// test: /mini-css-extract-plugin[\\/]dist[\\/]loader/,
// },
// ]),
// );
// }
if (isExtract) {
configureWebpackPlugin.push(
@ -286,7 +286,7 @@ module.exports = {
target: 'http://carbon.liantu.tech',
changeOrigin: true,
},
'/mhzc': {
'^/mhzc': {
target: 'http://carbon.liantu.tech',
changeOrigin: true,
},