自定义组件相对于其他组件,提供给大屏设计者更大的、个性化编程的创造空间。当大屏现有的组件无法满足业务需求时,用户可以将任意合法的JS代码写到组件配置项中实现所想实现的效果。要使用本组件,用户应具备以下基础技能:

  • 掌握了一定的JavaScript基础知识;
  • 掌握了一定的HTML基础知识;
  • 掌握了一定的CSS

组件配置项

配置

基础属性

组件位置:包括组件的横坐标纵坐标,单位为px;横坐标为组件左上角距离页面左边界的像素距离,纵坐标为组件左上角距离页面上边界的像素距离。

组件尺寸:包括组件的宽度高度,单位为px;可单击比例锁锁定组件宽高比,等比例调整组件的宽高。再次单击进行解锁,解锁后宽高比不受限制。比例锁默认不锁定。

旋转:以组件的中心为中心点,进行旋转,单位为度(°)。手动输入角度值,控制组件的旋转角度;

  • 单击图标,控制组件左右翻转样式;
  • 单击图标,控制组件上下翻转样式。

透明:取值范围为0~100%。为0%时,组件隐藏;为100%时,组件完全显示。默认为100%。

组件属性

参数列表

参数列表中包含了传递给调用函数的变量的声明,可以实现其他组件与自定义组件之间的联动。如:

  1. 添加一张选项卡,点击选项框后将其内容传给大屏变量基础知识;

  1. 参数列表中将变量设为参数

  1. 在渲染函数中接收该参数

渲染函数

代码输入框里本身是一个JavaScript代码环境,并且输入框中的代码最终会当做函数体来调用函数,并且该函数有如下形式参数:

参数名 说明
datas 自定义组件接入的数据。
dom 组件文档对象模型。
params 参数。
eventCallback 事件回调函数。
事件配置

代码输入框里本身是一个JavaScript代码环境,并且输入框中的代码最终会当做函数体来调用函数,并且该函数有如下形式参数:

参数名 说明
params 参数。
outValues 输出值。

事件类型必须与以下相匹配,若不传则默认为点击事件

/** 
 * params.eventType 事件类型
 * onClick          鼠标点击 可不传默认点击
 * onDataChange     数据变化 注: 不可手动调
 * onMouseenter     鼠标移入
 * onMouseleave     鼠标移出
 * onLoad           加载完成
 * onLoadEnd        加载结束
 */

数据

组件数据格式

字段 说明
任意 所配数据源中能获取到的所有字段都可以被组件使用。

交互

  1. 支持配置鼠标点击事件:当点击自定义组件时,触发交互事件:设置大屏变量、打开超链接、设置可见、设置JS事件。

  2. 支持配置数据变化事件。当自定义组件数据变化时,触发交互事件:设置大屏变量、打开超链接、设置可见、设置JS事件。

  3. 支持配置鼠标移入事件:当鼠标移入自定义组件时,触发交互事件:设置大屏变量、打开超链接、设置可见、设置JS事件。

  4. 支持配置鼠标移出事件:当鼠标移入自定义组件时,触发交互事件:设置大屏变量、打开超链接、设置可见、设置JS事件。

  5. 支持配置加载起始事件:当自定义组件加载起始时,触发交互事件:设置大屏变量、打开超链接、设置可见、设置JS事件。

  6. 支持配置加载结束事件:当自定义组件加载结束时,触发交互事件:设置大屏变量、打开超链接、设置可见、设置JS事件。

典型案例

制作步骤

  1. 准备自定义组件数据
  2. 编写组件构建代码

案例1:交互块

案例效果

配置过程
  1. 编写自定义组件构建代码
const $dom = $(dom)
$dom.html(`
  <div class="btn-wrapper">
    <div class="primary onClick">onClick</div>
    <div class="ghost onDataChange">onDataChange</div>
    <div class="dashed onMouseenter">onMouseenter</div>
    <br/>
    <div class="primary onMouseleave">onMouseleave</div>
    <div class="ghost onLoad">onLoad</div>
    <div class="dashed onLoadEnd">onLoadEnd</div>
  </div>
`)

$dom.find('.btn-wrapper .onClick').click(function(){
  eventCallback()
})

$dom.find('.btn-wrapper .onDataChange').click(function(){
  eventCallback({
    eventType: 'onDataChange',
    __dataChange: true
  })
})

$dom.find('.btn-wrapper .onMouseenter').click(function(){
  eventCallback({
    eventType: 'onMouseenter'
  })
})

$dom.find('.btn-wrapper .onMouseleave').click(function(){
  eventCallback({
    eventType: 'onMouseleave'
  })
})

$dom.find('.btn-wrapper .onLoad').click(function(){
  eventCallback({
    eventType: 'onLoad'
  })
})

$dom.find('.btn-wrapper .onLoadEnd').click(function(){
  eventCallback({
    eventType: 'onLoadEnd'
  })
})
  1. 编写自定义组件事件渲染代码
/** 
 * params.eventType 事件类型
 * onClick          鼠标点击 可不传默认点击
 * onDataChange     数据变化 注: 不可手动调
 * onMouseenter     鼠标移入
 * onMouseleave     鼠标移出
 * onLoad           加载完成
 * onLoadEnd        加载结束
 */




 switch(params.eventType){
   case 'onClick': { 
     outValues.value1 = "点击时"
     break
   }
   case 'onDataChange': {
     outValues.value1 = "数据变化时"
     break
   }
   case 'onMouseenter': {
     outValues.value1 = "鼠标移入时"
     break
   }
   case 'onMouseleave': {
     outValues.value1 = "鼠标移出时"
     break
   }
   case 'onLoad': {
     outValues.value1 = "加载完成时"
     break
   }
   case 'onLoadEnd': {
     outValues.value1 = "加载结束时"
     break
   }
 }
  1. 设置自定义组件交互事件

    1. 将”value1“的值传给大屏变量”变量1“;

    2. 将“变量1”赋值给标题数据模型;

案例2:红黑榜

案例效果

配置过程

  1. 准备自定义组件数据(该数据由后台获取)
[
    {
        "townName": "宁围街道-1",
        "rybNum": 1,
        "townCode": 1,
        "villageName": "宁牧村-1",
        "villageCode": 1
    },
    {
        "townName": "闻堰街道-1",
        "rybNum": 1,
        "townCode": 111,
        "villageName": "老虎洞村-1",
        "villageCode": 111
    },
    {
        "townName": "新塘街道-1",
        "rybNum": 1,
        "townCode": 1,
        "villageName": "新丰村-1",
        "villageCode": 1
    },
    {
        "townName": "闻堰街道-1",
        "rybNum": 1,
        "townCode": 1,
        "villageName": "老虎洞村-1",
        "villageCode": 1
    },
    {
        "townName": "闻堰街道-1",
        "rybNum": 1,
        "townCode": 1,
        "villageName": "老虎洞村-1",
        "villageCode": 1
    },
    {
        "townName": "闻堰街道-1",
        "rybNum": 1,
        "townCode": 1,
        "villageName": "老虎洞村-1",
        "villageCode": 1
    },
    {
        "townName": "闻堰街道-1",
        "rybNum": 1,
        "townCode": 1,
        "villageName": "老虎洞村-1",
        "villageCode": 1
    },
    {
        "townName": "宁围街道-2",
        "rybNum": 2,
        "townCode": 1,
        "villageName": "宁牧村-2",
        "villageCode": 1
    },
    {
        "townName": "闻堰街道-2",
        "rybNum": 2,
        "townCode": 1,
        "villageName": "老虎洞村-2",
        "villageCode": 1
    },
    {
        "townName": "新塘街道-2",
        "rybNum": 2,
        "townCode": 1,
        "villageName": "新丰村-2",
        "villageCode": 1
    },
    {
        "townName": "闻堰街道-2",
        "rybNum": 2,
        "townCode": 1,
        "villageName": "老虎洞村-2",
        "villageCode": 1
    },
    {
        "townName": "闻堰街道-2",
        "rybNum": 2,
        "townCode": 1,
        "villageName": "老虎洞村-2",
        "villageCode": 1
    },
    {
        "townName": "闻堰街道-2",
        "rybNum": 2,
        "townCode": 1,
        "villageName": "老虎洞村-2",
        "villageCode": 1
    },
    {
        "townName": "宁围街道-3",
        "rybNum": 3,
        "townCode": 1,
        "villageName": "宁牧村-3",
        "villageCode": 1
    },
    {
        "townName": "闻堰街道-3",
        "rybNum": 3,
        "townCode": 1,
        "villageName": "老虎洞村-3",
        "villageCode": 1
    },
    {
        "townName": "新塘街道-3",
        "rybNum": 3,
        "townCode": 1,
        "villageName": "新丰村-3",
        "villageCode": 1
    },
    {
        "townName": "闻堰街道-3",
        "rybNum": 3,
        "townCode": 1,
        "villageName": "老虎洞村-3",
        "villageCode": 1
    },
    {
        "townName": "闻堰街道-3",
        "rybNum": 3,
        "townCode": 1,
        "villageName": "老虎洞村-3",
        "villageCode": 1
    },
    {
        "townName": "闻堰街道-3",
        "rybNum": 3,
        "townCode": 1,
        "villageName": "老虎洞村-3",
        "villageCode": 1
    }
]
  1. 编写自定义组件构建代码
const dataList = datas

fetch(`https://ywtg.xiaoshan.gov.cn/entrance172/api/panelData/11902232?systemId=3&villageTypeId=3&userId=1`)
.then((request) => request.json())
.then(resolve=>{
  if(resolve.code==200){
    const dataList = resolve.data[0]
  }
})

let $list = $(dom).find('.ranking-list-container');

if (!$list[0]) {
  $list = $(dom)
    .append($('<div class="ranking-list-container"></div>'))
    .find('.ranking-list-container');
} else {
  $list.html('');
  clearRankingProgress && clearRankingProgress()
}


const totalLen = dataList.length,
      listData = {},
      rankType = {
        1: { title: '红榜', code: 'red' },
        2: { title: '黄榜', code: 'yellow' },
        3: { title: '黑榜', code: 'block' }
      }

// 处理数据
for (const key in rankType) {
  const currentDataList = dataList.filter((item) => item.rybNum == key);
  listData[key] = currentDataList;
}


for (const type in listData) {
  const list = listData[type],
    len = list.length,
    { code, title } = rankType[type],
    proportion = ((len / totalLen) * 100).toFixed(2),
    itemContent = $(`
    <div class='${code}-con list-item'>
      <div class='${code}-info list-info'>
        <div class='title'>
          <i class='${code}-sign sign'></i>
          <span>${title}</span>
        </div>
        <div class='proportion ${code}-proportion'>
          <span>${len}个</span>
          <i class='division'></i>
          <span>${proportion}%</span>
          <i class='switch sign' data-type='${code}'></i>
        </div>
      </div>
      <div class='progress' data-type='${code}' data-len='${len}'></div>
      <div class='data-list'></div>
    </div>`);

  const ul = $('<ul></ul>');
  const listItems = list.map((item) => {
    const $$ = $(
      `<li class="list-li">
        <div>
          <span class='village' title='${item.villageName}'>${item.villageName}</span>
          <span class='street' title='${item.townName}'>${item.townName}</span>
        </div>
        <i class='${code}-sign sign'></i>
      </li>`
    );
    $$.data('itemData', item);
    return $$;
  });
  ul.append(...listItems);
  itemContent.find('.data-list').append(ul);
  $list.append(itemContent);
}

let openEl = null;


 // 展开下拉
function expandDropDown(target, open = true) {
  if (openEl === target) openEl = null;

  const $target = $(target),
    dataListEl = $target.find(`.data-list`),
    ul = $target.find(`.data-list ul`),
    height = open ? ul.height() : 0;

  if (open && openEl) {
    expandDropDown(openEl, false);
  }

  dataListEl.css({ height: `${height}px` });
  !open ? $target.removeClass('active') : $target.addClass('active');
  open && (openEl = target);
}

$list.find('.list-item').ready(function () {
  const firstItem = $list.find('.list-item')[0];
  expandDropDown(firstItem);

  // 展开事件
  $list.find('i.switch').click(function ({ target }) {
    const switchEl = $(target),
      type = switchEl.attr('data-type'), // red yellow block
      dataListEl = $list.find(`.${type}-con`)[0];
    expandDropDown(dataListEl, openEl !== dataListEl);
  });
});

function addProgress(val, colorStops, groundColor, strokeColor = null) {
  const $this = $(this),
    w = $this.innerWidth() - 2,
    h = $this.innerHeight(),
    r = h / 2,
    zr = new zrender.init(this);

  const gradient = new zrender.LinearGradient(0, 0, 1, 1, colorStops);

  // 底色
  const rect = new zrender.Rect({
    shape: {
      r,
      x: 1,
      y: 0,
      width: w,
      height: h
    },
    style: {
      fill: groundColor
    }
  });
  zr.add(rect);

  // 内容
  const innerRect = new zrender.Rect({
    shape: {
      r: [r, 0, 0, r],
      x: 1,
      y: 0,
      width: w * val,
      height: h
    },
    style: {
      fill: gradient
    }
  });
  if (strokeColor) {
    innerRect.style.stroke = strokeColor;
    innerRect.shape.x = 2;
    innerRect.shape.y = 1;
    innerRect.shape.height = h - 2;
    innerRect.shape.width = w * val - 2;

    if (val > 0.994) {
      innerRect.shape.r = r;
    }
  }
  innerRect.setClipPath(rect);
  zr.add(innerRect);

  return zr;
}

window._rankingListprogressInstances = {
  red: null,
  yellow: null,
  block: null
};

// 添加进度条
$list.find('.progress').ready(function () {
  $list.find('.progress').each(function (index, target) {
    const $target = $(target),
      type = $target.attr('data-type'),
      len = $target.attr('data-len'),
      colorStops = {
        red: [
          {
            offset: 0,
            color: '#FF9384'
          },
          {
            offset: 1,
            color: '#FF0000'
          }
        ],
        yellow: [
          {
            offset: 0,
            color: '#FFDE00'
          },
          {
            offset: 1,
            color: '#FFBE00'
          }
        ],
        block: [
          {
            offset: 0,
            color: '#000000'
          },
          {
            offset: 1,
            color: '#323C4A'
          }
        ]
      }[type],
      val = len / totalLen;

    _rankingListprogressInstances[type] = addProgress.call(
      target,
      val,
      colorStops,
      'rgba(255,255,255,0.2)',
      type === 'block' ? '#B6C7CC' : null
    );
  });
});

// 村街道的点击事件
$list.on('click', 'li.list-li', function ({ target }) {
  const $target = $(target);
  const { townCode, villageCode, rybNum } = $target.data('itemData');
  const variants = encodeURIComponent(`townCode=${townCode};villageCode=${villageCode};rybNum=${rybNum}`) 
  openModel({
    url:`http://144.20.80.98:8081/HappyServer/lczMatrix/index.html?variants=${variants}#/publish/8b5fa66892144df893f2`
  })
});


 window.clearRankingProgress = function () {
  for (const key in _rankingListprogressInstances) {
    const element = _rankingListprogressInstances[key];
    element && element.dispose();
  }
  window._rankingListprogressInstances = null
};

案例3:富文本

案例效果

配置过程

  1. 准备自定义组件数据(该数据由后台获取)
[
    {
        "value": "<div><p><strong>乐享数据,创由个性!</strong></p><p><a href='http://www.lechuangzhe.com/#/videocenter' target='_blank'>视频中心</a></p><p><br/></p><p><img src='../lczResource/img/1/8cdfc75d83304a54a072.png' width='50'/></p><p><br/></p><p><br/></p><p><strong><span style='font-family:楷体, 楷体_GB2312, SimKai'>什么是乐创者<sup>®</sup></span></strong></p><p>乐创者同时是 <span class='warn'>商业智能软件</span><span class='warn'>低代码开发软件</span></p><p><br/></p><p><span class='warn'>商业智能软件</span></p><p><span style='font-size: 14px; font-family: &quot;Wingdings 2&quot;;'></span>√&nbsp;<span style='font-size: 14px; font-family: Calibri, sans-serif;'></span>定位明确:专注于数据采集、展示、分析和挖掘; &nbsp;</p><p><span style='white-space: normal; font-size: 14px; font-family: &quot;Wingdings 2&quot;;'></span>√&nbsp;<span style='white-space: normal; font-size: 14px; font-family: Calibri, sans-serif;'></span>需求广泛:越来越多的客户(政府或企业)需要利用数据,依赖数据进行决策;只要客户在业务中产生了数据就有对商业智能软件的需求;</p><p><span style='white-space: normal; font-size: 14px; font-family: &quot;Wingdings 2&quot;;'></span>√&nbsp;<span style='white-space: normal; font-size: 14px; font-family: Calibri, sans-serif;'></span>价值明显:赋予客户发现和创造数据价值的方法;挖掘数据金矿的过程中大幅度节约人力和资金投入;异构数据的整合能力,破解了多数据来源的难题;工欲善其事,必先利其器,投入小成本获得大收益。</p><p><br/></p><p><span style='white-space: normal;'>※&nbsp;</span> <span class='warn'>低代码开发软件</span></p><p>√ 定位明确:用较少的代码,主要是靠图形化的操作,基于低门槛的技能实现个性化开发,把业务和流程快速上线到内部网络或互联网;&nbsp;</p><p><span style='white-space: normal; font-size: 14px; font-family: &quot;Wingdings 2&quot;;'></span>√&nbsp;<span style='white-space: normal; font-size: 14px; font-family: Calibri, sans-serif;'></span>需求广泛:客户都希望有自己能够管控的个性化的软件,都希望自己的软件可以快速地随需而变;面对疫情等各类严峻的挑战,客户更加需要低代码开发软件;</p><p><span style='white-space: normal; font-size: 14px; font-family: &quot;Wingdings 2&quot;;'></span>√&nbsp;<span style='white-space: normal; font-size: 14px; font-family: Calibri, sans-serif;'></span>价值明显:大幅度减少开发人员数量,大幅度降低开发人员的能力要求,大幅度缩短适应业务变化的调整时间,大幅度节省软件运维投入;软件成熟度高、质量好、交互方便、桌面和移动平台兼容;工欲善其事,必先利其器,投入小成本获得大收益。</p><p><br/></p><p><strong><span style='font-family:楷体, 楷体_GB2312, SimKai'>什么是乐创者<strong style='white-space: normal;'><span style='font-family: 楷体, 楷体_GB2312, SimKai;'><sup>®</sup></span></strong>软件解决方案?</span></strong></p><p><span style='white-space: normal; font-size: 14px; font-family: &quot;Wingdings 2&quot;;'></span>√&nbsp;<span style='white-space: normal; font-size: 14px; font-family: Calibri, sans-serif;'></span>乐创者软件解决方案是乐创者原厂商基于乐创者打造的实现政府和企业具体业务的一系列软件系统。</p><p><br/></p><p>通过阅读本文档,我们希望您能够从宏观到微观,对乐创者产品有一个深入的了解。</p><p>本文档侧重于对乐创者线下部署产品的安装、部署和使用。大部分的知识同样适用于以云的方式操作和使用乐创者。部分页面内附有视频链接。</p><p><br/></p><p><strong>第1章 </strong><a href='http://?id=1.100' target='_self'>乐创者概况</a></p><p>介绍乐创者的宏观情况。</p><p><br/></p><p><strong>第2章 </strong><a href='http://?id=1.200' target='_self'>安装和升级</a></p><p>介绍乐创者在线下如何安装、部署和升级。</p><p><br/></p><p><strong>第3章 </strong><a href='http://?id=1.111' target='_self'>智能门户</a></p><p>通过智能门户 lczPortal 实现系统访问和系统管理。</p><p><br/></p><p><strong>第4章 </strong><a href='http://?id=1.123' target='_self'>智能门户(应用)</a></p><p>通过智能门户实现乐创者应用的 管理。</p></div>"
    }
]
  1. 编写自定义组件构建代码
const val = datas[0]?.value

dom.innerHTML = val
作者:倪  创建时间:2023-06-05 10:55
最后编辑:倪  更新时间:2025-02-07 17:25