Commit 3dad76cc76c9df78cb3248737e2302a84dc24618
1 parent
ba860f06
feat: commit ThingsKit README-DEFAULT.md
Showing
1 changed file
with
548 additions
and
0 deletions
README-DEFAULT.md
0 → 100644
1 | +## 准备 | |
2 | + | |
3 | +- [node](http://nodejs.org/) 和 [git](https://git-scm.com/) -项目开发环境 | |
4 | +- [layui](http://layui.org.cn/doc/index.html) - UI组件库 | |
5 | +- [jquery](https://jquery.cuishifeng.cn/index.html) - jquery库 | |
6 | +- [video.js](https://videojs.com/) - video.js库 | |
7 | +- [axios](https://axios-http.com/) - http请求库 | |
8 | +- [crypto-js](http://github.com/brix/crypto-js) - 加解密库 | |
9 | +- [echarts](https://echarts.apache.org/examples/zh/index.html) - 可视化图表库 | |
10 | + | |
11 | +## 目录文件及重要文件说明 | |
12 | + | |
13 | +### 目录文件 | |
14 | + | |
15 | +``` | |
16 | +/src/main/webapp/js | |
17 | +├── api api请求管理 | |
18 | +├── config 项目配置 oss 配置等 | |
19 | +├── const 项目中的常量 | |
20 | +├── diagramly | |
21 | +│ ├── sidebar | |
22 | +│ │ └── thingskit 项目新增的元件库 | |
23 | +├── grapheditor 图形编辑器有关文件 | |
24 | +├── plugin 项目中使用的插件 | |
25 | +│ ├── ace | |
26 | +│ ├── axios | |
27 | +│ ├── crypto-js | |
28 | +│ ├── echarts | |
29 | +│ ├── layui | |
30 | +│ │ ├── css | |
31 | +│ │ │ └── modules | |
32 | +│ │ │ ├── laydate | |
33 | +│ │ │ │ └── default | |
34 | +│ │ │ └── layer | |
35 | +│ │ │ └── default | |
36 | +│ │ └── font | |
37 | +│ └── videos | |
38 | +``` | |
39 | + | |
40 | +### 重要文件说明 | |
41 | + | |
42 | +#### 元件库开发 | |
43 | + | |
44 | + | |
45 | + | |
46 | +##### 文件位置 | |
47 | + | |
48 | +``` | |
49 | +. | |
50 | +├── src | |
51 | +│ └── main | |
52 | +│ └── webapp | |
53 | +│ └── js | |
54 | +| └── diagramly | |
55 | +│ └── Devel.js 加载元件库文件 | |
56 | +│ └── sidebar | |
57 | +| └── Sidebar.js 各图形库加载图形 | |
58 | +| └── thingskit 自定义元件库文件 | |
59 | +| └── Sidebar-Engine.js 元件库文件 | |
60 | +├── etc | |
61 | + └── build | |
62 | + └── build.xml 打包自定义元件库 | |
63 | +``` | |
64 | + | |
65 | +##### 源码介绍 | |
66 | + | |
67 | +###### 创建元件库 | |
68 | + | |
69 | +创建需要自定义新增的元件库 !!! 自定义属性 用于确定组件类型件组件和数据绑定面板关联 | |
70 | + | |
71 | +```js | |
72 | +// Sidebar.Engine.js | |
73 | +// src/main/webapp/js/diagramly/sidebar/thingskit/Sidebar-Engine.js | |
74 | +(function () { | |
75 | + // Adds Atlassian shapes | |
76 | + // conduit 管道 | |
77 | + Sidebar.prototype.addConduitPalette = function () { | |
78 | + // 组件归类 决定数据面板中组件有哪些操作面板 | |
79 | + const { COMPONENT_TYPE } = this.enumCellBasicAttribute | |
80 | + const { DEFAULT } = this.enumComponentType | |
81 | + | |
82 | + // 图形库信息 | |
83 | + const gn = 'mxgraph.engine';// 图形库id 后续注册时需要使用 | |
84 | + const dt = 'engine'; //图 形库id 后续注册时需要使用 | |
85 | + const label = '发动机' | |
86 | + | |
87 | + const width = 66; | |
88 | + const height = 74; | |
89 | + const staticPath = `${Proxy_Prefix}/img/lib/thingskit/` | |
90 | + const prefix = 'image;image=img/lib/thingskit/' | |
91 | + const defaultStyle = ';imageAspect=0;' | |
92 | + this.setCurrentSearchEntryLibrary(dt); | |
93 | + | |
94 | + // !!!自定义属性 当前设置该组件库为默认类型 | |
95 | + const cellAttribute = { | |
96 | + [COMPONENT_TYPE]: DEFAULT | |
97 | + } | |
98 | + | |
99 | + const graphPathLib = [ | |
100 | + { name: '3-D 发动机.svg', path: 'engine/3-D 发动机.svg' }, | |
101 | + ] | |
102 | + | |
103 | + const lib = graphPathLib.map(item => { | |
104 | + item.staticPath = staticPath + item.path | |
105 | + return item | |
106 | + }) | |
107 | + | |
108 | + const fns = graphPathLib.map(item => { | |
109 | + return this.addEntry(this.getTagsForStencil(gn, item.name, dt).join(' '), mxUtils.bind(this, function () { | |
110 | + const cell = new mxCell('', new mxGeometry(0, 0, width, height), `${prefix}${item.path}${defaultStyle}`); | |
111 | + cell.setVertex(true) | |
112 | + this.setCellAttributes(cell, cellAttribute) | |
113 | + return this.createVertexTemplateFromCells([cell], cell.geometry.width, cell.geometry.height, item.name); | |
114 | + })); | |
115 | + }) | |
116 | + | |
117 | + this.setVariableImageLib(dt, label, lib) | |
118 | + | |
119 | + this.addPaletteFunctions(dt, label, false, fns); | |
120 | + | |
121 | + this.setCurrentSearchEntryLibrary(); | |
122 | + }; | |
123 | +})(); | |
124 | + | |
125 | +``` | |
126 | + | |
127 | +>2. 将元件库导入 | |
128 | + | |
129 | +```js | |
130 | +// src/main/webapp/js/diagramly/Devel.js | |
131 | +// Devel.js | |
132 | +// 将Sidebar-Engine.js引入 | |
133 | +mxscript(drawDevUrl + 'js/diagramly/sidebar/thingskit/Sidebar-Engine.js'); | |
134 | +``` | |
135 | + | |
136 | +>3. 将元件库加入到需要打包的文件队列中 | |
137 | + | |
138 | +```xml | |
139 | + <!-- build.xml --> | |
140 | + <!-- /etc/build/build.xml --> | |
141 | + <!-- 将Sidebar-Engine.js添加至需要打包的文件中去 --> | |
142 | +<jscomp compilationLevel="simple" debug="false" forceRecompile="true" output="${basedir}/sidebar.min.js"> | |
143 | + ... | |
144 | + <file name="./thingskit/Sidebar-Engine.js" /> | |
145 | +</jscomp> | |
146 | +``` | |
147 | + | |
148 | +>4. 将元件库注册到侧边栏 | |
149 | + | |
150 | +```js | |
151 | +// Sidebar.js | |
152 | +// src/main/webapp/js/diagramly/sidebar/Sidebar.js | |
153 | +// 将图形库id加入Siderbar中 | |
154 | +Sidebar.prototype.configuration = [ | |
155 | + ... | |
156 | + { id: 'engine' } // 图形库id | |
157 | +] | |
158 | +// 添加到更多图形中去 | |
159 | +Sidebar.prototype.init = function () { | |
160 | + ... | |
161 | + var thingskitEntries = [ | |
162 | + // 注册至到更多图形中 | |
163 | + { title: "发动机", id: 'engine', image: IMAGE_PATH + '/thingskit/发动机.png' } | |
164 | + ]; | |
165 | + } | |
166 | +// 添加到侧边栏中 | |
167 | +Sidebar.prototype.initPalettes = function () { | |
168 | + ... | |
169 | + // 发动机 | |
170 | + this.addEnginePalette(); | |
171 | +} | |
172 | +``` | |
173 | + | |
174 | +#### 数据绑定面板开发 | |
175 | + | |
176 | + | |
177 | + | |
178 | + | |
179 | + | |
180 | +##### 文件位置 | |
181 | + | |
182 | +``` | |
183 | +/src/main/webapp/js | |
184 | +├── grapheditor | |
185 | +│ ├── Format.js | |
186 | +``` | |
187 | + | |
188 | +##### 源码介绍 | |
189 | + | |
190 | + | |
191 | + | |
192 | +>控制元件拥有哪些数据绑定面板,通过 this.setComponentPermission 方法设置各个类型的元件有哪些数据绑定面板。 | |
193 | + | |
194 | +```js | |
195 | +// Sidebar.js | |
196 | +// src/main/webapp/js/diagramly/sidebar/Sidebar.js | |
197 | + Sidebar.prototype.init = function () { | |
198 | + const { LINE_CHART_EXPAND, BAR_CHART_EXPAND, DASHBOARD_CHART_EXPAND, DYNAMIC_EFFECT, DATA_SOURCE, VAR_IMAGE, INTERACTION, VIDEO: VIDEO_PANEL, SWITCH_STATE_SETTING, ONLY_SINGLE_EVENT, RUNNING_AND_STOP } = this.enumPermissionPanel | |
199 | + const { LINE, LINE_CHART, REAL_TIME, TITLE, VARIABLE, DEFAULT, BAR_CHART, VIDEO, SWITCH, PARAMS_SETTING_BUTTON, DASHBOARD_CHART, IMAGE } = this.enumComponentType | |
200 | + | |
201 | + // 水流类型元件拥有水流效果面板与数据东西面板 | |
202 | + this.setComponentPermission(LINE, [RUNNING_AND_STOP, DYNAMIC_EFFECT]) | |
203 | + // 默认类型的元件拥有数据动效面板 | |
204 | + this.setComponentPermission(DEFAULT, [DYNAMIC_EFFECT]) | |
205 | + this.setComponentPermission(REAL_TIME, [DYNAMIC_EFFECT]) | |
206 | + // 标题类型的元件拥有数据交互面板与动态数据面板 | |
207 | + this.setComponentPermission(TITLE, [INTERACTION, DYNAMIC_EFFECT]) | |
208 | + this.setComponentPermission(VAR_IMAGE, [INTERACTION, VAR_IMAGE]) | |
209 | + this.setComponentPermission(VARIABLE, [DATA_SOURCE, INTERACTION, DYNAMIC_EFFECT]) | |
210 | + this.setComponentPermission(BAR_CHART, [DATA_SOURCE, BAR_CHART_EXPAND]) | |
211 | + this.setComponentPermission(LINE_CHART, [DATA_SOURCE, LINE_CHART_EXPAND]) | |
212 | + this.setComponentPermission(DASHBOARD_CHART, [DATA_SOURCE, DASHBOARD_CHART_EXPAND]) | |
213 | + this.setComponentPermission(VIDEO, [VIDEO_PANEL]) | |
214 | + this.setComponentPermission(SWITCH, [DATA_SOURCE, SWITCH_STATE_SETTING]) | |
215 | + this.setComponentPermission(PARAMS_SETTING_BUTTON, [DATA_SOURCE, ONLY_SINGLE_EVENT]) | |
216 | + this.setComponentPermission(IMAGE, [DATA_SOURCE]) | |
217 | + } | |
218 | +``` | |
219 | + | |
220 | + | |
221 | + | |
222 | +>Format.js 根据元件拥有的权限渲染数据绑定面板,如上图开关元件与变量元件数据绑定面板的差异化渲染。 | |
223 | + | |
224 | +```js | |
225 | +// 数据绑定面板的开发源码均在此方法中 | |
226 | +// 开发使用layui与jquery库 | |
227 | +// src/main/webapp/js/grapheditor/Format.js | |
228 | +DataFormatPanel.prototype.addDataFont = function () { | |
229 | + | |
230 | + // 该方法用于根据元件类型渲染不同的面板 | |
231 | + async function initNode() { | |
232 | + const basicAttr = sidebarInstance.enumCellBasicAttribute | |
233 | + const permissionKey = sidebarInstance.enumPermissionPanel | |
234 | + const { LINE_CHART, BAR_CHART, DASHBOARD_CHART } = Sidebar.prototype.enumComponentType | |
235 | + | |
236 | + const renderMapping = { | |
237 | + // 元件拥有数据源权限 | |
238 | + [permissionKey.DATA_SOURCE]: createDataSourcePanel, | |
239 | + // 元件拥有图表数据绑定面板 | |
240 | + [permissionKey.LINE_CHART_EXPAND]: createChartBindPanel.bind(this, LINE_CHART), | |
241 | + [permissionKey.BAR_CHART_EXPAND]: createChartBindPanel.bind(this, BAR_CHART), | |
242 | + // 元件拥有数据源拓展面板 | |
243 | + [permissionKey.DASHBOARD_CHART_EXPAND]: createChartBindPanel.bind(this, DASHBOARD_CHART), | |
244 | + // 元件拥有数据交互面板 | |
245 | + [permissionKey.INTERACTION]: createInteractionPanel, | |
246 | + // 元件拥有数据动效面板 | |
247 | + [permissionKey.DYNAMIC_EFFECT]: createDynamicEffectPanel, | |
248 | + // 元件库拥有变量图片选项 | |
249 | + [permissionKey.VAR_IMAGE]: createVarImagePanel, | |
250 | + // 元件库拥有视频配置面板 | |
251 | + [permissionKey.VIDEO]: createVideoBindPanel, | |
252 | + // 元件库拥有开关状态切换面板 | |
253 | + [permissionKey.SWITCH_STATE_SETTING]: createSwitchStateSettingPanel, | |
254 | + } | |
255 | + | |
256 | + // 根据元件的权限渲染数据绑定面板 | |
257 | + function permissionRender() { | |
258 | + try { | |
259 | + const cell = vertices[0] | |
260 | + const permission = graph.getAttributeForCell(cell, basicAttr.COMPONENT_TYPE) | |
261 | + const needDisplayPanel = sidebarInstance.getComponentPermission(permission) | |
262 | + for (const key of needDisplayPanel) { | |
263 | + renderMapping[key]() | |
264 | + } | |
265 | + if (needDisplayPanel.length) createSubmitPanel() | |
266 | + UseLayUi.nextTick(() => form.render()) | |
267 | + } catch (e) { | |
268 | + throw Error('component permission setting has some problem, please check your component permission bind on "Sidebar.prototype.init" method setComponentPermission') | |
269 | + } | |
270 | + } | |
271 | + } | |
272 | + | |
273 | + // 该方法用于创建提交按钮以及根据元件类型做提交参数转换处理 | |
274 | + function createSubmitPanel() { | |
275 | + ... | |
276 | + const value = getValueOnSubmit(field) | |
277 | + } | |
278 | + | |
279 | + // 根据元件类型做上传参数转换 | |
280 | + function getValueOnSubmit(field) { | |
281 | + const basicAttr = sidebarInstance.enumCellBasicAttribute | |
282 | + const componentType = sidebarInstance.enumComponentType | |
283 | + ... | |
284 | + const renderMapping = { | |
285 | + [componentType.BAR_CHART]: getChartSubmitValue, | |
286 | + [componentType.DEFAULT]: getSubmitValue, | |
287 | + [componentType.VIDEO]: getVideoSubmitValue, | |
288 | + [componentType.SWITCH]: getSwitchSubmitValue, | |
289 | + } | |
290 | + | |
291 | + ... | |
292 | + | |
293 | + // 处理方法 | |
294 | + function getChartSubmitValue() {} | |
295 | + function getSubmitValue() {} | |
296 | + function getVideoSubmitValue() {} | |
297 | + function getSwitchSubmitValue() {} | |
298 | + | |
299 | +} | |
300 | +``` | |
301 | + | |
302 | +>WebSocket接收数据,前端根据页面组件做发布订阅处理。 | |
303 | + | |
304 | +```js | |
305 | +// src/main/webapp/js/grapheditor/Format.js | |
306 | + | |
307 | +// 事件中心 发布订阅 | |
308 | +class EventCenter { | |
309 | + ... | |
310 | +} | |
311 | +// socket 相关 | |
312 | +class Ws { | |
313 | + .... | |
314 | +} | |
315 | + | |
316 | +// 调度中心 | |
317 | +class DispatchCenter { | |
318 | + // ... | |
319 | + // 初始化方法 | |
320 | + async init(editorUi, currentPage) { | |
321 | + // 创建事件中心 | |
322 | + this.createEventBus() | |
323 | + // 获取页面所有节点 | |
324 | + this.saveContentInfo(editorUi, currentPage) | |
325 | + // 建立socket连接 | |
326 | + this.connectSocket() | |
327 | + // 获取页面中所有绑定数据源的组件记录 | |
328 | + await this.getContentDataNode() | |
329 | + // 实例化各个处理模块 各个处理模块 | |
330 | + this.dataSourceHandlerInstance = new HandleDataSource(this) | |
331 | + this.dataInteractionInstance = new HandleDataInteraction(this) | |
332 | + this.dynamicEffectInstance = new HandleDynamicEffect(this) | |
333 | + // 更新队列 | |
334 | + this.updateQueueInstance = new UpdateQueue(this) | |
335 | + this.sendSubscribeMessage() | |
336 | + } | |
337 | + // 创建订阅消息模型 将 消息分类汇总过滤,重复数据源只订阅一条消息 | |
338 | + generateSubscribeMessage() { | |
339 | + // ... | |
340 | + } | |
341 | + | |
342 | + // 根据socket接受消息 调用不同的处理逻辑 | |
343 | + socketOnMessage() { | |
344 | + // ... | |
345 | + // 查找当前订阅id中,绑定的相同数据源 | |
346 | + const subList = this.subscribeIdMapping.get(subscriptionId) | |
347 | + subList.forEach(item => { | |
348 | + // ... | |
349 | + // 根据绑定的数据源判断调用的处理逻辑 例如调用 HandleDataSource 实例中的updateCommonDataSource 方法 | |
350 | + this.dataSourceHandlerInstance.updateCommonDataSource(message, item) | |
351 | + } | |
352 | + } | |
353 | + | |
354 | +} | |
355 | + | |
356 | + | |
357 | + | |
358 | +// 处理数据源 | |
359 | +class HandleDataSource { | |
360 | + ... | |
361 | + // 根据元件类型分发处理逻辑 | |
362 | + updateCommonDataSource(message, record) { | |
363 | + const { nodeId, attr } = record | |
364 | + const node = this.getNodeByCmdId(nodeId) | |
365 | + node && this.updatePage(() => { | |
366 | + const { data } = message | |
367 | + const type = this.getComponentType(node) | |
368 | + // ... | |
369 | + // 元件类型为图片时 | |
370 | + if (type === this.componentType.IMAGE) { | |
371 | + this.handleImageComponent(message, record) | |
372 | + return | |
373 | + } | |
374 | + }, node) | |
375 | + // ... | |
376 | + } | |
377 | + // 图片处理逻辑 | |
378 | + handleImageComponent(message, record) { | |
379 | + const { data = {} } = message | |
380 | + const { nodeId, attr } = record | |
381 | + const node = this.getNodeByCmdId(nodeId) | |
382 | + const [[_timespan, receiveValue] = []] = data[attr] || [] | |
383 | + this.updatePage(() => { | |
384 | + // 更新节点中的图片 | |
385 | + node.setAttribute('label', `<img class="basic-component__image" alt="图片" src="${receiveValue}" />`) | |
386 | + }, node) | |
387 | + } | |
388 | +} | |
389 | +// 处理数据交互 | |
390 | +class HandleDataInteraction { | |
391 | + ... | |
392 | +} | |
393 | +// 处理数据动效 | |
394 | +class HandleDynamicEffect { | |
395 | + ... | |
396 | +} | |
397 | +// 建立更新队列 | |
398 | +class UpdateQueue { | |
399 | + ... | |
400 | +} | |
401 | +``` | |
402 | + | |
403 | + | |
404 | + | |
405 | +#### const.js | |
406 | + | |
407 | +##### 文件位置 | |
408 | + | |
409 | +``` | |
410 | +/src/main/webapp/js | |
411 | +├── const | |
412 | +│ ├── const.js // 定义项目中的常量 | |
413 | +│ ├── persistentStorage.js // 加解密storage,与后台管理系统一致 | |
414 | +``` | |
415 | + | |
416 | +##### 源码介绍 | |
417 | + | |
418 | +> 1. const.js 常量名 | |
419 | + | |
420 | +``` | |
421 | +GLOBAL_TOKEN 访问令牌: | |
422 | + 用于请求中携带 | |
423 | + 来源于后台管理系统中存储在storage中的值,storage中的值涉及在生产环境和开发环境中是否加解密问题,加解密方式应与后台管理系统中 一致。 | |
424 | + | |
425 | +GLOBAL_PLATFORM_INFO 平台信息 | |
426 | + 用于项目中需要使用平台信息的场景,例如首屏加载时的loading,显示不同平台的平台名。 | |
427 | + | |
428 | +GLOBAL_WS_URL socket地址 | |
429 | + 用于项目中socket连接 | |
430 | + | |
431 | +hasSavePermission 检查是否权限 | |
432 | + 用于检查组态中时候拥有写入的权限 | |
433 | +``` | |
434 | + | |
435 | +> 2. persistentStorage.js 加解密storage相关 | |
436 | + | |
437 | +### 配置文件 | |
438 | + | |
439 | +#### OSS打包配置 | |
440 | + | |
441 | +##### 文件位置 | |
442 | + | |
443 | +``` | |
444 | +/src/main/webapp/js | |
445 | +├── config | |
446 | +│ ├── config.js | |
447 | +``` | |
448 | + | |
449 | +##### 源码介绍 | |
450 | + | |
451 | +```js | |
452 | +/** | |
453 | + * @description 加载OSS文件时使用的oss文件路径 | |
454 | + */ | |
455 | +const OSS_Prefix = 'https://oss.xxx.com/' | |
456 | +/** | |
457 | + * @description 是否使用OSS文件 开启时生产环境中使用oss服务的文件将从oss服务器中加载。 | |
458 | + */ | |
459 | +const Enable_OSS = false | |
460 | + | |
461 | +/** | |
462 | + * @description 代理配置项 | |
463 | + */ | |
464 | +const Proxy_Prefix = window.location.pathname.startsWith('/') ? window.location.pathname.replace(/\/$/, '') : window.location.pathname | |
465 | +``` | |
466 | + | |
467 | +```js | |
468 | +// index.html | |
469 | +// 例如在index.html中使用Enable_OSS判断是否开启OSS模式,开启则通过 OSS_Prefix 配置的oss服务器地址中加载文件 | |
470 | +const appMinSrc = Enable_OSS ? `${OSS_Prefix}app.min.js?v=${releaseVersion}` : `js/app.min.js?v=${releaseVersion}` | |
471 | +``` | |
472 | + | |
473 | +#### 项目打包配置 | |
474 | + | |
475 | +##### gulpfile.js执行流程 | |
476 | + | |
477 | +> 项目基于draw.io二次开发,使用ant进行打包,打包时不能编译es6+语法,如async,await, class等语法,使用新语法时会导致打包失败,因此先使用glup先编译,在通过ant打包。 | |
478 | + | |
479 | +```js | |
480 | +// 1.打包前先复制需要编译的文件源码 | |
481 | +function copyFile() {} | |
482 | +// 2.编译文件 | |
483 | +function complieFormat() {} | |
484 | +// 3.引入的文件增加版本号(用于打包部署后服务器上文件不更新) | |
485 | +function generatoreVersion(){} | |
486 | +// 4.构建war包 | |
487 | +async function buildWar() {} | |
488 | +// 5.复制需要上传到oss服务器中的文件 | |
489 | +function copyFileUsageOssServer() {} | |
490 | +// 6.还原文件 | |
491 | +function reductionFile() {} | |
492 | +// 7.清除复制的文件 | |
493 | +function clean() {} | |
494 | +``` | |
495 | + | |
496 | +## 开发环境搭建及源码运行 | |
497 | + | |
498 | +## 打包部署 | |
499 | + | |
500 | +### 准备工作 | |
501 | + | |
502 | +1. [JDK]([Download Java for macOS](https://www.java.com/zh-CN/download/))安装与环境变量配置(项目使用JDK11) [安装文档](https://blog.csdn.net/Marvin_996_ICU/article/details/106240065) | |
503 | +2. [Apache Ant]([Apache Ant - Welcome](https://ant.apache.org/))安装与环境变量配置(项目使用Ant version 1.10.12 版本) [安装文档](https://www.yiibai.com/ant/ant_environment.html#) ,安装Apache Ant 1 确保将JAVA_HOME环境变量设置到安装JDK的文件夹。 2 下载的二进制文件从 http%3A%2F%2Fant.apache.org 3,创建一个名为ANT_HOME,一个新的环境变量指向Ant的安装文件夹,在 c%3Aapache-ant-1.8.2-bin 文件夹。 5 附加的路径Apache Ant批处理文件添加到PATH环境变量中。 在我们的例子是 c%3Aapache-ant-1.8.2-binbin文件夹。)) | |
504 | +3. [Node.js]([Node.js (nodejs.org)](https://nodejs.org/en/))安装(项目使用v16.15.0版本) | |
505 | + | |
506 | +### 运行打包 | |
507 | + | |
508 | +```sh | |
509 | +# 安装依赖 | |
510 | +npm install | |
511 | + | |
512 | +# 运行打包 运行后开始打包 预计耗时1min | |
513 | +npm build | |
514 | + | |
515 | +``` | |
516 | + | |
517 | +> 打包成功后控制台输出结果与包存放位置,oss文件存放需要上传至oss服务器的js文件。 | |
518 | + | |
519 | + | |
520 | + | |
521 | + | |
522 | + | |
523 | + | |
524 | + | |
525 | +## 参考文档 | |
526 | + | |
527 | +* [mxGraph]([API Specification (jgraph.github.io)](https://jgraph.github.io/mxgraph/docs/js-api/files/index-txt.html)) - mxGraph 库 Api 文档 | |
528 | +* [Draw.io常见问题]([diagrams.net Frequently Asked Questions](https://www.diagrams.net/doc/faq/)) - Draw.io常见问题 | |
529 | +* [掘金二开文章一]([mxgraph配合draw.io再次使用总结 - 掘金 (juejin.cn)](https://juejin.cn/post/7065578041140838436)) - 掘金二次开发参考文章 | |
530 | +* [掘金二开文章二]([DrawIO 二开 —— 是时候给你的 ProcessOn 充值终身 VIP 了 - 掘金 (juejin.cn)](https://juejin.cn/post/7017686432009420808#heading-8)) - 掘金二次开发参考文章 | |
531 | +* [mxGraph二开文章一]([mxGraph入门 (gitee.io)](https://bibichuan.gitee.io/posts/3337d458.html)) - mxGraph二次开发参考文章 | |
532 | +* [mxGraph二开文章二]([mxGraph教程 - 李理的博客 (fancyerii.github.io)](http://fancyerii.github.io/2019/03/26/mxgraph/)) - mxGraph二次开发参考文章 | |
533 | + | |
534 | +## FAQ | |
535 | + | |
536 | +1. 打包过程中发生失败时,可能回导致需要gulp编译的文件被覆盖。应检查需要编译的文件是否已经被gulp编译。 | |
537 | + | |
538 | + 左侧文件则被gulp编译,失败时则到dist目录中找到未被编译的文件或者通过git进行回滚,在解决打包失败的原因后,再次打包。 | |
539 | + | |
540 | +  | |
541 | + | |
542 | +  | |
543 | + | |
544 | +2. 打包后index.html会发生变更,引入文件的版本号修改,导致index.html被git追踪,可以通过将index.html加入git忽略文件中去。 | |
545 | + | |
546 | +  | |
547 | + | |
548 | +3. 组态启动后的端口因与后台管理端的端口保持一致。 | |
\ No newline at end of file | ... | ... |