ciyon_ai/aiskill/ciyon-数据大屏.md
2026-04-15 17:28:46 +08:00

1618 lines
40 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Ciyon 数据大屏开发指南
## 技术架构
### 技术栈
- **前端框架**ciybigscreen.js自定义大屏面板框架
- **数据可视化**ECharts
- **3D地图**Cesium
- **后端语言**PHP命名空间结构
- **辅助库**ciy.js通用工具库
### 目录结构
```
web/admin/demo/bs/
├── index.html # 大屏入口页面
├── index.php # 后端数据接口
└── b64/ # 图表组件JS文件
├── bank1_c1.js # 银行大屏-中心上部数字卡片
├── bank1_c2.js # 银行大屏-中心地图
├── bank1_l1.js # 银行大屏-左侧饼图
├── farm1_bg_cemap.js # 农场大屏-3D地图背景
└── ... # 其他组件
```
---
## 核心开发模式
### bigpanel 面板系统
**核心对象**`ciyclass.bigpanel`
```javascript
// 创建面板
var chtpls = {};
chtpls['bank1'] = new ciyclass.bigpanel({
name: 'panel_bank1', // 面板唯一标识
jspath: './b64/', // 组件JS文件路径
style: 'position:absolute;top:4em;left:5px;right:5px;bottom:20px;',
animation: 'ani1', // 动画效果
mask: '' // 遮罩层颜色
});
```
**关键方法**
| 方法 | 说明 | 示例 |
|------|------|------|
| `addplot(opn)` | 添加图表组件 | `addplot({jsname: 'bank1_c1', style: '...'})` |
| `run(fsec)` | 启动数据轮询 | `run({'bank_c1': 50})` // 50秒刷新一次 |
| `setbtns(opn)` | 设置关闭按钮 | `setbtns({template: 'close1'})` |
| `resize()` | 窗口大小改变时调用 | 自动调用所有组件的resize方法 |
| `distory()` | 销毁面板 | 清理所有组件和定时器 |
---
### 图表组件开发规范
每个图表组件是一个独立的JS文件必须遵循以下规范
**文件命名**`{面板名}_{位置标识}.js`
- 位置标识:`c1`(中上)、`c2`(中)、`l1`(左上)、`l2`(左中)、`l3`(左下)、`r1`(右上)、`r2`(右中)、`r3`(右下)
**基本结构**
```javascript
function ciy_chart_bank1_c1(opdata) {
var thos = this;
// 必须定义:指定需要调用的后端接口
this.func = ['bank_c1'];
// 组件变量
this.lastdata = {};
var chart1 = null; // ECharts实例
// 必须实现:数据设置方法
this.setdata = function (funame, data) {
if (!data) return;
this.lastdata[funame] = data;
// 更新DOM元素
$5('[data-num="n1"]', opdata.container).text(data.n1);
// 或更新ECharts图表
chart1.setOption({...});
}
// 必须实现:响应窗口大小变化
this.resize = function () {
if (chart1) chart1.resize();
}
// 必须实现:清理资源
this.distory = function () {
if (chart1) chart1.dispose();
clearInterval(timer);
}
// 组件初始化添加DOM结构
opdata.container.append(`
<div id="chart1" style="height:100%;"></div>
`);
// 初始化ECharts
chart1 = echarts.init($5('#chart1', opdata.container)[0], 'dark');
chart1.setOption(option);
}
```
**关键属性**
| 属性 | 说明 | 示例 |
|------|------|------|
| `this.func` | 需要调用的后端接口数组 | `['bank_c1', 'bank_c2']` |
| `this.prefunc` | 接口前缀(可选) | `'farm_'` |
| `opdata.container` | 组件容器DOM | 用于添加子元素 |
---
### 后端接口开发规范
**PHP类结构**
```php
<?php
namespace web\admin\demo\bs;
class index {
// 初始化接口
public static function json_init() {
$ret['title'] = '演示大屏';
$ret['orgid'] = 1;
return succjson($ret);
}
// 图表数据接口:命名规则 json_{面板名}_{图表名}
public static function json_bank_c1() {
$ret['n1'] = '11,303.2';
$ret['n2'] = '9,395.1';
$ret['n3'] = '53';
$ret['name'] = '中国农业银行';
return succjson($ret);
}
// 复杂数据:返回数组
public static function json_bank_l1() {
$ret['pie'] = array();
for ($i = 1; $i < 4; $i++) {
$ret['pie'][] = array(
'id' => $i,
'name' => '风控' . $i,
'value' => rand(100, 300)
);
}
return succjson($ret);
}
}
```
**命名规范**
- 方法名:`json_{面板名}_{图表名}`
- 返回格式:使用 `succjson($ret)` 统一返回JSON
- 数据结构:简单类型、数组、对象均可
---
## 数据流机制
### 轮询机制
```javascript
// 面板启动时设置刷新频率单位0.5秒)
chtpls['bank1'].run({
'bank_c1': 50, // 每25秒刷新一次
'bank_c2': 10, // 每5秒刷新一次
'bplant': 50 // 每25秒刷新一次
});
```
### 数据请求流程
```
1. bigpanel.run() 启动定时器500ms间隔
2. 检查每个func的倒计时
3. 倒计时为0时调用 ciyfn.callfunc()
4. 请求后端POST json_{func}
5. 返回JSON数据
6. 调用对应组件的 setdata(funame, data)
7. 组件更新DOM或图表
8. 重置倒计时
```
### 跨组件数据共享
```javascript
// 全局数据对象
var Glob = {
post: {}, // 传递给后端的公共参数
bet: 1, // 屏幕缩放比例
fontsize: 14 // 字体大小
};
// 设置公共参数
ciyfn.callfunc('init', {}, function (json) {
Glob.post.orgid = json.orgid;
Glob.myparam = { title: json.title };
});
// 组件内使用
// 后端接口会自动合并 Glob.post 和 thos.post
```
---
## 常用组件类型
### 数字卡片组件
```javascript
// bank1_c1.js
function ciy_chart_bank1_c1(opdata) {
this.func = ['bank_c1'];
this.setdata = function (funame, data) {
$5('[data-num="n1"]', opdata.container).text(data.n1);
$5('[data-num="n2"]', opdata.container).text(data.n2);
$5('[data-bank]', opdata.container).text(data.name);
}
opdata.container.append(`
<div class="num" data-num="n1">--</div>
<div class="title">贷款金额 (万元)</div>
`);
}
```
### ECharts饼图组件
```javascript
// bank1_l1.js
function ciy_chart_bank1_l1(opdata) {
this.func = ['bank_l1'];
var chart1 = null;
this.setdata = function (funame, data) {
var option = {
series: [{
type: 'pie',
radius: ['25%', '40%'],
data: data.pie
}]
};
chart1.setOption(option);
}
opdata.container.append('<div id="chart1"></div>');
chart1 = echarts.init($5('#chart1')[0], 'dark');
// 自动高亮动画
var idx = -1;
setInterval(function () {
chart1.dispatchAction({ type: 'highlight', dataIndex: idx });
idx = (idx + 1) % data.pie.length;
}, 2200);
}
```
### Cesium地图组件
```javascript
// bank1_c2.js
function ciy_chart_bank1_c2(opdata) {
this.func = ['bank_c2'];
var thos = this;
var ce = null;
this.setdata = function (funame, data) {
if (ce) return; // 只初始化一次
ce = new ciyearth();
ce.init({
domid: 'map1',
wmts_source: 4,
wmts_style: 2
});
// 添加标记点
for (var i in data.bplants) {
var marker = ce.addmarker({
lat: data.bplants[i].lat,
lng: data.bplants[i].lng,
img: '/ud/bill/map' + data.bplants[i].cmcode + '.png'
});
marker.ciydata = data.bplants[i];
}
// 点击事件
ce.ciyevent = function (type, act, data) {
if (type == 'entity' && act == 'leftclick') {
showfarm(data.entity.ciydata);
}
};
}
this.distory = function () {
if (ce) ce.destroy();
}
opdata.container.append('<div id="map1"></div>');
}
```
### 图片轮播组件
```javascript
function ciy_chart_farm_l3(opdata) {
this.func = ['farm_l3'];
var thos = this;
var cyc = null;
this.setdata = function (funame, data) {
var imgs = data.farm.picszz.split('~');
cyc = new ciyclass.bigcychange({
values: imgs,
cycsec: 5,
changecb: function (img) {
$5('img', opdata.container).attr('src', img);
}
});
}
this.distory = function () {
if (cyc) cyc.distory();
}
opdata.container.append('<img src="" style="width:100%;height:100%;">');
}
```
---
## 高级功能
### 弹窗面板
```javascript
function showvideo(mas) {
var chtname = 'video1';
chtpls[chtname] = new ciyclass.bigpanel({
name: 'panel_' + chtname,
jspath: './b64/',
animation: 'small',
style: 'position:absolute;top:50px;left:50px;right:50px;bottom:50px;z-index:2010;'
});
chtpls[chtname].post = { videoid: mas.id, img: mas.capture };
chtpls[chtname].addplot({
jsname: chtname + '_c1',
style: 'position:absolute;left:1em;right:1em;bottom:1em;top:5em;'
});
chtpls[chtname].setbtns({ template: 'close1', hideopacity: 0.8 });
chtpls[chtname].run({});
}
```
### 地图弹窗提示
```javascript
this.showpopup = function (html, pos) {
if (thos.popup) thos.popup.remove();
var oset = $5(opdata.container).offset();
thos.popup = $5('<div class="popup-box"><div class="box">' + html + '</div><div class="line"></div><div class="rlc"></div></div>');
thos.popup.css({
top: pos.y - oset.top,
left: pos.x - oset.left,
opacity: 1
});
opdata.container.append(thos.popup);
}
```
### 屏幕自适应
```javascript
// 设置基准分辨率
ciyfn.big_resolution(1536, 864);
ciyfn.big_setbetsize(1536);
// 响应窗口大小变化
window.addEventListener("resize", function () {
ciyfn.big_setbetsize(1536);
for (var ipl in chtpls) {
chtpls[ipl].resize();
}
});
```
---
## 开发最佳实践
### 性能优化
1. **减少重复初始化**
```javascript
this.setdata = function (funame, data) {
if (ce) return; // 地图只初始化一次
// ...初始化代码
}
```
2. **使用全局缩放比例**
```javascript
var option = {
fontSize: 18 * Glob.bet, // 根据屏幕缩放
borderRadius: 4 * Glob.bet
};
```
3. **及时清理定时器**
```javascript
this.distory = function () {
clearInterval(t_autohight);
if (chart1) chart1.dispose();
}
```
### 样式规范
```css
/* 渐变文字 */
background: linear-gradient(to bottom, #ffffff, #50c4eb 60%);
background-clip: text;
-webkit-background-clip: text;
color: transparent;
/* 动画 */
@keyframes opa {
0% { opacity: 1; }
10% { opacity: 0.5; }
20% { opacity: 1; }
}
/* 弹窗样式 */
.popup-box {
position: absolute;
z-index: 999;
transform: translateX(-50%) translateY(-100%);
pointer-events: none;
transition: all 0.5s;
}
```
### 调试技巧
```javascript
// 开发模式
if (urlp.dev) {
console.log('组件名称', data);
// ...调试代码
}
// 查看当前刷新频率
console.log(funcsecs); // 查看所有接口的倒计时
// 手动刷新所有组件
setdata();
```
---
## 常见问题
### Q1: 组件不显示数据?
**检查**
1. `this.func` 数组是否正确
2. 后端接口命名是否匹配 `json_{func}`
3. `setdata()` 方法是否正确处理数据
### Q2: 地图不显示?
**检查**
1. 容器是否有高度:`style="height:100%"`
2. 初始化前是否已添加DOM
3. Cesium资源是否加载`/zces108/Cesium.js`
### Q3: 窗口调整后图表变形?
**解决**
```javascript
window.addEventListener("resize", function () {
chtpls[ipl].resize(); // 调用每个面板的resize
});
```
### Q4: 数据刷新太频繁?
**调整**
```javascript
chtpls['bank1'].run({
'bank_c1': 100 // 增加刷新间隔单位0.5秒)
});
```
---
## 开发流程
### 新建大屏步骤
1. **创建目录和文件**
```
web/admin/demo/bs/
├── index.html
├── index.php
└── b64/
```
2. **编写 index.html**
- 引入必要JS库
- 创建 `ciyclass.bigpanel`
- 添加图表组件
3. **编写 index.php**
- 创建 `json_init()` 接口
- 为每个组件创建数据接口
4. **开发组件JS文件**
- 实现 `setdata()`、`resize()`、`distory()`
- 添加DOM结构
- 初始化ECharts或其他库
5. **测试调试**
- 使用 `urlp.dev` 开发模式
- 检查数据流
- 优化性能
---
## 参考资源
### 技术文档
- ECharts: https://echarts.apache.org/
- Cesium: https://cesium.com/
- jQuery: https://jquery.com/
### 内部资源
- 样式文件:`/jscss/style.css`
- 大屏样式:`/ud/bigscreen/bigscr.css`
- 图片资源:`/ud/bigscreen/`
- 字体资源:`/ud/bigscreen/`
### 示例代码
- 银行大屏:`web/admin/demo/bs/`
- 参考组件:`b64/bank1_*.js`
---
## bigscreen CSS 资源详解
### 目录结构
```
/web/ud/bigscreen/
├── bigscr.css # 大屏核心样式文件
├── bg/ # 背景图片bg01.png - bg04.png
├── border/ # 边框图片34种通用边框 + 4种文本边框
├── caption/ # 标题样式11种大标题 + 1种底部样式
├── cir/ # 圆形装饰
├── font/ # 字体文件15种
├── fontweb/ # Web字体
├── icon/ # 图标
├── orn/ # 装饰元素
└── tit/ # 小标题6种
```
### 字体资源15种
#### 中文/装饰字体7种
| 字体名 | 文件路径 | 用途场景 | 推荐使用 |
|--------|----------|----------|----------|
| `fnt01` | font/fnt01.ttf | 大屏主标题cap02, cap06, cap07, cap09, cap10, cap11 | ⭐⭐⭐⭐⭐ |
| `fnt02` | font/fnt02.ttf | 中等标题cap03, cap05 | ⭐⭐⭐⭐ |
| `fnt03` | fontweb/fnt03.ttf | 网页特殊字体 | ⭐⭐⭐ |
| `fnt04-fnt07` | font/fnt04~07.ttf | 装饰字体备用 | ⭐⭐ |
#### 小标题字体4种
| 字体名 | 文件路径 | 格式 |
|--------|----------|------|
| `xt01` | font/xt01.ttf | .ttf |
| `xt02` | font/xt02.otf | .otf |
| `xt03` | font/xt03.otf | .otf |
| `xt04` | font/xt04.ttf | .ttf |
#### 英文/数字字体2种
| 字体名 | 文件路径 | 用途 | 推荐使用 |
|--------|----------|------|----------|
| `eng01` | font/eng01.ttf | 英文/数字1 | ⭐⭐⭐ |
| `eng02` | font/eng02.ttf | 英文/数字2数字卡片常用 | ⭐⭐⭐⭐⭐ |
#### 黑体系列3种
| 字体名 | 文件路径 | 粗细 |
|--------|----------|------|
| `hs-bold` | font/hs-bold.ttf | 粗体 |
| `hs-light` | font/hs-light.ttf | 细体 |
| `hs-normal` | font/hs-normal.ttf | 常规 |
**使用示例**
```css
/* 大屏标题 */
font-family: fnt01;
/* 数字卡片 */
font-family: eng02;
font-size: 1.8em;
letter-spacing: 4px;
/* 复合标题 */
font-family: SimHei, STHeiti, 黑体;
```
### 背景样式4种
| 类名 | 背景图片 | 渐变配色 | 适用场景 |
|------|----------|----------|----------|
| `.bd01` | bg/bg01.png | `radial-gradient(#232f5a, #232f5a)` | 通用深蓝大屏 |
| `.bd02` | bg/bg02.png | `radial-gradient(#232f5a, #0b1121)` | 深蓝+黑色渐变 |
| `.bd03` | bg/bg03.png | `radial-gradient(#232f5a, #0b1121)` | 备用深色背景 |
| `.bd04` | bg/bg04.png | `radial-gradient(#092b46, #041320)` | 现代海蓝色 ⭐ |
**共同特性**
- `height: 100vh`
- `color: #ffffff`
- 背景图片设置为 `repeat` 重复平铺
**使用示例**
```html
<body class="bd04">
<!-- 大屏内容 -->
</body>
```
### 边框样式38种
#### 通用边框34种
| 类名 | 切割值 | 边框宽度 | 内边距 | 重复模式 | 背景色 | 推荐度 |
|------|--------|----------|--------|----------|--------|--------|
| `.brimg01` | 15 22 19 16 | 15px 22px 19px 16px | 10px 15px 15px 10px | - | - | ⭐⭐⭐⭐ |
| `.brimg02` | 15 21 20 16 | 15px 21px 20px 16px | 10px 15px 15px 10px | - | - | ⭐⭐⭐⭐ |
| `.brimg03` | 13 13 13 13 | 13px 13px 13px 13px | 10px 10px | - | `#00000011` | ⭐⭐⭐ |
| `.brimg04` | 103 168 103 168 | 103px 168px 103px 168px | 10px 10px | - | - | ⭐⭐ |
| `.brimg05` | 97 76 97 76 | 97px 76px 97px 76px | 15px | - | - | ⭐⭐ |
| `.brimg10` | 14 | 14px | 8px | - | `#00000011` | ⭐⭐⭐ |
| `.brimg21` | 50 28 50 28 | 50px 28px 50px 28px | 3px 8px 3px 8px | - | `transparent` | ⭐⭐⭐ |
| `.brimg33` | 315 315 315 315 | 315px 315px 315px 315px | 7px | - | `transparent` | ⭐⭐ |
| `.brimg34` | 20 21 20 21 | 20px 21px 20px 21px | 7px | - | `#00000011` | ⭐⭐⭐⭐⭐ |
**推荐使用**
- `.brimg34` - 常用边框(地图容器常用)⭐⭐⭐⭐⭐
- `.brimg03` / `.brimg10` / `.brimg19` - 简薄边框(带半透明背景)⭐⭐⭐
- `.brimg21` / `.brimg23` / `.brimg24` / `.brimg25` - 透明边框⭐⭐⭐
#### 文本边框4种
| 类名 | 切割值 | 边框宽度 | 内边距 | 特色 |
|------|--------|----------|--------|------|
| `.brtxt01` | 2 23 22 23 | 2px 23px 22px 23px | 3px 10px | 红色警告边框,字体加粗 |
| `.brtxt02` | 35 60 35 60 | 35px 60px 35px 60px | 10px 20px | 装饰文本边框1 |
| `.brtxt03` | 30 54 30 54 | 30px 54px 30px 54px | 10px 20px | 装饰文本边框2 |
| `.brtxt04` | 31 93 31 71 | 31px 93px 31px 71px | 10px 20px | 装饰文本边框3 |
**brtxt01 特有样式**
```css
background: #ff000029;
color: #cc0000;
text-shadow: 1px 1px 0 #000000;
font-weight: bold;
```
**使用示例**
```html
<!-- 常用边框 -->
<div class="brimg34" style="padding:2px;">
<div id="map1" style="height:100%;"></div>
</div>
<!-- 薄边框 -->
<div class="brimg03" style="padding:10px;">
<div id="chart1" style="height:100%;"></div>
</div>
<!-- 警告文本 -->
<div class="brtxt01">警告信息</div>
```
### 标题样式11种大标题 + 1种底部样式
#### 大标题11种
| 类名 | 高度 | 最小宽度 | 字体 | 渐变色 | 特色 | 推荐度 |
|------|------|----------|------|--------|------|--------|
| `.cap01` | 100px | 1000px | 默认 | 白→白70%→青 | 倒影效果 | ⭐⭐⭐⭐ |
| `.cap02` | 50px | 1200px | fnt01 | 白→浅蓝 | 简洁大标题 | ⭐⭐⭐⭐ |
| `.cap03` | 40px | 1000px | fnt02 | 白30%→深蓝 | 紧凑标题 | ⭐⭐⭐ |
| `.cap04` | 40px | 1000px | 默认 | 白→浅蓝 | 线条装饰 | ⭐⭐⭐ |
| `.cap05` | 40px | 1000px | fnt02 | 白→青色 | 青色渐变 | ⭐⭐⭐ |
| `.cap06` | 120px | 1200px | fnt01 | 白→青色 | 大标题带装饰 | ⭐⭐⭐ |
| `.cap07` | 80px | 1600px | fnt01 | 白→青色 | 超宽标题 | ⭐⭐⭐ |
| `.cap08` | 65px | 900px | SimHei | - | 复合标题h1+h2 | ⭐⭐⭐⭐ |
| `.cap09` | 48px | 1300px | fnt01 | 白→浅蓝60% | 倒影效果 | ⭐⭐⭐⭐⭐ |
| `.cap10` | 42px | 950px | fnt01 | 深蓝→白50% | 蓝白渐变 | ⭐⭐⭐⭐ |
| `.cap11` | 60px | 1260px | fnt01 | 白→浅蓝50% | 双行标题h1+h2 | ⭐⭐⭐⭐ |
**通用标题样式**
```css
background-clip: text;
-webkit-background-clip: text;
color: transparent;
text-align: center;
```
**倒影效果**cap01, cap09
```css
-webkit-box-reflect: below -35px -webkit-linear-gradient(transparent, transparent 20%, rgba(0,0,0,0.23));
```
#### 底部样式1种
| 类名 | 高度 | 背景 | 对齐 |
|------|------|------|------|
| `.btm01` | 20px | btm01.png底部居中 | 居中 |
**使用示例**
```html
<!-- 推荐标题:带倒影大标题 -->
<div class="cap09">
<div data-title>数据大屏标题</div>
</div>
<!-- 简洁大标题 -->
<div class="cap02">
<div>简洁标题</div>
</div>
<!-- 复合标题 -->
<div class="cap08">
<h1>主标题</h1>
<h2>副标题</h2>
</div>
<!-- 底部装饰 -->
<div class="btm01">
<div>底部文字</div>
</div>
```
### 小标题样式6种
| 类名 | 高度 | 左边距 | 最小宽度 | 背景图 |
|------|------|--------|----------|--------|
| `.tit05` | 30px | 50px | 230px | tit/05.png左上角 |
```css
.tit05 {
height: 30px;
display: inline-block;
padding: 4px 0 0 50px;
min-width: 230px;
background: url(./tit/05.png) top left no-repeat;
background-size: contain;
}
```
### 动画效果1种
#### 立方体展开动画
```css
@keyframes ani01_cube {
0% {
transform: scale(0) rotate(0deg) translate(-50%, -50%);
opacity: 0.2;
}
5% {
transform: scale(50) rotate(660deg) translate(-50%, -50%);
opacity: 0;
}
100% {
transform: scale(50) rotate(660deg) translate(-50%, -50%);
opacity: 0;
}
}
.ani01 li {
position: absolute;
top: 50vh;
left: 50vw;
width: 10px;
height: 10px;
border: solid 1px #0039ad;
color: transparent;
transform-origin: top left;
transform: scale(0) rotate(0deg) translate(-50%, -50%);
animation: ani01_cube 20s ease-in forwards infinite;
}
```
**效果**:屏幕中心的边框立方体快速放大旋转消失,形成炫酷的展开效果
### 全局基础样式
```css
* {
user-select: none; /* 禁止文本选择 */
-webkit-user-select: none;
}
span {
vertical-align: middle; /* span垂直居中 */
}
img {
vertical-align: middle; /* 图片垂直居中 */
}
```
### 资源速查表
**字体选择**
```css
font-family: fnt01; /* 大屏主标题 ⭐⭐⭐⭐⭐ */
font-family: fnt02; /* 中等标题 ⭐⭐⭐⭐ */
font-family: eng02; /* 数字展示 ⭐⭐⭐⭐⭐ */
font-family: SimHei; /* 复合标题cap08 ⭐⭐⭐⭐ */
```
**背景选择**
```html
<body class="bd04"> <!-- 推荐:现代海蓝色 ⭐⭐⭐⭐⭐ -->
<body class="bd01"> <!-- 通用深蓝 ⭐⭐⭐⭐ -->
<body class="bd02"> <!-- 深蓝+黑 ⭐⭐⭐ -->
<body class="bd03"> <!-- 备用深色 ⭐⭐⭐ -->
```
**边框选择**
```html
<div class="brimg34"> <!-- 推荐:常用边框 ⭐⭐⭐⭐⭐ -->
<div class="brimg03"> <!-- 薄边框+半透明背景 ⭐⭐⭐ -->
<div class="brimg21"> <!-- 透明边框 ⭐⭐⭐ -->
<div class="brtxt01"> <!-- 红色警告文本框 ⭐⭐⭐ -->
```
**标题选择**
```html
<div class="cap09"> <!-- 推荐:带倒影大标题 ⭐⭐⭐⭐⭐ -->
<div class="cap01"> <!-- 倒影效果 ⭐⭐⭐⭐ -->
<div class="cap02"> <!-- 简洁大标题 ⭐⭐⭐⭐ -->
<div class="cap08"> <!-- 复合标题 ⭐⭐⭐⭐ -->
<div class="btm01"> <!-- 底部装饰 ⭐⭐⭐ -->
```
---
## ciybigscreen.js API 详解
### 类:`ciyclass.bigpanel`
**功能**:大屏面板管理核心类
#### 构造函数参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `name` | String | ✓ | - | 面板唯一标识用于DOM的id |
| `jspath` | String | ✓ | - | 组件JS文件路径`'./b64/'` |
| `style` | String | - | `''` | 面板容器内联样式 |
| `prop` | String | - | `''` | 面板容器HTML属性 |
| `animation` | String | - | - | 动画类型('ani1', 'ani2', 'small' |
| `mask` | String | - | - | 遮罩层颜色(如 `'rgba(0,0,0,0.5)'` |
**使用示例**
```javascript
var chtpls = {};
chtpls['bank1'] = new ciyclass.bigpanel({
name: 'panel_bank1', // 必填
jspath: './b64/', // 必填
style: 'position:absolute;top:4em;left:5px;right:5px;bottom:20px;',
animation: 'ani1',
mask: 'rgba(0,0,0,0.5)'
});
```
#### 实例属性
| 属性 | 类型 | 说明 |
|------|------|------|
| `this.container` | jQuery对象 | 面板容器DOM对象 |
| `this.post` | Object | 传递给后端的公共参数(每个组件独有) |
**使用示例**
```javascript
chtpls['bank1'].post = {
bankid: 123,
orgid: 1
};
```
#### 方法详解
**1. `addplot(opn)` - 添加图表组件**
**参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `opn.jsname` | String | ✓ | 组件名称(如 `'bank1_c1'` |
| `opn.style` | String | - | 组件容器样式 |
| `opn.prop` | String | - | 组件容器HTML属性 |
**使用示例**
```javascript
chtpls['bank1'].addplot({
jsname: 'bank1_c1',
style: 'position:absolute;left:0;top:0;width:33%;height:33%;',
prop: 'data-id="chart1"'
});
```
**内部流程**
```
1. 创建组件加载状态plots[opn.jsname] = { load: 0 }
2. 动态加载JS文件ciyfn.loadjs('ciy_chart_' + opn.jsname, ...)
3. 加载成功后创建容器load = 1
4. 添加到面板容器load = 2
5. 实例化组件类new window['ciy_chart_' + opn.jsname]()
```
**2. `setbtns(opn)` - 设置按钮**
**参数**
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `opn.template` | String | - | - | 模板类型(如 `'close1'` |
| `opn.html` | String | - | `''` | 自定义按钮HTML |
| `opn.hideopacity` | Number | - | `0.9` | 隐藏时透明度0-1 |
| `opn.hidesec` | Number | - | `5` | 鼠标静止X秒后隐藏 |
| `opn.top` | String | - | `'2px'` | 按钮顶部位置 |
| `opn.click` | Function | - | - | 自定义点击事件 |
**使用示例**
```javascript
// 使用内置模板
chtpls['bank1'].setbtns({
template: 'close1',
hideopacity: 0.9,
hidesec: 5,
top: '2px'
});
// 自定义按钮
chtpls['bank1'].setbtns({
html: '<button data-act="close">关闭</button>',
click: function(e) {
console.log('按钮被点击');
}
});
```
**内置模板**
- `close1` - 关闭按钮(右上角×)
**自动隐藏机制**
- 监听 `mousemove` 事件更新时间戳
- 每500ms检查是否超过 `hidesec` 秒未操作
- 超时则降低透明度到 `hideopacity`
**3. `run(fsec)` - 启动数据轮询**
**参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `fsec` | Object | ✓ | 刷新频率配置键为接口名值为0.5秒的倍数) |
**使用示例**
```javascript
chtpls['bank1'].run({
'bank_c1': 50, // 每25秒刷新一次50 × 0.5秒)
'bank_c2': 10, // 每5秒刷新一次10 × 0.5秒)
'bplant': 50 // 每25秒刷新一次
});
```
**内部流程**
```
初始化阶段(仅执行一次)
└─ 遍历所有组件
└─ 读取组件的 this.func 数组
└─ 为每个接口创建 funcsecs 对象
└─ 设置初始倒计时 t=0 和最大间隔 max
轮询阶段每500ms执行一次
└─ 遍历 funcsecs
├─ t == 0发起请求
│ ├─ 合并参数Glob.post + thos.post
│ ├─ 调用 ciyfn.callfunc(ifu, post, callback)
│ ├─ 成功:
│ │ ├─ 重置倒计时t = max
│ │ └─ 分发数据到所有相关组件
│ └─ 失败t = 55秒后重试
└─ t--(倒计时递减)
```
**数据分发逻辑**
```javascript
// 遍历所有组件
for (var iplot in plots) {
// 检查组件是否匹配(通过 prefunc
if (plots[iplot].clss.prefunc != funcsecs[ifu].prefunc) continue;
// 提取函数名(去掉前缀)
var funcstr = ifu.substring(funcsecs[ifu].prefunc.length);
// 检查组件是否需要此数据
if (plots[iplot].clss.func.indexOf(funcstr) == -1) continue;
// 调用组件的 setdata 方法
if (typeof (plots[iplot].clss.setdata) == 'function') {
plots[iplot].clss.setdata(funcstr, jsondata);
}
}
```
**4. `setdata()` - 手动刷新所有组件**
**参数**:无
**功能**:临时方法,用于调试或手动触发刷新
**使用示例**
```javascript
chtpls['bank1'].setdata();
```
**5. `resize()` - 窗口大小改变响应**
**参数**:无
**功能**:遍历所有组件,调用其 `resize()` 方法
**使用示例**
```javascript
window.addEventListener("resize", function () {
ciyfn.big_setbetsize(1536);
for (var ipl in chtpls) {
chtpls[ipl].resize();
}
});
```
**6. `distory()` - 销毁面板**
**参数**:无
**功能**清理面板资源包括定时器、组件、DOM元素
**清理流程**
```
1. 清除定时器tick, tick_btns
2. 遍历所有组件
└─ 调用组件的 distory() 方法
└─ 删除组件对象
3. 播放关闭动画(如果设置了 animation
4. 移除DOM元素
```
**使用示例**
```javascript
chtpls['bank1'].distory();
delete chtpls['bank1'];
```
---
### 工具函数:`ciyfn.big_setbetsize(basewidth, fontsize)`
**功能**:设置大屏缩放比例和字体大小
**参数**
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `basewidth` | Number | ✓ | - | 基准设计宽度(如 1536 |
| `fontsize` | Number/String | - | `'auto'` | 字体大小('auto' 或 具体数值) |
**返回值**:无
**使用示例**
```javascript
ciyfn.big_setbetsize(1536); // 自动计算
ciyfn.big_setbetsize(1536, 16); // 指定字体大小
ciyfn.big_setbetsize(1536, 0); // 不调整字体
```
**计算逻辑**
```
1. 获取屏幕宽度window.screen.width
2. 开发模式特殊处理urlp.dev
└─ devicePixelRatio < 0.8 时放大屏幕宽度
3. 屏幕宽度 > 基准宽度?
└─ 是:计算缩放比例 bet = screenwidth / basewidth
└─ 是:计算字体 fontsize = 14 * bet
4. 设置全局样式
└─ $5('body').css('fontSize', fontsize)
5. 更新全局变量
└─ Glob.fontsize = fontsize - 2
└─ Glob.bet = bet
```
**使用场景**
```javascript
// 页面加载时
ciyfn.big_resolution(1536, 864);
ciyfn.big_setbetsize(1536);
// 窗口大小改变时
window.addEventListener("resize", function () {
ciyfn.big_setbetsize(1536);
for (var ipl in chtpls) {
chtpls[ipl].resize();
}
});
```
---
### 工具函数:`ciyfn.big_resolution(width, height)`
**功能**:检查屏幕分辨率是否匹配建议值
**参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `width` | Number | ✓ | 基准宽度 |
| `height` | Number | ✓ | 基准高度 |
**返回值**:无
**使用示例**
```javascript
ciyfn.big_resolution(1536, 864);
```
**检查流程**
```
1. 检查物理分辨率window.screen.width/height
└─ 不匹配?提示:"最佳分辨率为:1536 x 864"
2. 检查窗口宽度window.innerWidth
└─ 不等于基准宽度?返回(判断为调试模式)
3. 检查窗口高度window.innerHeight
└─ 小于基准高度?提示:"请按F11进入全屏模式"
```
**使用场景**
```javascript
// 页面加载时检查
ciyfn.big_resolution(1536, 864);
```
---
### 类:`ciyclass.bigcychange`
**功能**:值循环切换工具(用于图片轮播、数据切换等)
#### 构造函数参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `values` | Array | ✓ | - | 值数组 |
| `changecb` | Function | ✓ | - | 值改变时的回调函数 |
| `cycsec` | Number | - | `5` | 切换间隔(秒) |
**使用示例**
```javascript
var cyc = new ciyclass.bigcychange({
values: ['img1.jpg', 'img2.jpg', 'img3.jpg'],
cycsec: 5,
changecb: function (img) {
$5('img', opdata.container).attr('src', img);
}
});
```
#### 实例属性
| 属性 | 类型 | 说明 |
|------|------|------|
| `this.value` | Any | 当前值 |
#### 方法详解
**1. `change(mm, longsec)` - 手动切换到指定值**
**参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `mm` | Any | ✓ | 要切换到的值 |
| `longsec` | Number | - | 停留时长(秒),默认使用 cycsec |
**返回值**Boolean成功返回 true失败返回 false
**使用示例**
```javascript
cyc.change('img2.jpg', 10); // 切换到'img2.jpg'停留10秒
cyc.change('img1.jpg'); // 切换到'img1.jpg',使用默认间隔
```
**2. `distory()` - 销毁定时器**
**参数**:无
**返回值**:无
**使用示例**
```javascript
cyc.distory();
```
**完整使用示例**
```javascript
function ciy_chart_farm_l3(opdata) {
this.func = ['farm_l3'];
var thos = this;
var cyc = null;
this.setdata = function (funame, data) {
var imgs = data.farm.picszz.split('~');
cyc = new ciyclass.bigcychange({
values: imgs,
cycsec: 5,
changecb: function (img) {
$5('img', opdata.container).attr('src', img);
}
});
}
this.distory = function () {
if (cyc) cyc.distory();
}
opdata.container.append('<img src="" style="width:100%;height:100%;">');
}
```
---
### 全局变量:`Glob`
| 属性 | 类型 | 说明 |
|------|------|------|
| `Glob.post` | Object | 传递给后端的公共参数(所有面板共享) |
| `Glob.bet` | Number | 屏幕缩放比例 |
| `Glob.fontsize` | Number | 字体大小 |
| `Glob.myparam` | Object | 自定义参数 |
**使用示例**
```javascript
// 页面加载时设置公共参数
ciyfn.callfunc('init', {}, function (json) {
Glob.post.orgid = json.orgid;
Glob.myparam = { title: json.title };
});
// 组件内使用
var option = {
fontSize: 18 * Glob.bet,
borderRadius: 4 * Glob.bet
};
```
---
## 样式命名规范与最佳实践
### CSS命名规范
为避免样式冲突组件内部CSS应遵循以下规范
#### BEM命名法
```css
/* 面板_组件__元素 */
.bank1-c1__num { }
.bank1-c1__title { }
.farm1-l2__info { }
.farm1-l2__item { }
```
**示例**
```javascript
opdata.container.append(`
<div class="bank1-c1">
<div class="bank1-c1__num" data-num="n1">--</div>
<div class="bank1-c1__title">贷款金额</div>
</div>
`);
// 动态注入样式
var style = document.createElement("style");
style.innerHTML = `
.bank1-c1__num {
font-size: 1.8em;
font-weight: bold;
color: #ffffff;
}
.bank1-c1__title {
font-size: 0.8em;
color: #6dcdee;
}
`;
window.document.head.appendChild(style);
```
#### ID选择器配合 opdata.container
```javascript
// 添加元素时指定ID
opdata.container.append('<div id="chart1"></div>');
// 访问时限定在容器内
var chart1 = echarts.init($5('#chart1', opdata.container)[0], 'dark');
```
#### data-* 属性选择器
```javascript
// 添加元素
opdata.container.append(`
<div data-num="n1">--</div>
<div data-bank>银行名称</div>
`);
// 更新数据
$5('[data-num="n1"]', opdata.container).text(data.n1);
$5('[data-bank]', opdata.container).text(data.name);
```
### 使用 bigscreen 资源
#### 字体选择
```css
/* 大屏主标题 */
font-family: fnt01;
font-size: 2em;
letter-spacing: 0.2em;
/* 中等标题 */
font-family: fnt02;
font-size: 1.5em;
/* 数字展示 */
font-family: eng02;
font-size: 1.8em;
letter-spacing: 4px;
```
#### 边框选择
```javascript
// 添加边框容器
opdata.container.append(`
<div class="brimg34" style="padding:2px;height:100%;">
<div id="map1" style="height:100%;"></div>
</div>
`);
// 或在HTML中定义
var chartHTML = `
<div class="brimg03" style="padding:10px;background:#00000011;">
<div style="pointer-events:none;min-width:180px;padding-left:1.5em;">
<span style="color:#fffffd;font-weight:bolder;letter-spacing:2px;">信贷团队统计</span>
</div>
<div id="chart1" style="height:100%;z-index:5;"></div>
</div>
`;
opdata.container.append(chartHTML);
```
#### 标题选择
```javascript
// 面板内部小标题
var titleHTML = `
<div style="pointer-events:none;min-width:180px;padding-left:1.5em;">
<span style="color:#fffffd;font-weight:bolder;letter-spacing:2px;">图表标题</span>
<div style="position:relative;margin-top:0.6em;">
<img src="/ud/bigscreen/tit/05.png" style="height:0.3em;display:block;">
<div style="position:absolute;left:12em;right:1.5em;border-bottom:0.05em solid #64ecf7;"></div>
</div>
</div>
`;
opdata.container.append(titleHTML);
```
### 渐变文字效果
```javascript
// 标题渐变
var captionHTML = `
<div style="font-family:fnt01;position:absolute;top:0;left:0;right:0;z-index:10;">
<img src="/ud/bigscreen/caption/09-og.png" style="height:3.5em;margin:auto;display:block;" />
<div data-title style="min-width:50em;position:absolute;top:0;left:0;right:0;text-align:center;line-height:1.7em;font-size:2em;
background: linear-gradient(to bottom, #ffffff, #50c4eb 60%);
background-clip: text;
-webkit-background-clip: text;
color: transparent;">
大屏标题
</div>
</div>
`;
opdata.container.append(captionHTML);
```
### 使用全局缩放比例
```javascript
// 在所有尺寸计算中使用 Glob.bet
var option = {
textStyle: {
fontSize: Glob.fontsize
},
series: [{
itemStyle: {
borderRadius: 4 * Glob.bet,
borderWidth: 1 * Glob.bet
},
label: {
fontSize: 18 * Glob.bet,
padding: [18 * Glob.bet, 0, 8 * Glob.bet, 0]
},
labelLine: {
length: 20 * Glob.bet,
length2: 80 * Glob.bet
}
}]
};
// CSS样式
var style = document.createElement("style");
style.innerHTML = `
.bank1-c1__num {
font-size: 1.8em;
padding: 10px * ${Glob.bet};
}
`;
```
### 动画效果
```javascript
// 透明度动画
@keyframes opa {
0% { opacity: 1; }
10% { opacity: 0.5; }
20% { opacity: 1; }
}
.ani-fade {
animation: opa 5s infinite;
}
// ECharts自动高亮动画
var idx_autohight = -1;
var t_autohight = setInterval(function () {
var option = chart1.getOption();
chart1.dispatchAction({
type: 'downplay',
dataIndex: idx_autohight
});
idx_autohight = (idx_autohight + 1) % option.series[0].data.length;
chart1.dispatchAction({
type: 'highlight',
dataIndex: idx_autohight
});
}, 2200);
// 记得在 distory() 中清理
this.distory = function () {
clearInterval(t_autohight);
if (chart1) chart1.dispose();
}
```
### 弹窗样式
```javascript
// 弹窗样式
var style = document.createElement("style");
style.innerHTML = `
.popup-box {
position: absolute;
z-index: 999;
transform: translateX(calc(-50%)) translateY(calc(-100% + 4px));
pointer-events: none;
transition: all 0.5s;
opacity: 0;
}
.popup-box > .box {
border: 1px solid #6d8ef4;
background: linear-gradient(344deg, #0753b2, #05254e);
border-radius: 0.5em;
padding: 0.5em;
white-space: nowrap;
color: #ffffff;
pointer-events: all;
}
.popup-box > .line {
height: 3em;
width: 1px;
margin: auto;
border-left: 1px solid #0753b2;
}
.popup-box > .rlc {
width: 7px;
height: 7px;
background: #0753b2;
margin: auto;
border-radius: 4px;
}
`;
window.document.head.appendChild(style);
```
### 性能优化建议
1. **减少重复初始化**
```javascript
this.setdata = function (funame, data) {
if (ce) return; // 地图只初始化一次
if (chart1) return; // 图表只初始化一次
// ...初始化代码
}
```
2. **使用事件委托**
```javascript
// 不推荐
$5('.item').on('click', function() {
// ...
});
// 推荐
opdata.container.on('click', '.item', function() {
// ...
});
```
3. **及时清理资源**
```javascript
this.distory = function () {
clearInterval(t_autohight);
if (chart1) chart1.dispose();
if (cyc) cyc.distory();
if (ce) ce.destroy();
// 移除动态添加的样式
if (thos.style) thos.style.remove();
}
```
---
## 总结
Ciyon数据大屏系统采用**组件化**、**模块化**的设计理念:
**优点**
- 组件独立开发,易于维护
- 数据轮询自动化
- 屏幕自适应
- 支持多种可视化类型
- 丰富的CSS资源库73个样式类 + 15种字体
📌 **核心要点**
1. 遵循命名规范文件、接口、方法、CSS类名
2. 实现三个核心方法:`setdata()`、`resize()`、`distory()`
3. 合理设置刷新频率,避免性能问题
4. 及时清理资源,防止内存泄漏
5. 使用BEM命名法避免CSS冲突
6. 充分利用bigscreen资源库字体、边框、标题
7. 使用 `Glob.bet` 实现屏幕自适应
🎨 **资源使用建议**
- 字体:`fnt01`(大标题)、`eng02`(数字)
- 背景:`bd04`(现代海蓝色)
- 边框:`brimg34`(常用)、`brimg03`(薄边框)
- 标题:`cap09`(带倒影)、`cap02`(简洁)
🔧 **API核心**
- `ciyclass.bigpanel` - 面板管理
- `ciyfn.big_setbetsize()` - 屏幕缩放
- `ciyfn.big_resolution()` - 分辨率检查
- `ciyclass.bigcychange` - 值循环切换
---
**版本**v2.0
**更新时间**2026-03-15
**维护团队**Ciyon开发团队