首页 文章 精选 留言 我的

精选列表

搜索[可视化工具],共10000篇文章
优秀的个人博客,低调大师

AI 预测可视化平台 | 异常检测标记系统:前端如何高亮预测异常点

# 引言 偏差分解把"不准"拆成了工单,但工单不会自己排进队列——总得有人先发现它。计划员每天面对成百上千个 SKU、每个 SKU 上百个时间点,**靠肉眼扫线图找异常,漏报率几乎是百分之百**。异常标记系统要解决的,正是这个"发现"环节:用统一的判定规则把可疑点筛出来,用分层视觉编码让最严重的点一眼可见,再给每个点挂上状态机和协作入口。 本文拆解异常的四类来源、多层级高亮策略、状态流转与持久化设计,并讨论前端该算到什么程度——哪些该自己做,哪些必须交给后端。 --- # 一、先分清:异常是"预测外"还是"预测内" 这是设计异常系统第一个要踩的坑。很多团队把所有偏差大的点都叫"异常",结果把节前促销这种**模型本来就该预测到**的点也算进去了——这类点偏差大,但它不异常,它是模型表现差。 异常至少应分四类,判定逻辑完全不同: |类型|判定逻辑|语义|建议色| | --- | --- | --- | --- | |区间外|`actual upper`|落在预测区间之外|红| |残差偏置|`|residual|` 显著高于该 SKU 残差分布| |趋势突变|相邻点斜率超过历史分位|行为模式突变|黄| |数据质量|缺值、负值、突降为零|源数据有问题|灰| ![](https://developer.qcloudimg.com/http-save/audit-10133498/f3d95c79a9f76f4bdac4bdf77c399a4c.png) **解析**:这是一条**优先级链,不是并列判断**。区间外最严重、最明确,单独成一类;残差离群要和历史自身比较,避免把天生波动大的 SKU 误杀;趋势突变捕捉的是"模式变了",即便单点不超界也值得关注;数据质量问题则独立于模型存在。**四类用不同颜色编码,是整套系统可读性的根基**——计划员扫一眼颜色就知道要处理什么性质的问题。 --- # 二、数据契约:让异常"带状态"地流动 异常不是一次性计算结果,它是一个**有生命周期的对象**。今天标红的点,可能被标注为"已核实、是促销",也可能被驳回"数据有误待修复"。所以后端下发的字段必须同时承载判定结果与人工状态。 ```javascript { "sku": "SKU-1002331", "series": [ { "ds": "2026-11-11", "actual": 1520, "yhat": 1370, "yhatLower": 1180, "yhatUpper": 1470, "residual": 150, "severity": 3, "codes": ["out_of_band", "residual_outlier"], "status": "open", "annotator": null, "annotatedAt": null, "comment": null } ], "thresholds": { "residualP95": 138, "slopeP95": 0.42, "intervalLevel": 0.8 } } ``` **解析**:`codes` 是数组而非单值,因为一个点上**可以同时命中多类异常**(如既区间外又残差离群),用单字符串就无法表达。`severity` 用 1-3 三级,是视觉编码的输入,也便于列表页排序。`status` 是状态机的核心字段,取值只能是 `open / confirmed / dismissed / resolved` 之一,前端据此控制交互可用性。`thresholds` 必须下发并展示,否则计划员会质疑"凭什么算异常"——**阈值可见是异常系统获得信任的前提**。 --- # 三、分级视觉编码:三级信号叠加 高亮不是把所有异常点都涂红。红色用滥了就等于零,这是视觉告警的通病。正确的做法是用**形状 + 描边 + 填充**三层信号叠加,让最严重的点"穿透"整张图。 ![](https://developer.qcloudimg.com/http-save/audit-10133498/b9daa6db1a2ca243cc97335f1c13bf1e.png) **解析**:三级编码遵循"**越严重,越不可忽略**"的原则。一级只加描边,不抢注意力;二级填充,扫图时能被发现;三级实心加发光,并同步推送到异常清单置顶。**形状和颜色同时编码,能让色弱用户也可读**——这是无障碍合规的基本要求,不能用颜色做唯一通道。 ```javascript const SEVERITY = { 0: { fill: '#9CA3AF', size: 3, stroke: 'none', glow: false }, 1: { fill: '#FBBF24', size: 5, stroke: '#B45309', glow: false }, 2: { fill: '#FB923C', size: 6, stroke: '#C2410C', glow: false }, 3: { fill: '#EF4444', size: 7, stroke: '#991B1B', glow: true }, } export function AnomalyMarkers({ series, onSelect }) { const anomalies = series.filter(d => d.severity > 0) return ( {anomalies.map(d => { const style = SEVERITY[d.severity] const cx = dateToX(d.ds) const cy = valueToY(d.actual) return ( onSelect(d)} tabIndex={0} onKeyDown={e => e.key === 'Enter' && onSelect(d)}> {style.glow && ( )} ) })} ) } ``` **解析**:异常点单独成一层、渲染在实际线**之上**,保证不被曲线遮挡。`SEVERITY` 用查表替代条件判断,新增等级只改配置不改逻辑。**三级加 SVG **`animate`** 脉冲**,是"需要立即处理"的最强信号,且脉冲是 CSS/SVG 原生实现、零 JS 开销。`tabIndex` 和键盘事件让点可用 Tab 聚焦、Enter 选中,是键盘可达性的最低要求。 --- # 四、阈值配置:让业务自己定"什么叫异常" 阈值写死在前端,是异常系统最常见的失败方式。不同品类、不同波动水平的 SKU,异常标准完全不同,必须支持用户调整并即时回看效果。 ![](https://developer.qcloudimg.com/http-save/audit-10133498/9094b665076d5f3bf1aec15eda15ceff.png) **解析**:阈值调整是高频试探动作,必须**即时回算、零网络往返**。只有用户点"保存"时才发请求,这是交互流畅与数据安全的基本平衡。 ```javascript import { useMemo, useState } from 'react' export function ThresholdPanel({ base, onChange }) { const [draft, setDraft] = useState(base) // 本地草稿与已提交值分离,避免误提交 const dirty = JSON.stringify(draft) !== JSON.stringify(base) return ( setDraft({ ...draft, residualP95: v })} /> setDraft({ ...draft, slopeP95: v })} /> onChange(draft)} disabled={!dirty} className="px-3 py-1 bg-indigo-600 text-white rounded disabled:opacity-40"> 应用到本 SKU setDraft(base)} disabled={!dirty} className="px-3 py-1 border rounded">重置 ) } // 纯函数:按当前阈值重算整段序列的异常码 export function detectAnomalies(series, t) { return series.map((d, i) => { if (d.actual == null) return { ...d, severity: 0, codes: [] } const codes = [] if (d.actual > d.yhatUpper || d.actual t.slopeP95) codes.push('trend_shift') } if (Math.abs(d.residual) > t.residualP95) codes.push('residual_outlier') const severity = codes.includes('out_of_band') ? 3 : codes.length >= 2 ? 2 : codes.length === 1 ? 1 : 0 return { ...d, codes, severity } }) } ``` **解析**:`draft` 与 `base` 比对控制"保存"按钮的可点状态,防止空提交,这是表单交互的基本功。`detectAnomalies` 是纯函数,输入序列和阈值、输出带标记的新序列——**纯函数意味着可测试、可复现**,单元测试直接覆盖边界情况(如首点无前驱、实际值为空、残差恰等于阈值)。`severity` 的合并规则体现优先级:区间外一律最高级,多重命中升一级,单类命中为一级。 --- # 五、状态机:从发现到闭环 异常标记不是终点。一个点被标红之后,必须走完"核实—决策—回传"的完整链路,否则系统只会越积越多的红点,最后被计划员无视。 ![](https://developer.qcloudimg.com/http-save/audit-10133498/428f8cc5aa5c8e1fdea241bbd0eb86c2.png) **解析**:`open` 是所有新异常的初始态,只有三种出口,且**每种出口都对应一个后续动作**。这保证了红点不会烂在系统里。`confirmed` 直接对接反馈队列(本系列最后一篇详述);`dismissed` 看似是"忽略",实际在积累规则例外数据,长期看是规则优化的重要样本;`resolved` 则触发重新预测,形成即时反馈。 ```javascript const TRANSITIONS = { open: ['confirmed', 'dismissed', 'resolved'], confirmed: [], dismissed: [], resolved: [], } export function AnnotationPanel({ point, onUpdate }) { const allowed = TRANSITIONS[point.status] || [] const submit = (next, comment) => { if (!allowed.includes(next)) return onUpdate({ ...point, status: next, comment, annotator: currentUser.id, annotatedAt: new Date().toISOString(), }) } return ( {point.ds} 严重度 {point.severity} {point.codes.map(c => • {CODE_LABEL[c]})} onUpdate({ ...point, draftComment: e.target.value })} /> {allowed.map(s => ( submit(s, point.draftComment)} disabled={!point.draftComment?.trim()} className="px-3 py-1 text-sm border rounded disabled:opacity-40"> {STATUS_LABEL[s]} ))} ) } ``` **解析**:`TRANSITIONS` 把状态流转规则**集中在一张表里**,新增状态只改配置,这是状态机模式的核心价值。`allowed` 决定按钮是否渲染,比"渲染了再禁用"更干净——**不该有的动作就不该出现**。提交按钮在说明为空时禁用,因为标注无说明等于无效数据,后端也无法据此学习。 --- # 六、异常清单:从发现到排期 图表上的标记解决"看见",清单解决"处理"。两者必须同步——点击清单行,图表跳转到对应点;点击图上点,清单自动高亮该行。 ![](https://developer.qcloudimg.com/http-save/audit-10133498/1f58ef83b09a8f7b0bd61cee30e1ffa7.png) **解析**:清单默认只显示 `open` 且按严重度降序,是"今天先处理最严重的"这个工作流的直接映射。已 dismissed 的点可展开查看,但不占主列表,避免干扰。虚拟滚动在这里是刚需——一个品类可能有上千个异常点。 ```javascript import { useVirtualizer } from '@tanstack/react-virtual' export function AnomalyList({ items, selected, onSelect }) { const parentRef = useRef(null) const virtualizer = useVirtualizer({ count: items.length, getScrollElement: () => parentRef.current, estimateSize: () => 56, overscan: 8, }) return ( {virtualizer.getVirtualItems().map(vi => { const d = items[vi.index] return ( onSelect(d)}> {d.ds} {d.codes.map(c => CODE_LABEL[c]).join('、')} {(d.actual - d.yhat > 0 ? '+' : '') + (d.actual - d.yhat)} ) })} ) } ``` **解析**:`react-virtual` 只渲染可视区域内的行,`overscan: 8` 让滚动时有缓冲不露白。**行高用固定 56px 并 **`estimateSize`** 声明**,是虚拟滚动流畅的前提——行高不固定会导致滚动条抖动。每行保留颜色点、日期、异常类型、偏差值四段信息,一眼可扫。 --- # 七、性能:前端判定 vs 后端判定 阈值调整的即时回算是前端判定的唯一合理场景,除此之外都应交给后端: |场景|判定位置|原因| | --- | --- | --- | |阈值试探|前端纯函数|需零延迟反馈| |首屏展示|后端下发|避免重复计算| |多 SKU 批量|后端预计算|数据量大| |规则更新|后端|保持一致性| **解析**:1 万点以内前端判定是毫秒级,完全可承受;超过 5 万点就接近一帧预算,**应改为 Worker 或把阈值回算也交给后端**。经验法则是:判定逻辑只在前端保留一份用于交互预览,正式结果一律以后端为准,避免规则分叉。 --- # 结语 异常标记系统的价值不在于"画红点",而在于把模型的不确定性和人工经验接成一条可追踪的链路。本文给出了从判定到闭环的完整设计:四类异常各有判定逻辑与视觉编码,三级严重度用形状、描边、填充和脉冲叠加保证可读与无障碍,阈值可试探调整但规则只保留一份权威源,状态机确保每颗红点都有出口。 阅读本文的收获: - 区间外、残差离群、趋势突变、数据质量必须分开标记并用不同颜色区分; - 颜色不能是唯一通道,需叠加形状编码以兼顾色弱用户; - 阈值调整必须在前端即时回算,但正式结果始终以后端为准,避免规则分叉; - 每个异常点都要走完 confirmed / dismissed / resolved 三种出口,否则红点会堆积到被无视。

优秀的个人博客,低调大师

基于Leaflet的高德AOI数据在天地图底图可视化纠偏实践

# 前言 之前有朋友咨询有一份从高德地图获取的数据。在高德地图上展示时,位置都是没有问题的。但是在底图切换到天地图时,发现空间范围面发生了偏移。想咨询怎么解决这个问题。关于地图中的坐标系,这里不讲述过多的理论知识,关于坐标系的内容,大家可以自行查找一些互联网的资料来进行学习。国内的地图提供商,比如高德、百度、腾讯等等,都会做一些偏移。关于偏移的效果如下所示: ![](https://developer.qcloudimg.com/http-save/yehe-12362774/c5eb2d15c86e0eeea39576b513bbd951.png) 选择天地图作为在线底图是一种常见的做法,也是推荐的做法。如前文所述,在进行一些在线数据的采集时,会将不同的矢量数据在底图中进行展示,因此发生的矢量数据和底图有偏移的情况。如上图中的红色是从高德中采集的原始数据,即偏移的数据,白色范围是对应的在天地图中的准确数据。当然,如果您的底图也是采用高德的底图的话,那么则无需处理这种情况。 本文即在此需求背景下产生,博客内容主要讲述如何从高德地图中查找我们需要的AOI边界数据,如何将采集回来的AOI数据在Leaflet地图中展示,其次讲述使用JavaScript在前端进行高德数据到WGS84坐标的转换,最后综合展示纠偏前和纠偏后的数据,让您对当前的场景有一个综合的了解和熟悉。如果您当前也遇到了这类问题,不妨来这里看看博文。 # 一、高德地图中的AOI数据 AOI数据是兴趣面数据,对应的是POI即兴趣点数据。在空间点的分布当中,通过POI可以找到对应的AOI数据,比如一个小区,可以构建成一个AOI。这里也不深入的讲解什么是AOI,这里以高德地图为例,重点讲解如何在高德地图中查询我们需要的AOI数据,同时可以将高德的AOI数据进行相应的抓取。 ## 1、数据查询 首先我们在浏览器中打开高德地图,将弹出如下界面: ![](https://developer.qcloudimg.com/http-save/yehe-12362774/6114c0d04e0e81eb26c2249854324c71.png) 以上是高德地图的首页,跟我们之前自己实现的Leaflet地图功能类似,可以做地图的缩放,非常清晰的,可以在地图的左上角可以看到可以支持关键词检索。比如在地址检索框中输入“梅溪湖步步高”,可以看到系统做了以下检索: ![](https://developer.qcloudimg.com/http-save/yehe-12362774/6e117ccf8458f4e1f02e14bc8a589c66.png) 可以看到,它在查询检索界面不仅将目标地址进行了列出,同时还在地图中展示了一个空间边界的范围,就是一个商场的外围边界。而这个外围边界就是指的AOI数据。 我们可以在控制台来看一下它的主要请求过程是怎么发生的。 ## 2、服务接口简介 为了能准确的获取目标兴趣点的边界数据,还需要对相关的接口进行介绍。主要分为两个接口。一个是获取目标兴趣点的列表信息,第二个是通过详情id获取坐标信息详情的接口。先来看下检索的过程是怎么处理的,打开网页的调试模式,如下图所示: ![](https://developer.qcloudimg.com/http-save/yehe-12362774/5e868369a9753ddd7a8e3c59d4c9c939.png) 可以在监控窗口可以看到,系统访问的后台服务地址如下: ``` https://www.amap.com/service/poiInfo?query_type=TQUERY&pagesize=20&pagenum=1&qii=true&cluster_state=5&need_utd=true&utd_sceneid=1000&div=PC1000&addr_poi_merge=true&is_classify=true&zoom=16.74&city=430100&geoobj=112.855343%7C28.196778%7C112.866758%7C28.200526&keywords=%E6%AD%A5%E6%AD%A5%E9%AB%98%E6%A2%85%E6%BA%AA%E6%96%B0%E5%A4%A9%E5%9C%B0 ``` 其携带的请求参数如下所示: ![](https://developer.qcloudimg.com/http-save/yehe-12362774/4f7ba920ddced5d246c825c74993f96b.png) 在响应中可以看到有以下的数据列表: ![](https://developer.qcloudimg.com/http-save/yehe-12362774/3f7abb887c4d9ee72269896bc54f02b3.png) 返回的是一个POI的数据列表,打开具体的一条记录,请记住里面的ID字段,这个字典就是后面的数据关联对象。 尤其是打开详情的时候的信息。 ``` { "rating": "4.0", "tel": "", "typecode": "060000", "areacode": "0731", "address": "东方红路657号", "cityname": "长沙市", "display_brand": "", "shape_region": "", "longitude": "112.862798", "review_total": "", "cinemazuo_flag": "0", "diner_flag": "0", "id": "B0KADSUQ7M", "name": "步步高梅溪新天地假日广场", "group_flag": "0", "distance": "0", "entrances": [], "recommend_flag": "3", "exits": [], "adcode": "430104", "domain_list": [ { "type": "html", "id": "1015", "name": "poiclosed" }, { "type": "img", "id": "1003", "name": "icon" }, { "type": "html", "id": "1011", "name": "traffic" }, { "type": "text", "id": "1014", "name": "roadaoi" }, { "type": "button", "id": "1012", "name": "ext_btn" }, { "type": "webimg", "id": "1009", "value": "http://store.is.autonavi.com/showpic/c399c8adab0448847bfa1b8d698fd252", "name": "pic_info" }, { "type": "img", "id": "1008", "name": "overbooked" }, { "type": "img", "id": "1007", "name": "moreservice" }, { "type": "html", "id": "1006", "name": "tag" }, { "type": "text", "id": "1005", "name": "parent_info" }, { "type": "array", "name": "parent_other_rel", "id": "1004" }, { "type": "text", "id": "1010", "name": "business_area" }, { "type": "html", "id": "1002", "name": "deepinfo" }, { "type": "html", "id": "1001", "name": "price" }, { "type": "text", "id": "1013", "name": "aoi" } ], "newtype": "060000", "disp_name": "步步高梅溪新天地假日广场", "cpdata": "", "latitude": "28.196510", "discount_flag": "0" } ``` 在最后打开详情页面,可以找到AOI详情数据。如下图所示: ![](https://developer.qcloudimg.com/http-save/yehe-12362774/920a0bc731e70b6aeb1accce5008c379.png) 访问连接如下: ``` https://www.amap.com/detail/get/detail?id=B0FFHRXORE ``` 在返回的值中就可以找到对应的AOI数据,查看data节点下的spec,再打开mining_shape字段,如下: ![](https://developer.qcloudimg.com/http-save/yehe-12362774/e80920774e90ffd7421acd5a02e8ee5b.png) 到这里,基本就可以获取到高德的AOI数据。下面我们结合天地图来讲解如何进行web展示以及纠偏展示。 # 二、在天地图中展示AOI数据 将面的坐标点导到本地后,就可以将坐标位置展示出来。本节结合天地图和Leaflet来看一下如何将这些面展示出来。 ## 1、对面数据的处理 首先我们来一个真实的AOI输入,数据样例如下所示: ``` "112.869683,28.191884;112.868807,28.191039;112.86821,28.190464;112.867508,28.189842;112.867465,28.189826;112.867417,28.189832;112.867366,28.189852;112.867218,28.189914;112.867173,28.189945;112.86708,28.190037;112.866052,28.191339;112.865927,28.191468;112.865743,28.191696;112.865561,28.19198;112.86546,28.192143;112.864943,28.193369;112.864461,28.194713;112.864407,28.194901;112.863687,28.198129;112.863535,28.198951;112.86354,28.198996;112.863564,28.199039;112.863605,28.199068;112.86367,28.199087;112.864193,28.199117;112.864551,28.199109;112.864858,28.199091;112.866598,28.199148;112.867201,28.199252;112.868416,28.199481;112.868517,28.199511;112.868986,28.199696;112.869025,28.199704;112.86906,28.199706;112.869095,28.199697;112.869139,28.199679;112.870409,28.198994;112.870438,28.198966;112.870451,28.198938;112.870463,28.198907;112.87052,28.198537;112.870597,28.198195;112.870866,28.197445;112.870891,28.197386;112.871148,28.196907;112.871583,28.196115;112.871695,28.195868;112.872088,28.195;112.872085,28.194965;112.872075,28.194937;112.872056,28.194919;112.872032,28.194904;112.870381,28.194416;112.870349,28.194398;112.870313,28.194379;112.87029,28.194356;112.870269,28.194334;112.870255,28.194275;112.87023,28.194178;112.870231,28.194067;112.870262,28.193956;112.870301,28.193888;112.870388,28.193776;112.87045,28.193705;112.870515,28.193636;112.870627,28.193523;112.87066,28.193483;112.870677,28.193449;112.870686,28.193396;112.870689,28.193341;112.870653,28.192904;112.870648,28.192846;112.870631,28.192802;112.870606,28.192773;112.870267,28.192485;112.870243,28.192456;112.870236,28.192425;112.870223,28.192318;112.870218,28.192292;112.870212,28.192266;112.870194,28.192244;112.869794,28.191969;112.869683,28.191884"; ``` 可以看到,这是一个由多个坐标点连续而成的面。两个坐标点之间用;号隔开。而坐标点的经纬度则用逗号隔开。因此我们在Javascript中只需要先按分号分隔字符串,再用逗号分隔就可以形成一个连续的面坐标。关键代码如下: ``` function convertStr2DataArrayNoTrans(strInfo){ var resultData = new Array(); var dataArray = strInfo.split(";"); for(var i = 0;i 137.8347) || ((lat 55.8271) || false) } ``` 接下来,我们将面坐标的构建进行一个简单的封装,跟之前的无转换不同,这里包含了坐标的转换。 ``` function convertStr2DataArrayTrans(strInfo){ var resultData = new Array(); var dataArray = strInfo.split(";"); for(var i = 0;i< dataArray.length;i++){ var _tempLatLon = dataArray[i].split(","); //parseFloat() 这里一定要用parseFloat函数,否则+运算后会变成非数字,导致偏移失败。 var pointJson = gcj02towgs84(parseFloat(_tempLatLon[0]),parseFloat(_tempLatLon[1])); resultData.push([pointJson[1],pointJson[0]]); } return resultData; } ``` 在这里,请注意由于我们的坐标点都是用字符串来表示,因此在传参时一定要转成浮点型来计算,否则将无法正确的计算对应的值。接下来我们将转换后的值叠加到地图当中去: ``` L.polygon([ convertStr2DataArrayTrans(diyishifanStr) ],blueStyle).addTo(map).bindPopup("湖南第一师范学院东方红校区转换数据"); ``` 然后在页面中查看一下具体的面数据,为了有所区别,我们将转换后的数据用白色来描述边界。效果如下: ![](https://developer.qcloudimg.com/http-save/yehe-12362774/b6ad51a5dacf3196a18a29fafb59edce.png) 通过上图可以看到,根据面数据的大小不一,均进行一定的偏移。同时经过我们的数据纠偏操作,成功的将数据进行了天地图的吻合和叠加。通过以上的代码和教程,大家就能掌握具体的纠偏方法。 # 四、总结 以上就是本文的主要内容,博客内容主要讲述如何从高德地图中查找我们需要的AOI边界数据,同时讲解如何将采集回来的AOI数据如何在Leaflet地图中展示,其次讲述如何使用JavaScript在前端进行高德数据到WGS84坐标的转换,最后综合展示纠偏前和纠偏后的数据,让您对当前的场景有一个综合的了解和熟悉。行文仓促,定有许多不足支持,如有不足还恳请各位专家朋友在评论区留言指正,不甚感激。

优秀的个人博客,低调大师

WebBuilder 模板引擎实战教程——零代码实现动态可视化数据卡片

## 一、前言 在企业级后台、ERP、MES、数据中台系统开发中,**数据卡片、指标看板、统计模块**是高频刚需场景。传统开发需要前端编写大量HTML、CSS、JS渲染逻辑,后端封装数据接口,前后端联调耗时费力,且样式复用性差、动态更新繁琐。 WebBuilder 内置自研高性能模板渲染引擎,支持**原生HTML模板 + 动态数据绑定 + 一键局部刷新**,无需复杂JS渲染逻辑,单组件即可完成多指标数据展示、实时更新,完美适配ERP数据看板、经营指标统计、生产数据监控等场景。本文基于完整可运行源码,手把手落地动态模板卡片实战。 ## 二、核心技术能力亮点 - **双向数据绑定**:支持静态默认值、动态对象取值、时间格式化、数字格式化; - **局部增量更新**:无需重载页面,一键更新指定字段数据; - **原生样式封装**:内置全套UI样式类,无需额外写CSS; - **两种渲染模式**:组件模板渲染 + 列表视图模板渲染,适配不同业务场景。 ## 三、完整实战代码解析 ### 1. 静态初始化数据模板 通过 `tplData` 预设初始化数据,模板通过 `{字段名}`、`{[data.字段.子属性]}` 两种语法快速渲染文本、数字、时间、格式化金额。 支持多种数据类型原生解析:百分比、金额美元格式化、自定义文本、12小时制时间、整型数字。 ### 2. 动态局部更新能力 传统开发更新看板数据需要重新请求接口、刷新DOM,WebBuilder 通过 `update()` 方法实现**无刷新局部更新**,仅修改指定字段,性能极致轻量化。 ``` // 一键局部更新模板数据,无需重载页面 app.tplComp.update({ p1: '56.82%', p2: 839213, p4: new Date() }); ``` ## 四、两种渲染方案业务场景适配 ### 1. Component 组件模板(适合固定指标卡片) 适用于ERP首页核心指标、系统概览、固定统计项:增长率、营收、市场数据、系统时间、累计总量等固定维度展示。 ### 2. View 视图模板(适合动态列表指标) ![](https://developer.qcloudimg.com/http-save/yehe-12550059/62fd1bde10b69c908480657a19a63ee8.png) 通过 `itemTpl` 循环渲染列表数据,支持动态增减字段,适合可变维度的数据统计看板,灵活适配企业自定义报表需求。 ## 五、实战落地价值 在ERP系统开发中,首页数据看板、经营统计、库存指标、生产进度统计,使用WebBuilder模板引擎可**省去90%前端渲染代码**,无需搭建接口、无需操作DOM,配置即生效、更新即实时,极大提升后台管理系统、数据中台、MES看板的开发效率。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册