DiagramTemplate.vue 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968
  1. <template>
  2. <div>
  3. <el-row>
  4. <!-- 模板树 -->
  5. <el-col :span="6" >
  6. <div style="height: 100vh;overflow: scroll;">
  7. <el-tree :data="templates" :props="{children: 'children', label: nodeLabel, value: 'id'}"
  8. @node-click="openTemplate"
  9. default-expand-all
  10. :expand-on-click-node="false"
  11. style="width: 500px;">
  12. <span class="custom-tree-node" slot-scope="{ node, data }">
  13. <span>{{ node.label}}</span>
  14. <span style="padding-left: 10px;">
  15. <el-button type="text" size="mini" icon="el-icon-plus" @click="() => newTemplate(node)" v-if="data.type == 'type'">
  16. 新建模板
  17. </el-button>
  18. <el-popconfirm title="确定删除模板?" v-if="data.diagramType" @confirm="() => delTemplate(node)">
  19. <el-button slot="reference" type="text" size="mini" icon="el-icon-remove">删除</el-button>
  20. </el-popconfirm>
  21. <el-button slot="reference" type="text" @click="() => editTemplate(node)" v-if="data.diagramType" size="mini" icon="el-icon-edit">修改</el-button>
  22. </span>
  23. </span>
  24. </el-tree>
  25. </div>
  26. </el-col>
  27. <!-- 编辑区 -->
  28. <el-col :span="18" style="border-left: 1px solid #f4f4f4">
  29. <!-- 工具条 -->
  30. <div ref="header" style="padding: 2px;border-bottom: 1px solid #f4f4f4">
  31. <span class="editor-title">{{currentTemplate.name}}</span>
  32. <el-button-group>
  33. <el-button size="mini" @click="() => addCon()" :disabled="!(state == 1 && !isEquipCompSel())">添加容器</el-button>
  34. </el-button-group>
  35. <el-button-group>
  36. <el-button size="mini" @click="() => moveCon(-1)" :disabled="state != 1">上移/左移</el-button>
  37. <el-button size="mini" @click="() => moveCon(1)" :disabled="state != 1">下移/右移</el-button>
  38. </el-button-group>
  39. &nbsp;
  40. <el-button-group>
  41. <el-button size="mini" @click="() => setProps()" :disabled="!(state == 1 || state == 2)">属性设置</el-button>
  42. <el-popconfirm title="确定删除选中对象?" @confirm="() => delCon()">
  43. <el-button slot="reference" size="mini" :disabled="!(state == 1 || state == 2)">删除</el-button>
  44. </el-popconfirm>
  45. </el-button-group>
  46. &nbsp;
  47. <el-button-group>
  48. <el-button size="mini" @click="() => editFilter()" :disabled="!isEquipCompSel()">设备过滤</el-button>
  49. <el-button size="mini" @click="() => editPack()" :disabled="!isEquipCompSel() || state != 1">设备打包</el-button>
  50. </el-button-group>
  51. &nbsp;
  52. <el-button-group>
  53. <el-button size="mini" @click="() => editDynGroup()" :disabled="state != 1 || isEquipCompSel()">动态组</el-button>
  54. </el-button-group>
  55. &nbsp;
  56. <el-button-group>
  57. <el-button size="mini" @click="() => beginMainLine()" :disabled="state == -1 || state == 9">绘制干管/线</el-button>
  58. <el-button size="mini" @click="() => nextLine()" :disabled="state != 9">下一条线</el-button>
  59. <el-button size="mini" @click="() => cancelMainLine()" :disabled="state != 9">取消绘制</el-button>
  60. <el-button size="mini" @click="() => finishMainLine()" :disabled="state != 9">完成绘制</el-button>
  61. </el-button-group>
  62. <!--选中信息-->
  63. <div class="info">
  64. <span>{{selectionInfo}}</span>
  65. <span style="margin-left: 30px;color: #a3a3a3;">{{dynInfo}}</span>
  66. </div>
  67. </div>
  68. <!-- 编辑界面 -->
  69. <div ref="editor" :style="editorStyle">
  70. </div>
  71. </el-col>
  72. </el-row>
  73. <!-- 模板信息对话框 -->
  74. <el-dialog title="容器属性" :visible.sync="dlgTemplateVisible">
  75. <div class="el-dialog-div">
  76. <el-form :model="propsData" label-width="130px">
  77. <el-form-item label="模板名称">
  78. <el-input v-model="propsData.name"></el-input>
  79. </el-form-item>
  80. <el-form-item label="备注">
  81. <el-input
  82. type="textarea"
  83. :rows="2"
  84. v-model="propsData.remark">
  85. </el-input>
  86. </el-form-item>
  87. </el-form>
  88. </div>
  89. <div slot="footer" class="dialog-footer">
  90. <el-button @click="dlgTemplateVisible = false">取 消</el-button>
  91. <el-button type="primary" @click='modifyTemplate'>确 定</el-button>
  92. </div>
  93. </el-dialog>
  94. <!-- 编辑容器对话框 -->
  95. <el-dialog title="容器属性" :visible.sync="dlgConVisible">
  96. <div class="el-dialog-div">
  97. <el-form :model="propsData" label-width="130px">
  98. <el-form-item label="容器Id">
  99. <el-input v-model="propsData.id" :disabled="propsData.root"></el-input>
  100. </el-form-item>
  101. <el-form-item label="容器名称">
  102. <el-input v-model="propsData.name" :disabled="propsData.root"></el-input>
  103. </el-form-item>
  104. <el-form-item label="备注">
  105. <el-input
  106. type="textarea"
  107. :rows="2"
  108. v-model="propsData.remark">
  109. </el-input>
  110. </el-form-item>
  111. <br>
  112. <el-form-item label="布局方式">
  113. <el-radio-group v-model="propsData.layout">
  114. <el-radio :label="1">行式</el-radio>
  115. <el-radio :label="2">列式</el-radio>
  116. </el-radio-group>
  117. </el-form-item>
  118. <el-form-item label="边距">
  119. <el-input-number v-model="propsData.margin" :min="2" :max="200"></el-input-number>
  120. </el-form-item>
  121. <el-form-item label="间距">
  122. <el-input-number v-model="propsData.space" :min="2" :max="200"></el-input-number>
  123. </el-form-item>
  124. <br>
  125. <el-form-item label="预设高度">
  126. <el-input-number v-model="propsData.minH" :min="100" :max="1000" :disabled="propsData.root"></el-input-number>
  127. </el-form-item>
  128. <el-form-item label="预设宽度">
  129. <el-input-number v-model="propsData.minW" :min="100" :max="1000" :disabled="propsData.root"></el-input-number>
  130. </el-form-item>
  131. <el-form-item label="定位">
  132. <el-checkbox v-model="propsData.absolute" :disabled="propsData.root">自由定位</el-checkbox>
  133. </el-form-item>
  134. <br>
  135. <el-form-item label="设备容器">
  136. <el-select
  137. v-model="propsData.equipTypes"
  138. multiple
  139. placeholder="设备类型,输入名称或代码搜索"
  140. style="width: 600px;"
  141. :disabled="propsData.root || propsData.hasChildren"
  142. filterable
  143. remote
  144. :remote-method="queryEquipTypes"
  145. >
  146. <el-option
  147. v-for="item in equipOptions"
  148. :key="item.id"
  149. :label="item.name + ' - ' + item.code"
  150. :value="item.code">
  151. </el-option>
  152. </el-select>
  153. </el-form-item>
  154. <el-form-item label="无设备时自动隐藏" v-if="propsData.equipTypes && propsData.equipTypes.length > 0">
  155. <el-radio-group v-model="propsData.auto_hidden">
  156. <el-radio :label="true">是</el-radio>
  157. <el-radio :label="false">否</el-radio>
  158. </el-radio-group>
  159. </el-form-item>
  160. </el-form>
  161. </div>
  162. <div slot="footer" class="dialog-footer">
  163. <el-button @click="dlgConVisible = false">取 消</el-button>
  164. <el-button type="primary" @click='modifyCon'>确 定</el-button>
  165. </div>
  166. </el-dialog>
  167. <!-- 编辑干管对话框 -->
  168. <el-dialog title="干管属性" :visible.sync="dlgLineVisible">
  169. <el-form :model="propsData" label-width="200px">
  170. <el-form-item label="Id">
  171. <el-input v-model="propsData.id"></el-input>
  172. </el-form-item>
  173. <el-form-item label="名称">
  174. <el-input v-model="propsData.name"></el-input>
  175. </el-form-item>
  176. <el-form-item label="备注">
  177. <el-input
  178. type="textarea"
  179. :rows="2"
  180. v-model="propsData.remark">
  181. </el-input>
  182. </el-form-item>
  183. <el-form-item label="类型">
  184. <el-radio-group v-model="propsData.pipeType">
  185. <el-radio :label="null">无</el-radio>
  186. <el-radio label="supply">供</el-radio>
  187. <el-radio label="return">回</el-radio>
  188. </el-radio-group>
  189. </el-form-item>
  190. <br>
  191. <el-form-item label="应用模式">
  192. <el-radio-group v-model="propsData.bindEquipment">
  193. <el-radio :label="false">承载连接关系</el-radio>
  194. <el-radio :label="true">绑定管道设备</el-radio>
  195. </el-radio-group>
  196. </el-form-item>
  197. <br>
  198. <el-form-item label="可放置在干管上的设备">
  199. <el-select
  200. v-model="propsData.equipTypes"
  201. multiple
  202. placeholder="设备类型,输入名称或代码搜索"
  203. style="width: 600px;"
  204. :disabled="propsData.root"
  205. filterable
  206. remote
  207. :remote-method="queryEquipTypes"
  208. >
  209. <el-option
  210. v-for="item in equipOptions"
  211. :key="item.id"
  212. :label="item.name + ' - ' + item.code"
  213. :value="item.code">
  214. </el-option>
  215. </el-select>
  216. </el-form-item>
  217. <br>
  218. <el-form-item label="干管承载的关系类型" v-if="!propsData.bindEquipment">
  219. <el-cascader
  220. placeholder="搜索"
  221. :options="dicRels" :props="{expandTrigger: 'hover', multiple: true, label: 'name', value: 'code'}"
  222. v-model="propsData.passbyRels" filterable collapse-tags clearable
  223. ref="relCascader" style="width: 400px;"></el-cascader>
  224. </el-form-item>
  225. <el-form-item label="直连干管的设备类型">
  226. <el-select
  227. v-model="propsData.connectEquips"
  228. multiple
  229. placeholder="设备类型,输入名称或代码搜索"
  230. style="width: 600px;"
  231. filterable
  232. remote
  233. :remote-method="queryEquipTypes"
  234. >
  235. <el-option
  236. v-for="item in equipOptions"
  237. :key="item.id"
  238. :label="item.name + ' - ' + item.code"
  239. :value="item.code">
  240. </el-option>
  241. </el-select>
  242. </el-form-item>
  243. </el-form>
  244. <div slot="footer" class="dialog-footer">
  245. <el-button @click="dlgLineVisible = false">取 消</el-button>
  246. <el-button type="primary" @click='modifyMainPipe'>确 定</el-button>
  247. </div>
  248. </el-dialog>
  249. <!-- 设备过滤对话框 -->
  250. <el-dialog title="设备过滤" :visible.sync="dlgFilterVisible">
  251. <FilterPanel ref="filterPanel" :dataFilter="dataFilter"></FilterPanel>
  252. <div slot="footer" class="dialog-footer">
  253. <el-button @click="dlgFilterVisible = false">取 消</el-button>
  254. <el-button type="primary" @click='modifyFilter'>确 定</el-button>
  255. </div>
  256. </el-dialog>
  257. <!-- 设备打包对话框 -->
  258. <el-dialog title="设备打包" :visible.sync="dlgPackVisible">
  259. <div>
  260. <el-form :model="propsData" label-width="100px">
  261. <el-form-item label="">
  262. <el-checkbox v-model="propsData.enablePack">启用打包</el-checkbox>
  263. </el-form-item>
  264. <el-form-item label="打包选项">
  265. <el-radio-group v-model="propsData.packByType" :disabled="!propsData.enablePack">
  266. <el-radio :label="true">按设备类型打包</el-radio>
  267. <el-radio :label="false">所有类型打包成一个</el-radio>
  268. </el-radio-group>
  269. </el-form-item>
  270. <el-form-item label="打包图例">
  271. <el-input
  272. v-model="propsData.legendId"
  273. clearable
  274. :disabled="!propsData.enablePack || propsData.packByType"
  275. >
  276. </el-input>
  277. </el-form-item>
  278. <el-form-item label="打包名称">
  279. <el-input
  280. v-model="propsData.packName"
  281. clearable
  282. :disabled="!propsData.enablePack || propsData.packByType"
  283. >
  284. </el-input>
  285. </el-form-item>
  286. </el-form>
  287. </div>
  288. <div slot="footer" class="dialog-footer">
  289. <el-button @click="dlgPackVisible = false">取 消</el-button>
  290. <el-button type="primary" @click='modifyPack'>确 定</el-button>
  291. </div>
  292. </el-dialog>
  293. <!-- 容器动态组对话框 -->
  294. <el-dialog title="动态组" :visible.sync="dlgDynGroupVisible">
  295. <div>
  296. <el-form :model="propsData" label-width="100px">
  297. <el-form-item label="">
  298. <el-checkbox v-model="propsData.enableDynGroup">启用动态组</el-checkbox>
  299. </el-form-item>
  300. <el-form-item label="数据分组依据">
  301. <el-select v-model="propsData.dynSource" :disabled="!propsData.enableDynGroup">
  302. <el-option
  303. v-for="item in dynSourceOptions"
  304. :key="item.value"
  305. :label="item.label"
  306. :value="item.value">
  307. </el-option>
  308. </el-select>
  309. </el-form-item>
  310. <el-form-item label="分组标签位置">
  311. <el-radio-group v-model="propsData.labelPosition" :disabled="!propsData.enableDynGroup">
  312. <el-radio label="left">左</el-radio>
  313. <el-radio label="bottom">下</el-radio>
  314. <el-radio label="right">右</el-radio>
  315. <el-radio label="top">上</el-radio>
  316. <el-radio :label="null">无</el-radio>
  317. </el-radio-group>
  318. </el-form-item>
  319. </el-form>
  320. </div>
  321. <div slot="footer" class="dialog-footer">
  322. <el-button @click="dlgDynGroupVisible = false">取 消</el-button>
  323. <el-button type="primary" @click='modifyDynGroup'>确 定</el-button>
  324. </div>
  325. </el-dialog>
  326. </div>
  327. </template>
  328. <script lang="ts">
  329. import {
  330. Component,
  331. Prop,
  332. Vue,
  333. Watch
  334. } from "vue-property-decorator";
  335. import FilterPanel from '@/components/FilterPanel.vue';
  336. import {TemplateEditor} from '@/lib/TemplateEditor';
  337. import {Container} from '@/lib/DiagramModel';
  338. @Component({components:{FilterPanel}})
  339. export default class DiagramTemplate extends Vue {
  340. editorStyle = {
  341. width: "100%",
  342. height: "",
  343. "overflow": "scroll"
  344. };
  345. templates = [];
  346. currentTemplate:any = {};
  347. editor:TemplateEditor = null;
  348. state = -1; //编辑状态(-1:关闭; 0:打开; 1:选中容器; 2:选中干管; 9:绘制干管)
  349. dlgTemplateVisible = false;
  350. dlgConVisible = false;
  351. dlgLineVisible = false;
  352. dlgFilterVisible = false;
  353. dlgPackVisible = false;
  354. dlgDynGroupVisible = false;
  355. propsData: any = {};
  356. dataFilter: any = {};
  357. selectionInfo = '~';
  358. dynInfo = '';
  359. equipTypes:any[] = null; //编辑时,系统对应的设备类型
  360. equipOptions:any[] = []; //属性设定时,下拉框中的设备类型列表(动态)
  361. dicRels:any[] = [];
  362. dicEquips:any[] = [];
  363. dynSourceOptions:any[] = [];
  364. mounted() {
  365. this.onWindowresize();
  366. this.editor = new TemplateEditor(this.$refs.editor);
  367. this.editor.setEditorPart(this);
  368. this['$axios'].get(this['$common'].url + "template/getTemplates")
  369. .then(res => {
  370. this.templates = res.data.data;
  371. })
  372. .catch(err => {
  373. //console.log(err);
  374. });
  375. this['$axios'].get(this['$common'].url + "relTypes")
  376. .then(res => {
  377. this.dicRels = res.data.data;
  378. })
  379. .catch(err => {
  380. //console.log(err);
  381. });
  382. this['$axios'].post(this['$common'].url + "equipTypes")
  383. .then(res => {
  384. const root = res.data;
  385. this.dicEquips = root.data;
  386. })
  387. .catch(err => {
  388. console.log(err);
  389. });
  390. }
  391. //系统图模板树的节点显示
  392. nodeLabel(data, node) {
  393. if(data.type) //文件夹
  394. return data.name;
  395. else if(data.diagramType)//模板
  396. return '[模板] ' + data.name;
  397. }
  398. //新建模板文件
  399. newTemplate(node){
  400. this.$prompt('请输入模板名称', '提示', {
  401. confirmButtonText: '确定',
  402. cancelButtonText: '取消',
  403. type: 'info',
  404. inputValidator: val => {return val != null}
  405. }).then(instance => {
  406. const params:any = {name: instance['value'], type: node.data.id};
  407. this['$axios'].post(this['$common'].url + "template/newTemplate", params)
  408. .then(res => {
  409. const root = res.data;
  410. if(root.message == 'success') {
  411. const newObj = root.data;
  412. node.data.children.push(newObj);
  413. this.$message({
  414. type: 'success',
  415. message: '操作成功!'
  416. });
  417. this.openTemplate(newObj);
  418. }
  419. })
  420. .catch(err => {
  421. console.log(err);
  422. });
  423. }).catch(() => {
  424. });
  425. }
  426. //删除模板
  427. delTemplate(node){
  428. const params:any = {id: node.data.id};
  429. this['$axios'].post(this['$common'].url + "template/delTemplate", params)
  430. .then(res => {
  431. const root = res.data;
  432. if(root.data == true) {
  433. const parent = node.parent;
  434. const children = parent.data.children || parent.data;
  435. const index = children.findIndex(d => d.id === node.data.id);
  436. children.splice(index, 1);
  437. this.$message({
  438. type: 'success',
  439. message: '操作成功!'
  440. });
  441. this.openTemplate({});
  442. }
  443. })
  444. .catch(err => {
  445. console.log(err);
  446. });
  447. }
  448. //编辑模板信息
  449. editTemplate(node){
  450. const props: any = {id: node.data.id, name: node.data.name, remark: node.data.remark};
  451. this.propsData = props;
  452. this.dlgTemplateVisible = true;
  453. }
  454. //修改模板信息
  455. modifyTemplate(){
  456. if(!this.propsData.name) {
  457. this.$message({
  458. type: 'warning',
  459. message: '名称不合法'
  460. });
  461. return;
  462. }
  463. this['$axios'].post(this['$common'].url + "template/editTemplateInfo", this.propsData)
  464. .then(res => {
  465. const root = res.data;
  466. if(root.data == true) {
  467. this.currentTemplate.name = this.propsData.name;
  468. this.currentTemplate.remark = this.propsData.remark;
  469. this.propsData = {};
  470. this.dlgTemplateVisible = false;
  471. }
  472. })
  473. .catch(err => {
  474. console.log(err);
  475. });
  476. }
  477. //在编辑器中打开模板文件
  478. openTemplate(data){
  479. if(data.type) //文件夹
  480. return;
  481. if(this.currentTemplate != data) {
  482. this.currentTemplate = data;
  483. this.selectionInfo = '~';
  484. this.dynInfo = '';
  485. this.editor.show(this.currentTemplate);
  486. if(!this.currentTemplate.id) //编辑对象为空
  487. this.state = -1;
  488. else {
  489. this.onSelectionChange();
  490. const sys = this.currentTemplate.diagramType.substr(0, 4);
  491. const arr = [];
  492. this.dicEquips.forEach(item => {
  493. if(item.systemCode == sys)
  494. arr.push(item);
  495. });
  496. this.equipTypes = arr;
  497. }
  498. }
  499. }
  500. created(){
  501. //window.addEventListener('resize', this.onWindowresize);
  502. }
  503. onWindowresize(){
  504. this.editorStyle.height = (window.innerHeight - this.$refs.header['offsetHeight']) + 'px';
  505. }
  506. //选中组件的事件触发
  507. onSelectionChange(){
  508. this.state = this.editor.getState();
  509. if(this.editor)
  510. this.selectionInfo = this.editor.buildSelInfo();
  511. }
  512. isEquipCompSel(){
  513. if(this.state == 1 || this.state == 2) {
  514. const sel = this.editor.getSelComp();
  515. return sel.equipmentTypes != null && sel.equipmentTypes.length > 0;
  516. }
  517. return false;
  518. }
  519. //添加容器
  520. addCon(){
  521. this.$prompt('请输入容器id', '提示', {
  522. confirmButtonText: '确定',
  523. cancelButtonText: '取消',
  524. type: 'info',
  525. inputValidator: val => {return val != null && this.checkId(val)}
  526. }).then(instance => {
  527. const params:any = {newCompId: instance['value'], currentCompId:this.editor.getSelComp().id, templateId: this.currentTemplate.id};
  528. this.propsData = {id: params.newCompId}; //方便后续选中操作
  529. this.callAction('addCon', params);
  530. }).catch(() => {
  531. });
  532. }
  533. //检测id是否冲突
  534. checkId(id:string):boolean {
  535. return this.editor.getCompById(id) == null;
  536. }
  537. //删除容器
  538. delCon(){
  539. const sel = this.editor.getSelComp();
  540. var type;
  541. if(sel.children) { //容器
  542. if(sel.id == 'frame') {
  543. this.$message({
  544. type: 'info',
  545. message: '不能删除根容器!'
  546. });
  547. return;
  548. }
  549. type = "container";
  550. } else { //干管
  551. type = "mainPipe";
  552. }
  553. const params:any = {currentCompId: sel.id, templateId: this.currentTemplate.id};
  554. this.callAction(type == 'container' ? 'delCon' : 'delLine', params);
  555. }
  556. //移动容器
  557. moveCon(offset) {
  558. if(this.editor.getSelComp().parent == null)
  559. return;
  560. const params:any = {currentCompId:this.editor.getSelComp().id, templateId: this.currentTemplate.id, moveOffset: offset};
  561. this.callAction('moveCon', params);
  562. }
  563. //打开属性编辑界面
  564. setProps() {
  565. this.equipOptions = this.equipTypes;
  566. const sel = this.editor.getSelComp();
  567. const props:any = {id0: sel.id, id: sel.id, name: sel.name, remark: sel.remark};
  568. if(sel.children) { //容器
  569. if(sel.id == 'frame')
  570. props.root = true;
  571. if(sel.children.length > 0)
  572. props.hasChildren = true;
  573. props.layout = sel.layout.layout;
  574. props.margin = sel.layout.marginTop; //暂时取上方值
  575. props.space = sel.layout.spaceH;
  576. props.minH = sel.position.minH;
  577. props.minW = sel.position.minW;
  578. props.absolute = sel.position.absolute;
  579. props.equipTypes = sel.equipmentTypes;
  580. if(sel.props) {
  581. props.auto_hidden = sel.props['auto_hidden'];
  582. }
  583. this.propsData = props;
  584. this.dlgConVisible = true;
  585. } else { //干管
  586. props.pipeType = sel.pipeType;
  587. props.equipTypes = sel.equipmentTypes;
  588. props.bindEquipment = sel.bindEquipment;
  589. if(sel.passbyRels){
  590. props.passbyRels = [];
  591. for(const r of sel.passbyRels) {
  592. props.passbyRels.push(r.split("/"));
  593. }
  594. }
  595. props.connectEquips = sel.connectEquips;
  596. this.propsData = props;
  597. this.dlgLineVisible = true;
  598. }
  599. }
  600. //设备容器下拉框搜索
  601. queryEquipTypes(query){
  602. if (query !== '')
  603. this.equipOptions = this.dicEquips.filter(data => this.filterMatch(data.name, query) || this.filterMatch(data.code, query));
  604. else
  605. this.equipOptions = this.equipTypes;
  606. }
  607. filterMatch(str, filter){
  608. return str.toLowerCase().indexOf(filter.toLowerCase()) !== -1;
  609. }
  610. //修改容器属性
  611. modifyCon(){
  612. if(this.propsData.id != this.propsData.id0 && !this.checkId(this.propsData.id)) {
  613. this.$message({
  614. type: 'warning',
  615. message: 'id冲突!'
  616. });
  617. return;
  618. }
  619. if(this.propsData.auto_hidden !== null){
  620. this.propsData.props = {auto_hidden: this.propsData.auto_hidden};
  621. }
  622. const params:any = {templatePropsData: this.propsData, currentCompId: this.propsData.id0, templateId: this.currentTemplate.id};
  623. this.callAction('modifyCon', params);
  624. }
  625. //修改干管属性
  626. modifyMainPipe(){
  627. if(this.propsData.id != this.propsData.id0 && !this.checkId(this.propsData.id)) {
  628. this.$message({
  629. type: 'warning',
  630. message: 'id冲突!'
  631. });
  632. return;
  633. }
  634. if(this.propsData.passbyRels) {
  635. const rels = [];
  636. for(const arr of this.propsData.passbyRels) {
  637. rels.push(arr.join("/"));
  638. }
  639. this.propsData.passbyRels = rels;
  640. }
  641. const params:any = {templatePropsData: this.propsData, currentCompId: this.propsData.id0, templateId: this.currentTemplate.id};
  642. this.callAction('modifyMainPipe', params);
  643. }
  644. //编辑设备过滤条件
  645. editFilter(){
  646. const sel = this.editor.getSelComp();
  647. this.dataFilter = sel.dataFilter != null ? sel.dataFilter : {};//为null时赋一个新对象,触发子组件watch
  648. this.dlgFilterVisible = true;
  649. }
  650. //修改设备过滤条件
  651. modifyFilter(){
  652. var filter = (this.$refs.filterPanel as FilterPanel).buildFilter();
  653. if(filter && filter.errMsg){
  654. this.$message({
  655. type: 'warning',
  656. message: filter.errMsg
  657. });
  658. return;
  659. }
  660. const params:any = {currentCompId: this.editor.getSelComp().id, templateId: this.currentTemplate.id, dataFilter: filter};
  661. this.callAction('modifyFilter', params);
  662. }
  663. //编辑设备打包配置
  664. editPack(){
  665. const sel = this.editor.getSelComp();
  666. const props:any = {};
  667. if(sel.equipPack) {
  668. props.enablePack = true;
  669. props.packByType = sel.equipPack.packByType;
  670. props.legendId = sel.equipPack.legendId;
  671. props.packName = sel.equipPack.packName;
  672. } else {
  673. props.enablePack = false;
  674. props.packByType = true;
  675. }
  676. this.propsData = props;
  677. this.dlgPackVisible = true;
  678. }
  679. //修改设备打包配置
  680. modifyPack(){
  681. var pack: any;
  682. if(!this.propsData.enablePack)
  683. pack = null;
  684. else
  685. pack = this.propsData;
  686. const params:any = {currentCompId: this.editor.getSelComp().id, templateId: this.currentTemplate.id, equipPack: pack};
  687. this.callAction('modifyPack', params);
  688. }
  689. //编辑容器的动态组配置
  690. editDynGroup(){
  691. const sel = this.editor.getSelComp();
  692. if(sel.id == 'frame') {
  693. this.$message({
  694. type: 'info',
  695. message: '根容器不支持动态组!'
  696. });
  697. return;
  698. }
  699. const props:any = {};
  700. if(sel.dynGroup) {
  701. props.enableDynGroup = true;
  702. props.dynSource = sel.dynGroup.dynSource;
  703. props.labelPosition = sel.dynGroup.labelPosition;
  704. } else {
  705. props.enableDynGroup = false;
  706. }
  707. this.propsData = props;
  708. this.dynSourceOptions = [{value:'floor', label: '楼层'}, {value:'building', label: '建筑'}];
  709. if(this.currentTemplate.mainPipes){
  710. for(const mp of this.currentTemplate.mainPipes) {
  711. if(mp.bindEquipment){
  712. this.dynSourceOptions.push({value: 'mainPipe:' + mp.id, label: '干管:' + mp.name});
  713. }
  714. }
  715. }
  716. const equipBoxes: any[] = Container.getEquipBoxes(sel);
  717. for(const box of equipBoxes) {
  718. this.dynSourceOptions.push({value: 'containerElement:' + box.id, label: '容器中设备:' + (box.name != null ? box.name : box.id)});
  719. }
  720. this.dlgDynGroupVisible = true;
  721. }
  722. //修改容器的动态组配置
  723. modifyDynGroup(){
  724. if(!this.propsData.dynSource) {
  725. this.$message({
  726. type: 'warning',
  727. message: '缺少必要的信息!'
  728. });
  729. return;
  730. }
  731. var dynGroup: any;
  732. if(!this.propsData.enableDynGroup)
  733. dynGroup = null;
  734. else
  735. dynGroup = this.propsData;
  736. const params:any = {currentCompId: this.editor.getSelComp().id, templateId: this.currentTemplate.id, dynGroup: dynGroup};
  737. this.callAction('modifyDynGroup', params);
  738. }
  739. //调用服务端编辑操作,返回新的模板对象,然后刷新
  740. callAction(action, params) {
  741. this['$axios'].post(this['$common'].url + 'template/' + action, params)
  742. .then(res => {
  743. const root = res.data;
  744. if(root.message == 'success') {
  745. //记录之前的选中对象id
  746. var selId = this.propsData.id;
  747. if(!selId) {
  748. const sel:any = this.editor.getSelComp();
  749. if(sel)
  750. selId = sel.id;
  751. }
  752. const newObj = root.data;
  753. if(newObj == null)
  754. return;
  755. this.currentTemplate.frame = newObj.frame;
  756. this.currentTemplate.mainPipes = newObj.mainPipes;
  757. this.currentTemplate.scatteredContainers = newObj.scatteredContainers;
  758. // this.$message({
  759. // type: 'success',
  760. // message: '操作成功!'
  761. // });
  762. if(this.dlgConVisible)
  763. this.dlgConVisible = false;
  764. if(this.dlgLineVisible)
  765. this.dlgLineVisible = false;
  766. if(this.dlgFilterVisible)
  767. this.dlgFilterVisible = false;
  768. if(this.dlgPackVisible)
  769. this.dlgPackVisible = false;
  770. if(this.dlgDynGroupVisible)
  771. this.dlgDynGroupVisible = false;
  772. this.propsData = {};
  773. this.editor.show(this.currentTemplate);
  774. this.editor.setSelComp(this.editor.getCompById(selId));
  775. }
  776. })
  777. .catch(err => {
  778. console.log(err);
  779. });
  780. }
  781. //开始绘制干管
  782. beginMainLine(){
  783. this.changeState(9);
  784. }
  785. //下一条线
  786. nextLine() {
  787. this.editor.currentTmpMainPipe = null;
  788. }
  789. //取消干管绘制操作
  790. cancelMainLine(){
  791. this.dynInfo = '';
  792. this.changeState(this.editor.getState());
  793. this.editor.redraw();
  794. }
  795. //完成干管绘制
  796. finishMainLine(){
  797. this.dynInfo = '';
  798. for(var i = 0; i < this.editor.tmpMainPipe.length; i++) {
  799. const line = this.editor.tmpMainPipe[i];
  800. if(line.length < 2) {
  801. this.editor.tmpMainPipe.splice(i, 1);
  802. i--;
  803. }
  804. }
  805. if(this.editor.tmpMainPipe.length == 0) {
  806. this.cancelMainLine();
  807. return;
  808. }
  809. const lines:any[] = [];
  810. this.editor.tmpMainPipe.forEach(item => {
  811. const line:any[] = [];
  812. lines.push(line);
  813. for(const p of item){
  814. line.push({x:p.x - this.editor.margin, y:p.y - this.editor.margin})
  815. }
  816. });
  817. const params:any = {lines: lines, templateId: this.currentTemplate.id};
  818. this.callAction('addMainPipe', params);
  819. }
  820. //切换编辑状态
  821. changeState(state) {
  822. this.state = state;
  823. this.editor.setState(state);
  824. }
  825. }
  826. </script>
  827. <style>
  828. .panel {
  829. padding: 30px;
  830. }
  831. .custom-tree-node {
  832. /* flex: 1;
  833. display: flex; */
  834. align-items: center;
  835. justify-content: space-between;
  836. font-size: 14px;
  837. padding-right: 20px;
  838. }
  839. .editor-title {
  840. font-size: 14px;
  841. font-weight: bold;
  842. padding:0 10px;
  843. }
  844. .info {
  845. font-size: 12px;
  846. padding:0 10px;
  847. }
  848. .el-dialog-div{
  849. height: 60vh;
  850. overflow: auto;
  851. }
  852. </style>