Переглянути джерело

实现"我的地块"模块功能

jiuling 11 місяців тому
батько
коміт
a7e881acde

+ 2 - 1
api/services/connect.js

@@ -85,6 +85,7 @@ export function clearLoginState() {
 
   storage.setHasLogin(false);
   storage.setAccessToken('');
-  storage.setUserInfo('')
+  storage.setUserInfo('');
+  // storage.setPlots('');
 }
 

+ 73 - 0
api/services/field.js

@@ -0,0 +1,73 @@
+import {
+	http,
+	Method
+} from '@/utils/request.js';
+// 使用storage模块的方法设置登录状态为false
+import storage from "@/utils/storage.js";
+const request = http.request;
+
+
+/**
+ * 获取用户关联的地块列表
+ * @param {number} pageNum - 页码
+ * @param {number} pageSize - 每页数量
+ * @returns {Promise} 
+ */
+export function fetchUserFieldList(pageNum = 1, pageSize = 10) {
+	const user = storage.getUserInfo();
+	return http.request({
+		url: 'uniapp/field/list/user',
+		method: Method.POST,
+		data: {
+			userId: user.userId,
+			params: {
+				pageNum: pageNum,
+				pageSize: pageSize
+			}
+		}
+	});
+}
+
+
+/**
+ * 获取当前登录用户默认地块
+ */
+export function getUserCurrentField() {
+	const user = storage.getUserInfo();
+	return http.request({
+		url: `uniapp/field/current/user/${user.userId}`,
+		method: Method.GET,
+	});
+}
+
+/**
+ * 根据当前登录用户搜索关联地块
+ * @param keyWord 搜索关键词
+ */
+export function searchUserField(data) {
+	console.log("da",data);
+	const user = storage.getUserInfo();
+	return http.request({
+		url: 'uniapp/field/search/user',
+		method: Method.POST,
+		data:{
+			userId: user.userId,
+			params: {
+				keyword:data.keyword,
+				pageNum: data.pageNum,
+				pageSize: data.pageSize
+			}
+		}
+	});
+}
+
+/**
+ * 根据当前登录用户统计地块信息
+ */
+export function countUserPlots() {
+	const user = storage.getUserInfo();
+	return http.request({
+		url: `uniapp/field/count/${user.userId}`,
+		method: Method.GET,
+	});
+}

+ 6 - 0
pages.json

@@ -112,6 +112,12 @@
       "style": {
         "navigationBarTitleText": "隐私政策"
       }
+    },
+    {
+      "path": "pages/plots/list",
+      "style": {
+        "navigationBarTitleText": "选择地块"
+      }
     }
   ],
   "tabBar": {

Різницю між файлами не показано, бо вона завелика
+ 559 - 457
pages/dashboard/index.vue


+ 0 - 4
pages/login/index.vue

@@ -161,10 +161,6 @@
 										delta: 1,
 									});
 								}
-								
-								// uni.navigateBack({
-								// 	delta: 1,
-								// });
 							});
 
 						},

+ 1052 - 0
pages/plots/list.vue

@@ -0,0 +1,1052 @@
+<template>
+	<view class="container">
+		<!-- 头部区域 -->
+		<view class="header">
+			<view class="back-button" @click="goBack">
+				<text class="iconfont icon-back">&#xe60e;</text>
+			</view>
+			<text class="page-title">选择地块</text>
+		</view>
+
+		<!-- 搜索栏 -->
+		<view class="search-box">
+			<view class="search-input">
+				<image src="@/static/icons/search.png" style="width: 40rpx; height: 40rpx; padding-right: 10rpx;"
+					mode="widthFix" />
+				<input type="text" v-model="searchKeyword" placeholder="搜索地块名称/编号/负责人/农场" confirm-type="search"
+					@input="handleSearch" />
+				<text v-if="searchKeyword" class="clear-icon" @click="clearSearch">×</text>
+			</view>
+		</view>
+
+		<!-- 当前选中地块 -->
+		<view class="current-block">
+			<view class="block-header">
+				<view class="left">
+					<text class="icon-tag">当前</text>
+					<text class="title">当前地块</text>
+				</view>
+			</view>
+			<view class="current-block-card">
+				<view class="current-tag">当前</view>
+
+				<view class="block-content">
+					<view class="block-icon">
+						<image src="/static/icons/location.svg" class="location-icon" mode="aspectFit"></image>
+					</view>
+
+					<view class="block-info">
+						<!-- 标题区域:显示地块名称 + 所属农场名称 -->
+						<view class="block-name">{{ currentBlock.name }}</view>
+						<view class="block-farm">{{ currentBlock.farmName }}</view>
+
+						<!-- 次级信息区域:显示地块编号、负责人 -->
+						<view class="block-meta">
+							<text>编号:{{ currentBlock.code }}</text>
+							<text class="separator">|</text>
+							<text>负责人:{{ currentBlock.manager }}</text>
+						</view>
+
+						<!-- 已有信息:面积、类型、作物 -->
+						<view class="block-details">
+							<text>{{ currentBlock.area }}亩</text>
+							<text class="separator">|</text>
+							<text>{{ currentBlock.type }}</text>
+							<text v-if="currentBlock.crop" class="separator">|</text>
+							<text v-if="currentBlock.crop">{{ currentBlock.crop }}</text>
+						</view>
+					</view>
+				</view>
+
+				<view class="block-stats">
+					<view class="stat-item">
+						<image src="/static/icons/device.svg" class="stat-icon" mode="aspectFit"></image>
+						<text>设备:{{ currentBlock.deviceCount }}</text>
+					</view>
+					<view class="stat-item">
+						<image src="/static/icons/online.svg" class="stat-icon online-icon" mode="aspectFit"></image>
+						<text>在线:{{ currentBlock.onlineDevices }}</text>
+					</view>
+					<view class="stat-item" v-if="currentBlock.alerts > 0">
+						<image src="/static/icons/alert.svg" class="stat-icon alert-icon" mode="aspectFit"></image>
+						<text class="alert-text">告警:{{ currentBlock.alerts }}</text>
+					</view>
+				</view>
+			</view>
+		</view>
+
+		<!-- 地块列表 -->
+		<view class="block-list">
+			<view class="block-header">
+				<view class="left">
+					<text class="icon-tag">列表</text>
+					<text class="title">可选地块列表</text>
+				</view>
+				<text class="count">共{{ filteredBlocks.length }}个地块</text>
+			</view>
+
+			<!-- 加载骨架屏 -->
+			<template v-if="isLoading">
+				<view class="skeleton-container">
+					<view class="skeleton-box" v-for="i in 3" :key="i">
+						<view class="skeleton-header">
+							<view class="skeleton-icon"></view>
+							<view class="skeleton-info">
+								<view class="skeleton-title"></view>
+								<view class="skeleton-detail"></view>
+							</view>
+						</view>
+						<view class="skeleton-stats"></view>
+					</view>
+				</view>
+			</template>
+
+			<!-- 空状态 -->
+			<template v-else-if="filteredBlocks.length === 0">
+				<view class="empty-state">
+					<image src="/static/images/empty.png" mode="aspectFit" class="empty-image"></image>
+					<text class="empty-text">暂无可选地块</text>
+					<text class="empty-subtext">请添加或关联地块后再试</text>
+				</view>
+			</template>
+
+			<!-- 地块列表 -->
+			<template v-else>
+				<view class="block-cards">
+					<view class="block-card" v-for="block in filteredBlocks" :key="block.id"
+						:class="{'active-block': currentBlock.id === block.id, 'clickable': currentBlock.id !== block.id}"
+						@click="handleBlockClick(block)">
+						<view v-if="block.status === 'active'" class="status-badge status-active-badge">使用中</view>
+						<view v-if="block.status === 'idle'" class="status-badge status-idle-badge">闲置</view>
+						<view v-if="block.status === 'maintenance'" class="status-badge status-maintenance-badge">维护中
+						</view>
+
+						<view class="block-content">
+							<view class="block-icon">
+								<image src="/static/icons/location.svg" class="location-icon" mode="aspectFit"></image>
+							</view>
+
+							<view class="block-info">
+								<!-- 标题区域:显示地块名称 + 所属农场名称 -->
+								<view class="block-name">{{ block.name }}</view>
+								<view class="block-farm">{{ block.farmName }}</view>
+
+								<!-- 次级信息区域:显示地块编号、负责人 -->
+								<view class="block-meta">
+									<text>编号:{{ block.code }}</text>
+									<text class="separator">|</text>
+									<text>负责人:{{ block.manager }}</text>
+								</view>
+
+								<!-- 已有信息:面积、类型、作物 -->
+								<view class="block-details">
+									<text>{{ block.area }}亩</text>
+									<text class="separator">|</text>
+									<text>{{ block.type }}</text>
+									<text v-if="block.crop" class="separator">|</text>
+									<text v-if="block.crop">{{ block.crop }}</text>
+								</view>
+							</view>
+						</view>
+
+						<view class="block-stats">
+							<view class="stat-item">
+								<image src="/static/icons/device.svg" class="stat-icon" mode="aspectFit"></image>
+								<text>设备:{{ block.deviceCount }}</text>
+							</view>
+							<view class="stat-item">
+								<image src="/static/icons/online.svg" class="stat-icon online-icon" mode="aspectFit">
+								</image>
+								<text>在线:{{ block.onlineDevices }}</text>
+							</view>
+							<view class="stat-item" v-if="block.alerts > 0">
+								<image src="/static/icons/alert.svg" class="stat-icon alert-icon" mode="aspectFit">
+								</image>
+								<text class="alert-text">告警:{{ block.alerts }}</text>
+							</view>
+						</view>
+					</view>
+				</view>
+			</template>
+		</view>
+
+		<!-- 底部加载提示区域 -->
+		<view class="loading-more" v-if="isLoadingTip || !hasMore">
+			<view v-if="loadingMore" class="loading-text">
+				<view class="loading-icon"></view>
+				<text>正在加载更多地块...</text>
+			</view>
+			<text v-else-if="!hasMore && blocks.length > 0" class="no-more-text">没有更多地块了</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		fetchUserFieldList,
+		getUserCurrentField,
+		searchUserField
+	} from '@/api/services/field.js';
+	import storage from "@/utils/storage.js";
+	export default {
+		// 配置页面的下拉刷新
+		onPullDownRefresh: true,
+
+		data() {
+			return {
+				isLoading: true,
+				searchKeyword: '',
+				currentBlock: {
+					id: '',
+					code: '',
+					name: '',
+					farmName: '',
+					manager: '',
+					area: 0,
+					type: '',
+					crop: '',
+					status: 'active',
+					deviceCount: 0,
+					onlineDevices: 0,
+					alerts: 0
+				},
+				blocks: [],
+				searchTimer: null,
+				// 添加分页相关数据
+				pageNum: 1, // 当前页码
+				pageSize: 10, // 每页数量
+				totalCount: 0, // 总记录数
+				loadingMore: false, // 是否正在加载更多
+				hasMore: true, // 是否还有更多数据
+				isLoadingTip: false, // 是否显示底部加载提示
+				refreshing: false // 是否正在下拉刷新
+			}
+		},
+
+		computed: {
+			filteredBlocks() {
+				return this.blocks;
+			}
+		},
+
+		mounted() {
+			// 获取当前选中地块
+			// this.fetchCurrentField();
+
+			// 获取地块列表
+			this.getFieldList(true);
+		},
+
+		// 添加页面触底事件处理函数
+		onReachBottom() {
+			this.loadMore();
+		},
+
+		// 下拉刷新
+		onPullDownRefresh() {
+			this.refreshing = true;
+			// 重置页码并刷新列表
+			this.getFieldList(true);
+
+			// 延迟关闭刷新动画
+			setTimeout(() => {
+				this.refreshing = false;
+				uni.stopPullDownRefresh();
+			}, 1000);
+		},
+
+		methods: {
+			// 获取当前选中的地块
+			fetchCurrentField() {
+				try {
+					// 获取当前登录用户的默认地块
+					getUserCurrentField().then((res) => {
+						console.log("fetchCurrentField", res);
+						if (res.data && res.data.code === 200 && res.data.data) {
+							this.currentBlock = res.data.data;
+						} else {
+							// 如果没有当前选中地块,则在获取列表成功后设置第一个为当前地块
+							console.log('未查询到当前地块,将使用列表第一个地块');
+						}
+					}).catch(err => {
+						console.error('获取当前地块失败', err);
+					});
+				} catch (e) {
+					console.log("fetchCurrentField 异常", e);
+				}
+			},
+
+			// 获取地块列表
+			getFieldList(isRefresh = false) {
+				console.log("执行情况");
+				// 刷新时重置页码
+				if (isRefresh) {
+					this.pageNum = 1;
+					this.blocks = [];
+					this.hasMore = true;
+				}
+
+				if (!this.hasMore && !isRefresh) {
+					return; // 如果没有更多数据且不是刷新,则不请求
+				}
+
+				// 标记正在加载
+				if (this.pageNum === 1) {
+					this.isLoading = true;
+				} else {
+					this.loadingMore = true;
+					this.isLoadingTip = true;
+				}
+				console.log("当前页码值:", this.pageNum);
+				// 获取当前登录用户关联的地块列表
+				fetchUserFieldList(
+					this.pageNum,
+					this.pageSize
+				).then((res) => {
+					if (this.pageNum === 1) {
+						this.isLoading = false;
+					} else {
+						this.loadingMore = false;
+					}
+					console.log("地块res", res);
+
+
+					if (res.data && res.data.code === 200 && res.data.data) {
+						// 获取总数
+						this.totalCount = res.data.data.total || 0;
+
+						// 追加数据,而不是替换
+						if (this.pageNum === 1) {
+							this.blocks = res.data.data.list;
+						} else {
+							this.blocks = [...this.blocks, ...res.data.data.list];
+						}
+
+						// 判断是否还有更多数据
+						this.hasMore = this.blocks.length < this.totalCount;
+
+						// 尝试从本地存储中读取上次选择的地块
+						if (this.pageNum === 1) {
+							this.loadSavedBlock();
+
+							// 如果当前没有选中地块,则设置第一个为当前地块
+							if (!this.currentBlock.id && this.blocks.length > 0) {
+								this.currentBlock = this.blocks[0];
+
+								// 保存当前选择的地块到本地存储
+								this.saveCurrentBlockToStorage(this.currentBlock);
+							}
+						}
+
+						// 页码加1,为下次加载做准备
+						this.pageNum++;
+					} else {
+						this.isLoading = false;
+						this.loadingMore = false;
+						this.hasMore = false;
+						console.error('获取地块列表失败', res);
+						uni.showToast({
+							title: '获取地块列表失败',
+							icon: 'none'
+						});
+					}
+
+					// 2秒后隐藏加载提示
+					setTimeout(() => {
+						this.isLoadingTip = false;
+					}, 2000);
+				}).catch(err => {
+					this.isLoading = false;
+					this.loadingMore = false;
+					this.hasMore = false;
+					console.error('获取地块列表失败', err);
+					uni.showToast({
+						title: '获取地块列表失败',
+						icon: 'none'
+					});
+
+					// 隐藏加载提示
+					this.isLoadingTip = false;
+				});
+			},
+
+			// 根据关键字搜索地块
+			searchFields(keyword) {
+				console.log("keyword",keyword);
+				if (!keyword) {
+					this.getFieldList(true);
+					return;
+				}
+
+				// 重置分页数据
+				this.pageNum = 1;
+				this.blocks = [];
+				this.hasMore = true;
+				this.isLoading = true;
+
+				// 使用用户关联地块搜索接口
+				searchUserField({
+					keyword: keyword,
+					pageNum: this.pageNum,
+					pageSize: this.pageSize
+				}).then((res) => {
+					this.isLoading = false;
+
+					if (res.data && res.data.code === 200 && res.data.data.list) {
+						this.blocks = res.data.data.list;
+						// 搜索结果可能没有总数信息,根据返回数据判断是否有更多
+						this.hasMore = res.data.data.total >= this.pageSize;
+
+						// 增加页码为下次加载做准备
+						this.pageNum++;
+					}
+				}).catch(err => {
+					this.isLoading = false;
+					this.hasMore = false;
+					console.error('搜索地块失败', err);
+				});
+			},
+
+			goBack() {
+				uni.navigateBack();
+			},
+
+			handleSearch() {
+				// 防抖处理,避免频繁请求
+				if (this.searchTimer) {
+					clearTimeout(this.searchTimer);
+				}
+
+				this.searchTimer = setTimeout(() => {
+					this.searchFields(this.searchKeyword);
+				}, 500);
+			},
+
+			clearSearch() {
+				this.searchKeyword = '';
+				this.getFieldList(true);
+			},
+
+			handleBlockClick(block) {
+				// 如果点击当前已选中的地块,不做任何操作
+				if (this.currentBlock.id === block.id) return;
+
+				// 弹出确认框
+				uni.showModal({
+					title: '切换地块',
+					content: '是否切换到该地块?切换后将查看该地块的相关设备数据。',
+					cancelText: '取消',
+					confirmText: '确定',
+					success: (res) => {
+						if (res.confirm) {
+							this.selectBlock(block);
+						}
+					}
+				});
+			},
+
+			selectBlock(block) {
+				this.currentBlock = block;
+
+				// 保存当前选择的地块到本地存储
+				this.saveCurrentBlockToStorage(block);
+
+				// 触发选择事件,传递地块ID
+				this.$emit('selectBlock', block.id);
+
+				// 获取页面参数,检查是否需要返回
+				const pages = getCurrentPages();
+				const currentPage = pages[pages.length - 1];
+				let eventChannel;
+
+				// 尝试获取页面参数和事件通道
+				let shouldReturn = true; // 默认行为是返回
+				try {
+					const options = currentPage.options || {};
+					// 获取事件通道(如果存在)
+					eventChannel = currentPage.getOpenerEventChannel && currentPage.getOpenerEventChannel();
+
+					// 如果有redirect参数,则跳转到指定页面而不是返回
+					if (options.redirect) {
+						shouldReturn = false;
+						uni.redirectTo({
+							url: decodeURIComponent(options.redirect),
+							success: () => {
+								// 跳转成功后传递选中的地块数据
+								if (eventChannel) {
+									eventChannel.emit('selectBlockResult', {
+										success: true,
+										blockId: block.id,
+										blockData: block
+									});
+								}
+							}
+						});
+					} else if (options.noReturn === 'true') {
+						// 如果设置了noReturn参数,则不执行返回操作
+						shouldReturn = false;
+					}
+				} catch (e) {
+					console.error('获取页面参数失败', e);
+				}
+
+				// 如果需要返回上一页,则执行返回操作
+				if (shouldReturn) {
+					setTimeout(() => {
+						uni.navigateBack({
+							success: () => {
+								// 返回成功后传递选中的地块数据
+								if (eventChannel) {
+									eventChannel.emit('selectBlockResult', {
+										success: true,
+										blockId: block.id,
+										blockData: block
+									});
+								}
+							}
+						});
+					}, 300);
+				}
+			},
+
+			// 保存当前选择的地块到本地存储
+			saveCurrentBlockToStorage(block) {
+				try {
+					this.currentBlock = block
+					console.log("this.currentBlock", this.currentBlock);
+					console.log("block", block);
+					storage.setPlots(JSON.stringify({
+						id: block.id,
+						code: block.code,
+						name: block.name,
+						timestamp: Date.now()
+					}))
+				} catch (e) {
+					console.error('保存地块选择状态失败', e);
+				}
+			},
+
+			// 从本地存储加载上次选择的地块
+			loadSavedBlock() {
+				try {
+					const savedPlot = storage.getPlots();
+					if (savedPlot) {
+						const plotData = JSON.parse(savedPlot);
+						// 如果存储的地块在当前地块列表中,则设置为当前选中地块
+						const matchedBlock = this.blocks.find(block => block.id == plotData.id);
+						if (matchedBlock) {
+							this.currentBlock = matchedBlock;
+						}
+					}
+				} catch (e) {
+					console.error('读取保存的地块失败', e);
+				}
+			},
+
+			getStatusClass(status) {
+				const statusMap = {
+					'active': 'status-active',
+					'idle': 'status-idle',
+					'maintenance': 'status-maintenance'
+				}
+				return statusMap[status] || '';
+			},
+
+			getStatusText(status) {
+				const statusMap = {
+					'active': '使用中',
+					'idle': '闲置',
+					'maintenance': '维护中'
+				}
+				return statusMap[status] || '未知';
+			},
+
+			// 可以被父组件调用的方法
+			onBack(callback) {
+				if (typeof callback === 'function') {
+					callback(this.currentBlock.id);
+				}
+			},
+
+			// 加载更多数据
+			loadMore() {
+				if (this.loadingMore || !this.hasMore) return;
+				this.getFieldList();
+			}
+		}
+	}
+</script>
+
+<style>
+	.container {
+		min-height: 100vh;
+		background-color: #F5F7FA;
+		padding-bottom: 30rpx;
+	}
+
+	/* 头部导航 */
+	.header {
+		display: none;
+		/* 隐藏整个头部标题栏 */
+	}
+
+	.back-button {
+		width: 60rpx;
+		height: 60rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.icon-back {
+		font-size: 36rpx;
+		color: #333;
+	}
+
+	.page-title {
+		flex: 1;
+		text-align: center;
+		font-size: 32rpx;
+		font-weight: bold;
+		color: #333;
+		margin-right: 60rpx;
+		/* 平衡左侧返回按钮 */
+	}
+
+	/* 搜索框 */
+	.search-box {
+		padding: 20rpx 30rpx;
+		background-color: #FFFFFF;
+		border-bottom: 1px solid rgba(0, 0, 0, 0.03);
+		margin-bottom: 20rpx;
+	}
+
+	.search-header {
+		font-size: 28rpx;
+		color: #333;
+		font-weight: 500;
+		margin-bottom: 15rpx;
+	}
+
+	.search-input {
+		display: flex;
+		align-items: center;
+		height: 70rpx;
+		background-color: #F5F7FA;
+		border-radius: 35rpx;
+		padding: 0 30rpx;
+		box-shadow: inset 0 1rpx 3rpx rgba(0, 0, 0, 0.05);
+		border: 1rpx solid rgba(0, 0, 0, 0.03);
+	}
+
+	.icon-search {
+		font-size: 28rpx;
+		color: #999;
+		margin-right: 10rpx;
+	}
+
+	.search-input input {
+		flex: 1;
+		height: 70rpx;
+		font-size: 28rpx;
+		color: #333;
+	}
+
+	.clear-icon {
+		width: 40rpx;
+		height: 40rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		font-size: 32rpx;
+		color: #999;
+	}
+
+	/* 块区域通用样式 */
+	.current-block,
+	.block-list {
+		margin: 0 30rpx 20rpx;
+		background-color: #FFFFFF;
+		padding: 24rpx;
+		border-radius: 24rpx;
+		box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
+	}
+
+	.block-header {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		margin-bottom: 20rpx;
+	}
+
+	.block-header .left {
+		display: flex;
+		align-items: center;
+	}
+
+	.icon-tag {
+		font-size: 24rpx;
+		color: #FFFFFF;
+		background: linear-gradient(135deg, #66CC6A 0%, #3BB44A 100%);
+		padding: 4rpx 16rpx;
+		border-radius: 6rpx;
+		margin-right: 16rpx;
+		box-shadow: 0 2rpx 5rpx rgba(59, 180, 74, 0.2);
+	}
+
+	.block-header .title {
+		font-size: 30rpx;
+		font-weight: bold;
+		color: #333;
+	}
+
+	.block-header .count {
+		font-size: 24rpx;
+		color: #999;
+		background-color: #F5F7FA;
+		padding: 4rpx 16rpx;
+		border-radius: 20rpx;
+	}
+
+	/* 当前选中地块卡片 */
+	.current-block-card {
+		background: linear-gradient(to right, #F0F8F0, #E7F5E8);
+		border-radius: 16rpx;
+		padding: 30rpx;
+		position: relative;
+		border: 2rpx solid rgba(59, 180, 74, 0.2);
+		box-shadow: 0 4rpx 16rpx rgba(59, 180, 74, 0.1);
+	}
+
+	.current-tag {
+		position: absolute;
+		top: 0;
+		right: 20rpx;
+		background: linear-gradient(135deg, #66CC6A 0%, #3BB44A 100%);
+		color: white;
+		font-size: 22rpx;
+		padding: 6rpx 16rpx;
+		border-radius: 0 0 12rpx 12rpx;
+		font-weight: bold;
+	}
+
+	/* 地块列表卡片 */
+	.block-cards {
+		display: flex;
+		flex-direction: column;
+		gap: 20rpx;
+	}
+
+	.block-card {
+		background-color: #FFFFFF;
+		border-radius: 16rpx;
+		padding: 30rpx;
+		box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
+		position: relative;
+		border: 1rpx solid rgba(0, 0, 0, 0.03);
+		transition: all 0.3s ease;
+	}
+
+	.block-card:active {
+		transform: scale(0.98);
+		box-shadow: 0 1rpx 5rpx rgba(0, 0, 0, 0.03);
+	}
+
+	.block-card.active-block {
+		border: 2rpx solid #3BB44A;
+		background-color: #F0F8F0;
+		box-shadow: 0 4rpx 16rpx rgba(59, 180, 74, 0.1);
+	}
+
+	.block-card.clickable {
+		cursor: pointer;
+	}
+
+	.block-card.clickable:hover {
+		box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
+	}
+
+	.block-content {
+		display: flex;
+		align-items: flex-start;
+		position: relative;
+		margin-bottom: 20rpx;
+	}
+
+	.block-icon {
+		width: 40rpx;
+		margin-right: 15rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.location-icon {
+		width: 36rpx;
+		height: 36rpx;
+	}
+
+	.block-info {
+		flex: 1;
+	}
+
+	.block-name {
+		font-size: 32rpx;
+		font-weight: bold;
+		color: #333;
+		margin-bottom: 6rpx;
+	}
+
+	.block-farm {
+		font-size: 26rpx;
+		color: #666;
+		margin-bottom: 10rpx;
+	}
+
+	.block-meta {
+		font-size: 26rpx;
+		color: #999;
+		margin-bottom: 10rpx;
+	}
+
+	.block-details {
+		font-size: 26rpx;
+		color: #666;
+	}
+
+	.separator {
+		margin: 0 10rpx;
+		color: #ccc;
+	}
+
+	.check-mark {
+		position: absolute;
+		right: 0;
+		top: 0;
+	}
+
+	.check-icon {
+		width: 48rpx;
+		height: 48rpx;
+	}
+
+	/* 状态标签 */
+	.status-badge {
+		position: absolute;
+		top: 0;
+		right: 0;
+		font-size: 22rpx;
+		padding: 4rpx 12rpx;
+		border-radius: 0 16rpx 0 12rpx;
+		font-weight: 500;
+		z-index: 1;
+	}
+
+	.status-active-badge {
+		background-color: #E6F7E6;
+		color: #3BB44A;
+		border-left: 1rpx solid rgba(59, 180, 74, 0.2);
+		border-bottom: 1rpx solid rgba(59, 180, 74, 0.2);
+	}
+
+	.status-idle-badge {
+		background-color: #F1F2F3;
+		color: #909399;
+		border-left: 1rpx solid rgba(144, 147, 153, 0.2);
+		border-bottom: 1rpx solid rgba(144, 147, 153, 0.2);
+	}
+
+	.status-maintenance-badge {
+		background-color: #FEF0F0;
+		color: #F56C6C;
+		border-left: 1rpx solid rgba(245, 108, 108, 0.2);
+		border-bottom: 1rpx solid rgba(245, 108, 108, 0.2);
+	}
+
+	/* 地块统计信息 */
+	.block-stats {
+		display: flex;
+		align-items: center;
+		flex-wrap: wrap;
+		border-top: 1rpx solid #F0F0F0;
+		padding-top: 20rpx;
+	}
+
+	.stat-item {
+		display: flex;
+		align-items: center;
+		margin-right: 24rpx;
+		font-size: 26rpx;
+		color: #666;
+	}
+
+	.stat-icon {
+		width: 36rpx;
+		height: 36rpx;
+		margin-right: 8rpx;
+		flex-shrink: 0;
+	}
+
+	.online-icon {
+		/* 在线图标使用绿色 */
+		filter: hue-rotate(120deg) saturate(1.2);
+	}
+
+	.alert-icon {
+		/* 告警图标使用红色 */
+		filter: hue-rotate(0deg) saturate(1.5);
+	}
+
+	.alert-text {
+		color: #F56C6C;
+	}
+
+	/* 骨架屏 */
+	.skeleton-container {
+		display: flex;
+		flex-direction: column;
+		gap: 20rpx;
+	}
+
+	.skeleton-box {
+		background-color: #FFFFFF;
+		border-radius: 16rpx;
+		padding: 20rpx;
+		margin-bottom: 10rpx;
+		box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
+		animation: skeleton-loading 1.5s infinite;
+	}
+
+	@keyframes skeleton-loading {
+		0% {
+			opacity: 0.7;
+		}
+
+		50% {
+			opacity: 0.5;
+		}
+
+		100% {
+			opacity: 0.7;
+		}
+	}
+
+	.skeleton-header {
+		display: flex;
+		align-items: flex-start;
+	}
+
+	.skeleton-icon {
+		width: 40rpx;
+		height: 40rpx;
+		background-color: #EEEEEE;
+		border-radius: 8rpx;
+		margin-right: 15rpx;
+	}
+
+	.skeleton-info {
+		flex: 1;
+	}
+
+	.skeleton-title {
+		width: 200rpx;
+		height: 32rpx;
+		background-color: #EEEEEE;
+		margin-bottom: 10rpx;
+		border-radius: 4rpx;
+	}
+
+	.skeleton-detail {
+		width: 300rpx;
+		height: 24rpx;
+		background-color: #EEEEEE;
+		border-radius: 4rpx;
+	}
+
+	.skeleton-stats {
+		margin-top: 16rpx;
+		padding-top: 16rpx;
+		border-top: 1rpx solid #F5F5F5;
+		height: 30rpx;
+		background-color: #EEEEEE;
+		border-radius: 4rpx;
+	}
+
+	/* 空状态 */
+	.empty-state {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		padding: 60rpx 0;
+	}
+
+	.empty-image {
+		width: 240rpx;
+		height: 240rpx;
+		margin-bottom: 20rpx;
+		opacity: 0.7;
+	}
+
+	.empty-text {
+		font-size: 32rpx;
+		color: #666;
+		font-weight: 500;
+		margin-bottom: 10rpx;
+	}
+
+	.empty-subtext {
+		font-size: 26rpx;
+		color: #999;
+	}
+
+	/* 基础图标样式 */
+	.iconfont {
+		font-family: "iconfont" !important;
+		font-style: normal;
+		-webkit-font-smoothing: antialiased;
+		-moz-osx-font-smoothing: grayscale;
+	}
+
+	/* 底部加载提示区域 */
+	.loading-more {
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		padding: 20rpx 0;
+		background-color: #FFFFFF;
+		border-top: 1px solid rgba(0, 0, 0, 0.03);
+	}
+
+	.loading-text {
+		display: flex;
+		align-items: center;
+		font-size: 28rpx;
+		color: #666;
+	}
+
+	.loading-icon {
+		width: 40rpx;
+		height: 40rpx;
+		margin-right: 10rpx;
+		background-color: #3BB44A;
+		border-radius: 50%;
+		animation: spin 1s linear infinite;
+	}
+
+	@keyframes spin {
+		0% {
+			transform: rotate(0deg);
+		}
+
+		100% {
+			transform: rotate(360deg);
+		}
+	}
+
+	.no-more-text {
+		font-size: 28rpx;
+		color: #999;
+		margin-left: 10rpx;
+	}
+</style>

+ 33 - 8
pages/user/index.vue

@@ -3,7 +3,7 @@
 		<!-- 用户信息卡片 -->
 		<view class="user-card">
 			<view class="user-header">
-				<image class="avatar" :src="userInfo.avatar || '/static/images/default-avatar.png'"></image>
+				<image class="avatar" :src="userInfo.avatar || '/static/icons/user_icon.png'"></image>
 				<view class="user-detail" v-if="isLogin">
 					<text class="nickname">{{userInfo.nickName}}</text>
 					<text class="user-id">性别: {{userInfo.sex == '0' ? '男' :'女' || '未知'}}</text>
@@ -92,14 +92,17 @@
 	import {
 		logout
 	} from '@/api/services/connect.js';
+	import {
+		countUserPlots
+	} from '@/api/services/field.js';
 	import storage from "@/utils/storage.js";
 	export default {
 		data() {
 			return {
 				plotInfo: {
-					total: 3,
-					active: 2,
-					idle: 1
+					total: 0,
+					active: 0,
+					idle: 0
 				},
 				serviceList: [{
 						name: '农资商城',
@@ -128,17 +131,35 @@
 					}
 				],
 				userInfo: {
-					nickName: '游客',
+					nickName: '',
 					id: '',
-					avatar: '/static/images/icon.png'
+					avatar: '',
+					sex:''
 				},
 				isLogin: false
 			}
 		},
 		onShow() {
 			this.checkLoginStatus();
+			if(this.isLogin){
+				this.userPlots();
+			}
 		},
 		methods: {
+			userPlots(){
+				countUserPlots().then((res=>{
+					if (res.data.code == 200) {
+						const {plotsTotal,inUseCount,leiSureCount} = res.data.data
+						this.plotInfo = {
+							total: plotsTotal,
+							active: inUseCount,
+							idle: leiSureCount
+						}
+					} else{
+						console.error("统计地块数量失败!")
+					}
+				}))
+			},
 			// 检查登录状态
 			checkLoginStatus() {
 				console.log("执行Show");
@@ -148,7 +169,11 @@
 					const userInfo = storage.getUserInfo();
 					console.log("执行Show",userInfo);
 					if (userInfo) {
-						this.userInfo = userInfo;
+						this.userInfo = {
+							nickName: userInfo.nickName || '游客',
+							avatar: userInfo.avatar || '/static/icons/user_icon.png',
+							sex:userInfo.sex
+						};
 					}
 				} else {
 					this.isLogin = false;
@@ -196,7 +221,7 @@
 								this.userInfo = {
 									nickname: '游客',
 									id: '',
-									avatar: '/static/images/icon.png'
+									avatar: '/static/icons/user_icon'
 								};
 							});
 						}

+ 1 - 1
pages/userInfo/index.vue

@@ -14,7 +14,7 @@
 		<!-- 头像授权 -->
 		<view class="avatar-section">
 			<button class="avatar-button" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
-				<image class="avatar" :src="userInfo.avatarUrl || '/static/images/icon.png'" mode="aspectFill"></image>
+				<image class="avatar" :src="userInfo.avatarUrl || '/static/icons/user_icon.png'" mode="aspectFill"></image>
 			</button>
 			<text class="avatar-text" v-if="isShow">授权头像</text>
 		</view>

BIN
static/icons/Pest_Alert.png


BIN
static/icons/activity-active.png


BIN
static/icons/activity.png


+ 5 - 0
static/icons/alert.svg

@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
+  <path d="M12 2L22 20H2L12 2Z" fill="#F56C6C"/>
+  <path d="M12 8v4" stroke="white" stroke-width="2" stroke-linecap="round"/>
+  <circle cx="12" cy="16" r="1" fill="white"/>
+</svg> 

BIN
static/icons/camera.png


+ 4 - 0
static/icons/check-circle.svg

@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
+  <circle cx="12" cy="12" r="10" fill="#3BB44A"/>
+  <path d="M8.5 12.5L10.5 14.5L15.5 9.5" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg> 

BIN
static/icons/control.png


BIN
static/icons/device-active.png


BIN
static/icons/device.png


+ 7 - 0
static/icons/device.svg

@@ -0,0 +1,7 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
+  <rect x="4" y="4" width="16" height="12" rx="2" ry="2" fill="#666666"/>
+  <rect x="6" y="6" width="12" height="8" rx="1" ry="1" fill="white"/>
+  <circle cx="12" cy="10" r="1.5" fill="#666666"/>
+  <rect x="9" y="17" width="6" height="1" rx="0.5" ry="0.5" fill="#666666"/>
+  <rect x="8" y="19" width="8" height="1" rx="0.5" ry="0.5" fill="#666666"/>
+</svg> 

BIN
static/icons/home 1.png


BIN
static/icons/home-active 1.png


BIN
static/icons/home-active.png


BIN
static/icons/home.png


BIN
static/icons/knowledge-active.png


BIN
static/icons/knowledge.png


+ 4 - 0
static/icons/location.svg

@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
+  <path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7z" fill="#3BB44A"/>
+  <circle cx="12" cy="9" r="2.5" fill="white"/>
+</svg> 

BIN
static/icons/offline.png


+ 5 - 0
static/icons/online.svg

@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
+  <circle cx="12" cy="12" r="10" fill="#3BB44A"/>
+  <circle cx="12" cy="12" r="3" fill="white"/>
+  <circle cx="12" cy="12" r="1.5" fill="#3BB44A"/>
+</svg> 

BIN
static/icons/search.png


BIN
static/icons/sensor.png


BIN
static/icons/task_delay.png


BIN
static/icons/tractor.png


BIN
static/icons/user-active.png


BIN
static/icons/user.png


BIN
static/icons/user_icon.png


BIN
static/icons/water.png


BIN
static/icons/weather_risk.png


+ 12 - 7
utils/request.js

@@ -26,18 +26,17 @@ function cleanStorage() {
 
 	storage.setHasLogin(false);
 	storage.setAccessToken("");
-	storage.setRefreshToken("");
-	console.log("清空token");
+	// storage.setRefreshToken("");
 	storage.setUuid("");
 	storage.setUserInfo({});
 
 
-	if (!isNavigateTo) {
+	/* if (!isNavigateTo) {
 		isNavigateTo = true
 		// 防抖处理跳转
 		// #ifdef MP-WEIXIN
 		uni.navigateTo({
-			url: "/pages/passport/wechatMPLogin",
+			url: "/pages/login/index",
 		});
 		// #endif
 		// #ifndef MP-WEIXIN
@@ -45,7 +44,7 @@ function cleanStorage() {
 			url: "/pages/passport/login",
 		});
 		//  #endif
-	}
+	} */
 }
 
 let http = new Request();
@@ -83,6 +82,8 @@ http.interceptors.request.use(
 		if(storage.getInviter()){
 			config.header.inviter = storage.getInviter();
 		}
+		
+		console.log("请求前处理");
 		if (accessToken) {
 			/**
 			 * 使用JWT解析
@@ -150,7 +151,9 @@ http.interceptors.response.use(
 				duration: 2000,
 				complete: () => {
 					setTimeout(() => {
-						uni.reLaunch({ url: '/pages/login/index' }); // 跳转登录页
+						uni.navigateTo({
+						  url: '/pages/login/index'
+						}); // 跳转登录页
 					}, 2000);
 				}
 			});
@@ -167,7 +170,9 @@ http.interceptors.response.use(
 				duration: 2000,
 				complete: () => {
 					setTimeout(() => {
-						uni.reLaunch({ url: '/pages/login/index' });
+						uni.navigateTo({
+						  url: '/pages/login/index'
+						});
 					}, 2000);
 				}
 			});

+ 133 - 124
utils/storage.js

@@ -1,6 +1,7 @@
 let isDev = process.env.NODE_ENV === "development";
 
 const UUID = isDev ? "uuid_key_dev" : "uuid_key";
+const CURRENT_PLOT = isDev ? "current_plot_dev" : "current_plot";
 const HAS_LOGIN = isDev ? "has_login_key_dev" : "has_login_key";
 const ACCESS_TOKEN = isDev ? "access_token_key_dev" : "access_token_key";
 const REFRESH_TOKEN = isDev ? "refresh_token_key_dev" : "refresh_token_key";
@@ -10,135 +11,143 @@ const FINGER_LOGIN = isDev ? "finger_login_dev" : "finger_login";
 const CART_BACKBTN = isDev ? "cart_backbtn_dev" : "cart_backbtn";
 const AFTERSALE_DATA = isDev ? "aftersale_data_dev" : "aftersale_data";
 export default {
-	setInviter(val){
+	setInviter(val) {
 		uni.setStorageSync('inviter', val)
 	},
-	getInviter(){
+	getInviter() {
 		return uni.getStorageSync('inviter');
 	},
 
-  //写入自动发券
-  setAutoCp(val){
-    uni.setStorageSync('autoCp', val)
-  },
-  //获取自动发券时间
-  getAutoCp(){
-    return uni.getStorageSync('autoCp');
-  },
-  // 写入热门搜索时间戳
-  setHotWords(val) {
-    uni.setStorageSync("hotWords", val);
-  },
-  // 获取热门搜索时间戳
-  getHotWords() {
-    return uni.getStorageSync(`hotWords`);
-  },
-  //写入 展示还是不展示
-  setShow(val) {
-    uni.setStorageSync("show", val);
-  },
-  getShow() {
-    if (uni.getStorageSync(`show`) === "" || uni.getStorageSync(`show`) === undefined) {
-      return true;
-    }
-    return uni.getStorageSync(`show`);
-  },
-  // 获取face id登录
-  getFaceLogin() {
-    return uni.getStorageSync(FACE_LOGIN);
-  },
-  // 写入face id
-  setFaceLogin(val) {
-    uni.setStorageSync(FACE_LOGIN, val);
-  },
-  // 获取指纹登录
-  getFingerLogin() {
-    return uni.getStorageSync(FINGER_LOGIN);
-  },
-  // 写入指纹登录
-  setFingerLogin(val) {
-    uni.setStorageSync(FINGER_LOGIN, val);
-  },
-  // 写入用户信息
-  setUserInfo(val) {
-    uni.setStorageSync(USER_INFO, val);
-  },
-  // 获取用户信息
-  getUserInfo() {
-    return uni.getStorageSync(USER_INFO);
-  },
-  setTalkToUser(val){
-    uni.setStorageSync("TALK_TO_USER", val);
-  },
-  getTalkToUser(){
-    return uni.getStorageSync("TALK_TO_USER");
-  },
-  // 写入uuid
-  setUuid(val) {
-    uni.setStorageSync(UUID, val);
-  },
-  // 获取uuid
-  getUuid() {
-    return uni.getStorageSync(UUID);
-  },
-  // 写入登录
-  setHasLogin(val) {
-    uni.setStorageSync(HAS_LOGIN, val);
-  },
-  // 获取是否登录
-  getHasLogin() {
-    return uni.getStorageSync(HAS_LOGIN);
-  },
-  // 删除uuid
-  removeUuid() {
-    uni.removeStorageSync(UUID);
-  },
-  // 写入accessToken
-  setAccessToken(val) {
-    uni.setStorageSync(ACCESS_TOKEN, val);
-  },
-  // 获取accessToken
-  getAccessToken() {
-    return uni.getStorageSync(ACCESS_TOKEN);
-  },
-  // 后退购物车
-  setCartBackbtn(val) {
-    uni.setStorageSync(CART_BACKBTN, val);
-  },
+	//写入自动发券
+	setAutoCp(val) {
+		uni.setStorageSync('autoCp', val)
+	},
+	//获取自动发券时间
+	getAutoCp() {
+		return uni.getStorageSync('autoCp');
+	},
+	// 写入热门搜索时间戳
+	setHotWords(val) {
+		uni.setStorageSync("hotWords", val);
+	},
+	// 获取热门搜索时间戳
+	getHotWords() {
+		return uni.getStorageSync(`hotWords`);
+	},
+	//写入 展示还是不展示
+	setShow(val) {
+		uni.setStorageSync("show", val);
+	},
+	getShow() {
+		if (uni.getStorageSync(`show`) === "" || uni.getStorageSync(`show`) === undefined) {
+			return true;
+		}
+		return uni.getStorageSync(`show`);
+	},
+	// 获取face id登录
+	getFaceLogin() {
+		return uni.getStorageSync(FACE_LOGIN);
+	},
+	// 写入face id
+	setFaceLogin(val) {
+		uni.setStorageSync(FACE_LOGIN, val);
+	},
+	// 获取指纹登录
+	getFingerLogin() {
+		return uni.getStorageSync(FINGER_LOGIN);
+	},
+	// 写入指纹登录
+	setFingerLogin(val) {
+		uni.setStorageSync(FINGER_LOGIN, val);
+	},
+	// 写入用户信息
+	setUserInfo(val) {
+		uni.setStorageSync(USER_INFO, val);
+	},
+	// 获取用户信息
+	getUserInfo() {
+		return uni.getStorageSync(USER_INFO);
+	},
+	setTalkToUser(val) {
+		uni.setStorageSync("TALK_TO_USER", val);
+	},
+	getTalkToUser() {
+		return uni.getStorageSync("TALK_TO_USER");
+	},
+	// 写入uuid
+	setUuid(val) {
+		uni.setStorageSync(UUID, val);
+	},
+	// 获取uuid
+	getUuid() {
+		return uni.getStorageSync(UUID);
+	},
+	// 写入登录
+	setHasLogin(val) {
+		uni.setStorageSync(HAS_LOGIN, val);
+	},
+	// 获取是否登录
+	getHasLogin() {
+		return uni.getStorageSync(HAS_LOGIN);
+	},
+	// 删除uuid
+	removeUuid() {
+		uni.removeStorageSync(UUID);
+	},
+	// 写入accessToken
+	setAccessToken(val) {
+		uni.setStorageSync(ACCESS_TOKEN, val);
+	},
+	// 获取accessToken
+	getAccessToken() {
+		return uni.getStorageSync(ACCESS_TOKEN);
+	},
+	// 后退购物车
+	setCartBackbtn(val) {
+		uni.setStorageSync(CART_BACKBTN, val);
+	},
 
-  // 删除token
-  removeAccessToken() {
-    uni.removeStorageSync(ACCESS_TOKEN);
-  },
-  // 写入刷新token
-  setRefreshToken(val) {
-    uni.setStorageSync(REFRESH_TOKEN, val);
-  },
-  // 获取刷新token
-  getRefreshToken() {
-    return uni.getStorageSync(REFRESH_TOKEN);
-  },
-  // 删除token
-  removeRefreshToken() {
-    uni.removeStorageSync(REFRESH_TOKEN);
-  },
+	// 删除token
+	removeAccessToken() {
+		uni.removeStorageSync(ACCESS_TOKEN);
+	},
+	// 写入刷新token
+	setRefreshToken(val) {
+		uni.setStorageSync(REFRESH_TOKEN, val);
+	},
+	// 获取刷新token
+	getRefreshToken() {
+		return uni.getStorageSync(REFRESH_TOKEN);
+	},
+	// 删除token
+	removeRefreshToken() {
+		uni.removeStorageSync(REFRESH_TOKEN);
+	},
 
-  setAfterSaleData(val) {
-    uni.setStorageSync(AFTERSALE_DATA, val);
-  },
+	setPlots(val) {
+		uni.setStorageSync(CURRENT_PLOT, val)
+	},
 
-  getAfterSaleData() {
-    return uni.getStorageSync(AFTERSALE_DATA);
-  },
-  // 删除token
-  removeAfterSaleData() {
-    uni.removeStorageSync(AFTERSALE_DATA);
-  },
-  // 是否发送商品连接记录
-  setImGoodsLink(val) {
-    uni.setStorageSync('imGoodId', val);
-  },
-  getImGoodsLink() {
-  return  uni.getStorageSync('imGoodId');
-  },
-};
+	getPlots() {
+		return uni.getStorageSync(CURRENT_PLOT)
+	},
+
+	setAfterSaleData(val) {
+		uni.setStorageSync(AFTERSALE_DATA, val);
+	},
+
+	getAfterSaleData() {
+		return uni.getStorageSync(AFTERSALE_DATA);
+	},
+	// 删除token
+	removeAfterSaleData() {
+		uni.removeStorageSync(AFTERSALE_DATA);
+	},
+	// 是否发送商品连接记录
+	setImGoodsLink(val) {
+		uni.setStorageSync('imGoodId', val);
+	},
+	getImGoodsLink() {
+		return uni.getStorageSync('imGoodId');
+	},
+};

Деякі файли не було показано, через те що забагато файлів було змінено