index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. <template>
  2. <scroll-view scroll-y>
  3. <view class="grayBackgroundColor">
  4. <view>
  5. <el-calendar
  6. id="calendar"
  7. ref="calendar"
  8. v-model="currentDatevalue"
  9. @touchstart="touchStart"
  10. @touchend="touchEnd"
  11. >
  12. <template #header="{ date }">
  13. <view style="display: flex; width: 100%">
  14. <view>{{ date }}</view>
  15. <view style="margin: auto"></view>
  16. <view style="display: flex">
  17. <view style="margin: 0px 10px">
  18. <span style="margin-right: 5px">合格</span>
  19. <span style="color: #00cdac">{{
  20. JSON.stringify(currentDateList) === "{}"
  21. ? 0
  22. : currentDateList.patrolledCount
  23. }}</span>
  24. </view>
  25. <view class="margin-left-xs">
  26. <span style="margin-right: 5px">漏检</span>
  27. <span style="color: #f07d28">{{
  28. JSON.stringify(currentDateList) === "{}"
  29. ? 0
  30. : currentDateList.undetectedCount
  31. }}</span>
  32. </view>
  33. </view>
  34. </view>
  35. </template>
  36. <template #dateCell="{ data }">
  37. <view @click="calendarClick(data)">
  38. <p :class="data.isSelected ? 'is-selected' : ''">
  39. {{ data.day.split("-").slice(2).join("-") }}
  40. </p>
  41. <view v-if="data.isSelected" class="filter"></view>
  42. </view>
  43. </template>
  44. </el-calendar>
  45. </view>
  46. <view>
  47. <view class="padding-sm" style="display: flex; margin: 10px">
  48. <el-radio-group
  49. v-model="tabPosition"
  50. style="margin: auto"
  51. @change="tabPositionChange()"
  52. >
  53. <el-radio-button label="task">巡检任务</el-radio-button>
  54. <el-radio-button label="record">巡检记录</el-radio-button>
  55. </el-radio-group>
  56. </view>
  57. <view>
  58. <el-timeline id="planTimeline" v-if="activities.length > 0">
  59. <view>
  60. <el-button
  61. type="primary"
  62. style="margin: 0px -7.5px"
  63. link
  64. @click="activitiesSortClick()"
  65. >
  66. 排序
  67. </el-button>
  68. </view>
  69. <view v-if="tabPosition == 'task'">
  70. <el-timeline-item
  71. v-for="(activity, index) in activities"
  72. :key="index"
  73. :icon="activity.icon"
  74. :type="activity.type"
  75. :color="activity.color"
  76. :size="activity.size"
  77. :hollow="activity.hollow"
  78. >
  79. <view style="display: flex">
  80. <view style="font-size: 15px"> {{ activity.planName }}</view>
  81. <view style="margin: auto"> </view>
  82. <view style="color: #b5b5b5"> {{ activity.timestamp }}</view>
  83. </view>
  84. <view
  85. style="
  86. margin-top: 15px;
  87. padding: 15px;
  88. background-color: #fff;
  89. border-radius: 10px;
  90. "
  91. >
  92. <view style="display: flex" v-if="activity.planStatus == 2">
  93. <view>
  94. <view>巡检任务结束</view>
  95. <br />
  96. <view>
  97. <el-button
  98. type="primary"
  99. link
  100. style="padding: 0"
  101. @click="reportClick(activity.id)"
  102. >
  103. 点击查看
  104. </el-button>
  105. </view>
  106. </view>
  107. <view style="margin: auto"></view>
  108. <view>
  109. <el-progress
  110. type="circle"
  111. :percentage="activity.completion"
  112. :width="50"
  113. />
  114. </view>
  115. </view>
  116. <view style="display: flex" v-if="activity.planStatus == 1">
  117. <view>
  118. <view
  119. >巡检任务执行中,还需完成
  120. {{ activity.undetectedSiteCount }}
  121. </view>
  122. <br />
  123. <view>
  124. <el-button
  125. type="primary"
  126. link
  127. style="padding: 0"
  128. @click="reportClick(activity.id)"
  129. >
  130. 点击巡检
  131. </el-button>
  132. </view>
  133. </view>
  134. <view style="margin: auto"></view>
  135. <view>
  136. <el-progress
  137. type="circle"
  138. :percentage="activity.completion"
  139. :width="50"
  140. />
  141. </view>
  142. </view>
  143. <view style="display: flex" v-if="activity.planStatus == 3">
  144. <view>
  145. <view>巡检任务结束</view>
  146. <br />
  147. <view>
  148. <span style="margin-right: 20px">
  149. 合格:
  150. <span style="color: #00cdac">
  151. {{ activity.patrolledSiteCount }}
  152. </span>
  153. </span>
  154. <span>
  155. 漏检:
  156. <span style="color: #f07d28">
  157. {{ activity.undetectedSiteCount }}
  158. </span>
  159. </span>
  160. </view>
  161. </view>
  162. <view style="margin: auto"></view>
  163. <view>
  164. <el-progress
  165. type="circle"
  166. :percentage="activity.completion"
  167. :width="50"
  168. />
  169. </view>
  170. </view>
  171. </view>
  172. </el-timeline-item>
  173. </view>
  174. <view v-if="tabPosition == 'record'">
  175. <el-timeline-item
  176. v-for="(activity, index) in activities"
  177. :key="index"
  178. :icon="activity.icon"
  179. :type="activity.type"
  180. :color="activity.color"
  181. :size="activity.size"
  182. :hollow="activity.hollow"
  183. >
  184. <view style="display: flex">
  185. <view style="font-size: 15px"> {{ activity.siteName }}</view>
  186. <view style="margin: auto"> </view>
  187. <view style="color: #b5b5b5"> {{ activity.createTime }}</view>
  188. </view>
  189. <view
  190. style="
  191. margin-top: 15px;
  192. padding: 15px;
  193. background-color: #fff;
  194. border-radius: 10px;
  195. "
  196. >
  197. <view>已检查{{ activity.contentCount }}项内容</view>
  198. <view
  199. :style="{
  200. color:
  201. activity.siteStatus == 0
  202. ? '#f07d28'
  203. : activity.siteStatus == 1
  204. ? '#00cdac'
  205. : '',
  206. textAlign: 'right',
  207. }"
  208. >
  209. {{
  210. activity.siteStatus == 0
  211. ? "未定位"
  212. : activity.siteStatus == 1
  213. ? "已定位"
  214. : ""
  215. }}
  216. </view>
  217. <view>
  218. <el-button type="primary" link style="padding: 0">
  219. 点击查看
  220. </el-button>
  221. </view>
  222. </view>
  223. </el-timeline-item>
  224. </view>
  225. </el-timeline>
  226. <view
  227. id="planTimeline"
  228. style="text-align: center; color: #bdbdbd; font-size: 14px"
  229. v-else
  230. >
  231. 暂无数据
  232. </view>
  233. </view>
  234. </view>
  235. </view>
  236. <img
  237. src="@/static/inspection/plan-scan.png"
  238. alt=""
  239. style="position: fixed; right: 0; bottom: 50px"
  240. @click="scanClick()"
  241. />
  242. <drawer
  243. v-if="scanArray.length > 0"
  244. :scanArray="scanArray"
  245. :scanBool="scanBool"
  246. @scanClose="scanClose"
  247. ></drawer>
  248. </scroll-view>
  249. </template>
  250. <script setup>
  251. import drawer from "./components/drawer.vue";
  252. import { onLoad, onShow } from "@dcloudio/uni-app";
  253. import { ref, onMounted, inject, shallowRef } from "vue";
  254. const myRequest = inject("$myRequest");
  255. import useXunJianStore from "@/store/modules/xunJian";
  256. const settingsStore = useXunJianStore(); //全局变量值Store
  257. import { MoreFilled } from "@element-plus/icons-vue";
  258. function reportClick(id) {
  259. settingsStore.planSonId1 = id;
  260. uni.navigateTo({
  261. url: "/pages/xunJian/plan/components/report",
  262. });
  263. }
  264. /**
  265. * @扫一扫
  266. * @点击事件
  267. */
  268. const scanArray = ref([]);
  269. const scanBool = ref(false);
  270. async function scanClick() {
  271. uni.scanCode({
  272. success: (res) => {
  273. console.log("扫码成功", res);
  274. },
  275. fail: (err) => {
  276. console.log("扫码失败", err);
  277. },
  278. complete: () => {
  279. console.log("扫码结束");
  280. },
  281. });
  282. settingsStore.inspectionStatus = 1;
  283. let res = await myRequest({
  284. url: "/service-fire/appPatrolInspection/planList",
  285. header: {
  286. "Content-Type": "application/json;charset=utf-8",
  287. },
  288. method: "GET",
  289. data: {
  290. siteNubmber: "0000000000",
  291. },
  292. });
  293. if (res.data.status == "SUCCESS") {
  294. if (res.data.data.length > 0) {
  295. scanArray.value = res.data.data;
  296. scanBool.value = true;
  297. } else {
  298. uni.showToast({
  299. title: "此点位下暂无数据,请切换点位重试!",
  300. icon: "none",
  301. });
  302. }
  303. } else {
  304. }
  305. }
  306. /**
  307. * @抽屉emit
  308. * @关闭事件
  309. */
  310. function scanClose(flag) {
  311. scanBool.value = flag;
  312. }
  313. /**
  314. * @巡检任务
  315. * @巡检记录
  316. * @api接口请求
  317. */
  318. const activities = ref([]);
  319. async function activitiesApi() {
  320. activities.value = [];
  321. if (tabPosition.value == "task") {
  322. let res = await myRequest({
  323. url: "/service-fire/appPatrolInspection/patrolInspectionPlan",
  324. header: {
  325. "Content-Type": "application/json;charset=utf-8",
  326. },
  327. method: "GET",
  328. data: {
  329. currentDate: currentDate.value,
  330. sort: activitiesSort.value,
  331. },
  332. });
  333. if (res.data.status == "SUCCESS") {
  334. res.data.data.forEach((el) => {
  335. activities.value.push({
  336. id: el.id,
  337. planName: el.planName,
  338. timestamp:
  339. (el.startTime == null || el.startTime == ""
  340. ? ""
  341. : el.startTime.split(":")[0] +
  342. ":" +
  343. el.startTime.split(":")[1] +
  344. "~") +
  345. (el.endTime == null || el.endTime == ""
  346. ? ""
  347. : el.endTime.split(":")[0] + ":" + el.endTime.split(":")[1]),
  348. planStatus: el.planStatus,
  349. completion: el.completion,
  350. patrolledSiteCount: el.patrolledSiteCount,
  351. undetectedSiteCount: el.undetectedSiteCount,
  352. });
  353. });
  354. } else {
  355. }
  356. } else if (tabPosition.value == "record") {
  357. let res = await myRequest({
  358. url: "/service-fire/appPatrolInspection/recordList",
  359. header: {
  360. "Content-Type": "application/json;charset=utf-8",
  361. },
  362. method: "GET",
  363. data: {
  364. currentDate: currentDate.value,
  365. sort: activitiesSort.value,
  366. },
  367. });
  368. if (res.data.status == "SUCCESS") {
  369. res.data.data.forEach((el) => {
  370. activities.value.push({
  371. siteName: el.siteName,
  372. contentCount: el.contentCount,
  373. createTime:
  374. el.createTime.split("T")[0] + " " + el.createTime.split("T")[1],
  375. siteStatus: el.siteStatus,
  376. });
  377. });
  378. } else {
  379. }
  380. }
  381. activities.value.forEach((el) => {
  382. el.size = "large";
  383. el.type = "primary";
  384. el.icon = shallowRef(MoreFilled);
  385. });
  386. }
  387. /**
  388. * @统计
  389. * @api接口请求
  390. */
  391. const currentDate = ref(
  392. settingsStore.getDate().year +
  393. "-" +
  394. settingsStore.getDate().month +
  395. "-" +
  396. settingsStore.getDate().dates
  397. ); //统计时间数据存储
  398. const currentDatevalue = ref(new Date());
  399. const currentDateList = ref({}); //统计list数据存储
  400. async function currentApi() {
  401. const res = await myRequest({
  402. url: "/service-fire/appPatrolInspection/appPlanStatistics",
  403. header: {
  404. "Content-Type": "application/json;charset=utf-8",
  405. },
  406. method: "GET",
  407. data: {
  408. currentDate: currentDate.value,
  409. },
  410. });
  411. if (res.data.status == "SUCCESS") {
  412. currentDateList.value = res.data.data;
  413. } else {
  414. }
  415. }
  416. /**
  417. * @排序按钮
  418. */
  419. const activitiesSort = ref("ASC");
  420. function activitiesSortClick() {
  421. if (activitiesSort.value == "ASC") {
  422. activitiesSort.value = "DESC";
  423. } else {
  424. activitiesSort.value = "ASC";
  425. }
  426. activitiesApi();
  427. }
  428. /**
  429. * @tabs切换change事件
  430. */
  431. const tabPosition = ref(settingsStore.planTabs);
  432. function tabPositionChange() {
  433. activitiesApi();
  434. }
  435. /**
  436. * @日期click事件
  437. */
  438. const calendar = ref(); //获取日期refs元素
  439. function calendarClick(data) {
  440. currentDate.value = data.day;
  441. currentApi();
  442. activitiesApi();
  443. }
  444. /**
  445. * @触摸开始
  446. **/
  447. let touchStartX = 0; // 触屏起始点x
  448. let touchStartY = 0; // 触屏起始点y
  449. function touchStart(e) {
  450. console.log("触摸开始");
  451. touchStartX = e.touches[0].clientX;
  452. touchStartY = e.touches[0].clientY;
  453. }
  454. /**
  455. * @触摸结束
  456. **/
  457. function touchEnd(e) {
  458. console.log("触摸结束");
  459. let deltaX = e.changedTouches[0].clientX - touchStartX;
  460. let deltaY = e.changedTouches[0].clientY - touchStartY;
  461. if (Math.abs(deltaX) > 50 && Math.abs(deltaX) > Math.abs(deltaY)) {
  462. if (deltaX >= 0) {
  463. console.log("左滑");
  464. calendar.value.selectDate("prev-month");
  465. } else {
  466. console.log("右滑");
  467. calendar.value.selectDate("next-month");
  468. }
  469. } else if (Math.abs(deltaY) > 50 && Math.abs(deltaX) < Math.abs(deltaY)) {
  470. if (deltaY < 0) {
  471. console.log("上滑");
  472. } else {
  473. console.log("下滑");
  474. }
  475. } else {
  476. console.log("可能是误触!");
  477. }
  478. }
  479. onLoad((options) => {
  480. currentApi();
  481. activitiesApi();
  482. });
  483. onMounted(() => {});
  484. </script>
  485. <style lang="scss">
  486. .is-selected {
  487. color: #1989fa;
  488. }
  489. </style>
  490. <style scoped>
  491. uni-page-body,
  492. uni-page-refresh,
  493. .grayBackgroundColor {
  494. background: rgb(241, 241, 241);
  495. }
  496. </style>