From d840ec98c37494baf79f3d05e3d2b01c76cec744 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期四, 30 十月 2025 13:05:38 +0800
Subject: [PATCH] 巡检

---
 src/pages.json                                     |    6 
 src/pages/routingInspection/index.vue              |  153 +++++++++++++++++
 src/pages/routingInspection/product_card/index.vue |  205 ++++++++++++++++++++++
 src/api/routingInspection/routingInspection.ts     |   23 ++
 src/pages/routingInspection/list/index.vue         |  111 ++++++++++++
 src/pages/index/index.vue                          |    6 
 src/static/icons/routingInspection.png             |    0 
 7 files changed, 504 insertions(+), 0 deletions(-)

diff --git a/src/api/routingInspection/routingInspection.ts b/src/api/routingInspection/routingInspection.ts
new file mode 100644
index 0000000..074de57
--- /dev/null
+++ b/src/api/routingInspection/routingInspection.ts
@@ -0,0 +1,23 @@
+import request from "@/utils/request";
+import { BaseResult } from "@/models/base";
+
+const RoutingInspectionApi = {
+  // 鏌ヨ宸℃璁板綍
+  getDeviceInspectListByPatrol(params: any) {
+    return request<BaseResult<any>>({
+      url: "/wireInspection/getDeviceInspectListByPatrol",
+      method: "GET",
+      data: params,
+    });
+  },
+  // 鑾峰彇宸℃鏁版嵁
+  getInspectListByPatrol(data: any) {
+    return request<BaseResult<any>>({
+      url: "/wireInspection/getInspectListByPatrol",
+      method: "POST",
+      data: data,
+    });
+  },
+};
+
+export default RoutingInspectionApi;
diff --git a/src/pages.json b/src/pages.json
index 55210a1..781c4b7 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -148,6 +148,12 @@
       }
     },
     {
+      "path": "pages/routingInspection/index",
+      "style": {
+        "navigationBarTitleText": "宸℃"
+      }
+    },
+    {
       "path": "pages/production/detail/wireDetail",
       "style": {
         "navigationBarTitleText": "鎷変笣璇︽儏"
diff --git a/src/pages/index/index.vue b/src/pages/index/index.vue
index 2df7101..e6e6454 100644
--- a/src/pages/index/index.vue
+++ b/src/pages/index/index.vue
@@ -177,6 +177,12 @@
     url: "/pages/timely/index",
     show: false,
   },
+  {
+    icon: "/static/icons/routingInspection.png",
+    title: "宸℃",
+    url: "/pages/routingInspection/index",
+    show: true,
+  },
 ]);
 
 // 鍔犺浇璁块棶缁熻鏁版嵁
diff --git a/src/pages/routingInspection/index.vue b/src/pages/routingInspection/index.vue
new file mode 100644
index 0000000..4e9a33a
--- /dev/null
+++ b/src/pages/routingInspection/index.vue
@@ -0,0 +1,153 @@
+<template>
+  <view>
+    <wd-row>
+      <wd-col :span="21">
+        <wd-search placeholder-left hide-cancel></wd-search>
+      </wd-col>
+      <wd-col :span="3">
+        <view class="scan_box" @click="openScan">
+          <wd-icon name="scan" size="24px" color="#0D867F"></wd-icon>
+        </view>
+      </wd-col>
+    </wd-row>
+    <wd-tabs v-model="tab" auto-line-width slidable="always" map-num>
+      <wd-tab 
+        v-for="(item, index) in patrolList" 
+        :key="index"
+        :title="`${item.deviceModel}锛堝緟妫�鏌�${item.pendingNum}鏉★級`"
+        class="tab_bg"
+      >
+        <ProductList
+          :api="RoutingInspectionApi.getInspectListByPatrol"
+          :ProList="item"
+        />
+      </wd-tab>
+    </wd-tabs>
+    <Scan ref="scanRef" emitName="scan" />
+    <wd-toast />
+  </view>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive, computed, onMounted, onUnmounted } from "vue";
+import ProductList from "./list/index.vue";
+import Scan from "@/components/scan/index.vue";
+import { useUserStore } from "@/store/modules/user";
+import reportApi from "@/api/work/report";
+import { useToast } from "wot-design-uni";
+import RoutingInspectionApi from "@/api/routingInspection/routingInspection";
+
+const scanRef = ref();
+const userStore = useUserStore();
+const userInfo: any = computed(() => userStore.userInfo);
+const toast = useToast();
+const tab = ref<number>(0);
+const patrolList = ref<any[]>([]);// 宸℃璁惧鍒楄〃鏁版嵁
+
+
+const handlePatrolData = (index: number, count: number) => {
+  // 鍙互鍦ㄨ繖閲屾洿鏂扮壒瀹氬贰妫�璁惧鐨勫緟妫�鏌ユ暟閲�
+  // 渚嬪锛歱atrolList.value[index].pendingNum = count;
+};
+
+const openScan = () => {
+  scanRef.value.triggerScan();
+};
+
+const getScanCode = async () => {
+  const { code } = await reportApi.sendWorkTime({
+    userName: userInfo.value.userName,
+  });
+  if (code == 200) {
+    toast.success("鎵爜鎴愬姛");
+  }
+};
+
+// 鑾峰彇鐗瑰畾宸℃璁惧鐨勬暟鎹�
+const getPatrolData = (item: any) => {
+  return async (params: any) => {
+    // 杩欓噷鍙互鏍规嵁item涓殑淇℃伅璋冪敤鐩稿簲鐨勬帴鍙h幏鍙栬鎯�
+    // 杩斿洖鐨勬暟鎹牸寮忛渶瑕佷笌ProductList缁勪欢鏈熸湜鐨勬牸寮忎竴鑷�
+    return {
+      code: 200,
+      data: {
+        type: "宸℃",
+        data: {
+          total: 0,
+          records: []
+        }
+      }
+    };
+  };
+};
+
+// 鑾峰彇宸℃璁惧鍒楄〃
+const loadPatrolList = async () => {
+  try {
+    const { data } = await RoutingInspectionApi.getDeviceInspectListByPatrol({});
+    if (data) {
+      patrolList.value = data;
+    }
+  } catch (error) {
+    toast.error("鑾峰彇宸℃璁惧鍒楄〃澶辫触");
+  }
+};
+
+// 纭繚鍏堢Щ闄ゅ啀娣诲姞鐩戝惉
+const setupScanListener = () => {
+  uni.$off("scan", getScanCode); // 鍏堢Щ闄ゆ棫鐨�
+  uni.$on("scan", getScanCode); // 鍐嶆坊鍔犳柊鐨�
+};
+
+onMounted(() => {
+  // 寮�鍚箍鎾洃鍚簨浠�
+  setupScanListener();
+  console.log("鏄剧ず1");
+  // 椤甸潰鍔犺浇鏃惰幏鍙栧贰妫�璁惧鍒楄〃
+  loadPatrolList();
+});
+
+onUnmounted(() => {
+  // 寮�鍚箍鎾洃鍚簨浠�
+  uni.$off("scan", getScanCode);
+  console.log("绂诲紑1");
+});
+</script>
+
+<style lang="scss" scoped>
+::v-deep .wd-search__block {
+  border-radius: unset;
+}
+.scan_box {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 38px;
+  height: 38px;
+  padding: 6px;
+  background: #fff;
+}
+::v-deep .wd-tabs__line {
+  background: #0d867f;
+}
+::v-deep .wd-tabs__nav {
+  border-bottom: 1px #dddddd solid;
+}
+.tab_bg {
+  background: #f3f9f8;
+}
+
+.icon_box {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 20px;
+  height: 20px;
+  background: #e7f4ec99;
+  border-radius: 50%;
+}
+
+.statistics_box {
+  margin: 15px;
+}
+</style>
\ No newline at end of file
diff --git a/src/pages/routingInspection/list/index.vue b/src/pages/routingInspection/list/index.vue
new file mode 100644
index 0000000..05c3bdf
--- /dev/null
+++ b/src/pages/routingInspection/list/index.vue
@@ -0,0 +1,111 @@
+<template>
+	<view class="card_box">
+		<z-paging ref="pagingRef" v-model="list" :fixed="false" :auto-show-back-to-top="true" @query="getList">
+			<ProductCard v-for="(item, index) in list" :key="index" :data="item" :map="map"
+				@click="toDetail(item.id, item.deviceType)" />
+		</z-paging>
+		<wd-toast />
+	</view>
+</template>
+
+<script setup lang="ts">
+	import ProductCard from "../product_card/index.vue";
+	import { useUserStore } from "@/store/modules/user";
+	import zPaging from "@/components/z-paging/z-paging.vue";
+	import { useToast } from "wot-design-uni";
+
+	const toast = useToast();
+	const userStore = useUserStore();
+	const userInfo : any = computed(() => userStore.userInfo);
+	const pagingRef = ref();
+const map = reactive({
+		deviceModel: "deviceModel",
+		model: "model",
+		firstNo: "firstNo",
+		recordDate: "recordDate",
+		workShift: "workShift",
+		teamName: "teamName",
+		poleModel: "poleModel",
+		poleNumber: "poleNumber",
+		outputNumber: "outputNumber",
+		inspectPerson: "inspectPerson",
+		status: "status",
+    rejectList: [
+      {
+        rejectPerson: "rejectPerson",
+        rejectTime: "rejectTime",
+        rejectReason: {
+          reason: "reason"
+        },
+      },
+		], // 鏀逛负瀵硅薄锛屽寘鍚墍闇�鐨勫祵濂楀睘鎬�
+	});
+	const props = defineProps({
+		api: {
+			type: Function,
+			default: () => { },
+		},
+		ProList: {
+			type: Object,
+			default: () => { },
+		},
+	});
+
+	const list = ref<any[]>([]);
+
+const toDetail = (id: number, deviceType: number) => {
+    console.log('鐐瑰嚮鍗$墖', id, deviceType);
+		toast.show("鐐瑰嚮鍗$墖");
+		if (deviceType == 0) {
+			uni.navigateTo({
+				url: `/pages/production/detail/wireDetail?id=${id}`,
+			});
+		} else if (deviceType == 1) {
+			uni.navigateTo({
+				url: `/pages/production/detail/twistDetail?id=${id}`,
+			});
+		}
+	};
+
+	const getList = async () => {
+		const { code, data } = await props.api({
+			deviceModel: props.ProList.deviceModel,
+			status: "0",
+			deviceType: props.ProList.deviceType,
+		});
+		if (code == 200) {
+      map.deviceModel = "deviceModel";
+			map.model = "model";
+			map.firstNo = "firstNo";
+			map.recordDate = "recordDate";
+			map.workShift = "workShift";
+			map.teamName = "teamName";
+			map.poleModel = "poleModel";
+			map.poleNumber = "poleNumber";
+			map.outputNumber = "outputNumber";
+      map.inspectPerson = "inspectPerson";
+      map.rejectList = [
+        {
+          rejectPerson: "rejectPerson",
+          rejectTime: "rejectTime",
+          rejectReason: {
+            reason: "reason"
+          },
+        },
+      ];
+			map.status = "status";
+			if (data.total == 0) {
+				pagingRef.value.complete(true);
+      } else {
+        console.log('data.records', data.records);
+				pagingRef.value.complete(data.records);
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.card_box {
+		height: calc(100vh - 120px);
+	}
+</style>
\ No newline at end of file
diff --git a/src/pages/routingInspection/product_card/index.vue b/src/pages/routingInspection/product_card/index.vue
new file mode 100644
index 0000000..9b14232
--- /dev/null
+++ b/src/pages/routingInspection/product_card/index.vue
@@ -0,0 +1,205 @@
+<template>
+	<wd-card class="card_bg" @click="handleCardClick">
+		<template #title>
+			<view class="flex justify-between w-full">
+				<text class="font-medium text-[#252525]">鏈哄彴: {{ data[map.deviceModel] }}</text>
+				<wd-tag color="#0D867F" bg-color="#E7F4EC">
+					<text class="text-xs">{{ data[map.model] }}</text>
+				</wd-tag>
+			</view>
+		</template>
+		<wd-row class="my-2">
+			<wd-col :span="24">
+				<view class="flex">
+					<view class="icon_box">
+						<wd-icon name="folder" color="#0D867F"></wd-icon>
+					</view>
+					<text class="text-[#646874] mx-2">
+						棣栨鍗曞彿:
+						<text class="text-[#252525]">{{ data[map.firstNo] }}</text>
+					</text>
+				</view>
+			</wd-col>
+		</wd-row>
+		<wd-row class="my-2">
+			<wd-col :span="24">
+				<view class="flex">
+					<view class="icon_box">
+						<wd-icon name="folder" color="#0D867F"></wd-icon>
+					</view>
+					<text class="text-[#646874] mx-2">
+						鐝:
+						<text class="text-[#252525]">{{ data[map.workShift] }}</text>
+					</text>
+				</view>
+			</wd-col>
+		</wd-row>
+		<wd-row class="my-2">
+			<wd-col :span="24">
+				<view class="flex">
+					<view class="icon_box">
+						<wd-icon name="folder" color="#0D867F"></wd-icon>
+					</view>
+					<text class="text-[#646874] mx-2">
+						鐝粍:
+						<text class="text-[#252525]">{{ data[map.teamName] }}</text>
+					</text>
+				</view>
+			</wd-col>
+		</wd-row>
+		<wd-row class="my-2">
+			<wd-col :span="24">
+				<view class="flex">
+					<view class="icon_box">
+						<wd-icon name="folder" color="#0D867F"></wd-icon>
+					</view>
+					<text class="text-[#646874] mx-2">
+						棰嗙敤鏉嗗彿:
+						<text class="text-[#252525]">{{ data[map.poleNumber] }}</text>
+					</text>
+				</view>
+			</wd-col>
+		</wd-row>
+		<wd-col :span="12">
+			<view class="flex">
+				<view class="icon_box">
+					<wd-icon name="folder" color="#0D867F"></wd-icon>
+				</view>
+				<text class="text-[#646874] mx-2">
+					鏉嗗瀷鍙�:
+					<text class="text-[#252525]">{{ data[map.poleModel] }}</text>
+				</text>
+			</view>
+		</wd-col>
+		<wd-row class="my-2">
+			<wd-col :span="12">
+				<view class="flex">
+					<view class="icon_box">
+						<wd-icon name="folder" color="#0D867F"></wd-icon>
+					</view>
+					<text class="text-[#646874] mx-2">
+						鐢熶骇杞存暟:
+						<text class="text-[#252525]">{{ data[map.outputNumber] }}</text>
+					</text>
+				</view>
+			</wd-col>
+
+		</wd-row>
+		<wd-row class="my-2">
+			<wd-col :span="12">
+				<view class="flex">
+					<view class="icon_box">
+						<wd-icon name="folder" color="#0D867F"></wd-icon>
+					</view>
+					<text class="text-[#646874] mx-2">
+						鑷浜�:
+						<text class="text-[#252525]">{{ data[map.inspectPerson] }}</text>
+					</text>
+				</view>
+			</wd-col>
+			<wd-col :span="12">
+				<view class="flex">
+					<view class="icon_box">
+						<wd-icon name="folder" color="#0D867F"></wd-icon>
+					</view>
+					<text class="text-[#646874] mx-2">
+						鐘舵��:
+						<text class="text-[#252525]">{{ data[map.status] == 1 ? "琚┏鍥�" : "宸℃" }}</text>
+					</text>
+				</view>
+			</wd-col>
+		</wd-row>
+		<wd-row class="my-2">
+			<wd-col :span="16">
+				<view class="flex">
+					<view class="icon_box">
+						<wd-icon name="folder" color="#0D867F"></wd-icon>
+					</view>
+					<text class="text-[#646874] mx-2">
+						璁板綍鏃堕棿:
+						<text class="text-[#252525]">{{ data[map.recordDate] }}</text>
+					</text>
+				</view>
+			</wd-col>
+			<wd-col :span="8">
+				<view class="flex">
+					<wd-button v-if="data[map.status] == 1" size="small" type="primary" @click.stop="showRejectPopup = true"
+						style="margin-left: auto;">
+						鏌ョ湅椹冲洖淇℃伅
+					</wd-button>
+				</view>
+			</wd-col>
+		</wd-row>
+	</wd-card>
+<wd-popup v-model="showRejectPopup" title="椹冲洖淇℃伅" custom-style="border-radius:32rpx;height: 500rpx;width: 600rpx;">
+  <wd-card v-for="(item, index) in data.rejectList" :key="index" 
+           :class="index % 2 === 0 ? 'reject-card-bg-1' : 'reject-card-bg-2'"
+           style="margin-bottom: 15px; padding: 10px; border-radius: 8px;">
+    <view class="content">
+      <view>
+        <view style="display: flex; justify-content: space-between; align-items: center; color: rgba(0,0,0,0.85); font-size: 14px; margin-bottom: 8px;">
+          <view>{{ item.rejectPerson }}</view>
+          <view>{{ item.rejectTime }}</view>
+        </view>
+        <view style="color: rgba(0,0,0,0.85); font-size: 14px; word-break: break-word; overflow-wrap: break-word; max-width: 100%; padding: 5px 0;">
+          {{ item.rejectReason.reason }}
+        </view>
+      </view>
+    </view>
+  </wd-card>
+</wd-popup>
+</template>
+
+<script setup lang="ts">
+import { ref } from "vue";
+const emit = defineEmits(['click']);
+	defineProps({
+		data: {
+			type: Object,
+			default: () => { },
+		},
+		map: {
+			type: Object,
+			default: () => { },
+		},
+	});
+const showRejectPopup = ref<boolean>(false)
+const handleCardClick = () => {
+  emit('click');
+};
+</script>
+
+<style lang="scss" scoped>
+  .card_bg {
+    box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.05);
+    padding-bottom: 10px;
+  }
+
+  // 娣诲姞锛氫袱绉嶄笉鍚岀殑鑳屾櫙鑹叉牱寮�
+  .reject-card-bg-1 {
+    background-color: #f5f7fa;
+  }
+  
+  .reject-card-bg-2 {
+    background-color: #eef2f7;
+  }
+
+  .page-class {
+    :deep() {
+      .custom-shadow {
+        box-shadow: 0 3px 1px -2px rgb(0 0 0 / 20%), 0 2px 2px 0 rgb(0 0 0 / 14%), 0 1px 5px 0 rgb(0 0 0 / 12%);
+      }
+    }
+  }
+
+  .header {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+  }
+
+  // 淇敼锛氳皟鏁村唴瀹瑰尯鍩熺殑鏍峰紡
+  .content {
+    padding: 5px;
+  }
+</style>
\ No newline at end of file
diff --git a/src/static/icons/routingInspection.png b/src/static/icons/routingInspection.png
new file mode 100644
index 0000000..e8bb5a4
--- /dev/null
+++ b/src/static/icons/routingInspection.png
Binary files differ

--
Gitblit v1.9.3