Browse Source

巡检模块

fanghuisheng 2 years ago
parent
commit
a9b3670261

+ 146 - 0
src/pages/business/mhxf/xunJian/collect/components/collectDetail.vue

@@ -0,0 +1,146 @@
+<template>
+  <scroll-view scroll-y class="grayBackgroundColor">
+    <view class="whiteBackgroundColor" style="padding: 15px 15px 15px 15px">
+      <u-form
+        ref="form"
+        labelPosition="left"
+        :model="model"
+        :rules="rules"
+        labelWidth="82"
+      >
+        <u-form-item label="地点号码:" prop="siteNubmber">
+          <u-input v-model="model.siteNubmber" disabled></u-input>
+        </u-form-item>
+        <u-form-item label="地点名称:" prop="siteName">
+          <u-input v-model="model.siteName"></u-input>
+        </u-form-item>
+        <u-form-item label="备注:" prop="siteDescribe">
+          <u-input v-model="model.siteDescribe"></u-input>
+        </u-form-item>
+      </u-form>
+
+      <u-button
+        type="primary"
+        style="width: 100%; height: 40px; font-size: 14px; margin-top: 15px"
+        @click="handleInsert()"
+        shape="circle"
+      >
+        保存
+      </u-button>
+    </view>
+  </scroll-view>
+</template>
+
+<script setup>
+import {
+  onReady,
+  onLoad,
+  onShow,
+  onPullDownRefresh, //下拉刷新
+  onReachBottom, // 上拉加载
+  onNavigationBarButtonTap,
+} from "@dcloudio/uni-app";
+import { reactive, ref, onMounted, inject, shallowRef } from "vue";
+import useXunJianStore from "@/store/modules/xunJian";
+
+const myRequest = inject("$myRequest"); //全局接口请求
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+const form = ref(null); //表单refs获取
+const model = reactive({
+  siteType: 1,
+  siteTime: "",
+  swipeBool: false,
+  siteName: "",
+  siteNubmber: "",
+  siteDescribe: "",
+}); //form表单数据定义
+const rules = ref({
+  siteName: {
+    type: "string",
+    required: true,
+    message: "地点名称不能为空",
+    trigger: ["blur", "change"],
+  },
+
+  siteNubmber: [
+    { required: true, message: "地点编号不能为空", trigger: "blur" },
+  ],
+
+  siteDescribe: [
+    { min: 1, max: 30, message: "长度在 1 到 30 个字符", trigger: "blur" },
+  ],
+}); //form表单校验
+
+/**
+ * @保存按钮点击事件
+ */
+function handleInsert() {
+  form.value
+    .validate()
+    .then((res) => {
+      let endTime = new Date();
+      model.siteTime = settingsStore.formatterDate(
+        endTime,
+        "yyyy-MM-dd hh:mm:ss"
+      );
+
+      settingsStore.collectDataList.push(model);
+
+      //   uni.navigateTo({
+      //     url: "/pages/business/mhxf/xunJian/collect/index",
+      //   });
+      uni.navigateBack({
+        delta: 1, //返回到需要执行方法的页面
+      });
+    })
+    .catch((errors) => {
+      uni.$u.toast("校验失败");
+    });
+}
+
+onLoad((options) => {
+  model.siteNubmber = options.siteNubmber;
+});
+
+onMounted(() => {});
+</script>
+
+<style lang="scss">
+.is-selected {
+  color: #1989fa;
+}
+</style>
+
+<style scoped>
+body,
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+.whiteBackgroundColor {
+  background-color: #ffffff;
+}
+
+.reportLeft {
+  margin-right: 15px;
+  display: flex;
+}
+
+.reportCenter {
+}
+
+.reportCenter .centerSiteName {
+  font-size: 15px;
+  margin-bottom: 5px;
+  height: 20px;
+  line-height: 20px;
+  display: flex;
+}
+
+.reportRight {
+  display: flex;
+  padding: 0 15px;
+}
+</style>

+ 173 - 0
src/pages/business/mhxf/xunJian/collect/components/collectRecord.vue

@@ -0,0 +1,173 @@
+<template>
+  <scroll-view scroll-y class="grayBackgroundColor">
+    <view class="example-body" v-if="show">
+      <uni-datetime-picker
+        v-model="datetimerange"
+        type="daterange"
+        rangeSeparator="~"
+        @change="confirm"
+      />
+    </view>
+    <view
+      v-for="(cu, index) in dataList.siteList"
+      :key="index"
+      class="whiteBackgroundColor"
+      style="display: flex; padding: 15px 0px 15px 15px; margin-bottom: 15px"
+    >
+      <view class="reportLeft">
+        <u-image
+          style="margin: auto"
+          width="40"
+          height="40"
+          src="@/static/images/xunjian/scan.png"
+          v-if="cu.siteType == 1"
+          shape="circle"
+        ></u-image>
+
+        <u-image
+          style="margin: auto"
+          width="40"
+          height="40"
+          src="@/static/images/xunjian/NFC.png"
+          v-if="cu.siteType == 2"
+          shape="circle"
+        ></u-image>
+      </view>
+      <view class="reportCenter">
+        <view class="centerSiteName">
+          {{ cu.siteName }}
+        </view>
+
+        <view style="font-size: 13px; color: #a1a1a1">
+          {{
+            cu.createTime == "" || cu.createTime == null ? "无" : cu.createTime
+          }}
+        </view>
+      </view>
+      <view style="margin: auto"></view>
+      <view class="reportRight">
+        <view style="margin: auto">
+          <view style="padding: 0; font-size: 14px; color: #a1a1a1">
+            已提交
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <u-empty
+      marginTop="20%"
+      mode="data"
+      icon="http://cdn.uviewui.com/uview/empty/data.png"
+      v-if="dataList.siteList.length <= 0"
+    >
+    </u-empty>
+  </scroll-view>
+</template>
+
+<script setup>
+import {
+  onReady,
+  onLoad,
+  onShow,
+  onNavigationBarButtonTap,
+} from "@dcloudio/uni-app";
+import { reactive, ref, onMounted, inject, shallowRef } from "vue";
+import useXunJianStore from "@/store/modules/xunJian";
+
+const myRequest = inject("$myRequest"); //全局接口请求
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+const show = ref(false);
+
+const dataList = reactive({
+  siteList: [],
+  startTime: "",
+  endTime: "",
+});
+
+/**
+ * @日期选中事件回调
+ */
+function confirm(e) {
+  dataList.startTime = e[0];
+  dataList.endTime = e[1];
+  handleSelectApi();
+}
+
+/**
+ * @采集记录接口查询
+ * @api请求
+ */
+async function handleSelectApi() {
+  const res = await myRequest({
+    url: "/service-fire/appPatrolInspection/siteList",
+    header: {
+      "Content-Type": "application/json;charset=utf-8",
+    },
+    method: "GET",
+    data: {
+      startTime: dataList.startTime, //开始时间
+      endTime: dataList.endTime, //结束时间
+    },
+  });
+  if (res.data.status == "SUCCESS") {
+    dataList.siteList = res.data.data;
+  } else {
+  }
+}
+
+// 自定义导航事件
+onNavigationBarButtonTap((e) => {
+  if (e.float == "right") {
+    show.value = !show.value;
+  } else {
+  }
+});
+
+onLoad((options) => {});
+
+onReady(() => {});
+
+onMounted(() => {
+  handleSelectApi();
+});
+</script>
+
+<style lang="scss">
+.is-selected {
+  color: #1989fa;
+}
+</style>
+
+<style scoped>
+body,
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+.whiteBackgroundColor {
+  background-color: #ffffff;
+}
+
+.reportLeft {
+  margin-right: 15px;
+  display: flex;
+}
+
+.reportCenter {
+}
+
+.reportCenter .centerSiteName {
+  font-size: 15px;
+  margin-bottom: 5px;
+  height: 20px;
+  line-height: 20px;
+  display: flex;
+}
+
+.reportRight {
+  display: flex;
+  padding: 0 15px;
+}
+</style>

+ 237 - 0
src/pages/business/mhxf/xunJian/collect/index.vue

@@ -0,0 +1,237 @@
+<template>
+  <scroll-view scroll-y class="grayBackgroundColor">
+    <!-- 按组使用 -->
+    <uni-swipe-action>
+      <uni-swipe-action-item
+        v-for="(cu, index) in settingsStore.collectDataList"
+        :key="index"
+        :right-options="options"
+        @click="bindClick($event, index)"
+        @change="swipeChange($event, index)"
+        style="margin-bottom: 15px"
+      >
+        <view class="whiteBackgroundColor" style="display: flex; padding: 15px 0px 15px 15px">
+          <view class="reportLeft">
+            <u-image style="margin: auto" width="40" height="40" src="@/static/images/xunjian/scan.png" v-if="cu.siteType == 1" shape="circle"></u-image>
+
+            <u-image style="margin: auto" width="40" height="40" src="@/static/images/xunjian/NFC.png" v-if="cu.siteType == 2" shape="circle"></u-image>
+          </view>
+          <view class="reportCenter">
+            <view class="centerSiteName">
+              {{ cu.siteName }}
+            </view>
+
+            <view style="font-size: 13px; color: #a1a1a1">
+              {{ cu.siteTime == "" || cu.siteTime == null ? "无" : cu.siteTime }}
+            </view>
+          </view>
+          <view style="margin: auto"></view>
+          <view class="reportRight">
+            <view style="margin: auto" v-if="cu.swipeBool == false">
+              <view style="padding: 0; font-size: 14px; color: #409eff" @click="handleInsert(cu)"> 提交 </view>
+            </view>
+          </view>
+        </view>
+      </uni-swipe-action-item>
+    </uni-swipe-action>
+
+    <view style="position: fixed; right: 0; bottom: 50px">
+      <u-image width="67" height="67" src="@/static/images/xunjian/plan-scan.png" shape="circle" @click="scanClick()"></u-image>
+    </view>
+
+    <!-- 提示信息弹窗 -->
+    <uni-popup ref="message" type="message">
+      <uni-popup-message
+        :style="{
+          color: messageList.color,
+        }"
+        :type="messageList.type"
+        :message="messageList.message"
+        :duration="messageList.duration"
+      ></uni-popup-message>
+    </uni-popup>
+
+    <u-empty marginTop="20%" mode="data" icon="http://cdn.uviewui.com/uview/empty/data.png" v-if="settingsStore.collectDataList.length <= 0"> </u-empty>
+  </scroll-view>
+</template>
+
+<script setup>
+import { onReady, onLoad, onShow, onNavigationBarButtonTap } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef, reactive } from "vue";
+import useXunJianStore from "@/store/modules/xunJian";
+
+const myRequest = inject("$myRequest"); //全局接口请求
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+/**
+ * @扫一扫
+ * @点击事件
+ */
+const scanArray = ref([]);
+const scanBool = ref(false);
+function scanClick() {
+  uni.scanCode({
+    success: (e) => {
+      uni.showToast({
+        title: "扫码成功",
+        icon: "none",
+      });
+      uni.navigateTo({
+        url: "/pages/business/mhxf/xunJian/collect/components/collectDetail?siteNubmber=" + e.result,
+      });
+    },
+    fail: (err) => {
+      uni.showToast({
+        title: "扫码失败",
+        icon: "none",
+      });
+      console.log("扫码失败", err);
+    },
+    complete: () => {
+      console.log("扫码结束");
+    },
+  });
+}
+
+/**
+ * @api请求
+ * @提交按钮点击事件
+ */
+const message = ref(null);
+const messageList = reactive({
+  type: "",
+  message: "",
+  duration: 0,
+  color: "",
+});
+function handleInsert(e) {
+  uni.getLocation({
+    type: "wgs84",
+    success: function (res) {
+      console.log("当前位置的经度:" + res.longitude);
+      console.log("当前位置的纬度:" + res.latitude);
+      api(res.longitude, res.latitude);
+    },
+    fail: function (res) {
+      uni.showToast({
+        title: "请打开手机定位或相关应用权限定位!",
+        icon: "none",
+      });
+    },
+  });
+
+  async function api(longitude, latitude) {
+    const res = await myRequest({
+      url: "/service-fire/appPatrolInspection/addSite",
+      header: {
+        "Content-Type": "application/json;charset=utf-8",
+      },
+      method: "POST",
+      data: {
+        siteName: e.siteName, //地点名称
+        siteNubmber: e.siteNubmber, //地点号码
+        siteDescribe: e.siteDescribe, //地点描述
+        siteType: e.siteType, //地点类型(1二维码,2NFC)
+        longitude: longitude, //经度
+        latitude: latitude, //纬度
+        pictureUrl: "", //图片地址
+        distanceRange: 10, //误差范围
+        // areaId: 0, //区域id
+        // companyId: 0, //单位ID
+      },
+    });
+    if (res.data.status == "SUCCESS") {
+      messageList.type = "SUCCESS";
+      messageList.message = "提交成功";
+      messageList.duration = 2000;
+      messageList.color = "#09bb07";
+      message.value.open();
+
+      settingsStore.collectDataList.splice(settingsStore.collectDataList.indexOf(e), 1);
+    } else {
+    }
+  }
+}
+
+const options = ref([
+  {
+    text: "删除",
+    style: {
+      backgroundColor: "#dd524d",
+    },
+  },
+]);
+
+/**
+ * @左滑删除点击事件
+ */
+function bindClick(e, index) {
+  settingsStore.collectDataList.splice(index, 1);
+}
+
+/**
+ * @左滑删除change事件
+ */
+function swipeChange(e, index) {
+  if (e == "right") {
+    settingsStore.collectDataList[index].swipeBool = true;
+  } else {
+    settingsStore.collectDataList[index].swipeBool = false;
+  }
+}
+
+// 自定义导航事件
+onNavigationBarButtonTap((e) => {
+  if (e.float == "right") {
+    uni.navigateTo({
+      url: "/pages/business/mhxf/xunJian/collect/components/collectRecord",
+    });
+  } else {
+  }
+});
+
+onLoad((options) => {});
+
+onReady(() => {});
+
+onMounted(() => {});
+</script>
+
+<style lang="scss">
+.is-selected {
+  color: #1989fa;
+}
+</style>
+
+<style scoped>
+body,
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+.whiteBackgroundColor {
+  background-color: #ffffff;
+}
+
+.reportLeft {
+  margin-right: 15px;
+  display: flex;
+}
+
+.reportCenter {
+}
+
+.reportCenter .centerSiteName {
+  font-size: 15px;
+  margin-bottom: 5px;
+  height: 20px;
+  line-height: 20px;
+  display: flex;
+}
+
+.reportRight {
+  display: flex;
+  padding: 0 15px;
+}
+</style>

+ 170 - 0
src/pages/business/mhxf/xunJian/components/echarts/chart.vue

@@ -0,0 +1,170 @@
+<template>
+  <view class="content">
+    <l-echart ref="domMyChart" class="echarts"></l-echart>
+    <!-- <view
+      @click="initEcharts"
+      :prop="option"
+      ref="domMyChart"
+      id="linEcharts"
+      class="echarts"
+    >
+    </view> -->
+  </view>
+</template>
+
+<script setup>
+import * as echarts from "echarts";
+import { onLoad, onShow, onHide, onLaunch, onResize } from "@dcloudio/uni-app";
+import { defineComponent, ref, onMounted, nextTick } from "vue";
+
+const props = defineProps({
+  currentDateList: {
+    type: Object,
+    default: null,
+  },
+});
+
+let myChart;
+const domMyChart = ref(null);
+var datas = [
+  {
+    name: "漏检任务",
+    value: 0,
+  },
+  {
+    name: "已巡检任务",
+    value: 0,
+  },
+];
+
+datas[0].value = props.currentDateList[0].undetectedCount;
+datas[1].value = props.currentDateList[0].patrolledCount;
+
+let option = {
+  color: ["#F07D28", "#00CDAC"],
+  title: [
+    {
+      text: "今日巡检情况",
+      left: "center",
+      top: 15,
+      textStyle: {
+        color: "black",
+        fontWeight: "normal",
+        fontSize: 14,
+      },
+    },
+    {
+      text: [
+        `{value|${props.currentDateList[0].planSonCount}}`,
+        "{name|巡检总数}",
+      ].join("\n "),
+      top: "40%",
+      left: "center",
+      textStyle: {
+        color: "black",
+        fontWeight: "normal",
+        fontSize: 14,
+        lineHeight: 22,
+        rich: {
+          name: {
+            fontFamily: "PingFangSC-Regular",
+            fontSize: 13,
+            color: "rgba(0,0,0,0.45)",
+            lineHeight: 22,
+            marginBottom: "5px",
+          },
+          value: {
+            fontFamily: "HelveticaNeue",
+            fontSize: 24,
+            color: "rgba(0,0,0,0.85)",
+            lineHeight: 30,
+          },
+        },
+      },
+    },
+  ],
+
+  series: {
+    type: "pie",
+    radius: [40, 80],
+    height: "100%",
+    left: "center",
+    width: "100%",
+    itemStyle: {
+      borderColor: "#fff",
+      borderWidth: 1,
+    },
+    label: {
+      alignTo: "edge",
+      formatter: function (el) {
+        return `${el.name}\n${el.value}`;
+      },
+      minMargin: 5,
+      edgeDistance: 10,
+      lineHeight: 20,
+      rich: {
+        time: {
+          fontSize: 10,
+          color: "#999",
+        },
+      },
+    },
+    labelLine: {
+      length: 25,
+      length2: 0,
+      maxSurfaceAngle: 80,
+    },
+    labelLayout: function (params) {
+      // var isLeft = params.labelRect.x < myChart.getWidth() / 2;
+      var isLeft = params.labelRect.x < myChart.nodeWidth / 2;
+      var points = params.labelLinePoints;
+      points[2][0] = isLeft
+        ? params.labelRect.x
+        : params.labelRect.x + params.labelRect.width;
+      return {
+        labelLinePoints: points,
+      };
+    },
+
+    data: datas,
+  },
+};
+
+function initEcharts() {
+  // let dom = uni.createSelectorQuery().select("#linEcharts");
+  // myChart = echarts.init(document.getElementById("linEcharts"));
+  // 观测更新的数据在 view 层可以直接访问到
+  // myChart.setOption(option);
+
+  myChart = domMyChart.value;
+  myChart.init(echarts, (myChart) => {
+    myChart.setOption(option);
+  });
+}
+
+onLoad(() => {
+  nextTick(() => {
+    initEcharts();
+  });
+});
+
+onResize(() => {
+  myChart.resize();
+});
+</script>
+
+<style>
+.content {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+}
+
+.echarts {
+  width: 100%;
+  height: 600rpx;
+  /* margin-top: 70rpx; */
+  /* background:pink */
+}
+</style>

+ 0 - 0
src/pages/business/mhxf/xunJian/components/index.vue


+ 363 - 0
src/pages/business/mhxf/xunJian/plan/components/content.vue

@@ -0,0 +1,363 @@
+<template>
+  <scroll-view scroll-y class="grayBackgroundColor">
+    <view>
+      <view
+        class="whiteBackgroundColor"
+        style="padding: 15px; margin-bottom: 15px"
+        v-for="(con, index) in contentList"
+        :key="index"
+      >
+        <view class="siteHeader">
+          <uni-section :title="con.contentTitle" type="line"></uni-section>
+
+          <view style="margin: auto"> </view>
+
+          <u-button
+            v-if="con.remarksBool == false"
+            type="primary"
+            icon="list-dot"
+            style="width: 18px; height: 18px; padding: 0; margin: 0"
+            shape="circle"
+            @click="remarksClick(index)"
+          >
+          </u-button>
+        </view>
+        <view>
+          <view v-if="con.submissionMethod == 1" style="margin-top: 15px">
+            <u-checkbox-group
+              v-model="con.contentOptionListValue1"
+              @change="
+                (val) => {
+                  checkboxChange(val, index);
+                }
+              "
+              :disabled="
+                settingsStore.contentArray.siteList.inspectionStatus == 2
+              "
+            >
+              <u-row style="width: 100%; flex-wrap: wrap">
+                <u-col
+                  v-for="option in con.contentOptionList"
+                  :key="option"
+                  span="6"
+                  style="margin-bottom: 15px"
+                >
+                  <u-checkbox
+                    :label="option.optionName"
+                    :name="option.id"
+                    :checked="
+                      con.contentOptionListValue1.length > 0
+                        ? con.contentOptionListValue1.indexOf(option.id) >= 0
+                        : false
+                    "
+                  >
+                  </u-checkbox>
+                </u-col>
+              </u-row>
+            </u-checkbox-group>
+
+            <view
+              v-if="con.remarksBool == true"
+              style="
+                display: flex;
+                height: 32px;
+                line-height: 32px;
+                white-space: nowrap;
+              "
+            >
+              <span style="">备注:</span>
+              <u-input
+                v-model="con.remarks"
+                placeholder="请输入备注"
+                :disabled="
+                  settingsStore.contentArray.siteList.inspectionStatus == 2
+                "
+              ></u-input>
+            </view>
+          </view>
+          <view v-if="con.submissionMethod == 2" style="margin-top: 15px">
+            <u-radio-group placement="row" v-model="con.contentOptionListValue">
+              <u-row style="width: 100%; flex-wrap: wrap">
+                <u-col
+                  v-for="option in con.contentOptionList"
+                  :key="option"
+                  :span="6"
+                  style="margin-bottom: 15px"
+                >
+                  <u-radio
+                    :disabled="
+                      settingsStore.contentArray.siteList.inspectionStatus == 2
+                    "
+                    :label="option.optionName"
+                    :name="option.id"
+                  >
+                  </u-radio>
+                </u-col>
+              </u-row>
+            </u-radio-group>
+
+            <view
+              v-if="con.remarksBool == true"
+              style="
+                display: flex;
+                height: 32px;
+                line-height: 32px;
+                white-space: nowrap;
+              "
+            >
+              <span style="">备注:</span>
+              <u-input
+                v-model="con.remarks"
+                placeholder="请输入备注"
+                :disabled="
+                  settingsStore.contentArray.siteList.inspectionStatus == 2
+                "
+              ></u-input>
+            </view>
+          </view>
+          <view v-if="con.submissionMethod == 3" style="margin-top: 15px">
+            <u-textarea
+              v-model="con.contentOptionListValue"
+              placeholder="请输入"
+              maxlength="30"
+              :disabled="
+                settingsStore.contentArray.siteList.inspectionStatus == 2
+              "
+            ></u-textarea>
+
+            <view
+              v-if="con.remarksBool == true"
+              style="
+                display: flex;
+                margin-top: 15px;
+                height: 32px;
+                line-height: 32px;
+                white-space: nowrap;
+              "
+            >
+              <span style="">备注:</span>
+              <u-input
+                v-model="con.remarks"
+                placeholder="请输入备注"
+                :disabled="
+                  settingsStore.contentArray.siteList.inspectionStatus == 2
+                "
+              ></u-input>
+            </view>
+          </view>
+        </view>
+      </view>
+
+      <view style="margin-bottom: 125px"></view>
+    </view>
+    <view style="position: fixed; left: 0; right: 0; bottom: 0; padding: 15px">
+      <view>
+        <u-button
+          v-if="settingsStore.contentArray.siteList.inspectionStatus == 1"
+          type="primary"
+          style="
+            width: 100%;
+            height: 40px;
+            font-size: 14px;
+            margin-bottom: 15px;
+          "
+          shape="circle"
+          @click="buttonClick(1)"
+        >
+          上一步
+        </u-button>
+      </view>
+      <view>
+        <u-button
+          v-if="settingsStore.contentArray.siteList.inspectionStatus == 1"
+          type="primary"
+          style="width: 100%; height: 40px; font-size: 14px"
+          shape="circle"
+          @click="buttonClick(2)"
+        >
+          提交
+        </u-button>
+      </view>
+    </view>
+
+    <u-modal
+      ref="uModal"
+      :show="show"
+      :title="title"
+      :content="content"
+      @confirm="confirm"
+    ></u-modal>
+  </scroll-view>
+</template>
+
+<script setup>
+import { onLoad, onShow } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef } from "vue";
+const myRequest = inject("$myRequest");
+const BASE_URL = inject("$BASE_URL");
+
+import useXunJianStore from "@/store/modules/xunJian";
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+const contentList = ref([]);
+function checkboxChange(value, index) {
+  contentList.value[index].contentOptionListValue1 = value;
+}
+
+/**
+ * @按钮点击事件
+ * @备注显示事件
+ */
+function remarksClick(index) {
+  settingsStore.contentArray.contentList[index].remarksBool = true;
+}
+
+/**
+ * @confirm确定回调事件
+ * @模态框
+ */
+const show = ref(false);
+const title = ref("");
+const content = ref("");
+function confirm() {
+  show.value = false;
+  uni.$emit("planSelect"); //执行页面中的自定义方法
+  uni.navigateBack({
+    delta: 3, //返回到需要执行方法的页面
+  });
+}
+
+/**
+ * @按钮点击事件
+ * @上一步
+ * @提交
+ */
+async function buttonClick(type) {
+  if (type == 1) {
+    //上一步
+    uni.navigateBack({
+      delta: 1,
+    });
+  } else if (type == 2) {
+    //提交
+
+    const recordOptionList = [];
+    if (contentList.value.length > 0) {
+      contentList.value.forEach((e) => {
+        if (e.contentOptionListValue && e.contentOptionList.length > 0) {
+          recordOptionList.push({
+            contentId: e.id,
+            contentOptionId: e.contentOptionListValue,
+            remarks: e.remarks,
+          });
+        }
+
+        if (e.contentOptionListValue && e.contentOptionList.length == 0) {
+          recordOptionList.push({
+            contentId: e.id,
+            content: e.contentOptionListValue,
+            remarks: e.remarks,
+          });
+        }
+
+        if (e.contentOptionListValue1.length > 0) {
+          e.contentOptionListValue1.forEach((l) => {
+            recordOptionList.push({
+              contentId: e.id,
+              contentOptionId: l,
+              remarks: e.remarks,
+            });
+          });
+        }
+      });
+    }
+
+    const array = {
+      siteType: settingsStore.contentArray.siteList.siteType,
+      siteNubmber: settingsStore.contentArray.siteList.siteNubmber,
+      siteName: settingsStore.contentArray.siteList.siteName,
+      siteStatus: 1, //定位 (0:未定位 1:已定位)
+      longitude: settingsStore.contentArray.siteList.longitude,
+      latitude: settingsStore.contentArray.siteList.latitude,
+      planSonId: settingsStore.contentArray.siteList.planSonId,
+      siteId: settingsStore.contentArray.siteList.id,
+      recordPictureList: settingsStore.contentArray.siteList.recordPictureList,
+      recordOptionList: recordOptionList,
+    };
+
+    let res = await myRequest({
+      url: "/service-fire/appPatrolInspection/updatePlan",
+      header: {
+        "Content-Type": "application/json;charset=utf-8",
+      },
+      method: "POST",
+      data: array,
+    });
+
+    if (res.data.status == "SUCCESS") {
+      title.value = "消息";
+      content.value = "提交成功,确定后返回!";
+      show.value = true;
+    } else {
+    }
+  }
+}
+
+onLoad((options) => {
+  contentList.value = settingsStore.contentArray.contentList;
+
+  if (settingsStore.contentArray.siteList.inspectionStatus == 2) {
+    if (contentList.value.length > 0) {
+      contentList.value.forEach((el) => {
+        el.contentOptionListValue1 = [];
+      });
+
+      contentList.value.filter((e) => {
+        if (e.remarks) {
+          e.remarksBool = true;
+        } else {
+          e.remarksBool = false;
+        }
+
+        if (e.contentOptionList) {
+          e.contentOptionList.forEach((s) => {
+            if (e.contentOptionValue.indexOf(s.id) >= 0) {
+              //提交方式:1多选 2单选 3输入框
+              if (e.submissionMethod == 1) {
+                e.contentOptionListValue1.push(s.id);
+              } else if (e.submissionMethod == 2) {
+                e.contentOptionListValue = s.id;
+              }
+            }
+          });
+        } else {
+          e.contentOptionListValue = e.content;
+        }
+      });
+    }
+  }
+});
+
+onMounted(() => {});
+</script>
+
+<style scoped>
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+
+.whiteBackgroundColor {
+  background-color: #ffffff;
+}
+</style>
+
+<style lang="scss">
+.siteHeader {
+  display: flex;
+  height: 18px;
+  line-height: 18px;
+  margin-bottom: 10px;
+}
+</style>

+ 122 - 0
src/pages/business/mhxf/xunJian/plan/components/drawer.vue

@@ -0,0 +1,122 @@
+<template>
+  <u-popup :show="scanBool" @close="close" @open="open" mode="bottom">
+    <template #default>
+      <view style="margin-bottom: 15px; margin-top: 15px">
+        <h4
+          style="
+            font-size: 16px;
+            color: #149eff;
+            text-align: center;
+            margin-bottom: 10px;
+          "
+        >
+          请选择计划
+        </h4>
+        <view style="font-size: 12px; color: #b7b7b7; text-align: center">
+          当前地点存在于多个计划,请选择目标计划
+        </view>
+      </view>
+      <scroll-view
+        scroll-y
+        style="
+          padding-left: 15px;
+          padding-right: 15px;
+          height: calc(100vh - 30rem);
+        "
+      >
+        <view v-for="(scan, index) in scanArray" :key="index">
+          <view
+            style="
+              display: flex;
+              font-size: 15px;
+              height: 50px;
+              line-height: 50px;
+            "
+          >
+            <view style="margin-right: 15px">
+              <img src="@/static/images/xunjian/plan-scan-drawer.png" alt="" />
+            </view>
+            <view>{{ scan.planName }} </view>
+            <view style="margin: auto"></view>
+            <view style="margin: auto 0">
+              <u-button
+                type="primary"
+                shape="circle"
+                style="height: 25px; font-size: 13px"
+                @click="reportClick(scan.siteId, scan.id)"
+              >
+                上报
+              </u-button>
+            </view>
+          </view>
+
+          <view style="border-bottom: 1.5px #dad7d7 solid"></view>
+        </view>
+      </scroll-view>
+    </template>
+  </u-popup>
+</template>
+
+<script setup>
+import { ElMessageBox } from "element-plus";
+import { onLoad, onShow } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef, watchEffect } from "vue";
+const myRequest = inject("$myRequest");
+
+import useXunJianStore from "@/store/modules/xunJian";
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+const props = defineProps({
+  scanArray: {
+    type: Object,
+    default: null,
+  },
+  scanBool: {
+    type: Boolean,
+    default: null,
+  },
+});
+const emit = defineEmits(["scanClose"]);
+
+const scanArray = ref(props.scanArray);
+const scanBool = ref(false);
+
+/**
+ * @巡检上报
+ * @按钮点击事件
+ */
+function reportClick(siteId, planSonId) {
+  settingsStore.contentArray = {};
+  settingsStore.siteNubmber = undefined;
+  settingsStore.siteId = siteId;
+  settingsStore.planSonId = planSonId;
+
+  uni.navigateTo({
+    url: "/pages/business/mhxf/xunJian/plan/components/siteDetails",
+  });
+}
+
+/**
+ * @开启抽屉时执行
+ */
+function open() {}
+
+/**
+ * @关闭抽屉时执行
+ */
+function close() {
+  scanBool.value = false;
+  emit("scanClose", false);
+}
+
+/**
+ * @监听器
+ */
+watchEffect((fn, options) => {
+  scanBool.value = props.scanBool;
+});
+
+onLoad((options) => {});
+
+onMounted(() => {});
+</script>

+ 310 - 0
src/pages/business/mhxf/xunJian/plan/components/report.vue

@@ -0,0 +1,310 @@
+<template>
+  <scroll-view scroll-y class="grayBackgroundColor">
+    <view
+      class="whiteBackgroundColor"
+      style="display: flex; padding: 15px 0px 15px 15px; margin-bottom: 15px"
+      v-for="cu in currentDateList"
+      :key="cu"
+    >
+      <view class="reportLeft" @click="pulicClick(cu)">
+        <u-image
+          style="margin: auto"
+          width="40"
+          height="40"
+          src="@/static/images/xunjian/scan.png"
+          v-if="cu.siteType == 1"
+          shape="circle"
+        ></u-image>
+
+        <u-image
+          style="margin: auto"
+          width="40"
+          height="40"
+          src="@/static/images/xunjian/NFC.png"
+          v-if="cu.siteType == 2"
+          shape="circle"
+        ></u-image>
+      </view>
+      <view class="reportCenter" @click="pulicClick(cu)">
+        <view class="centerSiteName">
+          {{ cu.siteName }}
+          <view
+            :style="{
+              margin: 'auto auto auto 15px',
+              fontSize: '5px',
+              backgroundColor: cu.inspectionStatus == 1 ? '#ffbebb' : '#ABE399',
+              color: cu.inspectionStatus == 1 ? '#FF3128' : '#189400',
+              borderRadius: '10px',
+              padding: '0px 5px',
+            }"
+          >
+            {{ cu.inspectionStatus == 1 ? "未巡检" : "已巡检" }}
+          </view>
+
+          <!-- "inspectionStatus": 2 //巡检状态(1 未巡检,2 已巡检) -->
+        </view>
+        <view style="font-size: 13px; color: #a1a1a1; margin-bottom: 5px">
+          描述:{{
+            cu.siteDescribe == "" || cu.siteDescribe == null
+              ? "无"
+              : cu.siteDescribe
+          }}
+        </view>
+        <view style="font-size: 13px; color: #a1a1a1">
+          完成时间:
+          {{
+            cu.inspectionTime == "" || cu.inspectionTime == null
+              ? "无"
+              : cu.inspectionTime
+          }}
+        </view>
+      </view>
+      <view style="margin: auto" @click="pulicClick(cu)"></view>
+      <view class="reportRight">
+        <view
+          class="rightChild"
+          :style="{
+            color:
+              cu.siteStatus == null || cu.siteStatus == 0
+                ? '#a0a0a0'
+                : '#1989fa',
+          }"
+        >
+          <text class="iconfont ucicon-map" style="font-size: 22px"></text>
+          <view>定位</view>
+        </view>
+        <view
+          class="rightChild"
+          :style="{
+            color:
+              cu.siteStatus == null || cu.siteStatus == 0
+                ? '#a0a0a0'
+                : '#1989fa',
+          }"
+        >
+          <text class="iconfont ucicon-appstore" style="font-size: 22px"></text>
+
+          <view>状态</view>
+        </view>
+      </view>
+    </view>
+
+    <view style="position: fixed; right: 0; bottom: 50px">
+      <u-image
+        width="67"
+        height="67"
+        src="@/static/images/xunjian/plan-scan.png"
+        shape="circle"
+        @click="scanClick()"
+      ></u-image>
+    </view>
+  </scroll-view>
+</template>
+
+<script setup>
+import { onLoad, onShow } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef } from "vue";
+const myRequest = inject("$myRequest");
+
+import useXunJianStore from "@/store/modules/xunJian";
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+async function pulicClick(obj) {
+  if (obj.inspectionStatus == 2) {
+    const res = await myRequest({
+      url: "/service-fire/appPatrolInspection/recordList",
+      header: {
+        "Content-Type": "application/json;charset=utf-8",
+      },
+      method: "GET",
+      data: {
+        siteId: obj.id,
+        planSonId: settingsStore.planSonId,
+      },
+    });
+
+    if (res.data.status == "SUCCESS") {
+      if (res.data.data.length > 0) {
+        const res1 = await myRequest({
+          url: "/service-fire/appPatrolInspection/recordOption",
+          header: {
+            "Content-Type": "application/json;charset=utf-8",
+          },
+          method: "GET",
+          data: {
+            siteId: res.data.data[0].siteId,
+            recordId: res.data.data[0].id,
+          },
+        });
+
+        res.data.data[0].inspectionStatus = 2;
+        res.data.data[0].pictureUrl = obj.pictureUrl;
+
+        settingsStore.contentArray = {
+          contentList: [res1.data.data.contentList],
+          siteList: res.data.data[0],
+        };
+        settingsStore.siteId = undefined;
+        settingsStore.siteNubmber = undefined;
+      }
+    } else {
+    }
+  } else {
+    settingsStore.contentArray = {};
+    settingsStore.siteId = obj.id;
+    settingsStore.siteNubmber = undefined;
+  }
+
+  uni.navigateTo({
+    url: "/pages/business/mhxf/xunJian/plan/components/siteDetails",
+  });
+}
+
+/**
+ * @扫一扫
+ * @点击事件
+ */
+const scanArray = ref([]);
+const scanBool = ref(false);
+async function scanClick() {
+  uni.scanCode({
+    success: async (e) => {
+      uni.showToast({
+        title: "扫码成功",
+        icon: "none",
+      });
+
+      settingsStore.contentArray = {};
+      settingsStore.siteId = undefined;
+      settingsStore.siteNubmber = e.result;
+
+      let res = await myRequest({
+        url: "/service-fire/appPatrolInspection/siteDetails",
+        header: {
+          "Content-Type": "application/json;charset=utf-8",
+        },
+        method: "GET",
+        data: {
+          siteId: settingsStore.siteId,
+          siteNubmber: settingsStore.siteNubmber,
+          planSonId: settingsStore.planSonId,
+        },
+      });
+
+      if (res.data.status == "SUCCESS") {
+        currentDateList.value.forEach((e) => {
+          if (e.id == res.data.data.siteList[0].id) {
+            uni.navigateTo({
+              url: "/pages/business/mhxf/xunJian/plan/components/siteDetails",
+            });
+          }
+        });
+      } else {
+      }
+    },
+    fail: (err) => {
+      uni.showToast({
+        title: "扫码失败",
+        icon: "none",
+      });
+      console.log("扫码失败", err);
+    },
+    complete: () => {
+      console.log("扫码结束");
+    },
+  });
+}
+
+/**
+ * @地点列表
+ * @api接口请求
+ */
+const currentDateList = ref([]); //地点列表list数据存储
+async function currentApi() {
+  const res = await myRequest({
+    url: "/service-fire/appPatrolInspection/planSonSiteDetails",
+    header: {
+      "Content-Type": "application/json;charset=utf-8",
+    },
+    method: "GET",
+    data: {
+      planSonId: settingsStore.planSonId,
+    },
+  });
+
+  if (res.data.status == "SUCCESS") {
+    currentDateList.value = res.data.data;
+
+    currentDateList.value.forEach((e) => {
+      if (e.inspectionTime) {
+        e.inspectionTime = e.inspectionTime.replace("T", " ");
+      }
+    });
+  } else {
+  }
+}
+
+onLoad((options) => {
+  currentApi();
+});
+
+onMounted(() => {});
+</script>
+
+<style lang="scss">
+.is-selected {
+  color: #1989fa;
+}
+</style>
+
+<style scoped>
+body,
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+.whiteBackgroundColor {
+  background-color: #ffffff;
+}
+
+.reportLeft {
+  margin-right: 15px;
+  display: flex;
+}
+
+.reportCenter {
+}
+
+.reportCenter .centerSiteName {
+  font-size: 15px;
+  margin-bottom: 5px;
+  height: 20px;
+  line-height: 20px;
+  display: flex;
+}
+
+.reportRight {
+  display: flex;
+  background-color: rgba(238, 238, 238, 0.3);
+  margin: -15px 0;
+}
+
+.reportRight .rightChild {
+  margin: auto;
+  text-align: center;
+  padding: 10px;
+}
+
+.reportRight .rightChild .el-icon {
+  font-size: 20px;
+  margin: auto;
+  font-weight: 600;
+}
+
+.reportRight .rightChild view {
+  font-size: 12px;
+  margin: auto;
+  font-weight: 600;
+}
+</style>

+ 356 - 0
src/pages/business/mhxf/xunJian/plan/components/siteDetails.vue

@@ -0,0 +1,356 @@
+<template>
+  <scroll-view scroll-y class="grayBackgroundColor">
+    <view>
+      <view
+        class="whiteBackgroundColor"
+        style="display: flex; padding: 15px; margin-bottom: 15px"
+      >
+        <view style="margin-right: 15px; display: flex">
+          <u-image
+            style="margin: auto"
+            width="40"
+            height="40"
+            src="@/static/images/xunjian/scan.png"
+            v-if="siteList.siteType == 1"
+            shape="circle"
+          ></u-image>
+
+          <u-image
+            style="margin: auto"
+            width="40"
+            height="40"
+            src="@/static/images/xunjian/NFC.png"
+            v-if="siteList.siteType == 2"
+            shape="circle"
+          ></u-image>
+        </view>
+        <view>
+          <view style="font-size: 15px; margin-bottom: 2px">
+            {{ siteList.siteName }}
+          </view>
+          <view style="font-size: 13px; color: #a1a1a1">
+            {{ siteList.contentCount }}项内容
+          </view>
+        </view>
+        <view style="margin: auto"></view>
+        <view style="margin: auto 0">
+          <!-- {{ siteList.siteStatus == null }} -->
+          <view style="font-size: 15px; color: #30bb00">已定位</view>
+          <!-- #f07d28 -->
+        </view>
+      </view>
+
+      <view
+        class="whiteBackgroundColor"
+        style="margin-bottom: 15px; padding: 15px"
+      >
+        <view class="siteHeader">
+          <uni-section title="上报现场" type="line"></uni-section>
+        </view>
+        <view style="display: flex; flex-wrap: wrap">
+          <view
+            class="uploadView"
+            v-for="record in siteList.recordPictureList"
+            :key="record"
+          >
+            <view class="uploadUimage">
+              <u-image
+                width="100%"
+                height="100%"
+                :src="record.pictureUrl"
+              ></u-image>
+            </view>
+
+            <view
+              v-if="siteList.inspectionStatus == 1"
+              class="uploadViewClose"
+              @click="uploadViewClose(record)"
+            >
+              <u-icon name="close" color="#ffffff" size="12"></u-icon>
+            </view>
+          </view>
+          <view
+            :class="
+              siteList.inspectionStatus == 2
+                ? 'uploadView upload-buttom uploadDisabled'
+                : 'uploadView upload-buttom'
+            "
+            @click="uploadClick"
+          >
+            <u-icon
+              style="margin: auto"
+              name="plus"
+              color="#909399"
+              size="28"
+            ></u-icon>
+          </view>
+        </view>
+      </view>
+
+      <view
+        class="whiteBackgroundColor"
+        style="
+          margin-bottom: 15px;
+          padding: 15px;
+          height: 170px;
+          max-height: 170px;
+        "
+      >
+        <view class="siteHeader">
+          <uni-section title="备注" type="line"></uni-section>
+        </view>
+        <view style="height: calc(100% - 25px)">
+          <span v-if="siteList.inspectionStatus == 2">
+            {{ siteList.remarks }}
+          </span>
+
+          <u-textarea
+            v-if="siteList.inspectionStatus == 1"
+            style="height: 100%"
+            v-model="siteList.remarks"
+            placeholder="请输入备注"
+            maxlength="50"
+          ></u-textarea>
+        </view>
+      </view>
+
+      <view class="whiteBackgroundColor" style="padding: 15px">
+        <view class="siteHeader">
+          <uni-section title="消防设施分布图" type="line"></uni-section>
+        </view>
+        <view>
+          <u-image width="100%" :src="siteList.pictureUrl"></u-image>
+        </view>
+      </view>
+
+      <view style="margin-bottom: 70px"></view>
+    </view>
+    <view style="position: fixed; left: 0; right: 0; bottom: 0; padding: 15px">
+      <view>
+        <u-button
+          v-if="siteList.inspectionStatus == 1"
+          type="primary"
+          style="width: 100%; height: 40px; font-size: 14px"
+          @click="buttonClick()"
+          shape="circle"
+        >
+          下一步
+        </u-button>
+
+        <u-button
+          v-if="siteList.inspectionStatus == 2"
+          type="primary"
+          style="width: 100%; height: 40px; font-size: 14px"
+          @click="buttonClick()"
+          shape="circle"
+        >
+          查看巡检项
+        </u-button>
+      </view>
+    </view>
+  </scroll-view>
+</template>
+
+<script setup>
+import { onLoad, onShow } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef, reactive } from "vue";
+const myRequest = inject("$myRequest");
+const sendUploadFile = inject("$sendUploadFile");
+
+import useXunJianStore from "@/store/modules/xunJian";
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+/**
+ * @站点详情
+ * @api接口查询
+ * @siteList站点详情信息存储
+ * @contentList内容详情信息存储
+ */
+const siteList = ref([]);
+const contentList = ref([]);
+async function selectAPI() {
+  let res = await myRequest({
+    url: "/service-fire/appPatrolInspection/siteDetails",
+    header: {
+      "Content-Type": "application/json;charset=utf-8",
+    },
+    method: "GET",
+    data: {
+      siteId: settingsStore.siteId,
+      siteNubmber: settingsStore.siteNubmber,
+      planSonId: settingsStore.planSonId,
+    },
+  });
+
+  if (res.data.status == "SUCCESS") {
+    contentList.value = res.data.data.contentList;
+    siteList.value = res.data.data.siteList[0];
+    siteList.value.recordPictureList = [];
+
+    contentList.value.forEach((el) => {
+      el.remarksBool = false;
+      el.contentOptionListValue = "";
+      el.contentOptionListValue1 = [];
+    });
+  } else {
+  }
+}
+
+/**
+ * @按钮点击事件
+ * @下一步
+ * @查看巡检项
+ */
+function buttonClick() {
+  settingsStore.contentArray = {
+    contentList: contentList.value,
+    siteList: siteList.value,
+  };
+  uni.navigateTo({
+    url: "/pages/business/mhxf/xunJian/plan/components/content",
+  });
+}
+
+/**
+ * @upload图片上传
+ * @点击事件
+ */
+function uploadClick() {
+  uni.chooseImage({
+    count: 1, //默认9
+    sizeType: ["original", "compressed"], //可以指定是原图还是压缩图,默认二者都有
+    sourceType: ["album", "camera"], //从相册选择、摄像头
+    success: function (res) {
+      uploadApi(res);
+    },
+  });
+}
+
+/**
+ * @upload图片上传
+ * @api接口请求
+ */
+async function uploadApi(res) {
+  let list = await sendUploadFile({
+    url: "/service-file/upload",
+    method: "POST",
+    filePath: res.tempFilePaths[0],
+    file: res.tempFiles[0],
+  });
+
+  siteList.value.recordPictureList.push({
+    name: list.data.name,
+    pictureUrl: list.data.url,
+  });
+}
+
+/**
+ * @upload图片上传
+ * @点击事件
+ * @删除事件
+ */
+function uploadViewClose(el) {
+  siteList.value.recordPictureList.splice(
+    siteList.value.recordPictureList.indexOf(el),
+    1
+  );
+}
+
+onLoad((options) => {
+  if (JSON.stringify(settingsStore.contentArray) == "{}") {
+    selectAPI();
+  } else {
+    contentList.value = settingsStore.contentArray.contentList[0];
+    siteList.value = settingsStore.contentArray.siteList;
+  }
+});
+
+onMounted(() => {});
+</script>
+
+
+<style scoped>
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+
+.whiteBackgroundColor {
+  background-color: #ffffff;
+}
+
+.siteHeader {
+  display: flex;
+  height: 20px;
+  line-height: 20px;
+  margin-bottom: 10px;
+}
+</style>
+
+<!--自定义图片上传功能样式-->
+<style scoped>
+.uploadView {
+  position: relative;
+  overflow: hidden;
+  width: calc(33% - 10px);
+  height: 110px;
+  margin: 0 15px 15px 0;
+  border: 1px solid #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+}
+
+.uploadView .uploadUimage {
+  height: 100%;
+}
+
+.uploadView .uploadUimage > uni-view {
+  height: 100%;
+}
+
+.uploadViewClose {
+  position: absolute;
+  background-color: #409eff;
+  transform: rotate(45deg);
+  width: 40px;
+  height: 24px;
+  text-align: center;
+  right: -15px;
+  top: -6px;
+  cursor: pointer;
+}
+
+.uploadViewClose .u-icon,
+.uploadViewClose .el-icon {
+  font-size: 12px;
+  margin-top: 4px;
+  margin-left: 10px;
+  transform: rotate(-45deg);
+  color: #ffffff;
+}
+
+.uploadView img {
+  width: 100%;
+}
+
+.upload-buttom {
+  display: flex;
+  font-size: 28px;
+  color: #909399;
+  border: 1px dashed #d9d9d9;
+  background-color: #fafafa;
+}
+
+.uploadView:nth-child(3n) {
+  margin: 0 !important;
+}
+
+.upload-buttom:hover {
+  border: 1px dashed #409eff;
+}
+
+::v-deep .uploadDisabled {
+  display: none !important;
+}
+</style>

+ 75 - 0
src/pages/business/mhxf/xunJian/plan/components/upload.vue

@@ -0,0 +1,75 @@
+<template>
+  <scroll-view scroll-y>
+    <el-upload
+      v-model:file-list="siteList.recordPictureList"
+      :class="
+        settingsStore.inspectionStatus == 2
+          ? 'avatar-uploader uploadDisabled'
+          : 'avatar-uploader'
+      "
+      :headers="{ Authorization: Authorization }"
+      :action="uploadUrl"
+      :on-success="uploadSuccess"
+      list-type="picture-card"
+    >
+      <el-icon class="avatar-uploader-icon"><Plus /></el-icon>
+      <template #file="{ file }">
+        <div :id="file.url">
+          <img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
+          <span class="el-upload-list__item-actions">
+            <span
+              v-if="!disabled"
+              class="el-upload-list__item-delete"
+              @click="handleRemove(file)"
+            >
+              <el-icon><Delete /></el-icon>
+            </span>
+          </span>
+        </div>
+      </template>
+    </el-upload>
+  </scroll-view>
+</template>
+
+<script setup>
+import { onLoad, onShow } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef } from "vue";
+const myRequest = inject("$myRequest");
+const sendUploadFile = inject("$sendUploadFile");
+const BASE_URL = inject("$BASE_URL");
+
+import useXunJianStore from "@/store/modules/xunJian";
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+const siteList = ref({ recordPictureList: [] });
+
+const uploadUrl = ref(BASE_URL + "/service-file/upload");
+const Authorization = uni.getStorageSync("Authorization");
+const disabled = ref(false);
+function handleRemove(file) {
+  document.getElementById(file.url).parentNode.remove();
+  siteList.value.recordPictureList.splice(
+    siteList.value.recordPictureList.indexOf(file),
+    1
+  );
+}
+/**
+ * @upload图片上传
+ * @图片上传成功回调
+ */
+function uploadSuccess(el, UploadFile) {
+  UploadFile.name = el.data.name;
+  UploadFile.url = el.data.url;
+}
+
+onLoad((options) => {});
+
+onMounted(() => {});
+</script>
+
+
+<style scoped>
+::v-deep .uploadDisabled .el-upload--picture-card {
+  display: none;
+}
+</style>

+ 480 - 0
src/pages/business/mhxf/xunJian/plan/index.vue

@@ -0,0 +1,480 @@
+<template>
+  <scroll-view scroll-y class="grayBackgroundColor">
+    <view class="grayBackgroundColor">
+      <view>
+        <el-calendar id="calendar" ref="calendar" v-model="currentDatevalue" @touchstart="touchStart" @touchend="touchEnd">
+          <template #header="{ date }">
+            <view style="display: flex; width: 100%">
+              <view>{{ date }}</view>
+              <view style="margin: auto"></view>
+              <view style="display: flex">
+                <view style="margin: 0px 10px">
+                  <span style="margin-right: 5px">合格</span>
+                  <span style="color: #00cdac">{{ JSON.stringify(currentDateList) === "{}" ? 0 : currentDateList.patrolledCount }}</span>
+                </view>
+                <view class="margin-left-xs">
+                  <span style="margin-right: 5px">漏检</span>
+                  <span style="color: #f07d28">{{ JSON.stringify(currentDateList) === "{}" ? 0 : currentDateList.undetectedCount }}</span>
+                </view>
+              </view>
+            </view>
+          </template>
+          <template #dateCell="{ data }">
+            <view @click="calendarClick(data)">
+              <p :class="data.isSelected ? 'is-selected' : ''">
+                {{ data.day.split("-").slice(2).join("-") }}
+              </p>
+              <view v-if="data.isSelected" class="filter"></view>
+            </view>
+          </template>
+        </el-calendar>
+      </view>
+      <view>
+        <view class="padding-sm" style="display: flex; margin: 10px; padding: 10px 5rem">
+          <u-subsection :list="list" :current="tabPosition" inactiveColor="#303133" activeColor="#3c9cff" @change="tabPositionChange"></u-subsection>
+        </view>
+        <view>
+          <view id="planTimeline1" v-if="activities.length > 0">
+            <view style="margin: 0px -3.5px; font-size: 13px; color: #409eff" @click="activitiesSortClick()"> 排序 </view>
+            <view v-for="(activity, index) in activities" :key="index" v-show="tabPosition == 0">
+              <view style="display: flex; height: 25px; line-height: 25px">
+                <view style="margin: auto 0">
+                  <u-icon name="info-circle-fill" color="#409eff" size="18"></u-icon>
+                </view>
+                <view style="display: flex; width: 100%; margin-left: 15px">
+                  <view style="font-size: 15px; color: #000000">
+                    {{ activity.planName }}
+                  </view>
+                  <view style="margin: auto"> </view>
+                  <view style="font-size: 14px; color: #b5b5b5">
+                    {{ activity.timestamp }}
+                  </view>
+                </view>
+              </view>
+
+              <view style="display: flex">
+                <view style="width: 18px; display: flex">
+                  <view v-if="index != activities.length - 1" style="width: 2px; background-color: #e4e7ed; margin: -5px auto"></view>
+                </view>
+                <view style="width: 100%; margin: 15px 0px 15px 15px; padding: 15px; background-color: #fff; border-radius: 10px">
+                  <view style="display: flex" v-if="activity.planStatus == 2">
+                    <view>
+                      <view>巡检任务结束</view>
+                      <br />
+                      <view style="padding: 0; font-size: 14px; color: #409eff" @click="reportClick(activity)"> 点击查看 </view>
+                    </view>
+                    <view style="margin: auto"></view>
+                    <view style="display: flex">
+                      <el-progress style="margin: auto" type="circle" :percentage="activity.completion" :width="50" />
+                    </view>
+                  </view>
+                  <view style="display: flex" v-if="activity.planStatus == 1">
+                    <view>
+                      <view>巡检任务执行中,还需完成 {{ activity.undetectedSiteCount }}个 </view>
+                      <br />
+                      <view @click="reportClick(activity)" style="padding: 0; font-size: 14px; color: #409eff"> 点击巡检 </view>
+                    </view>
+                    <view style="margin: auto"></view>
+                    <view style="display: flex">
+                      <el-progress style="margin: auto" type="circle" :percentage="activity.completion" :width="50" />
+                    </view>
+                  </view>
+                  <view style="display: flex" v-if="activity.planStatus == 3">
+                    <view>
+                      <view>巡检任务结束</view>
+                      <br />
+                      <view>
+                        <span style="margin-right: 20px">
+                          合格:
+                          <span style="color: #00cdac">
+                            {{ activity.patrolledSiteCount }}
+                          </span>
+                        </span>
+                        <span>
+                          漏检:
+                          <span style="color: #f07d28">
+                            {{ activity.undetectedSiteCount }}
+                          </span>
+                        </span>
+                      </view>
+                    </view>
+                    <view style="margin: auto"></view>
+                    <view style="display: flex">
+                      <el-progress style="margin: auto" type="circle" :percentage="activity.completion" :width="50" />
+                    </view>
+                  </view>
+                </view>
+              </view>
+            </view>
+
+            <view v-for="(activity, index) in activities" :key="index" v-show="tabPosition == 1">
+              <view style="display: flex; height: 25px; line-height: 25px">
+                <view style="margin: auto 0">
+                  <u-icon name="info-circle-fill" color="#409eff" size="18"></u-icon>
+                </view>
+                <view style="display: flex; width: 100%; margin-left: 15px">
+                  <view style="font-size: 15px; color: #000000">
+                    {{ activity.areaName }}
+                  </view>
+                  <view style="margin: auto"> </view>
+                  <view style="font-size: 14px; color: #b5b5b5">
+                    {{ activity.createTime }}
+                  </view>
+                </view>
+              </view>
+
+              <view style="display: flex">
+                <view style="width: 18px; display: flex">
+                  <view v-if="index != activities.length - 1" style="width: 2px; background-color: #e4e7ed; margin: -5px auto"></view>
+                </view>
+                <view style="width: 100%; margin: 15px 0px 15px 15px; padding: 15px; background-color: #fff; border-radius: 10px">
+                  <view style="display: flex">
+                    <view>
+                      <view>已检查{{ activity.contentCount }}项内容</view>
+                      <br />
+                      <view style="padding: 0; font-size: 14px; color: #409eff" @click="reportClick(activity)"> 点击查看 </view>
+                    </view>
+                    <view style="margin: auto"></view>
+                    <view style="display: flex; font-size: 15px; color: #30bb00">
+                      <view style="margin: auto">
+                        {{ activity.siteStatus == 0 ? "未定位" : "已定位" }}
+                      </view>
+                    </view>
+                  </view>
+                </view>
+              </view>
+            </view>
+          </view>
+
+          <view id="planTimeline" style="text-align: center; color: #bdbdbd; font-size: 14px" v-else> 暂无数据 </view>
+        </view>
+      </view>
+    </view>
+
+    <view style="position: fixed; right: 0; bottom: 50px">
+      <u-image width="67" height="67" src="@/static/images/xunjian/plan-scan.png" shape="circle" @click="scanClick()"></u-image>
+    </view>
+
+    <drawer v-if="scanArray.length > 0" :scanArray="scanArray" :scanBool="scanBool" @scanClose="scanClose"></drawer>
+  </scroll-view>
+</template>
+
+<script setup>
+import drawer from "./components/drawer.vue";
+
+import { onLoad, onShow, onLaunch } from "@dcloudio/uni-app";
+import { ref, onMounted, inject, shallowRef } from "vue";
+const myRequest = inject("$myRequest");
+
+import useXunJianStore from "@/store/modules/xunJian";
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+/**
+ * @点击巡检
+ * @点击事件
+ */
+async function reportClick(obj) {
+  if (tabPosition.value == 0) {
+    settingsStore.planSonId = obj.id;
+    uni.navigateTo({
+      url: "/pages/business/mhxf/xunJian/plan/components/report",
+    });
+  } else if (tabPosition.value == 1) {
+    const res = await myRequest({
+      url: "/service-fire/appPatrolInspection/recordList",
+      header: {
+        "Content-Type": "application/json;charset=utf-8",
+      },
+      method: "GET",
+      data: {
+        siteId: obj.id,
+        planSonId: obj.planSonId,
+      },
+    });
+
+    if (res.data.status == "SUCCESS") {
+      if (res.data.data.length > 0) {
+        const res1 = await myRequest({
+          url: "/service-fire/appPatrolInspection/recordOption",
+          header: {
+            "Content-Type": "application/json;charset=utf-8",
+          },
+          method: "GET",
+          data: {
+            siteId: res.data.data[0].siteId,
+            recordId: res.data.data[0].id,
+          },
+        });
+
+        res.data.data[0].inspectionStatus = 2;
+        res.data.data[0].pictureUrl = obj.pictureUrl;
+
+        settingsStore.contentArray = {
+          contentList: [res1.data.data.contentList],
+          siteList: res.data.data[0],
+        };
+        settingsStore.siteId = undefined;
+        settingsStore.siteNubmber = undefined;
+
+        uni.navigateTo({
+          url: "/pages/business/mhxf/xunJian/plan/components/siteDetails",
+        });
+      }
+    } else {
+    }
+  }
+}
+
+/**
+ * @扫一扫
+ * @点击事件
+ */
+const scanArray = ref([]);
+const scanBool = ref(false);
+function scanClick() {
+  uni.scanCode({
+    success: async (e) => {
+      uni.showToast({
+        title: "扫码成功",
+        icon: "none",
+      });
+      settingsStore.inspectionStatus = 1;
+      let res = await myRequest({
+        url: "/service-fire/appPatrolInspection/planList",
+        header: {
+          "Content-Type": "application/json;charset=utf-8",
+        },
+        method: "GET",
+        data: {
+          siteNubmber: e.result,
+        },
+      });
+
+      if (res.data.status == "SUCCESS") {
+        if (res.data.data.length > 0) {
+          scanArray.value = res.data.data;
+          scanBool.value = true;
+        } else {
+          uni.showToast({
+            title: "此点位下暂无数据,请切换点位重试!",
+            icon: "none",
+          });
+        }
+      } else {
+      }
+    },
+    fail: (err) => {
+      uni.showToast({
+        title: "扫码失败",
+        icon: "none",
+      });
+      console.log("扫码失败", err);
+    },
+    complete: () => {
+      // uni.showToast({
+      //   title: "扫码结束",
+      //   icon: "none",
+      // });
+      console.log("扫码结束");
+    },
+  });
+}
+
+/**
+ * @抽屉emit
+ * @关闭事件
+ */
+function scanClose(flag) {
+  scanBool.value = flag;
+}
+
+/**
+ * @巡检任务
+ * @巡检记录
+ * @api接口请求
+ */
+const activities = ref([]);
+async function activitiesApi() {
+  activities.value = [];
+  if (tabPosition.value == 0) {
+    let res = await myRequest({
+      url: "/service-fire/appPatrolInspection/patrolInspectionPlan",
+      header: {
+        "Content-Type": "application/json;charset=utf-8",
+      },
+      method: "GET",
+      data: {
+        currentDate: currentDate.value,
+        sort: activitiesSort.value,
+      },
+    });
+
+    if (res.data.status == "SUCCESS") {
+      res.data.data.forEach((el) => {
+        activities.value.push({
+          id: el.id,
+          planName: el.planName,
+          timestamp:
+            (el.startTime == null || el.startTime == "" ? "" : el.startTime.split(":")[0] + ":" + el.startTime.split(":")[1] + "~") +
+            (el.endTime == null || el.endTime == "" ? "" : el.endTime.split(":")[0] + ":" + el.endTime.split(":")[1]),
+
+          planStatus: el.planStatus,
+          completion: el.completion,
+          patrolledSiteCount: el.patrolledSiteCount,
+          undetectedSiteCount: el.undetectedSiteCount,
+        });
+      });
+    } else {
+    }
+  } else if (tabPosition.value == 1) {
+    let res = await myRequest({
+      url: "/service-fire/appPatrolInspection/recordList",
+      header: {
+        "Content-Type": "application/json;charset=utf-8",
+      },
+      method: "GET",
+      data: {
+        currentDate: currentDate.value,
+        sort: activitiesSort.value,
+      },
+    });
+
+    if (res.data.status == "SUCCESS") {
+      res.data.data.forEach((el) => {
+        activities.value.push({
+          areaName: el.areaName,
+          siteName: el.siteName,
+          contentCount: el.contentCount,
+          createTime: el.createTime.replace("T", " "),
+          siteStatus: el.siteStatus,
+        });
+      });
+    } else {
+    }
+  }
+}
+
+/**
+ * @统计
+ * @api接口请求
+ */
+const currentDate = ref(settingsStore.getDate().year + "-" + settingsStore.getDate().month + "-" + settingsStore.getDate().dates); //统计时间数据存储
+const currentDatevalue = ref(new Date());
+const currentDateList = ref({}); //统计list数据存储
+async function currentApi() {
+  const res = await myRequest({
+    url: "/service-fire/appPatrolInspection/appPlanStatistics",
+    header: {
+      "Content-Type": "application/json;charset=utf-8",
+    },
+    method: "GET",
+    data: {
+      currentDate: currentDate.value,
+    },
+  });
+
+  if (res.data.status == "SUCCESS") {
+    currentDateList.value = res.data.data;
+  } else {
+  }
+}
+
+/**
+ * @排序按钮
+ */
+const activitiesSort = ref("DESC");
+function activitiesSortClick() {
+  if (activitiesSort.value == "ASC") {
+    activitiesSort.value = "DESC";
+  } else {
+    activitiesSort.value = "ASC";
+  }
+  activitiesApi();
+}
+
+/**
+ * @tabs切换change事件
+ */
+const list = ref(["巡检任务", "巡检记录"]);
+const tabPosition = ref(settingsStore.planTabs);
+function tabPositionChange(index) {
+  tabPosition.value = index;
+  activitiesApi();
+}
+
+/**
+ * @日期click事件
+ */
+const calendar = ref(); //获取日期refs元素
+function calendarClick(data) {
+  currentDate.value = data.day;
+  currentApi();
+  activitiesApi();
+}
+
+/**
+ * @触摸开始
+ **/
+let touchStartX = 0; // 触屏起始点x
+let touchStartY = 0; // 触屏起始点y
+function touchStart(e) {
+  console.log("触摸开始");
+  touchStartX = e.touches[0].clientX;
+  touchStartY = e.touches[0].clientY;
+}
+
+/**
+ * @触摸结束
+ **/
+function touchEnd(e) {
+  console.log("触摸结束");
+  let deltaX = e.changedTouches[0].clientX - touchStartX;
+  let deltaY = e.changedTouches[0].clientY - touchStartY;
+  if (Math.abs(deltaX) > 50 && Math.abs(deltaX) > Math.abs(deltaY)) {
+    if (deltaX >= 0) {
+      console.log("左滑");
+
+      calendar.value.selectDate("prev-month");
+    } else {
+      console.log("右滑");
+      calendar.value.selectDate("next-month");
+    }
+  } else if (Math.abs(deltaY) > 50 && Math.abs(deltaX) < Math.abs(deltaY)) {
+    if (deltaY < 0) {
+      console.log("上滑");
+    } else {
+      console.log("下滑");
+    }
+  } else {
+    console.log("可能是误触!");
+  }
+}
+
+onLoad((options) => {
+  currentApi();
+  activitiesApi();
+
+  // 从详情页返回该页面的获取数据
+  uni.$on("planSelect", () => {
+    currentApi();
+    activitiesApi();
+  });
+});
+
+onMounted(() => {});
+</script>
+
+<style lang="scss">
+.is-selected {
+  color: #1989fa;
+}
+</style>
+
+<style scoped>
+body,
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+</style>

+ 99 - 0
src/pages/business/mhxf/xunJian/record/record.vue

@@ -0,0 +1,99 @@
+<template>
+  <view class="">
+    <view class="cu-list menu-avatar">
+      <view
+        class="cu-item"
+        :class="modalName == 'move-box-' + index ? 'move-cur' : ''"
+        v-for="(item, index) in this.getData"
+        :key="index"
+        :data-target="'move-box-' + index"
+        @tap="goDetail(item)"
+      >
+        <view class="content" style="left: 0; width: 80%">
+          <view class="pro-title">
+            <view class="cut">计划:{{ item.plan_name }}</view>
+          </view>
+          <view class="pro-des">
+            <view class="text-cut"> 点位:{{ item.spot_name }} </view>
+          </view>
+          <view class="pro-date">{{ item.wc_time }}</view>
+        </view>
+        <view class="nav-right num margin-right-sm">
+          <view class="text-grey">
+            <button
+              class="cu-btn radius bg-green sm"
+              v-if="item.spot_abnormal == 0"
+            >
+              正常
+            </button>
+            <button
+              class="cu-btn radius bg-orange sm"
+              v-if="item.spot_abnormal == 1"
+            >
+              异常
+            </button>
+            <button
+              class="cu-btn radius bg-red sm"
+              v-if="item.spot_abnormal == 2"
+            >
+              故障
+            </button>
+            <button
+              class="cu-btn radius bg-orange sm"
+              v-if="item.spot_abnormal == 3"
+            >
+              其他
+            </button>
+          </view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import json from "@/data/json.js";
+export default {
+  data() {
+    return {
+      modalName: null,
+      getData: [],
+    };
+  },
+
+  onLoad: function (option) {
+    this.goRecordList({ company_code: uni.getStorageSync("selectedCode") });
+  },
+  onNavigationBarButtonTap(e) {
+    console.log(e);
+    uni.navigateTo({
+      url: "/pages/export/export",
+    });
+  },
+  methods: {
+    // 巡检记录列表数据请求
+    async goRecordList(params = {}) {
+      const res = await this.$myRequest({
+        url: "Inspection/getInspectionRecordList",
+        data: params,
+        showLoading: true,
+      });
+      this.getData = res.data.data;
+      console.log(this.getData);
+    },
+
+    // 页面跳转
+    goDetail(item) {
+      uni.navigateTo({
+        url: "/pages/business/mhxf/xunJian/record/recordDetail/index?id=" + item.id,
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+.cu-item {
+  height: 180rpx !important;
+}
+</style>

+ 159 - 0
src/pages/business/mhxf/xunJian/record/recordDetail/index.vue

@@ -0,0 +1,159 @@
+<template>
+  <view>
+    <view class="timeBox flex justify-between align-center padding-lr-sm">
+      <view class="time">{{ this.getData.plan_name }}</view>
+      <button
+        class="cu-btn radius bg-green sm"
+        v-if="this.getData.spot_abnormal == 0"
+      >
+        正常
+      </button>
+      <button
+        class="cu-btn radius bg-orange sm"
+        v-if="this.getData.spot_abnormal == 1"
+      >
+        异常
+      </button>
+      <button
+        class="cu-btn radius bg-red sm"
+        v-if="this.getData.spot_abnormal == 2"
+      >
+        故障
+      </button>
+      <button
+        class="cu-btn radius bg-red sm"
+        v-if="this.getData.spot_abnormal == 3"
+      >
+        其他
+      </button>
+    </view>
+
+    <view>
+      <view class="basic-info">
+        <view class="info-tit margin-left-xs">
+          <text class="cuIcon-titles margin-right-xs"></text>
+          基本信息
+        </view>
+        <view class="info-content">
+          <view class="info-one-info">
+            <text>所属单位:</text>
+            <text>{{ this.getData.owner_name }}</text>
+          </view>
+
+          <view class="info-one-info">
+            <text>单位地址:</text>
+            <text>{{ this.getData.owner_address }}</text>
+          </view>
+          <view class="info-one-info">
+            <text>巡检点位:</text>
+            <text>{{ this.getData.spot_name }}</text>
+          </view>
+          <view class="info-one-info">
+            <text>点位地址:</text>
+            <text>{{ this.getData.spot_address }}</text>
+          </view>
+          <view class="info-one-info">
+            <text>预期时间:</text>
+            <text>{{ this.getData.ywc_time }}</text>
+          </view>
+          <view class="info-one-info">
+            <text>完成时间:</text>
+            <text>{{ this.getData.wc_time }}</text>
+          </view>
+        </view>
+      </view>
+
+      <!-- 巡检信息 -->
+      <view class="basic-info">
+        <view class="info-tit margin-left-xs">
+          <text class="cuIcon-titles margin-right-xs"></text>
+          巡检信息
+        </view>
+        <view class="info-content">
+          <view class="info-one-info">
+            <text>巡检人员:</text>
+            <text>{{ this.getData.name }}</text>
+          </view>
+
+          <view class="info-one-info">
+            <text>联系方式:</text>
+            <text>{{ this.getData.phone }}</text>
+          </view>
+          <view class="info-one-info">
+            <text>巡检描述:</text>
+            <text>{{ this.getData.dwsb_remarks }}</text>
+          </view>
+        </view>
+      </view>
+      <!-- 处理状态start -->
+      <view class="processStatus">
+        <view class="info-tit margin-left-xs">
+          <text class="cuIcon-titles margin-right-xs"></text>
+          巡检图片
+        </view>
+        <view class="padding-lr padding-bottom-lg imgPic">
+          <image
+            v-if="!this.getData.report_photos && this.dataRes == 1"
+            mode="widthFix"
+            src="@/static/images/defaultImg.jpg"
+            width="100%"
+          />
+          <image
+            v-else
+            mode="widthFix"
+            :src="`${this.$websiteUrl}${this.getData.report_photos}`"
+            width="100%"
+          />
+
+          <!-- <image class="image-bg"  v-if="!this.getData.report_photos&&this.dataRes==1"  src="@/static/images/defaultImg.jpg"/>
+						<image  class="image-bg" v-else :src="this.getData.report_photos" /> -->
+        </view>
+      </view>
+      <!-- 处理状态end -->
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      radio: "A",
+      radio: "B",
+      modalName: null,
+      reason: "",
+      type: "0",
+      detailMessage: {},
+      detailMessage2: {},
+      msg: "",
+      msg2: "",
+      flag: false,
+      companyCode: 0,
+      getData: {},
+      dataRes: 0,
+    };
+  },
+  onLoad: function (option) {
+    this.goRecordDetail({
+      company_code: uni.getStorageSync("selectedCode"),
+      id: option.id,
+    });
+  },
+  methods: {
+    // 巡检记录列详情数据请求
+    async goRecordDetail(params = {}) {
+      const res = await this.$myRequest({
+        url: "Inspection/getInspectionRecordDetails",
+        data: params,
+        showLoading: true,
+      });
+      this.getData = res.data.data[0];
+      this.dataRes = 1;
+      console.log(this.getData);
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+</style>

+ 119 - 0
src/pages/business/mhxf/xunJian/xunJian.vue

@@ -0,0 +1,119 @@
+<template>
+  <scroll-view scroll-x class="grayBackgroundColor">
+    <view class="padding-sm">
+      <!-- 图表 -->
+      <view class="section1 section bg-white padding-xs">
+        <chart v-if="currentDateList.length > 0" :currentDateList="currentDateList"></chart>
+      </view>
+      <!-- 图表 end-->
+
+      <!-- <view class="cu-list menu-avatar">
+				<view class="cu-item deviceTypeItem" v-for="(item,index) in inspectList" :key="index"
+					@tap="goRecordPage(index)">
+					<view class="cu-avatar round">
+						<image class="image-bg" :src=item.imgUrl />
+					</view>
+					<view class="content">
+						<view class="title">{{item.title}}</view>
+					</view>
+					<view class="nav-right num">
+						<view>
+							<text class="icon iconfont margin-right-xs margin-left-lg">&#xe629;</text>
+						</view>
+					</view>
+				</view>
+			</view> -->
+      <!-- 宫格列表 -->
+      <view class="section2 section bg-white margin-top-sm">
+        <view class="cu-list grid col-4 no-border" style="padding-top: 0.3125rem">
+          <view class="cu-item justify-center align-center" v-for="(item, index) in inspectList" :key="index" @tap="navItemClick(item.redirectUrl, item.id)">
+            <image :src="item.imgUrl" style="width: 40px; height: 40px"></image>
+            <view class="cu-tag badge" v-if="item.num != 0">
+              <block v-if="item.num != 0">{{ item.num > 99 ? "99+" : item.num }}</block>
+            </view>
+            <text style="font-size: 14px">{{ item.title }}</text>
+          </view>
+        </view>
+      </view>
+      <!-- 宫格列表 end -->
+    </view>
+  </scroll-view>
+</template>
+
+<script setup>
+import chart from "./components/echarts/chart.vue";
+
+import useXunJianStore from "@/store/modules/xunJian";
+const settingsStore = useXunJianStore(); //全局变量值Store
+
+import { ref, onMounted, inject } from "vue";
+const myRequest = inject("$myRequest"); //api请求方法
+
+import json from "@/data/json.js";
+const inspectList = json.xunJianList; //九宫格json数据
+
+const currentDate = settingsStore.getDate().year + "-" + settingsStore.getDate().month + "-" + settingsStore.getDate().dates;
+const currentDateList = ref([]);
+
+function navItemClick(url, id) {
+  if (url) {
+    if (id == 1) {
+      settingsStore.planTabs = 0;
+    } else if (id == 2) {
+      settingsStore.planTabs = 1;
+    }
+
+    uni.navigateTo({
+      url: url,
+    });
+  } else {
+    uni.showModal({
+      title: "Tips",
+      content: "此模块开发中~",
+      showCancel: false,
+      success: function (res) {
+        if (res.confirm) {
+        } else if (res.cancel) {
+        }
+      },
+    });
+  }
+}
+
+/**
+ * @ehcarts
+ * @api接口请求
+ */
+async function echartsApi() {
+  const res = await myRequest({
+    url: "/service-fire/appPatrolInspection/appPlanStatistics",
+    header: {
+      "Content-Type": "application/json;charset=utf-8",
+    },
+    method: "GET",
+    data: {
+      currentDate: currentDate,
+    },
+  });
+
+  if (res.data.status == "SUCCESS") {
+    currentDateList.value = [res.data.data];
+  } else {
+  }
+}
+
+onMounted(() => {
+  echartsApi();
+});
+</script>
+
+<style lang="scss"></style>
+
+<style scoped>
+body,
+uni-page-body,
+uni-page-refresh,
+.grayBackgroundColor {
+  background: rgb(241, 241, 241);
+}
+</style>

BIN
src/static/images/xunjian/NFC.png


BIN
src/static/images/xunjian/plan-scan-drawer.png


BIN
src/static/images/xunjian/plan-scan.png


BIN
src/static/images/xunjian/scan.png


BIN
src/static/images/xunjian/xunJian-icon1.png


BIN
src/static/images/xunjian/xunJian-icon2.png


BIN
src/static/images/xunjian/xunJian-icon3.png