index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. <template>
  2. <div class="sc-workflow-design">
  3. <div class="zoom-scale">
  4. <el-button circle icon="plus" :disabled="zoom >= 150" @click="onZoom(1)" />
  5. <span>{{ zoom }}%</span>
  6. <el-button circle icon="minus" :disabled="zoom <= 40" @click="onZoom(-1)" />
  7. </div>
  8. <div class="box-scale" :style="`transform: scale(${zoom / 100})`">
  9. <node-wrap v-if="nodeConfig" v-model="nodeConfig" :disabled="disabled"></node-wrap>
  10. <div class="node-wrap">
  11. <div class="node-wrap-box node-wrap-box--disabled end-node" :class="[`node-wrap-box--${nodeConfig.lastNode_local_status}`]">
  12. <div class="title" style="background: var(--el-color-info)">
  13. <span class="title_label">结束</span>
  14. </div>
  15. <div class="content">
  16. <span>流程结束</span>
  17. </div>
  18. </div>
  19. </div>
  20. <!-- <div class="end-node">
  21. <div class="end-node-circle"></div>
  22. <div class="end-node-text">流程结束</div>
  23. </div>-->
  24. </div>
  25. <use-select v-if="selectVisible" ref="useselect" @update:selected="update_activeSelected" @closed="selectVisible = false"></use-select>
  26. </div>
  27. </template>
  28. <script>
  29. import nodeWrap from './nodeWrap'
  30. import useSelect from './select'
  31. // import promoter from '@/components/scWorkflow/nodes/promoter.vue'
  32. export default {
  33. name: 'ScWorkflow',
  34. components: {
  35. // promoter,
  36. nodeWrap,
  37. useSelect
  38. },
  39. provide() {
  40. return {
  41. select: this.selectHandle,
  42. getRootConfig: this.getCurrentConfig
  43. }
  44. },
  45. props: {
  46. modelValue: { type: Object, default: () => {} },
  47. disabled: {
  48. type: Boolean,
  49. default: false
  50. }
  51. },
  52. data() {
  53. return {
  54. zoom: 100,
  55. nodeConfig: this.modelValue,
  56. selectVisible: false,
  57. activeSelected: [] /*,
  58. end_nodeConfig: {
  59. nodeName: '结束'
  60. // nodeName: '发起人',
  61. // type: 0,
  62. // nodeAssigneeList: []
  63. }*/
  64. }
  65. },
  66. watch: {
  67. modelValue(val) {
  68. this.nodeConfig = val
  69. },
  70. nodeConfig(val) {
  71. this.$emit('update:modelValue', val)
  72. }
  73. },
  74. mounted() {},
  75. methods: {
  76. getCurrentConfig() {
  77. return this.nodeConfig
  78. },
  79. update_activeSelected(newSelected) {
  80. this.activeSelected.splice(0, this.activeSelected.length, ...newSelected)
  81. },
  82. selectHandle(type, data) {
  83. this.selectVisible = true
  84. this.activeSelected = data
  85. this.$nextTick(() => {
  86. this.$refs.useselect.open(type, data)
  87. })
  88. },
  89. onZoom(n) {
  90. this.zoom += 10 * n
  91. if (this.zoom <= 40) {
  92. this.zoom = 40
  93. } else if (this.zoom >= 150) {
  94. this.zoom = 150
  95. }
  96. }
  97. }
  98. }
  99. </script>
  100. <style lang="scss">
  101. $bg_color: #f6f8f9;
  102. .sc-workflow-design {
  103. height: 100%;
  104. background: $bg_color;
  105. //width: 100%;
  106. .box-scale {
  107. transform-origin: 50% 0px 0px;
  108. }
  109. .zoom-scale {
  110. z-index: 999;
  111. position: fixed;
  112. top: 178px;
  113. right: 40px;
  114. span {
  115. margin: 0 10px;
  116. font-size: 15px;
  117. color: #7a7a7a;
  118. width: 50px;
  119. }
  120. }
  121. }
  122. .sc-workflow-design .box-scale {
  123. display: inline-block;
  124. position: relative;
  125. width: 100%;
  126. min-height: 100%;
  127. padding: 54.5px 0;
  128. align-items: flex-start;
  129. justify-content: center;
  130. flex-wrap: wrap;
  131. min-width: min-content;
  132. background: $bg_color;
  133. }
  134. .sc-workflow-design {
  135. .node-wrap {
  136. display: inline-flex;
  137. width: 100%;
  138. flex-flow: column wrap;
  139. justify-content: flex-start;
  140. align-items: center;
  141. padding: 0px 50px;
  142. position: relative;
  143. z-index: 1;
  144. & + .node-wrap {
  145. .node-wrap-box.end-node:before {
  146. content: '';
  147. }
  148. }
  149. }
  150. .node-wrap-box {
  151. display: inline-flex;
  152. flex-direction: column;
  153. position: relative;
  154. width: 220px;
  155. min-height: 72px;
  156. flex-shrink: 0;
  157. background: rgb(255, 255, 255);
  158. border-radius: 4px;
  159. cursor: pointer;
  160. box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.1);
  161. &--disabled {
  162. cursor: default;
  163. /*.content {
  164. color: var(--el-text-color-disabled);
  165. }*/
  166. .title_label {
  167. &:hover {
  168. text-decoration-line: none !important;
  169. }
  170. }
  171. }
  172. // 已执行
  173. &--success {
  174. .title {
  175. background: var(--el-color-success) !important;
  176. }
  177. }
  178. // 执行中
  179. &--error {
  180. .title {
  181. background: var(--el-color-warning) !important;
  182. }
  183. }
  184. // 未执行
  185. &--info {
  186. .title {
  187. background: var(--el-color-info) !important;
  188. }
  189. }
  190. &.start-node,
  191. &.end-node {
  192. .title_label {
  193. &:hover {
  194. text-decoration-line: none;
  195. }
  196. }
  197. }
  198. }
  199. .node-wrap-box::before {
  200. content: '';
  201. position: absolute;
  202. top: -12px;
  203. left: 50%;
  204. transform: translateX(-50%);
  205. width: 0px;
  206. border-style: solid;
  207. border-width: 8px 6px 4px;
  208. border-color: rgb(202, 202, 202) transparent transparent;
  209. background: $bg_color;
  210. }
  211. .node-wrap-box.start-node:before,
  212. .node-wrap-box.end-node:before {
  213. content: none;
  214. }
  215. .node-wrap-box .title {
  216. height: 24px;
  217. line-height: 24px;
  218. color: #fff;
  219. padding-left: 16px;
  220. padding-right: 30px;
  221. border-radius: 4px 4px 0 0;
  222. position: relative;
  223. display: flex;
  224. align-items: center;
  225. &_label {
  226. display: inline-flex;
  227. align-items: center;
  228. &:hover {
  229. text-decoration-line: underline;
  230. }
  231. .edit-icon {
  232. margin-left: 4px;
  233. }
  234. }
  235. }
  236. .node-wrap-box .title .icon {
  237. margin-right: 5px;
  238. }
  239. .node-wrap-box .title .close {
  240. font-size: 15px;
  241. position: absolute;
  242. top: 50%;
  243. transform: translateY(-50%);
  244. right: 10px;
  245. display: none;
  246. }
  247. .node-wrap-box .content {
  248. position: relative;
  249. padding: 15px;
  250. }
  251. .node-wrap-box .content .placeholder {
  252. color: #999;
  253. }
  254. .node-wrap-box:hover .close {
  255. display: block;
  256. }
  257. .add-node-btn-box {
  258. width: 240px;
  259. display: inline-flex;
  260. flex-shrink: 0;
  261. position: relative;
  262. z-index: 1;
  263. }
  264. .add-node-btn-box:before {
  265. content: '';
  266. position: absolute;
  267. top: 0px;
  268. left: 0px;
  269. right: 0px;
  270. bottom: 0px;
  271. z-index: -1;
  272. margin: auto;
  273. width: 2px;
  274. height: 100%;
  275. background-color: rgb(202, 202, 202);
  276. }
  277. .add-node-btn {
  278. user-select: none;
  279. width: 240px;
  280. padding: 20px 0px 32px;
  281. display: flex;
  282. justify-content: center;
  283. flex-shrink: 0;
  284. flex-grow: 1;
  285. }
  286. .add-node-btn span {
  287. }
  288. .add-branch {
  289. justify-content: center;
  290. padding: 0px 10px;
  291. position: absolute;
  292. top: -16px;
  293. left: 50%;
  294. transform: translateX(-50%);
  295. transform-origin: center center;
  296. z-index: 1;
  297. display: inline-flex;
  298. align-items: center;
  299. }
  300. .branch-wrap {
  301. display: inline-flex;
  302. width: 100%;
  303. &--disabled {
  304. .branch-box {
  305. margin-top: 0;
  306. }
  307. .add-branch {
  308. display: none;
  309. }
  310. .auto-judge {
  311. cursor: default;
  312. &:hover {
  313. .close {
  314. display: none;
  315. }
  316. .priority-title {
  317. display: block;
  318. //display: none;
  319. }
  320. &:after {
  321. border: unset;
  322. box-shadow: unset;
  323. }
  324. .sort-left {
  325. display: none;
  326. }
  327. .sort-right {
  328. display: none;
  329. }
  330. }
  331. }
  332. }
  333. /*// 已执行
  334. &--success {
  335. .auto-judge:after {
  336. border: 1px solid var(--el-color-success) !important;
  337. }
  338. //.title {
  339. // //background: var(--el-color-success) !important;
  340. //}
  341. }
  342. // 执行中
  343. &--error {
  344. .auto-judge:after {
  345. border: 1px solid var(--el-color-error) !important;
  346. }
  347. !* .title {
  348. background: var(--el-color-error) !important;
  349. }*!
  350. }
  351. // 未执行
  352. &--info {
  353. .auto-judge:after {
  354. border: 1px solid var(--el-color-info) !important;
  355. }
  356. !*.title {
  357. background: var(--el-color-info) !important;
  358. }*!
  359. }*/
  360. }
  361. .branch-box-wrap {
  362. display: flex;
  363. flex-flow: column wrap;
  364. align-items: center;
  365. min-height: 270px;
  366. width: 100%;
  367. flex-shrink: 0;
  368. }
  369. .col-box {
  370. display: inline-flex;
  371. flex-direction: column;
  372. align-items: center;
  373. position: relative;
  374. background: $bg_color;
  375. }
  376. .branch-box {
  377. display: flex;
  378. overflow: visible;
  379. min-height: 180px;
  380. height: auto;
  381. border-bottom: 2px solid #ccc;
  382. border-top: 2px solid #ccc;
  383. position: relative;
  384. margin-top: 15px;
  385. }
  386. .branch-box .col-box::before {
  387. content: '';
  388. position: absolute;
  389. top: 0px;
  390. left: 0px;
  391. right: 0px;
  392. bottom: 0px;
  393. z-index: 0;
  394. margin: auto;
  395. width: 2px;
  396. height: 100%;
  397. background-color: rgb(202, 202, 202);
  398. }
  399. .condition-node {
  400. display: inline-flex;
  401. flex-direction: column;
  402. min-height: 220px;
  403. }
  404. .condition-node-box {
  405. padding-top: 30px;
  406. padding-right: 50px;
  407. padding-left: 50px;
  408. justify-content: center;
  409. align-items: center;
  410. flex-grow: 1;
  411. position: relative;
  412. display: inline-flex;
  413. flex-direction: column;
  414. }
  415. .condition-node-box::before {
  416. content: '';
  417. position: absolute;
  418. top: 0px;
  419. left: 0px;
  420. right: 0px;
  421. bottom: 0px;
  422. margin: auto;
  423. width: 2px;
  424. height: 100%;
  425. background-color: rgb(202, 202, 202);
  426. }
  427. .auto-judge {
  428. position: relative;
  429. width: 220px;
  430. min-height: 72px;
  431. background: rgb(255, 255, 255);
  432. border-radius: 4px;
  433. padding: 15px 15px;
  434. cursor: pointer;
  435. box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.1);
  436. // 已执行
  437. &--success:after {
  438. border: 1px solid var(--el-color-success) !important;
  439. }
  440. // 未执行
  441. &--info:after {
  442. border: 1px solid var(--el-color-info) !important;
  443. }
  444. }
  445. .auto-judge::before {
  446. content: '';
  447. position: absolute;
  448. top: -12px;
  449. left: 50%;
  450. transform: translateX(-50%);
  451. width: 0px;
  452. border-style: solid;
  453. border-width: 8px 6px 4px;
  454. border-color: rgb(202, 202, 202) transparent transparent;
  455. //background: rgb(245, 245, 247);
  456. background: $bg_color;
  457. }
  458. .auto-judge .title {
  459. line-height: 16px;
  460. }
  461. .auto-judge .title .node-title {
  462. color: var(--el-color-success);
  463. &.last-child-title {
  464. color: #999;
  465. }
  466. }
  467. .auto-judge .title .close {
  468. font-size: 15px;
  469. position: absolute;
  470. top: 15px;
  471. right: 15px;
  472. color: #999;
  473. display: none;
  474. }
  475. .auto-judge .title .priority-title {
  476. position: absolute;
  477. top: 15px;
  478. right: 15px;
  479. color: #999;
  480. }
  481. .auto-judge .content {
  482. position: relative;
  483. padding-top: 15px;
  484. &.last-child-title {
  485. padding-top: 5px;
  486. span {
  487. line-height: 1;
  488. }
  489. }
  490. }
  491. .auto-judge .content .placeholder {
  492. color: #999;
  493. }
  494. .auto-judge:hover {
  495. .close {
  496. display: block;
  497. }
  498. .priority-title {
  499. display: none;
  500. }
  501. }
  502. .top-left-cover-line,
  503. .top-right-cover-line {
  504. position: absolute;
  505. height: 3px;
  506. width: 50%;
  507. background-color: $bg_color;
  508. top: -2px;
  509. }
  510. .bottom-left-cover-line,
  511. .bottom-right-cover-line {
  512. position: absolute;
  513. height: 3px;
  514. width: 50%;
  515. background-color: $bg_color;
  516. bottom: -2px;
  517. }
  518. .top-left-cover-line {
  519. left: -1px;
  520. }
  521. .top-right-cover-line {
  522. right: -1px;
  523. }
  524. .bottom-left-cover-line {
  525. left: -1px;
  526. }
  527. .bottom-right-cover-line {
  528. right: -1px;
  529. }
  530. .end-node {
  531. //border-radius: 50%;
  532. //font-size: 14px;
  533. //color: rgba(25, 31, 37, 0.4);
  534. color: var(--el-text-color-disabled);
  535. //text-align: left;
  536. }
  537. /*.end-node-circle {
  538. width: 10px;
  539. height: 10px;
  540. margin: auto;
  541. border-radius: 50%;
  542. background: #dbdcdc;
  543. }
  544. .end-node-text {
  545. margin-top: 5px;
  546. text-align: center;
  547. }*/
  548. .auto-judge:hover {
  549. .sort-left {
  550. display: flex;
  551. }
  552. .sort-right {
  553. display: flex;
  554. }
  555. }
  556. .auto-judge .sort-left {
  557. position: absolute;
  558. top: 0;
  559. bottom: 0;
  560. z-index: 1;
  561. left: 0;
  562. display: none;
  563. justify-content: center;
  564. align-items: center;
  565. flex-direction: column;
  566. }
  567. .auto-judge .sort-right {
  568. position: absolute;
  569. top: 0;
  570. bottom: 0;
  571. z-index: 1;
  572. right: 0;
  573. display: none;
  574. justify-content: center;
  575. align-items: center;
  576. flex-direction: column;
  577. }
  578. .auto-judge .sort-left:hover,
  579. .auto-judge .sort-right:hover {
  580. background: #eee;
  581. }
  582. .auto-judge:after {
  583. pointer-events: none;
  584. content: '';
  585. position: absolute;
  586. top: 0;
  587. bottom: 0;
  588. left: 0;
  589. right: 0;
  590. z-index: 2;
  591. border-radius: 4px;
  592. transition: all 0.1s;
  593. }
  594. .auto-judge:hover:after {
  595. border: 1px solid var(--el-color-primary);
  596. box-shadow: 0 0 6px 0 var(--el-color-primary-light-5);
  597. }
  598. .node-wrap-box:after {
  599. pointer-events: none;
  600. content: '';
  601. position: absolute;
  602. top: 0;
  603. bottom: 0;
  604. left: 0;
  605. right: 0;
  606. z-index: 2;
  607. border-radius: 4px;
  608. transition: all 0.1s;
  609. }
  610. .node-wrap-box:not(.node-wrap-box--disabled):hover:after {
  611. border: 1px solid var(--el-color-primary);
  612. box-shadow: 0 0 6px 0 var(--el-color-primary-light-5);
  613. }
  614. }
  615. .tags-list {
  616. margin-top: 15px;
  617. width: 100%;
  618. }
  619. .add-node-popover-body {
  620. ul {
  621. padding: 0;
  622. }
  623. }
  624. .add-node-popover-body li {
  625. display: inline-block;
  626. width: 80px;
  627. text-align: center;
  628. padding: 10px 0;
  629. }
  630. .add-node-popover-body li i {
  631. border: 1px solid var(--el-border-color-light);
  632. width: 40px;
  633. height: 40px;
  634. border-radius: 50%;
  635. text-align: center;
  636. line-height: 38px;
  637. font-size: 18px;
  638. cursor: pointer;
  639. }
  640. .add-node-popover-body li i:hover {
  641. border: 1px solid var(--el-color-primary);
  642. background: var(--el-color-primary);
  643. color: #fff !important;
  644. }
  645. .add-node-popover-body li p {
  646. font-size: 12px;
  647. margin-top: 5px;
  648. }
  649. .node-wrap-drawer__title {
  650. padding-right: 40px;
  651. }
  652. .node-wrap-drawer__title label {
  653. cursor: pointer;
  654. font-size: 14px;
  655. }
  656. .node-wrap-drawer__title label:hover {
  657. border-bottom: 1px dashed var(--el-color-primary);
  658. }
  659. .node-wrap-drawer__title .node-wrap-drawer__title-edit {
  660. color: var(--el-color-primary);
  661. margin-left: 10px;
  662. vertical-align: middle;
  663. }
  664. .dark .sc-workflow-design {
  665. .box-scale {
  666. background: var(--el-bg-color);
  667. }
  668. /*.col-box {
  669. background: var(--el-bg-color);
  670. }*/
  671. .node-wrap-box,
  672. .auto-judge {
  673. background: #2b2b2b;
  674. }
  675. .top-left-cover-line,
  676. .top-right-cover-line,
  677. .bottom-left-cover-line,
  678. .bottom-right-cover-line {
  679. background-color: var(--el-bg-color);
  680. }
  681. .node-wrap-box::before,
  682. .auto-judge::before {
  683. background-color: var(--el-bg-color);
  684. }
  685. .branch-box .add-branch {
  686. background: var(--el-bg-color);
  687. }
  688. .end-node .end-node-text {
  689. color: #d0d0d0;
  690. }
  691. .auto-judge .sort-left:hover,
  692. .auto-judge .sort-right:hover {
  693. background: var(--el-bg-color);
  694. }
  695. }
  696. $header_height: 55px;
  697. // drawer样式
  698. .aDrawer {
  699. .el-drawer__header {
  700. display: flex;
  701. flex-shrink: 0;
  702. align-items: center;
  703. box-sizing: border-box;
  704. width: 100%;
  705. height: 48px;
  706. padding: 0 16px;
  707. margin-bottom: 0px;
  708. border-bottom: 1px solid var(--el-border-color-lighter);
  709. color: var(--el-overlay-color);
  710. }
  711. .el-drawer__body {
  712. box-sizing: border-box;
  713. height: 100%;
  714. padding: 12px 16px;
  715. overflow: auto;
  716. .el-main {
  717. padding: 0;
  718. }
  719. .el-footer {
  720. padding: 10px 0 0 0;
  721. }
  722. }
  723. }
  724. // 公用的样式
  725. .svg-icon-box {
  726. position: absolute;
  727. bottom: -20px;
  728. right: 50%;
  729. background-color: rgb(255, 255, 255);
  730. padding: 10px;
  731. border-radius: 50%;
  732. margin-right: -18px;
  733. z-index: 99;
  734. }
  735. </style>