perfectStoreTask.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. <template>
  2. <div class="perfectStoreTask" v-if="formData">
  3. <van-nav-bar class="navBar" left-arrow :title="formData.taskName" @click-left="onClickLeft">
  4. <template #right>
  5. <!-- <span
  6. v-if="isEdit && insert == '1'"
  7. @click="onSubmit"
  8. style="
  9. color: white;
  10. background: rgb(0, 87, 186);
  11. display: block;
  12. padding: 6px 10px;
  13. border-radius: 6px;
  14. "
  15. >保存</span
  16. > -->
  17. </template>
  18. </van-nav-bar>
  19. <div class="content" v-if="formData">
  20. <div class="container">
  21. <van-form ref="tabstoreVal">
  22. <div v-for="(item, index) in formData.collectionItemList" :key="index">
  23. <div v-if="item.answerType == 'zp'" class="formLabel z-cell">
  24. <van-cell>
  25. <template #title>
  26. <!-- <span v-if="item.isMust == 0" class="van-f-red">*</span> -->
  27. <div class="headline">
  28. <span class="headlineIcon"></span>
  29. <span class="headlineTitle">任务相关照片</span>
  30. </div>
  31. <!-- 操作说明图片和电话 -->
  32. <taskTips
  33. v-if="item.contactPhone || item.examplePhoto"
  34. :contactPhone="item.contactPhone"
  35. :examplePhoto="item.examplePhoto">
  36. </taskTips>
  37. </template>
  38. </van-cell>
  39. <template
  40. v-if="
  41. formData.taskPhotoSkuImageUrlList && formData.taskPhotoSkuImageUrlList.length
  42. ">
  43. <div
  44. class="imgBox"
  45. v-for="(urls, index) in formData.taskPhotoSkuImageUrlList"
  46. :key="index">
  47. <img
  48. :src="urls.skuImageUrl"
  49. @click="previewsImg(formData.taskPhotoSkuImageUrlList, index)" />
  50. </div>
  51. </template>
  52. <!-- <deleteUploadImg
  53. :imgs="item.fileInfoList"
  54. :storeGroupId="storeGroupId"
  55. :taskIds="taskIds"
  56. :visitsId="visitsId"
  57. :collectionItemId="item.collectionId"
  58. :putInCode="formData.putInCode"
  59. :photoIdentifyType="formData.photoIdentifyType"
  60. :pictureSource="item.pictureSource"
  61. :continuousShoot="item.continuousShoot"
  62. :insert="insert"
  63. :objectType="objectType"
  64. v-if="item.fileInfoList.length"></deleteUploadImg> -->
  65. <span style="font-size: 16px" v-else>暂未识别到产品照片</span>
  66. </div>
  67. </div>
  68. </van-form>
  69. </div>
  70. <div class="skuDeatil">
  71. <div class="headline" style="margin-top: 10px; justify-content: space-between">
  72. <div
  73. class="skuDeatilHeaderLeft"
  74. style="
  75. font-weight: 600;
  76. font-size: 16px;
  77. position: relative;
  78. display: flex;
  79. align-items: center;
  80. ">
  81. <span class="headlineIcon"></span>
  82. <span class="headlineTitle">SKU图像识别结果</span>
  83. </div>
  84. <div
  85. class="skuDeatilHeaderRight"
  86. v-if="formData.displayRewardTaskEditable"
  87. style="margin-right: 72px">
  88. <van-button plain type="primary" @click="editTable" v-if="!editTableFlag"
  89. >编辑</van-button
  90. >
  91. <van-button type="primary" @click="saveTable" v-if="editTableFlag">保存</van-button>
  92. <!-- <span style="color: #07c160" @click="editTable" v-if="!editTableFlag">编辑</span>
  93. <span style="color: red" @click="saveTable" v-if="editTableFlag">保存</span> -->
  94. </div>
  95. </div>
  96. <el-table
  97. :data="taskPhotoRecognitionResult"
  98. :span-method="taskObjectSpanMethod"
  99. border
  100. class="table-headermd1"
  101. style="width: 100%">
  102. <el-table-column label="序号" type="index" align="center" width="40"> </el-table-column>
  103. <el-table-column
  104. label="品类"
  105. prop="skuProductType"
  106. align="center"
  107. width="60"></el-table-column>
  108. <el-table-column label="SKU名称" prop="skuProductName" align="center">
  109. <template slot-scope="scope">
  110. <span class="tipTitle">{{ scope.row.skuProductName }}</span>
  111. </template>
  112. </el-table-column>
  113. <el-table-column label="排面数" prop="identifyTheNumberOfCards" align="center" width="80">
  114. <template slot-scope="scope">
  115. <span v-if="!editTableFlag" :class="{ shelfEdit: scope.row.shelfEdit == 1 }"
  116. >{{ scope.row.identifyTheNumberOfCards }}
  117. </span>
  118. <span v-else-if="!editTableFlag">
  119. {{ scope.row.identifyTheNumberOfCards }}
  120. </span>
  121. <van-field
  122. v-else
  123. :class="{ shelfEdit: scope.row.shelfEdit == 1 }"
  124. v-model="scope.row.identifyTheNumberOfCards"
  125. placeholder="请输入排面数"
  126. type="digit"
  127. :disabled="scope.row.identifyTheNumberOfCards == '0'"
  128. @input="onPositiveIntegerInput(scope.row, $event)"
  129. @blur="inputbluwl(scope.row)" />
  130. </template>
  131. </el-table-column>
  132. <el-table-column label="要求" prop="conditionIdentifyNum" align="center" width="60px">
  133. <template slot-scope="scope">
  134. <span
  135. v-if="scope.row.meetTheStandard != null"
  136. :style="{ color: scope.row.meetTheStandard == 1 ? '#07c160' : 'red' }">
  137. {{ scope.row.conditionIdentifyNum }}
  138. </span>
  139. <span v-else>{{ scope.row.conditionIdentifyNum }}</span>
  140. </template>
  141. </el-table-column>
  142. </el-table>
  143. </div>
  144. <div class="dataList" v-if="formData">
  145. <div class="headline" style="margin-top: 10px">
  146. <span class="headlineIcon"></span>
  147. <span class="headlineTitle">陈列任务要求</span>
  148. </div>
  149. <div class="dataItem">
  150. <div class="itemTop">
  151. <div class="itemIndex">
  152. <p>1、</p>
  153. </div>
  154. <div class="itemHtml" v-html="formData.displayInstructions"></div>
  155. </div>
  156. <div class="itemBottom" v-if="insert == '0'">
  157. <van-button round type="primary" v-if="formData.taskPhotoConditionPassed == 1"
  158. >通过</van-button
  159. >
  160. <van-button round type="danger" v-if="formData.taskPhotoConditionPassed == 0"
  161. >不通过</van-button
  162. >
  163. </div>
  164. </div>
  165. </div>
  166. </div>
  167. <el-dialog
  168. title="识别结果"
  169. :visible.sync="vanPopup"
  170. width="80%"
  171. :append-to-body="true"
  172. :close-on-click-modal="false"
  173. @close="vanPopup == false"
  174. custom-class="identifyResultdialog">
  175. <!-- 识别结果 -->
  176. <div class="identifyResult" v-if="taskPhotoRecognitionResult" style="padding: 0 10px">
  177. <div class="resultContent">
  178. <el-table
  179. :data="taskPhotoRecognitionResult"
  180. :span-method="taskObjectSpanMethod"
  181. border
  182. class="table-headermd1"
  183. style="width: 100%">
  184. <el-table-column label="" type="index" width="50px" align="center" />
  185. <el-table-column label="产品" prop="skuProductName" align="center" />
  186. <el-table-column
  187. label="识别排面数"
  188. prop="identifyTheNumberOfCards"
  189. width="70px"
  190. align="center">
  191. </el-table-column>
  192. <el-table-column label="要求" prop="conditionIdentifyNum" align="center" width="60px">
  193. <template slot-scope="scope">
  194. <span :style="{ color: scope.row.meetTheStandard == 1 ? '#07c160' : 'red' }">
  195. {{ scope.row.conditionIdentifyNum }}
  196. </span>
  197. </template>
  198. </el-table-column>
  199. </el-table>
  200. </div>
  201. </div>
  202. </el-dialog>
  203. </div>
  204. </template>
  205. <script>
  206. import {
  207. addCollectionAnswerBatch,
  208. getVisitsDetailPerfectStore,
  209. getVisitsDetailPerfectStoreByTaskId,
  210. updateDisplayRewardCaseSkuCount,
  211. } from '@/api/index';
  212. import taskTips from '@/views/deviceWithin/taskTips';
  213. import deleteUploadImg from '@/components/deleteUploadImgTaskPhoto';
  214. import { ImagePreview } from 'vant';
  215. export default {
  216. name: 'abnortaskPhotoTakingmalVisit',
  217. components: { taskTips, deleteUploadImg },
  218. data() {
  219. return {
  220. isEdit: true,
  221. formData: null,
  222. dataList: null,
  223. taskIds: [],
  224. visitsId: null,
  225. storeGroupId: '',
  226. objectType: '',
  227. insert: '',
  228. vanPopup: false,
  229. taskPhotoRecognitionResult: null,
  230. spanArr: [],
  231. editTableFlag: false,
  232. editCountArr: [],
  233. };
  234. },
  235. activated() {
  236. this.taskIds = this.$route.query.taskIds || [];
  237. this.visitsId = this.$route.query.visitsId || '';
  238. this.storeGroupId = this.$route.query.storeGroupId || '';
  239. this.objectType = this.$route.query.photoType || '';
  240. this.insert = this.$route.query.insert;
  241. this.formData = null;
  242. this.editCountArr = [];
  243. this.editTableFlag = false;
  244. this.getVisitsDetailFun();
  245. },
  246. methods: {
  247. taskObjectSpanMethod({ row, column, rowIndex, columnIndex }) {
  248. const cellValue = row[column.property];
  249. if (cellValue && ['conditionIdentifyNum'].includes(column.property)) {
  250. const _row = this.spanArr[rowIndex]; // 合并行数
  251. const _col = this.spanArr[rowIndex] > 0 ? 1 : 0; // 合并的列数
  252. return {
  253. rowspan: _row,
  254. colspan: _col,
  255. };
  256. }
  257. },
  258. getSpanArr(data) {
  259. if (!data) return;
  260. this.spanArr = []; // tip: 后台获取完成数据后,一定要重置spanArr=[],避免出现合并混乱!!!!!
  261. for (let i = 0; i < data.length; i++) {
  262. // 当为第一行时
  263. if (i === 0) {
  264. this.spanArr.push(1);
  265. this.pos = 0;
  266. } else {
  267. // 判断当前值是否与上一行的【名称】相等,相等则进行合并
  268. if (data[i].conditionDetailId === data[i - 1].conditionDetailId) {
  269. this.spanArr[this.pos] += 1; // 合并单元格:合并的行数 +1
  270. this.spanArr.push(0); // 0代表单元格是不需要显示, 已经被合并的单元格
  271. } else {
  272. this.spanArr.push(1); // 1代表当前这行的数据需要被显示
  273. this.pos = i;
  274. }
  275. }
  276. }
  277. },
  278. getVisitsDetailFun() {
  279. this.toastLoading(0, '加载中...', true);
  280. getVisitsDetailPerfectStoreByTaskId({
  281. visitsId: this.visitsId,
  282. taskIdList: this.$route.query.taskId,
  283. }).then((res) => {
  284. this.toastLoading().clear();
  285. if (res.code == 200 && res.data && res.data.length > 0) {
  286. this.formData = res.data[0];
  287. this.taskPhotoRecognitionResult =
  288. JSON.parse(JSON.stringify(this.formData.taskPhotoRecognitionResult)) || [];
  289. this.getSpanArr(this.taskPhotoRecognitionResult);
  290. console.log(this.formData);
  291. } else {
  292. this.formData = null;
  293. }
  294. });
  295. },
  296. openDialog(item) {
  297. this.vanPopup = true;
  298. },
  299. onSubmit() {
  300. let formData = {
  301. storeId: this.$route.query.storeId,
  302. storeCode: this.$route.query.storeCode,
  303. storeGroupId: this.$route.query.storeGroupId,
  304. visitsId: this.visitsId,
  305. taskList: this.taskIds.split(',').map((val) => Number(val)),
  306. insert: true,
  307. collectionAnswers: [],
  308. checkUnManage: 'N',
  309. deviceCode: '',
  310. putInCode: '',
  311. equipmentCode: '',
  312. };
  313. addCollectionAnswerBatch(formData).then((res) => {
  314. if (res.code == 200) {
  315. localStorage.setItem('getRequestFlage', 'true');
  316. this.$router.go(-1);
  317. }
  318. });
  319. },
  320. previewsImg(fileInfoList, index) {
  321. var arrimg = [];
  322. for (var imgi = 0; imgi < fileInfoList.length; imgi++) {
  323. arrimg.push(fileInfoList[imgi].skuImageUrl);
  324. }
  325. ImagePreview({
  326. images: arrimg,
  327. startPosition: index,
  328. });
  329. },
  330. inputbluwl(row) {
  331. let filteredResults = this.formData.taskPhotoRecognitionResult.filter(
  332. (val) => val.skuProductCode == row.skuProductCode,
  333. );
  334. if (row.identifyTheNumberOfCards != null && row.identifyTheNumberOfCards !== '') {
  335. const original = Number(filteredResults[0]?.identifyTheNumberOfCards || '0');
  336. const current = Number(row.identifyTheNumberOfCards);
  337. if (current < original) {
  338. this.$toast('排面数不能小于原始值');
  339. row.identifyTheNumberOfCards = String(original);
  340. const existingIndex = this.editCountArr.findIndex(
  341. (item) => item.skuProductCode === row.skuProductCode,
  342. );
  343. if (existingIndex >= 0) {
  344. this.editCountArr.splice(existingIndex, 1);
  345. }
  346. } else {
  347. const editCount = current - original;
  348. if (editCount > 0) {
  349. const existingIndex = this.editCountArr.findIndex(
  350. (item) => item.skuProductCode === row.skuProductCode,
  351. );
  352. if (existingIndex >= 0) {
  353. this.editCountArr[existingIndex].editCount = editCount;
  354. } else {
  355. this.editCountArr.push({
  356. taskId: row.taskId, // Long 任务id
  357. visitId: row.visitId, // Long 拜访id
  358. skuProductCode: row.skuProductCode, // String 产品code
  359. editCount,
  360. });
  361. }
  362. } else if (editCount === 0) {
  363. const existingIndex = this.editCountArr.findIndex(
  364. (item) => item.skuProductCode === row.skuProductCode,
  365. );
  366. if (existingIndex >= 0) {
  367. this.editCountArr.splice(existingIndex, 1);
  368. }
  369. }
  370. }
  371. } else {
  372. this.$toast('排面数不能为空');
  373. row.identifyTheNumberOfCards = filteredResults[0]?.identifyTheNumberOfCards;
  374. }
  375. },
  376. onPositiveIntegerInput(row, value) {
  377. if (value == null) {
  378. row.identifyTheNumberOfCards = '';
  379. return;
  380. }
  381. let sanitized = String(value).replace(/[^\d]/g, '');
  382. if (sanitized !== '') {
  383. sanitized = sanitized.replace(/^0+/, '');
  384. if (sanitized === '') {
  385. sanitized = '0';
  386. }
  387. }
  388. row.identifyTheNumberOfCards = sanitized;
  389. },
  390. editTable() {
  391. this.editTableFlag = true;
  392. },
  393. saveTable() {
  394. console.log(this.editCountArr);
  395. if (this.editCountArr.length == 0) {
  396. // this.$toast('请至少修改一项排面数');
  397. } else {
  398. updateDisplayRewardCaseSkuCount(this.editCountArr).then((res) => {
  399. if (res.code == 200) {
  400. this.$toast('修改成功');
  401. this.getVisitsDetailFun();
  402. } else {
  403. this.$toast(res.message || '修改失败');
  404. }
  405. });
  406. }
  407. this.editTableFlag = false;
  408. },
  409. onClickLeft() {
  410. this.$router.go(-1);
  411. },
  412. },
  413. };
  414. </script>
  415. <style lang="scss" scoped>
  416. .perfectStoreTask {
  417. display: flex;
  418. flex-direction: column;
  419. width: 100%;
  420. height: 100%;
  421. // overflow: hidden;
  422. .content {
  423. padding: 10px;
  424. flex: 1;
  425. width: 100%;
  426. height: 100%;
  427. display: flex;
  428. flex-direction: column;
  429. padding-bottom: 46px;
  430. .container {
  431. background: #fff;
  432. width: 100%;
  433. border-radius: 6px;
  434. // padding: 10px;
  435. padding: 0 10px 10px 0px;
  436. }
  437. .formLabel {
  438. // margin-left: 20px;
  439. // border-bottom: 1px solid #f1f1f1;
  440. }
  441. .formLabel .van-cell {
  442. padding: 10px 0;
  443. }
  444. .formLabel .van-cell::after {
  445. border: 0;
  446. }
  447. .formLabel .van-field {
  448. border: 1px solid #f1f1f1;
  449. padding: 6px;
  450. width: 100%;
  451. border-radius: 4px;
  452. overflow: hidden;
  453. }
  454. .formLabel .van-field__control {
  455. padding: 0 10px;
  456. }
  457. .formLabel .formLabeltitle {
  458. position: absolute;
  459. top: 8px;
  460. }
  461. .z-cell .van-cell__title {
  462. font-size: 16px;
  463. }
  464. .van-f-red {
  465. color: red;
  466. width: 8px;
  467. display: inline-block;
  468. line-height: 26px;
  469. }
  470. .headline {
  471. font-weight: 600;
  472. font-size: 16px;
  473. position: relative;
  474. display: flex;
  475. align-items: center;
  476. .headlineIcon {
  477. display: inline-block;
  478. position: absolute;
  479. width: 3px;
  480. height: 60%;
  481. background: #3875c6;
  482. border-radius: 5px;
  483. }
  484. .headlineTitle {
  485. display: inline-block;
  486. padding: 0px 20px;
  487. background: #eef5ff;
  488. border-radius: 0 18px 18px 0;
  489. height: 36px;
  490. line-height: 36px;
  491. }
  492. }
  493. }
  494. .dataList {
  495. width: 100%;
  496. margin-top: 10px;
  497. // overflow-y: auto;
  498. background: #fff;
  499. .dataItem {
  500. display: flex;
  501. // border-radius: 6px;
  502. flex-direction: row;
  503. margin-bottom: 10px;
  504. // padding: 10px;
  505. font-size: 16px;
  506. margin-left: 20px;
  507. border-bottom: 1px solid #e2e1e1;
  508. .itemIndex {
  509. }
  510. .itemTop {
  511. flex: 1;
  512. overflow: hidden;
  513. padding-bottom: 10px;
  514. .itemHtml {
  515. overflow-x: auto;
  516. }
  517. }
  518. .itemTop,
  519. .itemBottom {
  520. display: flex;
  521. flex-direction: row;
  522. }
  523. .itemBottom {
  524. align-items: center;
  525. width: 60px;
  526. margin-left: 5px;
  527. img {
  528. width: 100%;
  529. height: 30px;
  530. }
  531. button {
  532. width: 55px;
  533. height: 25px;
  534. padding: 0;
  535. font-size: 12px;
  536. }
  537. }
  538. }
  539. }
  540. .tableTitle {
  541. padding: 10px 0;
  542. font-size: 16px;
  543. font-weight: bold;
  544. background: #f5f5f5;
  545. margin: 15px 0;
  546. }
  547. .imgBox {
  548. width: 22%;
  549. height: 80px;
  550. position: relative;
  551. display: inline-block;
  552. border-radius: 6px;
  553. overflow: hidden;
  554. margin: 3px 1.5%;
  555. img {
  556. width: 100%;
  557. height: 100%;
  558. }
  559. }
  560. }
  561. </style>
  562. <style lang="scss">
  563. .perfectStoreTask {
  564. .van-button--danger {
  565. background-color: #ee0a24 !important;
  566. border: 1px solid #ee0a24 !important;
  567. }
  568. .table-headermd1 {
  569. .el-table__cell {
  570. height: 50px !important;
  571. .van-field {
  572. padding: 0 !important;
  573. }
  574. .van-field__control {
  575. height: 32px;
  576. text-align: center;
  577. }
  578. }
  579. }
  580. .shelfEdit {
  581. color: red;
  582. input {
  583. color: red;
  584. }
  585. }
  586. }
  587. .identifyResultdialog {
  588. width: vw(690) !important;
  589. margin-top: 1vh !important;
  590. border-radius: 8px !important;
  591. font-size: vw(32) !important;
  592. height: 70% !important;
  593. display: flex;
  594. flex-direction: column;
  595. .el-dialog__headerbtn {
  596. width: vw(44);
  597. height: vw(44);
  598. background-color: #e1e1e1;
  599. border-radius: 50%;
  600. margin-top: -3px;
  601. }
  602. .el-dialog__body {
  603. flex: 1;
  604. overflow-y: auto;
  605. }
  606. }
  607. .table-headermd1 {
  608. font-size: 14px;
  609. text-align: center;
  610. position: initial;
  611. width: 98% !important;
  612. margin: 0 auto;
  613. border-right: 0;
  614. border-radius: 8px;
  615. th {
  616. color: #000;
  617. font-weight: bold;
  618. }
  619. td {
  620. color: #000;
  621. }
  622. .el-table__cell {
  623. padding: 6px 0 !important;
  624. .cell {
  625. padding: 0;
  626. }
  627. }
  628. }
  629. .skuDeatil {
  630. width: 100%;
  631. margin-top: 10px;
  632. background: #fff;
  633. border-radius: 6px;
  634. .table-headermd1 {
  635. font-size: 14px;
  636. text-align: center;
  637. position: initial;
  638. width: 98% !important;
  639. margin: 0 auto;
  640. border-right: 0;
  641. border-radius: 8px;
  642. margin-top: 10px;
  643. th {
  644. color: #000;
  645. font-weight: bold;
  646. }
  647. td {
  648. color: #000;
  649. }
  650. .el-table__cell {
  651. padding: 6px 0 !important;
  652. .cell {
  653. padding: 0;
  654. }
  655. }
  656. }
  657. .table-headermd1 th.el-table__cell {
  658. background-color: #f5f5f5;
  659. }
  660. }
  661. .el-table::before {
  662. height: 0;
  663. }
  664. .skuDeatilHeaderRight {
  665. button {
  666. // width: 120px;
  667. height: 36px;
  668. border-radius: 18px;
  669. }
  670. .van-button--primary {
  671. background-color: #2b73cf;
  672. border-color: #2b73cf;
  673. }
  674. .van-button--primary.van-button--plain {
  675. color: #3875c6;
  676. border-color: #dcdfe6;
  677. background-color: rgba(217, 233, 255, 1);
  678. }
  679. }
  680. </style>