index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. <template>
  2. <div class="TemplateManagementNew">
  3. <!-- <Breadcrumb separator=">" class="breadcrumb">
  4. <BreadcrumbItem to="/TemplateManagementLists">模版管理</BreadcrumbItem>
  5. <BreadcrumbItem>{{$route.params.id != '-1'?'编辑模版':'新建模版'}}</BreadcrumbItem>
  6. </Breadcrumb> -->
  7. <!-- 预览状态 -->
  8. <div class="content" v-if="this.readOnly">
  9. <div class="tips" v-if="currentSteps === 2">
  10. <p>
  11. <span>单据类型:</span><span>{{data.businessTypeText}}</span>
  12. </p>
  13. <p>
  14. <span>模版名称:</span><span>{{data.name}}</span>
  15. </p>
  16. <p>
  17. <span>查询索引:</span><span>{{data.businessKey}}</span>
  18. </p>
  19. <p>
  20. <span>模版描述:</span><span>{{data.description}}</span>
  21. </p>
  22. <p>
  23. <span>自动处理:</span><span>{{data.autoClose?'开':'关'}}</span>
  24. </p>
  25. <p>
  26. <span>业务数据检查:</span><span>{{data.businessCheckUrl}}</span>
  27. </p>
  28. </div>
  29. <FlowChartComponent
  30. v-if="currentSteps === 2"
  31. :data="data"
  32. :currentSteps="2"
  33. :readOnly="readOnly"
  34. ref="component_2"
  35. >
  36. </FlowChartComponent>
  37. <p class="buttonGroups" v-if="currentSteps === 2">
  38. <Button type="primary" @click="close">关闭</Button>
  39. </p>
  40. </div>
  41. <!-- 编辑状态 -->
  42. <Steps :current="currentSteps" class="steps" v-if="!this.readOnly">
  43. <Step title="参数配置" ></Step>
  44. <Step title="流程设计器" ></Step>
  45. <Step title="保存发布模版" ></Step>
  46. </Steps>
  47. <div class="content" v-if="!this.readOnly">
  48. <keep-alive exclude="component_2" >
  49. <component
  50. :is="currentComponent"
  51. :ref="currentComponent"
  52. class="block"
  53. :editable="currentSteps === 1?true:false"
  54. :data="data"
  55. :currentSteps="currentSteps"
  56. :noFreshFlag="noFreshFlag"
  57. @dataChange="dataChange"
  58. >
  59. </component>
  60. </keep-alive>
  61. <p class="buttonGroups">
  62. <Button type="primary" v-if="currentSteps > 0" @click="previousSteps">上一步</Button>
  63. <Button type="primary" v-if="currentSteps < 2" @click="nextSteps">下一步</Button>
  64. <Button type="primary" v-if="(currentSteps === 2 && this.data.status !== 1)" @click="confirm(false)">保存</Button>
  65. <Button type="primary" v-if="(currentSteps === 2 && this.data.status !== 1)" @click="confirmAndPublish()">保存并发布</Button>
  66. </p>
  67. </div>
  68. </div>
  69. </template>
  70. <script>
  71. import '@/utils/go'
  72. import Vue from 'vue'
  73. import ParameterConfiguration from '@/components/ParameterConfiguration'
  74. import FlowChartComponent from '@/components/FlowChartComponent'
  75. import FlowSuccess from '@/components/FlowSuccess'
  76. import { mapMutations } from 'vuex';
  77. import { setTimeout } from 'timers';
  78. import {
  79. getLoad,
  80. getCommit,
  81. getDuplicate,
  82. getPublish
  83. } from '@/api/modeler.js'
  84. export default {
  85. name:'TemplateManagementNew',
  86. components:{ParameterConfiguration,FlowChartComponent,FlowSuccess},
  87. data () {
  88. return {
  89. currentSteps:0,
  90. currentComponent:null,
  91. imgBase:'',
  92. defaultData:{
  93. guiStyle:JSON.stringify({
  94. "class": "NewGraphLinksModel",
  95. "linkFromPortIdProperty": "fromPort",
  96. "linkToPortIdProperty": "toPort",
  97. "nodeDataArray": [
  98. {"key":-1, "category":"Start", "loc":"175 0", "text":"开始", "type": 1},
  99. {"key":0, "loc":"175 100", "text":"审批节点","type": 0, "category": 'Approval'},
  100. {"key":-2, "category":"End", "loc":"175 200", "text":"结束", "type": 2}
  101. ],
  102. "linkDataArray": [
  103. {"from":-1, "to":0, "fromPort":"B", "toPort":"T","key":0},
  104. {"from":0, "to":-2, "fromPort":"B", "toPort":"T","key":1}
  105. ]
  106. }),
  107. nodeMsg:[
  108. {"key":-1, "category":"Start", "loc":"175 0", "text":"开始", "name":"开始", "type": 1,"ruleList":[]},
  109. {"key":0, "loc":"175 100", "text":"审批节点", "name":"审批节点", "category": 'Approval',"type": 0,"ruleList":[],"actServiceS":[],"actionConfig":[],"approvelList":[],"approverStyle":0},
  110. {"key":-2, "category":"End", "loc":"175 200", "text":"结束", "name":"结束", "type": 2,"actionConfig":[{
  111. handleValue:null,
  112. extra_msg:{},
  113. handleType:31
  114. },
  115. {
  116. handleValue:'{}',
  117. extra_msg:{},
  118. handleType:41
  119. }]}
  120. ],
  121. pathMsg:[
  122. {"from":-1, "to":0, "fromPort":"B", "toPort":"T","ruleList":[],"key":0},
  123. {"from":0, "to":-2, "fromPort":"B", "toPort":"T","ruleList":[],"key":1}
  124. ],
  125. removeNode:[],
  126. removePath:[],
  127. },
  128. data:{
  129. guiStyle:JSON.stringify({
  130. "class": "NewGraphLinksModel",
  131. "linkFromPortIdProperty": "fromPort",
  132. "linkToPortIdProperty": "toPort",
  133. "nodeDataArray": [
  134. {"key":-1, "category":"Start", "loc":"175 0", "text":"开始", "type": 1},
  135. {"key":0, "loc":"175 100", "text":"审批节点","type": 0, "category": 'Approval'},
  136. {"key":-2, "category":"End", "loc":"175 200", "text":"结束", "type": 2}
  137. ],
  138. "linkDataArray": [
  139. {"from":-1, "to":0, "fromPort":"B", "toPort":"T","key":0},
  140. {"from":0, "to":-2, "fromPort":"B", "toPort":"T","key":1}
  141. ]
  142. }),
  143. nodeMsg:[
  144. {"key":-1, "category":"Start", "loc":"175 0", "text":"开始", "name":"开始", "type": 1,"ruleList":[]},
  145. {"key":0, "loc":"175 100", "text":"审批节点", "name":"审批节点", "category": 'Approval',"type": 0,"ruleList":[],"actServiceS":[],"actionConfig":[],"approvelList":[],"approverStyle":0},
  146. {"key":-2, "category":"End", "loc":"175 200", "text":"结束", "name":"结束", "type": 2,"actionConfig":[{
  147. handleValue:null,
  148. extra_msg:{},
  149. handleType:31
  150. },
  151. {
  152. handleValue:'{}',
  153. extra_msg:{},
  154. handleType:41
  155. }]}
  156. ],
  157. pathMsg:[
  158. {"from":-1, "to":0, "fromPort":"B", "toPort":"T","ruleList":[],"key":0},
  159. {"from":0, "to":-2, "fromPort":"B", "toPort":"T","ruleList":[],"key":1}
  160. ],
  161. removeNode:[],
  162. removePath:[],
  163. autoClose: true,
  164. moduleType: 0
  165. },
  166. noFreshFlag:false,
  167. readOnly:false, //是否只读为预览模式
  168. //存放三步骤的数据
  169. defaultModuleType: null, //暂存模版类型
  170. }
  171. },
  172. watch:{
  173. currentSteps (val) {
  174. // if(this.readOnly){
  175. // return
  176. // }
  177. let componentName = `component_${val}`
  178. if(Vue.component(componentName) === undefined){
  179. if(val === 0 ){
  180. Vue.component(componentName,ParameterConfiguration)
  181. }else if(val === 1){
  182. Vue.component(componentName,FlowChartComponent)
  183. }else if(val === 2){
  184. Vue.component(componentName,FlowSuccess)
  185. }
  186. }
  187. this.currentComponent = componentName
  188. }
  189. },
  190. methods:{
  191. ...mapMutations(['currentChange']),
  192. getModuleInfo (id) {
  193. getLoad({id:id}).then((res) => {
  194. if(res.resultCode === 0){
  195. res.data.businessType = [{
  196. ID:res.data.businessType,
  197. Label:res.data.businessTypeName,
  198. val:res.data.businessTypeText
  199. }]
  200. res.data.businessNumber = [{
  201. ID:String(res.data.businessKeyId),
  202. Label:res.data.businessKey,
  203. val:res.data.businessKeyName
  204. }]
  205. this.data = res.data
  206. this.data.guiStyle = JSON.parse(res.data.guiStyle)
  207. this.data.moduleId = res.data.id
  208. this.$nextTick(() => {
  209. if(this.readOnly){
  210. this.currentSteps = 2
  211. this.noFreshFlag = false
  212. }else{
  213. this.$refs.component_1.init()
  214. this.noFreshFlag = false
  215. }
  216. })
  217. }else{
  218. this.$Modal.fcWarning({
  219. title:'警告',
  220. content:res.resultMsg,
  221. mask:true
  222. })
  223. }
  224. });
  225. },
  226. async nextSteps () { //下一步
  227. if(await this.checkModuleName()){
  228. return false
  229. }
  230. if(this.currentSteps === 0 && (this.defaultModuleType != this.data.moduleType) && this.defaultModuleType !== null){
  231. this.$Modal.fcWarning({
  232. title:'警告',
  233. content:'您已修改模板类型/单据类型,这将导致下一步的流程设计器内所有设置恢复初始化,是否确定更改?',
  234. showCancel: true,
  235. mask: true,
  236. onOk: () => {
  237. this.defaultModuleType = this.data.moduleType
  238. this.data = Object.assign(this.data,JSON.parse(JSON.stringify(this.defaultData)))
  239. if(this.data.businessType && this.data.businessType.length > 0 && this.data.name){
  240. this.defaultModuleType = this.data.moduleType
  241. ++this.currentSteps
  242. }else{
  243. this.$Modal.fcWarning({
  244. title:'警告',
  245. content:'请填写必填项!',
  246. mask:true
  247. })
  248. }
  249. },
  250. onCancel: () => {
  251. }
  252. })
  253. return
  254. }
  255. if( this.data.name && (this.data.moduleType === 0?(this.data.businessType && this.data.businessType.length > 0):true) ){
  256. this.defaultModuleType = this.data.moduleType
  257. ++this.currentSteps
  258. }else{
  259. this.$Modal.fcWarning({
  260. title:'警告',
  261. content:'请填写必填项!',
  262. mask:true
  263. })
  264. }
  265. },
  266. async checkModuleName () {
  267. await new Promise((resolve, reject) => {
  268. let jsonObject = {
  269. ID:this.data.moduleId,
  270. NAME:this.data.name
  271. }
  272. getDuplicate(jsonObject).then(res => {
  273. if(res.resultCode !== 0){
  274. this.$Modal.fcWarning({
  275. title:'警告',
  276. content:res.resultMsg,
  277. mask:true
  278. })
  279. reject()
  280. }
  281. resolve(res)
  282. })
  283. })
  284. },
  285. previousSteps () { //上一步
  286. --this.currentSteps
  287. },
  288. async confirm (flag) { //确定
  289. return await new Promise((resolve,reject) => {
  290. var svg = this.data.myDisplay.makeImage({
  291. scale: 2
  292. });
  293. this.imgBase = svg.getAttribute('src')
  294. let nodeMsg = []
  295. Object.keys(this.data.nodeMsg).map(item => {
  296. nodeMsg.push(this.data.nodeMsg[item])
  297. return item
  298. })
  299. let pathMsg = []
  300. Object.keys(this.data.pathMsg).map(item => {
  301. pathMsg.push(this.data.pathMsg[item])
  302. return item
  303. })
  304. let jsonObject = {
  305. id:this.data.moduleId,
  306. name:this.data.name,
  307. description:this.data.description,
  308. GUI_STYLE:this.data.guiStyle,
  309. url:svg.getAttribute('src'),
  310. moduleType: this.data.moduleType,
  311. BUSINESS_TYPE:this.data.businessType?this.data.businessType[0].ID:null,
  312. BUSINESS_TYPE_NAME:this.data.businessType?this.data.businessType[0].Label:null,
  313. businessTypeText:this.data.businessType?this.data.businessType[0].val:null,
  314. businessKeyId:(this.data.businessNumber && this.data.businessNumber.length > 0)?this.data.businessNumber[0].ID:null,
  315. businessKey:(this.data.businessNumber && this.data.businessNumber.length > 0)?this.data.businessNumber[0].Label:null,
  316. businessKeyName:(this.data.businessNumber && this.data.businessNumber.length > 0)?this.data.businessNumber[0].val:null,
  317. autoClose:this.data.autoClose,
  318. businessCheckUrl:this.data.businessCheckUrl,
  319. nodeMsg: nodeMsg,
  320. pathMsg: pathMsg,
  321. removeNode: this.data.removeNode,
  322. removePath: this.data.removePath
  323. }
  324. getCommit(jsonObject).then(res => {
  325. if(res.resultCode === 0){
  326. // this.data = {
  327. // guiStyle:{
  328. // "class": "go.GraphLinksModel",
  329. // "linkFromPortIdProperty": "fromPort",
  330. // "linkToPortIdProperty": "toPort",
  331. // "nodeDataArray": [],
  332. // "linkDataArray": []
  333. // }
  334. // }
  335. if(!flag){
  336. window.flag = true
  337. this.$router.push('/tool/activiti/modeler')
  338. this.currentChange({
  339. path:'/tool/activiti/modeler'
  340. });
  341. }
  342. resolve(res)
  343. }else{
  344. this.$Modal.fcError({
  345. title:'错误',
  346. content:res.resultMsg,
  347. onOk: () => {
  348. }
  349. })
  350. }
  351. })
  352. })
  353. },
  354. async formatGuiStyle () { //format整个流程图
  355. await new Promise((resolve) => {
  356. let startNode = {} //获取开始节点
  357. this.data.guiStyle.nodeDataArray.map(item => {
  358. if(item.key === -1){
  359. startNode = item
  360. }
  361. })
  362. let startlink = {}
  363. //获取第一根线的数据
  364. this.data.guiStyle.linkDataArray.map(item => {
  365. if(item.from === -1){
  366. startlink = item
  367. }
  368. })
  369. //获取连线的正确排序
  370. let linkMap = []
  371. new Array(this.data.guiStyle.linkDataArray.length).fill(null).map(() => {
  372. this.data.guiStyle.linkDataArray.map(item => {
  373. if(linkMap.length === 0 && item.from === -1){
  374. linkMap.push(item)
  375. }
  376. if(linkMap.length > 0 && item.from === linkMap[linkMap.length-1].to){
  377. linkMap.push(item)
  378. }
  379. })
  380. })
  381. this.data.guiStyle.linkDataArray = linkMap
  382. //获取节点的正确顺序
  383. // let nodeMap = [startNode]
  384. this.data.guiStyle.nodeDataArray = this.data.guiStyle.linkDataArray.reduce((sum,item) => {
  385. sum.push(this.data.Diagram.model.findNodeDataForKey(item.to))
  386. return sum
  387. },[startNode])
  388. //将所有节点的x轴与开始节点对齐
  389. this.data.guiStyle.nodeDataArray.map((item,index) => {
  390. let loc = item.loc.split(' ')
  391. loc[0] = startNode.loc.split(' ')[0]
  392. loc[1] = Number(startNode.loc.split(' ')[1]) + index*80
  393. item.loc = loc.join(' ')
  394. })
  395. //将所有连线的x轴与开始节点对齐
  396. this.data.guiStyle.linkDataArray.map((item,index) => {
  397. item.points.j.map(temp => {
  398. temp.F = startlink.points.j[0].F
  399. })
  400. item.points.j.map((temp,j) => {
  401. if(index === 0){
  402. if(j !== item.points.j.length-1){
  403. temp.G = Number(this.data.guiStyle.nodeDataArray[index].loc.split(' ')[1])+20
  404. }else{
  405. temp.G = Number(this.data.guiStyle.nodeDataArray[index+1].loc.split(' ')[1])-20
  406. }
  407. }else if(index === this.data.guiStyle.linkDataArray.length - 1){
  408. if(j !== item.points.j.length-1){
  409. temp.G = Number(this.data.guiStyle.nodeDataArray[index].loc.split(' ')[1])+20
  410. }else{
  411. temp.G = Number(this.data.guiStyle.nodeDataArray[index+1].loc.split(' ')[1])-20
  412. }
  413. }else{
  414. if(j !== item.points.j.length-1){
  415. temp.G = Number(this.data.guiStyle.nodeDataArray[index].loc.split(' ')[1])+20
  416. }else{
  417. temp.G = Number(this.data.guiStyle.nodeDataArray[index+1].loc.split(' ')[1])-20
  418. }
  419. }
  420. })
  421. })
  422. this.data.Diagram.model = go.Model.fromJson(this.data.guiStyle)
  423. setTimeout(() => {
  424. resolve()
  425. },100)
  426. })
  427. },
  428. dataChange (data) { //每一步中的数据变化
  429. this.data = Object.assign(this.data,data)
  430. },
  431. close () {
  432. this.$store.dispatch("tagsView/delView", this.$route);
  433. this.$router.push('/tool/activiti/modeler')
  434. this.currentChange({
  435. path:'/tool/activiti/modeler'
  436. });
  437. },
  438. confirmAndPublish () { //保存并发布
  439. this.confirm(true).then(res => {
  440. getPublish({id:res.data.id}).then((response) => {
  441. if(response.resultCode === 0){
  442. this.$store.dispatch("tagsView/delView", this.$route);
  443. this.$router.push('/tool/activiti/modeler')
  444. this.currentChange({
  445. path:'/tool/activiti/modeler'
  446. });
  447. }
  448. })
  449. })
  450. }
  451. },
  452. created () {
  453. Vue.component(`component_${this.currentSteps}`,Vue.extend(Object.assign({isKeepAliveModel:true},ParameterConfiguration)))
  454. this.currentComponent = `component_${this.currentSteps}`
  455. if(this.$route.params.flag === '1'){
  456. this.readOnly = true
  457. this.noFreshFlag = true
  458. this.currentSteps = 1
  459. this.getModuleInfo(this.$route.params.id)
  460. return
  461. }
  462. if(this.$route.params.id === undefined){ //新增
  463. }else{ //编辑
  464. this.noFreshFlag = true
  465. this.currentSteps = 1
  466. this.getModuleInfo(this.$route.params.id)
  467. }
  468. },
  469. beforeDestroy () {
  470. }
  471. }
  472. </script>
  473. <style lang="scss" scoped>
  474. .TemplateManagementNew{
  475. padding:16px;
  476. background: white;
  477. display: flex;
  478. height: calc(100vh - 100px);
  479. flex-direction: column;
  480. .breadcrumb{
  481. margin-bottom: 30px;
  482. font-size: 18px;
  483. }
  484. .steps{
  485. width: 75%;
  486. margin-left: 12.5%;
  487. margin-bottom: 30px;
  488. }
  489. .content{
  490. flex:1;
  491. border:1px solid rgba(220,222,226,1);
  492. display: flex;
  493. flex-direction: column;
  494. position: relative;
  495. // 预览tips
  496. .tips{
  497. width:260px;
  498. height:204px;
  499. background:rgba(236,236,236,1);
  500. padding: 16px;
  501. box-sizing: border-box;
  502. display: inline-block;
  503. position: absolute;
  504. top: 0;
  505. left: 0;
  506. z-index: 99;
  507. >p{
  508. font-weight:400;
  509. color:rgba(52,52,52,1);
  510. line-height:16px;
  511. margin-bottom: 12px;
  512. display: flex;
  513. >span:first-child{
  514. margin-right: 8px;
  515. white-space: nowrap;
  516. }
  517. >span:last-child{
  518. word-break: break-all;
  519. }
  520. }
  521. }
  522. .block{
  523. flex: 1;
  524. }
  525. .buttonGroups{
  526. text-align: right;
  527. padding-bottom: 16px;
  528. button{
  529. margin-right: 10px;
  530. &:last-child{
  531. margin-right:16px;
  532. }
  533. }
  534. }
  535. }
  536. .burgeon-steps-item.burgeon-steps-status-finish .burgeon-steps-head-inner > .burgeon-steps-icon, .burgeon-steps-item.burgeon-steps-status-finish .burgeon-steps-head-inner span{
  537. color: white;
  538. }
  539. .burgeon-steps-item.burgeon-steps-status-finish .burgeon-steps-head-inner{
  540. border-color: #09A155;
  541. background: #09A155;
  542. }
  543. }
  544. </style>