index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. <template>
  2. <div class="mainContentBox">
  3. <avue-crud
  4. ref="crudRef"
  5. v-model:search="search"
  6. v-model="form"
  7. :data="data"
  8. :option="option"
  9. v-model:page="page"
  10. @row-save="createRowSave"
  11. @row-update="updateRow"
  12. @row-del="deleteRow"
  13. :table-loading="loading"
  14. @search-change="searchChange"
  15. @search-reset="resetChange"
  16. @size-change="dataList"
  17. @current-change="dataList"
  18. @selection-change="selectionChange"
  19. >
  20. <!-- <template #menu-right="{}">
  21. <el-button
  22. class="ml-3"
  23. @click="handleExport"
  24. >
  25. <template #icon> <i-ep-download /> </template>导出
  26. </el-button>
  27. </template>-->
  28. <template #menu="{ size, row, index }">
  29. <!-- <el-button
  30. icon="el-icon-edit"
  31. text
  32. @click="openDialog(1, row.id)"
  33. type="primary"
  34. :size="size"
  35. >编辑</el-button
  36. >-->
  37. <el-button
  38. icon="el-icon-view"
  39. text
  40. @click="openDialog(0, row)"
  41. type="primary"
  42. :size="size"
  43. >详情</el-button
  44. >
  45. </template>
  46. </avue-crud>
  47. <el-dialog
  48. v-model="dialog.visible"
  49. :title="dialog.title"
  50. width="1600px"
  51. @close="dialog.visible = false"
  52. >
  53. <el-table :data="itemList" border style="width: 100%">
  54. <el-table-column
  55. show-overflow-tooltip
  56. prop="operationName"
  57. label="工序"
  58. width="90"
  59. />
  60. <el-table-column
  61. show-overflow-tooltip
  62. prop="materialModel"
  63. label="物料型号"
  64. width="90"
  65. />
  66. <el-table-column
  67. show-overflow-tooltip
  68. prop="workOrderCode"
  69. label="产品批号"
  70. width="90"
  71. />
  72. <el-table-column prop="reReceiveUser" label="操作人" width="140">
  73. <template v-if="dialog.type === 1" #default="scope">
  74. <el-input v-model="scope.row.reReceiveUser"></el-input>
  75. </template>
  76. </el-table-column>
  77. <el-table-column prop="reDate" label="时间" width="120">
  78. <template v-if="dialog.type === 1" #default="scope">
  79. <el-date-picker
  80. value-format="YYYY-MM-DD"
  81. type="date"
  82. v-model="scope.row.reDate"
  83. ></el-date-picker>
  84. </template>
  85. </el-table-column>
  86. <el-table-column prop="reNum" label="接收数量" width="80">
  87. <template v-if="dialog.type === 1" #default="scope">
  88. <el-input v-model="scope.row.reNum"></el-input>
  89. </template>
  90. </el-table-column>
  91. <el-table-column prop="next0Num" label="合格品数" width="80">
  92. <template v-if="dialog.type === 1" #default="scope">
  93. <el-input v-model="scope.row.next0Num"></el-input>
  94. </template>
  95. </el-table-column>
  96. <el-table-column prop="next1Num" label="不合格品数" width="80">
  97. <template v-if="dialog.type === 1" #default="scope">
  98. <el-input v-model="scope.row.next1Num"></el-input>
  99. </template>
  100. </el-table-column>
  101. <el-table-column prop="passRate" label="合格品率" width="80">
  102. <template v-if="dialog.type === 1" #default="scope">
  103. <el-input v-model="scope.row.passRate"></el-input>
  104. </template>
  105. </el-table-column>
  106. <el-table-column prop="useDevice" label="使用设备及编号" width="150">
  107. <template v-if="dialog.type === 1" #default="scope">
  108. <el-input v-model="scope.row.useDevice"></el-input>
  109. </template>
  110. </el-table-column>
  111. <el-table-column prop="craftCondition" label="工艺条件" width="160">
  112. <template v-if="dialog.type === 1" #default="scope">
  113. <el-input v-model="scope.row.craftCondition"></el-input>
  114. </template>
  115. </el-table-column>
  116. <el-table-column prop="temperature" label="温度" width="85">
  117. <template v-if="dialog.type === 1" #default="scope">
  118. <el-input v-model="scope.row.temperature"></el-input>
  119. </template>
  120. </el-table-column>
  121. <el-table-column prop="humidity" label="湿度" width="85">
  122. <template v-if="dialog.type === 1" #default="scope">
  123. <el-input v-model="scope.row.humidity"></el-input>
  124. </template>
  125. </el-table-column>
  126. <el-table-column prop="remark" label="备注" width="100">
  127. <template v-if="dialog.type === 1" #default="scope">
  128. <el-input v-model="scope.row.remark"></el-input>
  129. </template>
  130. </el-table-column>
  131. <el-table-column prop="none" label="关联表单">
  132. <!-- <template #default="scope">
  133. <el-button v-if="scope.row.type == 1" @click="clickH(scope.row)" type="primary" link>
  134. 工作记录表
  135. </el-button>
  136. </template>-->
  137. <template #default="scope">
  138. <el-button
  139. icon="el-icon-setting"
  140. text
  141. @click="formList(scope.row)"
  142. type="primary"
  143. size="small"
  144. >表单列表</el-button
  145. >
  146. </template>
  147. </el-table-column>
  148. </el-table>
  149. <div class="dialog-footer" align="center" style="margin-top: 10px">
  150. <el-button @click="dialog.visible = false">取 消</el-button>
  151. <el-button
  152. type="primary"
  153. @click="handleExport"
  154. v-if="itemList.value !== 0"
  155. >导 出</el-button
  156. >
  157. </div>
  158. </el-dialog>
  159. <el-dialog
  160. v-model="dialog1.visible"
  161. :title="dialog1.title"
  162. width="800px"
  163. @close="dialog1.visible = false"
  164. >
  165. <el-form
  166. label-width="120px"
  167. size="large"
  168. :model="hInfo"
  169. ref="applyFormRef"
  170. >
  171. <el-row>
  172. <el-col :span="12">
  173. <el-form-item label="电路型号" prop="materialModel">
  174. <el-input v-model="hInfo.materialModel" />
  175. </el-form-item>
  176. </el-col>
  177. <el-col :span="12">
  178. <el-form-item label="生产批号" prop="workOrderCode">
  179. <el-input v-model="hInfo.workOrderCode" />
  180. </el-form-item>
  181. </el-col>
  182. </el-row>
  183. <el-row>
  184. <el-col :span="24">
  185. <el-form-item label="工艺规程" prop="craft">
  186. <el-input v-model="hInfo.craft" />
  187. </el-form-item>
  188. </el-col>
  189. </el-row>
  190. <el-row>
  191. <el-col :span="24">
  192. <el-form-item label="产品装配图" prop="drawing">
  193. <el-input v-model="hInfo.drawing" />
  194. </el-form-item>
  195. </el-col>
  196. </el-row>
  197. <el-row>
  198. <el-col :span="8">
  199. <el-form-item label="温度" prop="temperature">
  200. <el-input v-model="hInfo.temperature" />
  201. </el-form-item>
  202. </el-col>
  203. <el-col :span="8">
  204. <el-form-item label="相对湿度" prop="humidity">
  205. <el-input v-model="hInfo.humidity" />
  206. </el-form-item>
  207. </el-col>
  208. </el-row>
  209. <el-row>
  210. <el-col :span="8">
  211. <el-form-item label="烤箱温度设置" prop="temperatureSet">
  212. <el-input v-model="hInfo.temperatureSet" />
  213. </el-form-item>
  214. </el-col>
  215. <el-col :span="8">
  216. <el-form-item label="烘烤时间" prop="bakeTime">
  217. <el-input v-model="hInfo.bakeTime" />
  218. </el-form-item>
  219. </el-col>
  220. <el-col :span="8">
  221. <el-form-item label="烘箱真空度" prop="vacuum">
  222. <el-input v-model="hInfo.vacuum" />
  223. </el-form-item>
  224. </el-col>
  225. </el-row>
  226. <el-row>
  227. <el-col :span="8">
  228. <el-form-item label="氦气流量" prop="nitrogen">
  229. <el-input v-model="hInfo.nitrogen" />
  230. </el-form-item>
  231. </el-col>
  232. <el-col :span="8">
  233. <el-form-item label="氧含量" prop="oxygen">
  234. <el-input v-model="hInfo.oxygen" />
  235. </el-form-item>
  236. </el-col>
  237. <el-col :span="8">
  238. <el-form-item label="封前箱内相对湿度监控值" prop="frontHumidity">
  239. <el-input v-model="hInfo.frontHumidity" />
  240. </el-form-item>
  241. </el-col>
  242. </el-row>
  243. <el-row>
  244. <el-col :span="8">
  245. <el-form-item label="封焊功率" prop="sealPower">
  246. <el-input v-model="hInfo.sealPower" />
  247. </el-form-item>
  248. </el-col>
  249. <el-col :span="8">
  250. <el-form-item label="封焊压力" prop="sealPressure">
  251. <el-input v-model="hInfo.sealPressure" />
  252. </el-form-item>
  253. </el-col>
  254. <el-col :span="8">
  255. <el-form-item label="封焊速度" prop="sealSpeed">
  256. <el-input v-model="hInfo.sealSpeed" />
  257. </el-form-item>
  258. </el-col>
  259. </el-row>
  260. <el-row>
  261. <el-col :span="8">
  262. <el-form-item label="封装数" prop="num">
  263. <el-input v-model="hInfo.num" />
  264. </el-form-item>
  265. </el-col>
  266. <el-col :span="8">
  267. <el-form-item label="合格数" prop="passNum">
  268. <el-input v-model="hInfo.passNum" />
  269. </el-form-item>
  270. </el-col>
  271. </el-row>
  272. <el-row>
  273. <el-col :span="8">
  274. <el-form-item label="操作者" prop="operator">
  275. <el-input v-model="hInfo.operator" />
  276. </el-form-item>
  277. </el-col>
  278. <el-col :span="8">
  279. <el-form-item label="日期" prop="operatorTime">
  280. <el-date-picker
  281. value-format="YYYY-MM-DD"
  282. type="date"
  283. v-model="hInfo.operatorTime"
  284. ></el-date-picker>
  285. </el-form-item>
  286. </el-col>
  287. </el-row>
  288. </el-form>
  289. <div class="dialog-footer" align="center" style="margin-top: 10px">
  290. <el-button @click="dialog1.visible = false">取 消</el-button>
  291. <el-button type="primary" @click="handleExport1">导 出</el-button>
  292. </div>
  293. </el-dialog>
  294. <el-dialog
  295. v-model="dialog8.visible"
  296. :title="dialog8.title"
  297. width="950px"
  298. @close="dialog8.visible = false"
  299. >
  300. <el-card
  301. style="cursor: pointer; font-size: 20px"
  302. shadow="always"
  303. :key="index"
  304. @click="toShowExcel(item)"
  305. v-for="(item, index) in showProList"
  306. >{{ item.formName }}-{{ item.formCode }}({{ item.seqs }})</el-card
  307. >
  308. </el-dialog>
  309. <el-dialog
  310. v-model="excelShow"
  311. title="详情"
  312. @close="excelShow = false"
  313. width="1600"
  314. destroy-on-close
  315. >
  316. <ExcelDataBbox :data="ExDataObj" @close="excelShow = false" />
  317. </el-dialog>
  318. </div>
  319. </template>
  320. <script setup>
  321. import { ref, getCurrentInstance } from "vue";
  322. import { useCrud } from "@/hooks/userCrud";
  323. import {
  324. exportOperationRecord,
  325. exportOperationRecord1,
  326. queryFormList,
  327. addProRecord,
  328. queryProductHandover,
  329. updateHandoverList,
  330. queryHInfo,
  331. saveOpDetails,
  332. } from "@/api/process";
  333. import { useCommonStoreHook } from "@/store";
  334. import dictDataUtil from "@/common/configs/dictDataUtil";
  335. const { isShowTable, tableType } = toRefs(useCommonStoreHook());
  336. import ExcelDataBbox from "@/views/base/apply/excelDataBbox.vue";
  337. const test = () => {
  338. isShowTable.value = true;
  339. tableType.value = tableType.value == 1 ? 2 : 1;
  340. };
  341. const radio = ref(0);
  342. // 传入一个url,后面不带/
  343. const { form, data, option, search, page, toDeleteIds, Methords, Utils } =
  344. useCrud({
  345. dataListUrl: "/api/v1/proRecord/queryCompleteOpList",
  346. });
  347. const { dataList, createRow, updateRow, deleteRow, searchChange, resetChange } =
  348. Methords; //增删改查
  349. const { selectionChange, multipleDelete } = Methords; //选中和批量删除事件
  350. const { checkBtnPerm, downloadTemplate, exportData } = Utils; //按钮权限等工具
  351. const loading = ref(false);
  352. const crudRef = ref(null); //crudRef.value 获取avue-crud对象
  353. const dialog = reactive({
  354. title: "工作记录",
  355. visible: false,
  356. type: 0,
  357. });
  358. const dialog1 = reactive({
  359. title: "工作记录",
  360. visible: false,
  361. });
  362. const dialog8 = reactive({
  363. title: "表单列表",
  364. visible: false,
  365. });
  366. const showProList = ref([]);
  367. const formList = (row) => {
  368. queryFormList({
  369. ...search.value,
  370. workOrderId: row.workOrderId,
  371. operationId: row.operationId,
  372. }).then((data) => {
  373. if (data.data.length > 0) {
  374. showProList.value = data.data;
  375. dialog8.visible = true;
  376. } else {
  377. ElMessage.error("未关联到表单");
  378. }
  379. });
  380. };
  381. const excelShow = ref(false);
  382. const ExDataObj = ref({});
  383. const toShowExcel = (item) => {
  384. ExDataObj.value = item;
  385. excelShow.value = true;
  386. };
  387. const createRowSave = (row, done, loading) => {
  388. form.value.type = "1";
  389. addProRecord(form.value)
  390. .then((data) => {
  391. ElMessage.success(data.msg);
  392. form.value.startDate = "";
  393. form.value.endDate = "";
  394. done();
  395. dialog.visible = true;
  396. dialog.type = 1;
  397. itemList.value = data.data;
  398. dataList();
  399. })
  400. .catch(() => {
  401. loading();
  402. });
  403. };
  404. const itemList = ref([]);
  405. const hInfo = ref({
  406. operator: "",
  407. materialModel: "",
  408. });
  409. const clickOperationType = ref(null);
  410. const openDialog = (type, row) => {
  411. clickOperationType.value = row.operationType;
  412. row.type = 1;
  413. queryProductHandover(row).then((data) => {
  414. itemList.value = data.data;
  415. dialog.visible = true;
  416. dialog.type = type;
  417. });
  418. };
  419. const clickH = (row) => {
  420. if (null === row.detailId) {
  421. hInfo.value = JSON.parse(JSON.stringify(row));
  422. hInfo.value.operator = row.reReceiveUser;
  423. hInfo.value.operatorTime = row.reDate;
  424. hInfo.value.handoverId = row.id;
  425. hInfo.value.num = row.reNum;
  426. } else {
  427. queryHInfo(row.detailId).then((data) => {
  428. hInfo.value = data.data;
  429. });
  430. }
  431. dialog1.visible = true;
  432. };
  433. const saveDetails = () => {
  434. saveOpDetails(hInfo.value).then((data) => {
  435. ElMessage.success("操作成功");
  436. dialog1.visible = false;
  437. });
  438. };
  439. const saveItemList = () => {
  440. updateHandoverList(itemList.value).then((data) => {
  441. if (data.code === "200") {
  442. ElMessage.success("操作成功");
  443. dialog.visible = false;
  444. form.value.type = "1";
  445. search.value.type = "1";
  446. dataList();
  447. } else {
  448. ElMessage.error(data.msg);
  449. }
  450. });
  451. };
  452. // 设置表格列或者其他自定义的option
  453. option.value = Object.assign(option.value, {
  454. searchEnter: true,
  455. editBtn: false,
  456. viewBtn: false,
  457. delBtn: false,
  458. addBtn: false,
  459. selection: false,
  460. column: [
  461. {
  462. label: "开始日期",
  463. prop: "startDate",
  464. type: "date",
  465. format: "YYYY-MM-DD", //前端展示格式
  466. valueFormat: "YYYY-MM-DD", //设置后端接收的日期格式
  467. overHidden: true,
  468. search: true,
  469. },
  470. {
  471. label: "结束日期",
  472. prop: "endDate",
  473. type: "date",
  474. format: "YYYY-MM-DD", //前端展示格式
  475. valueFormat: "YYYY-MM-DD", //设置后端接收的日期格式
  476. search: true,
  477. overHidden: true,
  478. },
  479. {
  480. label: "工序类型",
  481. overHidden: true,
  482. prop: "operationType",
  483. search: true,
  484. type: "select",
  485. dicUrl: dictDataUtil.request_url + dictDataUtil.TYPE_CODE.process_type,
  486. props: {
  487. label: "dictLabel",
  488. value: "dictValue",
  489. },
  490. addDisplay: false,
  491. editDisplay: false,
  492. },
  493. {
  494. label: "完工数量",
  495. overHidden: true,
  496. prop: "completeNum",
  497. addDisplay: false,
  498. editDisplay: false,
  499. },
  500. ],
  501. });
  502. const handleExport = () => {
  503. exportOperationRecord({
  504. ...search.value,
  505. operationType: clickOperationType.value,
  506. type: 1,
  507. }).then((response) => {
  508. try {
  509. const decoder = new TextDecoder("utf-8");
  510. const jsonString = decoder.decode(response.data);
  511. const jsonObject = JSON.parse(jsonString);
  512. const { code, msg } = jsonObject;
  513. if (code != "200") {
  514. ElMessage.error(msg);
  515. }
  516. } catch (e) {
  517. downFile(response);
  518. }
  519. });
  520. };
  521. const handleExport1 = () => {
  522. exportOperationRecord1(hInfo.value).then((response) => {
  523. try {
  524. const decoder = new TextDecoder("utf-8");
  525. const jsonString = decoder.decode(response.data);
  526. const jsonObject = JSON.parse(jsonString);
  527. const { code, msg } = jsonObject;
  528. if (code != "200") {
  529. ElMessage.error(msg);
  530. }
  531. } catch (e) {
  532. downFile(response);
  533. }
  534. });
  535. };
  536. const downFile = (response) => {
  537. const fileData = response.data;
  538. const fileName = decodeURI(
  539. response.headers["content-disposition"].split(";")[1].split("=")[1]
  540. );
  541. const fileType =
  542. "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";
  543. const blob = new Blob([fileData], { type: fileType });
  544. const downloadUrl = window.URL.createObjectURL(blob);
  545. const downloadLink = document.createElement("a");
  546. downloadLink.href = downloadUrl;
  547. downloadLink.download = fileName;
  548. document.body.appendChild(downloadLink);
  549. downloadLink.click();
  550. document.body.removeChild(downloadLink);
  551. window.URL.revokeObjectURL(downloadUrl);
  552. };
  553. onMounted(() => {
  554. form.value.type = "1";
  555. search.value.type = "1";
  556. const now = new Date();
  557. const year = now.getFullYear();
  558. let month = now.getMonth() + 1; // 从0开始的月份
  559. // 当月结束日期
  560. const daysInMonth = new Date(year, now.getMonth() + 1, 0).getDate();
  561. month = month.toLocaleString().length === 1 ? "0" + month : month;
  562. search.value.startDate = year + "-" + month + "-" + "01";
  563. search.value.endDate = year + "-" + month + "-" + daysInMonth;
  564. dataList();
  565. });
  566. </script>
  567. <style>
  568. .gray-header-table .el-table__header-wrapper {
  569. background-color: #f2f2f2; /* 灰色背景 */
  570. }
  571. </style>