form.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. <template>
  2. <view class="page-container uni-column">
  3. <view class="carrier-info uni-column">
  4. <view class="carrier-code uni-row">
  5. <text>箱号</text>
  6. <text style="margin-left: 24rpx;">{{auxiliaryDayworkItem.carrierName}}</text>
  7. </view>
  8. <view class="info-row uni-row">
  9. <view class="label">批次号</view>
  10. <view class="value">{{ auxiliaryDayworkItem.lotCode }}</view>
  11. </view>
  12. <view class="info-row uni-row">
  13. <view class="label">产品描述</view>
  14. <view class="value">{{ auxiliaryDayworkItem.product.description }}</view>
  15. </view>
  16. <view class="info-row uni-row">
  17. <view class="label">生产工序</view>
  18. <view class="value">{{ auxiliaryDayworkItem.process.processAlias }}</view>
  19. </view>
  20. <view class="info-row uni-row">
  21. <view class="label">辅助工序</view>
  22. <view class="value">{{ auxiliaryDayworkItem.auxiliaryProcess.name }}</view>
  23. </view>
  24. </view>
  25. <!-- 废品信息 -->
  26. <view class="title unfit-title uni-row">
  27. <text>报工信息</text>
  28. </view>
  29. <view class="unfit-container">
  30. <view class="unfit-item-container uni-column" v-for="(item, index) in oldUnfitInfos" :key="index">
  31. <view class="resu uni-row">
  32. <view class="label">检查标准</view>
  33. <view class="value">{{ item.checkStandard }}</view>
  34. </view>
  35. <view class="resu uni-row">
  36. <view class="label">检查结果</view>
  37. <view class="value">{{ item.checkResult }}</view>
  38. </view>
  39. <view class="resu uni-row">
  40. <view class="label">超差范围</view>
  41. <view class="value">{{ item.exceedLimits }}</view>
  42. </view>
  43. <view class="resu uni-row">
  44. <view :class="'label'">检查量</view>
  45. <view class="number value">{{ item.examiningNum }}</view>
  46. <view :class="'label'">不良品量</view>
  47. <view class="value">{{ item.disqualificationNum }}</view>
  48. <view :class="'label'">废品量</view>
  49. <view class="value">{{ item.rejectNum }}</view>
  50. </view>
  51. </view>
  52. <view class="unfit-item-container uni-column" v-for="(item, index) in unfitInfos" :key="index">
  53. <view class="resu uni-row">
  54. <view class="label">报工人</view>
  55. <view class="value">{{ item.dayworkItem.nickName }}</view>
  56. </view>
  57. <view class="resu uni-row">
  58. <view class="label">开始时间</view>
  59. <view class="value">{{ item.dayworkItem.startTime }}</view>
  60. </view>
  61. <view class="resu uni-row">
  62. <view class="label">结束时间</view>
  63. <view class="value">{{ item.dayworkItem.endTime }}</view>
  64. </view>
  65. <view class="resu uni-row">
  66. <view :class="!editable() ? 'label' : ''">投产数量</view>
  67. <view class="number value">{{ item.prodNum }}</view>
  68. <view :class="!editable() ? 'label' : ''">合格数量</view>
  69. <view class="value">{{ item.qualificationNum }}</view>
  70. <view :class="!editable() ? 'label' : ''">废品量</view>
  71. <input v-if="editable()" class="number" type="number" @blur="rejectNumberChange"
  72. v-model="item.rejectNum" placeholder="" />
  73. <view v-else class="value">{{ item.rejectNum }}</view>
  74. </view>
  75. </view>
  76. </view>
  77. <!-- 报工部分 -->
  78. <view class="daywork-container">
  79. <view class="result uni-row">
  80. <view class="label">废品总数</view>
  81. <view class="value" style="margin-left: 10px;">{{ auxiliaryDayworkItem.rejectNum }}</view>
  82. </view>
  83. <view class="remark uni-row">
  84. <view class="label">备注</view>
  85. <textarea v-if="editable()" v-model="auxiliaryDayworkItem.remark" />
  86. <view v-else class="value">{{ auxiliaryDayworkItem.remark }}</view>
  87. </view>
  88. <view class="btns-container uni-row">
  89. <view v-if="editable()" class="finished-btn" @click="endWork">结束报工</view>
  90. <view v-if="editable()" class="pause-btn" @click="pauseWork">暂停报工</view>
  91. </view>
  92. </view>
  93. </view>
  94. </template>
  95. <script setup>
  96. import {
  97. ref,
  98. onMounted,
  99. getCurrentInstance
  100. } from 'vue'
  101. import {
  102. onLoad,
  103. onReady,
  104. onUnload,
  105. onShow
  106. } from '@dcloudio/uni-app'
  107. import {
  108. store
  109. } from '@/store/index.js'
  110. import {
  111. getAuxiliaryDayworkItemById,
  112. finishedDaywork,
  113. pauseDaywork
  114. } from '@/api/business/auxiliaryDaywork.js'
  115. const lot = ref({})
  116. const unfitInfos = ref([]) //废品信息
  117. const oldUnfitInfos = ref([])
  118. const isEventTriggered = ref(false); // 创建一个标志位
  119. // 创建一个引用来存储最后一次请求的时间戳
  120. const lastRequestTimestamp = ref(0);
  121. const consultations = ref([]) //咨询信息
  122. const auxiliaryDayworkItem = ref({
  123. remark: "",
  124. rejectNum: 0,
  125. examiningNum: 0,
  126. status: 0,
  127. product: {},
  128. process: {},
  129. auxiliaryProcess: {}
  130. })
  131. const initStatus = ref(0)
  132. const editable = () => {
  133. if (store.userInfo.permissions.some(item => item === 'business:outsourcedInspection:edit')) {
  134. return true
  135. }
  136. if (initStatus.value == 0) {
  137. return true
  138. }
  139. if (auxiliaryDayworkItem.value.firstUpdaterId == store.userInfo.userId) {
  140. return true
  141. }
  142. return false
  143. }
  144. const consul = [{
  145. value: 0,
  146. text: "待确认",
  147. type: "color: #fcab53"
  148. }, {
  149. value: 2,
  150. text: "合格",
  151. type: "color: #55ff7f"
  152. }, {
  153. value: 1,
  154. text: "不合格",
  155. type: "color: #ff0c2c"
  156. }]
  157. const range = [{
  158. value: 0,
  159. text: "待确认",
  160. type: "color: #fcab53"
  161. }, {
  162. value: 1,
  163. text: "合格",
  164. type: "color: #55ff7f"
  165. }, {
  166. value: 2,
  167. text: "不合格",
  168. type: "color: #ff0c2c"
  169. }]
  170. /***************************** 页面生命周期函数 *****************************/
  171. onMounted(() => {
  172. const instance = getCurrentInstance().proxy
  173. const eventChannel = instance.getOpenerEventChannel();
  174. eventChannel.on('outsourcedInspectionFrom', function(data) {
  175. console.log('outsourcedInspectionFrom', data)
  176. if (data && data.data) {
  177. auxiliaryDayworkItem.value.lot = data.data;
  178. }
  179. })
  180. })
  181. onShow(() => {
  182. if (store.auxiliaryDaywork != null) {
  183. uni.showLoading({
  184. title: '加载中'
  185. });
  186. auxiliaryDayworkItem.value = store.auxiliaryDaywork
  187. getAuxiliaryDayworkItemById(auxiliaryDayworkItem.value).then(res => {
  188. console.log("res", res);
  189. if (res.code == 200) {
  190. auxiliaryDayworkItem.value = res.data;
  191. initStatus.value = res.data.status
  192. unfitInfos.value = res.data.rejectList;
  193. console.log("res", res);
  194. uni.hideLoading();
  195. // getInspecion();
  196. } else {
  197. uni.showToast({
  198. icon: 'none',
  199. title: res.msg,
  200. duration: 2000
  201. })
  202. }
  203. });
  204. }
  205. })
  206. /***************************** 定义了一些方法 *****************************/
  207. //咨询文本
  208. function selectText(item) {
  209. for (var i = 0; i < consul.length; i++) {
  210. if (item.status == consul[i].value) {
  211. return consul[i].text
  212. }
  213. }
  214. }
  215. //打开电子图纸
  216. function handleDrawingMenu() {
  217. var outsourceOrderDetailId = encodeURIComponent(auxiliaryDayworkItem.value.outsourceOrderDetailId);
  218. var lotCode = encodeURIComponent(auxiliaryDayworkItem.value.lot.lotCode);
  219. // 构建查询参数字符串
  220. var queryParam = `param1=${outsourceOrderDetailId}&param2=${lotCode}`;
  221. // 使用模板字符串构建完整的URL
  222. var navigateUrl = `/pages/outsourcedDrawingMenu/index?${queryParam}`;
  223. // 导航到指定页面
  224. uni.navigateTo({
  225. url: navigateUrl
  226. });
  227. }
  228. const rejectNumberChange = () => {
  229. let sumReject = 0
  230. let sumDisqualificationNum = 0
  231. let sumExaminingNum = 0
  232. unfitInfos.value.forEach(v => {
  233. sumReject += (v.rejectNum != null ? Number(v.rejectNum) : 0)
  234. sumDisqualificationNum += (v.disqualificationNum != null ? Number(v.disqualificationNum) : 0)
  235. sumExaminingNum += (v.examiningNum != null ? Number(v.examiningNum) : 0)
  236. })
  237. auxiliaryDayworkItem.value.rejectNum = sumReject
  238. auxiliaryDayworkItem.value.disqualificationNum = sumDisqualificationNum
  239. auxiliaryDayworkItem.value.examiningNum = sumExaminingNum
  240. console.log(auxiliaryDayworkItem.value)
  241. }
  242. //查询咨询列表
  243. function getInspecion() {
  244. auxiliaryDayworkItem.value = store.processInspection
  245. selectInspecion(auxiliaryDayworkItem.value).then(res => {
  246. console.log("咨询", res);
  247. if (res.code == 200) {
  248. console.log("res", res);
  249. } else {
  250. uni.showToast({
  251. icon: 'none',
  252. title: res.msg,
  253. duration: 2000
  254. })
  255. }
  256. });
  257. }
  258. //结束报工按钮
  259. function endWork() {
  260. let unf = unfitInfos.value;
  261. for (var i = 0; i < unfitInfos.value.length; i++) {
  262. if (unf[i].rejectNum > unf[i].prodNum) {
  263. uni.showToast({
  264. icon: 'none',
  265. title: '检查量不能大于投产量'
  266. })
  267. return
  268. }
  269. }
  270. let sumReject = 0
  271. unfitInfos.value.forEach(v => {
  272. sumReject += Number(v.rejectNum)
  273. })
  274. auxiliaryDayworkItem.value.rejectNum = sumReject
  275. endSave();
  276. }
  277. // 暂停报工按钮
  278. function pauseWork() {
  279. pauseSave()
  280. }
  281. function endSave() {
  282. const currentTime = Date.now();
  283. // 检查是否已经过去了 2 秒
  284. if (currentTime - lastRequestTimestamp.value < 2000) {
  285. // 如果在 2 秒 内已经点击,那么不执行
  286. uni.showToast({
  287. icon: 'none',
  288. title: `请勿重复点击`,
  289. duration: 2000
  290. })
  291. return;
  292. }
  293. let pages = getCurrentPages();
  294. auxiliaryDayworkItem.value.rejectList = unfitInfos.value;
  295. auxiliaryDayworkItem.value.user = store.userInfo;
  296. finishedDaywork(auxiliaryDayworkItem.value).then(res => {
  297. if (res.code == 200) {
  298. let index = 0;
  299. for (let i = 0; i < pages.length; i++) {
  300. if (pages[i].$page.fullPath == "/pages/auxiliaryDaywork/index") {
  301. index = pages.length - i - 1;
  302. }
  303. }
  304. console.log("index", index);
  305. uni.navigateBack({
  306. delta: index
  307. });
  308. } else {
  309. uni.showToast({
  310. icon: 'none',
  311. title: res.msg,
  312. duration: 2000
  313. })
  314. }
  315. });
  316. }
  317. function pauseSave() {
  318. const currentTime = Date.now();
  319. // 检查是否已经过去了 2 秒
  320. if (currentTime - lastRequestTimestamp.value < 2000) {
  321. // 如果在 2 秒 内已经点击,那么不执行
  322. uni.showToast({
  323. icon: 'none',
  324. title: `请勿重复点击`,
  325. duration: 2000
  326. })
  327. return;
  328. }
  329. let pages = getCurrentPages();
  330. auxiliaryDayworkItem.value.rejectList = unfitInfos.value;
  331. auxiliaryDayworkItem.value.user = store.userInfo;
  332. pauseDaywork(auxiliaryDayworkItem.value).then(res => {
  333. if (res.code == 200) {
  334. let index = 0;
  335. for (let i = 0; i < pages.length; i++) {
  336. if (pages[i].$page.fullPath == "/pages/auxiliaryDaywork/index") {
  337. index = pages.length - i - 1;
  338. }
  339. }
  340. console.log("index", index);
  341. uni.navigateBack({
  342. delta: index
  343. });
  344. } else {
  345. uni.showToast({
  346. icon: 'none',
  347. title: res.msg,
  348. duration: 2000
  349. })
  350. }
  351. });
  352. }
  353. //咨询样式
  354. function selectType(item) {
  355. for (var i = 0; i < consul.length; i++) {
  356. if (item.status == consul[i].value) {
  357. return consul[i].type
  358. }
  359. }
  360. }
  361. const addWasteInfo = (data) => {
  362. const info = {
  363. title: data.title,
  364. checkStandard: data.standard
  365. }
  366. unfitInfos.value.push(info)
  367. }
  368. const addConsultation = (data) => {
  369. console.log(data)
  370. let info = data
  371. info.forEach(item => {
  372. item.status = 0
  373. })
  374. consultations.value = info
  375. isEventTriggered.value = true; // 更新标志位状态
  376. }
  377. /***************************** 定义了一些事件 *****************************/
  378. // 添加不合格信息
  379. const handleAddWaste = () => {
  380. let info = {}
  381. unfitInfos.value.push(info)
  382. // 监听事件,暂时不用,后续会使用
  383. // uni.$once('addWasteInfoEvent', (data) => {
  384. // addWasteInfo(data)
  385. // })
  386. // uni.navigateTo({
  387. // url: "/pages/processInspection/options"
  388. // })
  389. }
  390. // 删除不合格信息
  391. const handleDelWaste = (index) => {
  392. uni.showModal({
  393. title: '提示',
  394. content: '确定删除该项?',
  395. success: function(res) {
  396. if (res.confirm) {
  397. unfitInfos.value.splice(index, 1)
  398. rejectNumberChange()
  399. } else if (res.cancel) {
  400. return
  401. }
  402. }
  403. })
  404. }
  405. // 咨询
  406. const handleAddConsultation = () => {
  407. isEventTriggered.value = false;
  408. // 监听事件
  409. uni.$once('wasteConsultationEvent', (data) => {
  410. if (!isEventTriggered.value) {
  411. // 如果事件尚未触发,则执行事件触发逻辑
  412. addConsultation(data)
  413. }
  414. })
  415. uni.navigateTo({
  416. url: "/pages/outsourcedInspection/consultation",
  417. success: (res) => {
  418. // 通过eventChannel向被打开页面传送数据
  419. res.eventChannel.emit("outsourcedInspectionConsultation", {
  420. data: auxiliaryDayworkItem.value.lot
  421. })
  422. }
  423. })
  424. }
  425. </script>
  426. <style lang="scss">
  427. .page-container {
  428. // height: 100%;
  429. background-color: #ececec;
  430. font-size: 28rpx;
  431. >.title {
  432. font-weight: 700;
  433. margin: 24rpx 16rpx;
  434. }
  435. }
  436. .carrier-info {
  437. margin: 32rpx 16rpx 0 16rpx;
  438. padding: 24rpx;
  439. background-color: #ffffff;
  440. border-radius: 8rpx;
  441. .carrier-code {
  442. font-size: 32rpx;
  443. font-weight: 700;
  444. }
  445. .info-row {
  446. margin-top: 16rpx;
  447. color: #767676;
  448. .label {
  449. width: 160rpx;
  450. }
  451. .drawing-btn {
  452. padding: 12rpx 32rpx;
  453. background-color: #0055ff;
  454. color: #ffffff;
  455. border-radius: 12rpx;
  456. margin-left: auto;
  457. font-size: 28rpx;
  458. }
  459. .value {
  460. flex: 1;
  461. textarea {
  462. flex: 1;
  463. border: 1px solid #888888;
  464. box-sizing: border-box;
  465. padding: 16rpx;
  466. }
  467. }
  468. }
  469. }
  470. .unfit-title {
  471. margin-bottom: 24rpx;
  472. justify-content: space-between;
  473. align-items: center;
  474. text {
  475. font-size: 28rpx;
  476. font-weight: 700;
  477. }
  478. .add-btn {
  479. margin-right: 26rpx;
  480. padding: 12rpx 32rpx;
  481. background-color: #a4adb3;
  482. color: #ffffff;
  483. border-radius: 12rpx;
  484. font-size: 24rpx;
  485. }
  486. }
  487. .unfit-container {
  488. padding: 24rpx;
  489. margin: 0 16rpx;
  490. background-color: #ffffff;
  491. border-radius: 12rpx;
  492. .unfit-item-container {
  493. position: relative;
  494. >* {
  495. margin-bottom: 24rpx;
  496. }
  497. .title {
  498. font-weight: 700;
  499. justify-content: space-between;
  500. align-items: center;
  501. image {
  502. width: 40rpx;
  503. height: 40rpx;
  504. }
  505. }
  506. .standard {}
  507. .resu {
  508. width: 100%;
  509. align-items: center;
  510. input {
  511. margin-left: 20rpx;
  512. width: 200rpx;
  513. height: 56rpx;
  514. flex: 1;
  515. border: 1px solid #9f9f9f;
  516. font-size: 28rpx;
  517. }
  518. .label {
  519. width: 160rpx;
  520. }
  521. .value {
  522. flex: 1;
  523. textarea {
  524. flex: 1;
  525. border: 1px solid #888888;
  526. box-sizing: border-box;
  527. padding: 16rpx;
  528. }
  529. }
  530. }
  531. .result {
  532. border-bottom: 1px solid #9f9f9f;
  533. padding-bottom: 32rpx;
  534. align-items: center;
  535. .label {
  536. width: 160rpx;
  537. }
  538. .value {
  539. flex: 1;
  540. textarea {
  541. flex: 1;
  542. border: 1px solid #888888;
  543. box-sizing: border-box;
  544. padding: 16rpx;
  545. }
  546. }
  547. input {
  548. width: 280rpx;
  549. height: 56rpx;
  550. border: 1px solid #9f9f9f;
  551. font-size: 28rpx;
  552. &.number {
  553. width: 104rpx;
  554. text-align: center;
  555. }
  556. }
  557. }
  558. }
  559. .unfit-item-container:last-child {
  560. .result {
  561. border-bottom: none;
  562. padding-bottom: 0;
  563. }
  564. }
  565. }
  566. .consultation-container {
  567. margin: 0 16rpx;
  568. padding: 24rpx;
  569. background-color: #ffffff;
  570. border-radius: 8rpx;
  571. .consultation-item-container {
  572. margin-bottom: 24rpx;
  573. border-bottom: 2px solid #888888;
  574. padding-bottom: 24rpx;
  575. }
  576. .consultation-item-container:last-child {
  577. margin-bottom: 0;
  578. border-bottom: 0;
  579. padding-bottom: 0;
  580. }
  581. .question,
  582. .answer {
  583. .label {
  584. justify-content: space-between;
  585. margin-bottom: 16rpx;
  586. font-weight: 700;
  587. }
  588. .content {
  589. line-height: 40rpx;
  590. }
  591. }
  592. .answer {
  593. margin-top: 24rpx;
  594. }
  595. }
  596. .daywork-container {
  597. margin-top: 24rpx;
  598. padding: 24rpx;
  599. background-color: #ffffff;
  600. border: 1px solid #bcbcbc;
  601. .result {
  602. align-items: center;
  603. .label {
  604. width: 112rpx;
  605. }
  606. input {
  607. flex: 1;
  608. height: 56rpx;
  609. border: 1px solid #9f9f9f;
  610. font-size: 28rpx;
  611. text-align: center;
  612. }
  613. }
  614. .remark {
  615. margin-top: 24rpx;
  616. .label {
  617. width: 112rpx;
  618. }
  619. textarea {
  620. flex: 1;
  621. border: 1px solid #9f9f9f;
  622. height: 168rpx;
  623. }
  624. }
  625. .btns-container {
  626. margin-top: 24rpx;
  627. .finished-btn {
  628. display: flex;
  629. flex: 1;
  630. height: 80rpx;
  631. background-color: #fc6565;
  632. color: #ffffff;
  633. text-align: center;
  634. justify-content: center;
  635. align-items: center;
  636. border-radius: 8rpx;
  637. }
  638. .pause-btn {
  639. display: flex;
  640. flex: 1;
  641. height: 80rpx;
  642. background-color: #393cfc;
  643. color: #ffffff;
  644. text-align: center;
  645. justify-content: center;
  646. align-items: center;
  647. border-radius: 8rpx;
  648. }
  649. .question-btn {
  650. width: 80rpx;
  651. align-items: flex-end;
  652. image {
  653. width: 48rpx;
  654. height: 48rpx;
  655. }
  656. text {
  657. font-size: 24rpx;
  658. }
  659. }
  660. }
  661. }
  662. </style>