JGDetails.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. <template>
  2. <div class="ele-body">
  3. <el-card shadow="never">
  4. <ele-split-layout
  5. width="260px"
  6. allow-collapse
  7. :resizable="true"
  8. :min-size="200"
  9. :max-size="-200"
  10. :left-style="{
  11. overflow: 'hidden',
  12. width: '100%'
  13. }"
  14. :right-style="{ overflow: 'hidden' }"
  15. :responsive="false"
  16. >
  17. <div class="ele-border-lighter sys-organization-list">
  18. <div class="radio_box rx-cc">
  19. <el-radio-group
  20. size="small"
  21. v-model="currentNodeData.bomType"
  22. @change="bomChange"
  23. >
  24. <el-radio-button :label="1">PBOM </el-radio-button>
  25. <el-radio-button
  26. v-if="[1, 9].includes(rootPathIdParent)"
  27. :label="2"
  28. >MBOM</el-radio-button
  29. >
  30. <el-radio-button
  31. v-if="[1, 9].includes(rootPathIdParent)"
  32. :label="3"
  33. >ABOM</el-radio-button
  34. >
  35. </el-radio-group>
  36. </div>
  37. <el-input
  38. size="small"
  39. placeholder="在结构中查找"
  40. v-model="filterText"
  41. >
  42. </el-input>
  43. <el-tree
  44. class="treeData"
  45. :data="treeList"
  46. :expand-on-click-node="false"
  47. :props="defaultProps"
  48. ref="treeRef"
  49. :default-expanded-keys="current && current.id ? [current.id] : []"
  50. :highlight-current="true"
  51. node-key="id"
  52. @node-click="handleNodeClick"
  53. >
  54. <span class="custom-tree-node" slot-scope="{ node, data }">
  55. {{ node.label }} / {{ data.code }}
  56. </span>
  57. </el-tree>
  58. </div>
  59. <template v-slot:content>
  60. <div class="pbom-box">
  61. <div class="button-list">
  62. <el-dropdown @command="handleDown">
  63. <el-button type="primary" size="mini" icon="el-icon-plus">
  64. 新建<i class="el-icon-arrow-down el-icon--right"></i>
  65. </el-button>
  66. <el-dropdown-menu slot="dropdown" >
  67. <el-dropdown-item command="a">新建BOM</el-dropdown-item>
  68. <el-dropdown-item command="b">新建物料</el-dropdown-item>
  69. </el-dropdown-menu>
  70. </el-dropdown>
  71. <el-button
  72. v-if="
  73. (currentNodeData.bomType == 2 ||
  74. currentNodeData.bomType == 3) &&
  75. currentNodeData.children?.length <= 0
  76. "
  77. type="danger"
  78. size="mini"
  79. icon="el-icon-delete"
  80. plain
  81. @click="remove"
  82. >删除</el-button
  83. >
  84. <el-button
  85. v-if="currentNodeData.bomType == 1"
  86. type="primary"
  87. size="mini"
  88. icon="el-icon-download"
  89. plain
  90. >导出</el-button
  91. >
  92. <el-button
  93. @click="uploadFile"
  94. v-if="currentNodeData.bomType == 1"
  95. type="primary"
  96. size="mini"
  97. icon="el-icon-upload2"
  98. plain
  99. >导入</el-button
  100. >
  101. <el-button
  102. type="primary"
  103. size="mini"
  104. icon="el-icon-refresh"
  105. plain
  106. @click="transformation('M')"
  107. v-if="currentNodeData.bomType == 1"
  108. >转换MBOM</el-button
  109. >
  110. <el-button
  111. type="primary"
  112. size="mini"
  113. icon="el-icon-refresh"
  114. plain
  115. @click="transformation('A')"
  116. v-if="currentNodeData.bomType == 1"
  117. >转换ABOM</el-button
  118. >
  119. <div v-if="!noBack" class="back-btn">
  120. <el-button size="mini" icon="el-icon-back" @click="back"
  121. >返回</el-button
  122. >
  123. </div>
  124. </div>
  125. <baseInfo :dataInfo="currentNodeData" />
  126. <el-tabs
  127. v-model="activeName"
  128. class="tab-box"
  129. type="border-card"
  130. @tab-click="handleClick"
  131. >
  132. <el-tab-pane label="属性" name="属性">
  133. <attribute :attributeData="currentNodeData"></attribute>
  134. </el-tab-pane>
  135. <el-tab-pane
  136. :label="
  137. currentNodeData.bomType == 1
  138. ? 'PBOM明细表'
  139. : currentNodeData.bomType == 2
  140. ? 'MBOM明细表'
  141. : 'ABOM明细表'
  142. "
  143. name="明细表"
  144. >
  145. <!-- <document></document> -->
  146. <detailedList :attributeData="currentNodeData"></detailedList>
  147. </el-tab-pane>
  148. <el-tab-pane
  149. label="工艺路线"
  150. name="工艺路线"
  151. v-if="
  152. [1, 9].includes(rootPathIdParent) &&
  153. currentNodeData.bomType != 1
  154. "
  155. >
  156. <routing
  157. ref="routingRef"
  158. :taskParam="currentNodeData"
  159. ></routing>
  160. </el-tab-pane>
  161. <el-tab-pane
  162. label="工序配置"
  163. name="工序配置"
  164. v-if="
  165. [1, 9].includes(rootPathIdParent) &&
  166. currentNodeData.bomType != 1
  167. "
  168. >
  169. <workmanship
  170. ref="workmanshipRef"
  171. :taskParam="currentNodeData"
  172. ></workmanship>
  173. </el-tab-pane>
  174. </el-tabs>
  175. </div>
  176. </template>
  177. </ele-split-layout>
  178. </el-card>
  179. <bomTreeDialog ref="bomTreeDialogRef" @reload="bomTreeDialogReload" />
  180. <importDialog
  181. :defModule="moudleName"
  182. ref="importDialogRef"
  183. @success="reload"
  184. />
  185. </div>
  186. </template>
  187. <script>
  188. import {
  189. getBomTreeList,
  190. getBomGetById,
  191. convert,
  192. convertABom,
  193. deleteBomTreeList
  194. } from '@/api/material/jgBom.js';
  195. import { getTreeByGroup } from '@/api/classifyManage';
  196. import attribute from './components/attribute.vue';
  197. import routing from './components/routing.vue';
  198. import baseInfo from './components/baseInfo.vue';
  199. // import document from './components/document.vue';
  200. import workmanship from './components/workmanship.vue';
  201. import bomTreeDialog from './components/bomTreeDialog.vue';
  202. import importDialog from './qualityTesting/import-dialog.vue';
  203. import detailedList from './components/detailedList.vue';
  204. export default {
  205. name: 'BOMmanage',
  206. components: {
  207. attribute,
  208. baseInfo,
  209. // document,
  210. workmanship,
  211. bomTreeDialog,
  212. routing,
  213. importDialog,
  214. detailedList
  215. },
  216. data() {
  217. return {
  218. activeName: '属性',
  219. currentNodeData: {
  220. bomType: 1,
  221. children: []
  222. },
  223. taskParam: [],
  224. current: {},
  225. treeList: [],
  226. treeLoading: false,
  227. rootTreeId: null,
  228. defaultProps: {
  229. children: 'children',
  230. label: 'name'
  231. },
  232. loading: false,
  233. filterText: null,
  234. categoryId: 1,
  235. versions: null,
  236. loadingInstance: null,
  237. noBack: false,
  238. treeId: null,
  239. moudleName: 'mainUser',
  240. rootPathIdParent: null
  241. };
  242. },
  243. watch: {
  244. // 监听$route.query对象的变化
  245. '$route.query': {
  246. immediate: true, // 启用立即执行
  247. handler(newQuery, oldQuery) {
  248. this.rootPathIdParent = Number(newQuery.categoryLevelPathIdParent);
  249. }
  250. }
  251. },
  252. mounted() {
  253. this.initData();
  254. },
  255. activated() {
  256. this.initData();
  257. },
  258. methods: {
  259. bomTreeDialogReload(versions) {
  260. this.versions = versions;
  261. if (!this.$route.query.versions) {
  262. this.$router.replace({
  263. path: '/material/BOMmanage/details',
  264. query: { categoryId: this.categoryId, versions: versions }
  265. });
  266. }
  267. this.getTreeData();
  268. },
  269. initData() {
  270. this.versions = this.$route.query.versions;
  271. this.categoryId = this.$route.query.categoryId;
  272. this.noBack = this.$route.query.noBack;
  273. (this.currentNodeData = {
  274. bomType: this.$route.query.bType || 1,
  275. children: []
  276. }),
  277. this.getTreeData();
  278. },
  279. handleClick(tab) {
  280. if (
  281. tab.name === '工艺路线' &&
  282. this.currentNodeData.children?.length < 1
  283. ) {
  284. this.$refs.routingRef.reload();
  285. }
  286. if (
  287. tab.name === '工序配置' &&
  288. this.currentNodeData.children?.length < 1
  289. ) {
  290. this.$refs.workmanshipRef.reload();
  291. }
  292. },
  293. remove() {
  294. this.$confirm('是否确认删除?', '提示', {
  295. confirmButtonText: '确定',
  296. cancelButtonText: '取消',
  297. type: 'warning'
  298. })
  299. .then(() => {
  300. const loading = this.$loading({ lock: true });
  301. deleteBomTreeList([this.currentNodeData.id])
  302. .then((msg) => {
  303. loading.close();
  304. this.$message.success('删除' + msg);
  305. this.getTreeData();
  306. })
  307. .catch((e) => {
  308. loading.close();
  309. // this.$message.error(e.message);
  310. });
  311. })
  312. .catch(() => {
  313. this.$message({
  314. type: 'info',
  315. message: '已取消删除'
  316. });
  317. });
  318. },
  319. bomChange(e) {
  320. this.currentNodeData.bomType = e;
  321. this.getTreeData();
  322. },
  323. back() {
  324. this.$router.go(-1);
  325. },
  326. transformation(tt) {
  327. this.loadingInstance = this.$loading({
  328. lock: true,
  329. text: '转换中...',
  330. background: 'rgba(0, 0, 0, 0.7)'
  331. });
  332. let ULR = tt == 'M' ? convert : tt == 'A' ? convertABom : '';
  333. ULR({ versions: this.versions, categoryId: this.categoryId }).then(
  334. (data) => {
  335. if (data.code == '0') {
  336. this.loadingInstance.close();
  337. this.$message.success('转换成功');
  338. }
  339. }
  340. );
  341. },
  342. handleDown(command) {
  343. if(command == 'b') {
  344. this.add()
  345. }
  346. },
  347. add() {
  348. this.$refs.bomTreeDialogRef.open(
  349. this.currentNodeData.bomType,
  350. this.versions,
  351. this.categoryId,
  352. this.treeId
  353. );
  354. },
  355. async getTreeData() {
  356. try {
  357. this.treeLoading = true;
  358. const res = await getBomTreeList({
  359. categoryId: this.categoryId,
  360. versions: this.versions,
  361. bomType: this.currentNodeData.bomType
  362. });
  363. this.treeLoading = false;
  364. if (res?.code === '0') {
  365. if (res.data?.length > 0) {
  366. this.treeList = res.data;
  367. this.$nextTick(() => {
  368. // 默认高亮第一个
  369. this.$refs.treeRef.setCurrentKey(res.data[0].id);
  370. this.handleNodeClick(res.data[0]);
  371. });
  372. } else {
  373. this.treeList = [];
  374. }
  375. return this.treeList;
  376. }
  377. } catch (error) {
  378. console.log(error);
  379. }
  380. this.treeLoading = false;
  381. },
  382. handleNodeClick(data) {
  383. this.treeId = data.id;
  384. this.handBomDetails(data.id);
  385. },
  386. handBomDetails(id) {
  387. if (id) {
  388. getBomGetById(id).then((res) => {
  389. // this.versions = res.data.versions;
  390. this.currentNodeData = res.data;
  391. if (
  392. this.activeName == '工艺路线' &&
  393. this.currentNodeData.children?.length < 1
  394. ) {
  395. this.$nextTick(() => {
  396. this.$refs.routingRef.reload();
  397. });
  398. }
  399. if (
  400. this.activeName == '工序配置' &&
  401. this.currentNodeData.children?.length < 1
  402. ) {
  403. this.$nextTick(() => {
  404. this.$refs.workmanshipRef.reload();
  405. });
  406. }
  407. });
  408. } else {
  409. this.currentNodeData = {
  410. bomType: 1,
  411. children: []
  412. };
  413. }
  414. },
  415. uploadFile() {
  416. this.$refs.importDialogRef.open();
  417. },
  418. reload(where) {
  419. this.getTreeData();
  420. }
  421. }
  422. };
  423. </script>
  424. <style lang="scss" scoped>
  425. .sys-organization-list {
  426. height: calc(100vh - 165px);
  427. box-sizing: border-box;
  428. border-width: 1px;
  429. border-style: solid;
  430. overflow: auto;
  431. padding: 0 10px;
  432. box-sizing: border-box;
  433. display: flex;
  434. flex-direction: column;
  435. overflow: hidden;
  436. .treeData {
  437. height: 0 1 auto;
  438. overflow-y: auto;
  439. }
  440. }
  441. .pbom-box,
  442. .mbom-box {
  443. height: calc(100vh - 165px);
  444. display: flex;
  445. flex-direction: column;
  446. .tab-box {
  447. flex: 1;
  448. display: flex;
  449. flex-direction: column;
  450. overflow: hidden;
  451. ::v-deep .el-tabs__content {
  452. flex: 1;
  453. overflow-y: auto !important;
  454. .table_box {
  455. height: 100%;
  456. }
  457. }
  458. }
  459. }
  460. .radio_box {
  461. margin: 12px 0;
  462. ::v-deep .el-radio-group {
  463. width: 100%;
  464. display: flex;
  465. .el-radio-button {
  466. flex: 1;
  467. > span {
  468. width: 100%;
  469. }
  470. }
  471. }
  472. }
  473. .sys-organization-list :deep(.el-tree-node__content) {
  474. height: 40px;
  475. & > .el-tree-node__expand-icon {
  476. margin-left: 10px;
  477. }
  478. }
  479. .button-list {
  480. display: flex;
  481. align-items: center;
  482. background-color: #f4f4f4;
  483. border: 1px solid #e3e5e5;
  484. padding: 10px;
  485. box-sizing: border-box;
  486. border-bottom: 0;
  487. .back-btn {
  488. flex: 1;
  489. text-align: right;
  490. }
  491. }
  492. </style>