Diagram.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. <template>
  2. <div>
  3. <el-row>
  4. <!-- 模板树 -->
  5. <el-col :span="6" >
  6. <div style="height: 100vh;overflow: scroll;">
  7. <el-tree :data="diagrams" :props="{children: 'children', label: nodeLabel, value: 'id'}"
  8. @node-click="open"
  9. default-expand-all
  10. :expand-on-click-node="false">
  11. <span class="custom-tree-node" slot-scope="{ node, data }">
  12. <span>{{ node.label}}</span>
  13. <span style="padding-left: 10px;">
  14. <el-button type="text" size="mini" icon="el-icon-plus" @click="() => newDiagram(node)"
  15. v-if="data.objType == 'folder' && data.type == 'type'">
  16. 创建系统图
  17. </el-button>
  18. <el-popconfirm title="确定删除?" v-if="data.objType != 'folder'" @confirm="() => delDiagram(node)">
  19. <el-button slot="reference" type="text" size="mini" icon="el-icon-remove">删除</el-button>
  20. </el-popconfirm>
  21. </span>
  22. </span>
  23. </el-tree>
  24. </div>
  25. </el-col>
  26. <!-- 编辑区 -->
  27. <el-col :span="18" style="border-left: 1px solid #f4f4f4">
  28. <!-- 工具条 -->
  29. <div ref="header" style="padding: 2px;border-bottom: 1px solid #f4f4f4">
  30. <span class="editor-title">{{currentDiagram.name}}</span>
  31. <el-button-group>
  32. <el-button size="mini" @click="() => prjEnv()">项目环境</el-button>
  33. </el-button-group>
  34. <el-button-group>
  35. <el-button size="mini" @click="() => chooseTemplate()" :disabled="state == -1">选择模板</el-button>
  36. <el-button size="mini" @click="() => loadData()" :disabled="state == -1">加载数据</el-button>
  37. &nbsp;
  38. <el-button size="mini" @click="() => reset()" :disabled="state == -1">重置</el-button>
  39. </el-button-group>
  40. <el-button-group>
  41. <el-button size="mini" @click="() => {}" :disabled="state != 1">上移/左移</el-button>
  42. <el-button size="mini" @click="() => {}" :disabled="state != 1">下移/右移</el-button>
  43. </el-button-group>
  44. &nbsp;
  45. <el-button-group>
  46. <el-button size="mini" @click="() => changeConState()" :disabled="state == -1">{{conButtonText}}</el-button>
  47. </el-button-group>
  48. &nbsp;
  49. <el-button-group>
  50. <el-button size="mini" @click="() => save()" :disabled="state == -1">保存</el-button>
  51. </el-button-group>
  52. <!--选中信息-->
  53. <div class="info">
  54. <span>{{selectionInfo}}</span>
  55. <span style="margin-left: 30px;color: #a3a3a3;">{{dynInfo}}</span>
  56. </div>
  57. </div>
  58. <!-- 编辑界面 -->
  59. <div ref="editor" :style="editorStyle">
  60. </div>
  61. </el-col>
  62. </el-row>
  63. <!-- 编辑项目环境对话框 -->
  64. <el-dialog title="项目环境" :visible.sync="dlgEnvVisible">
  65. <el-form :model="propsData" label-width="100px">
  66. <el-form-item label="项目Id">
  67. <el-autocomplete
  68. class="inline-input"
  69. v-model="propsData.projectId"
  70. :fetch-suggestions="getPrjIds"></el-autocomplete>
  71. </el-form-item>
  72. <el-form-item label="系统实例Id">
  73. <el-input v-model="propsData.systemId"></el-input>
  74. </el-form-item>
  75. <el-form-item label="集团编码">
  76. <el-input v-model="propsData.groupCode"></el-input>
  77. </el-form-item>
  78. </el-form>
  79. <div slot="footer" class="dialog-footer">
  80. <el-button @click="dlgEnvVisible = false">取 消</el-button>
  81. <el-button type="primary" @click='modifyEnv'>确 定</el-button>
  82. </div>
  83. </el-dialog>
  84. <!-- 选择模板对话框 -->
  85. <el-dialog title="系统图模板" :visible.sync="dlgTemplateVisible">
  86. <el-form :model="propsData" label-width="100px">
  87. <el-form-item label="选择模板">
  88. <el-select
  89. v-model="propsData.templateId"
  90. style="width: 600px;"
  91. >
  92. <el-option
  93. v-for="item in templateOptions"
  94. :key="item.id"
  95. :label="item.name"
  96. :value="item.id">
  97. </el-option>
  98. </el-select>
  99. </el-form-item>
  100. </el-form>
  101. <div slot="footer" class="dialog-footer">
  102. <el-button @click="dlgTemplateVisible = false">取 消</el-button>
  103. <el-button type="primary" @click='modifyTemplate'>确 定</el-button>
  104. </div>
  105. </el-dialog>
  106. </div>
  107. </template>
  108. <script lang="ts">
  109. import {
  110. Component,
  111. Prop,
  112. Vue,
  113. Watch
  114. } from "vue-property-decorator";
  115. import {DiagramEditor} from '@/lib/DiagramEditor';
  116. import {Template} from '@/lib/DiagramModel';
  117. @Component({})
  118. export default class DiagramTemplate extends Vue {
  119. projectId = 'Pj1101080665';
  120. systemId = '';
  121. groupCode = '';
  122. editorStyle = {
  123. width: "100%",
  124. height: "",
  125. "overflow": "scroll"
  126. };
  127. diagrams = [];
  128. currentDiagram:any = {};
  129. editor:DiagramEditor = null;
  130. state = -1; //编辑状态(-1:关闭; 0:打开; 1:容器编辑中; 2:绘制干管)
  131. dlgEnvVisible = false;
  132. dlgTemplateVisible = false;
  133. propsData: any = {};
  134. templateOptions:any[] = [];
  135. selectionInfo = '~';
  136. dynInfo = '';
  137. conButtonText = '隐藏容器';
  138. mounted() {
  139. this.onWindowresize();
  140. this.editor = new DiagramEditor(this.$refs.editor);
  141. this.editor.setEditorPart(this);
  142. this.loadDiagrams();
  143. }
  144. loadDiagrams(){
  145. this['$axios'].get(this['$common'].url + "diagram0/getDiagrams" + this.buildUrlParams())
  146. .then(res => {
  147. this.diagrams = res.data.data;
  148. })
  149. .catch(err => {
  150. //console.log(err);
  151. });
  152. }
  153. buildUrlParams(){
  154. var str = "?projectId=" + this.projectId;
  155. if(this.systemId)
  156. str += '&systemId=' + this.systemId;
  157. if(this.groupCode)
  158. str += '&groupCode=' + this.groupCode;
  159. return str;
  160. }
  161. //系统图模板树的节点显示
  162. nodeLabel(data, node) {
  163. if(data.objType == 'folder') //文件夹
  164. return data.name;
  165. else //图
  166. return '[系统图] ' + data.name;
  167. }
  168. prjEnv() {
  169. this.propsData = {projectId: this.projectId, systemId: this.systemId, groupCode: this.groupCode};
  170. this.dlgEnvVisible = true;
  171. }
  172. getPrjIds(queryString, cb){
  173. const list = [
  174. { "value": "Pj1101080665", "code": "JDKJ" },
  175. { "value": "Pj1101050036", "code": "JM" },
  176. { "value": "Pj1101050031", "code": "YT" }
  177. ];
  178. cb(list);
  179. }
  180. modifyEnv() {
  181. const reload = this.projectId != this.propsData.projectId;
  182. this.projectId = this.propsData.projectId;
  183. this.systemId = this.propsData.systemId;
  184. this.groupCode = this.propsData.groupCode;
  185. this.dlgEnvVisible = false;
  186. if(reload) {
  187. this.loadDiagrams();
  188. this.open(new Object());
  189. }
  190. }
  191. //新建模板文件
  192. newDiagram(node){
  193. this.$prompt('请输入系统图名称', '提示', {
  194. confirmButtonText: '确定',
  195. cancelButtonText: '取消',
  196. type: 'info',
  197. inputValidator: val => {return val != null}
  198. }).then(instance => {
  199. const params:any = {name: instance['value'], type: node.data.id};
  200. this['$axios'].post(this['$common'].url + "diagram0/newDiagram" + this.buildUrlParams(), params)
  201. .then(res => {
  202. const root = res.data;
  203. if(root.result == 'success') {
  204. const newObj = root.data;
  205. node.data.children.push(newObj);
  206. this.$message({
  207. type: 'success',
  208. message: '操作成功!'
  209. });
  210. this.open(newObj);
  211. }
  212. })
  213. .catch(err => {
  214. console.log(err);
  215. });
  216. }).catch(() => {
  217. });
  218. }
  219. //删除模板
  220. delDiagram(node){
  221. const params:any = {id: node.data.id};
  222. this['$axios'].post(this['$common'].url + "diagram0/delDiagram", params)
  223. .then(res => {
  224. const root = res.data;
  225. if(root.data == true) {
  226. const parent = node.parent;
  227. const children = parent.data.children || parent.data;
  228. const index = children.findIndex(d => d.id === node.data.id);
  229. children.splice(index, 1);
  230. this.$message({
  231. type: 'success',
  232. message: '操作成功!'
  233. });
  234. this.open({});
  235. }
  236. })
  237. .catch(err => {
  238. console.log(err);
  239. });
  240. }
  241. //在编辑器中打开模板文件
  242. open(data){
  243. if(data.objType == 'folder') //文件夹
  244. return;
  245. if(this.currentDiagram != data) {
  246. this.currentDiagram = data;
  247. this.selectionInfo = '~';
  248. this.dynInfo = '';
  249. this.editor.show(this.currentDiagram);
  250. if(!this.currentDiagram.id) //编辑对象为空
  251. this.state = -1;
  252. else {
  253. this.onSelectionChange();
  254. }
  255. }
  256. }
  257. chooseTemplate() {
  258. this.templateOptions = [];
  259. this['$axios'].get(this['$common'].url + "template/getTemplatesByType?diagramType=" + this.currentDiagram.type)
  260. .then(res => {
  261. this.templateOptions = res.data.data;
  262. })
  263. .catch(err => {
  264. //console.log(err);
  265. });
  266. const props:any = new Object();
  267. props.templateId = this.currentDiagram.templateId;
  268. this.propsData = props;
  269. this.dlgTemplateVisible = true;
  270. }
  271. modifyTemplate() {
  272. const tId = this.propsData.templateId;
  273. this.currentDiagram.templateId = tId;
  274. this.dlgTemplateVisible = false;
  275. this.editor.redraw();
  276. const params:any = {diagramId: this.currentDiagram.id, templateId: this.propsData.templateId};
  277. //this.propsData = {id: params.newCompId}; //方便后续选中操作
  278. this.callAction('setTemplate', params);
  279. }
  280. loadData() {
  281. const params:any = {diagramId: this.currentDiagram.id};
  282. //this.propsData = {id: params.newCompId}; //方便后续选中操作
  283. this.callAction('loadData', params);
  284. }
  285. created(){
  286. //window.addEventListener('resize', this.onWindowresize);
  287. }
  288. onWindowresize(){
  289. this.editorStyle.height = (window.innerHeight - this.$refs.header['offsetHeight']) + 'px';
  290. }
  291. //选中组件的事件触发
  292. onSelectionChange(){
  293. this.state = this.editor.getState();
  294. if(this.editor)
  295. this.selectionInfo = this.editor.buildSelInfo();
  296. }
  297. //调用服务端编辑操作,返回新的系统图对象,然后刷新
  298. callAction(action, params) {
  299. this['$axios'].post(this['$common'].url + 'diagram0/' + action, params)
  300. .then(res => {
  301. const root = res.data;
  302. if(root.result == 'success') {
  303. //记录之前的选中对象id
  304. // var selId = this.propsData.id;
  305. // if(!selId) {
  306. // const sel:any = this.editor.getSelComp();
  307. // if(sel)
  308. // selId = sel.id;
  309. // }
  310. const newObj = root.data;
  311. if(newObj == null)
  312. return;
  313. for(const i in newObj) {
  314. this.currentDiagram[i] = newObj[i];
  315. }
  316. // this.$message({
  317. // type: 'success',
  318. // message: '操作成功!'
  319. // });
  320. if(this.dlgTemplateVisible)
  321. this.dlgTemplateVisible = false;
  322. this.propsData = {};
  323. this.editor.show(this.currentDiagram);
  324. //this.editor.setSelComp(this.editor.getCompById(selId));
  325. }
  326. })
  327. .catch(err => {
  328. console.log(err);
  329. });
  330. }
  331. changeConState(){
  332. this.editor.showContainer = !this.editor.showContainer;
  333. this.editor.redraw();
  334. this.conButtonText = this.editor.showContainer ? '隐藏容器' : '显示容器';
  335. }
  336. save(){
  337. Template.clearParent(this.currentDiagram.template);
  338. const params:any = {diagram: this.currentDiagram};
  339. this.callAction("saveDiagram", params);
  340. }
  341. reset(){
  342. const params:any = {diagramId: this.currentDiagram.id};
  343. this.callAction("resetDiagram", params);
  344. }
  345. //切换编辑状态
  346. changeState(state) {
  347. this.state = state;
  348. this.editor.setState(state);
  349. }
  350. }
  351. </script>
  352. <style>
  353. .panel {
  354. padding: 30px;
  355. }
  356. .custom-tree-node {
  357. /* flex: 1;
  358. display: flex; */
  359. align-items: center;
  360. justify-content: space-between;
  361. font-size: 14px;
  362. padding-right: 20px;
  363. }
  364. .editor-title {
  365. font-size: 14px;
  366. font-weight: bold;
  367. padding:0 10px;
  368. }
  369. .info {
  370. font-size: 12px;
  371. padding:0 10px;
  372. }
  373. .el-dialog-div{
  374. height: 60vh;
  375. overflow: auto;
  376. }
  377. </style>