scheduling-mould-details.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. <template>
  2. <div class="production">
  3. <el-dialog title="排产模板详情"
  4. width="70%"
  5. :close-on-click-modal="false"
  6. :visible.sync="visible">
  7. <el-form :model="dataForm" :rules="dataRule" ref="dataForm" label-width="auto">
  8. <el-row class="my-row">
  9. <el-col :span="8">
  10. <el-form-item label="产品" prop="productId">
  11. <el-select
  12. v-model="dataForm.productId"
  13. :disabled="display"
  14. @change="productChange"
  15. remote
  16. placeholder="请选择">
  17. <el-option
  18. v-for="item in productList"
  19. :key="item.productId"
  20. :label="item.productName"
  21. :value="item.productId">
  22. </el-option>
  23. </el-select>
  24. </el-form-item>
  25. </el-col>
  26. <el-col :span="12">
  27. <el-form-item label="模板名称" prop="mouldName">
  28. <el-input placeholder="请输入模板名称" v-model="dataForm.mouldName" maxlength="30" show-word-limit></el-input>
  29. </el-form-item>
  30. </el-col>
  31. </el-row>
  32. <el-row class="my-row" style="height: 350px; background-color: #efefef;">
  33. <super-flow
  34. v-if="visible"
  35. ref="superFlow"
  36. :node-list="nodeList"
  37. :link-list="linkList"
  38. :graph-menu="graphMenuList"
  39. :node-menu="nodeMenuList"
  40. :link-menu="linkMenuList"
  41. :link-desc="linkDesc">
  42. </super-flow>
  43. </el-row>
  44. </el-form>
  45. <span slot="footer" class="dialog-footer">
  46. <el-button @click="visible = false">取消</el-button>
  47. <el-button type="primary" @click="dataFormSubmit()">确认提交</el-button>
  48. </span>
  49. </el-dialog>
  50. <el-dialog
  51. :title="drawerConf.title"
  52. :visible.sync="drawerConf.visible"
  53. :close-on-click-modal="false"
  54. width="500px">
  55. <el-form
  56. @keyup.native.enter="settingSubmit"
  57. @submit.native.prevent
  58. v-show="drawerConf.type === drawerType.node"
  59. ref="nodeSetting"
  60. :rules="dataRule1"
  61. :model="nodeSetting">
  62. <el-row class="my-row">
  63. <el-col :span="24">
  64. <el-form-item
  65. label="节点名称"
  66. prop="name">
  67. <el-input
  68. v-model="nodeSetting.name"
  69. placeholder="请输入节点名称"
  70. maxlength="30"
  71. disabled>
  72. </el-input>
  73. </el-form-item>
  74. </el-col>
  75. </el-row>
  76. <el-row class="my-row" >
  77. <el-col :span="24" v-if="drawerConf.prop !== 'end'">
  78. <el-form-item
  79. label="操作人员"
  80. prop="operatorIds">
  81. <el-select
  82. v-model="nodeSetting.operatorIds"
  83. multiple
  84. style="width:100%"
  85. placeholder="请选择">
  86. <el-option
  87. v-for="item in operatorList"
  88. :key="item.userId"
  89. :label="item.name"
  90. :value="item.userId">
  91. </el-option>
  92. </el-select>
  93. </el-form-item>
  94. </el-col>
  95. </el-row>
  96. </el-form>
  97. <span
  98. slot="footer"
  99. class="dialog-footer">
  100. <el-button
  101. @click="drawerConf.cancel">
  102. 取 消
  103. </el-button>
  104. <el-button
  105. type="primary"
  106. @click="settingSubmit">
  107. 确 定
  108. </el-button>
  109. </span>
  110. </el-dialog>
  111. </div>
  112. </template>
  113. <script>
  114. import { getStepId } from '@/api/crafts'
  115. import { getMouldDetail, getProductList, getMouldDetailByProductId, saveProdProductionMould, updateProdProductionMould } from '@/api/production'
  116. import { workTypeMasterList } from '@/api/worktype'
  117. import { uuid } from '../common/vue-super-flow/utils'
  118. const drawerType = {
  119. node: 0,
  120. link: 1
  121. }
  122. export default {
  123. name: 'scheduling-details',
  124. data () {
  125. return {
  126. mouldId: '',
  127. visible: false,
  128. dataForm: {
  129. mouldName: ''
  130. },
  131. drawerType,
  132. operatorList: [],
  133. operatorIds: [],
  134. productList: [],
  135. display: false,
  136. drawerConf: {
  137. title: '',
  138. visible: false,
  139. prop: '',
  140. type: null,
  141. info: null,
  142. open: (type, info) => {
  143. if (info.meta.workTypeId && info.meta.prop !== 'end') {
  144. this.getOperatorList(info.meta.workTypeId);
  145. }
  146. const conf = this.drawerConf
  147. conf.visible = true
  148. conf.type = type
  149. conf.info = info
  150. if (conf.type === drawerType.node) {
  151. conf.title = '节点'
  152. conf.prop = info.meta.prop
  153. if (this.$refs.nodeSetting) this.$refs.nodeSetting.resetFields()
  154. this.$set(this.nodeSetting, 'name', info.meta.name)
  155. this.$set(this.nodeSetting, 'desc', info.meta.desc)
  156. // this.$set(this.nodeSetting, 'prop', info.meta.prop)
  157. this.$set(this.nodeSetting, 'type', info.meta.type)
  158. this.$set(this.nodeSetting, 'workTypeId', info.meta.workTypeId)
  159. this.$set(this.nodeSetting, 'operatorIds', info.meta.operatorIds)
  160. } else {
  161. conf.title = '连线'
  162. if (this.$refs.linkSetting) this.$refs.linkSetting.resetFields()
  163. // this.$set(this.linkSetting, 'desc', info.meta ? info.meta.desc : '')
  164. }
  165. },
  166. cancel: () => {
  167. this.drawerConf.visible = false
  168. if (this.drawerConf.type === drawerType.node) {
  169. this.$refs.nodeSetting.clearValidate()
  170. } else {
  171. this.$refs.linkSetting.clearValidate()
  172. }
  173. }
  174. },
  175. linkSetting: {
  176. desc: ''
  177. },
  178. nodeSetting: {
  179. name: '',
  180. desc: '',
  181. type: 1,
  182. workTypeId: ''
  183. },
  184. nodeList: [],
  185. linkList: [],
  186. graphMenuList: [
  187. [
  188. {
  189. label: '开始节点',
  190. disable: true,
  191. selected: async (graph, coordinate) => {
  192. const start = graph.nodeList.find(node => node.meta.prop === 'start')
  193. let id = ''
  194. await getStepId().then(({ data }) => {
  195. id = data.data.stepId
  196. })
  197. if (!start) {
  198. graph.addNode({
  199. width: 90,
  200. height: 50,
  201. coordinate: coordinate,
  202. id: id,
  203. meta: {
  204. prop: 'start',
  205. name: '开始节点'
  206. }
  207. })
  208. }
  209. }
  210. },
  211. {
  212. label: '节点',
  213. disable: true,
  214. selected: async (graph, coordinate) => {
  215. let id = ''
  216. await getStepId().then(({ data }) => {
  217. id = data.data.stepId
  218. })
  219. graph.addNode({
  220. width: 120,
  221. height: 70,
  222. coordinate: coordinate,
  223. id: id,
  224. meta: {
  225. prop: 'condition',
  226. name: '节点名称'
  227. }
  228. })
  229. }
  230. },
  231. {
  232. label: '结束节点',
  233. disable: true,
  234. selected: async (graph, coordinate) => {
  235. let id = ''
  236. await getStepId().then(({ data }) => {
  237. id = data.data.stepId
  238. })
  239. graph.addNode({
  240. width: 90,
  241. height: 50,
  242. coordinate: coordinate,
  243. id: id,
  244. meta: {
  245. prop: 'end',
  246. name: '结束节点'
  247. }
  248. })
  249. }
  250. }
  251. ],
  252. [
  253. {
  254. label: '完成',
  255. selected: (graph, coordinate) => {
  256. graph.selectAll()
  257. this.datas = graph
  258. console.log(graph)
  259. }
  260. }
  261. ]
  262. ],
  263. nodeMenuList: [
  264. [
  265. {
  266. label: '删除',
  267. disable: true,
  268. hidden (node) {
  269. return node.meta.prop === 'start'
  270. },
  271. selected (node, coordinate) {
  272. node.remove()
  273. }
  274. }
  275. ],
  276. [
  277. {
  278. label: '编辑',
  279. selected: (node, coordinate) => {
  280. this.drawerConf.open(drawerType.node, node)
  281. }
  282. }
  283. ]
  284. ],
  285. linkMenuList: [
  286. [
  287. {
  288. label: '删除',
  289. selected: (link, coordinate) => {
  290. link.remove()
  291. }
  292. }
  293. ]
  294. ],
  295. datas: {},
  296. dataRule: {
  297. mouldName: [{required: true, message: '请输入模板名称', trigger: 'blur'}]
  298. },
  299. dataRule1: {
  300. operatorIds: [{ required: true, message: '操作人员不能为空', trigger: 'change' }]
  301. }
  302. }
  303. },
  304. methods: {
  305. // 初始化产品名称列表
  306. async initProductList() {
  307. getProductList().then(({data}) => {
  308. if(data && data.code === '200') {
  309. data.data.forEach(item => {
  310. this.productList.push(item)
  311. })
  312. }
  313. })
  314. },
  315. // 初始化表单
  316. async init (id, disable) {
  317. this.visible = true
  318. this.display = disable
  319. this.nodeList = []
  320. this.linkList = []
  321. this.mouldId = id;
  322. if(!disable){
  323. await this.initProductList();
  324. }
  325. await getMouldDetail(id).then(async ({data}) => {
  326. if (data && data.code === '200') {
  327. this.dataForm = data.data
  328. // 图纸
  329. if (this.dataForm.proTechnologyStepList) {
  330. const dataline = []
  331. const datanode = []
  332. await this.dataForm.proTechnologyStepList.forEach((v, i) => {
  333. // eslint-disable-next-line no-unused-vars
  334. const sortNo = []
  335. const datas = v.sort((a, b) => Number(a['sortNo']) - Number(b['sortNo']))
  336. let length = datas.length
  337. datas.forEach((item, index) => {
  338. const find = datanode.find(map => map.id === item.stepId)
  339. if (!find) {
  340. datanode.push({
  341. id: item.stepId,
  342. width: (index === 0 || item.workTypeId === '0') ? 90 : 120,
  343. height: (index === 0 || item.workTypeId === '0') ? 50 : 70,
  344. coordinate: item.coordinate.split(','),
  345. meta: {
  346. name: item.stepName,
  347. desc: item.operatorName,
  348. prop: index === 0 ? 'start' : (index === length - 1) ? 'end' : 'condition',
  349. notes: item.notes || '',
  350. workTypeId: item.workTypeId || '',
  351. type: item.type || '',
  352. operatorIds: item.operatorId.split(',')
  353. }
  354. })
  355. }
  356. const id = item.stepId
  357. if ((index + 1) < datas.length) {
  358. if (datas[index + 1]) {
  359. dataline.push({
  360. id: uuid('link'),
  361. startId: id,
  362. endId: datas[index + 1].stepId,
  363. meta: '',
  364. startAt: [(index === 0 || item.workTypeId === '0') ? 90 : 120, (index === 0 || item.workTypeId === '0') ? 25 : 35],
  365. endAt: [0, (index === 0 || item.workTypeId === '0') ? 25 : 35]
  366. })
  367. }
  368. }
  369. })
  370. })
  371. this.$nextTick(() => {
  372. setTimeout(() => {
  373. this.nodeList = datanode
  374. this.linkList = dataline
  375. }, 200)
  376. })
  377. }
  378. }
  379. })
  380. },
  381. //根据产品ID查询步骤详情
  382. async productChange(productId) {
  383. getMouldDetailByProductId(productId).then(async ({data}) => {
  384. if (data && data.code === '200') {
  385. this.dataForm = {...this.dataForm, proTechnologyStepLists :data.data}
  386. // 图纸
  387. if (this.dataForm.proTechnologyStepLists) {
  388. const dataline = []
  389. const datanode = []
  390. await this.dataForm.proTechnologyStepLists.forEach((v, i) => {
  391. // eslint-disable-next-line no-unused-vars
  392. const sortNo = []
  393. const datas = v.sort((a, b) => Number(a['sortNo']) - Number(b['sortNo']))
  394. let length = datas.length
  395. datas.forEach((item, index) => {
  396. const find = datanode.find(map => map.id === item.stepId)
  397. if (!find) {
  398. datanode.push({
  399. id: item.stepId,
  400. width: (index === 0 || item.workTypeId === '0') ? 90 : 120,
  401. height: (index === 0 || item.workTypeId === '0') ? 50 : 70,
  402. coordinate: item.coordinate.split(','),
  403. meta: {
  404. name: item.stepName,
  405. prop: index === 0 ? 'start' : (index === length - 1) ? 'end' : 'condition',
  406. notes: item.notes || '',
  407. workTypeId: item.workTypeId || '',
  408. type: item.type || ''
  409. }
  410. })
  411. }
  412. const id = item.stepId
  413. if ((index + 1) < datas.length) {
  414. if (datas[index + 1]) {
  415. dataline.push({
  416. id: uuid('link'),
  417. startId: id,
  418. endId: datas[index + 1].stepId,
  419. meta: '',
  420. startAt: [(index === 0 || item.workTypeId === '0') ? 90 : 120, (index === 0 || item.workTypeId === '0') ? 25 : 35],
  421. endAt: [0, (index === 0 || item.workTypeId === '0') ? 25 : 35]
  422. })
  423. }
  424. }
  425. })
  426. })
  427. this.$nextTick(() => {
  428. setTimeout(() => {
  429. this.nodeList = datanode
  430. this.linkList = dataline
  431. }, 200)
  432. })
  433. }
  434. }
  435. })
  436. },
  437. // 按工种ID查询操作人列表
  438. getOperatorList(workTypeId) {
  439. workTypeMasterList(workTypeId).then(({data}) => {
  440. if (data && data.code === '200') {
  441. this.operatorList = []
  442. data.data.forEach(item => {
  443. this.operatorList.push(item);
  444. })
  445. }
  446. })
  447. },
  448. linkDesc (link) {
  449. return link.meta ? link.meta.desc : ''
  450. },
  451. settingSubmit () {
  452. this.$refs['nodeSetting'].validate((valid) => {
  453. if (valid) {
  454. const conf = this.drawerConf
  455. if (this.drawerConf.type === drawerType.node) {
  456. if (!conf.info.meta) conf.info.meta = {}
  457. Object.keys(this.nodeSetting).forEach(key => {
  458. if (key == 'operatorIds') {
  459. let idList = this.nodeSetting[key];
  460. let nameList = [];
  461. idList.forEach(id => {
  462. let name = this.operatorList.find(item => {
  463. return item.userId === id
  464. }).name
  465. nameList.push(name)
  466. })
  467. this.$set(conf.info.meta, 'desc', nameList.join(','))
  468. }
  469. this.$set(conf.info.meta, key, this.nodeSetting[key])
  470. })
  471. this.$refs.nodeSetting.resetFields()
  472. } else {
  473. if (!conf.info.meta) conf.info.meta = {}
  474. Object.keys(this.linkSetting).forEach(key => {
  475. this.$set(conf.info.meta, key, this.linkSetting[key])
  476. })
  477. this.$refs.linkSetting.resetFields()
  478. }
  479. conf.visible = false
  480. }
  481. })
  482. },
  483. dataFormSubmit () {
  484. if (!this.datas.nodeList) {
  485. this.$message.error('请先完成流程图!')
  486. return
  487. }
  488. if (this.datas.nodeList.length <= 2) {
  489. this.$message.error('请先完成流程图!')
  490. return
  491. }
  492. this.$refs['dataForm'].validate((valid) => {
  493. if(valid) {
  494. const proTechnologyStepLists = []
  495. let productionPlanSteps = []
  496. for (let index = 0; index < this.datas.nodeList.length; index++) {
  497. const v = this.datas.nodeList[index];
  498. let tmp = v.meta.operatorIds || []
  499. if(v.meta.prop !== 'end' && tmp.length == 0){
  500. this.$message.error(`请选择 ${v.meta.name} 的操作人员!`)
  501. return
  502. }
  503. productionPlanSteps.push({stepId: v.id, operatorId: tmp.join(',')})
  504. }
  505. let submitData = {
  506. mouldName: this.dataForm.mouldName,
  507. productId: this.dataForm.productId,
  508. stepList: productionPlanSteps
  509. }
  510. if(this.mouldId === 0) {
  511. // 新增
  512. saveProdProductionMould(submitData).then(({data}) => {
  513. if (data && data.code === '200') {
  514. this.$message({
  515. message: '操作成功',
  516. type: 'success',
  517. duration: 1500,
  518. onClose: () => {
  519. this.$emit('refreshDataList')
  520. this.visible = false
  521. }
  522. })
  523. } else {
  524. this.$message.error(data.msg)
  525. }
  526. })
  527. } else {
  528. // 更新
  529. submitData.mouldId = this.mouldId;
  530. updateProdProductionMould(submitData).then(({data}) => {
  531. if (data && data.code === '200') {
  532. this.$message({
  533. message: '操作成功',
  534. type: 'success',
  535. duration: 1500,
  536. onClose: () => {
  537. this.$emit('refreshDataList')
  538. this.visible = false
  539. }
  540. })
  541. } else {
  542. this.$message.error(data.msg)
  543. }
  544. })
  545. }
  546. }
  547. })
  548. },
  549. getLineData (dataAll, dList, lList, id, sortNo) {
  550. const _l = []
  551. lList.forEach(l => {
  552. if (l.start.id === id) {
  553. _l.push(l.end.id)
  554. }
  555. })
  556. if (!sortNo) {
  557. const data = dList.filter(v => v.meta.prop === 'start')[0]
  558. _l.forEach(item => {
  559. dataAll.push([{
  560. 'notes': data.meta.desc || '',
  561. 'sortNo': 0,
  562. 'stepId': data.id,
  563. 'stepName': data.meta.name,
  564. 'workTypeId': data.meta.workTypeId || null,
  565. 'type': data.meta.type || null,
  566. 'coordinate': data.coordinate.join(','),
  567. 'operatorIds': data.meta.operatorIds
  568. }])
  569. })
  570. }
  571. dList.forEach(v => {
  572. const _i = _l.indexOf(v.id)
  573. if (_i > -1) {
  574. if (!v.meta.workTypeId && v.meta.prop !== 'end') {
  575. this.$message.error('完善节点工种')
  576. return
  577. }
  578. if (!sortNo) {
  579. dataAll[_i].push({
  580. 'notes': v.meta.desc || '',
  581. 'sortNo': (sortNo + 1),
  582. 'stepId': v.id,
  583. 'stepName': v.meta.name,
  584. 'workTypeId': v.meta.workTypeId || null,
  585. 'type': v.meta.type || null,
  586. 'coordinate': v.coordinate.join(',')
  587. })
  588. this.getLineData(dataAll[_i], dList, lList, v.id, (sortNo + 1))
  589. } else {
  590. let _has = false
  591. dataAll.forEach(items => {
  592. if (items.stepId === v.id) {
  593. _has = true
  594. }
  595. })
  596. if (!_has) {
  597. dataAll.push({
  598. 'notes': v.meta.desc || '',
  599. 'sortNo': (sortNo + 1),
  600. 'stepId': v.id,
  601. 'stepName': v.meta.name,
  602. 'workTypeId': v.meta.prop === 'end' ? 0 : (v.meta.workTypeId || ''),
  603. 'type': v.meta.type || '',
  604. 'coordinate': v.coordinate.join(',')
  605. })
  606. }
  607. this.getLineData(dataAll, dList, lList, v.id, (sortNo + 1))
  608. }
  609. }
  610. })
  611. },
  612. }
  613. }
  614. </script>
  615. <style scoped>
  616. </style>