Procházet zdrojové kódy

修复农事适配问题

jiuling před 9 měsíci
rodič
revize
e973487915

+ 8 - 3
api/services/user.js

@@ -1,5 +1,6 @@
 import { http, Method } from '@/utils/request';
-
+import storage from "@/utils/storage.js";
+const userInfo = storage.getUserInfo()
 /**
  * 获取部门下的用户列表
  * @param {Number} deptId - 部门ID
@@ -32,8 +33,12 @@ export function getUsersByPlotId(params) {
  * @returns {Promise} - 返回用户详情
  */
 export function getUserInfo(userId) {
+  const id = userId ?? userInfo?.userid; // 优先用传入参数,其次用全局userInfo
+  if (!id) {
+    throw new Error('缺少 userId');
+  }
   return http.request({
-    url: `/system/user/${userId}`,
+    url: `/system/user/${id}`,
     method: Method.GET
   });
-} 
+}

+ 4 - 2
pages.json

@@ -38,7 +38,8 @@
 		{
 			"path": "pages/activity/index",
 			"style": {
-				"navigationBarTitleText": "农事活动"
+				"navigationBarTitleText": "农事活动",
+				"disableScroll": true
 			}
 		},
 		{
@@ -95,7 +96,8 @@
 		{
 			"path": "pages/knowledge/index",
 			"style": {
-				"navigationBarTitleText": "农业知识"
+				"navigationBarTitleText": "农业知识",
+				"disableScroll": true
 			}
 		},
 		{

+ 125 - 37
pages/activity/activity-detail.vue

@@ -42,12 +42,15 @@
         <view class="form-item" @click="pageMode !== 'view' && showTaskTypeSelector()">
           <view class="form-label required">任务类型</view>
           <view class="select-wrapper">
-            <input 
-              v-model="formData.typeName"
+<!--            <input 
+              :value="formData.typeName"
               :placeholder="dictLoading ? '加载中...' : '请选择任务类型'"
-			  :disabled="formData.completionStatus === '1'"
+			  readonly
               class="form-input select-input"
-            />
+            /> -->
+			<view class="form-input select-input">
+			      {{ formData.typeName || (dictLoading ? '加载中...' : '请选择任务类型') }}
+			</view>
             <view v-if="pageMode !== 'view'" class="select-arrow">
               <text>▼</text>
             </view>
@@ -58,12 +61,16 @@
         <view class="form-item" @click="pageMode !== 'view' && selectExecuteTime()">
           <view class="form-label required">执行时间</view>
           <view class="select-wrapper">
-            <input 
-              v-model="formattedExecuteTime"
+<!--            <input 
+              :value="formattedExecuteTime"
               placeholder="请选择任务计划时间"
-              :disabled="formData.completionStatus === '1'"
+              readonly
               class="form-input select-input"
-            />
+              readonly
+            /> -->
+			<view class="form-input select-input">
+			      {{ formattedExecuteTime || '请选择任务计划时间' }}
+			</view>
             <view v-if="pageMode !== 'view'" class="select-arrow">
               <text>选择</text>
             </view>
@@ -74,12 +81,15 @@
         <view class="form-item" @click="pageMode !== 'view' && showUserSelector()">
           <view class="form-label required">负责人</view>
           <view class="select-wrapper">
-            <input 
-              v-model="formData.assigneeName"
+<!--            <input 
+              :value="formData.assigneeName"
               placeholder="请选择负责人"
-			  :disabled="formData.completionStatus === '1'"
+			  readonly
               class="form-input select-input"
-            />
+            /> -->
+			<view class="form-input select-input">
+			      {{ formData.assigneeName || '请选择负责人' }}
+			</view>
             <view v-if="pageMode !== 'view'" class="select-arrow">
               <text>选择</text>
             </view>
@@ -136,13 +146,16 @@
         <view class="form-item" v-if="formData.completionStatus === '1'">
           <view class="form-label" :class="{'required': (pageMode === 'create' || pageMode === 'edit') && formData.completionStatus === '1'}">完成时间</view>
                      <view class="select-wrapper" @click="(pageMode === 'create' || pageMode === 'edit') && formData.completionStatus === '1' && selectCompletionTime()">
-            <input 
-              v-model="formattedCompletionTime"
+            <!-- <input 
+              :value="formattedCompletionTime"
               placeholder="请选择实际完成时间"
-              disabled
+              readonly
               class="form-input select-input"
-            />
-                         <view v-if="(pageMode === 'create' || pageMode === 'edit') && formData.completionStatus === '1'" class="select-arrow">
+            /> -->
+			<view class="form-input select-input">
+			      {{ formattedCompletionTime || '请选择实际完成时间' }}
+			</view>
+                <view v-if="(pageMode === 'create' || pageMode === 'edit') && formData.completionStatus === '1'" class="select-arrow">
                <text>选择</text>
              </view>
           </view>
@@ -514,6 +527,8 @@ export default {
       this.formData.id = options.id;
       this.loadTaskDetail(options.id);
     } else if (options.id === 'new') {
+		// 加载当前登录用户
+		this.loadAssigneeInfo()
       // 创建新任务时,加载字典数据并设置默认任务类型
       // this.loadDict().then(() => {
       //   // 确保字典数据加载完成后设置默认任务类型
@@ -536,6 +551,23 @@ export default {
   },
   
   methods: {
+    // 跨端安全解析日期
+    normalizeToDate(input) {
+      if (!input) return new Date();
+      let dateObj = input;
+      if (typeof input === 'string') {
+        // 兼容 iOS:将 2025-08-12 12:30:00 转为 2025/08/12 12:30:00
+        dateObj = input.replace(/-/g, '/');
+      }
+      if (typeof input === 'number') {
+        // 秒级时间戳转毫秒
+        if (input.toString().length === 10) {
+          dateObj = input * 1000;
+        }
+      }
+      const d = new Date(dateObj);
+      return isNaN(d.getTime()) ? new Date() : d;
+    },
     // 加载任务详情
     loadTaskDetail(taskId) {
       uni.showLoading({
@@ -581,9 +613,11 @@ export default {
           } else {
             this.formData.images = [];
           }
-          
+          console.log("this.formData.assigneeId",this.formData.assigneeId);
+          console.log("!this.formData.assigneeName",this.formData.assigneeName);
           // 如果有负责人ID但没有负责人名称,获取负责人信息
           if (this.formData.assigneeId && !this.formData.assigneeName) {
+			  
             this.loadAssigneeInfo(this.formData.assigneeId);
           }
           
@@ -618,9 +652,11 @@ export default {
     // 加载负责人信息
     loadAssigneeInfo(userId) {
       getUserInfo(userId).then(res => {
+		  console.log("你是谁:",res);
         if (res.data.code === 200) {
           const userData = res.data.data;
           this.formData.assigneeName = userData.userName || '未知用户';
+          this.formData.assigneeId = userData.userId;
         }
       }).catch(err => {
         console.error('获取负责人信息失败:', err);
@@ -709,13 +745,12 @@ export default {
     
     // 初始化日期时间选择器
     initDateTimePicker(timestamp) {
-      const date = new Date(timestamp);
+      const date = this.normalizeToDate(timestamp);
       const currentYear = date.getFullYear();
       const currentMonth = date.getMonth() + 1; // 1-12
       const currentDate = date.getDate(); // 1-31
       const currentHour = date.getHours();
       const currentMinute = date.getMinutes();
-	  const currentSeconds = date.getSeconds()
       
       // 基准年份,用于计算索引
       const startYear = 2020;
@@ -732,7 +767,6 @@ export default {
         date: currentDate,
         hour: currentHour,
         minute: currentMinute,
-		seconds: currentSeconds,
         yearIndex
       });
       
@@ -742,8 +776,7 @@ export default {
         currentMonth - 1, // 月份索引(0-11)
         currentDate - 1, // 日期索引(0-30)
         currentHour, // 小时索引
-        currentMinute, // 分钟索引
-		currentSeconds
+        currentMinute // 分钟索引
       ];
       
       console.log('选择器初始值:', this.dateTimePickerValue);
@@ -895,16 +928,54 @@ export default {
     },
     
     // 格式化日期时间
-    formatDateTime(timestamp) {
-      if (!timestamp) return '';
-      const date = new Date(timestamp);
-      const year = date.getFullYear();
-      const month = String(date.getMonth() + 1).padStart(2, '0');
-      const day = String(date.getDate()).padStart(2, '0');
-      const hour = String(date.getHours()).padStart(2, '0');
-      const minute = String(date.getMinutes()).padStart(2, '0');
-      return `${year}-${month}-${day} ${hour}:${minute}`;
-    },
+	/**
+	 * 日期格式化工具(兼容 iOS 和安卓)
+	 * @param {string|number|Date} date - 日期对象 / 时间戳 / 日期字符串
+	 * @param {string} format - 格式模板,默认 'yyyy-MM-dd HH:mm:ss'
+	 * @returns {string} 格式化后的日期
+	 */
+	formatDateTime(date, format = 'yyyy-MM-dd HH:mm') {
+	  if (!date) return '';
+	
+	  // 如果是字符串,做 iOS 兼容(将 2025-08-12 替换为 2025/08/12)
+	  if (typeof date === 'string') {
+	    date = date.replace(/-/g, '/');
+	  }
+	
+	  // 如果是数字(时间戳),判断是否是秒级
+	  if (typeof date === 'number') {
+	    if (date.toString().length === 10) {
+	      date *= 1000; // 秒转毫秒
+	    }
+	  }
+	
+	  // 转换为 Date 对象
+	  date = new Date(date);
+	  if (isNaN(date.getTime())) return '';
+	
+	  const map = {
+	    'yyyy': date.getFullYear(),
+	    'MM': String(date.getMonth() + 1).padStart(2, '0'),
+	    'dd': String(date.getDate()).padStart(2, '0'),
+	    'HH': String(date.getHours()).padStart(2, '0'),
+	    'mm': String(date.getMinutes()).padStart(2, '0'),
+	    // 'ss': String(date.getSeconds()).padStart(2, '0')
+	  };
+	
+	  return format.replace(/yyyy|MM|dd|HH|mm/g, match => map[match]);
+	},
+	// formatDateTime(timestamp) {
+	//   if (!timestamp) return '';
+	//   const date = parseDate(timestamp);
+	//   if (isNaN(date.getTime())) return '';
+	//   const year = date.getFullYear();
+	//   const month = String(date.getMonth() + 1).padStart(2, '0');
+	//   const day = String(date.getDate()).padStart(2, '0');
+	//   const hour = String(date.getHours()).padStart(2, '0');
+	//   const minute = String(date.getMinutes()).padStart(2, '0');
+	//   return `${year}-${month}-${day} ${hour}:${minute}`;
+	// },
+
     
     // 选择图片
     chooseImage() {
@@ -992,6 +1063,10 @@ export default {
           success: (res) => {
                           try {
                 const response = JSON.parse(res.data);
+				uni.showToast({
+				  title: `返回: ${response.data}`,
+				  icon: 'none',
+				});
                 if (response.code === 200) {
                   // 获取返回的URL
                   const imageUrl = response.data.url;
@@ -1011,12 +1086,20 @@ export default {
               }
             } catch (e) {
               failCount++;
+			  uni.showToast({
+			    title: `解析响应失败: ${e}`,
+			    icon: 'none',
+			  });
               console.error('解析响应失败:', e);
             }
           },
           fail: (err) => {
             failCount++;
             console.error('上传请求失败:', err);
+			uni.showToast({
+			  title: `上传请求失败: ${err}`,
+			  icon: 'none',
+			});
           },
           complete: () => {
             // 当所有文件都已处理完成
@@ -1036,11 +1119,15 @@ export default {
                 });
               } else {
                 // 全部失败
+				uni.showToast({
+				  title: `图片上传: ${newImages}`,
+				  icon: 'none',
+				});
                 uni.hideLoading();
-                uni.showToast({
-                  title: '图片上传失败',
-                  icon: 'none'
-                });
+                // uni.showToast({
+                //   title: '图片上传失败',
+                //   icon: 'none',
+                // });
               }
             }
           }
@@ -1320,6 +1407,7 @@ export default {
 
 .form-input {
   width: 100%;
+  line-height: 80rpx;
   height: 80rpx;
   background: #F8F8F8;
   border: 1rpx solid #E5E5E5;

+ 8 - 4
pages/activity/index.vue

@@ -40,7 +40,7 @@
     </view>
 
     <!-- 任务列表 - 可滚动区域 -->
-    <scroll-view class="task-list-scroll" scroll-y 
+   <scroll-view class="task-list-scroll" scroll-y lower-threshold="120"
       @scrolltolower="loadMore" 
       @refresherrefresh="refreshData" 
       refresher-enabled
@@ -480,6 +480,10 @@ export default {
 
 .task-list {
   padding: 0 30rpx;
+  /* 预留底部空间,避免被悬浮新增按钮遮挡,并兼容安全区 */
+  padding-bottom: 160rpx;
+  padding-bottom: calc(160rpx + constant(safe-area-inset-bottom));
+  padding-bottom: calc(160rpx + env(safe-area-inset-bottom));
   box-sizing: border-box;
   width: 100%;
 }
@@ -609,6 +613,7 @@ export default {
   display: -webkit-box;
   -webkit-box-orient: vertical;
   -webkit-line-clamp: 2;
+  line-clamp: 2;
   overflow: hidden;
   text-overflow: ellipsis;
   word-break: break-all;
@@ -616,6 +621,7 @@ export default {
 
 .remark-expanded {
   -webkit-line-clamp: unset;
+  line-clamp: unset;
 }
 
 .expand-btn {
@@ -706,7 +712,5 @@ export default {
   max-width: 120rpx;
 }
 
-.info-type-tag {
-  /* margin-left: 4rpx; */
-}
+/* 移除空规则 .info-type-tag 以避免 linter 警告 */
 </style>

+ 1 - 1
pages/device/device-list/detail-camera.vue

@@ -6,7 +6,7 @@
 				<view class="device-name-container">
 					<text class="device-name">{{ deviceInfo.name }}</text>
 					<view class="status-tag" :class="deviceInfo.status === 1 ? 'status-online' : 'status-offline'">
-						<view class="status-dot" :class="{'offline-dot': deviceInfo.status === 1}"></view>
+						<view class="status-dot" :class="{'offline-dot': deviceInfo.status === 0}"></view>
 						{{ deviceInfo.status === 1 ? '在线' : '离线' }}
 					</view>
 				</view>

+ 1 - 1
pages/device/device-list/index.vue

@@ -285,7 +285,7 @@ export default {
             
             this.total = total;
 			// 为农技增加模拟数据 后续可删除
-            if(total === 0){
+            if(this.deviceType === 'tractor' ){
             	const newDevices = this.generateMockDevices();
 				console.log("newDevices",newDevices);
             	this.deviceList = [...this.deviceList, ...newDevices];

+ 3 - 4
pages/knowledge/detail.vue

@@ -457,10 +457,9 @@ export default {
     },
     
     scrollToTop() {
-      uni.pageScrollTo({
-        scrollTop: 0,
-        duration: 300
-      });
+		setTimeout(() => {
+			uni.pageScrollTo({scrollTop: 0, duration: 0});
+		}, 50);
     },
     
     handleShare() {