index.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. <template>
  2. <div class="ele-body">
  3. <el-card shadow="never">
  4. <seek-page
  5. :seekList="seekList"
  6. @search="search"
  7. ref="search"
  8. :keyValue="'qms-inspectionWork-index-search'"
  9. ></seek-page>
  10. <ele-pro-table
  11. ref="table"
  12. :columns="columns"
  13. :datasource="datasource"
  14. :pageSize="20"
  15. :pageSizes="[20, 30, 40, 50, 100]"
  16. @columns-change="handleColumnChange"
  17. :cache-key="cacheKeyUrl"
  18. row-key="id"
  19. @selection-change="selectionChangeHandle"
  20. >
  21. <!-- 表头工具栏 -->
  22. <template v-slot:toolbar>
  23. <el-button
  24. v-if="$hasPermission('qms:quality_work_order:close')"
  25. size="small"
  26. type="primary"
  27. class="ele-btn-icon"
  28. @click="batchClose"
  29. :disabled="selection.length === 0"
  30. >
  31. 批量关闭
  32. </el-button>
  33. </template>
  34. <template v-slot:code="{ row }">
  35. <el-link
  36. type="primary"
  37. :underline="false"
  38. @click="openDetails(row)"
  39. >{{ row.code }}</el-link
  40. >
  41. </template>
  42. <template v-slot:sourceCode="{ row }">
  43. <div>{{
  44. row.qualityPlanCode ? row.qualityPlanCode : row.workOrderCode
  45. }}</div>
  46. </template>
  47. <template v-slot:files="scope">
  48. <el-link
  49. v-for="link in scope.row.files"
  50. :key="link.id"
  51. type="primary"
  52. :underline="false"
  53. @click="downloadFile(link)"
  54. >{{ link.name }}</el-link
  55. >
  56. </template>
  57. <template v-slot:qualityType="{ row }">{{
  58. getDictValue('质检计划类型', row.qualityType)
  59. }}</template>
  60. <template v-slot:qualityMode="{ row }">{{
  61. getDictValue('取样类型', row.qualityMode)
  62. }}</template>
  63. <template v-slot:accessory="scope">
  64. <el-link
  65. v-for="link in scope.row.accessory"
  66. :key="link.id"
  67. type="primary"
  68. :underline="false"
  69. @click="downloadFile(link)"
  70. >{{ link.name }}</el-link
  71. >
  72. </template>
  73. <!-- 操作列 -->
  74. <template v-slot:action="{ row }">
  75. <!-- <el-link
  76. type="primary"
  77. :underline="false"
  78. @click="addSampleOpen(row)"
  79. >取样</el-link
  80. > -->
  81. <el-link
  82. type="primary"
  83. :underline="false"
  84. v-if="row.status == 0 && $hasPermission('qms:quality_work_order:update')"
  85. @click="openEdit('edit', row)"
  86. >报工</el-link
  87. >
  88. <el-link
  89. type="primary"
  90. :underline="false"
  91. v-if="row.status == 0 && $hasPermission('qms:quality_work_order:transfer')"
  92. @click="openTransfer(row.id)"
  93. >转派</el-link
  94. >
  95. <el-link v-if="$hasPermission('qms:quality_work_order:certificate')" type="primary" :underline="false" @click="openNumber(row)"
  96. >合格证</el-link
  97. >
  98. <jimureportBrowse
  99. style="display: inline-block; margin-left: 5px"
  100. v-if="row.status == 1 && $hasPermission('qms:quality_work_order:qualityReport')"
  101. text="质检报告"
  102. :businessId="row.id"
  103. businessCode="qmsqualityinspectionprint"
  104. ></jimureportBrowse>
  105. <el-dropdown
  106. trigger="click"
  107. v-if="
  108. row.status == 1 &&
  109. isReportApproval == 1 &&
  110. (!row.reportApprovalStatus || row.reportApprovalStatus == 0) && isEmptyObject(row.reportTemplateJson) &&
  111. $hasPermission('qms:quality_work_order:generateReport')
  112. "
  113. >
  114. <el-link
  115. type="primary"
  116. :underline="false"
  117. >生成质检报告</el-link
  118. >
  119. <el-dropdown-menu slot="dropdown">
  120. <el-dropdown-item
  121. v-for="item in reportTemplateList"
  122. :key="item.id"
  123. @click.native="generateReportApproval(row, item)"
  124. >{{ item.name }}</el-dropdown-item
  125. >
  126. </el-dropdown-menu>
  127. </el-dropdown>
  128. <el-link
  129. v-if="
  130. row.status == 1 &&
  131. isReportApproval == 1 &&
  132. (row.reportApprovalStatus && !isEmptyObject(row.reportTemplateJson)) &&
  133. $hasPermission('qms:quality_work_order:generateReport')
  134. "
  135. type="primary"
  136. :underline="false"
  137. @click="openReport(row)"
  138. >查看质检报告</el-link
  139. >
  140. <!-- 质检报告审批 -->
  141. <el-link
  142. v-if="
  143. row.status == 1 &&
  144. isReportApproval == 1 &&
  145. !row.reportApprovalStatus &&
  146. $hasPermission('qms:quality_work_order:qualityReportApproval')
  147. "
  148. type="primary"
  149. :underline="false"
  150. @click="reportApprovalSubmit(row)"
  151. >质检报告审批</el-link
  152. >
  153. <el-popconfirm
  154. class="ele-action"
  155. title="确定要关闭吗?"
  156. @confirm="close(row)"
  157. v-if="row.status == 0 && row.qualityType == 2 && $hasPermission('qms:quality_work_order:close')"
  158. >
  159. <template v-slot:reference>
  160. <el-link type="warning" :underline="false"> 关闭 </el-link>
  161. </template>
  162. </el-popconfirm>
  163. </template>
  164. </ele-pro-table>
  165. </el-card>
  166. <Certificate
  167. @search="search"
  168. v-if="addOpen"
  169. :rowData="rowData"
  170. :addOpen="addOpen"
  171. @closeModel="closeModel"
  172. />
  173. <Transfer
  174. v-if="transferVisible"
  175. :transferVisible.sync="transferVisible"
  176. @success="transferConfirm"
  177. :id="transferId"
  178. ></Transfer>
  179. <process-submit-dialog
  180. api-fun-name="qmsReportApprovalAPI"
  181. :processSubmitDialogFlag.sync="processSubmitDialogFlag"
  182. :isCloseRefresh="false"
  183. v-if="processSubmitDialogFlag"
  184. ref="processSubmitDialogRef"
  185. @reload="search"
  186. ></process-submit-dialog>
  187. <addSample ref="addSampleRef" @reload="search"></addSample>
  188. <!-- <inspectionReport1 ref="qualityRef" @reload="search" :isView="true"></inspectionReport1> -->
  189. <component
  190. :is="targetComponent"
  191. ref="targetComponentRef"
  192. v-if="targetComponent"
  193. :key="targetComponent"
  194. :isView="isView"
  195. :visible.sync="targetVisible"
  196. :row="currentRow"
  197. :item="currentItem"
  198. @reload="search"
  199. ></component>
  200. </div>
  201. </template>
  202. <script>
  203. import Certificate from './components/Certificate.vue';
  204. import search from './components/search.vue';
  205. import addSample from './components/addSample.vue';
  206. import jimureportBrowse from '@/components/jimureport/browseModal.vue';
  207. import Transfer from './components/transfer.vue';
  208. import processSubmitDialog from '@/components/processSubmitDialog/processSubmitDialog.vue';
  209. import {
  210. getList,
  211. removeItem,
  212. updateCertificateNumber,
  213. closeWorkList,
  214. verificationQualityInspector,
  215. closeWork
  216. } from '@/api/inspectionWork';
  217. import { queryTodo } from '@/api/bpm/task';
  218. import dictMixins from '@/mixins/dictMixins';
  219. import { getFile } from '@/api/system/file';
  220. import { getByCode } from '@/api/system/dictionary-data';
  221. import { parameterGetByCode } from '@/api/main/index';
  222. import tabMixins from '@/mixins/tableColumnsMixin';
  223. import { getCategoryByCode } from '@/api/main/index';
  224. import { getQmsReportTemplatePageList } from '@/api/inspectionWork';
  225. import inspection_report1 from '../inspectionReport/template/inspection_report1.vue';
  226. export default {
  227. mixins: [dictMixins, tabMixins],
  228. components: {
  229. search,
  230. jimureportBrowse,
  231. Certificate,
  232. Transfer,
  233. processSubmitDialog,
  234. addSample,
  235. inspection_report1
  236. },
  237. data() {
  238. return {
  239. cacheKeyUrl: 'qsm-c2e9664a-inspectionWork',
  240. targetComponent: null,
  241. isView: false,
  242. targetVisible: false,
  243. currentRow: {},
  244. currentItem: {},
  245. columns: [
  246. // 新增多选列
  247. {
  248. width: 45,
  249. type: 'selection',
  250. columnKey: 'selection',
  251. align: 'center',
  252. reserveSelection: true
  253. },
  254. {
  255. type: 'index',
  256. columnKey: 'index',
  257. align: 'center',
  258. label: '序号',
  259. width: 55,
  260. showOverflowTooltip: true,
  261. fixed: 'left'
  262. },
  263. {
  264. prop: 'code',
  265. label: '质检工单编码',
  266. slot: 'code',
  267. align: 'center',
  268. width: 180,
  269. showOverflowTooltip: true,
  270. fixed: 'left'
  271. },
  272. {
  273. prop: 'name',
  274. slot: 'name',
  275. width: 120,
  276. label: '质检工单名称',
  277. align: 'center',
  278. showOverflowTooltip: true
  279. },
  280. {
  281. label: '来源单号',
  282. prop: 'sourceCode',
  283. slot: 'sourceCode',
  284. align: 'center',
  285. width: 160,
  286. showOverflowTooltip: true
  287. },
  288. {
  289. label: '类型',
  290. prop: 'qualityType',
  291. slot: 'qualityType',
  292. align: 'center',
  293. width: 120,
  294. showOverflowTooltip: true
  295. },
  296. {
  297. label: '质检方式',
  298. prop: 'qualityMode',
  299. slot: 'qualityMode',
  300. align: 'center',
  301. width: 120,
  302. showOverflowTooltip: true
  303. },
  304. {
  305. prop: 'qualityName',
  306. label: '质检人',
  307. align: 'center',
  308. width: 120,
  309. showOverflowTooltip: true,
  310. formatter: (row) => {
  311. if (row.qualityName) {
  312. return row.qualityName;
  313. }
  314. return row.qualityNames || '';
  315. }
  316. },
  317. {
  318. prop: 'qualityTime',
  319. label: '质检时间',
  320. align: 'center',
  321. width: 120,
  322. showOverflowTooltip: true
  323. },
  324. {
  325. prop: 'productCode',
  326. width: 120,
  327. label: '编码',
  328. align: 'center',
  329. showOverflowTooltip: true
  330. },
  331. {
  332. prop: 'productName',
  333. width: 120,
  334. label: '名称',
  335. align: 'center',
  336. showOverflowTooltip: true
  337. },
  338. {
  339. prop: 'batchNo',
  340. label: '批次号',
  341. align: 'center',
  342. width: 120,
  343. showOverflowTooltip: true
  344. },
  345. {
  346. prop: 'specification',
  347. label: '规格',
  348. align: 'center',
  349. showOverflowTooltip: true
  350. },
  351. {
  352. prop: 'brandNo',
  353. label: '牌号',
  354. align: 'center',
  355. showOverflowTooltip: true
  356. },
  357. {
  358. prop: 'produceTaskName',
  359. label: '工序',
  360. align: 'center',
  361. width: 120,
  362. showOverflowTooltip: true
  363. },
  364. {
  365. prop: 'total',
  366. label: '总数量',
  367. align: 'center',
  368. showOverflowTooltip: true
  369. },
  370. {
  371. prop: 'qualifiedNumber',
  372. label: '合格数',
  373. align: 'center',
  374. showOverflowTooltip: true
  375. },
  376. {
  377. prop: 'qualificationRate',
  378. label: '合格率',
  379. align: 'center',
  380. showOverflowTooltip: true
  381. },
  382. {
  383. prop: 'noQualifiedNumber',
  384. label: '不合格数',
  385. align: 'center',
  386. showOverflowTooltip: true
  387. },
  388. {
  389. prop: 'noQualificationRate',
  390. label: '不合格率',
  391. align: 'center',
  392. showOverflowTooltip: true
  393. },
  394. {
  395. prop: 'hours',
  396. label: '工时',
  397. align: 'center',
  398. showOverflowTooltip: true
  399. },
  400. {
  401. label: '附件',
  402. prop: 'accessory',
  403. align: 'center',
  404. slot: 'accessory',
  405. showOverflowTooltip: true
  406. },
  407. {
  408. label: '创建时间',
  409. prop: 'createTime',
  410. align: 'center',
  411. width: 160
  412. },
  413. {
  414. prop: 'status',
  415. label: '状态',
  416. align: 'center',
  417. width: 80,
  418. formatter: (row, column, cellValue) => {
  419. // 状态(0未报工;1已报工;2已关闭;3待取样)
  420. switch (cellValue) {
  421. case 0:
  422. return '未报工';
  423. case 1:
  424. return '已报工';
  425. case 2:
  426. return '已关闭';
  427. case 3:
  428. return '待取样';
  429. default:
  430. return '';
  431. }
  432. },
  433. fixed: 'right'
  434. },
  435. {
  436. columnKey: 'action',
  437. label: '操作',
  438. align: 'center',
  439. width: 200,
  440. resizable: false,
  441. slot: 'action',
  442. fixed: 'right'
  443. }
  444. ],
  445. formData: {
  446. certificateNumber: ''
  447. },
  448. processSubmitDialogFlag: false,
  449. rowData: {},
  450. typeList: [], //类型列表
  451. qualityMode: [], //取样类型
  452. // 状态(0未报工;1已报工;2已关闭;3待取样)
  453. statusList: [
  454. {
  455. value: 0,
  456. label: '未报工'
  457. },
  458. {
  459. value: 1,
  460. label: '已报工'
  461. }
  462. // ,
  463. // {
  464. // value: 2,
  465. // label: '已关闭'
  466. // },
  467. // {
  468. // value: 3,
  469. // label: '待取样'
  470. // }
  471. ],
  472. addOpen: false,
  473. transferVisible: false,
  474. transferId: '',
  475. isReportApproval: 0,
  476. selection: [], // 存储选中的行数据
  477. reportTemplateList: [], // 报表模板列表
  478. templateArr: ['inspection_report1', 'ABBCCC']
  479. };
  480. },
  481. created() {
  482. this.requestDict('质检计划类型');
  483. this.requestDict('不良品处理类型');
  484. this.requestDict('取样类型');
  485. this.getCode();
  486. this.getReportTemplateList();
  487. this.getTnspectionPlanType();
  488. this.getQualityMethodCode();
  489. },
  490. computed: {
  491. seekList() {
  492. return [
  493. {
  494. label: '工单编码:',
  495. value: 'code',
  496. type: 'input',
  497. placeholder: ''
  498. },
  499. {
  500. label: '工单名称:',
  501. value: 'name',
  502. type: 'input',
  503. placeholder: ''
  504. },
  505. {
  506. label: '来源单号:',
  507. value: 'sourceCode',
  508. type: 'input',
  509. placeholder: ''
  510. },
  511. {
  512. label: '类型:',
  513. value: 'qualityType',
  514. type: 'select',
  515. placeholder: '',
  516. planList: this.typeList
  517. },
  518. {
  519. label: '质检方式:',
  520. value: 'qualityMode',
  521. type: 'select',
  522. placeholder: '',
  523. planList: this.qualityMode
  524. },
  525. {
  526. label: '编码:',
  527. value: 'productCode',
  528. type: 'input',
  529. placeholder: ''
  530. },
  531. {
  532. label: '名称:',
  533. value: 'productName',
  534. type: 'input',
  535. placeholder: ''
  536. },
  537. {
  538. label: '质检人:',
  539. value: 'qualityName',
  540. type: 'input',
  541. placeholder: ''
  542. },
  543. {
  544. label: '状态:',
  545. value: 'status',
  546. type: 'select',
  547. placeholder: '',
  548. planList: this.statusList
  549. }
  550. ];
  551. },
  552. clientEnvironmentId() {
  553. return this.$store.state.user.info.clientEnvironmentId;
  554. }
  555. },
  556. methods: {
  557. getReportTemplateList() {
  558. getQmsReportTemplatePageList({
  559. pageNum: 1,
  560. pageSize: 999,
  561. isEnabled: 1
  562. }).then((res) => {
  563. this.reportTemplateList = res.list;
  564. console.log('reportTemplateList', this.reportTemplateList);
  565. }).catch((err) => {
  566. console.error('获取报表模板列表失败:', err);
  567. // this.$message.error('获取报表模板列表失败:' + (err.message || '操作异常'));
  568. });
  569. },
  570. generateReportApproval(row, item) {
  571. console.log('item~~~', item);
  572. console.log('generateReportApproval', row, item);
  573. this.targetComponent = item.code;
  574. this.isView = false;
  575. this.currentRow = row;
  576. this.currentItem = item;
  577. // this.$refs.targetComponentRef.open(item, row);
  578. this.$nextTick(() => {
  579. // this.$refs.targetComponentRef.open(row, isView);
  580. this.targetVisible = true;
  581. console.log('targetVisible~~~~', this.targetVisible);
  582. });
  583. },
  584. openReport(row) {
  585. console.log('openReport', row);
  586. this.targetComponent = row.reportTemplateCode;
  587. this.isView = true;
  588. this.currentRow = row;
  589. this.$nextTick(() => {
  590. this.targetVisible = true;
  591. });
  592. },
  593. selectionChangeHandle(val) {
  594. this.selection = val;
  595. },
  596. addSampleOpen(row) {
  597. this.$refs.addSampleRef.open(row);
  598. },
  599. // 批量关闭
  600. batchClose() {
  601. const validRows = this.selection.filter(
  602. (row) => row.status === 0 && row.qualityType === 2
  603. );
  604. if (validRows.length === 0) {
  605. this.$message.warning('所选工单中没有可关闭的工单');
  606. return;
  607. }
  608. this.$confirm(`确定关闭选中的 ${validRows.length} 个工单吗?`, '提示', {
  609. confirmButtonText: '确定',
  610. cancelButtonText: '取消',
  611. type: 'warning'
  612. }).then(async () => {
  613. try {
  614. await closeWorkList(validRows.map((row) => row.id));
  615. this.$refs.table.clearSelection();
  616. this.search();
  617. } catch (err) {
  618. this.$message.error('批量关闭失败:' + (err.message || '操作异常'));
  619. }
  620. });
  621. },
  622. reportApprovalSubmit(res) {
  623. this.processSubmitDialogFlag = true;
  624. this.$nextTick(async () => {
  625. let params = {
  626. businessId: res.id,
  627. businessKey: 'qms_report_approval',
  628. formCreateUserId: res.createUserId,
  629. variables: {
  630. businessCode: res.code,
  631. businessName: res.name,
  632. businessType: '质检报告单'
  633. }
  634. };
  635. if (this.clientEnvironmentId == 5) {
  636. const data = await getCategoryByCode(res.productCode);
  637. if (data && data.categoryLevelCodePath?.includes('W3-209')) {
  638. params.businessKey = 'qms_report_approval1';
  639. } else {
  640. params.businessKey = 'qms_report_approval';
  641. }
  642. }
  643. this.$refs.processSubmitDialogRef.init(params);
  644. });
  645. },
  646. getCode() {
  647. parameterGetByCode({
  648. code: 'qms_report_approval'
  649. }).then((res) => {
  650. this.isReportApproval = res.value;
  651. });
  652. },
  653. async datasource({ page, where, limit }) {
  654. try {
  655. await queryTodo({});
  656. } catch (err) {
  657. console.error('调用queryTodo失败:', err);
  658. }
  659. return getList({
  660. ...where,
  661. pageNum: page,
  662. size: limit
  663. });
  664. },
  665. search(where) {
  666. this.$refs.table.reload({
  667. where: where
  668. // page: 1
  669. });
  670. },
  671. isEmptyObject(obj) {
  672. return Object.keys(obj).length === 0;
  673. },
  674. async openEdit(type, row) {
  675. const menusList = this.$store.state.user.menus;
  676. let found = false;
  677. if (type == 'edit') {
  678. const code = await verificationQualityInspector(row.id);
  679. if (code == '-1') {
  680. return;
  681. }
  682. }
  683. for (const item of menusList) {
  684. if (item.children) {
  685. for (const item2 of item.children) {
  686. if (item2.path === '/inspectionWork/edit') {
  687. found = true;
  688. const id = type !== 'add' ? row.id : '';
  689. const qualityType = type !== 'add' ? row.qualityType : null;
  690. const qualityTimeStart = row.qualityTimeStart || '';
  691. this.$router.push({
  692. path: '/inspectionWork/edit',
  693. query: {
  694. type,
  695. id,
  696. qualityType,
  697. qualityTimeStart
  698. }
  699. });
  700. return;
  701. }
  702. }
  703. }
  704. }
  705. if (!found) {
  706. this.$message.error('请到角色管理配置菜单权限!');
  707. }
  708. },
  709. openDetails(row) {
  710. let id = row.id;
  711. this.$router.push({
  712. path: '/inspectionWork/details',
  713. query: { id, path: '/inspectionWork', name: '工单' }
  714. });
  715. },
  716. downloadFile(file) {
  717. getFile({ objectName: file.storePath }, file.name);
  718. },
  719. remove(row) {
  720. removeItem([row.id])
  721. .then((message) => {
  722. this.$message.success(message);
  723. this.done();
  724. })
  725. .catch((e) => {});
  726. },
  727. done() {
  728. this.$refs.search.search();
  729. },
  730. openNumber(row) {
  731. this.formData.certificateNumber = row.certificateNumber;
  732. this.rowData = row;
  733. this.addOpen = true;
  734. },
  735. closeModel() {
  736. this.addOpen = false;
  737. },
  738. async close(row) {
  739. await closeWork(row);
  740. this.done();
  741. },
  742. async getTnspectionPlanType() {
  743. let res = await getByCode('inspection_plan_type');
  744. if (res?.code == 0) {
  745. let list = res.data.map((item) => {
  746. let key = Object.keys(item)[0];
  747. return { value: key, label: item[key] };
  748. });
  749. this.typeList = list;
  750. }
  751. },
  752. async getQualityMethodCode() {
  753. let res = await getByCode('quality_method_code');
  754. if (res?.code == 0) {
  755. let list = res.data.map((item) => {
  756. let key = Object.keys(item)[0];
  757. return { value: key, label: item[key] };
  758. });
  759. this.qualityMode = list;
  760. }
  761. },
  762. openTransfer(id) {
  763. this.transferVisible = true;
  764. this.transferId = id;
  765. },
  766. transferConfirm(id) {
  767. this.transferVisible = false;
  768. this.$message.success('转派成功');
  769. this.done();
  770. }
  771. }
  772. };
  773. </script>