|
|
@@ -21,12 +21,14 @@
|
|
|
<button class="manual-btn" @click="init" :disabled="isDisable">
|
|
|
<text class="fa fa-power-off"></text> {{ isDeviceReady ? '已开启' : '开启设备' }}
|
|
|
</button>
|
|
|
- <!-- <button class="btn" type="primary" @click="release" :disabled="isReDisabled">release</button> -->
|
|
|
- <button class="scan-btn" @click="scan" :disabled="!isDisable">
|
|
|
- <text class="fa fa-camera"></text> 扫描耳标签
|
|
|
+ <!-- 释放端口按钮 -->
|
|
|
+ <!-- <button class="btn" type="primary" @click="release" :disabled="isReDisabled">release</button> -->
|
|
|
+ <button class="scan-btn" @click="toggleContinuousScan" :disabled="!isDisable">
|
|
|
+ <text class="fa fa-camera"></text> {{ isContinuousScanning ? '停止持续扫描' : '开始持续扫描' }}
|
|
|
</button>
|
|
|
</view>
|
|
|
<input class="input-box" v-model="form.earId" disabled placeholder="当前FID标签号码将显示在这里" style="height: 30px;width: 95%;" />
|
|
|
+
|
|
|
<!-- 存储的FID标签数据 -->
|
|
|
<scroll-view scroll-y class="sv">
|
|
|
<view v-for="(item, index) in dataList" :key="index" class="data-item">
|
|
|
@@ -41,7 +43,7 @@
|
|
|
</scroll-view>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 操作按钮组 -->
|
|
|
+ <!-- 操作按钮部分 -->
|
|
|
<view class="btn-group">
|
|
|
<button class="manual-btn" @click="resetForm">重置</button>
|
|
|
<button class="scan-btn" @click="submitForm">提交数据</button>
|
|
|
@@ -72,6 +74,8 @@ export default {
|
|
|
retryTimeout: null, // 重试计时器
|
|
|
maxScanTimer: null, // 最大扫描时间计时器
|
|
|
settingChangeListener: null, // 设置变化监听器
|
|
|
+ isContinuousScanning: false, // 是否正在持续扫描
|
|
|
+ continuousScanInterval: null, // 持续扫描间隔计时器
|
|
|
|
|
|
// 列表数据
|
|
|
buildingList: [], // 栋舍列表
|
|
|
@@ -123,6 +127,7 @@ export default {
|
|
|
|
|
|
// 监听全局设置变化
|
|
|
this.settingChangeListener = uni.$on('settingsUpdated', (settings) => {
|
|
|
+ console.log('监听到设置更新事件,更新设置:', settings);
|
|
|
this.loadSavedSettings(settings);
|
|
|
});
|
|
|
},
|
|
|
@@ -132,68 +137,29 @@ export default {
|
|
|
* @param {number} retryCount - 当前重试次数
|
|
|
*/
|
|
|
initializePluginWithRetry(retryCount = 0) {
|
|
|
-
|
|
|
- console.log('设备初始化成功');
|
|
|
- this.isDisable = false;
|
|
|
- uni.showToast({
|
|
|
- title: '设备初始化成功',
|
|
|
- icon: 'success',
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
-
|
|
|
- //如果开启设备 初始化失败,重试,请打开下面代码,上方代码可以删除掉
|
|
|
- const MAX_RETRIES = 1;
|
|
|
- const RETRY_DELAY = 2000; // 2秒
|
|
|
- const isPluginInitialized = this.initPluginInstance();
|
|
|
- // if (!isPluginInitialized) {
|
|
|
- // console.warn(`Plugin initialization failed (attempt ${retryCount + 1}/${MAX_RETRIES})`);
|
|
|
- // this.isDisable = true; // 禁用依赖插件的按钮
|
|
|
-
|
|
|
- // // 如果未达到最大重试次数,继续重试
|
|
|
- // if (retryCount < MAX_RETRIES) {
|
|
|
- // console.log(`Retrying plugin initialization after ${RETRY_DELAY}ms`);
|
|
|
- // setTimeout(() => {
|
|
|
- // if (this._isMounted) {
|
|
|
- // this.initializePluginWithRetry(retryCount + 1);
|
|
|
- // }
|
|
|
- // }, RETRY_DELAY);
|
|
|
- // } else {
|
|
|
- // console.error('Max retries reached for plugin initialization');
|
|
|
- // uni.showToast({
|
|
|
- // title: '设备初始化失败,请重启应用',
|
|
|
- // icon: 'none',
|
|
|
- // duration: 3000
|
|
|
- // });
|
|
|
- // }
|
|
|
- // } else {
|
|
|
- // console.log('Plugin initialized successfully');
|
|
|
- // this.isDisable = false;
|
|
|
- // uni.showToast({
|
|
|
- // title: '设备初始化成功',
|
|
|
- // icon: 'success',
|
|
|
- // duration: 2000
|
|
|
- // });
|
|
|
- // }
|
|
|
+ console.log('设备初始化成功');
|
|
|
+ this.isDisable = false;
|
|
|
},
|
|
|
|
|
|
beforeUnmount() {
|
|
|
// 标记组件已卸载
|
|
|
this._isMounted = false;
|
|
|
-
|
|
|
+ // 停止持续扫描
|
|
|
+ this.isContinuousScanning = false;
|
|
|
+ if (this.continuousScanInterval) {
|
|
|
+ clearTimeout(this.continuousScanInterval);
|
|
|
+ this.continuousScanInterval = null;
|
|
|
+ }
|
|
|
// 清除所有计时器
|
|
|
this.cancelScan();
|
|
|
-
|
|
|
// 释放设备
|
|
|
this.releaseDevice();
|
|
|
-
|
|
|
// 清理插件实例
|
|
|
this.uhfSFHelper = null;
|
|
|
-
|
|
|
// 移除事件监听
|
|
|
if (this.settingChangeListener) {
|
|
|
uni.$off('settingsUpdated', this.settingChangeListener);
|
|
|
}
|
|
|
-
|
|
|
// 移除登录成功事件监听
|
|
|
if (this.reloadUserSettingsListener) {
|
|
|
uni.$off('reloadUserSettings', this.reloadUserSettingsListener);
|
|
|
@@ -201,23 +167,81 @@ export default {
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
- * 页面显示时触发,确保获取最新的编号信息
|
|
|
+ * 页面显示时触发,确保获取最新的编号信息并检查登录状态
|
|
|
*/
|
|
|
onShow() {
|
|
|
this.loadSavedSettings();
|
|
|
+ this.checkTokenExpiration();
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
+ /**
|
|
|
+ * 检查token是否过期
|
|
|
+ */
|
|
|
+ checkTokenExpiration() {
|
|
|
+ const app = getApp();
|
|
|
+
|
|
|
+ // 获取过期时间和token
|
|
|
+ let expireAt = app.globalData.expireAt || uni.getStorageSync('token_expire_time') || '';
|
|
|
+ const token = app.globalData.token || uni.getStorageSync('equipment_token') || '';
|
|
|
+
|
|
|
+ // 如果没有token或过期时间,视为未登录
|
|
|
+ if (!token || !expireAt) {
|
|
|
+ console.log('未登录或缺少登录信息');
|
|
|
+ // 不要直接跳转登录页,让App.vue的checkLoginStatus来处理
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 解析过期时间和当前时间
|
|
|
+ let expireTime;
|
|
|
+
|
|
|
+ // 处理不同类型的expireAt
|
|
|
+ if (typeof expireAt === 'string') {
|
|
|
+ // 尝试直接解析为数字
|
|
|
+ const timestamp = parseInt(expireAt);
|
|
|
+ if (!isNaN(timestamp)) {
|
|
|
+ expireTime = timestamp;
|
|
|
+ } else {
|
|
|
+ // 如果不是数字字符串,尝试作为日期字符串解析
|
|
|
+ expireTime = new Date(expireAt).getTime();
|
|
|
+ }
|
|
|
+ } else if (typeof expireAt === 'number') {
|
|
|
+ // 如果已经是数字类型,直接使用
|
|
|
+ expireTime = expireAt;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 确保过期时间有效
|
|
|
+ if (isNaN(expireTime)) {
|
|
|
+ console.error('无效的过期时间:', expireAt);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const currentTime = new Date().getTime();
|
|
|
+
|
|
|
+ // 提前1分钟检查过期,给用户预留时间
|
|
|
+ const earlyCheckTime = 60 * 1000;
|
|
|
+ if (currentTime + earlyCheckTime > expireTime) {
|
|
|
+ console.log('登录即将过期或已过期');
|
|
|
+ // 不要直接跳转登录页,让App.vue的checkLoginStatus来处理
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('检查token过期时发生错误:', error);
|
|
|
+ }
|
|
|
+ },
|
|
|
/**
|
|
|
* 带重试的插件初始化
|
|
|
* @param {number} retryCount - 当前重试次数
|
|
|
*/
|
|
|
initializePluginWithRetry(retryCount = 0) {
|
|
|
- const MAX_RETRIES = 1;
|
|
|
+ const MAX_RETRIES = 3; // 增加重试次数到3次
|
|
|
const RETRY_DELAY = 2000; // 2秒
|
|
|
+
|
|
|
+ console.log(`开始插件初始化尝试 ${retryCount + 1}/${MAX_RETRIES}`);
|
|
|
+
|
|
|
const isPluginInitialized = this.initPluginInstance();
|
|
|
if (!isPluginInitialized) {
|
|
|
- console.warn(`Plugin initialization failed (attempt ${retryCount + 1}/${MAX_RETRIES})`);
|
|
|
+ console.warn(`插件初始化失败 (attempt ${retryCount + 1}/${MAX_RETRIES})`);
|
|
|
this.isDisable = true; // 禁用依赖插件的按钮
|
|
|
|
|
|
// 如果未达到最大重试次数,继续重试
|
|
|
@@ -251,82 +275,116 @@ export default {
|
|
|
* @param {number} retryCount - 当前重试次数(默认0)
|
|
|
*/
|
|
|
fetchBuildingList(retryCount = 0) {
|
|
|
+ const MAX_RETRIES = 2; // 最大重试次数
|
|
|
+
|
|
|
// 显示加载提示
|
|
|
if (retryCount === 0) {
|
|
|
uni.showLoading({ title: '加载栋舍列表...', mask: true });
|
|
|
}
|
|
|
|
|
|
- // 发送请求到API获取栋舍列表
|
|
|
+ //获取栋舍列表
|
|
|
uni.request({
|
|
|
url: API.getBuilding,
|
|
|
method: 'GET',
|
|
|
timeout: 10000, // 增加超时时间到10秒
|
|
|
+ header: {
|
|
|
+ 'content-type': 'application/x-www-form-urlencoded',
|
|
|
+ "x-token": uni.getStorageSync('equipment_token') || ''
|
|
|
+ },
|
|
|
success: (res) => {
|
|
|
// 隐藏加载提示
|
|
|
if (retryCount === 0) {
|
|
|
uni.hideLoading();
|
|
|
}
|
|
|
- // 更新栋舍列表
|
|
|
- this.buildingList = res.data.data || [];
|
|
|
+ this.buildingList = res.data.data || [];
|
|
|
+ },
|
|
|
+
|
|
|
+ complete: () => {
|
|
|
+ // 确保最终隐藏loading
|
|
|
+ if (retryCount === MAX_RETRIES) {
|
|
|
+ uni.hideLoading();
|
|
|
+ }
|
|
|
}
|
|
|
});
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
* 加载已保存的设置
|
|
|
- * @param {object} settings - 可选的设置参数
|
|
|
*/
|
|
|
loadSavedSettings(settings = null) {
|
|
|
- const app = getApp();
|
|
|
-
|
|
|
- let buildingName, roomName, penNo;
|
|
|
-
|
|
|
- // 如果提供了设置参数,优先使用参数值
|
|
|
- if (settings && typeof settings === 'object') {
|
|
|
- buildingName = settings.building || '';
|
|
|
- roomName = settings.room || '';
|
|
|
- penNo = settings.pen || '';
|
|
|
-
|
|
|
- // 更新全局数据
|
|
|
- app.globalData.buildingName = buildingName;
|
|
|
- app.globalData.roomName = roomName;
|
|
|
- app.globalData.penNo = penNo;
|
|
|
-
|
|
|
- // 更新本地存储
|
|
|
- uni.setStorageSync('buildingName', buildingName);
|
|
|
- uni.setStorageSync('roomName', roomName);
|
|
|
- uni.setStorageSync('penNo', penNo);
|
|
|
- } else {
|
|
|
- // 从全局数据或本地存储获取编号信息
|
|
|
- buildingName = app.globalData.buildingName || uni.getStorageSync('buildingName') || '';
|
|
|
- roomName = app.globalData.roomName || uni.getStorageSync('roomName') || '';
|
|
|
- penNo = app.globalData.penNo || uni.getStorageSync('penNo') || '';
|
|
|
- }
|
|
|
|
|
|
- // 更新表单数据
|
|
|
- this.form.buildingName = buildingName;
|
|
|
- this.form.roomName = roomName;
|
|
|
- this.form.penNo = penNo;
|
|
|
-
|
|
|
- // 如果栋舍不为空且房间列表为空,加载房间列表
|
|
|
- if (buildingName && this.roomList.length === 0) {
|
|
|
- this.fetchRoomList(buildingName);
|
|
|
- } else if (buildingName && this.roomList.length > 0 && roomName) {
|
|
|
- // 如果房间已变更,更新房间列表
|
|
|
- this.fetchRoomList(buildingName);
|
|
|
- }
|
|
|
+ const app = getApp();
|
|
|
+ console.log('当前全局数据完整内容:', JSON.stringify(app.globalData));
|
|
|
+
|
|
|
+ const buildingName = uni.getStorageSync('building') || '';
|
|
|
+ const roomName = uni.getStorageSync('room') || '';
|
|
|
+ const penNo = uni.getStorageSync('pen') || '';
|
|
|
+
|
|
|
+ this.form.buildingName = buildingName;
|
|
|
+ this.form.roomName = roomName;
|
|
|
+ this.form.penNo = penNo;
|
|
|
+
|
|
|
+ console.log('表单最终赋值结果', this.form.buildingName);
|
|
|
+ console.log('表单最终赋值结果', this.form.roomName);
|
|
|
+ console.log('表单最终赋值结果', this.form.penNo);
|
|
|
+
|
|
|
+ // 如果栋舍不为空且房间列表为空,加载房间列表
|
|
|
+ if (buildingName && this.roomList.length === 0) {
|
|
|
+ this.fetchRoomList(buildingName);
|
|
|
+ } else if (buildingName && this.roomList.length > 0 && roomName) {
|
|
|
+ // 如果房间已变更,更新房间列表
|
|
|
+ this.fetchRoomList(buildingName);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果房间不为空且栏位列表为空,加载栏位列表
|
|
|
+ if (roomName && this.Fieldnumber.length === 0) {
|
|
|
+ this.fetchFieldList(roomName);
|
|
|
+ } else if (roomName && this.Fieldnumber.length > 0 && penNo) {
|
|
|
+ // 如果栏位已变更,更新栏位列表
|
|
|
+ this.fetchFieldList(roomName);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 手动刷新全局数据
|
|
|
+ */
|
|
|
+ refreshGlobalData() {
|
|
|
+ console.log('手动刷新全局数据');
|
|
|
+
|
|
|
+ // 尝试从本地存储恢复最新数据到全局数据
|
|
|
+ try {
|
|
|
+ const app = getApp();
|
|
|
+ const token = uni.getStorageSync('equipment_token') || '';
|
|
|
+ const expireAt = uni.getStorageSync('token_expire_time') || '';
|
|
|
+ const userInfo = uni.getStorageSync('user_info') || {};
|
|
|
+ const building = uni.getStorageSync('building') || '';
|
|
|
+ const room = uni.getStorageSync('room') || '';
|
|
|
+ const pen = uni.getStorageSync('pen') || '';
|
|
|
|
|
|
- // 如果房间不为空且栏位列表为空,加载栏位列表
|
|
|
- if (roomName && this.Fieldnumber.length === 0) {
|
|
|
- this.fetchFieldList(roomName);
|
|
|
- } else if (roomName && this.Fieldnumber.length > 0 && penNo) {
|
|
|
- // 如果栏位已变更,更新栏位列表
|
|
|
- this.fetchFieldList(roomName);
|
|
|
+ if (token && expireAt) {
|
|
|
+ app.globalData.token = token;
|
|
|
+ app.globalData.expireAt = expireAt;
|
|
|
+ app.globalData.userInfo = userInfo;
|
|
|
+ app.globalData.isLoggedIn = true;
|
|
|
+ app.globalData.building = building;
|
|
|
+ app.globalData.room = room;
|
|
|
+ app.globalData.pen = pen;
|
|
|
+ app.globalData.buildingName = building;
|
|
|
+ app.globalData.roomName = room;
|
|
|
+ app.globalData.penNo = pen;
|
|
|
+ console.log('从本地存储恢复全局数据成功');
|
|
|
}
|
|
|
- },
|
|
|
+ } catch (e) {
|
|
|
+ console.error('从本地存储恢复全局数据失败:', e);
|
|
|
+ }
|
|
|
+
|
|
|
+ this.loadSavedSettings();
|
|
|
+ // 刷新栋舍列表
|
|
|
+ this.fetchBuildingList();
|
|
|
+ },
|
|
|
|
|
|
/**
|
|
|
- * 根据栋舍获取房间列表(带重试机制)
|
|
|
+ * 根据栋舍获取房间列表
|
|
|
* @param {string} buildingName - 栋舍名称
|
|
|
* @param {number} retryCount - 当前重试次数
|
|
|
*/
|
|
|
@@ -342,6 +400,9 @@ export default {
|
|
|
method: 'GET',
|
|
|
data: { building: buildingName },
|
|
|
timeout: 10000, // 增加超时时间到10秒
|
|
|
+ header: {
|
|
|
+ "x-token": uni.getStorageSync('equipment_token') || ''
|
|
|
+ },
|
|
|
success: (res) => {
|
|
|
// 隐藏加载提示
|
|
|
if (retryCount === 0) {
|
|
|
@@ -358,7 +419,7 @@ export default {
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
- * 根据房间名称获取栏位列表(带重试机制)
|
|
|
+ * 根据房间名称获取栏位列表
|
|
|
* @param {string} roomName - 房间名称
|
|
|
* @param {number} retryCount - 当前重试次数(默认0)
|
|
|
*/
|
|
|
@@ -373,19 +434,21 @@ export default {
|
|
|
|
|
|
// 发送请求到API获取栏位列表
|
|
|
uni.request({
|
|
|
- url: API.getField,
|
|
|
+ url: API.getPen,
|
|
|
method: 'GET',
|
|
|
- data: { room: roomName },
|
|
|
timeout: 10000, // 增加超时时间到10秒
|
|
|
+ header: {
|
|
|
+ "x-token": uni.getStorageSync('equipment_token') || ''
|
|
|
+ },
|
|
|
success: (res) => {
|
|
|
// 隐藏加载提示
|
|
|
if (retryCount === 0) {
|
|
|
- uni.hideLoading();
|
|
|
+ uni.hideLoading();
|
|
|
}
|
|
|
- // 更新栏位列表
|
|
|
- this.Fieldnumber = res.data.data || [];
|
|
|
- // 重置栏位选择
|
|
|
- this.form.penNo = '';
|
|
|
+ // 更新栏位列表
|
|
|
+ this.Fieldnumber = res.data.data || [];
|
|
|
+ // 重置栏位选择
|
|
|
+ this.form.penNo = '';
|
|
|
},
|
|
|
fail: (err) => {
|
|
|
// 隐藏加载提示
|
|
|
@@ -429,25 +492,14 @@ export default {
|
|
|
|
|
|
// 验证插件实例是否有效
|
|
|
if (!this.uhfSFHelper) {
|
|
|
- console.error('插件实例为空或未定义');
|
|
|
- // 检查插件是否存在于项目中
|
|
|
- console.log('检查插件是否存在于项目中...');
|
|
|
- // 提示可能的解决方案
|
|
|
- console.warn('可能的解决方案:');
|
|
|
- console.warn('1. 验证插件名称是否正确:Alvin-CBZUhfModule');
|
|
|
- console.warn('2. 检查插件是否正确安装在nativeplugins目录中');
|
|
|
- console.warn('3. 确保您的开发环境支持原生插件');
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
if (typeof this.uhfSFHelper.doInitDevice !== 'function') {
|
|
|
- console.error('插件实例缺少必要方法: doInitDevice');
|
|
|
- // 输出插件实例的所有方法,帮助调试
|
|
|
- console.log('插件实例可用方法:', Object.keys(this.uhfSFHelper));
|
|
|
+ //插件实例缺少必要方法: doInitDevice
|
|
|
this.uhfSFHelper = null;
|
|
|
return false;
|
|
|
}
|
|
|
-
|
|
|
console.log('UHF插件实例创建成功');
|
|
|
return true;
|
|
|
} catch (e) {
|
|
|
@@ -497,7 +549,6 @@ export default {
|
|
|
|
|
|
if (missingMethods.length > 0) {
|
|
|
console.error(`插件实例缺少必要方法: ${missingMethods.join(', ')}`);
|
|
|
- console.log('插件实例可用方法:', Object.keys(this.uhfSFHelper));
|
|
|
this.uhfSFHelper = null;
|
|
|
|
|
|
// 如果未达到最大重试次数,尝试重新初始化
|
|
|
@@ -540,7 +591,6 @@ export default {
|
|
|
uni.hideLoading();
|
|
|
|
|
|
console.log('扫描已取消');
|
|
|
- uni.showToast({ title: '扫描已取消', icon: 'none' });
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
@@ -613,7 +663,50 @@ export default {
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
- * 开始扫描耳标
|
|
|
+ * 切换持续扫描状态
|
|
|
+ */
|
|
|
+ toggleContinuousScan() {
|
|
|
+ // 确保插件实例已初始化且有效
|
|
|
+ if (!this.checkAndRestorePluginInstance()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this.isDeviceReady) {
|
|
|
+ return uni.showToast({ title: '请先开启设备', icon: 'none' })
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.isContinuousScanning) {
|
|
|
+ // 停止持续扫描
|
|
|
+ this.isContinuousScanning = false;
|
|
|
+
|
|
|
+ // 调用cancelScan方法清除所有计时器和加载提示
|
|
|
+ this.cancelScan();
|
|
|
+
|
|
|
+ // 清除持续扫描间隔计时器(双重保障)
|
|
|
+ if (this.continuousScanInterval) {
|
|
|
+ clearTimeout(this.continuousScanInterval);
|
|
|
+ this.continuousScanInterval = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 显示扫描停止提示
|
|
|
+ uni.showToast({ title: '已停止扫描', icon: 'none' });
|
|
|
+ } else {
|
|
|
+ // 开始持续扫描
|
|
|
+ this.isContinuousScanning = true;
|
|
|
+
|
|
|
+ // 显示持续扫描提示
|
|
|
+ uni.showLoading({
|
|
|
+ title: '持续扫描中...',
|
|
|
+ mask: true
|
|
|
+ });
|
|
|
+
|
|
|
+ // 开始持续扫描
|
|
|
+ this.performContinuousScan();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 开始扫描耳标(单次)
|
|
|
*/
|
|
|
scan() {
|
|
|
// 确保插件实例已初始化且有效
|
|
|
@@ -625,13 +718,19 @@ export default {
|
|
|
return uni.showToast({ title: '请先开启设备', icon: 'none' })
|
|
|
}
|
|
|
|
|
|
+ // 如果正在持续扫描,先停止
|
|
|
+ if (this.isContinuousScanning) {
|
|
|
+ this.toggleContinuousScan();
|
|
|
+ }
|
|
|
+
|
|
|
// 设置扫描参数 - 优化参数以提高成功率
|
|
|
const scanConfig = {
|
|
|
retryCount: 3, // 增加重试次数
|
|
|
currentRetry: 0,
|
|
|
timeout: 2000, // 增加超时时间
|
|
|
interval: 400, // 增加间隔,给设备恢复时间
|
|
|
- signalThreshold: 0.5 // 降低信号阈值,接受更多信号
|
|
|
+ signalThreshold: 0.5, // 降低信号阈值,接受更多信号
|
|
|
+ continuous: false // 非持续扫描模式
|
|
|
};
|
|
|
|
|
|
// 初始化扫描进度变量
|
|
|
@@ -647,10 +746,39 @@ export default {
|
|
|
// 执行扫描函数
|
|
|
this.performScan(scanConfig);
|
|
|
},
|
|
|
- // release() {
|
|
|
- // this.isDeviceReady = false;
|
|
|
- // this.isDisable = false;
|
|
|
- // },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行持续扫描
|
|
|
+ */
|
|
|
+ performContinuousScan() {
|
|
|
+ // 检查是否仍在持续扫描状态
|
|
|
+ if (!this.isContinuousScanning || !this._isMounted || !this.isDeviceReady) {
|
|
|
+ if (this.isContinuousScanning) {
|
|
|
+ uni.hideLoading();
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查并恢复插件实例
|
|
|
+ if (!this.checkAndRestorePluginInstance()) {
|
|
|
+ uni.hideLoading();
|
|
|
+ this.isContinuousScanning = false;
|
|
|
+ return uni.showToast({ title: '设备功能异常,无法持续扫描', icon: 'none' });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置持续扫描参数
|
|
|
+ const scanConfig = {
|
|
|
+ retryCount: 100, //重试次数
|
|
|
+ currentRetry: 0,
|
|
|
+ timeout: 1500, // 增加超时时间到1.5秒
|
|
|
+ interval: 300, // 减少重试间隔到300ms
|
|
|
+ signalThreshold: 0.3, // 降低信号阈值,提高扫描成功率
|
|
|
+ continuous: true // 持续扫描模式
|
|
|
+ };
|
|
|
+
|
|
|
+ // 执行扫描
|
|
|
+ this.performScan(scanConfig);
|
|
|
+ },
|
|
|
|
|
|
/**
|
|
|
* 执行扫描(带重试机制)
|
|
|
@@ -689,27 +817,30 @@ export default {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (config.currentRetry >= config.retryCount) {
|
|
|
+ // 非持续扫描模式下才检查最大重试次数
|
|
|
+ if (!config.continuous && config.currentRetry >= config.retryCount) {
|
|
|
uni.hideLoading();
|
|
|
console.log('Scan failed after maximum retries');
|
|
|
return uni.showToast({ title: '扫描失败,请调整位置重试', icon: 'none' });
|
|
|
}
|
|
|
|
|
|
- // 添加最大扫描时间限制 (总时间 = 超时时间 * 重试次数)
|
|
|
- const maxScanTime = config.timeout * config.retryCount;
|
|
|
- if (!this.maxScanTimer) {
|
|
|
- this.maxScanTimer = setTimeout(() => {
|
|
|
- console.log('Maximum scan time exceeded');
|
|
|
- this.cancelScan();
|
|
|
- }, maxScanTime);
|
|
|
+ // 非持续扫描模式下才添加最大扫描时间限制
|
|
|
+ if (!config.continuous) {
|
|
|
+ const maxScanTime = config.timeout * config.retryCount;
|
|
|
+ if (!this.maxScanTimer) {
|
|
|
+ this.maxScanTimer = setTimeout(() => {
|
|
|
+ console.log('Maximum scan time exceeded');
|
|
|
+ this.cancelScan();
|
|
|
+ }, maxScanTime);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// 增加重试计数
|
|
|
config.currentRetry++;
|
|
|
this.scanProgress = config.currentRetry;
|
|
|
|
|
|
- // 更新加载提示(简化提示,避免频繁更新)
|
|
|
- if (config.currentRetry % 2 === 0 || config.currentRetry === config.retryCount) {
|
|
|
+ // 持续扫描模式下不更新加载提示,以避免干扰停止操作
|
|
|
+ if (!config.continuous && (config.currentRetry % 2 === 0 || config.currentRetry === config.retryCount)) {
|
|
|
uni.hideLoading();
|
|
|
uni.showLoading({
|
|
|
title: `扫描中 (${Math.round(config.currentRetry/config.retryCount*100)}%)...`,
|
|
|
@@ -758,10 +889,10 @@ export default {
|
|
|
}
|
|
|
|
|
|
console.error('Invalid plugin instance for scanning after restore attempt');
|
|
|
- // 尝试重新初始化设备
|
|
|
- this.initDevice();
|
|
|
- uni.hideLoading();
|
|
|
- return uni.showToast({ title: '设备功能异常,正在重新初始化', icon: 'none' });
|
|
|
+ // 尝试重新初始化设备
|
|
|
+ this.init(); // 修复:使用init而不是不存在的initDevice方法
|
|
|
+ uni.hideLoading();
|
|
|
+ return uni.showToast({ title: '设备功能异常,正在重新初始化', icon: 'none' });
|
|
|
}
|
|
|
|
|
|
// 保存当前实例引用,防止闭包中实例变化
|
|
|
@@ -790,8 +921,7 @@ export default {
|
|
|
}
|
|
|
|
|
|
if (result) {
|
|
|
- // 假设result是一个包含id和signalStrength的对象
|
|
|
- // 如果result只是ID字符串,我们将其包装成对象
|
|
|
+ // 如果result只是ID字符串,将其包装成对象
|
|
|
const scanResult = typeof result === 'string' ? { id: result, signalStrength: 1 } : result;
|
|
|
|
|
|
// 检查信号强度是否足够
|
|
|
@@ -806,7 +936,9 @@ export default {
|
|
|
this.retryTimeout = null;
|
|
|
}
|
|
|
|
|
|
- uni.hideLoading();
|
|
|
+ if (!config.continuous) {
|
|
|
+ uni.hideLoading();
|
|
|
+ }
|
|
|
console.log('扫描成功:', scanResult);
|
|
|
this.form.earId = scanResult.id;
|
|
|
|
|
|
@@ -815,11 +947,37 @@ export default {
|
|
|
|
|
|
if (isDuplicate) {
|
|
|
console.log('耳标已存在:', scanResult.id);
|
|
|
- uni.showToast({ title: '该耳标已扫描过', icon: 'none' });
|
|
|
+ // 持续扫描模式下也显示重复提示,但持续时间较短
|
|
|
+ uni.showToast({
|
|
|
+ title: '该耳标已扫描过',
|
|
|
+ icon: 'none',
|
|
|
+ duration: config.continuous ? 500 : 2000
|
|
|
+ });
|
|
|
} else {
|
|
|
// 默认添加为'正常'类型
|
|
|
this.dataList.push({ id: scanResult.id, typeIndex: 0 });
|
|
|
- uni.showToast({ title: '扫描成功', icon: 'success' });
|
|
|
+ if (!config.continuous) {
|
|
|
+ uni.showToast({ title: '扫描成功', icon: 'success' });
|
|
|
+ } else {
|
|
|
+ // 持续扫描模式下,短暂提示后继续
|
|
|
+ uni.showToast({ title: '扫描到耳标', icon: 'success', duration: 500 });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 持续扫描模式下,确保继续扫描
|
|
|
+ if (config.continuous && this.isContinuousScanning) {
|
|
|
+ // 清除可能存在的旧计时器
|
|
|
+ if (this.continuousScanInterval) {
|
|
|
+ clearTimeout(this.continuousScanInterval);
|
|
|
+ this.continuousScanInterval = null;
|
|
|
+ }
|
|
|
+ // 设置新的计时器,确保持续扫描
|
|
|
+ this.continuousScanInterval = setTimeout(() => {
|
|
|
+ // 再次检查持续扫描状态
|
|
|
+ if (this.isContinuousScanning && this.isDeviceReady) {
|
|
|
+ this.performContinuousScan();
|
|
|
+ }
|
|
|
+ }, 500); // 短暂延迟后继续扫描
|
|
|
}
|
|
|
} else {
|
|
|
console.log(`Scan result with weak signal (${scanResult.signalStrength}), retrying`);
|
|
|
@@ -856,8 +1014,12 @@ export default {
|
|
|
this.scanTimeout = null;
|
|
|
}
|
|
|
|
|
|
- // 检查是否是实例不可用错误
|
|
|
- if (e.message && e.message.includes('instance is not available')) {
|
|
|
+ // 检查是否是实例不可用错误,增强检测逻辑
|
|
|
+ if (e.message && (
|
|
|
+ e.message.includes('instance is not available') ||
|
|
|
+ e.message.includes('receiveTasks') ||
|
|
|
+ e.message.includes('Failed to receiveTasks')
|
|
|
+ )) {
|
|
|
console.error('Plugin instance not available during scan');
|
|
|
// 尝试重新初始化
|
|
|
this.uhfSFHelper = null;
|
|
|
@@ -885,8 +1047,12 @@ export default {
|
|
|
}
|
|
|
|
|
|
console.error('Error during scan setup:', e);
|
|
|
- // 检查错误是否与实例不可用相关
|
|
|
- if (e.message && e.message.includes('instance is not available')) {
|
|
|
+ // 检查错误是否与实例不可用相关,增强检测逻辑
|
|
|
+ if (e.message && (
|
|
|
+ e.message.includes('instance is not available') ||
|
|
|
+ e.message.includes('receiveTasks') ||
|
|
|
+ e.message.includes('Failed to receiveTasks')
|
|
|
+ )) {
|
|
|
console.error('Plugin instance not available during scan setup');
|
|
|
// 清除当前实例
|
|
|
this.uhfSFHelper = null;
|
|
|
@@ -913,9 +1079,10 @@ export default {
|
|
|
* 提交表单数据
|
|
|
*/
|
|
|
submitForm() {
|
|
|
- // 确保加载最新的设置
|
|
|
+ // 在验证前先尝试重新加载设置
|
|
|
this.loadSavedSettings();
|
|
|
-
|
|
|
+ console.log('提交表单数据:', this.form);
|
|
|
+
|
|
|
// 验证编号是否已选择
|
|
|
let missingField = '';
|
|
|
if (!this.form.buildingName) missingField = '栋舍';
|
|
|
@@ -933,33 +1100,43 @@ export default {
|
|
|
|
|
|
// 验证用户ID是否存在
|
|
|
const app = getApp();
|
|
|
- const userInfo = app.globalData.userInfo || uni.getStorageSync('user_info') || {};
|
|
|
- const userId = userInfo.id || '';
|
|
|
+ const userInfo = app.globalData.userInfo;
|
|
|
+ console.log('用户信息:', userInfo);
|
|
|
+
|
|
|
+ // 更安全地获取用户ID,增加多重检查
|
|
|
+ const userId = userInfo.ID;
|
|
|
if (!userId) {
|
|
|
return uni.showToast({ title: '用户未登录', icon: 'none', duration: 3000 })
|
|
|
}
|
|
|
|
|
|
- // 显示加载提示
|
|
|
uni.showLoading({ title: '提交中...', mask: true });
|
|
|
|
|
|
- // 将dataList数组转换为包含类型的逗号分隔字符串
|
|
|
- // 格式: id:type,id:type,...
|
|
|
const rfidString = this.dataList.map(item => {
|
|
|
return `${item.id}:${this.types[item.typeIndex]}`;
|
|
|
}).join(',');
|
|
|
|
|
|
+ // 获取设备信息
|
|
|
+ let deviceInfo = {};
|
|
|
+ try {
|
|
|
+ deviceInfo = uni.getSystemInfoSync();
|
|
|
+ } catch (e) {
|
|
|
+ console.error('获取设备信息失败:', e);
|
|
|
+ }
|
|
|
+
|
|
|
// 准备提交数据
|
|
|
const submitData = {
|
|
|
+ token: uni.getStorageSync('equipment_token'),
|
|
|
rfid: rfidString,
|
|
|
buildingName: this.form.buildingName,
|
|
|
roomName: this.form.roomName,
|
|
|
penNo: this.form.penNo,
|
|
|
userId: userId,
|
|
|
username: userInfo.username || '',
|
|
|
- time: new Date().toISOString()
|
|
|
+ time: new Date().toISOString(),
|
|
|
+ deviceModel: deviceInfo.model || '未获取到设备型号', // 设备型号
|
|
|
+ deviceVersion: deviceInfo.system || '未获取到设备版本号' // 设备版本号
|
|
|
};
|
|
|
|
|
|
- console.log('准备提交的数据:', submitData);
|
|
|
|
|
|
// 发送请求到API
|
|
|
this.submitData(submitData);
|
|
|
@@ -970,6 +1147,8 @@ export default {
|
|
|
* @param {object} data - 要提交的数据
|
|
|
*/
|
|
|
submitData(data) {
|
|
|
+ console.log('token',uni.getStorageSync('equipment_token'))
|
|
|
+ console.log('提交的数据',data)
|
|
|
// 设置独立的提交加载状态标志
|
|
|
this.isSubmitting = true;
|
|
|
|
|
|
@@ -977,9 +1156,10 @@ export default {
|
|
|
url: API.postListAdd,
|
|
|
method: 'POST',
|
|
|
data: data,
|
|
|
- timeout: 10000, // 设置10秒超时
|
|
|
- method: 'POST',
|
|
|
- data: data,
|
|
|
+ header: {
|
|
|
+ 'content-type': 'application/json',
|
|
|
+ 'x-token': uni.getStorageSync('equipment_token') // 将token添加到请求头中
|
|
|
+ },
|
|
|
timeout: 10000, // 设置10秒超时
|
|
|
success: (res) => {
|
|
|
console.log('API响应:', res);
|
|
|
@@ -992,7 +1172,6 @@ export default {
|
|
|
|
|
|
if (res.data) {
|
|
|
console.log('服务器返回数据:', res.data);
|
|
|
- // 显示结果提示
|
|
|
const message = res.data.msg || '提交成功';
|
|
|
console.log('显示提示:', message);
|
|
|
|
|
|
@@ -1012,6 +1191,13 @@ export default {
|
|
|
userId: data.userId,
|
|
|
time: new Date().toLocaleTimeString()
|
|
|
});
|
|
|
+
|
|
|
+ // 停止持续扫描
|
|
|
+ if (this.isContinuousScanning) {
|
|
|
+ this.toggleContinuousScan();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清空扫描数据
|
|
|
this.resetForm();
|
|
|
}
|
|
|
} else {
|
|
|
@@ -1061,7 +1247,6 @@ export default {
|
|
|
// 清除扫描结果列表
|
|
|
this.dataList = []
|
|
|
},
|
|
|
-
|
|
|
|
|
|
// 选择
|
|
|
onBuildingChange(e) {
|
|
|
@@ -1104,15 +1289,34 @@ export default {
|
|
|
// 释放设备资源
|
|
|
this.releaseDevice();
|
|
|
|
|
|
- // 清除用户信息
|
|
|
+ // 清除全局用户信息和登录状态
|
|
|
const app = getApp();
|
|
|
app.globalData.userInfo = null;
|
|
|
- uni.removeStorageSync('user_info');
|
|
|
-
|
|
|
- // 跳转到登录页面
|
|
|
- uni.redirectTo({ url: '/pages/login/login' });
|
|
|
+ app.globalData.token = '';
|
|
|
+ app.globalData.expireAt = '';
|
|
|
+ app.globalData.isLoggedIn = false;
|
|
|
+ app.globalData.building = '';
|
|
|
+ app.globalData.room = '';
|
|
|
+ app.globalData.pen = '';
|
|
|
+ app.globalData.buildingName = '';
|
|
|
+ app.globalData.roomName = '';
|
|
|
+ app.globalData.penNo = '';
|
|
|
|
|
|
- uni.showToast({ title: '已退出登录', icon: 'none' })
|
|
|
+ // 清除本地缓存中的所有登录相关信息
|
|
|
+ try {
|
|
|
+ uni.removeStorageSync('user_info');
|
|
|
+ uni.removeStorageSync('equipment_token');
|
|
|
+ uni.removeStorageSync('token_expire_time');
|
|
|
+ // 可选:清除编号相关的缓存
|
|
|
+ // uni.removeStorageSync('building');
|
|
|
+ // uni.removeStorageSync('room');
|
|
|
+ // uni.removeStorageSync('pen');
|
|
|
+ // uni.removeStorageSync('buildingName');
|
|
|
+ // uni.removeStorageSync('roomName');
|
|
|
+ // uni.removeStorageSync('penNo');
|
|
|
+ } catch (e) {
|
|
|
+ console.error('清除登录信息失败:', e);
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
toggleServerConfig() {
|
|
|
@@ -1121,33 +1325,20 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
-
|
|
|
<style>
|
|
|
.page { display: flex; flex-direction: column; height: 100vh; width: 100%; box-sizing: border-box; padding: 0 10rpx; }
|
|
|
-
|
|
|
.data-item { display: flex; justify-content: space-between; align-items: center; padding: 10rpx; margin-bottom: 10rpx; background-color: #f5f5f5; border-radius: 5rpx; }
|
|
|
-
|
|
|
-.picker { padding: 5rpx 10rpx;
|
|
|
- margin-left: 20px;
|
|
|
- background-color: #fff; border: 1px solid #ddd; border-radius: 5rpx; min-width: 120rpx; text-align: center; }
|
|
|
-
|
|
|
+.picker { padding: 5rpx 10rpx; margin-left: 20px;background-color: #fff; border: 1px solid #ddd; border-radius: 5rpx; min-width: 120rpx; text-align: center; }
|
|
|
.arrow::after { content: '▾'; font-size: 12rpx; margin-left: 5rpx; }
|
|
|
-
|
|
|
.delete-btn { background-color: #ff4d4f; color: white; font-size: 24rpx; padding: 5rpx 10rpx; min-width: 80rpx; line-height: normal; }
|
|
|
-.nav-bar {
|
|
|
- display: flex; justify-content: space-between; align-items: center;
|
|
|
- background: #007aff; color: white; padding: 15rpx 30rpx;
|
|
|
-}
|
|
|
+.nav-bar {display: flex; justify-content: space-between; align-items: center;background: #007aff; color: white; padding: 15rpx 30rpx;}
|
|
|
.nav-title { font-weight: bold; font-size: 32rpx; }
|
|
|
.nav-btn { background: transparent; border: none; font-size: 32rpx; }
|
|
|
.scroll-area { flex: 1; }
|
|
|
.section-title { display: flex; justify-content: space-between; margin-bottom: 20rpx; }
|
|
|
.section-title .title { font-weight: bold; font-size: 30rpx; }
|
|
|
.section-title .date { font-size: 24rpx; color: #666; }
|
|
|
-.rfid-card {
|
|
|
- background: #f6f6f6; border: 2rpx dashed #ccc;
|
|
|
- border-radius: 20rpx; text-align: center;
|
|
|
-}
|
|
|
+.rfid-card {background: #f6f6f6; border: 2rpx dashed #ccc; border-radius: 20rpx; text-align: center; }
|
|
|
.scan-icon { font-size: 50rpx; color: #007aff; margin-bottom: 10rpx; display: block; }
|
|
|
.btn-group { display: flex; gap: 20rpx; margin: 20rpx 0; flex-wrap: wrap; justify-content: center; }
|
|
|
.scan-btn { background: #007aff; color: white; flex: 1; min-width: 200rpx; padding: 20rpx; border-radius: 12rpx; font-size: 28rpx; }
|
|
|
@@ -1156,13 +1347,7 @@ export default {
|
|
|
.form-item .label { display: block; font-weight: bold; margin-bottom: 10rpx; }
|
|
|
.input-box { width: 100%; border: 1rpx solid #ccc; border-radius: 10rpx; background: #fff; }
|
|
|
.status-options { display: flex; gap: 20rpx; margin-top: 10rpx; }
|
|
|
-.status-option {
|
|
|
- flex: 1; border: 1rpx solid #ccc; border-radius: 10rpx;
|
|
|
- padding: 20rpx; text-align: center; color: #666;
|
|
|
-}
|
|
|
+.status-option {flex: 1; border: 1rpx solid #ccc; border-radius: 10rpx;padding: 20rpx; text-align: center; color: #666;}
|
|
|
.status-option.active { border-color: #007aff; color: #007aff; }
|
|
|
-.sv {
|
|
|
- height: 300rpx;
|
|
|
- margin-top: 20rpx;
|
|
|
-}
|
|
|
+.sv {height: 300rpx;margin-top: 20rpx;}
|
|
|
</style>
|