form.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. <template>
  2. <view class="page-container uni-column">
  3. <view class="lot-info uni-column">
  4. <view class="lot-code uni-row">
  5. <text>批次号</text>
  6. <text style="margin-left: 24rpx;">{{ dayworkItem.lotCode }}</text>
  7. </view>
  8. <view class="product-info">
  9. 产品描述: {{ dayworkItem.productDescription }}
  10. </view>
  11. <view class="product-info">
  12. 原材料厂家: {{ dayworkInfo.furnaceNoInfo.factory }}
  13. </view>
  14. <view class="product-info">
  15. 投产数量: {{ dayworkItem.prodNum }}
  16. </view>
  17. </view>
  18. <!-- 不合格信息 -->
  19. <view class="title unfit-title uni-row">
  20. <text>不合格信息</text>
  21. <view v-if="Number(dayworkItem.status) < 3" class="add-btn" @click="handleAddUnfit">添加</view>
  22. </view>
  23. <view class="unfit-container">
  24. <view class="unfit-item-container uni-column" v-for="(item, index) in unfitInfos" :key="index">
  25. <view class="title uni-row">
  26. <text>检查标准-{{ item.checkStandard }}</text>
  27. <uni-icons v-if="Number(dayworkItem.status) < 3" type="trash" size="24" color="#fc6565"
  28. @click="handleDelUnfit(index)" />
  29. </view>
  30. <!-- <view class="standard">检查标准:{{ item.checkStandard }}</view> -->
  31. <view class="result uni-row" style="display: flex;flex-direction: row;justify-content: space-between;">
  32. <!-- align-items: flex-start; -->
  33. <view class="label" style="padding-right: 16rpx;flex: 0 1 auto; min-width: 118rpx;">
  34. 检查结果</view>
  35. <input v-if="Number(dayworkItem.status) < 3" v-model="item.reason" placeholder="请输入检查结果" />
  36. <span v-else style="flex-grow: 1;">{{ item.reason }}</span>
  37. <view class="label"
  38. style="text-align: right; padding-right: 16rpx;flex: 0 1 auto; min-width: 68rpx;">数量</view>
  39. <input v-if="Number(dayworkItem.status) < 3" class="number" type="number" v-model="item.rejectNum"
  40. @blur="rejectNumberChange" />
  41. <span v-else>{{ item.rejectNum }}</span>
  42. </view>
  43. </view>
  44. </view>
  45. <!-- 咨询部分 -->
  46. <view class="title">咨询</view>
  47. <view class="consultation-container uni-column">
  48. <view class="consultation-item-container" v-for="(item, index) in consultations" :key="index">
  49. <view class="question uni-column">
  50. <view class="label uni-row">
  51. <text>问题描述</text>
  52. <text :style="{ color: showStatusColor(item.status) }">{{item.consultDepartment == 0?'技术':'品管'}} {{ showStatus(item.status) }}</text>
  53. </view>
  54. <view class="content">{{ item.content }}</view>
  55. </view>
  56. <!-- <view v-if="item.answer !== ''" class="answer"
  57. style="margin-top: 24rpx; padding-top: 24rpx; border-top: 1px dotted #aaaaaa;">
  58. <view class="label">回复</view>
  59. <view class="content">{{ item.answer }}</view>
  60. </view> -->
  61. </view>
  62. </view>
  63. <!-- 报工部分 -->
  64. <view class="daywork-container">
  65. <view class="result uni-row">
  66. <view class="label">合格量</view>
  67. <input v-if="Number(dayworkItem.status) < 3" type="number" placeholder="请输入合格量"
  68. v-model="dayworkItem.qualifiedNum" />
  69. <span v-else>{{ dayworkItem.qualifiedNum }}</span>
  70. <view class="label" style="text-align: right; padding-right: 24rpx">废品量</view>
  71. <input v-if="Number(dayworkItem.status) < 3" :disabled="true" type="number" placeholder="请输入废品量"
  72. v-model="dayworkItem.rejectNum" />
  73. <span v-else>{{ dayworkItem.rejectNum }}</span>
  74. </view>
  75. <view class="remark uni-row">
  76. <view class="label">备注</view>
  77. <textarea v-if="Number(dayworkItem.status) < 3" v-model="dayworkItem.remark" />
  78. <span v-else>{{ dayworkItem.remark }}</span>
  79. </view>
  80. <view class="btns-container uni-row">
  81. <!-- 最后一步完成不能更换载具 -->
  82. <view v-if="dayworkItem.daywork != null && dayworkItem.daywork.status != 2" class="bottom-btn left-btn "
  83. @click="handleChangeCarrier">
  84. 更换载具</view>
  85. <view v-if="checkFinishable()&&Number(dayworkItem.status) < 3" class="finished-btn"
  86. @click.stop="handleFinishDaywork">结束报工</view>
  87. <view v-if="!checkFinishable()&&Number(dayworkItem.status) < 3" class="pause-btn"
  88. @click.stop="handleUpdateDaywork">暂停</view>
  89. <view v-if="Number(dayworkItem.status) < 3" class="question-btn uni-column"
  90. @click.stop="handleAddConsultation">
  91. <uni-icons type="headphones" size="24" />
  92. <text>咨询</text>
  93. </view>
  94. </view>
  95. </view>
  96. </view>
  97. </template>
  98. <script setup>
  99. import {
  100. ref
  101. } from 'vue'
  102. import {
  103. onMounted,
  104. getCurrentInstance
  105. } from 'vue';
  106. import {
  107. getSortingDayworkItem,
  108. saveConsult,
  109. finish,
  110. update
  111. } from '@/api/business/sortDaywork.js'
  112. import {
  113. onLoad,
  114. onReady,
  115. onUnload,
  116. onShow
  117. } from '@dcloudio/uni-app'
  118. import {
  119. store
  120. } from '@/store/index.js'
  121. const isEventTriggered = ref(false); // 创建一个标志位
  122. const unfitInfos = ref([])
  123. const consultations = ref([])
  124. const dayworkInfo = ref({})
  125. // 创建一个引用来存储最后一次请求的时间戳
  126. const lastRequestTimestamp = ref(0);
  127. const dayworkItem = ref({})
  128. /***************************** 页面生命周期函数 *****************************/
  129. onShow(() => {
  130. })
  131. onMounted(() => {
  132. const instance = getCurrentInstance().proxy
  133. const eventChannel = instance.getOpenerEventChannel();
  134. eventChannel.on('acceptDataFromOpenerPage', function(data) {
  135. if (data && data.data) {
  136. dayworkInfo.value = data.data
  137. init({
  138. id: data.data.id
  139. })
  140. } else {
  141. let reqParam = {
  142. id: dayworkInfo.value.id
  143. }
  144. init(reqParam);
  145. }
  146. })
  147. })
  148. /***************************** 定义了一些方法 *****************************/
  149. const init = (data) => {
  150. console.log("dayworkInfo", dayworkInfo.value);
  151. // 获取当前报工信息
  152. getSortingDayworkItem(data).then(res => {
  153. console.log(res)
  154. if (res.code === 200) {
  155. dayworkItem.value = res.data
  156. console.log(dayworkItem.value)
  157. if (dayworkItem.value.qualifiedNum === 0 && dayworkItem.value.rejectNum === 0) {
  158. dayworkItem.value.qualifiedNum = res.data.prodNum
  159. }
  160. consultations.value = res.data.consults
  161. unfitInfos.value = res.data.rejectList
  162. } else {
  163. uni.showToast({
  164. icon: none,
  165. title: res.message
  166. })
  167. }
  168. })
  169. }
  170. const addUnfitInfo = (data) => {
  171. console.log(data)
  172. if (data.index > unfitInfos.value.length) {
  173. const info = {
  174. inspectionInstructionId: data.id,
  175. title: data.title,
  176. standard: data.standard,
  177. checkStandard: data.standard,
  178. type: data.type,
  179. reason: ''
  180. }
  181. unfitInfos.value.push(info)
  182. }
  183. }
  184. const addConsultation = (data) => {
  185. const info = {
  186. dayworkItemId: dayworkItem.value.id,
  187. content: data.content,
  188. userId: store.userInfo.userId,
  189. nickName: store.userInfo.nickName,
  190. dayworkId: dayworkItem.value.dayworkId,
  191. productionPlandetailId: dayworkItem.value.productionPlandetailId,
  192. productionPlanDetailSubDetailId: dayworkItem.value.productionPlanDetailSubDetailId,
  193. lotId: dayworkItem.value.lotId,
  194. lotCode: dayworkItem.value.lotCode,
  195. productId: dayworkItem.value.productId,
  196. productDescription: dayworkItem.value.productDescription,
  197. technologicalProcessId: dayworkItem.value.technologicalProcessId,
  198. technologicalProcessDetailId: dayworkItem.value.technologicalProcessDetailId,
  199. processId: dayworkItem.value.processId,
  200. processAlias: dayworkItem.value.process.processAlias,
  201. technicianId: dayworkItem.value.technicianId,
  202. departments : data.departments,
  203. pictures : data.pictures
  204. }
  205. saveConsult(info).then(res => {
  206. if (res.code === 200) {
  207. consultations.value = res.data
  208. console.log(consultations.value)
  209. } else {
  210. uni.showToast({
  211. icon: 'none',
  212. title: res.message
  213. })
  214. }
  215. })
  216. isEventTriggered.value = true; // 更新标志位状态
  217. consultations.value.push(info)
  218. }
  219. /***************************** 定义了一些事件 *****************************/
  220. // 添加不合格信息
  221. const handleAddUnfit = () => {
  222. // 监听事件
  223. uni.$once('addUnfitInfoEvent', (data) => {
  224. addUnfitInfo(data)
  225. })
  226. // console.log(dayworkItem.value)
  227. uni.navigateTo({
  228. url: "/pages/sorting/options",
  229. success: (res) => {
  230. // 通过eventChannel向被打开页面传送数据
  231. res.eventChannel.emit('acceptDataFromOpenerPage', {
  232. data: dayworkItem.value,
  233. query: {
  234. productId: dayworkItem.value.daywork.productId,
  235. processId: dayworkItem.value.process.id,
  236. technologyVersion: dayworkItem.value.technologicalProcessDetail
  237. .technologyVersion
  238. },
  239. index: unfitInfos.value.length
  240. })
  241. }
  242. })
  243. }
  244. // 删除不合格信息
  245. const handleDelUnfit = (index) => {
  246. let tempInfo = unfitInfos.value[index]
  247. console.log(tempInfo)
  248. uni.showModal({
  249. title: '提示',
  250. content: '确定删除该项?',
  251. success: function(res) {
  252. if (res.confirm) {
  253. dayworkItem.value.rejectNum = dayworkItem.value.rejectNum - tempInfo.rejectNum
  254. dayworkItem.value.qualifiedNum = parseInt(dayworkItem.value.qualifiedNum) + parseInt(
  255. tempInfo.rejectNum)
  256. unfitInfos.value.splice(index, 1)
  257. } else if (res.cancel) {
  258. return
  259. }
  260. }
  261. })
  262. }
  263. /* 更换载具*/
  264. function handleChangeCarrier(item) {
  265. // uni.$once('refreshQuickReport', () => {
  266. // init()
  267. // })
  268. store.dayworkInfo = null
  269. uni.navigateTo({
  270. url: "/pages/changeBox/index",
  271. success: function(res) {
  272. // 通过eventChannel向被打开页面传送数据
  273. res.eventChannel.emit('sortingFromOpenerPage', {
  274. data: dayworkItem.value
  275. })
  276. }
  277. })
  278. }
  279. // 添加不合格信息
  280. const handleAddConsultation = () => {
  281. isEventTriggered.value = false; // 更新标志位状态
  282. // 监听事件
  283. uni.$once('addConsulttationEvent', (data) => {
  284. if (!isEventTriggered.value) {
  285. // 如果事件尚未触发,则执行事件触发逻辑
  286. addConsultation(data)
  287. }
  288. })
  289. uni.navigateTo({
  290. url: "/pages/sorting/consultation",
  291. success: (res) => {
  292. // 通过eventChannel向被打开页面传送数据
  293. res.eventChannel.emit('acceptDataFromOpenerPage', {
  294. data: dayworkItem.value
  295. })
  296. }
  297. })
  298. }
  299. const checkFinishable = () => {
  300. if (consultations.value.findIndex(v => v.status === 0) >= 0) {
  301. return false
  302. } else {
  303. return true
  304. }
  305. }
  306. const showStatus = (status) => {
  307. // console.log(status)
  308. switch (status) {
  309. case 0:
  310. return '未确认'
  311. case 1:
  312. return '不合格'
  313. case 2:
  314. return '合格'
  315. default:
  316. return ''
  317. }
  318. }
  319. const showStatusColor = (status) => {
  320. // console.log(status)
  321. switch (status) {
  322. case 0:
  323. return '#fcab53'
  324. case 1:
  325. return '#fc044f'
  326. case 2:
  327. return '#1deb19'
  328. default:
  329. return ''
  330. }
  331. }
  332. const rejectNumberChange = () => {
  333. let sumReject = 0
  334. unfitInfos.value.forEach(v => {
  335. sumReject += v.rejectNum == null ? 0 : Number(v.rejectNum)
  336. })
  337. dayworkItem.value.rejectNum = sumReject
  338. dayworkItem.value.qualifiedNum = dayworkItem.value.prodNum - sumReject
  339. console.log(dayworkItem.value)
  340. }
  341. const validHandle = () => {
  342. for (let i = 0; i < unfitInfos.value.length; i++) {
  343. const e = unfitInfos.value[i]
  344. if (e.rejectNum == null || e.rejectNum == 0) {
  345. uni.showToast({
  346. icon: 'none',
  347. title: `第${i + 1}条不合格信息未输入不合格数量`
  348. })
  349. return false
  350. }
  351. }
  352. if (!dayworkItem.value.qualifiedNum) {
  353. uni.showToast({
  354. icon: 'none',
  355. title: "合格数不能为空",
  356. duration: 2000
  357. })
  358. return false;
  359. }
  360. if (dayworkItem.value.qualifiedNum < 0) {
  361. uni.showToast({
  362. icon: 'none',
  363. title: "合格数不能为负数,请检查不合格信息后提交",
  364. duration: 2000
  365. })
  366. return false;
  367. }
  368. return true
  369. // unfitInfos.value.forEach((e, i) => {
  370. // if (e.name)
  371. // })
  372. }
  373. const handleFinishDaywork = () => {
  374. if (!validHandle()) {
  375. return
  376. }
  377. const saveData = {
  378. rejectList: unfitInfos.value,
  379. consult: consultations.value,
  380. id: dayworkItem.value.id,
  381. prodNum: dayworkItem.value.prodNum,
  382. rejectNum: dayworkItem.value.rejectNum,
  383. qualifiedNum: dayworkItem.value.qualifiedNum,
  384. remark: dayworkItem.value.remark
  385. }
  386. const currentTime = Date.now();
  387. // 检查是否已经过去了 2 秒
  388. if (currentTime - lastRequestTimestamp.value < 2000) {
  389. // 如果在 2 秒 内已经点击,那么不执行
  390. uni.showToast({
  391. icon: 'none',
  392. title: `请勿重复点击`,
  393. duration: 2000
  394. })
  395. return;
  396. }
  397. finish(saveData).then(res => {
  398. if (res.code === 200) {
  399. uni.navigateBack()
  400. } else {
  401. uni.showToast({
  402. icon: 'none',
  403. title: res.message
  404. })
  405. }
  406. })
  407. }
  408. const handleUpdateDaywork = () => {
  409. if (!validHandle()) {
  410. return
  411. }
  412. const saveData = {
  413. rejectList: unfitInfos.value,
  414. consult: consultations.value,
  415. id: dayworkItem.value.id,
  416. prodNum: dayworkItem.value.prodNum,
  417. rejectNum: dayworkItem.value.rejectNum,
  418. qualifiedNum: dayworkItem.value.qualifiedNum,
  419. remark: dayworkItem.value.remark
  420. }
  421. update(saveData).then(res => {
  422. if (res.code === 200) {
  423. uni.$emit("formBack")
  424. uni.navigateBack()
  425. } else {
  426. uni.showToast({
  427. icon: 'none',
  428. title: res.message
  429. })
  430. }
  431. })
  432. }
  433. </script>
  434. <style lang="scss">
  435. .page-container {
  436. height: 100%;
  437. background-color: #ececec;
  438. font-size: 28rpx;
  439. >.title {
  440. font-weight: 700;
  441. margin: 24rpx 16rpx;
  442. }
  443. }
  444. .lot-info {
  445. margin: 32rpx 16rpx 0 16rpx;
  446. padding: 24rpx;
  447. background-color: #ffffff;
  448. border-radius: 8rpx;
  449. .lot-code {
  450. font-size: 32rpx;
  451. font-weight: 700;
  452. margin-bottom: 16rpx;
  453. }
  454. .product-info {
  455. font-size: 28rpx;
  456. color: #9f9f9f;
  457. }
  458. }
  459. .unfit-title {
  460. margin-bottom: 24rpx;
  461. justify-content: space-between;
  462. align-items: center;
  463. text {
  464. font-size: 28rpx;
  465. font-weight: 700;
  466. }
  467. .add-btn {
  468. padding: 12rpx 32rpx;
  469. background-color: #a4adb3;
  470. color: #ffffff;
  471. border-radius: 12rpx;
  472. font-size: 24rpx;
  473. }
  474. }
  475. .unfit-container {
  476. padding: 24rpx;
  477. margin: 0 16rpx;
  478. background-color: #ffffff;
  479. border-radius: 12rpx;
  480. .unfit-item-container {
  481. position: relative;
  482. >* {
  483. margin-bottom: 24rpx;
  484. }
  485. .title {
  486. font-weight: 700;
  487. justify-content: space-between;
  488. align-items: center;
  489. image {
  490. width: 40rpx;
  491. height: 40rpx;
  492. }
  493. }
  494. .standard {}
  495. .result {
  496. align-items: center;
  497. border-bottom: 1px solid #9f9f9f;
  498. padding-bottom: 32rpx;
  499. .label {
  500. flex: 1;
  501. }
  502. input {
  503. width: 280rpx;
  504. height: 56rpx;
  505. border: 1px solid #9f9f9f;
  506. font-size: 28rpx;
  507. &.number {
  508. width: 104rpx;
  509. text-align: center;
  510. }
  511. }
  512. }
  513. }
  514. .unfit-item-container:last-child {
  515. .result {
  516. border-bottom: none;
  517. padding-bottom: 0;
  518. }
  519. }
  520. }
  521. .consultation-container {
  522. margin: 0 16rpx;
  523. padding: 24rpx;
  524. background-color: #ffffff;
  525. border-radius: 8rpx;
  526. .consultation-item-container {
  527. margin-bottom: 24rpx;
  528. border-bottom: 2px solid #888888;
  529. padding-bottom: 24rpx;
  530. }
  531. .consultation-item-container:last-child {
  532. margin-bottom: 0;
  533. border-bottom: 0;
  534. padding-bottom: 0;
  535. }
  536. .question,
  537. .answer {
  538. .label {
  539. justify-content: space-between;
  540. margin-bottom: 16rpx;
  541. font-weight: 700;
  542. }
  543. .content {
  544. line-height: 40rpx;
  545. }
  546. }
  547. .answer {
  548. margin-top: 24rpx;
  549. }
  550. }
  551. .daywork-container {
  552. margin-top: 24rpx;
  553. padding: 24rpx;
  554. background-color: #ffffff;
  555. border: 1px solid #bcbcbc;
  556. .result {
  557. align-items: center;
  558. .label {
  559. width: 112rpx;
  560. }
  561. input {
  562. flex: 1;
  563. height: 56rpx;
  564. border: 1px solid #9f9f9f;
  565. font-size: 28rpx;
  566. text-align: center;
  567. }
  568. }
  569. .remark {
  570. margin-top: 24rpx;
  571. .label {
  572. width: 112rpx;
  573. }
  574. textarea {
  575. flex: 1;
  576. border: 1px solid #9f9f9f;
  577. height: 168rpx;
  578. }
  579. }
  580. .btns-container {
  581. margin-top: 24rpx;
  582. .bottom-btn {
  583. display: flex;
  584. flex: 1;
  585. height: 80rpx;
  586. background-color: #5555ff;
  587. color: #ffffff;
  588. text-align: center;
  589. justify-content: center;
  590. align-items: center;
  591. border-radius: 8rpx;
  592. margin-right: 10rpx;
  593. &.left-btn {
  594. background-color: rgba(85, 85, 255, 1.0);
  595. }
  596. &.right-btn {
  597. margin-left: 24rpx;
  598. }
  599. }
  600. .finished-btn {
  601. display: flex;
  602. flex: 1;
  603. height: 80rpx;
  604. background-color: #fc6565;
  605. color: #ffffff;
  606. text-align: center;
  607. justify-content: center;
  608. align-items: center;
  609. border-radius: 8rpx;
  610. }
  611. .pause-btn {
  612. display: flex;
  613. flex: 1;
  614. height: 80rpx;
  615. background-color: #55d90d;
  616. color: #ffffff;
  617. text-align: center;
  618. justify-content: center;
  619. align-items: center;
  620. border-radius: 8rpx;
  621. }
  622. .question-btn {
  623. width: 80rpx;
  624. align-items: flex-end;
  625. image {
  626. width: 48rpx;
  627. height: 48rpx;
  628. }
  629. text {
  630. font-size: 24rpx;
  631. }
  632. }
  633. }
  634. }
  635. </style>