修改大屏模块
This commit is contained in:
310
README.md
310
README.md
@@ -1,207 +1,106 @@
|
|||||||
# 宁夏智慧畜牧大数据平台 - 官网展示系统
|
# 全国牛产业数据中心(website 子项目)
|
||||||
|
|
||||||
|
本仓库为“官网展示系统(website)”子项目,作为整个项目的入口页面与数据大屏,遵循中文文档与目录规范。其余文档请放置于 `docs/` 目录。
|
||||||
|
|
||||||
|
## 项目简介
|
||||||
|
|
||||||
|
全国牛产业大数据中心面向全国牛产业上下游(养殖、交易、监管、保险等)数据,提供统一的采集、治理与可视化能力。官网子项目承担门户与数据大屏展示,支持价格行情、预警监测、3D 地图态势与多维指标对比,面向领导查看与公众科普两类场景。
|
||||||
|
|
||||||
|
核心目标:
|
||||||
|
- 打通多源数据(国统局、行业报送、地方平台)并统一口径展示;
|
||||||
|
- 以可视化与可交互分析为主,强调直观、准确与性能;
|
||||||
|
- 保持 Windows 开发友好与 CentOS 生产部署稳定。
|
||||||
|
|
||||||
## 项目概述
|
## 项目概述
|
||||||
|
|
||||||
宁夏智慧畜牧大数据平台官网是一个现代化的数据可视化展示系统,基于Vue 3和Three.js技术栈构建。该系统提供3D地图展示、实时数据监控、养殖场管理和数据大屏可视化等功能,为宁夏地区的智慧畜牧业发展提供数字化支撑。
|
- 基于 Vue 3 + Vite 构建的可视化大屏,整合 3D 地图、图表与业务面板。
|
||||||
|
- 使用 Three.js 渲染 3D 地球与地图,ECharts 绘制数据图表。
|
||||||
## 核心功能
|
- 面向 Windows 开发环境与 CentOS 10(64位)部署环境。
|
||||||
|
|
||||||
### 🗺️ 3D地图可视化
|
|
||||||
- 基于Three.js的3D地球和地图展示
|
|
||||||
- 宁夏回族自治区地理边界可视化
|
|
||||||
- 养殖场地理位置标注和信息展示
|
|
||||||
- 交互式地图操作(缩放、旋转、点击)
|
|
||||||
|
|
||||||
### 📊 数据大屏展示
|
|
||||||
- 实时数据监控大屏
|
|
||||||
- 多维度数据图表展示
|
|
||||||
- 养殖业态势感知
|
|
||||||
- 预警信息集中展示
|
|
||||||
|
|
||||||
### 🏭 养殖场管理
|
|
||||||
- 养殖场基本信息展示
|
|
||||||
- 养殖规模和类型统计
|
|
||||||
- 联系方式和建立时间管理
|
|
||||||
- 点击弹窗详情查看
|
|
||||||
|
|
||||||
### 🎨 现代化UI设计
|
|
||||||
- 科技感十足的深色主题
|
|
||||||
- 流畅的动画效果
|
|
||||||
- 响应式布局设计
|
|
||||||
- 多页面导航系统
|
|
||||||
|
|
||||||
## 技术栈
|
## 技术栈
|
||||||
|
|
||||||
### 前端框架
|
前端与可视化:
|
||||||
- **Vue 3** - 渐进式JavaScript框架
|
- `vue@3` 组合式 API + 单文件组件。
|
||||||
- **Vite** - 现代化构建工具
|
- `vite@7` 开发与构建,快速热更新。
|
||||||
- **Vue Router** - 官方路由管理器
|
- `vue-router@4` 页面路由与导航。
|
||||||
- **Pinia** - 状态管理库
|
- `pinia@3` 轻量状态管理(如需全局状态时使用)。
|
||||||
|
- `echarts@5` + `vue-echarts@7` 图表组件封装(柱状、折线、饼图、环形进度等)。
|
||||||
|
- `three@0.179` 3D 场景渲染(地球、地图、光效)。
|
||||||
|
- `@jiaminghi/data-view` 大屏装饰与框架组件。
|
||||||
|
- 静态资源与纹理:`public/texture` 与 `public/data/map`。
|
||||||
|
|
||||||
### 3D可视化
|
工程工具:
|
||||||
- **Three.js** - 3D图形库
|
- `eslint` + `eslint-plugin-vue` 代码规范校验;`oxlint` 性能更优的静态检查。
|
||||||
- **CSS2DRenderer** - 2D标签渲染器
|
- `vite-plugin-vue-devtools` 调试与组件检查。
|
||||||
- **WebGL** - 硬件加速图形渲染
|
- `npm-run-all2` 脚本编排;`axios` 数据请求。
|
||||||
|
|
||||||
### 数据可视化
|
地图与空间:
|
||||||
- **ECharts** - 数据图表库
|
- 项目包含 `three` 地球/地图渲染能力;同时预置 `cesium` 与 `mapbox-gl` 以便后续扩展(当前未强依赖,可选接入)。
|
||||||
- **Vue-ECharts** - Vue集成组件
|
|
||||||
- **@jiaminghi/data-view** - 数据大屏组件
|
|
||||||
|
|
||||||
### 地图服务
|
后续扩展:
|
||||||
- **Mapbox GL** - 地图渲染引擎
|
- 管理后台(`admin-system`)、小程序(`mini-program`)、后端服务(`backend`)、官网(`website`)与脚本(`scripts`)模块协同,详见 `docs/` 架构与需求文档。
|
||||||
- **Cesium** - 3D地球可视化
|
|
||||||
- **GeoJSON** - 地理数据格式
|
|
||||||
|
|
||||||
### 开发工具
|
## 目录结构(关键)
|
||||||
- **ESLint** - 代码质量检查
|
|
||||||
- **Oxlint** - 高性能代码检查
|
|
||||||
- **TypeScript** - 类型定义支持
|
|
||||||
|
|
||||||
## 项目结构
|
|
||||||
|
|
||||||
```
|
```
|
||||||
website/
|
├── README.md # 项目入口文档(当前文件)
|
||||||
├── public/ # 静态资源
|
├── DASHBOARD_COLOR_UPDATE.md# 大屏调色与配色记录
|
||||||
│ ├── data/ # 地图数据文件
|
├── docs/ # 项目文档目录(见下方文档索引)
|
||||||
│ └── texture/ # 纹理贴图
|
├── public/ # 静态资源(地图数据、纹理等)
|
||||||
├── src/
|
├── src/
|
||||||
│ ├── components/ # Vue组件
|
│ ├── App.vue # 顶部导航与页面切换
|
||||||
│ │ ├── Map3D.vue # 3D地图主组件
|
│ ├── components/
|
||||||
│ │ ├── Home.vue # 首页组件
|
│ │ ├── Home.vue # 首页数据大屏
|
||||||
│ │ ├── Alert.vue # 预警监测组件
|
│ │ ├── Map3D.vue # 3D 地图
|
||||||
│ │ └── FarmPopup.vue # 养殖场弹窗组件
|
│ │ ├── Price.vue # 价格行情页
|
||||||
│ ├── hooks/ # 组合式API钩子
|
│ │ └── Alert.vue # 预警监测页
|
||||||
│ │ ├── useCoord.js # 坐标转换
|
│ ├── hooks/ # 组合式 API 工具
|
||||||
│ │ ├── useFileLoader.js # 文件加载
|
│ ├── assets/ # 静态资源
|
||||||
│ │ └── useCSS2DRender.js # 2D渲染
|
│ ├── utils/ # 工具函数
|
||||||
│ ├── utils/ # 工具函数
|
│ └── main.js # 应用入口
|
||||||
│ ├── assets/ # 静态资源
|
├── index.html
|
||||||
│ ├── App.vue # 根组件
|
├── package.json
|
||||||
│ └── main.js # 应用入口
|
└── vite.config.js
|
||||||
├── index.html # HTML模板
|
|
||||||
├── package.json # 项目配置
|
|
||||||
├── vite.config.js # Vite配置
|
|
||||||
└── README.md # 项目文档
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 快速开始
|
## 环境要求
|
||||||
|
|
||||||
### 环境要求
|
- Node.js ≥ 20.19.0(或 ≥ 22.12.0)
|
||||||
- Node.js >= 20.19.0 或 >= 22.12.0
|
- npm(或 yarn / pnpm)
|
||||||
- npm 或 yarn 包管理器
|
|
||||||
|
## 本地开发(Windows)
|
||||||
|
|
||||||
### 安装依赖
|
|
||||||
```bash
|
```bash
|
||||||
npm install
|
npm install
|
||||||
```
|
|
||||||
|
|
||||||
### 开发环境运行
|
|
||||||
```bash
|
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
访问 http://localhost:5173 查看应用
|
|
||||||
|
|
||||||
### 生产环境构建
|
- 终端会显示本地预览地址,例如:`http://localhost:5174/`(端口以实际输出为准)。
|
||||||
|
- 若端口占用,Vite 会自动切换到可用端口。
|
||||||
|
|
||||||
|
## 构建与预览
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build # 生产构建,输出到 dist/
|
||||||
|
npm run preview # 本地预览 dist/
|
||||||
```
|
```
|
||||||
|
|
||||||
### 预览构建结果
|
## 部署(CentOS 10 64位)
|
||||||
```bash
|
|
||||||
npm run preview
|
|
||||||
```
|
|
||||||
|
|
||||||
### 代码质量检查
|
1. 上传 `dist/` 到服务器目录(例如:`/var/www/cattle-datav`)。
|
||||||
```bash
|
2. Nginx 配置示例:
|
||||||
# 运行所有代码检查
|
|
||||||
npm run lint
|
|
||||||
|
|
||||||
# 仅运行ESLint检查
|
|
||||||
npm run lint:eslint
|
|
||||||
|
|
||||||
# 仅运行Oxlint检查
|
|
||||||
npm run lint:oxlint
|
|
||||||
```
|
|
||||||
|
|
||||||
## 主要特性
|
|
||||||
|
|
||||||
### 3D地图交互
|
|
||||||
- 鼠标拖拽旋转地球
|
|
||||||
- 滚轮缩放地图视角
|
|
||||||
- 点击养殖场标记查看详情
|
|
||||||
- 平滑的相机动画过渡
|
|
||||||
|
|
||||||
### 数据展示
|
|
||||||
- 实时养殖场数据更新
|
|
||||||
- 多种图表类型支持
|
|
||||||
- 响应式数据大屏
|
|
||||||
- 自定义主题配置
|
|
||||||
|
|
||||||
### 用户体验
|
|
||||||
- 流畅的页面切换动画
|
|
||||||
- 现代化的UI设计
|
|
||||||
- 移动端适配支持
|
|
||||||
- 无障碍访问优化
|
|
||||||
|
|
||||||
## 开发指南
|
|
||||||
|
|
||||||
### 添加新的养殖场数据
|
|
||||||
在 `src/components/Map3D.vue` 文件中的 `farmData` 数组中添加新的养殖场信息:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const farmData = [
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
name: '新养殖场',
|
|
||||||
position: [106.2081, 38.4681], // [经度, 纬度]
|
|
||||||
livestock: 15000,
|
|
||||||
area: '800亩',
|
|
||||||
type: '肉羊养殖',
|
|
||||||
established: '2023年',
|
|
||||||
contact: '张经理 138****1234'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
```
|
|
||||||
|
|
||||||
### 自定义地图样式
|
|
||||||
修改 `src/components/Map3D.vue` 中的材质和颜色配置:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// 修改地图边界线颜色
|
|
||||||
const lineMaterial = new THREE.LineBasicMaterial({
|
|
||||||
color: 0x00ffff, // 青色
|
|
||||||
linewidth: 2
|
|
||||||
});
|
|
||||||
|
|
||||||
// 修改养殖场标记颜色
|
|
||||||
const markerMaterial = new THREE.MeshBasicMaterial({
|
|
||||||
color: 0xff6b35 // 橙色
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 添加新的页面
|
|
||||||
1. 在 `src/components/` 目录下创建新的Vue组件
|
|
||||||
2. 在 `src/App.vue` 中注册组件和导航
|
|
||||||
3. 更新页面组件映射和导航菜单
|
|
||||||
|
|
||||||
## 部署说明
|
|
||||||
|
|
||||||
### 静态部署
|
|
||||||
构建完成后,将 `dist` 目录部署到任何静态文件服务器即可。
|
|
||||||
|
|
||||||
### Nginx配置示例
|
|
||||||
```nginx
|
```nginx
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name your-domain.com;
|
server_name your-domain.com; # 修改为你的域名或IP
|
||||||
root /path/to/dist;
|
root /var/www/cattle-datav; # 指向 dist 目录
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
|
||||||
expires 1y;
|
expires 1y;
|
||||||
add_header Cache-Control "public, immutable";
|
add_header Cache-Control "public, immutable";
|
||||||
@@ -209,30 +108,59 @@ server {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 贡献指南
|
3. 重新加载 Nginx:`sudo nginx -s reload`。
|
||||||
|
|
||||||
1. Fork 项目仓库
|
## 文档索引(docs/)
|
||||||
2. 创建功能分支 (`git checkout -b feature/AmazingFeature`)
|
|
||||||
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
|
文档均使用 Markdown 编写,并统一放置在 `docs/` 目录。建议按以下文件名组织:
|
||||||
4. 推送到分支 (`git push origin feature/AmazingFeature`)
|
|
||||||
5. 创建 Pull Request
|
- 需求文档:
|
||||||
|
- `整个项目需求文档.md`
|
||||||
|
- `官网需求文档.md`
|
||||||
|
- `后端管理需求文档.md`
|
||||||
|
- `管理后台需求文档.md`
|
||||||
|
- `小程序app需求文档.md`
|
||||||
|
- 架构文档:
|
||||||
|
- `整个项目的架构文档.md`
|
||||||
|
- `后端架构文档.md`
|
||||||
|
- `小程序架构文档.md`
|
||||||
|
- `管理后台架构文档.md`
|
||||||
|
- 详细设计文档:
|
||||||
|
- `数据库设计文档.md`
|
||||||
|
- `管理后台接口设计文档.md`
|
||||||
|
- `小程序app接口设计文档.md`
|
||||||
|
- 开发文档(细分到每个子任务的开发计划):
|
||||||
|
- `后端开发文档.md`
|
||||||
|
- `小程序app开发文档.md`
|
||||||
|
- `管理后台开发文档.md`
|
||||||
|
- `后端管理开发文档.md`
|
||||||
|
- 其他:`测试文档.md`、`部署文档.md`、`运维文档.md`、`安全文档.md`、`用户手册文档.md`
|
||||||
|
|
||||||
|
> 说明:本 README 作为项目入口文档;如需新增或更新详细说明,请在 `docs/` 中对应文件维护。
|
||||||
|
|
||||||
|
## 项目总结(阶段性)
|
||||||
|
|
||||||
|
本阶段完成内容:
|
||||||
|
- 首页大屏改版:新增“全国牛存栏量”与“全国牛出栏率”年度图表(含折线样式与统一主题配色)。
|
||||||
|
- 价格行情入口默认跳转至内蒙古数据页;地图 Top5 来源省份更新为“内蒙古/四川/河北”。
|
||||||
|
- 浏览器标签图标(favicon)替换为牛产业主题图标,统一品牌风格。
|
||||||
|
|
||||||
|
后续计划:
|
||||||
|
- 完成官网子项目与管理后台、后端、小程序的数据接口联调;
|
||||||
|
- 按 `docs/` 需求与架构文档迭代细分功能与测试用例;
|
||||||
|
- 强化安全与运维文档,完善监控与日志采集方案。
|
||||||
|
|
||||||
|
## 常见问题(FAQ)
|
||||||
|
|
||||||
|
- 预览地址端口与 README 不一致?以终端输出为准,Vite 会根据占用情况动态选择端口。
|
||||||
|
- 图表配色如何统一?参考 `DASHBOARD_COLOR_UPDATE.md`,并在 `Home.vue` 中的各图表 `option` 与数据源颜色字段进行维护。
|
||||||
|
- 地图数据加载失败?检查 `public/data/map` 路径与资源权限,确保部署路径与 Nginx `root` 对应。
|
||||||
|
|
||||||
## 许可证
|
## 许可证
|
||||||
|
|
||||||
本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情。
|
本项目采用 MIT 许可证。
|
||||||
|
|
||||||
## 联系方式
|
## 变更记录
|
||||||
|
|
||||||
- 项目维护者:开发团队
|
- 2025-01-18:初始化版本与大屏展示。
|
||||||
- 邮箱:dev@example.com
|
- 2025-01-XX:图表与配色优化、首页标题对齐与功能调整。
|
||||||
- 项目地址:https://github.com/your-org/nx-smart-livestock
|
|
||||||
|
|
||||||
## 更新日志
|
|
||||||
|
|
||||||
### v1.0.0 (2025-01-18)
|
|
||||||
- ✨ 初始版本发布
|
|
||||||
- 🗺️ 3D地图可视化功能
|
|
||||||
- 📊 数据大屏展示
|
|
||||||
- 🏭 养殖场管理系统
|
|
||||||
- 🎨 现代化UI设计
|
|
||||||
- 📱 响应式布局支持
|
|
||||||
|
|||||||
@@ -1,24 +1,23 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 64 64">
|
||||||
<!-- 背景圆形 -->
|
<defs>
|
||||||
<circle cx="16" cy="16" r="15" fill="#0c1426" stroke="#00d4ff" stroke-width="2"/>
|
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
||||||
|
<stop offset="0" stop-color="#0c1426"/>
|
||||||
<!-- 牛头轮廓 -->
|
<stop offset="1" stop-color="#0a2a3b"/>
|
||||||
<path d="M8 18 Q8 12 12 10 Q16 8 20 10 Q24 12 24 18 L22 20 Q20 22 16 22 Q12 22 10 20 Z" fill="#00d4ff" opacity="0.8"/>
|
</linearGradient>
|
||||||
|
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
|
||||||
<!-- 牛角 -->
|
<feGaussianBlur stdDeviation="2" result="blur"/>
|
||||||
<path d="M10 12 Q8 10 7 8" stroke="#00ffff" stroke-width="2" fill="none" stroke-linecap="round"/>
|
<feMerge>
|
||||||
<path d="M22 12 Q24 10 25 8" stroke="#00ffff" stroke-width="2" fill="none" stroke-linecap="round"/>
|
<feMergeNode in="blur"/>
|
||||||
|
<feMergeNode in="SourceGraphic"/>
|
||||||
<!-- 眼睛 -->
|
</feMerge>
|
||||||
<circle cx="13" cy="15" r="1.5" fill="#ffffff"/>
|
</filter>
|
||||||
<circle cx="19" cy="15" r="1.5" fill="#ffffff"/>
|
</defs>
|
||||||
|
<!-- 背景圆 -->
|
||||||
<!-- 鼻子 -->
|
<circle cx="32" cy="32" r="30" fill="url(#bg)" stroke="#00d4ff" stroke-width="2"/>
|
||||||
<ellipse cx="16" cy="18" rx="2" ry="1" fill="#ffffff" opacity="0.6"/>
|
<!-- 牛字标识 -->
|
||||||
|
<g fill="#ffffff" font-family="'Microsoft YaHei','Arial'" font-weight="800" text-anchor="middle" filter="url(#glow)">
|
||||||
<!-- 数据点装饰 -->
|
<text x="32" y="40" font-size="34">牛</text>
|
||||||
<circle cx="6" cy="8" r="1" fill="#00ffff" opacity="0.6"/>
|
</g>
|
||||||
<circle cx="26" cy="8" r="1" fill="#00ffff" opacity="0.6"/>
|
<!-- 亮边描边 -->
|
||||||
<circle cx="6" cy="24" r="1" fill="#00ffff" opacity="0.6"/>
|
<circle cx="32" cy="32" r="30" fill="none" stroke="rgba(0,212,255,0.35)" stroke-width="2"/>
|
||||||
<circle cx="26" cy="24" r="1" fill="#00ffff" opacity="0.6"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 950 B |
@@ -89,7 +89,7 @@ const navigateToWarningMonitor = (provinceName) => {
|
|||||||
<div class="nav-item" :class="{ active: currentPage === 'home' }" @click="switchPage('home')">
|
<div class="nav-item" :class="{ active: currentPage === 'home' }" @click="switchPage('home')">
|
||||||
<span>首页</span>
|
<span>首页</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-item" :class="{ active: currentPage === 'price' }" @click="switchPage('price')">
|
<div class="nav-item" :class="{ active: currentPage === 'price' }" @click="switchPage('price', 'NM')">
|
||||||
<span>价格行情</span>
|
<span>价格行情</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-item" :class="{ active: currentPage === 'alert' }" @click="switchPage('alert')">
|
<div class="nav-item" :class="{ active: currentPage === 'alert' }" @click="switchPage('alert')">
|
||||||
@@ -161,7 +161,7 @@ body {
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background: rgba(12, 20, 38, 0.7); /* 半透明深色遮罩 */
|
background: rgba(12, 20, 38, 0.45); /* 降低遮罩不透明度以提升整体亮度 */
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,7 +508,7 @@ body {
|
|||||||
overflow-y: auto; /* 允许垂直滚动 */
|
overflow-y: auto; /* 允许垂直滚动 */
|
||||||
overflow-x: hidden; /* 隐藏水平滚动条 */
|
overflow-x: hidden; /* 隐藏水平滚动条 */
|
||||||
pointer-events: auto; /* 确保侧边栏可以交互 */
|
pointer-events: auto; /* 确保侧边栏可以交互 */
|
||||||
background: rgba(12, 20, 38, 0.8);
|
background: rgba(12, 20, 38, 0.35); /* 降低透明度,使背景更通透 */
|
||||||
/* background: url('/data/map/1.png') no-repeat center center; */
|
/* background: url('/data/map/1.png') no-repeat center center; */
|
||||||
/* background-size: cover; */
|
/* background-size: cover; */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,87 +2,58 @@
|
|||||||
<div class="dashboard-container">
|
<div class="dashboard-container">
|
||||||
<!-- 左侧面板 -->
|
<!-- 左侧面板 -->
|
||||||
<aside class="dashboard-left">
|
<aside class="dashboard-left">
|
||||||
<!-- 不同品种牛出栏率统计模块 -->
|
<!-- 全国牛单价排行榜 -->
|
||||||
<div class="panel slaughter-panel">
|
<div class="panel price-ranking-panel">
|
||||||
<div class="panel-header">
|
<div class="panel-header">
|
||||||
|
<h3>全国牛单价排行榜(元/头)</h3>
|
||||||
<h3>不同品种牛出栏率统计</h3>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="price-table">
|
||||||
<div class="echarts-container">
|
<div class="price-table-header">
|
||||||
<v-chart
|
<div>序号</div>
|
||||||
ref="slaughterPieChart"
|
<div>省份</div>
|
||||||
class="slaughter-pie"
|
<div>品种</div>
|
||||||
:option="slaughterPieOption"
|
<div>单价(元/头)</div>
|
||||||
autoresize
|
|
||||||
/>
|
|
||||||
<v-chart
|
|
||||||
ref="slaughterBarChart"
|
|
||||||
class="slaughter-bar"
|
|
||||||
:option="slaughterBarOption"
|
|
||||||
autoresize
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="slaughter-legend">
|
<div v-for="(row, idx) in nationalPriceTableSortedRows" :key="row.id" class="price-table-row">
|
||||||
<div class="legend-item" v-for="s in slaughterSpeciesData" :key="s.key">
|
<div>{{ idx + 1 }}</div>
|
||||||
<span class="legend-color" :style="{ background: s.color }"></span>
|
<div>{{ row.province }}</div>
|
||||||
<span class="legend-label">{{ s.name }}</span>
|
<div>{{ row.breed }}</div>
|
||||||
|
<div class="price-bar-cell">
|
||||||
|
<div class="price-bar-track">
|
||||||
|
<div class="price-bar" :style="getPriceBarStyle(row.price)">
|
||||||
|
<span class="price-value on-bar">{{ formatPrice(row.price) }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 全国牛存栏量模块 -->
|
||||||
|
<div class="panel slaughter-panel">
|
||||||
|
<div class="panel-header">
|
||||||
|
<h3>全国牛存栏量</h3>
|
||||||
|
</div>
|
||||||
|
<div class="total-stock">
|
||||||
|
<div class="total-number">
|
||||||
|
<!-- <span class="currency">≈</span> -->
|
||||||
|
<!-- <span class="value">{{ nationalLivestockDisplay }}</span> -->
|
||||||
|
<!-- <span class="unit">头</span> -->
|
||||||
|
</div>
|
||||||
|
<div class="echarts-container">
|
||||||
|
<v-chart
|
||||||
|
ref="nationalLivestockYearChart"
|
||||||
|
class="national-livestock-year-chart"
|
||||||
|
:option="nationalLivestockYearOption"
|
||||||
|
autoresize
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div class="data-notes">
|
<div class="data-notes">
|
||||||
<div class="data-source">数据来源:行业估算(示例)。注:区间值展示按区间中值绘图,标签显示区间。</div>
|
<div class="data-source">数据来源:国家统计/行业估算(示例)。该值为全国牛总存栏量基准。</div>
|
||||||
<div v-if="validationMessageSlaughter" class="validation-message">{{ validationMessageSlaughter }}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 不同品种牛存栏率模块 -->
|
<!-- 已移除:不同品种年度总销售额柱状图模块 -->
|
||||||
<div class="panel livestock-panel">
|
|
||||||
<div class="panel-header">
|
|
||||||
|
|
||||||
<h3>不同品种牛存栏率</h3>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="echarts-container">
|
|
||||||
<v-chart
|
|
||||||
ref="livestockPieChart"
|
|
||||||
class="livestock-pie"
|
|
||||||
:option="livestockPieOption"
|
|
||||||
autoresize
|
|
||||||
/>
|
|
||||||
<v-chart
|
|
||||||
ref="livestockBarChart"
|
|
||||||
class="livestock-bar"
|
|
||||||
:option="livestockBarOption"
|
|
||||||
autoresize
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="livestock-legend">
|
|
||||||
<div class="legend-item" v-for="s in livestockSpeciesData" :key="s.key">
|
|
||||||
<span class="legend-color" :style="{ background: s.color }"></span>
|
|
||||||
<span class="legend-label">{{ s.name }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="data-notes">
|
|
||||||
<!-- <div class="total-annotation">全国牛总存栏量基准值:100,000,000头</div> -->
|
|
||||||
<!-- <div class="yak-note">牦牛全球占比:>90%,国内占比:16%</div> -->
|
|
||||||
<div class="data-source">数据来源:国家统计/行业估算(示例)。注:各品类统计口径可能不同,比例求和不一定为100%。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 不同品种年度总销售额柱状图模块 -->
|
|
||||||
<div class="panel sales-revenue-panel">
|
|
||||||
<div class="panel-header">
|
|
||||||
|
|
||||||
<h3>不同品种年度总销售额</h3>
|
|
||||||
</div>
|
|
||||||
<v-chart
|
|
||||||
ref="salesRevenueChart"
|
|
||||||
class="sales-revenue-chart"
|
|
||||||
:option="salesRevenueChartOption"
|
|
||||||
autoresize
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
@@ -96,42 +67,62 @@
|
|||||||
|
|
||||||
<!-- 右侧面板 -->
|
<!-- 右侧面板 -->
|
||||||
<aside class="dashboard-right">
|
<aside class="dashboard-right">
|
||||||
<!-- 地区-品种明细表 -->
|
<!-- 品种单价排行榜(替换原地区-品种明细) -->
|
||||||
<div class="panel detail-panel">
|
<div class="panel price-ranking-panel">
|
||||||
<div class="panel-header">
|
<div class="panel-header">
|
||||||
|
<h3>品种单价排行榜(元/头)</h3>
|
||||||
<h3>地区-品种明细</h3>
|
<select v-model="rightSelectedBreed" class="breed-selector">
|
||||||
|
<option v-for="b in rightBreedOptions" :key="b" :value="b">{{ b }}</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-table">
|
<div class="species-price-table">
|
||||||
<div class="detail-header">
|
<div class="species-price-table-header">
|
||||||
|
<div>序号</div>
|
||||||
|
<div>品种</div>
|
||||||
<div>地区</div>
|
<div>地区</div>
|
||||||
<div>存栏(头)</div>
|
|
||||||
<div>出售(头)</div>
|
|
||||||
<div>单价(元/头)</div>
|
<div>单价(元/头)</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-for="row in filteredDetailRows" :key="row.id" class="detail-row">
|
<div v-for="(row, idx) in speciesPriceTableSortedRows" :key="row.id" class="species-price-table-row">
|
||||||
|
<div>{{ idx + 1 }}</div>
|
||||||
|
<div>{{ row.breed }}</div>
|
||||||
<div>{{ row.region }}</div>
|
<div>{{ row.region }}</div>
|
||||||
<div>{{ row.stock }}</div>
|
<div>{{ formatPrice(row.price) }}</div>
|
||||||
<div>{{ row.sold }}</div>
|
|
||||||
<div>{{ row.price }}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 品种单价排行榜 -->
|
<!-- 全国省份单价排行榜(元/头) -->
|
||||||
<div class="panel price-panel" >
|
<div class="panel price-ranking-panel">
|
||||||
<div class="panel-header">
|
<div class="panel-header">
|
||||||
<h3>2025年主要品种牛单价趋势预测(元/公斤,活重)</h3>
|
<h3>全国省份单价排行榜(元/头)</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="price-content">
|
<div class="echarts-container">
|
||||||
<v-chart
|
<v-chart
|
||||||
class="price-chart"
|
ref="provincePriceRankingChart"
|
||||||
:option="priceRankingOption"
|
class="province-price-ranking-chart"
|
||||||
|
:option="nationalProvincePriceRankingOption"
|
||||||
autoresize
|
autoresize
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 全国牛出栏率模块(年度全国出栏总量) -->
|
||||||
|
<div class="panel livestock-panel">
|
||||||
|
<div class="panel-header">
|
||||||
|
<h3>全国牛出栏率</h3>
|
||||||
|
</div>
|
||||||
|
<div class="echarts-container">
|
||||||
|
<v-chart
|
||||||
|
ref="nationalSlaughterYearChart"
|
||||||
|
class="national-slaughter-year-chart"
|
||||||
|
:option="nationalSlaughterYearOption"
|
||||||
|
autoresize
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="data-notes">
|
||||||
|
<div class="data-source">全国出栏总量(单位:万头)。数据来源:国家统计/行业估算(示例)。</div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -145,6 +136,153 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 全国牛存栏量显示样式 */
|
||||||
|
.total-stock {
|
||||||
|
padding: 10px 5px;
|
||||||
|
}
|
||||||
|
.total-number {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
.total-number .currency {
|
||||||
|
color: #00ffff;
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.total-number .value {
|
||||||
|
color: #00ffcc;
|
||||||
|
font-size: 36px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
.total-number .unit {
|
||||||
|
color: #cfefff;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.national-livestock-year-chart {
|
||||||
|
width: 100%;
|
||||||
|
height: 190px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.national-slaughter-year-chart {
|
||||||
|
width: 100%;
|
||||||
|
height: 150px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.national-price-ranking-chart {
|
||||||
|
width: 100%;
|
||||||
|
height: 180px;
|
||||||
|
}
|
||||||
|
.province-price-ranking-chart {
|
||||||
|
width: 100%;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
.price-ranking-panel {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.price-ranking-panel .echarts-container {
|
||||||
|
height: auto;
|
||||||
|
padding: 0 0 5px 0; /* 左侧去掉内边距,整体更靠左 */
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 品种单价排行榜列表样式(右侧) */
|
||||||
|
.species-price-table {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 10px;
|
||||||
|
flex: 1; /* 自适应撑满当前面板剩余空间 */
|
||||||
|
min-height: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.species-price-table-header,
|
||||||
|
.species-price-table-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 0.7fr 1.2fr 1.4fr 1.2fr; /* 序号/品种/地区/单价 */
|
||||||
|
gap: 12px;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.species-price-table-header {
|
||||||
|
color: #84acf0;
|
||||||
|
border-bottom: 1px solid rgba(132, 172, 240, 0.2);
|
||||||
|
padding-bottom: 6px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.species-price-table-row {
|
||||||
|
color: #eaf7ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 全国牛单价排行榜表格样式 */
|
||||||
|
.price-table {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
/* 表格自适应增高,撑满左侧面板剩余空间 */
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.price-table-header,
|
||||||
|
.price-table-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 0.6fr 1fr 1.2fr 2fr;
|
||||||
|
gap: 12px;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.price-table-header {
|
||||||
|
color: #84acf0;
|
||||||
|
border-bottom: 1px solid rgba(132, 172, 240, 0.2);
|
||||||
|
padding-bottom: 6px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.price-table-row {
|
||||||
|
color: #eaf7ff;
|
||||||
|
}
|
||||||
|
/* 单价列条形图样式 */
|
||||||
|
.price-bar-cell {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.price-bar-track {
|
||||||
|
flex: 1;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 0;
|
||||||
|
background: transparent; /* 去掉背景色,仅保留条形图颜色 */
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.price-bar {
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 0 0 0 0; /* 去掉左侧圆角,仅保留右侧 */
|
||||||
|
background: #4e73df; /* 与图二一致的蓝色 */
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.price-value {
|
||||||
|
min-width: 86px;
|
||||||
|
text-align: right;
|
||||||
|
color: #eaf7ff;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
.price-value.on-bar {
|
||||||
|
min-width: unset;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
.dashboard-center {
|
.dashboard-center {
|
||||||
flex: 1; /* 中心区域保持基准宽度 */
|
flex: 1; /* 中心区域保持基准宽度 */
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
@@ -161,6 +299,13 @@
|
|||||||
max-width: 520px;
|
max-width: 520px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 左侧数据栏按列布局并占满视口高度 */
|
||||||
|
.dashboard-left {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
/* 中低分辨率下进一步缩小到70%,保证协调性 */
|
/* 中低分辨率下进一步缩小到70%,保证协调性 */
|
||||||
@media (max-width: 1366px) {
|
@media (max-width: 1366px) {
|
||||||
.dashboard-left,
|
.dashboard-left,
|
||||||
@@ -290,6 +435,9 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
// 右侧品种单价排行榜下拉选项与选中值
|
||||||
|
rightBreedOptions: ['安格斯','牦牛','黄牛','利木赞牛','鲁西牛','奶牛','肉牛','水牛','西门塔尔牛','夏洛莱牛','杂交牛','牛'],
|
||||||
|
rightSelectedBreed: '安格斯',
|
||||||
// 存栏率视图模式:percent 或 count
|
// 存栏率视图模式:percent 或 count
|
||||||
livestockViewMode: 'percent',
|
livestockViewMode: 'percent',
|
||||||
// 全国牛总存栏量基准值
|
// 全国牛总存栏量基准值
|
||||||
@@ -406,87 +554,147 @@ export default {
|
|||||||
],
|
],
|
||||||
slaughterPieOption: {},
|
slaughterPieOption: {},
|
||||||
slaughterBarOption: {},
|
slaughterBarOption: {},
|
||||||
// 不同品种牛存栏率两个独立图表配置(初始化为空,mounted时构建)
|
// 不同品种牛存栏率图表(已改为全国出栏率,此处不再使用)
|
||||||
livestockPieOption: {},
|
livestockPieOption: {},
|
||||||
livestockBarOption: {},
|
livestockBarOption: {},
|
||||||
|
|
||||||
|
// 全国牛出栏总量年度柱状图(单位:万头)
|
||||||
|
nationalSlaughterYearOption: {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||||
|
borderColor: '#00ffff',
|
||||||
|
borderWidth: 1,
|
||||||
|
textStyle: { color: '#ffffff' },
|
||||||
|
formatter: function(params) {
|
||||||
|
const p = params[0]
|
||||||
|
return `${p.axisValue}<br/>${p.marker}${p.seriesName}: ${p.value} 万头`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: { left: '12%', right: '8%', bottom: '12%', top: '18%' },
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: ['2020年','2021年','2022年','2023年','2024年'],
|
||||||
|
axisLine: { lineStyle: { color: '#00ffff' } },
|
||||||
|
axisLabel: { color: '#ffffff', fontSize: 10 }
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
name: '万头',
|
||||||
|
nameTextStyle: { color: '#00ffff', fontSize: 11 },
|
||||||
|
axisLine: { lineStyle: { color: '#00ffff' } },
|
||||||
|
axisLabel: { color: '#ffffff', fontSize: 10 },
|
||||||
|
splitLine: { lineStyle: { color: 'rgba(0,255,255,0.2)' } }
|
||||||
|
},
|
||||||
|
series: [{
|
||||||
|
name: '全国牛出栏总量',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 4,
|
||||||
|
data: [4565.45, 4707.43, 4839.91, 5023.48, 5098.70],
|
||||||
|
lineStyle: { color: '#00CDCD', width: 2 },
|
||||||
|
itemStyle: { color: '#00CDCD' },
|
||||||
|
areaStyle: { color: 'rgba(0,205,205,0.15)' },
|
||||||
|
label: { show: true, position: 'top', color: '#cfefff', fontSize: 10, formatter: '{c} 万头' }
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
|
||||||
// 品种单价趋势图配置(2025年主要品种牛,单位:元/公斤,活重)
|
// 全国牛存栏量年度柱状图(单位:万头)
|
||||||
priceRankingOption: {
|
nationalLivestockYearOption: {
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||||
borderColor: '#00ffff',
|
borderColor: '#00ffff',
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
textStyle: { color: '#ffffff' },
|
textStyle: { color: '#ffffff' },
|
||||||
formatter: function(params) {
|
formatter: function(params) {
|
||||||
let result = params[0].axisValue + '<br/>';
|
const p = params[0]
|
||||||
params.forEach(param => {
|
return `${p.axisValue}<br/>${p.marker}${p.seriesName}: ${p.value} 万头`
|
||||||
result += param.marker + param.seriesName + ': ' + param.value + ' 元/公斤<br/>';
|
}
|
||||||
});
|
},
|
||||||
return result;
|
grid: { left: '12%', right: '8%', bottom: '12%', top: '18%' },
|
||||||
}
|
xAxis: {
|
||||||
},
|
type: 'category',
|
||||||
legend: {
|
data: ['2020年','2021年','2022年','2023年','2024年'],
|
||||||
data: ['杂交改良牛(西门塔尔)', '地方黄牛(秦川牛等)', '高端肉牛(安格斯/和牛)'],
|
axisLine: { lineStyle: { color: '#00ffff' } },
|
||||||
textStyle: { color: '#fff', fontSize: 10 },
|
axisLabel: { color: '#ffffff', fontSize: 10 }
|
||||||
top: '5%',
|
},
|
||||||
itemWidth: 12,
|
yAxis: {
|
||||||
itemHeight: 8
|
type: 'value',
|
||||||
},
|
name: '万头',
|
||||||
grid: { top: '25%', right: '8%', bottom: '15%', left: '15%' },
|
nameTextStyle: { color: '#00ffff', fontSize: 11 },
|
||||||
xAxis: {
|
axisLine: { lineStyle: { color: '#00ffff' } },
|
||||||
type: 'category',
|
axisLabel: { color: '#ffffff', fontSize: 10 },
|
||||||
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
|
splitLine: { lineStyle: { color: 'rgba(0,255,255,0.2)' } }
|
||||||
name: '月份',
|
},
|
||||||
nameTextStyle: { color: '#00ffff', fontSize: 11 },
|
series: [{
|
||||||
axisLabel: { color: '#fff', fontSize: 10, rotate: 0 },
|
name: '全国牛存栏总量',
|
||||||
axisLine: { lineStyle: { color: '#00ffff' } },
|
type: 'bar',
|
||||||
splitLine: { show: false }
|
data: [ 9562, 9817, 10215, 10508, 10046],
|
||||||
},
|
barWidth: '40%',
|
||||||
yAxis: {
|
itemStyle: { color: '#00CDCD' },
|
||||||
type: 'value',
|
label: { show: true, position: 'top', color: '#cfefff', fontSize: 10, formatter: '{c} 万头' }
|
||||||
name: '单价(元/公斤)',
|
}]
|
||||||
nameTextStyle: { color: '#00ffff', fontSize: 11 },
|
},
|
||||||
axisLabel: { color: '#fff', fontSize: 10 },
|
|
||||||
axisLine: { lineStyle: { color: '#00ffff' } },
|
|
||||||
splitLine: { lineStyle: { color: 'rgba(0,255,255,0.2)' } },
|
// 已移除:2025年主要品种牛单价趋势预测配置
|
||||||
min: 25,
|
|
||||||
max: 90
|
// 全国牛单价排行榜表格数据
|
||||||
},
|
nationalPriceTableRows: [
|
||||||
series: [
|
{ id: 1, province: '河北省', breed: '安格斯牛', price: 14200 },
|
||||||
{
|
{ id: 2, province: '山东省', breed: '荷斯坦牛', price: 17000 },
|
||||||
name: '杂交改良牛(西门塔尔)',
|
{ id: 3, province: '江苏省', breed: '复洲黄牛', price: 14500 },
|
||||||
type: 'line',
|
{ id: 4, province: '浙江省', breed: '西门塔尔牛', price: 16800 },
|
||||||
data: [35, 36, 36, 35, 34, 33, 34, 36, 38, 40, 42, 44],
|
{ id: 5, province: '新疆维吾尔自治区', breed: '夏洛莱牛', price: 16500 },
|
||||||
lineStyle: { color: '#267EEF', width: 2 },
|
{ id: 6, province: '甘肃省', breed: '水牛', price: 17387 },
|
||||||
itemStyle: { color: '#267EEF' },
|
{ id: 7, province: '广东省', breed: '安格斯牛', price: 14200 },
|
||||||
symbol: 'circle',
|
{ id: 8, province: '广西壮族自治区', breed: '荷斯坦牛', price: 17000 },
|
||||||
symbolSize: 4,
|
{ id: 9, province: '湖南省', breed: '复洲黄牛', price: 14500 },
|
||||||
smooth: true
|
{ id: 10, province: '河南省', breed: '西门塔尔牛', price: 16800 }
|
||||||
},
|
],
|
||||||
{
|
|
||||||
name: '地方黄牛(秦川牛等)',
|
// 全国牛单价排行榜配置(单位:元/头)
|
||||||
type: 'line',
|
nationalPriceRankingOption: {
|
||||||
data: [70, 71, 70, 68, 66, 65, 66, 68, 72, 75, 78, 80],
|
backgroundColor: 'transparent',
|
||||||
lineStyle: { color: '#00CDCD', width: 2 },
|
tooltip: {
|
||||||
itemStyle: { color: '#00CDCD' },
|
trigger: 'axis',
|
||||||
symbol: 'circle',
|
axisPointer: { type: 'shadow' },
|
||||||
symbolSize: 4,
|
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||||
smooth: true
|
borderColor: '#00ffff',
|
||||||
},
|
borderWidth: 1,
|
||||||
{
|
textStyle: { color: '#ffffff' },
|
||||||
name: '高端肉牛(安格斯/和牛)',
|
formatter: function(params) {
|
||||||
type: 'line',
|
const p = params[0]
|
||||||
data: [80, 81, 80, 78, 76, 75, 76, 78, 82, 85, 86, 85],
|
return `${p.axisValue}<br/>${p.marker}${p.seriesName}: ${p.value} 元/头`
|
||||||
lineStyle: { color: '#42A2E1', width: 2 },
|
}
|
||||||
itemStyle: { color: '#42A2E1' },
|
},
|
||||||
symbol: 'circle',
|
grid: { left: '18%', right: '12%', bottom: '15%', top: '20%' },
|
||||||
symbolSize: 4,
|
xAxis: {
|
||||||
smooth: true
|
type: 'value',
|
||||||
}
|
name: '单价(元/头)',
|
||||||
]
|
nameTextStyle: { color: '#00ffff', fontSize: 11 },
|
||||||
|
axisLine: { lineStyle: { color: '#00ffff' } },
|
||||||
|
axisLabel: { color: '#ffffff', fontSize: 10 },
|
||||||
|
splitLine: { lineStyle: { color: 'rgba(0,255,255,0.2)' } }
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: ['荷斯坦牛','西门塔尔牛','夏洛莱牛','复洲黄牛','安格斯牛','水牛'],
|
||||||
|
axisLine: { lineStyle: { color: '#00ffff' } },
|
||||||
|
axisLabel: { color: '#ffffff', fontSize: 11 }
|
||||||
|
},
|
||||||
|
series: [{
|
||||||
|
name: '全国主要品种单价',
|
||||||
|
type: 'bar',
|
||||||
|
data: [17000, 16800, 16500, 14500, 14200, 17387],
|
||||||
|
barWidth: '45%',
|
||||||
|
itemStyle: { color: '#00CDCD' },
|
||||||
|
label: { show: true, position: 'right', color: '#cfefff', fontSize: 10, formatter: '{c} 元/头' }
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
|
|
||||||
// 地区-品种明细数据
|
// 地区-品种明细数据
|
||||||
@@ -510,7 +718,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 耳标佩戴统计堆叠柱状图配置
|
// 耳标佩戴统计堆叠柱状图配置
|
||||||
earTagChartOption: {
|
earTagChartOption: {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
axisPointer: {
|
axisPointer: {
|
||||||
@@ -660,97 +868,22 @@ export default {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
// 不同品种年度总销售额柱状图配置
|
// 已移除:不同品种年度总销售额柱状图配置
|
||||||
salesRevenueChartOption: {
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
|
||||||
borderColor: '#00ffff',
|
|
||||||
borderWidth: 1,
|
|
||||||
textStyle: {
|
|
||||||
color: '#ffffff'
|
|
||||||
},
|
|
||||||
formatter: '{a} <br/>{b}: {c}万元'
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
top: '15%',
|
|
||||||
right: '8%',
|
|
||||||
bottom: '15%',
|
|
||||||
left: '15%',
|
|
||||||
containLabel: true
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
data: ['安格斯牛', '荷斯坦牛', '夏洛莱牛', '西门塔尔牛', '利木赞牛', '其他品种'],
|
|
||||||
axisLabel: {
|
|
||||||
color: '#ffffff',
|
|
||||||
fontSize: 12,
|
|
||||||
rotate: 45
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#00ffff'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#00ffff'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
name: '销售额(万元)',
|
|
||||||
nameTextStyle: {
|
|
||||||
color: '#00ffff',
|
|
||||||
fontSize: 12
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
color: '#ffffff',
|
|
||||||
fontSize: 11
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#00ffff'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#00ffff'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: 'rgba(0, 255, 255, 0.2)'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '年度总销售额',
|
|
||||||
type: 'bar',
|
|
||||||
data: [
|
|
||||||
{ value: 28500, itemStyle: { color: '#00CDCD' } },
|
|
||||||
{ value: 22800, itemStyle: { color: '#869DB0' } },
|
|
||||||
{ value: 18600, itemStyle: { color: '#267EEF' } },
|
|
||||||
{ value: 15200, itemStyle: { color: '#42A2E1' } },
|
|
||||||
{ value: 12800, itemStyle: { color: '#3BF3D3' } },
|
|
||||||
{ value: 9600, itemStyle: { color: '#00CDCD' } }
|
|
||||||
],
|
|
||||||
barWidth: '60%',
|
|
||||||
emphasis: {
|
|
||||||
itemStyle: {
|
|
||||||
shadowBlur: 10,
|
|
||||||
shadowColor: '#00ffff'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
nationalLivestockCount() {
|
||||||
|
return this.livestockBaseline || 0
|
||||||
|
},
|
||||||
|
nationalLivestockDisplay() {
|
||||||
|
try {
|
||||||
|
return (this.nationalLivestockCount || 0).toLocaleString('zh-CN')
|
||||||
|
} catch (e) {
|
||||||
|
return String(this.nationalLivestockCount || 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
totalLivestock() {
|
totalLivestock() {
|
||||||
// 以数据源计算总存栏量(万头)
|
// 以数据源计算总存栏量(万头)
|
||||||
@@ -761,9 +894,97 @@ export default {
|
|||||||
return this.detailRows
|
return this.detailRows
|
||||||
}
|
}
|
||||||
return this.detailRows.filter(row => row.breed === this.selectedBreed)
|
return this.detailRows.filter(row => row.breed === this.selectedBreed)
|
||||||
|
},
|
||||||
|
// 品种单价排行榜(右侧)基于地区-品种明细,按价格升序
|
||||||
|
speciesPriceTableSortedRows() {
|
||||||
|
let rows = Array.isArray(this.detailRows) ? this.detailRows.map(r => ({
|
||||||
|
id: r.id,
|
||||||
|
breed: r.breed,
|
||||||
|
region: r.region,
|
||||||
|
price: r.price
|
||||||
|
})) : []
|
||||||
|
// 下拉选择生效:按包含关系过滤(处理“安格斯”匹配“安格斯牛”等)
|
||||||
|
if (this.rightSelectedBreed) {
|
||||||
|
rows = rows.filter(x => String(x.breed || '').includes(this.rightSelectedBreed))
|
||||||
|
}
|
||||||
|
rows.sort((a, b) => a.price - b.price)
|
||||||
|
return rows
|
||||||
|
},
|
||||||
|
// 全国省份单价排行榜(右侧图表):以 nationalPriceTableRows 为数据源,按单价升序
|
||||||
|
nationalProvincePriceRankingOption() {
|
||||||
|
const rows = Array.isArray(this.nationalPriceTableRows) ? [...this.nationalPriceTableRows] : []
|
||||||
|
rows.sort((a, b) => a.price - b.price)
|
||||||
|
const yCategories = rows.map(r => r.province)
|
||||||
|
const prices = rows.map(r => r.price)
|
||||||
|
return {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: { type: 'shadow' },
|
||||||
|
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||||
|
borderColor: '#00ffff',
|
||||||
|
borderWidth: 1,
|
||||||
|
textStyle: { color: '#ffffff' },
|
||||||
|
formatter: function(params) {
|
||||||
|
const p = params[0]
|
||||||
|
return `${p.axisValue}<br/>${p.seriesName}: ${p.value} 元/头`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: { left: '0%', right: '10%', bottom: '10%', top: '10%', containLabel: true },
|
||||||
|
xAxis: {
|
||||||
|
type: 'value',
|
||||||
|
name: '单价(元/头)',
|
||||||
|
nameTextStyle: { color: '#00ffff', fontSize: 11 },
|
||||||
|
axisLine: { lineStyle: { color: '#00ffff' } },
|
||||||
|
axisLabel: { color: '#ffffff', fontSize: 10 },
|
||||||
|
splitLine: { lineStyle: { color: 'rgba(0,255,255,0.2)' } }
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: yCategories,
|
||||||
|
axisLine: { lineStyle: { color: '#00ffff' } },
|
||||||
|
axisLabel: { color: '#ffffff', fontSize: 11 }
|
||||||
|
},
|
||||||
|
series: [{
|
||||||
|
name: '省份单价',
|
||||||
|
type: 'bar',
|
||||||
|
data: prices,
|
||||||
|
barWidth: '45%',
|
||||||
|
itemStyle: { color: '#4e73df' },
|
||||||
|
label: { show: true, position: 'right', color: '#cfefff', fontSize: 10, formatter: '{c} 元/头' }
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 单价条形图需要的最大值(用于计算宽度百分比)
|
||||||
|
priceBarMax() {
|
||||||
|
const arr = Array.isArray(this.nationalPriceTableRows) ? this.nationalPriceTableRows.map(r => r.price) : []
|
||||||
|
const max = Math.max(...arr, 1)
|
||||||
|
return max
|
||||||
|
},
|
||||||
|
// 单价升序排列后的行数据
|
||||||
|
nationalPriceTableSortedRows() {
|
||||||
|
const rows = Array.isArray(this.nationalPriceTableRows) ? [...this.nationalPriceTableRows] : []
|
||||||
|
rows.sort((a, b) => a.price - b.price)
|
||||||
|
return rows
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 格式化价格显示(千分位)
|
||||||
|
formatPrice(value) {
|
||||||
|
try {
|
||||||
|
return Number(value || 0).toLocaleString('zh-CN')
|
||||||
|
} catch (e) {
|
||||||
|
return String(value || 0)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 计算条形宽度样式
|
||||||
|
getPriceBarStyle(price) {
|
||||||
|
const max = this.priceBarMax || 1
|
||||||
|
const ratio = Math.max(0, Math.min(1, Number(price || 0) / max))
|
||||||
|
// 增强对比:非线性拉伸,最小5%,最大100%,采用幂函数放大差异
|
||||||
|
const percent = 5 + Math.pow(ratio, 0.6) * 95
|
||||||
|
return { width: `${percent.toFixed(2)}%` }
|
||||||
|
},
|
||||||
// 构建环形图(占比)
|
// 构建环形图(占比)
|
||||||
buildLivestockPieOption() {
|
buildLivestockPieOption() {
|
||||||
const baseline = this.livestockBaseline
|
const baseline = this.livestockBaseline
|
||||||
@@ -1236,7 +1457,7 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
gap: 10px; /* 两图间距约16px */
|
gap: 10px; /* 两图间距约16px */
|
||||||
height:230px;
|
height:190px;
|
||||||
padding: 0 5px 5px 5px;
|
padding: 0 5px 5px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1312,14 +1533,20 @@ export default {
|
|||||||
|
|
||||||
/* 出栏率统计样式 */
|
/* 出栏率统计样式 */
|
||||||
.slaughter-panel {
|
.slaughter-panel {
|
||||||
height: 330px;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
/* 与“全国牛存栏率”模块保持一致的自适应面板高度 */
|
||||||
|
flex: 0 0 auto;
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
.slaughter-panel .echarts-container {
|
.slaughter-panel .echarts-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
height: 200px;
|
/* 图表容器高度与“全国牛存栏率”模块一致 */
|
||||||
|
flex: 0 0 230px;
|
||||||
|
height: 230px;
|
||||||
}
|
}
|
||||||
.slaughter-pie {
|
.slaughter-pie {
|
||||||
flex: 0 0 42%;
|
flex: 0 0 42%;
|
||||||
@@ -1398,16 +1625,7 @@ export default {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* 品种单价排行榜样式 */
|
/* 已移除:品种单价排行榜样式 */
|
||||||
.price-panel .price-content {
|
|
||||||
height: 280px;
|
|
||||||
padding: 0 15px 10px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.price-chart {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 明细表样式 */
|
/* 明细表样式 */
|
||||||
.detail-table {
|
.detail-table {
|
||||||
@@ -1446,21 +1664,7 @@ export default {
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 销售额柱状图模块样式 */
|
/* 已移除:销售额柱状图模块样式 */
|
||||||
.sales-revenue-panel {
|
|
||||||
margin-top: 5px;
|
|
||||||
height: 280px; /* 缩小高度 */
|
|
||||||
background: rgba(0, 20, 40, 0.3);
|
|
||||||
border: 1px solid rgba(0, 212, 255, 0.2);
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sales-revenue-chart {
|
|
||||||
width: 100%;
|
|
||||||
height: calc(100% - 40px); /* 调整高度计算 */
|
|
||||||
margin-top: 15px; /* 添加上边距,将图表往下移 */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1504,7 +1708,7 @@ export default {
|
|||||||
border: 1px solid rgba(0, 212, 255, 0.4);
|
border: 1px solid rgba(0, 212, 255, 0.4);
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
padding: 4px 8px;
|
padding: 4px 4px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
@@ -1526,4 +1730,4 @@ export default {
|
|||||||
.data-source {
|
.data-source {
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: rgba(255, 255, 255, 0.7);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -58,11 +58,11 @@ export default {
|
|||||||
// const showPopup = ref(false);
|
// const showPopup = ref(false);
|
||||||
// const selectedFarmData = ref(null);
|
// const selectedFarmData = ref(null);
|
||||||
|
|
||||||
// 全国牛源地TOP5数据
|
// 全国牛源地TOP3数据(单位:万)
|
||||||
const cattleSourceTop5 = ref([
|
const cattleSourceTop5 = ref([
|
||||||
{ province: '广西', count: 760 },
|
{ province: '内蒙古', count: 1032 },
|
||||||
{ province: '云南', count: 247 },
|
{ province: '新疆', count: 849 },
|
||||||
{ province: '贵州', count: 186 },
|
{ province: '四川', count: 811 },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 重置
|
// 重置
|
||||||
@@ -1715,17 +1715,20 @@ export default {
|
|||||||
<style>
|
<style>
|
||||||
/* 地图容器样式 - 响应式设计 */
|
/* 地图容器样式 - 响应式设计 */
|
||||||
.map-3d-container {
|
.map-3d-container {
|
||||||
width: 100%;
|
position: fixed;
|
||||||
height: 100%;
|
top: 80px; /* 紧贴顶部标题栏,高度与 .dashboard-header 保持一致 */
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: calc(100vh - 80px);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
z-index: 0; /* 低于侧边栏与标题 */
|
||||||
}
|
}
|
||||||
|
|
||||||
#app-32-map {
|
#app-32-map {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 700px; /* 最大化增加最小高度 */
|
|
||||||
min-width: 900px; /* 最大化增加最小宽度 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 响应式设计 - 适应不同屏幕尺寸 */
|
/* 响应式设计 - 适应不同屏幕尺寸 */
|
||||||
@@ -1768,8 +1771,8 @@ export default {
|
|||||||
|
|
||||||
@media screen and (max-width: 768px) {
|
@media screen and (max-width: 768px) {
|
||||||
#app-32-map {
|
#app-32-map {
|
||||||
min-height: 500px;
|
width: 100%;
|
||||||
min-width: 600px;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.province-name-label {
|
.province-name-label {
|
||||||
@@ -2068,4 +2071,4 @@ export default {
|
|||||||
|
|
||||||
/* 移除养殖场标签样式 */
|
/* 移除养殖场标签样式 */
|
||||||
/* .farm-label { ... } */
|
/* .farm-label { ... } */
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default class Earth3d {
|
|||||||
container: null,
|
container: null,
|
||||||
width: window.innerWidth,
|
width: window.innerWidth,
|
||||||
height: window.innerHeight,
|
height: window.innerHeight,
|
||||||
bgColor: 0x000000,
|
bgColor: 0x0e2438, // 深蓝偏亮背景,替代纯黑以提升亮度
|
||||||
materialColor: 0xff0000,
|
materialColor: 0xff0000,
|
||||||
controls: {
|
controls: {
|
||||||
visibel: true, // 是否开启
|
visibel: true, // 是否开启
|
||||||
|
|||||||
Reference in New Issue
Block a user