Просмотр исходного кода

feat: 添加批量操作功能到检查页面

在检查页面中添加批量选择、全选和批量设置状态功能,包括批量操作弹窗和选择状态栏
yusheng 3 месяцев назад
Родитель
Сommit
73a9c79d05

+ 4 - 0
pages/maintenance/check/components/CheckCard.vue

@@ -1,6 +1,7 @@
 <template>
 	<view class="kd-check-card">
 		<view class="title">
+			<checkbox color="#fff" @click="checkboxChange(item)"   :checked="item.checked" />
 			<text class="label">{{ index + 1 }}</text>
 			<text>{{ item.name }}</text>
 		</view>
@@ -142,6 +143,9 @@
 			}
 		},
 		methods: {
+			checkboxChange(item) {
+				item.checked = !item.checked
+			},
 			// inputChange(obj, item) {
 			// 	if (obj.target.value.length > 0 && obj.target.value != '正常') {
 			// 		item.status = -1

+ 266 - 3
pages/maintenance/check/index.vue

@@ -10,6 +10,27 @@
 				{{ equiName }}
 				<text>{{ equiCode }}</text>
 			</view>
+			<!-- 选择状态栏 -->
+			<view class="select-bar" v-if="showSelectBar">
+				<view class="select-actions">
+					<view class="select-all" @click="selectAll">
+						<checkbox :checked="allSelected" color="#157a2c" />
+						<text>{{ allSelected ? '取消全选' : '全选' }}</text>
+					</view>
+					<view class="selected-count">
+						<text>已选择 {{ selectedCount }} 项</text>
+					</view>
+				</view>
+				<view class="batch-btn" @click="openBatchDialog" :class="{ disabled: selectedCount === 0 }">
+					<text>批量操作</text>
+				</view>
+				<view class="close-select" @click="closeSelectBar">
+					<text>取消选择</text>
+				</view>
+			</view>
+			<view class="batch-trigger" @click="openSelectBar" v-if="!showSelectBar">
+				<text>批量操作</text>
+			</view>
 			<view class="check-list">
 				<CheckCard v-for="(item, index) in equipList" :item="item" class="mb20" :index="index"></CheckCard>
 			</view>
@@ -18,6 +39,31 @@
 				<view class="btn primary" @click="handleSave">保存</view>
 			</view>
 		</view>
+
+		<!-- 批量操作弹窗 -->
+		<uni-popup ref="batchPopup" type="bottom">
+			<view class="batch-popup-content">
+				<view class="popup-header">
+					<text class="header-title">批量操作</text>
+					<view class="close-btn" @click="closeBatchPopup">
+						<text class="close-icon">×</text>
+					</view>
+				</view>
+				<view class="popup-body">
+					<view class="select-info">
+						<text>已选择 {{ selectedCount }} 项</text>
+					</view>
+					<view class="action-btn status-btn" @click="batchSetStatus(1)">
+						<text class="status-icon normal-icon">✓</text>
+						<text>批量设为正常</text>
+					</view>
+					<view class="action-btn status-btn" @click="batchSetStatus(-1)">
+						<text class="status-icon abnormal-icon">✗</text>
+						<text>批量设为异常</text>
+					</view>
+				</view>
+			</view>
+		</uni-popup>
 		<u-modal :show.sync="visible" class="maintenance-order" :showCancelButton="true" @confirm="confirm"
 			@cancel="cancel" :closeOnClickOverlay="true">
 			<view class="" style="flex: 1">
@@ -68,7 +114,14 @@
 				workOrderId: '',
 				applyEquiPartList: [],
 				originList: [],
-				workOrderCode: ''
+				workOrderCode: '',
+				showSelectBar: false,
+				allSelected: false
+			}
+		},
+		computed: {
+			selectedCount() {
+				return this.equipList.filter(item => item.checked).length
 			}
 		},
 		onLoad(options) {
@@ -262,6 +315,64 @@
 					})
 			},
 
+			// 打开选择栏
+			openSelectBar() {
+				this.showSelectBar = true
+			},
+			// 关闭选择栏
+			closeSelectBar() {
+				this.showSelectBar = false
+				this.equipList.forEach(item => {
+					item.checked = false
+				})
+				this.allSelected = false
+			},
+			// 全选/取消全选
+			selectAll() {
+				this.allSelected = !this.allSelected
+				this.equipList.forEach(item => {
+					item.checked = this.allSelected
+				})
+			},
+			// 打开批量操作弹窗
+			openBatchDialog() {
+				if (this.selectedCount === 0) {
+					uni.showToast({
+						title: '请先选择要操作的项目',
+						icon: 'none'
+					})
+					return
+				}
+				this.$refs.batchPopup.open()
+			},
+			// 关闭批量操作弹窗
+			closeBatchPopup() {
+				this.$refs.batchPopup.close()
+			},
+			// 批量设置状态
+			batchSetStatus(status) {
+				const statusText = status === 1 ? '正常' : '异常'
+				uni.showModal({
+					title: '确认提示',
+					content: `确认将选中的 ${this.selectedCount} 项设置为${statusText}吗?`,
+					success: (res) => {
+						if (res.confirm) {
+							this.equipList.forEach(item => {
+								if (item.checked) {
+									item.status = status
+									item.result = statusText
+								}
+							})
+							uni.showToast({
+								title: '批量设置成功',
+								icon: 'success'
+							})
+							this.closeBatchPopup()
+							this.closeSelectBar()
+						}
+					}
+				})
+			},
 			getList() {
 				getDeviceInfo({
 					id: this.id
@@ -274,7 +385,8 @@
 							id: data.id,
 							status: 1,
 							result: '正常',
-							executeStatus: 1
+							executeStatus: 1,
+							checked: false
 						}
 					})
 				})
@@ -326,7 +438,7 @@
 			width: 100vw;
 			border: 1rpx solid $j-primary-border-green;
 			background: #fff;
-			z-index: 100;
+			z-index: 99;
 
 			.btn {
 				display: flex;
@@ -345,6 +457,71 @@
 		.mb20 {
 			margin-bottom: 20rpx;
 		}
+
+		.batch-trigger {
+			padding: 20rpx 30rpx;
+			text-align: right;
+
+			text {
+				background-color: #157a2c;
+				color: #fff;
+				padding: 10rpx 30rpx;
+				border-radius: 8rpx;
+				font-size: 28rpx;
+			}
+		}
+
+		.select-bar {
+			background-color: #f5f5f5;
+			padding: 20rpx 30rpx;
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			border-bottom: 1rpx solid #e0e0e0;
+
+			.select-actions {
+				display: flex;
+				align-items: center;
+				flex: 1;
+
+				.select-all {
+					display: flex;
+					align-items: center;
+					margin-right: 20rpx;
+
+					text {
+						margin-left: 10rpx;
+						font-size: 28rpx;
+					}
+				}
+
+				.selected-count {
+					font-size: 28rpx;
+					color: #666;
+				}
+			}
+
+			.batch-btn {
+				background-color: #157a2c;
+				color: #fff;
+				padding: 10rpx 30rpx;
+				border-radius: 8rpx;
+				font-size: 28rpx;
+				margin: 0 10rpx;
+
+				&.disabled {
+					background-color: #ccc;
+					opacity: 0.6;
+				}
+			}
+
+			.close-select {
+				padding: 10rpx 20rpx;
+				background-color: #fff;
+				border-radius: 8rpx;
+				font-size: 28rpx;
+			}
+		}
 	}
 
 	.nav-right {
@@ -392,4 +569,90 @@
 			}
 		}
 	}
+
+	.batch-popup-content {
+		background-color: #fff;
+		border-radius: 20rpx 20rpx 0 0;
+		padding: 30rpx;
+		z-index: 1000;
+
+		.popup-header {
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			padding-bottom: 30rpx;
+			border-bottom: 1rpx solid #e0e0e0;
+
+			.header-title {
+				font-size: 36rpx;
+				font-weight: bold;
+				color: #333;
+			}
+
+			.close-btn {
+				width: 60rpx;
+				height: 60rpx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+
+				.close-icon {
+					font-size: 60rpx;
+					color: #999;
+					line-height: 1;
+				}
+			}
+		}
+
+		.popup-body {
+			padding: 30rpx 0;
+
+			.select-info {
+				padding: 20rpx 0;
+				text-align: center;
+				color: #666;
+				font-size: 28rpx;
+			}
+
+			.action-btn {
+				display: flex;
+				align-items: center;
+				padding: 25rpx 30rpx;
+				margin: 0 0 20rpx 0;
+				background-color: #f5f5f5;
+				border-radius: 12rpx;
+				font-size: 30rpx;
+
+				&:active {
+					background-color: #e0e0e0;
+				}
+
+				text {
+					margin-left: 20rpx;
+				}
+			}
+
+			.status-btn {
+				.status-icon {
+					width: 40rpx;
+					height: 40rpx;
+					border-radius: 50%;
+					display: flex;
+					align-items: center;
+					justify-content: center;
+					font-size: 28rpx;
+					color: #fff;
+					margin-left: 0;
+				}
+
+				.normal-icon {
+					background-color: #157a2c;
+				}
+
+				.abnormal-icon {
+					background-color: #ff4444;
+				}
+			}
+		}
+	}
 </style>

+ 299 - 280
pages/tour_tally/check/components/CheckCard.vue

@@ -1,19 +1,24 @@
 <template>
-	<view class="kd-check-card">
-		<view class="title">
-			<checkbox :value="item.id" color="#fff" />
-			<text class="label">{{ index + 1 }}</text>
-			<text>{{ item.name }}</text>
-		</view>
-		<view class="card-cell">
-			<text class="label">内容</text>
-			<text class="cell-content">{{ item.content }}</text>
-		</view>
-		<view class="card-cell">
-			<text class="label">标准</text>
-			<text class="cell-content">{{ item.norm }}</text>
-		</view>
-		<!-- <view class="card-cell">
+  <view class="kd-check-card">
+    <view class="title">
+      <checkbox
+        :value="item.id"
+        color="#fff"
+        @click="checkboxChange(item)"
+        :checked="item.checked"
+      />
+      <text class="label">{{ index + 1 }}</text>
+      <text>{{ item.name }}</text>
+    </view>
+    <view class="card-cell">
+      <text class="label">内容</text>
+      <text class="cell-content">{{ item.content }}</text>
+    </view>
+    <view class="card-cell">
+      <text class="label">标准</text>
+      <text class="cell-content">{{ item.norm }}</text>
+    </view>
+    <!-- <view class="card-cell">
 			<text class="label">工具</text>
 			<view class="cell-content" v-if="item.operationGuide && item.operationGuide.toolList.length > 0">
 				<view v-for="(item, index) in item.operationGuide.toolList">{{ index + 1 }}、{{ item.categoryLevelName }}</view>
@@ -27,30 +32,37 @@
 			</view>
 			<view class="cell-content" v-else>无</view>
 		</view> -->
-		<view class="card-cell">
-			<text class="label">状态</text>
-			<text class="cell-content">
-
-				<view v-if="type == 'view'">
-					<div v-if="item.status == -1" style="color: red">异常</div>
-					<div v-else style="color: green">正常</div>
-				</view>
-				<view v-else>
-					<uni-data-picker @change="statusChange" style="width:100%" v-model="item.status" placeholder="请选择"
-						:localdata="statusList" :clear-icon="false">
-					</uni-data-picker>
-				</view>
-			</text>
-		</view>
-		<view class="card-cell">
-			<text class="label">结果</text>
-			<view class="cell-content">
-
-				<textarea v-if="type !== 'view'" placeholder="请输入" v-model="item.result"
-					 />
-				<view class="result-text" v-else>{{ item.result }}</view>
-				<view class="radio-wrapper">
-					<!-- <div
+    <view class="card-cell">
+      <text class="label">状态</text>
+      <text class="cell-content">
+        <view v-if="type == 'view'">
+          <div v-if="item.status == -1" style="color: red">异常</div>
+          <div v-else style="color: green">正常</div>
+        </view>
+        <view v-else>
+          <uni-data-picker
+            @change="statusChange"
+            style="width: 100%"
+            v-model="item.status"
+            placeholder="请选择"
+            :localdata="statusList"
+            :clear-icon="false"
+          >
+          </uni-data-picker>
+        </view>
+      </text>
+    </view>
+    <view class="card-cell">
+      <text class="label">结果</text>
+      <view class="cell-content">
+        <textarea
+          v-if="type !== 'view'"
+          placeholder="请输入"
+          v-model="item.result"
+        />
+        <view class="result-text" v-else>{{ item.result }}</view>
+        <view class="radio-wrapper">
+          <!-- <div
 						v-for="(it, ind) in statusList"
 						:key="ind"
 						v-if="type !== 'view'"
@@ -59,7 +71,7 @@
 						:style="item.status == it.status && item.status == -1 ? 'color:red;border: 1rpx solid red' : item.status == it.status && item.status == 0 ? 'color:green;border: 1rpx solid green' : ''">
 						{{ it.label }}
 					</div> -->
-					<!-- <u-radio-group
+          <!-- <u-radio-group
             v-model="item.executeStatus"
             placement="row"
             v-if="type !== 'view'"
@@ -75,275 +87,282 @@
             <u-radio :customStyle="{}" :labelSize="30" label="异常" :name="0">
             </u-radio>
           </u-radio-group> -->
-					<!-- <view
+          <!-- <view
             :class="item.executeStatus === 0 ? 'text-danger' : ''"
             v-else
             style="min-height: 1em"
           >
             {{ ['异常', '正常'][item.executeStatus] }}
           </view> -->
-				</view>
-			</view>
-		</view>
-		<!-- 新增拍照 *** -->
-		<view class="card-cell">
-			<text class="label">
-				<span class="mark"></span>
-			</text>
-			<view class="photo_info">
-				<view class="btn_box" v-if="type != 'view'">
-					<text class="photo_btn" @click="chooseImage">拍照</text>
-				</view>
-				<view class="photo_list">
-					<PreviewPhoto :type="type" @imagedelete="imagedelete" :imageList="photoList" />
-				</view>
-			</view>
-		</view>
-		<u-toast ref="uToast"></u-toast>
-	</view>
+        </view>
+      </view>
+    </view>
+    <!-- 新增拍照 *** -->
+    <view class="card-cell">
+      <text class="label">
+        <span class="mark"></span>
+      </text>
+      <view class="photo_info">
+        <view class="btn_box" v-if="type != 'view'">
+          <text class="photo_btn" @click="chooseImage">拍照</text>
+        </view>
+        <view class="photo_list">
+          <PreviewPhoto
+            :type="type"
+            @imagedelete="imagedelete"
+            :imageList="photoList"
+          />
+        </view>
+      </view>
+    </view>
+    <u-toast ref="uToast"></u-toast>
+  </view>
 </template>
 
 <script>
-	import PreviewPhoto from '@/pages/maintenance/check/components/PreviewPhoto.vue'
-	export default {
-		components: {
-			PreviewPhoto
-		},
-		props: {
-			item: {
-				type: Object,
-				default: () => ({})
-			},
-			index: Number,
-			type: {
-				type: String,
-				default: 'edit'
-			}
-		},
-		data() {
-			return {
-				statusList: [{
-						text: '正常',
-						value: 1
-					},
-					{
-						text: '异常',
-						value: -1
-					}
-				]
-			}
-		},
-		// *** 新增
-		computed: {
-			photoList() {
-				if (!this.item.photoList) return []
-				return this.item.photoList
-			}
-		},
-		methods: {
-			// inputChange(obj, item) {
-			// 	if (obj.target.value.length > 0 && obj.target.value != '正常') {
-			// 		item.status = -1
-			// 	} else {
-			// 		item.status = 1
-			// 	}
-			// },
-			statusChange() {
-				if (this.item.status == 1) {
-					this.item.result = '正常'
-				} else {
-					this.item.result = '异常'
-				}
-
-			},
-
-			// *** 新增拍照功能
-			chooseImage() {
-				const _this = this
-				if (_this.photoList.length >= 9) {
-					_this.$refs.uToast.show({
-						type: "warning",
-						message: "最多上传9张照片",
-					})
-					return
-				}
-				uni.chooseImage({
-					count: 9, //默认9
-					sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
-					sourceType: ['camera'], //从相册选择
-					success: function(res) {
-						uni.showLoading({
-							title: '加载中'
-						})
+import PreviewPhoto from "@/pages/maintenance/check/components/PreviewPhoto.vue";
+export default {
+  components: {
+    PreviewPhoto,
+  },
+  props: {
+    item: {
+      type: Object,
+      default: () => ({}),
+    },
+    index: Number,
+    type: {
+      type: String,
+      default: "edit",
+    },
+  },
+  data() {
+    return {
+      statusList: [
+        {
+          text: "正常",
+          value: 1,
+        },
+        {
+          text: "异常",
+          value: -1,
+        },
+      ],
+    };
+  },
+  // *** 新增
+  computed: {
+    photoList() {
+      if (!this.item.photoList) return [];
+      return this.item.photoList;
+    },
+  },
+  methods: {
+    checkboxChange(item) {
+      item.checked = !item.checked;
+    },
+    // inputChange(obj, item) {
+    // 	if (obj.target.value.length > 0 && obj.target.value != '正常') {
+    // 		item.status = -1
+    // 	} else {
+    // 		item.status = 1
+    // 	}
+    // },
+    statusChange() {
+      if (this.item.status == 1) {
+        this.item.result = "正常";
+      } else {
+        this.item.result = "异常";
+      }
+    },
 
-						_this.uploadFile(res.tempFilePaths).then(res => {
-							res.forEach(item => {
-								let fileNames = item.storePath.split('/')
-								let url = _this.apiUrl +
-									'/main/file/getFile?objectName=' + item.storePath +
-									'&fullfilename=' + fileNames[fileNames.length -
-										1]
-								console.log(_this.item, 'url ---')
-								if (!_this.item.photoList || _this.item.photoList?.length ==
-									0) {
-									_this.$set(_this.item, 'photoList', [url])
-								} else {
-									// 不能存储超过 9 张
-									if (_this.item.photoList.length < 9) {
-										_this.item.photoList.push(url);
-									}
-								}
-								// _this.imgs.push(url)
-							})
-							uni.hideLoading()
+    // *** 新增拍照功能
+    chooseImage() {
+      const _this = this;
+      if (_this.photoList.length >= 9) {
+        _this.$refs.uToast.show({
+          type: "warning",
+          message: "最多上传9张照片",
+        });
+        return;
+      }
+      uni.chooseImage({
+        count: 9, //默认9
+        sizeType: ["original", "compressed"], //可以指定是原图还是压缩图,默认二者都有
+        sourceType: ["camera"], //从相册选择
+        success: function (res) {
+          uni.showLoading({
+            title: "加载中",
+          });
 
-						})
-					}
-				});
-			},
-			uploadFile(list) {
-				let PromiseAll = []
-				const apiUrl = this.apiUrl
-				const token = uni.getStorageSync("token"); //取存本地的token
-				list.forEach(item => {
-					PromiseAll.push(
-						new Promise((resolve, reject) => {
-							uni.uploadFile({
-								url: apiUrl + '/main/file/upload',
-								filePath: item,
-								name: 'multiPartFile',
-								header: {
-									authorization: token
-								},
-								success: (uploadFileRes) => {
-									let data = JSON.parse(uploadFileRes.data)
-									resolve(data.data)
-								}
-							});
-						}),
-					)
-				})
-				return Promise.all(PromiseAll)
-			},
-			// 图片删除
-			imagedelete(index) {
-				this.item.photoList.splice(index, 1);
-			},
-		}
-	}
+          _this.uploadFile(res.tempFilePaths).then((res) => {
+            res.forEach((item) => {
+              let fileNames = item.storePath.split("/");
+              let url =
+                _this.apiUrl +
+                "/main/file/getFile?objectName=" +
+                item.storePath +
+                "&fullfilename=" +
+                fileNames[fileNames.length - 1];
+              console.log(_this.item, "url ---");
+              if (!_this.item.photoList || _this.item.photoList?.length == 0) {
+                _this.$set(_this.item, "photoList", [url]);
+              } else {
+                // 不能存储超过 9 张
+                if (_this.item.photoList.length < 9) {
+                  _this.item.photoList.push(url);
+                }
+              }
+              // _this.imgs.push(url)
+            });
+            uni.hideLoading();
+          });
+        },
+      });
+    },
+    uploadFile(list) {
+      let PromiseAll = [];
+      const apiUrl = this.apiUrl;
+      const token = uni.getStorageSync("token"); //取存本地的token
+      list.forEach((item) => {
+        PromiseAll.push(
+          new Promise((resolve, reject) => {
+            uni.uploadFile({
+              url: apiUrl + "/main/file/upload",
+              filePath: item,
+              name: "multiPartFile",
+              header: {
+                authorization: token,
+              },
+              success: (uploadFileRes) => {
+                let data = JSON.parse(uploadFileRes.data);
+                resolve(data.data);
+              },
+            });
+          }),
+        );
+      });
+      return Promise.all(PromiseAll);
+    },
+    // 图片删除
+    imagedelete(index) {
+      this.item.photoList.splice(index, 1);
+    },
+  },
+};
 </script>
 
 <style lang="scss" scoped>
-	$border-color: #f2f2f2;
+$border-color: #f2f2f2;
 
-	.kd-check-card {
-		font-size: 28rpx;
-		border: 1rpx solid $border-color;
+.kd-check-card {
+  font-size: 28rpx;
+  border: 1rpx solid $border-color;
 
-		.label {
-			display: inline-block;
-			width: 80rpx;
-			text-align: center;
-			border-right: 1px solid $border-color;
-			justify-content: center;
-		}
+  .label {
+    display: inline-block;
+    width: 80rpx;
+    text-align: center;
+    border-right: 1px solid $border-color;
+    justify-content: center;
+  }
 
-		.mark {
-			width: 80rpx;
-			height: 4rpx;
-			display: inline-block;
-		}
+  .mark {
+    width: 80rpx;
+    height: 4rpx;
+    display: inline-block;
+  }
 
-		.title {
-			line-height: 72rpx;
-			font-weight: bold;
-			background-color: #f2f2f2;
-		}
+  .title {
+    line-height: 72rpx;
+    font-weight: bold;
+    background-color: #f2f2f2;
+  }
 
-		.card-cell {
-			min-height: 72rpx;
-			display: flex;
-			align-items: stretch;
-			border: 1px solid $border-color;
+  .card-cell {
+    min-height: 72rpx;
+    display: flex;
+    align-items: stretch;
+    border: 1px solid $border-color;
 
-			text {
-				display: flex;
-				align-items: center;
-			}
-		}
+    text {
+      display: flex;
+      align-items: center;
+    }
+  }
 
-		.cell-content {
-			flex: 1;
+  .cell-content {
+    flex: 1;
 
-			/deep/span {
-				width: 100%;
-			}
+    /deep/span {
+      width: 100%;
+    }
 
-			.content-status {
-				width: 100%;
-				height: 50rpx;
-				line-height: 50rpx;
-				text-indent: 10rpx;
-				border-bottom: 1rpx solid #f2f2f2;
-			}
-		}
+    .content-status {
+      width: 100%;
+      height: 50rpx;
+      line-height: 50rpx;
+      text-indent: 10rpx;
+      border-bottom: 1rpx solid #f2f2f2;
+    }
+  }
 
-		.radio-wrapper {
-			padding: 10rpx 20rpx;
-			border-bottom: 1px solid $border-color;
-			margin-left: -8rpx;
-		}
+  .radio-wrapper {
+    padding: 10rpx 20rpx;
+    border-bottom: 1px solid $border-color;
+    margin-left: -8rpx;
+  }
 
-		/deep/uni-textarea {
-			width: 100%;
-			box-sizing: border-box;
-		}
+  /deep/uni-textarea {
+    width: 100%;
+    box-sizing: border-box;
+  }
 
-		.result-text {
-			min-height: 100rpx;
-			padding: 10rpx;
-		}
+  .result-text {
+    min-height: 100rpx;
+    padding: 10rpx;
+  }
 
-		.cell-content {
-			padding-left: 8rpx;
-		}
+  .cell-content {
+    padding-left: 8rpx;
+  }
 
-		.radio-wrapper {
-			display: flex;
-			align-items: center;
-			justify-content: space-around;
-		}
+  .radio-wrapper {
+    display: flex;
+    align-items: center;
+    justify-content: space-around;
+  }
 
-		.wrapper-box {
-			width: 45%;
-			height: 80rpx;
-			line-height: 80rpx;
-			text-align: center;
-			border: 1rpx solid #000;
-			color: #000;
-			border-radius: 15rpx;
-		}
-	}
+  .wrapper-box {
+    width: 45%;
+    height: 80rpx;
+    line-height: 80rpx;
+    text-align: center;
+    border: 1rpx solid #000;
+    color: #000;
+    border-radius: 15rpx;
+  }
+}
 
-	.photo_info {
-		width: 100%;
-		padding: 6px 12rpx;
+.photo_info {
+  width: 100%;
+  padding: 6px 12rpx;
 
-		.btn_box {
-			width: 100%;
-		}
+  .btn_box {
+    width: 100%;
+  }
 
-		.photo_btn {
-			background-color: #157a2c;
-			width: 140rpx;
-			height: 60rpx;
-			line-height: 60rpx;
-			font-size: 24rpx;
-			color: #fff;
-			text-align: center;
-			border-radius: 8rpx;
-			margin-bottom: 12rpx;
-			display: inline-block !important;
-		}
-	}
-</style>
+  .photo_btn {
+    background-color: #157a2c;
+    width: 140rpx;
+    height: 60rpx;
+    line-height: 60rpx;
+    font-size: 24rpx;
+    color: #fff;
+    text-align: center;
+    border-radius: 8rpx;
+    margin-bottom: 12rpx;
+    display: inline-block !important;
+  }
+}
+</style>

+ 610 - 334
pages/tour_tally/check/index.vue

@@ -1,8 +1,14 @@
 <template>
-	<view>
-		<uni-nav-bar fixed="true" statusBar="true" left-icon="back" title="检查中" @clickLeft="back"></uni-nav-bar>
+  <view>
+    <uni-nav-bar
+      fixed="true"
+      statusBar="true"
+      left-icon="back"
+      title="检查中"
+      @clickLeft="back"
+    ></uni-nav-bar>
 
-<!-- 		<view class="top-wrapper">
+    <!-- 		<view class="top-wrapper">
 			<uni-section>
 				<uni-easyinput prefixIcon="search" style="width: 460rpx" v-model="keyWords" placeholder="请输入">
 				</uni-easyinput>
@@ -15,340 +21,610 @@
 
 		</view> -->
 
-		<view class="check-content">
-			<view class="title">
-				{{ equiName }}
-				<text>{{ equiCode }}</text>
-			</view>
-			<view class="check-list" ref="scrollContainer">
-
-				<view v-for="(item,index) in filterList">
-					<CheckCard :item="item" class="mb20" :index="index" ref="CheckCardRef"></CheckCard>
-				</view>
-			</view>
-			<view class="footer">
-
-
-				<view class="btn" @click="back">返回</view>
-				<view class="btn primary" @click="handleSave">保存</view>
-			</view>
-		</view>
-
-		<uni-popup ref="inputDialog" type="dialog">
-			<uni-popup-dialog ref="inputClose" mode="input" title="您当前已超出计划完成时间,请填写原因" placeholder="请输入内容"
-				:before-close="true" @close="handleClose" @confirm="timeoutCauseConfirm"></uni-popup-dialog>
-		</uni-popup>
-	</view>
+    <view class="check-content">
+      <view class="title">
+        {{ equiName }}
+        <text>{{ equiCode }}</text>
+      </view>
+      <!-- 选择状态栏 -->
+      <view class="select-bar" v-if="showSelectBar">
+        <view class="select-actions">
+          <view class="select-all" @click="selectAll">
+            <checkbox :checked="allSelected" color="#157a2c" />
+            <text>{{ allSelected ? "取消全选" : "全选" }}</text>
+          </view>
+          <view class="selected-count">
+            <text>已选择 {{ selectedCount }} 项</text>
+          </view>
+        </view>
+        <view
+          class="batch-btn"
+          @click="openBatchDialog"
+          :class="{ disabled: selectedCount === 0 }"
+        >
+          <text>批量操作</text>
+        </view>
+        <view class="close-select" @click="closeSelectBar">
+          <text>取消选择</text>
+        </view>
+      </view>
+      <view class="batch-trigger" @click="openSelectBar" v-if="!showSelectBar">
+        <text>批量操作</text>
+      </view>
+      <view class="check-list" ref="scrollContainer">
+        <view v-for="(item, index) in filterList">
+          <CheckCard
+            :item="item"
+            class="mb20"
+            :index="index"
+            ref="CheckCardRef"
+          ></CheckCard>
+        </view>
+      </view>
+      <view class="footer">
+        <view class="btn" @click="back">返回</view>
+        <view class="btn primary" @click="handleSave">保存</view>
+      </view>
+    </view>
+
+    <!-- 批量操作弹窗 -->
+    <uni-popup ref="batchPopup" type="bottom">
+      <view class="batch-popup-content">
+        <view class="popup-header">
+          <text class="header-title">批量操作</text>
+          <view class="close-btn" @click="closeBatchPopup">
+            <text class="close-icon">×</text>
+          </view>
+        </view>
+        <view class="popup-body">
+          <view class="select-info">
+            <text>已选择 {{ selectedCount }} 项</text>
+          </view>
+          <view class="action-btn status-btn" @click="batchSetStatus(1)">
+            <text class="status-icon normal-icon">✓</text>
+            <text>批量设为正常</text>
+          </view>
+          <view class="action-btn status-btn" @click="batchSetStatus(-1)">
+            <text class="status-icon abnormal-icon">✗</text>
+            <text>批量设为异常</text>
+          </view>
+        </view>
+      </view>
+    </uni-popup>
+
+    <uni-popup ref="inputDialog" type="dialog">
+      <uni-popup-dialog
+        ref="inputClose"
+        mode="input"
+        title="您当前已超出计划完成时间,请填写原因"
+        placeholder="请输入内容"
+        :before-close="true"
+        @close="handleClose"
+        @confirm="timeoutCauseConfirm"
+      ></uni-popup-dialog>
+    </uni-popup>
+  </view>
 </template>
 
 <script>
-	import {
-		getDeviceInfo,
-		mattersChecked
-	} from '@/api/myTicket/index.js'
-	import {
-		post,
-		postJ
-	} from '@/utils/api.js'
-	import CheckCard from './components/CheckCard.vue'
-	export default {
-		components: {
-			CheckCard
-		},
-		data() {
-			return {
-				keyWords: '',
-				id: '',
-				pageId: '',
-				page: 1,
-				equipList: [],
-				filterList: [],
-				isEnd: false,
-				equiName: '',
-				equiCode: '',
-				workOrderId: '',
-				workOrderCode: ''
-			}
-		},
-		onLoad(options) {
-			this.id = options.id
-			this.keyWords = options.codes
-			this.getList()
-			//   this.pageId = options.id
-			//   this.equiName = options.equiName
-			//   this.equiCode = options.equiCode
-			//   this.workOrderId = +options.workOrderId
-			// this.workOrderCode = options.workOrderCode
-		},
-		// onReachBottom() {
-		// 	if (this.isEnd) return
-		// 	this.page++
-		// 	this.getList()
-		// },
-		methods: {
-			back() {
-				uni.navigateBack({
-					delta: 1
-				})
-			},
-			doSearch() {
-				if (!this.keyWords) {
-					this.filterList = this.equipList;
-				} else {
-					this.filterList = this.equipList.filter(item =>
-						item.categoryCode.includes(this.keyWords)
-					);
-				}
-			},
-			handleSave() {
-				let isAllPass = true
-				isAllPass = this.equipList.every(item => item.status > -1)
-				let params = {
-					id: this.equipList[0].id,
-					executeStatus: isAllPass ? 1 : 2,
-					isAbnormal: isAllPass ? 1 : 0,
-					workItems: this.equipList.map(item => {
-						return {
-							content: item.content,
-							name: item.name,
-							norm: item.norm,
-							operationGuide: item.operationGuide,
-							result: item.result,
-							serialNum: item.serialNum,
-							status: item.status == -1 ? -1 : 1,
-							photoList: item.photoList || []
-						}
-					})
-				}
-				mattersChecked(params).then(data => {
-					uni.showToast({
-						duration: 2000,
-						title: '保存成功!'
-					})
-					this.back()
-				})
-				// let _this = this
-				// const params = {
-				// 	itemList: this.equipList,
-				// 	planEquiId: this.pageId,
-				// 	workOrderId: +this.workOrderId,
-				// 	workOrderType: 1
-				// }
-				// postJ(this.apiUrl + `/workOrder/itemsInspect`, params, true).then(res => {
-				// 	if (res?.success) {
-				// 		if (res.data) {
-				// 			uni.showModal({
-				// 				title: '提示',
-				// 				content: '所有设备已执行完,是否报工?',
-				// 				cancelText: '取消', // 取消按钮的文字
-				// 				confirmText: '报工', // 确认按钮的文字
-				// 				showCancel: true, // 是否显示取消按钮,默认为 true
-				// 				success: res => {
-				// 					if (res.confirm) {
-				// 						_this._report()
-				// 					} else {
-				// 						_this.back()
-				// 					}
-				// 				}
-				// 			})
-				// 		} else {
-				// 			uni.showToast({
-				// 				duration: 2000,
-				// 				title: '保存成功!'
-				// 			})
-				// 			this.back()
-				// 		}
-				// 	}
-				// })
-			},
-
-			handleClose() {
-				this.$refs.inputDialog.close()
-			},
-			timeoutCauseConfirm(value) {
-				if (!value) {
-					uni.showToast({
-						title: '请输入超时原因',
-						icon: 'none'
-					})
-					return
-				}
-				this.$refs.inputDialog.close()
-				this._report(value)
-			},
-			_report(timeoutCause = '') {
-				let _this = this
-				post(
-						this.apiUrl + '/workOrder/reportWork', {
-							workOrderId: this.workOrderId,
-							timeoutCause
-						},
-						true,
-						false
-					)
-					.then(res => {
-						if (res?.success) {
-							let data = res.data
-							if (data.length) {
-								uni.showModal({
-									title: '提示',
-									content: `有${data.length}台设备被标记为缺陷,是否要报修?`,
-									cancelText: '取消', // 取消按钮的文字
-									confirmText: '报修', // 确认按钮的文字
-									showCancel: true, // 是否显示取消按钮,默认为 true
-									success: res => {
-										if (res.confirm) {
-											if (data.length > 1) {
-												uni.navigateTo({
-													url: `/pages/tour_tally/detail/detail?workOrderCode=${this.workOrderCode}&id=${this.workOrderId}&chooseTab=true`
-												})
-											} else {
-												uni.navigateTo({
-													url: `/pages/repair/repair/index?source=5&workOrderCode=${this.workOrderCode}&equiCode=${data[0].equiCode}&equiId=${data[0].equiId}&workOrderId=${this.pageId}&equiName=${data[0].equiName}&equiModel=${data[0].equiModel}&equiLocation=${data[0].equiLocation}`
-												})
-											}
-										} else {
-											_this.back()
-										}
-									}
-								})
-							} else {
-								uni.showToast({
-									icon: 'success',
-									title: '操作成功!',
-									duration: 2000
-								})
-								_this.back()
-							}
-						}
-					})
-					.catch(res => {
-						if (res.code === '4444') {
-							this.$refs.inputDialog.open()
-						}
-					})
-			},
-
-			getList() {
-				getDeviceInfo({
-					id: this.id
-				}).then(data => {
-					this.equiName = data.name
-					this.equiCode = data.code
-					this.equipList = data.workItems.map(item => {
-						return {
-							...item,
-							id: data.id,
-							status:1,
-							result:'正常',
-							executeStatus: 1
-						}
-					})
-					this.doSearch()
-				})
-				// const { page } = this
-				// post(this.apiUrl + `/workOrder/getEquipmentItemsListApp?size=10&page=${page}`, { planEquiId: +this.pageId, workOrderId: this.workOrderId }, true).then(res => {
-				// 	if (res?.success) {
-				// 		res.data.records.forEach(item => {
-				// 			item.isNormal = item.isNormal === null || item.isNormal === undefined ? 1 : item.isNormal
-				// 		})
-				// 		if (page === 1) {
-				// 			this.equipList = res.data.records
-				// 		} else {
-				// 			this.equipList.push(...res.data.records)
-				// 		}
-
-				// 		this.isEnd = this.equipList.length >= res.data.total
-				// 	}
-				// })
-			}
-		}
-	}
+import { getDeviceInfo, mattersChecked } from "@/api/myTicket/index.js";
+import { post, postJ } from "@/utils/api.js";
+import CheckCard from "./components/CheckCard.vue";
+export default {
+  components: {
+    CheckCard,
+  },
+  data() {
+    return {
+      keyWords: "",
+      id: "",
+      pageId: "",
+      page: 1,
+      equipList: [],
+      filterList: [],
+      isEnd: false,
+      equiName: "",
+      equiCode: "",
+      workOrderId: "",
+      workOrderCode: "",
+      showSelectBar: false,
+      allSelected: false,
+    };
+  },
+  computed: {
+    selectedCount() {
+      return this.equipList.filter((item) => item.checked).length;
+    },
+  },
+  onLoad(options) {
+    this.id = options.id;
+    this.keyWords = options.codes;
+    this.getList();
+    //   this.pageId = options.id
+    //   this.equiName = options.equiName
+    //   this.equiCode = options.equiCode
+    //   this.workOrderId = +options.workOrderId
+    // this.workOrderCode = options.workOrderCode
+  },
+  // onReachBottom() {
+  // 	if (this.isEnd) return
+  // 	this.page++
+  // 	this.getList()
+  // },
+  methods: {
+    back() {
+      uni.navigateBack({
+        delta: 1,
+      });
+    },
+    doSearch() {
+      if (!this.keyWords) {
+        this.filterList = this.equipList;
+      } else {
+        this.filterList = this.equipList.filter((item) =>
+          item.categoryCode.includes(this.keyWords),
+        );
+      }
+    },
+    handleSave() {
+      let isAllPass = true;
+      isAllPass = this.equipList.every((item) => item.status > -1);
+      let params = {
+        id: this.equipList[0].id,
+        executeStatus: isAllPass ? 1 : 2,
+        isAbnormal: isAllPass ? 1 : 0,
+        workItems: this.equipList.map((item) => {
+          return {
+            content: item.content,
+            name: item.name,
+            norm: item.norm,
+            operationGuide: item.operationGuide,
+            result: item.result,
+            serialNum: item.serialNum,
+            status: item.status == -1 ? -1 : 1,
+            photoList: item.photoList || [],
+          };
+        }),
+      };
+      mattersChecked(params).then((data) => {
+        uni.showToast({
+          duration: 2000,
+          title: "保存成功!",
+        });
+        this.back();
+      });
+      // let _this = this
+      // const params = {
+      // 	itemList: this.equipList,
+      // 	planEquiId: this.pageId,
+      // 	workOrderId: +this.workOrderId,
+      // 	workOrderType: 1
+      // }
+      // postJ(this.apiUrl + `/workOrder/itemsInspect`, params, true).then(res => {
+      // 	if (res?.success) {
+      // 		if (res.data) {
+      // 			uni.showModal({
+      // 				title: '提示',
+      // 				content: '所有设备已执行完,是否报工?',
+      // 				cancelText: '取消', // 取消按钮的文字
+      // 				confirmText: '报工', // 确认按钮的文字
+      // 				showCancel: true, // 是否显示取消按钮,默认为 true
+      // 				success: res => {
+      // 					if (res.confirm) {
+      // 						_this._report()
+      // 					} else {
+      // 						_this.back()
+      // 					}
+      // 				}
+      // 			})
+      // 		} else {
+      // 			uni.showToast({
+      // 				duration: 2000,
+      // 				title: '保存成功!'
+      // 			})
+      // 			this.back()
+      // 		}
+      // 	}
+      // })
+    },
+
+    handleClose() {
+      this.$refs.inputDialog.close();
+    },
+    timeoutCauseConfirm(value) {
+      if (!value) {
+        uni.showToast({
+          title: "请输入超时原因",
+          icon: "none",
+        });
+        return;
+      }
+      this.$refs.inputDialog.close();
+      this._report(value);
+    },
+    _report(timeoutCause = "") {
+      let _this = this;
+      post(
+        this.apiUrl + "/workOrder/reportWork",
+        {
+          workOrderId: this.workOrderId,
+          timeoutCause,
+        },
+        true,
+        false,
+      )
+        .then((res) => {
+          if (res?.success) {
+            let data = res.data;
+            if (data.length) {
+              uni.showModal({
+                title: "提示",
+                content: `有${data.length}台设备被标记为缺陷,是否要报修?`,
+                cancelText: "取消", // 取消按钮的文字
+                confirmText: "报修", // 确认按钮的文字
+                showCancel: true, // 是否显示取消按钮,默认为 true
+                success: (res) => {
+                  if (res.confirm) {
+                    if (data.length > 1) {
+                      uni.navigateTo({
+                        url: `/pages/tour_tally/detail/detail?workOrderCode=${this.workOrderCode}&id=${this.workOrderId}&chooseTab=true`,
+                      });
+                    } else {
+                      uni.navigateTo({
+                        url: `/pages/repair/repair/index?source=5&workOrderCode=${this.workOrderCode}&equiCode=${data[0].equiCode}&equiId=${data[0].equiId}&workOrderId=${this.pageId}&equiName=${data[0].equiName}&equiModel=${data[0].equiModel}&equiLocation=${data[0].equiLocation}`,
+                      });
+                    }
+                  } else {
+                    _this.back();
+                  }
+                },
+              });
+            } else {
+              uni.showToast({
+                icon: "success",
+                title: "操作成功!",
+                duration: 2000,
+              });
+              _this.back();
+            }
+          }
+        })
+        .catch((res) => {
+          if (res.code === "4444") {
+            this.$refs.inputDialog.open();
+          }
+        });
+    },
+
+    // 打开选择栏
+    openSelectBar() {
+      this.showSelectBar = true;
+    },
+    // 关闭选择栏
+    closeSelectBar() {
+      this.showSelectBar = false;
+      this.equipList.forEach((item) => {
+        item.checked = false;
+      });
+      this.allSelected = false;
+    },
+    // 全选/取消全选
+    selectAll() {
+      this.allSelected = !this.allSelected;
+      this.equipList.forEach((item) => {
+        item.checked = this.allSelected;
+      });
+    },
+    // 打开批量操作弹窗
+    openBatchDialog() {
+      if (this.selectedCount === 0) {
+        uni.showToast({
+          title: "请先选择要操作的项目",
+          icon: "none",
+        });
+        return;
+      }
+      this.$refs.batchPopup.open();
+    },
+    // 关闭批量操作弹窗
+    closeBatchPopup() {
+      this.$refs.batchPopup.close();
+    },
+    // 批量设置状态
+    batchSetStatus(status) {
+      const statusText = status === 1 ? "正常" : "异常";
+      uni.showModal({
+        title: "确认提示",
+        content: `确认将选中的 ${this.selectedCount} 项设置为${statusText}吗?`,
+        success: (res) => {
+          if (res.confirm) {
+            this.equipList.forEach((item) => {
+              if (item.checked) {
+                item.status = status;
+                item.result = statusText;
+              }
+            });
+            uni.showToast({
+              title: "批量设置成功",
+              icon: "success",
+            });
+            this.closeBatchPopup();
+            this.closeSelectBar();
+          }
+        },
+      });
+    },
+    getList() {
+      getDeviceInfo({
+        id: this.id,
+      }).then((data) => {
+        this.equiName = data.name;
+        this.equiCode = data.code;
+        this.equipList = data.workItems.map((item) => {
+          return {
+            ...item,
+            id: data.id,
+            status: 1,
+            result: "正常",
+            executeStatus: 1,
+            checked: false,
+          };
+        });
+        this.doSearch();
+      });
+      // const { page } = this
+      // post(this.apiUrl + `/workOrder/getEquipmentItemsListApp?size=10&page=${page}`, { planEquiId: +this.pageId, workOrderId: this.workOrderId }, true).then(res => {
+      // 	if (res?.success) {
+      // 		res.data.records.forEach(item => {
+      // 			item.isNormal = item.isNormal === null || item.isNormal === undefined ? 1 : item.isNormal
+      // 		})
+      // 		if (page === 1) {
+      // 			this.equipList = res.data.records
+      // 		} else {
+      // 			this.equipList.push(...res.data.records)
+      // 		}
+
+      // 		this.isEnd = this.equipList.length >= res.data.total
+      // 	}
+      // })
+    },
+  },
+};
 </script>
 
 <style lang="scss" scoped>
-	.top-wrapper {
-		background-color: #fff;
-		display: flex;
-		width: 750rpx;
-		height: 88rpx;
-		padding: 16rpx 32rpx;
-		align-items: center;
-		gap: 16rpx;
-
-		/deep/.uni-section {
-			margin-top: 0px;
-		}
-
-		/deep/.uni-section-header {
-			padding: 0px;
-
-		}
-
-		.search_btn {
-			width: 120rpx;
-			height: 70rpx;
-			line-height: 70rpx;
-			padding: 0 24rpx;
-			background: $theme-color;
-			font-size: 32rpx;
-			color: #fff;
-			margin: 0;
-			margin-left: 26rpx;
-		}
-
-		.menu_icon {
-			width: 44rpx;
-			height: 44rpx;
-			margin-left: 14rpx;
-		}
-	}
-
-	.check-content {
-		box-sizing: border-box;
-		// height: calc(100vh - 88rpx);
-		display: flex;
-		flex-direction: column;
-		padding-bottom: 100rpx;
-
-		.title {
-			line-height: 80rpx;
-			display: flex;
-			justify-content: space-between;
-			padding: 0 30rpx;
-		}
-
-		.check-list {
-			flex: 1;
-			overflow: auto;
-			padding: 0 30rpx 30rpx;
-		}
-
-		.footer {
-			height: 100rpx;
-			display: flex;
-			border: 1rpx solid $j-primary-border-green;
-			position: fixed;
-			bottom: 0;
-			width: 100vw;
-			background: #fff;
-
-			.btn {
-				display: flex;
-				flex: 1;
-				justify-content: center;
-				align-items: center;
-				border-radius: 0;
-
-				&.primary {
-					background-color: $j-primary-border-green;
-					color: #fff;
-				}
-			}
-		}
-
-		.mb20 {
-			margin-bottom: 20rpx;
-		}
-	}
-</style>
+.top-wrapper {
+  background-color: #fff;
+  display: flex;
+  width: 750rpx;
+  height: 88rpx;
+  padding: 16rpx 32rpx;
+  align-items: center;
+  gap: 16rpx;
+
+  /deep/.uni-section {
+    margin-top: 0px;
+  }
+
+  /deep/.uni-section-header {
+    padding: 0px;
+  }
+
+  .search_btn {
+    width: 120rpx;
+    height: 70rpx;
+    line-height: 70rpx;
+    padding: 0 24rpx;
+    background: $theme-color;
+    font-size: 32rpx;
+    color: #fff;
+    margin: 0;
+    margin-left: 26rpx;
+  }
+
+  .menu_icon {
+    width: 44rpx;
+    height: 44rpx;
+    margin-left: 14rpx;
+  }
+}
+
+.check-content {
+  box-sizing: border-box;
+  // height: calc(100vh - 88rpx);
+  display: flex;
+  flex-direction: column;
+  padding-bottom: 100rpx;
+
+  .title {
+    line-height: 80rpx;
+    display: flex;
+    justify-content: space-between;
+    padding: 0 30rpx;
+  }
+
+  .check-list {
+    flex: 1;
+    overflow: auto;
+    padding: 0 30rpx 30rpx;
+  }
+
+  .footer {
+    height: 100rpx;
+    display: flex;
+    border: 1rpx solid $j-primary-border-green;
+    position: fixed;
+    bottom: 0;
+    width: 100vw;
+    background: #fff;
+
+    .btn {
+      display: flex;
+      flex: 1;
+      justify-content: center;
+      align-items: center;
+      border-radius: 0;
+
+      &.primary {
+        background-color: $j-primary-border-green;
+        color: #fff;
+      }
+    }
+  }
+
+  .mb20 {
+    margin-bottom: 20rpx;
+  }
+
+  .batch-trigger {
+    padding: 20rpx 30rpx;
+    text-align: right;
+
+    text {
+      background-color: #157a2c;
+      color: #fff;
+      padding: 10rpx 30rpx;
+      border-radius: 8rpx;
+      font-size: 28rpx;
+    }
+  }
+
+  .select-bar {
+    background-color: #f5f5f5;
+    padding: 20rpx 30rpx;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    border-bottom: 1rpx solid #e0e0e0;
+
+    .select-actions {
+      display: flex;
+      align-items: center;
+      flex: 1;
+
+      .select-all {
+        display: flex;
+        align-items: center;
+        margin-right: 20rpx;
+
+        text {
+          margin-left: 10rpx;
+          font-size: 28rpx;
+        }
+      }
+
+      .selected-count {
+        font-size: 28rpx;
+        color: #666;
+      }
+    }
+
+    .batch-btn {
+      background-color: #157a2c;
+      color: #fff;
+      padding: 10rpx 30rpx;
+      border-radius: 8rpx;
+      font-size: 28rpx;
+      margin: 0 10rpx;
+
+      &.disabled {
+        background-color: #ccc;
+        opacity: 0.6;
+      }
+    }
+
+    .close-select {
+      padding: 10rpx 20rpx;
+      background-color: #fff;
+      border-radius: 8rpx;
+      font-size: 28rpx;
+    }
+  }
+}
+
+.batch-popup-content {
+  background-color: #fff;
+  border-radius: 20rpx 20rpx 0 0;
+  padding: 30rpx;
+  z-index: 1000;
+
+  .popup-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding-bottom: 30rpx;
+    border-bottom: 1rpx solid #e0e0e0;
+
+    .header-title {
+      font-size: 36rpx;
+      font-weight: bold;
+      color: #333;
+    }
+
+    .close-btn {
+      width: 60rpx;
+      height: 60rpx;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+
+      .close-icon {
+        font-size: 60rpx;
+        color: #999;
+        line-height: 1;
+      }
+    }
+  }
+
+  .popup-body {
+    padding: 30rpx 0;
+
+    .select-info {
+      padding: 20rpx 0;
+      text-align: center;
+      color: #666;
+      font-size: 28rpx;
+    }
+
+    .action-btn {
+      display: flex;
+      align-items: center;
+      padding: 25rpx 30rpx;
+      margin: 0 0 20rpx 0;
+      background-color: #f5f5f5;
+      border-radius: 12rpx;
+      font-size: 30rpx;
+
+      &:active {
+        background-color: #e0e0e0;
+      }
+
+      text {
+        margin-left: 20rpx;
+      }
+    }
+
+    .status-btn {
+      .status-icon {
+        width: 40rpx;
+        height: 40rpx;
+        border-radius: 50%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        font-size: 28rpx;
+        color: #fff;
+        margin-left: 0;
+      }
+
+      .normal-icon {
+        background-color: #157a2c;
+      }
+
+      .abnormal-icon {
+        background-color: #ff4444;
+      }
+    }
+  }
+}
+</style>

+ 2 - 1
utils/request.js

@@ -37,6 +37,7 @@ const http = ({
 			timeout: 600000,
 			...other,
 			complete: (res) => {
+				console.log(res,'res')
 				if (showLoading) {
 					uni.hideLoading();
 				}
@@ -44,7 +45,7 @@ const http = ({
 					uni.navigateTo({
 						url: "/pages/login/login",
 					});
-				} else if (res.data.code == "B00101") {
+				} else if (res.statusCode == "401") {
 					//刷新token
 					uni.showToast({
 						title: "身份验证已过期,请重新登录",