detail.vue 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119
  1. <template>
  2. <div class="page_box">
  3. <van-form ref="resumption_form">
  4. <div class="panel">
  5. <NavBar />
  6. <van-panel :title="resumptionData.taskName">
  7. <div class="tts">
  8. <van-row>
  9. <van-col span="12">
  10. <div class="total_panel">
  11. <div class="title">履职项</div>
  12. <div class="content">
  13. <span class="con_num ok">已查 {{ resumptionData.yesPointNums }}</span>
  14. <span class="con_num no">未查 {{ resumptionData.noPointNums }}</span>
  15. </div>
  16. </div>
  17. </van-col>
  18. <van-col span="12">
  19. <div class="total_panel" @click="showDetail(1)">
  20. <div class="title">NFC</div>
  21. <div class="content">
  22. <span class="con_num ok">已扫 {{ yesList.length }}</span>
  23. <span class="con_num no">未扫 {{ noList.length }}</span>
  24. </div>
  25. </div>
  26. </van-col>
  27. </van-row>
  28. </div>
  29. </van-panel>
  30. </div>
  31. <div class="progress">
  32. <van-progress :percentage="calcProgress" />
  33. </div>
  34. <!-- 检查区域 -->
  35. <div class="card">
  36. <van-panel title="巡检区域">
  37. <div style="padding: 5px">
  38. <van-row>
  39. <van-col span="8" v-for="(va, i) in areas" :key="va.areaId">
  40. <div :class="{ active: i === 0 }" class="check-area" @click="clickArea(va, i)">
  41. <div class="ysj">
  42. <van-icon name="checked" :color="areaColor.complete" v-if="va.areaStatus === '1'" />
  43. <van-icon name="warning" :color="areaColor.loading" v-if="va.areaStatus === '2'" />
  44. <van-icon name="warning" :color="areaColor.noOpen" v-if="va.areaStatus === '0'" />
  45. </div>
  46. {{ va.areaName }}
  47. </div>
  48. </van-col>
  49. </van-row>
  50. </div>
  51. </van-panel>
  52. </div>
  53. <van-action-sheet v-model="total_show">
  54. <div class="content">
  55. <van-tabs>
  56. <van-tab title="未扫描" name="b">
  57. <van-list finished-text="没有更多了" @load="onLoad">
  58. <van-cell
  59. v-for="item in sheetNoList"
  60. :key="item.nfcCode"
  61. :label="areasMap[item.areaId]"
  62. :title="item.nfcName"
  63. >
  64. <!-- <img :src="require('../../../assets/svg/NFC.svg')" class="nfc-icon"/>-->
  65. <span>{{ item.pointScan === 1 ? '必扫' : '可选' }}</span>
  66. </van-cell>
  67. </van-list>
  68. </van-tab>
  69. <van-tab title="已扫描" name="a">
  70. <van-list finished-text="没有更多了" @load="onLoad">
  71. <van-cell
  72. v-for="item in sheetYesList"
  73. :key="item.nfcCode"
  74. :label="areasMap[item.areaId]"
  75. :title="item.nfcName"
  76. >
  77. <span style="color: green">已完成</span>
  78. <div>{{item.submitTime === null ? '' : item.submitTime}}</div>
  79. </van-cell>
  80. </van-list>
  81. </van-tab>
  82. </van-tabs>
  83. </div>
  84. </van-action-sheet>
  85. <div class="card">
  86. <van-row>
  87. <van-col span="14">
  88. <van-cell @click="showDetail(0)">
  89. <template #title>
  90. <span>NFC</span>
  91. </template>
  92. <template #extra>
  93. <div>
  94. <span style="display: inline-block; color: #26850c">{{ areaYesList.length }}</span>
  95. <span style="display: inline-block; color: #0e0e0e">/</span>
  96. <span style="display: inline-block; color: #0e0e0e">{{
  97. areaNoList.length + areaYesList.length
  98. }}</span>
  99. </div>
  100. <img :src="require('../../../assets/svg/NFC.svg')" class="nfc-icon" />
  101. </template>
  102. </van-cell>
  103. </van-col>
  104. <van-col span="10">
  105. <van-cell>
  106. <div class="okAll">
  107. <!-- <van-button type="default" icon="checked" size="small" @click="changeSwitch">一键正常</van-button>-->
  108. <span v-for="(va, i) in areas" :key="va.areaId">
  109. <van-radio-group
  110. v-if="va.areaId === areaId"
  111. v-model="selectRadio[va.areaId]"
  112. v-show="resumptionData.status !== 3"
  113. @change="changeAreaSwitch(va.areaId)"
  114. >
  115. <van-radio name="1" icon-size="20px" >一键正常</van-radio>
  116. </van-radio-group>
  117. </span>
  118. </div>
  119. </van-cell>
  120. </van-col>
  121. </van-row>
  122. <van-row>
  123. <van-col span="24">
  124. <van-cell v-show="currentImgNFC.length > 0" :border="false">
  125. <div
  126. v-if="v.areaId === areaId && v.img"
  127. class="nfc-img"
  128. v-for="(v, i) in nfcs"
  129. :key="v.img"
  130. @click="preViewNFC(i)"
  131. >
  132. <img :src="imgUrl(v.img)" alt="" />
  133. <span>{{ v.nfcName }}</span>
  134. <div v-if="enable" class="cancel_icon" @click="cancelImg(v)">
  135. <van-icon name="clear" />
  136. </div>
  137. </div>
  138. </van-cell>
  139. </van-col>
  140. </van-row>
  141. <van-collapse v-model="activeNames" class="soc_resumption">
  142. <van-collapse-item
  143. v-show="areaId === item.areaId"
  144. v-for="item in checks"
  145. :name="item.itemName"
  146. :key="item.areaId"
  147. :value="item.points.length + '项'"
  148. title-style="min-width:80%"
  149. >
  150. <template #title>
  151. <pre style="font-weight: bold">{{ item.itemName }}</pre>
  152. </template>
  153. <div v-for="(point, index) in item.points" :key="index">
  154. <van-cell>
  155. <template #title>
  156. <pre>{{ point.pointName }}</pre>
  157. </template>
  158. <template #right-icon>
  159. <van-switch
  160. style="margin-left: 10px"
  161. v-model="point.resValue"
  162. v-show="point.dataStatus === 2"
  163. v-if="enable"
  164. :active-value="1"
  165. :inactive-value="0"
  166. inactive-color="#4fc08d"
  167. active-color="#ee0a24"
  168. size="18"
  169. @change="validateArea(item.areaId)"
  170. />
  171. <span v-else>
  172. <van-tag v-if="point.resValue === 1" type="warning">异常</van-tag>
  173. <van-tag v-else type="success">正常</van-tag>
  174. </span>
  175. <van-switch
  176. style="margin-left: 10px"
  177. v-model="point.dataStatus"
  178. v-show="point.dataStatus === 1"
  179. :active-value="2"
  180. :inactive-value="1"
  181. inactive-color="#fcfcfc"
  182. active-color="#ee0a24"
  183. size="18"
  184. @change="changeCurrentSwitch(item.areaId)"
  185. />
  186. </template>
  187. </van-cell>
  188. <van-cell v-show="point.pointDataSource==2||point.pointDataSource==3">
  189. <template #title>
  190. <pre class="gray-text">边缘主机自动巡查结果:{{ point.exceptionChannelNum }}个通道存在{{point.pointDataSource == 2 ?'录像丢失':'视频质量'}}问题</pre>
  191. <a @click="viewDetails(point)"
  192. :class="{ 'link-color': point.pointDataSource == 2 || point.pointDataSource == 3 }">查看详情</a>
  193. </template>
  194. </van-cell>
  195. <van-cell-group v-show="point.resValue">
  196. <van-field
  197. :rules="[
  198. { required: enable, message: '请输入情况描述' },
  199. { validator, message: '输入长度200字符以内' }
  200. ]"
  201. :required="enable"
  202. v-model="point.resRemark"
  203. :readonly="!enable"
  204. rows="1"
  205. name="resRemark"
  206. autosize
  207. autofocus="true"
  208. label="情况描述"
  209. type="textarea"
  210. :placeholder="enable ? '请输入情况描述' : ''"
  211. @input="validateArea(item.areaId)"
  212. maxlength="200"
  213. show-word-limit
  214. />
  215. <van-field
  216. :readonly="!enable"
  217. rows="1"
  218. name="uploader"
  219. autosize
  220. autofocus="true"
  221. label="上传图片"
  222. type="textarea"
  223. >
  224. <template #input>
  225. <div class="upload-box">
  226. <uploader :maxCount="5" v-if="enable" v-model="point.imgs" />
  227. <van-cell v-else>
  228. <div
  229. class="nfc-img van-hairline--surround"
  230. v-for="(v, i) in point.imgs"
  231. :key="v.imgPath"
  232. @click="clickWarnImage(point.imgs, i)"
  233. >
  234. <img :src="imgUrl(v.imgPath)" alt="" />
  235. <span>{{ v.checkName }}</span>
  236. </div>
  237. </van-cell>
  238. </div>
  239. </template>
  240. </van-field>
  241. <select-cell
  242. :required="enable"
  243. :disabled="!enable"
  244. title="整改期限"
  245. name="rectificationDeadline"
  246. v-model="point.rectificationDeadline"
  247. :data-list="dayList"
  248. @change="validateArea(item.areaId)"
  249. />
  250. </van-cell-group>
  251. </div>
  252. </van-collapse-item>
  253. </van-collapse>
  254. </div>
  255. <div class="bottomClass" v-if="enable" v-show="showButton">
  256. <van-row>
  257. <van-col span="8">
  258. <van-button type="primary" @click="clickNFC">扫描NFC</van-button>
  259. </van-col>
  260. <van-col span="8">
  261. <van-button type="default" @click="resumptionDataSave">保存</van-button>
  262. </van-col>
  263. <van-col span="8">
  264. <van-button type="info" @click="submitResumptionData">提交</van-button>
  265. </van-col>
  266. </van-row>
  267. </div>
  268. <!-- nfc弹窗 -->
  269. <nfc-popup v-if="enable" ref="NfcPopup" @checkNFC="checkNFC" @change="changeNfcImg"></nfc-popup>
  270. <!-- 主机详情弹窗 -->
  271. <DvrDetailDialog ref="dvrDetail"/>
  272. </van-form>
  273. </div>
  274. </template>
  275. <script>
  276. import { ImagePreview, Dialog } from 'vant'
  277. import NavBar from '@/components/NavBar/index.vue'
  278. import Uploader from '@/components/upload/gxuploader.vue'
  279. import SelectCell from '@/components/selectCell/index.vue'
  280. import { getDict } from '@/api/toConsult'
  281. import { saveTask, taskDetail } from '@/views/menu/resumption/api'
  282. import NfcPopup from '@/components/nfcPopup/gxmore'
  283. import DvrDetailDialog from "./dvrDetailDialog.vue"
  284. import { imgUrl } from '@/utils'
  285. import dayjs from 'dayjs'
  286. import { mapGetters } from 'vuex'
  287. export default {
  288. components: {
  289. DvrDetailDialog,
  290. SelectCell,
  291. Uploader,
  292. NavBar,
  293. NfcPopup,
  294. imgUrl,
  295. [Dialog.Component.name]: Dialog.Component
  296. },
  297. data() {
  298. return {
  299. areaColor: {
  300. // 已完成
  301. complete: '#26850c',
  302. // 未开始
  303. noOpen: '#1989fa',
  304. // 进行中
  305. loading: '#ffa500'
  306. },
  307. NFCnums: 0,
  308. yesNFCnums: 0,
  309. currentImgNFC: [],
  310. areaId: null,
  311. resumptionData: {},
  312. areas: [],
  313. areasMap: {},
  314. checks: [],
  315. nfcs: [],
  316. selectRadio: {},
  317. total_show: false,
  318. enable: false,
  319. activeNames: [],
  320. dayList: [15, 30, 90, 180],
  321. yesList: [],
  322. noList: [],
  323. areaYesList: [],
  324. areaNoList: [],
  325. sheetYesList: [],
  326. sheetNoList: [],
  327. loading: false,
  328. finished: false,
  329. selectArea: null,
  330. showButton: true,
  331. preViewImages: {
  332. images: [],
  333. startPosition: 0
  334. },
  335. timer: null,
  336. }
  337. },
  338. computed: {
  339. ...mapGetters(['id']),
  340. calcProgress() {
  341. let p = (
  342. ((this.resumptionData.yesPointNums + this.yesList.length) /
  343. (this.resumptionData.yesPointNums + this.resumptionData.noPointNums + this.yesList.length + this.noList.length)) *
  344. 100
  345. ).toFixed(2)
  346. if (window.isNaN(p)) return 0
  347. return p
  348. }
  349. },
  350. mounted() {
  351. this.getResumptionData()
  352. window.openNFCScanCallBack = this.openNFCScanCallBack
  353. },
  354. created() {
  355. getDict('rectification_deadline').then(res => {
  356. let { data } = res
  357. this.dayList = data
  358. })
  359. },
  360. methods: {
  361. showButtoFun(vel) {
  362. if (vel === 1) {
  363. this.showButton = false
  364. }
  365. if (vel === 2) {
  366. this.showButton = true
  367. }
  368. },
  369. //长度校验
  370. validator(val) {
  371. let len = val.length
  372. if (len > 200) {
  373. this.$toast.fail('问题情况输入长度不能超过200')
  374. return false
  375. } else {
  376. return true
  377. }
  378. },
  379. checkNFC() {
  380. this.useNFC()
  381. this.$toast.loading({
  382. duration: 0, // 持续展示 toast
  383. position: 'top',
  384. forbidClick: true,
  385. message: '请靠近NFC标签,进行扫描!'
  386. })
  387. let second = 15
  388. this.timer = setInterval(() => {
  389. second--
  390. if (!second) {
  391. this.$toast.clear()
  392. clearInterval(this.timer)
  393. this.$toast({
  394. type: 'fail',
  395. position: 'top',
  396. message: '未扫描到任何信息!'
  397. })
  398. }
  399. }, 1000)
  400. },
  401. openNFCScanCallBack(nfcStr) {
  402. clearInterval(this.timer)
  403. let nfcCode = ''
  404. try {
  405. let nfc = JSON.parse(nfcStr)
  406. nfcCode = nfc.content
  407. } catch (e) {
  408. nfcCode = nfcStr.content
  409. }
  410. this.checkNfcFilter(nfcCode)
  411. //保存一次数据
  412. this.resumptionDataSave();
  413. },
  414. checkNfcFilter(nfcCode) {
  415. let areaId = null
  416. let checkOk = false
  417. this.nfcs.forEach(v => {
  418. if (v.nfcCode === nfcCode) {
  419. areaId = v.areaId
  420. this.switchArea(areaId)
  421. if (v.status === 1) {
  422. // this.$toast.fail('NFC点位:' + v.nfcName + '已扫描,请勿重复扫描!');
  423. this.$toast({
  424. type: 'fail',
  425. message: 'NFC点位:' + v.nfcName + '已扫描,请勿重复扫描!',
  426. position: 'top'
  427. })
  428. throw new Error('NFC点位:' + v.nfcName + '已扫描,请勿重复扫描!')
  429. }
  430. v.status = 1
  431. v.scanMethod = 2
  432. v.submitTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
  433. v.submitBy = this.id
  434. // this.$toast.success('NFC点位:' + v.nfcName + '扫描成功!');
  435. this.$toast({
  436. type: 'success',
  437. message: 'NFC点位:' + v.nfcName + '扫描成功!',
  438. position: 'top'
  439. })
  440. checkOk = true
  441. }
  442. })
  443. this.updateNFC(1, nfcCode)
  444. if (!checkOk) {
  445. // this.$toast.fail(nfcCode + ",不在本次履职范围内!");
  446. this.$toast({
  447. type: 'fail',
  448. message: '此NFC标签,不在本次履职范围内!',
  449. position: 'top'
  450. })
  451. }
  452. this.validateArea(areaId)
  453. },
  454. switchArea(areaId) {
  455. this.areas.forEach((area, i) => {
  456. if (areaId === area.areaId) {
  457. this.activeArea(area, i)
  458. }
  459. })
  460. },
  461. useNFC() {
  462. let system = this.isAndroidOrIos()
  463. const parms = {
  464. iOS_SessionType: '0'
  465. }
  466. if (system === 1) {
  467. //android
  468. // 判断当前环境是是否存在 js桥 'sap'
  469. const hasSap = window.hasOwnProperty('sap')
  470. if (hasSap) {
  471. // 判断是否存在方法 ?preview
  472. const fun = sap.hasOwnProperty('openNFCScan')
  473. if (fun) {
  474. sap.openNFCScan(JSON.stringify(parms))
  475. }
  476. }
  477. }
  478. if (system === 2) {
  479. //ios
  480. // 判断 ios是否存在方法 preview
  481. const fun = window.webkit.messageHandlers.hasOwnProperty('openNFCScan')
  482. if (fun) {
  483. window.webkit.messageHandlers.openNFCScan.postMessage(JSON.stringify(parms))
  484. }
  485. }
  486. },
  487. isAndroidOrIos() {
  488. const urls = navigator.userAgent
  489. let isAndroid = urls.indexOf('Android') > -1 || urls.indexOf('Linux') > -1
  490. let isIos = !!urls.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
  491. if (isAndroid) {
  492. return 1
  493. }
  494. if (isIos) {
  495. return 2
  496. }
  497. },
  498. preViewNFC(i) {
  499. this.preViewImages.images = this.currentImgNFC.map(v => imgUrl(v.img))
  500. this.preViewImages.startPosition = i
  501. ImagePreview(this.preViewImages)
  502. },
  503. clickWarnImage(arr, i) {
  504. this.preViewImages.images = arr.map(v => imgUrl(v.imgPath))
  505. this.preViewImages.startPosition = i
  506. ImagePreview(this.preViewImages)
  507. },
  508. getResumptionData() {
  509. let data = {
  510. taskId: this.$route.query.id,
  511. taskDate: this.$route.query.taskDate
  512. }
  513. taskDetail(data).then(res => {
  514. let { taskId, taskName, yesPointNums, noPointNums, yesNFCNums, noNFCNums, status } = res.data
  515. this.resumptionData = {
  516. taskId,
  517. taskName,
  518. yesPointNums,
  519. noPointNums,
  520. yesNFCNums,
  521. noNFCNums,
  522. status
  523. }
  524. this.enable = this.resumptionData.status === 1 || this.resumptionData.status === 2
  525. this.checks = res.data.checks
  526. this.nfcs = res.data.nfcs
  527. this.areas = res.data.areas
  528. let obj = {}
  529. let tts = {}
  530. res.data.areas.forEach(function (v, i) {
  531. obj[v.areaId] = v.areaName
  532. tts[v.areaId] = 0
  533. })
  534. this.selectArea = tts
  535. this.areasMap = obj
  536. this.activeArea(this.areas[0], 0)
  537. this.openCollapseItems()
  538. this.updateNFC(0)
  539. this.validateAreaAll()
  540. })
  541. },
  542. openCollapseItems() {
  543. let len = this.checks.length
  544. for (let i = 0; i < len; i++) {
  545. let title = this.checks[i].itemName
  546. this.activeNames.push(title)
  547. }
  548. },
  549. changeAreaSwitch(areaId) {
  550. let num = 0
  551. let total = 0
  552. for (let i = 0; i < this.checks.length; i++) {
  553. total = total + this.checks[i].points.length
  554. for (let j = 0; j < this.checks[i].points.length; j++) {
  555. if (this.checks[i].areaId === areaId) {
  556. this.checks[i].points[j].dataStatus = 2
  557. num++
  558. } else {
  559. if (this.checks[i].points[j].dataStatus === 2) {
  560. num++
  561. }
  562. }
  563. }
  564. }
  565. this.resumptionData.yesPointNums = num
  566. this.resumptionData.noPointNums = total - num
  567. this.validateAreaAll()
  568. this.openCollapseItems()
  569. //保存一次数据
  570. this.resumptionDataSave();
  571. },
  572. changeSwitch() {
  573. let num = 0
  574. let total = 0
  575. for (let i = 0; i < this.checks.length; i++) {
  576. total = total + this.checks[i].points.length
  577. for (let j = 0; j < this.checks[i].points.length; j++) {
  578. if (this.checks[i].areaId === this.areaId) {
  579. this.checks[i].points[j].dataStatus = 2
  580. num++
  581. } else {
  582. if (this.checks[i].points[j].dataStatus === 2) {
  583. num++
  584. }
  585. }
  586. }
  587. }
  588. this.resumptionData.yesPointNums = num
  589. this.resumptionData.noPointNums = total - num
  590. this.validateAreaAll()
  591. this.openCollapseItems()
  592. },
  593. validateAreaAll() {
  594. this.areas.forEach((item, index) => {
  595. this.validateArea(item.areaId)
  596. })
  597. },
  598. changeCurrentSwitch(areaId) {
  599. this.resumptionData.yesPointNums = this.resumptionData.yesPointNums + 1
  600. this.resumptionData.noPointNums = this.resumptionData.noPointNums - 1
  601. this.validateArea(areaId)
  602. },
  603. validateArea(areaId) {
  604. //检查项数量
  605. let total = 0
  606. //完成检查项数量
  607. let yes = 0
  608. let loading = 0
  609. //完成NFC扫描的数量
  610. let nfc_num = 0
  611. let nfc_no = 0
  612. this.checks.forEach(item => {
  613. let pointList = item.points
  614. pointList.forEach(point => {
  615. if (item.areaId === areaId) {
  616. total++
  617. if (point.dataStatus === 2) {
  618. yes++
  619. if (point.resValue === 1) {
  620. if (point.resRemark === null || point.resRemark === '' || point.rectificationDeadline === null) {
  621. loading++
  622. }
  623. }
  624. }
  625. }
  626. })
  627. this.nfcs.forEach(nfc => {
  628. if (areaId === nfc.areaId) {
  629. nfc_num++
  630. if (nfc.status === 0) {
  631. nfc_no++
  632. }
  633. }
  634. })
  635. })
  636. // 0:未开始,2:进行中,1已完成
  637. let areaStatus = '0'
  638. if (total === yes && nfc_no === 0) {
  639. //检查项完成检查,nfc完成扫描,或者没有nfc扫描
  640. areaStatus = '1'
  641. if (loading > 0) {
  642. areaStatus = '2'
  643. }
  644. } else if (yes === 0 && nfc_no === nfc_num) {
  645. //检查项完成检查项为0,nfc也没动
  646. areaStatus = '0'
  647. } else {
  648. areaStatus = '2'
  649. }
  650. this.areas.forEach((item, index) => {
  651. if (item.areaId === areaId) {
  652. this.areas[index].areaStatus = areaStatus
  653. }
  654. })
  655. },
  656. clickNFC() {
  657. let arr = this.nfcs.filter(item => {
  658. return item.areaId === this.areaId && item.status === 0
  659. })
  660. if (arr.length > 0) {
  661. let nfcs = []
  662. for (const nfc of arr) {
  663. let pro = {}
  664. pro.checkName = nfc.nfcName
  665. pro.nfccdoe = nfc.nfcCode
  666. nfcs.push(pro)
  667. }
  668. this.$refs.NfcPopup.show(nfcs)
  669. } else {
  670. this.$toast.fail({
  671. message: '该区域没有需要扫描的NFC!',
  672. position: 'top'
  673. })
  674. }
  675. },
  676. cancelImg(imgItem) {
  677. this.updateNFC(2, imgItem.nfcCode, imgItem)
  678. this.validateArea(this.areaId)
  679. },
  680. changeNfcImg(imgItem) {
  681. this.updateNFC(1, imgItem.nfcCode, imgItem)
  682. this.validateArea(this.areaId);
  683. this.resumptionDataSave();
  684. },
  685. updateNFC(type, nfcCode, imgItem) {
  686. //type 1 表示新增加扫描的数据,2 表示新增未扫描的数量,0 未做任何操作
  687. //nfcCode 代表扫描和减少的nfc数据。
  688. //更新全局nfc已扫描 和未扫描
  689. this.yesList = []
  690. this.noList = []
  691. this.areaYesList = []
  692. this.areaNoList = []
  693. this.nfcs.forEach(item => {
  694. if (type === 1) {
  695. //新增扫描到的标签
  696. if (nfcCode === item.nfcCode) {
  697. item.status = 1
  698. item.submitTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
  699. item.submitBy = this.id
  700. if (imgItem) {
  701. item.scanMethod = 1
  702. //拍照NFC特殊处理
  703. item.img = imgItem.url
  704. this.currentImgNFC.push(item)
  705. } else {
  706. item.scanMethod = 0
  707. }
  708. }
  709. }
  710. if (type === 2) {
  711. //新增未扫描的标签
  712. if (nfcCode === item.nfcCode) {
  713. item.status = 0
  714. item.scanMethod = null
  715. item.submitTime = null
  716. item.submitBy = null
  717. if (item.img) {
  718. //拍照NFC特殊处理
  719. item.img = null
  720. this.currentImgNFC = this.currentImgNFC.filter(v => {
  721. return v.nfcCode !== item.nfcCode
  722. })
  723. }
  724. }
  725. }
  726. //扫描到nfc
  727. if (item.status === 1) {
  728. this.yesList.push(item)
  729. if (this.areaId === item.areaId) {
  730. this.areaYesList.push(item)
  731. }
  732. }else {
  733. this.noList.push(item)
  734. if (this.areaId === item.areaId) {
  735. this.areaNoList.push(item)
  736. }
  737. }
  738. })
  739. },
  740. showDetail(data) {
  741. if (data === 1) {
  742. this.sheetYesList = this.yesList
  743. this.sheetNoList = this.noList
  744. } else {
  745. this.sheetNoList = this.areaNoList
  746. this.sheetYesList = this.areaYesList
  747. }
  748. this.total_show = true
  749. },
  750. onLoad() {},
  751. //点击区域
  752. clickArea(area, index) {
  753. this.activeArea(area, index)
  754. },
  755. //选中区域时数据变更
  756. activeArea(area, index) {
  757. //获取当前选中区域
  758. this.areaId = area.areaId
  759. this.updateNFC(0)
  760. //设置选中样式
  761. this.$nextTick(() => {
  762. let doms = document.getElementsByClassName('check-area')
  763. Array.prototype.forEach.call(doms, item => {
  764. item.classList.remove('active')
  765. })
  766. doms[index].classList.add('active')
  767. })
  768. let nfcs = 0
  769. let current = []
  770. let yesNum = 0
  771. for (let i = 0; i < this.nfcs.length; i++) {
  772. let nfc = this.nfcs[i]
  773. let areaId = nfc.areaId
  774. if (areaId === area.areaId) {
  775. nfcs++
  776. if (nfc.status === 1) {
  777. yesNum++
  778. }
  779. if (nfc.img) {
  780. current.push(nfc)
  781. }
  782. }
  783. }
  784. this.currentImgNFC = current
  785. this.yesNFCnums = yesNum
  786. this.NFCnums = nfcs
  787. this.selectArea = area
  788. },
  789. viewDetails(point){
  790. console.log("point",point)
  791. this.$refs.dvrDetail.show(point)
  792. },
  793. //保存数据
  794. resumptionDataSave() {
  795. //组装数据
  796. let data = {}
  797. data.taskId = this.resumptionData.taskId
  798. data.checks = this.checks
  799. data.nfcs = this.nfcs
  800. data.subType = 1
  801. saveTask(data).then(res => {
  802. this.$toast('保存成功')
  803. })
  804. },
  805. submitResumptionData() {
  806. //备份数据
  807. let bakNfcs = this.nfcs
  808. let bakChecks = this.checks
  809. try {
  810. //验证数据
  811. let subNFCS = []
  812. let noNfc = this.nfcs.filter((item, index) => {
  813. if (item.status === 1) {
  814. subNFCS.push(item)
  815. }
  816. if (item.status === 0 && item.pointScan === 1) {
  817. return true
  818. }
  819. })
  820. if (noNfc.length > 0) {
  821. Dialog.alert({
  822. message: 'NFC标签还未扫描完成,请完成后提交!'
  823. })
  824. throw new Error('NFC标签还未扫描完成,请完成后提交!')
  825. return
  826. }
  827. for (let i = 0; i < this.checks.length; i++) {
  828. for (let j = 0; j < this.checks[i].points.length; j++) {
  829. let point = this.checks[i].points[j]
  830. let item = this.checks[i]
  831. if (point.resValue === 0) {
  832. this.checks[i].points[j].rectificationDeadline = null
  833. //this.checks[i].points[j].imgs = [];
  834. this.checks[i].points[j].resRemark = null
  835. }
  836. if (point.dataStatus === 1) {
  837. if (point.required === 0) {
  838. //如果不是必填内容
  839. this.checks[i].points[j].dataStatus = 2
  840. this.checks[i].points[j].resValue = 0
  841. } else {
  842. Dialog.alert({
  843. message: '存在未编辑完成履职项,无法提交!'
  844. })
  845. throw new Error('还有未完成的内容,请先完成再提交')
  846. }
  847. } else {
  848. if (point.resValue === 1) {
  849. if (!point.rectificationDeadline) {
  850. this.changeSwitch()
  851. this.areas.forEach((area, i) => {
  852. if (area.areaId === item.areaId) {
  853. this.activeArea(area, i)
  854. //切换后验证表单
  855. this.$refs.resumption_form.validate()
  856. this.$toast.fail({
  857. message: '请选择整改期限!',
  858. position: 'top'
  859. })
  860. }
  861. })
  862. throw new Error('存在未编辑完成履职项,无法提交')
  863. }
  864. if (!point.resRemark) {
  865. this.changeSwitch()
  866. this.areas.forEach((area, i) => {
  867. if (area.areaId === item.areaId) {
  868. this.activeArea(area, i)
  869. //切换后验证表单
  870. this.$refs.resumption_form.validate()
  871. this.$toast.fail({
  872. message: '请完成异常情况的信息填写!',
  873. position: 'top'
  874. })
  875. }
  876. })
  877. throw new Error('存在未编辑完成履职项,无法提交')
  878. }
  879. // if(point.imgs.length < 1){
  880. // this.changeSwitch()
  881. // this.areas.forEach((area, i) => {
  882. // if (area.areaId === item.areaId) {
  883. // this.activeArea(area, i)
  884. // //切换后验证表单
  885. // this.$refs.resumption_form.validate()
  886. // this.$toast.fail({
  887. // message: '请拍照上传异常图片!',
  888. // position: 'top'
  889. // })
  890. // throw new Error('请上传异常图片!');
  891. // }
  892. // })
  893. // }
  894. }
  895. }
  896. }
  897. }
  898. let data = {}
  899. data.taskId = this.resumptionData.taskId
  900. data.checks = this.checks
  901. data.nfcs = subNFCS
  902. data.subType = 2
  903. saveTask(data).then(res => {
  904. this.$toast('提交成功')
  905. /*this.$router.replace({
  906. path: '/resumption',
  907. name: 'resumption',
  908. params:{event:'refresh'}
  909. });*/
  910. this.$router.go(-1)
  911. })
  912. } catch (e) {
  913. this.nfcs = bakNfcs
  914. this.checks = bakChecks
  915. }
  916. }
  917. }
  918. }
  919. </script>
  920. <style lang="scss" scoped>
  921. .gray-text {
  922. color: #999;
  923. }
  924. .link-color {
  925. color: #3f51b5;
  926. }
  927. .van-progress {
  928. z-index: 999;
  929. width: 98%;
  930. left: 6px;
  931. right: 6px;
  932. }
  933. .page_box {
  934. height: calc(100vh - 60px);
  935. overflow: scroll;
  936. }
  937. .content {
  938. padding: 16px 16px 10px;
  939. }
  940. .panel {
  941. background-color: white;
  942. border-radius: 10px;
  943. border: 1px solid #ffffff;
  944. display: flex;
  945. flex-direction: column;
  946. box-shadow: 0 8px 12px #ebedf0;
  947. margin-bottom: 10px;
  948. .van-cell__title {
  949. font-weight: bold;
  950. }
  951. }
  952. .soc_resumption .van-cell__title {
  953. min-width: 80% !important;
  954. }
  955. .van-cell__title span {
  956. text-align: left;
  957. word-break: break-all;
  958. }
  959. .total_panel {
  960. text-align: center;
  961. .title {
  962. padding-top: 10px;
  963. }
  964. .content {
  965. padding-top: 10px;
  966. padding-bottom: 10px;
  967. .con_num {
  968. padding: 15px;
  969. }
  970. .ok {
  971. color: #26850c;
  972. }
  973. .no {
  974. color: #98632d;
  975. }
  976. }
  977. }
  978. .card {
  979. box-shadow: 0 10px 10px #eaeaea;
  980. }
  981. .van-popup {
  982. height: 50%;
  983. }
  984. .check-area {
  985. //background-color: #f1f1f1;
  986. text-align: center;
  987. margin: 10px;
  988. padding: 20px;
  989. //color: #aaa;
  990. border-radius: 6px;
  991. justify-content: space-between;
  992. align-items: center;
  993. box-shadow: 0 2px 6px #ddd;
  994. position: relative;
  995. height: 80px;
  996. display: flex;
  997. justify-content: center;
  998. align-items: center;
  999. .ysj {
  1000. position: absolute;
  1001. right: 5px;
  1002. top: 5px;
  1003. }
  1004. }
  1005. .active {
  1006. background-color: #bdbdbd;
  1007. color: #333;
  1008. }
  1009. .complete {
  1010. color: #fff;
  1011. background-color: #1989fa;
  1012. }
  1013. .nfc-icon {
  1014. width: 50px;
  1015. height: 50px;
  1016. margin-left: 20px;
  1017. }
  1018. .bottomClass {
  1019. position: fixed;
  1020. width: 100%;
  1021. bottom: 0;
  1022. z-index: 999;
  1023. background: #ebedf0;
  1024. text-align: center;
  1025. .van-button {
  1026. width: 95%;
  1027. margin-top: 10px;
  1028. }
  1029. }
  1030. .okAll {
  1031. background-color: #fff;
  1032. display: flex;
  1033. justify-content: center;
  1034. align-items: center;
  1035. height: 7vw;
  1036. }
  1037. .nfc-img {
  1038. display: inline-block;
  1039. width: 160px;
  1040. height: 160px;
  1041. margin: 0 10px;
  1042. position: relative;
  1043. > img {
  1044. width: 100%;
  1045. height: 100%;
  1046. border: none;
  1047. }
  1048. > span {
  1049. position: absolute;
  1050. padding: 0 10px;
  1051. bottom: 0;
  1052. left: 0;
  1053. display: block;
  1054. width: 100%;
  1055. background-color: rgba(0, 0, 0, 0.2);
  1056. color: #eaeaea;
  1057. font-size: 5px;
  1058. overflow: hidden;
  1059. text-overflow: ellipsis;
  1060. line-height: 30px;
  1061. white-space: break-spaces;
  1062. height: 30px;
  1063. }
  1064. .cancel_icon {
  1065. position: absolute;
  1066. font-size: 30px;
  1067. right: 5px;
  1068. top: 2px;
  1069. }
  1070. }
  1071. </style>