index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <template>
  2. <u-navbar :titleStyle="{ color: '#fff' }" :autoBack="true" title="巡检计划" :placeholder="true" :safeAreaInsetTop="true" :bgColor="proxy.$settingStore.themeColor.color">
  3. <template #left>
  4. <view class="u-navbar__content__left__item">
  5. <u-icon name="arrow-left" size="20" color="#fff"></u-icon>
  6. </view>
  7. </template>
  8. </u-navbar>
  9. <oa-scroll
  10. customClass="xunjian-plan-container scroll-height"
  11. :customStyle="{ height: `calc(100vh - (44px + ${proxy.$settingStore.StatusBarHeight} + ${proxy.$settingStore.tabBarHeight}))` }"
  12. :refresherLoad="false"
  13. :refresherEnabled="false"
  14. :refresherEnabledTitle="false"
  15. :refresherDefaultStyle="'none'"
  16. :refresherThreshold="44"
  17. :refresherBackground="'#f5f6f7'"
  18. :data-theme="'theme-' + proxy.$settingStore.themeColor.name"
  19. >
  20. <template #default>
  21. <!-- 日历组件 -->
  22. <oa-calendar class="uni-calendar--hook" :selected="info.selected" :showMonth="false" @change="change" @monthSwitch="monthSwitch">
  23. <template #headerRight>
  24. <view class="item">
  25. <span class="item_title">巡检</span>
  26. <span class="item_cont" style="color: #00cdac">{{ JSON.stringify(currentDateList) === "{}" ? 0 : currentDateList.patrolledCount }}</span>
  27. </view>
  28. <view class="item">
  29. <span class="item_title">漏检</span>
  30. <span class="item_cont" style="color: #f07d28">{{ JSON.stringify(currentDateList) === "{}" ? 0 : currentDateList.undetectedCount }}</span>
  31. </view>
  32. </template>
  33. </oa-calendar>
  34. <!-- 分段器组件 -->
  35. <view class="app-subsection">
  36. <u-subsection :list="list" :current="tabPosition" inactiveColor="#303133" :activeColor="proxy.$settingStore.themeColor.color" @change="tabPositionChange" style="width: 100%"></u-subsection>
  37. </view>
  38. <!-- 内容 -->
  39. <oa-timeLine v-if="activities.length > 0" :fontColor="proxy.$settingStore.themeColor.color" :sort="activitiesSort" @activitiesSortChange="activitiesSortChange">
  40. <oa-timeLine-item
  41. v-for="(ac, index) in activities"
  42. :key="index"
  43. :titleValue="ac.planName"
  44. :timeValue="ac.timestamp"
  45. :iconColor="proxy.$settingStore.themeColor.color"
  46. v-show="tabPosition == 0"
  47. >
  48. <view style="display: flex" v-if="ac.planStatus == 1">
  49. <view>
  50. <view style="margin-bottom: 15px">巡检任务执行中,还需完成 {{ ac.undetectedSiteCount }}个 </view>
  51. <view style="padding: 0; font-size: 14px" :style="{ color: proxy.$settingStore.themeColor.color }" @click="reportClick(ac)"> 点击巡检 </view>
  52. </view>
  53. <view style="margin: auto"></view>
  54. <view style="display: flex">
  55. <c-progress-circle style="margin: auto" :progress="ac.completion / 100" :color="proxy.$settingStore.themeColor.color" size="100rpx" boderWidth="100rpx"></c-progress-circle>
  56. </view>
  57. </view>
  58. <view style="display: flex" v-if="ac.planStatus == 2">
  59. <view>
  60. <view style="margin-bottom: 15px">巡检任务结束</view>
  61. <view style="padding: 0; font-size: 14px" :style="{ color: proxy.$settingStore.themeColor.color }" @click="reportClick(ac)"> 点击查看 </view>
  62. </view>
  63. <view style="margin: auto"></view>
  64. <view style="display: flex">
  65. <c-progress-circle style="margin: auto" :progress="ac.completion / 100" :color="proxy.$settingStore.themeColor.color" size="100rpx" boderWidth="100rpx"></c-progress-circle>
  66. </view>
  67. </view>
  68. <view style="display: flex" v-if="ac.planStatus == 3">
  69. <view>
  70. <view style="margin-bottom: 15px">巡检任务结束</view>
  71. <view>
  72. <span style="margin-right: 20px">
  73. 合格:
  74. <span style="color: #00cdac">
  75. {{ ac.patrolledSiteCount }}
  76. </span>
  77. </span>
  78. <span>
  79. 漏检:
  80. <span style="color: #f07d28">
  81. {{ ac.undetectedSiteCount }}
  82. </span>
  83. </span>
  84. </view>
  85. </view>
  86. <view style="margin: auto"></view>
  87. <view style="display: flex">
  88. <c-progress-circle style="margin: auto" :progress="ac.completion / 100" :color="proxy.$settingStore.themeColor.color" size="100rpx" boderWidth="100rpx"></c-progress-circle>
  89. </view>
  90. </view>
  91. </oa-timeLine-item>
  92. <oa-timeLine-item
  93. v-for="(ac, index) in activities"
  94. :key="index"
  95. :titleValue="ac.siteName"
  96. :timeValue="ac.createTime"
  97. :iconColor="proxy.$settingStore.themeColor.color"
  98. v-show="tabPosition == 1"
  99. >
  100. <view style="display: flex">
  101. <view>
  102. <view>已检查{{ ac.contentCount }}项内容</view>
  103. <br />
  104. <view style="padding: 0; font-size: 14px" :style="{ color: proxy.$settingStore.themeColor.color }" @click="reportClick(ac)"> 点击查看 </view>
  105. </view>
  106. <view style="margin: auto"></view>
  107. <view style="display: flex; font-size: 15px; color: #30bb00">
  108. <view style="margin: auto">
  109. {{ ac.siteStatus == 0 ? "未定位" : "已定位" }}
  110. </view>
  111. </view>
  112. </view>
  113. </oa-timeLine-item>
  114. </oa-timeLine>
  115. <view id="planTimeline" style="text-align: center; color: #bdbdbd; font-size: 14px" v-else> 暂无数据 </view>
  116. <oaMovable v-if="scanArray.length <= 0" :themesColor="proxy.$settingStore.themeColor.color">
  117. <template #content>
  118. <view class="iconfont oaIcon-nfc menu-item-icon" @click="nfcClick()"></view>
  119. <view class="iconfont oaIcon-saoyisao menu-item-icon" @click="scanClick()"></view>
  120. </template>
  121. </oaMovable>
  122. <drawer v-if="scanArray.length > 0" :scanArray="scanArray" :scanBool="scanBool" @scanClose="scanClose"></drawer>
  123. </template>
  124. </oa-scroll>
  125. </template>
  126. <script setup>
  127. /*----------------------------------依赖引入-----------------------------------*/
  128. import { onLoad, onShow, onLaunch, onUnload } from "@dcloudio/uni-app";
  129. import { ref, onMounted, reactive, computed, getCurrentInstance, toRefs, inject, shallowRef, defineAsyncComponent } from "vue";
  130. /*----------------------------------接口引入-----------------------------------*/
  131. import { recordList, recordOption, planList, patrolInspectionPlan, appPlanStatistics } from "@/api/business/zhaf/xunJian/plan.js";
  132. /*----------------------------------组件引入-----------------------------------*/
  133. import drawer from "./components/drawer.vue"; // 引入组件
  134. import oaMovable from "@/components/oa-movable/index.vue"; // 引入组件
  135. /*----------------------------------store引入-----------------------------------*/
  136. import { useStores, commonStores, xunJianStores } from "@/store/modules/index";
  137. /*----------------------------------公共方法引入-----------------------------------*/
  138. /*----------------------------------公共变量-----------------------------------*/
  139. const { proxy } = getCurrentInstance();
  140. const xunJianStore = xunJianStores(); //全局变量值Store
  141. /*----------------------------------变量声明-----------------------------------*/
  142. const info = ref({
  143. lunar: true,
  144. range: true,
  145. insert: false,
  146. selected: [],
  147. });
  148. /**
  149. * @日期change事件
  150. */
  151. function change(e) {
  152. // console.log("change 返回:", e);
  153. currentDate.value = e.fulldate;
  154. currentApi();
  155. activitiesApi();
  156. }
  157. /**
  158. * @月份切换事件
  159. */
  160. function monthSwitch(e) {
  161. // console.log("monthSwitchs 返回:", e);
  162. }
  163. /**
  164. * @点击巡检
  165. * @点击事件
  166. */
  167. function reportClick(obj) {
  168. xunJianStore.inspectionStatus = null;
  169. if (tabPosition.value == 0) {
  170. xunJianStore.planSonId = obj.id;
  171. uni.navigateTo({
  172. url: "/pages/business/zhaf/xunJian/plan/components/report",
  173. });
  174. } else if (tabPosition.value == 1) {
  175. xunJianStore.siteId = obj.siteId;
  176. xunJianStore.planSonId = obj.planSonId;
  177. xunJianStore.inspectionStatus = 2;
  178. uni.navigateTo({
  179. url: "/pages/business/zhaf/xunJian/plan/components/siteDetails",
  180. });
  181. }
  182. }
  183. /**
  184. * @NFC
  185. */
  186. function nfcClick() {
  187. // proxy.$nfc.initNFC();
  188. uni.navigateTo({
  189. url: "/pages/common/nfc/index",
  190. });
  191. }
  192. /**
  193. * @扫一扫
  194. * @点击事件
  195. */
  196. const scanArray = ref([]);
  197. const scanBool = ref(false);
  198. function scanClick() {
  199. uni.scanCode({
  200. autoZoom: false,
  201. success: async (e) => {
  202. uni.showToast({
  203. title: "扫码成功",
  204. icon: "none",
  205. });
  206. planListApi(e.result);
  207. },
  208. fail: (err) => {
  209. uni.showToast({
  210. title: "扫码失败",
  211. icon: "none",
  212. });
  213. console.log("扫码失败", err);
  214. },
  215. complete: () => {
  216. console.log("扫码结束");
  217. },
  218. });
  219. }
  220. /**
  221. * @点位查询
  222. * @接口查询
  223. */
  224. function planListApi(value) {
  225. xunJianStore.inspectionStatus = 1;
  226. if (!proxy.$common.isNetwork()) {
  227. return false;
  228. }
  229. planList({
  230. siteNubmber: value,
  231. })
  232. .then((res) => {
  233. if (res.status == "SUCCESS") {
  234. if (res.data.length > 0) {
  235. scanArray.value = res.data;
  236. scanBool.value = true;
  237. } else {
  238. uni.showToast({
  239. title: "此点位下暂无数据,请切换点位重试!",
  240. icon: "none",
  241. });
  242. }
  243. }
  244. })
  245. .catch((err) => {
  246. proxy.$modal.msg(err);
  247. });
  248. }
  249. /**
  250. * @抽屉emit
  251. * @关闭事件
  252. */
  253. function scanClose(flag) {
  254. scanBool.value = flag;
  255. scanArray.value = [];
  256. }
  257. /**
  258. * @巡检任务
  259. * @巡检记录
  260. * @api接口请求
  261. */
  262. const activities = ref([]);
  263. function activitiesApi() {
  264. activities.value = [];
  265. if (!proxy.$common.isNetwork()) {
  266. return false;
  267. }
  268. if (tabPosition.value == 0) {
  269. patrolInspectionPlan({
  270. currentDate: currentDate.value,
  271. sort: activitiesSort.value,
  272. })
  273. .then((res) => {
  274. if (res.status == "SUCCESS") {
  275. res.data.forEach((el) => {
  276. activities.value.push({
  277. id: el.id,
  278. planName: el.planName,
  279. timestamp: (el.startTime ? el.startTime.split(":")[0] + ":" + el.startTime.split(":")[1] + "~" : "") + (el.endTime ? el.endTime.split(":")[0] + ":" + el.endTime.split(":")[1] : ""),
  280. planStatus: el.planStatus,
  281. completion: el.completion,
  282. patrolledSiteCount: el.patrolledSiteCount,
  283. undetectedSiteCount: el.undetectedSiteCount,
  284. });
  285. });
  286. } else {
  287. }
  288. })
  289. .catch((err) => {
  290. proxy.$modal.msg(err);
  291. });
  292. } else if (tabPosition.value == 1) {
  293. recordList({
  294. currentDate: currentDate.value,
  295. sort: activitiesSort.value,
  296. })
  297. .then((res) => {
  298. if (res.status == "SUCCESS") {
  299. res.data.forEach((el) => {
  300. activities.value.push({
  301. siteId: el.siteId,
  302. planSonId: el.planSonId,
  303. areaName: el.areaName,
  304. siteName: el.siteName,
  305. contentCount: el.contentCount,
  306. createTime: el.createTime ? el.createTime.replace("T", " ") : el.createTime,
  307. siteStatus: el.siteStatus,
  308. });
  309. });
  310. } else {
  311. }
  312. })
  313. .catch((err) => {
  314. proxy.$modal.msg(err);
  315. });
  316. }
  317. }
  318. /**
  319. * @统计
  320. * @api接口请求
  321. */
  322. const currentDate = ref(proxy.$dayjs().format("YYYY-MM-DD")); //统计时间数据存储
  323. const currentDatevalue = ref(new Date());
  324. const currentDateList = ref({}); //统计list数据存储
  325. function currentApi() {
  326. if (!proxy.$common.isNetwork()) {
  327. return false;
  328. }
  329. appPlanStatistics({
  330. currentDate: currentDate.value,
  331. })
  332. .then((res) => {
  333. if (res.status == "SUCCESS") {
  334. currentDateList.value = res.data;
  335. } else {
  336. }
  337. })
  338. .catch((err) => {
  339. proxy.$modal.msg(err);
  340. });
  341. }
  342. /**
  343. * @排序按钮
  344. */
  345. const activitiesSort = ref("DESC");
  346. function activitiesSortChange(val) {
  347. activitiesSort.value = val;
  348. activitiesApi();
  349. }
  350. /**
  351. * @tabs切换change事件
  352. */
  353. const list = ref(["巡检任务", "巡检记录"]);
  354. const tabPosition = ref(xunJianStore.planTabs);
  355. function tabPositionChange(index) {
  356. tabPosition.value = index;
  357. activitiesApi();
  358. }
  359. onLoad((options) => {
  360. if (options.planTabs) {
  361. xunJianStore.planTabs = parseInt(options.planTabs);
  362. tabPosition.value = parseInt(options.planTabs);
  363. }
  364. currentApi();
  365. activitiesApi();
  366. xunJianStore.planForSubmit(); //调用巡检计划循环提交
  367. // 从详情页返回该页面的获取数据
  368. uni.$on("planSelect", () => {
  369. scanArray.value = [];
  370. currentApi();
  371. activitiesApi();
  372. });
  373. });
  374. onShow(() => {
  375. //调用系统主题颜色
  376. proxy.$settingStore.systemThemeColor([1]);
  377. uni.$on("NFC_readID", function (value) {
  378. planListApi(value);
  379. });
  380. });
  381. onUnload(() => {
  382. uni.$off("NFC_readID"); //将值删除监听器
  383. });
  384. onMounted(() => {});
  385. </script>
  386. <style lang="scss" scoped>
  387. .is-selected {
  388. color: #1989fa;
  389. }
  390. .xunjian-plan-container {
  391. .app-subsection {
  392. display: flex;
  393. margin: 10px;
  394. padding: 10px 5rem;
  395. }
  396. }
  397. </style>