humiture.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. <template>
  2. <!-- 温湿度 -->
  3. <view>
  4. <u-navbar title="温湿度记录" autoBack placeholder></u-navbar>
  5. <view class="card_qiucharts" v-if="userType == 'customer'">
  6. <view class="card_echart">
  7. <qiun-data-charts type="gauge" :opts="opts" :chartData="chartData" />
  8. </view>
  9. <view class="card_echart">
  10. <qiun-data-charts type="gauge" :opts="opts1" :chartData="chartData1" />
  11. </view>
  12. </view>
  13. <view v-else>
  14. <view v-if="humitureList.length > 0">
  15. <view class="card_particulars" v-for="(item,index) in humitureList" :key="index">
  16. <view class="card_describe">
  17. <view @click="selectChangeil(item)">
  18. <x-checkbox :label="item.title" :isChecked="item.isChecked"></x-checkbox>
  19. </view>
  20. <!-- <view class="describe_title">{{item.title}}</view> -->
  21. <!-- <view class="describe_time">{{item.startTime}}</view>
  22. <view class="describe_time">{{item.endTime}}</view> -->
  23. </view>
  24. <view class="dateTime_card" style="margin: 20rpx 10rpx;">
  25. <uni-datetime-picker v-model="item.datetimeRange" type="datetimerange"
  26. @change="changeDatetime($event,item)" />
  27. </view>
  28. <view class="humiture_details" @click="foldingPanel(item)">
  29. <view class="title_details">温湿度</view>
  30. <view style="display: flex;">
  31. <view class="title_blue title_details">查看详情</view>
  32. <u-icon name="arrow-down"></u-icon>
  33. </view>
  34. </view>
  35. <view v-show="item.collapseil">
  36. <x-humiture ref="humiture" :startTime="item.datetimeRange[0]" :endTime="item.datetimeRange[1]"
  37. :taskId="item.id" :waybillNo="waybillNo" :current="item.presentNum"
  38. :probeList="item.deviceSensorList"></x-humiture>
  39. </view>
  40. </view>
  41. </view>
  42. <view style="margin-top: 30%;" v-else>
  43. <u-empty mode="data" text="当前没有温湿度记录"></u-empty>
  44. </view>
  45. </view>
  46. <view style="width: 100%;height: 230rpx;"></view>
  47. <view class="card_btn"
  48. v-if="humitureList.length > 0 && waybillData.status != 1 || waybillData.status != 2 || waybillData.status != 3 || waybillData.status != 9">
  49. <u-button style="margin-bottom: 20rpx;" type="primary"
  50. @click="humidityRecording('send')">发送温湿度记录PDF</u-button>
  51. <u-button style="margin-bottom: 20rpx;" type="success"
  52. @click="humidityRecording('print')">打印温湿度记录</u-button>
  53. </view>
  54. <view class="card_stop">
  55. <u-modal :show="show" confirmText="停止" showCancelButton :buttonReverse="true" @cancel="cancel"
  56. @confirm="confirm">
  57. <view class="slot-content" style="width: 100%;">
  58. <view>{{stoprecording}}</view>
  59. <view style="width: 100%;">
  60. <view style="padding: 10px 0px;font-size: 30rpx;color: #ff9900;">选择停止时间:</view>
  61. <uni-datetime-picker v-model="stopTime" type="datetime" @change="changeStopTime" />
  62. </view>
  63. </view>
  64. </u-modal>
  65. </view>
  66. <u-popup :show="shareShow" mode="center" round="5" closeable @close="shareShow = false">
  67. <view style="padding: 0rpx 30rpx 30rpx 30rpx;margin-top: 50rpx; width: 400rpx;">
  68. <u-button style="margin: 20rpx 0rpx;" type="success" text="发送邮箱" @click="sendingMailbox"></u-button>
  69. <u-button type="primary" text="分享微信好友" @click="shareWechatFriends"></u-button>
  70. </view>
  71. </u-popup>
  72. <u-popup :show="emailShow" mode="center" round="5" closeable @close="close">
  73. <view style="padding: 30rpx;">
  74. <view style="margin-top: 20rpx;width: 600rpx;">
  75. <view class="email_title" style="margin-bottom: 10rpx;">运单号:{{waybillNo}}</view>
  76. <view class="card_email">
  77. <span class="email_title">邮箱地址:</span>
  78. <view style="margin-top: 20rpx;">
  79. <u--input v-model="email" placeholder="请输入邮箱" border="surround"></u--input>
  80. </view>
  81. </view>
  82. </view>
  83. <view style="margin-top: 20rpx;">
  84. <u-button type="primary" :loading="sendLoading" text="发送" @click="confirmSend"></u-button>
  85. </view>
  86. </view>
  87. </u-popup>
  88. </view>
  89. </template>
  90. <script>
  91. const FileShare = uni.requireNativePlugin('life-FileShare');
  92. export default {
  93. data() {
  94. return {
  95. show: false,
  96. orderList: {},
  97. humitureList: [],
  98. userType: '',
  99. myChart: null,
  100. chartData: {},
  101. chartData1: {},
  102. opts: {
  103. color: ["#3592FE"],
  104. padding: undefined,
  105. title: {
  106. // name: "66℃",
  107. fontSize: 25,
  108. color: "#3592FE",
  109. offsetY: 0
  110. },
  111. subtitle: {
  112. name: "当前温度",
  113. fontSize: 15,
  114. color: "#1890ff",
  115. offsetY: 0
  116. },
  117. extra: {
  118. gauge: {
  119. type: "progress",
  120. width: 20,
  121. labelColor: "#666666",
  122. startAngle: 0.75,
  123. endAngle: 0.25,
  124. // startNumber: 5,
  125. // endNumber: 35,
  126. labelFormat: "",
  127. splitLine: {
  128. fixRadius: -10,
  129. splitNumber: 10,
  130. width: 15,
  131. color: "#FFFFFF",
  132. childNumber: 5,
  133. childWidth: 12
  134. },
  135. pointer: {
  136. width: 24,
  137. color: "auto"
  138. }
  139. }
  140. },
  141. },
  142. opts1: {
  143. color: ["#67C23A"],
  144. padding: 20,
  145. title: {
  146. // name: "66℃",
  147. fontSize: 25,
  148. color: "#2fc25b",
  149. offsetY: 0
  150. },
  151. subtitle: {
  152. name: "当前湿度",
  153. fontSize: 15,
  154. color: "#67C23A",
  155. offsetY: 0
  156. },
  157. extra: {
  158. gauge: {
  159. type: "progress",
  160. width: 20,
  161. labelColor: "#000000",
  162. startAngle: 0.75,
  163. endAngle: 0.25,
  164. // startNumber: 0,
  165. // endNumber: 100,
  166. labelFormat: "",
  167. splitLine: {
  168. fixRadius: -10,
  169. splitNumber: 10,
  170. width: 15,
  171. color: "#67C23A",
  172. childNumber: 5,
  173. childWidth: 12
  174. },
  175. labelOffset: 20,
  176. pointer: {
  177. width: 24,
  178. color: "auto"
  179. }
  180. }
  181. },
  182. },
  183. datetimeRange: [],
  184. waybillNo: '',
  185. waybillData: [],
  186. shareShow: false,
  187. stoprecording: '打印前需停止记录,是否继续?',
  188. stopTime: this.getDateTime(new Date()),
  189. humitureType: '',
  190. checkboxValue: [],
  191. emailShow: false,
  192. email: '',
  193. sendLoading: false,
  194. humidityFlag: false,
  195. }
  196. },
  197. onLoad(option) {
  198. this.waybillNo = option.waybillNo
  199. // 获取运单详情
  200. this.waybillDetails(option.waybillNo)
  201. },
  202. mounted() {
  203. var userInfo = this.$cache.getCache('userInfo')
  204. this.userType = userInfo.userType
  205. var orderList = this.$cache.getCache('orderDetails')
  206. this.orderList = orderList
  207. if (this.userType == 'customer') {
  208. this.getServerData();
  209. } else {
  210. this.getList()
  211. }
  212. },
  213. methods: {
  214. getList() {
  215. this.$api.get('/api/waybill-task', {
  216. waybillNo: this.waybillNo,
  217. }).then(res => {
  218. if (res.code == 200) {
  219. this.humitureList = JSON.parse(JSON.stringify(res.data.list))
  220. this.humitureList.forEach((item, index) => {
  221. this.checkboxValue.push(item.id)
  222. item.isChecked = true
  223. item.title = ''
  224. item.collapseil = false
  225. item.datetimeRange = []
  226. item.datetimeRange.push(item.startTime)
  227. if (item.endTime) {
  228. item.datetimeRange.push(item.endTime)
  229. } else {
  230. item.datetimeRange.push(this.getDateTime(new Date()))
  231. }
  232. if (item.car.id) {
  233. item.title = item.car.carNo
  234. } else if (item.warehouse.id) {
  235. item.title = item.warehouse.name
  236. } else if (item.coolerBox.id) {
  237. item.title = item.coolerBox.name
  238. }
  239. })
  240. }
  241. })
  242. },
  243. // 获取运单详情
  244. waybillDetails(waybillNo) {
  245. this.$api.get('/api/waybill/' + waybillNo).then(res => {
  246. if (res.code == 200) {
  247. this.waybillData = res.data
  248. }
  249. })
  250. },
  251. // 发送邮箱
  252. sendingMailbox() {
  253. this.shareShow = false
  254. this.emailShow = true
  255. },
  256. // 分享微信好友
  257. shareWechatFriends() {
  258. uni.showLoading({
  259. title: '获取温湿度记录中,请稍等',
  260. mask: true,
  261. });
  262. this.$api.post('/api/waybill/temperature-pdf-url', {
  263. waybillNo: this.waybillNo,
  264. waybillTaskIds: this.checkboxValue,
  265. }).then(res => {
  266. if (res.code == 200) {
  267. let arrData = res.data.split("/");
  268. var dtask = plus.downloader.createDownload(res.data, {
  269. filename: "_doc/pdf/" + arrData[3]
  270. }, function(d, status) {
  271. // 下载完成
  272. if (status == 200) {
  273. FileShare.render({
  274. type: "WX", //QQ为QQ,微信为WX,系统默认是SYSTEM,不填写默认SYSTEM
  275. filePath: plus.io.convertLocalFileSystemURL(d.filename),
  276. }, result => {
  277. uni.hideLoading()
  278. });
  279. } else {
  280. console.log("Download failed: " + status);
  281. }
  282. });
  283. dtask.start();
  284. } else {
  285. this.shareShow = false
  286. uni.$u.toast('发送失败')
  287. }
  288. uni.hideLoading()
  289. }).catch(() => {
  290. uni.hideLoading()
  291. })
  292. return
  293. },
  294. // 发送邮箱
  295. confirmSend() {
  296. if (this.email) {
  297. let flag = validateEmail(this.email)
  298. if (flag) {
  299. if (!this.sendLoading) {
  300. this.sendLoading = true
  301. let arrTo = []
  302. arrTo.push(this.email)
  303. this.$api.post('/api/waybill/send-mail', {
  304. waybillNo: this.waybillNo,
  305. humidityShow: this.humidityFlag,
  306. to: arrTo,
  307. waybillTaskIds: this.checkboxValue,
  308. }).then(res => {
  309. if (res.code == 200) {
  310. uni.$u.toast(res.msg)
  311. this.email = ''
  312. this.emailShow = false
  313. } else {
  314. this.emailShow = false
  315. uni.$u.toast('发送失败')
  316. }
  317. this.sendLoading = false
  318. }).catch(() => {
  319. this.sendLoading = false
  320. })
  321. }
  322. } else {
  323. uni.$u.toast('邮箱格式错误')
  324. }
  325. } else {
  326. uni.$u.toast('请输入邮箱')
  327. }
  328. // 如果邮箱格式正确,输出 true,否则输出 false
  329. function validateEmail(email) {
  330. const emailRegex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
  331. return emailRegex.test(email);
  332. }
  333. },
  334. // 打印温湿度记录
  335. humidityRecording(type) {
  336. this.humitureType = type
  337. if ([4, 5, 10].includes(this.waybillData.status)) {
  338. if (type == 'send') {
  339. this.stoprecording = '发送温湿度记录前需停止记录,是否继续?'
  340. } else {
  341. this.stoprecording = '打印前需停止记录,是否继续?'
  342. }
  343. this.show = true
  344. } else {
  345. if (type == 'send') {
  346. this.shareShow = true
  347. } else {
  348. if (this.waybillData.id) {
  349. this.$cache.setCache('commodity', JSON.stringify(this.waybillData))
  350. uni.navigateTo({
  351. url: '/pages/order/quantum?waybillNo=' + this.waybillData.waybillNo +
  352. '&printType=record'
  353. });
  354. } else {
  355. uni.$u.toast('暂无运单详情数据,无法打印!')
  356. }
  357. }
  358. }
  359. },
  360. cancel() {
  361. this.show = false
  362. },
  363. // 确定停止记录
  364. confirm() {
  365. if (this.stopTime) {
  366. this.$api.post('/api/waybill/stop-record', {
  367. waybillNo: this.waybillData.waybillNo,
  368. startTime: this.stopTime,
  369. }).then(res => {
  370. if (res.code == 200) {
  371. if (this.humitureType == 'send') {
  372. this.show = false
  373. this.shareShow = true
  374. } else {
  375. if (this.waybillData.id) {
  376. this.$cache.setCache('commodity', JSON.stringify(this.waybillData))
  377. uni.navigateTo({
  378. url: '/pages/order/quantum?waybillNo=' + this.waybillData
  379. .waybillNo +
  380. '&printType=record'
  381. });
  382. } else {
  383. uni.$u.toast('暂无运单详情数据,无法打印!')
  384. }
  385. }
  386. }
  387. this.show = false
  388. }).catch(() => {
  389. this.show = false
  390. })
  391. } else {
  392. uni.$u.toast('请选择停止时间')
  393. }
  394. },
  395. // 选择停止时间
  396. changeStopTime(time) {
  397. this.stopTime = time
  398. },
  399. // 折叠面板
  400. foldingPanel(value) {
  401. this.humitureList.forEach((item, index) => {
  402. if (item.id == value.id) {
  403. if (item.collapseil) {
  404. item.collapseil = false
  405. } else {
  406. this.$refs.humiture[index].getlistil(item.deviceSensorList[0].T_id)
  407. item.collapseil = true
  408. }
  409. }
  410. })
  411. this.$forceUpdate()
  412. },
  413. change(e) {
  414. if (e[0].status == 'open') {
  415. this.humitureList.forEach((item, index) => {
  416. this.$refs.humiture[index].getlistil(item.deviceSensorList[0].T_id)
  417. })
  418. }
  419. },
  420. getServerData() {
  421. this.$api.post('/api/waybill-task/newest-locus', {
  422. waybillNo: this.waybillNo,
  423. }).then((res) => {
  424. if (res.code == 200) {
  425. this.opts.title.name = res.data.T_t + '℃'
  426. this.opts.extra.gauge.startNumber = res.data.T_tl
  427. this.opts.extra.gauge.endNumber = res.data.T_tu
  428. this.opts1.title.name = res.data.T_rh + '℃'
  429. this.opts1.extra.gauge.startNumber = res.data.T_rhl
  430. this.opts1.extra.gauge.endNumber = res.data.T_rhu
  431. let arr = (res.data.T_t - res.data.T_tl) / (res.data.T_tu - res.data.T_tl)
  432. let arr1 = (res.data.T_rh - res.data.T_rhl) / (res.data.T_rhu - res.data.T_rhl)
  433. let value = {
  434. categories: [{
  435. "value": 0.2,
  436. "color": "#1890ff"
  437. }, {
  438. "value": 0.8,
  439. "color": "#2fc25b"
  440. }, {
  441. "value": 1,
  442. "color": "#f04864"
  443. }],
  444. series: [{
  445. data: arr.toFixed(1)
  446. }]
  447. };
  448. let value1 = {
  449. categories: [{
  450. "value": 0.2,
  451. "color": "#1890ff"
  452. }, {
  453. "value": 0.8,
  454. "color": "#2fc25b"
  455. }, {
  456. "value": 1,
  457. "color": "#f04864"
  458. }],
  459. series: [{
  460. data: arr1.toFixed(1)
  461. }]
  462. };
  463. this.chartData = JSON.parse(JSON.stringify(value));
  464. this.chartData1 = JSON.parse(JSON.stringify(value1));
  465. }
  466. })
  467. },
  468. // 选择某段温湿度数据
  469. selectChangeil(value) {
  470. this.humitureList.forEach((item, index) => {
  471. if (value.id == item.id) {
  472. if (value.isChecked) {
  473. item.isChecked = false
  474. } else {
  475. item.isChecked = true
  476. }
  477. }
  478. })
  479. this.selectChange(value.id)
  480. this.$forceUpdate()
  481. },
  482. // 选择打印
  483. selectChange(stingId) {
  484. const result = this.checkboxValue
  485. const index = result.indexOf(stingId)
  486. if (index > -1) {
  487. result.splice(index, 1)
  488. } else {
  489. result.push(stingId)
  490. }
  491. this.checkboxValue = result
  492. },
  493. // 时间范围选择
  494. changeDatetime(value, item) {
  495. this.humitureList.forEach((item1, index) => {
  496. if (item1.id == item.id) {
  497. setTimeout(() => {
  498. item.datetimeRange = value
  499. // this.getDatas()
  500. this.$refs.humiture[index].getlistil(item.deviceSensorList[0].T_id)
  501. }, 500)
  502. }
  503. })
  504. this.$forceUpdate()
  505. },
  506. close(){
  507. this.emailShow = false
  508. this.email = ''
  509. },
  510. getDateTime(date, addZero = true) {
  511. return `${this.getDate(date, addZero)} ${this.getTime(date, addZero)}`
  512. },
  513. getDate(date, addZero = true) {
  514. date = new Date(date)
  515. const year = date.getFullYear()
  516. const month = date.getMonth() + 1
  517. const day = date.getDate()
  518. return `${year}-${addZero ? this.addZero(month) : month}-${addZero ? this.addZero(day) : day}`
  519. },
  520. getTime(date, addZero = true) {
  521. date = new Date(date)
  522. const hour = date.getHours()
  523. const minute = date.getMinutes()
  524. const second = date.getSeconds()
  525. return this.hideSecond ?
  526. `${addZero ? this.addZero(hour) : hour}:${addZero ? this.addZero(minute) : minute}` :
  527. `${addZero ? this.addZero(hour) : hour}:${addZero ? this.addZero(minute) : minute}:${addZero ? this.addZero(second) : second}`
  528. },
  529. addZero(num) {
  530. if (num < 10) {
  531. num = `0${num}`
  532. }
  533. return num
  534. }
  535. }
  536. }
  537. </script>
  538. <style lang="scss">
  539. .card_particulars {
  540. display: flex;
  541. flex-direction: column;
  542. padding-top: 20rpx;
  543. margin: 30rpx 20rpx 20rpx 20rpx;
  544. border-radius: 20rpx;
  545. background-color: #fff;
  546. }
  547. .card_describe {
  548. padding-left: 20rpx;
  549. padding-bottom: 20rpx;
  550. border-bottom: 1rpx solid #EBEEF5;
  551. }
  552. .describe_title {
  553. font-size: 30rpx;
  554. font-weight: 600;
  555. }
  556. .describe_time {
  557. font-size: 28rpx;
  558. }
  559. .humiture_details {
  560. display: flex;
  561. justify-content: space-between;
  562. align-items: center;
  563. padding: 20rpx;
  564. }
  565. .title_blue {
  566. color: #2979ff;
  567. margin-right: 10rpx;
  568. }
  569. .title_details {
  570. font-size: 28rpx;
  571. }
  572. ::v-deep .u-collapse-item__content__text {
  573. padding: 0rpx 0rpx 30rpx 0rpx;
  574. }
  575. ::v-deep .u-line {
  576. display: none;
  577. }
  578. .card_qiucharts {
  579. display: flex;
  580. align-items: center;
  581. flex-direction: column;
  582. }
  583. .card_echart {
  584. width: 80%;
  585. height: 500rpx;
  586. }
  587. .card_echart {
  588. width: 80%;
  589. height: 500rpx;
  590. }
  591. .dateTime_card ::v-deep .icon-calendar {
  592. display: none;
  593. }
  594. .card_btn {
  595. position: fixed;
  596. left: 0;
  597. right: 0;
  598. bottom: 0;
  599. padding-left: 30rpx;
  600. padding-right: 30rpx;
  601. padding-top: 20rpx;
  602. background-color: #fff;
  603. padding-bottom: constant(safe-area-inset-bottom); //兼容 IOS<11.2
  604. padding-bottom: env(safe-area-inset-bottom); //兼容 IOS>11.2
  605. }
  606. .card_stop ::v-deep .u-modal__button-group {
  607. border-top: 1px solid #e5e5e5;
  608. }
  609. </style>