修改NFC读取
This commit is contained in:
78
src/pages/business/polling/nfcTest/index.vue
Normal file
78
src/pages/business/polling/nfcTest/index.vue
Normal file
@@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<input class="input-box" v-model="inputText" @input="input" type="text" placeholder="请输入内容"/>
|
||||
<view class="btn-box">
|
||||
<button class="btn-write" @click="writeData()">写信息</button>
|
||||
<button class="btn-read" @click="readData()">读信息</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import nfc from '@/utils/ouu-nfc.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
inputText: 'https://baidu.com'
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
nfc.listenNFCStatus();
|
||||
},
|
||||
methods: {
|
||||
input(e) {
|
||||
nfc.inputChanage(e.detail.value)
|
||||
},
|
||||
writeData() {
|
||||
nfc.writeData()
|
||||
},
|
||||
readData() {
|
||||
nfc.readData()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
padding: 15px;
|
||||
box-sizing: border-box;
|
||||
.iframe {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
border: none;
|
||||
margin: 0;
|
||||
}
|
||||
.input-box {
|
||||
border: 1px solid #aaa;
|
||||
margin: 30px 0;
|
||||
padding: 10px;
|
||||
border-radius: 100px;
|
||||
}
|
||||
.btn-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.btn-write {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
}
|
||||
.btn-read {
|
||||
width: 100%;
|
||||
margin-left: 20px;
|
||||
height: 100px;
|
||||
background-color: #1ee176;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
784
src/pages/business/polling/nfcTest/nfcTemplate.vue
Normal file
784
src/pages/business/polling/nfcTest/nfcTemplate.vue
Normal file
@@ -0,0 +1,784 @@
|
||||
<template>
|
||||
<view class="container" @touchstart="touchStart" @touchend="touchEnd">
|
||||
<view class="header">
|
||||
<text class="title">NFC卡片读取器</text>
|
||||
</view>
|
||||
|
||||
<view class="content" :class="{ 'landscape-layout': isLandscape }">
|
||||
<!-- NFC读取按钮 - 平板适配:按钮尺寸不小于48px×48px -->
|
||||
<button class="nfc-button" @click="startNFCReading" :disabled="isReading">
|
||||
<text v-if="!isReading">开始NFC读取</text>
|
||||
<view v-else class="loading-wrapper">
|
||||
<view class="loading-spinner"></view>
|
||||
<text>正在读取中...</text>
|
||||
</view>
|
||||
</button>
|
||||
|
||||
<!-- 读取状态提示 -->
|
||||
<view class="status-section">
|
||||
<text class="status-text" :class="statusClass">{{ statusMessage }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 读取结果显示区域 -->
|
||||
<view class="result-section" v-if="nfcResult">
|
||||
<view class="result-header">
|
||||
<text class="result-label">NFC ID:</text>
|
||||
<button class="copy-button" @click="copyToClipboard">复制</button>
|
||||
</view>
|
||||
<text class="result-value">{{ nfcResult }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 操作提示 -->
|
||||
<view class="instruction">
|
||||
<text class="instruction-title">操作指南:</text>
|
||||
<text class="instruction-text">1. 确保设备NFC功能已开启</text>
|
||||
<text class="instruction-text">2. 将NFC卡片贴近设备感应区域</text>
|
||||
<text class="instruction-text">3. 听到提示音或感受到震动时,表示读取成功</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部信息 -->
|
||||
<view class="footer">
|
||||
<text class="footer-text">支持卡片类型: ISO14443A/B, Mifare, NFC-V, FeliCa</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import nfcUtil from "@/utils/hexiii-nfc.js"
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isReading: false,
|
||||
statusMessage: '准备就绪',
|
||||
statusClass: 'status-ready',
|
||||
nfcResult: '',
|
||||
statusHistory: [], // 记录状态历史
|
||||
isLandscape: false, // 是否横屏
|
||||
screenWidth: 0, // 屏幕宽度
|
||||
screenHeight: 0, // 屏幕高度
|
||||
deviceInfo: null, // 设备信息
|
||||
touchStartTime: 0, // 触摸开始时间
|
||||
touchStartX: 0, // 触摸开始X坐标
|
||||
touchStartY: 0 // 触摸开始Y坐标
|
||||
}
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
// 获取设备信息
|
||||
this._getDeviceInfo();
|
||||
// 页面加载时检查NFC状态
|
||||
this._checkNFCStatus();
|
||||
// 添加屏幕旋转监听
|
||||
uni.onWindowResize(this._onWindowResize);
|
||||
},
|
||||
|
||||
onShow() {
|
||||
// 页面显示时重新检查NFC状态
|
||||
this._checkNFCStatus();
|
||||
},
|
||||
|
||||
onHide() {
|
||||
// 页面隐藏时暂停NFC监听
|
||||
if (this.isReading) {
|
||||
nfcUtil.stopNFCListening();
|
||||
this.isReading = false;
|
||||
}
|
||||
},
|
||||
|
||||
onUnload() {
|
||||
// 页面卸载时清理NFC资源
|
||||
nfcUtil.cleanupNFC();
|
||||
// 移除屏幕旋转监听
|
||||
uni.offWindowResize(this._onWindowResize);
|
||||
},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* 获取设备信息
|
||||
* @private
|
||||
*/
|
||||
_getDeviceInfo() {
|
||||
uni.getSystemInfo({
|
||||
success: (res) => {
|
||||
this.deviceInfo = res;
|
||||
this.screenWidth = res.screenWidth;
|
||||
this.screenHeight = res.screenHeight;
|
||||
// 判断是否为横屏
|
||||
this.isLandscape = res.windowWidth > res.windowHeight;
|
||||
console.log('设备信息:', res);
|
||||
console.log('当前屏幕方向:', this.isLandscape ? '横屏' : '竖屏');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 监听屏幕旋转
|
||||
* @private
|
||||
*/
|
||||
_onWindowResize(res) {
|
||||
if (res) {
|
||||
const isLandscape = res.windowWidth > res.windowHeight;
|
||||
// 屏幕方向改变时更新状态
|
||||
if (this.isLandscape !== isLandscape) {
|
||||
this.isLandscape = isLandscape;
|
||||
console.log('屏幕旋转为:', isLandscape ? '横屏' : '竖屏');
|
||||
// 屏幕旋转时重新调整布局
|
||||
this._adjustLayoutForOrientation();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 根据屏幕方向调整布局
|
||||
* @private
|
||||
*/
|
||||
_adjustLayoutForOrientation() {
|
||||
// 可以在这里进行特定的布局调整
|
||||
// 例如:横屏时调整按钮位置、改变元素大小等
|
||||
// 目前主要通过CSS媒体查询实现,这里预留接口
|
||||
console.log('调整布局适应屏幕方向');
|
||||
},
|
||||
|
||||
/**
|
||||
* 开始NFC读取
|
||||
*/
|
||||
async startNFCReading() {
|
||||
// 提供触觉反馈 - 平板用户体验增强
|
||||
this._provideHapticFeedback();
|
||||
|
||||
// 设置读取状态
|
||||
this.isReading = true;
|
||||
this.statusMessage = '等待NFC卡片...';
|
||||
this.statusClass = 'status-waiting';
|
||||
this._addStatusHistory('开始读取NFC');
|
||||
|
||||
try {
|
||||
// 调用NFC读取功能
|
||||
this._addStatusHistory('正在监听NFC信号...');
|
||||
const nfcId = await nfcUtil.listenNFCStatus();
|
||||
|
||||
// 确保ID有效
|
||||
if (nfcId) {
|
||||
// 成功读取,提供触觉反馈
|
||||
this._provideHapticFeedback('success');
|
||||
|
||||
// 播放成功提示音
|
||||
this._playBeepSound();
|
||||
|
||||
// 显示结果并输出到控制台
|
||||
this.nfcResult = nfcId;
|
||||
console.log('NFC读取结果:', nfcId);
|
||||
|
||||
// 更新状态
|
||||
this.statusMessage = '读取成功';
|
||||
this.statusClass = 'status-success';
|
||||
this._addStatusHistory(`成功读取ID: ${nfcId}`);
|
||||
|
||||
// 显示成功提示框
|
||||
uni.showModal({
|
||||
title: '读取成功',
|
||||
content: `NFC ID: ${nfcId}\n\n是否复制到剪贴板?`,
|
||||
showCancel: true,
|
||||
cancelText: '取消',
|
||||
confirmText: '复制',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.copyToClipboard();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.statusMessage = '未读取到NFC数据';
|
||||
this.statusClass = 'status-error';
|
||||
this._addStatusHistory('未读取到NFC数据');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('NFC读取错误:', error);
|
||||
|
||||
// 错误情况,提供触觉反馈
|
||||
this._provideHapticFeedback('error');
|
||||
|
||||
// 根据错误类型显示不同的提示
|
||||
let errorMsg = '读取失败';
|
||||
if (error.message.includes('不支持NFC')) {
|
||||
errorMsg = '设备不支持NFC功能';
|
||||
} else if (error.message.includes('未开启')) {
|
||||
errorMsg = '请先在系统设置中开启NFC功能';
|
||||
} else if (error.message.includes('超时')) {
|
||||
errorMsg = '读取超时,请重试';
|
||||
} else {
|
||||
errorMsg = '读取失败: ' + error.message;
|
||||
}
|
||||
|
||||
this.statusMessage = errorMsg;
|
||||
this.statusClass = 'status-error';
|
||||
this._addStatusHistory(`错误: ${error.message}`);
|
||||
|
||||
// 显示错误提示
|
||||
uni.showModal({
|
||||
title: '读取失败',
|
||||
content: errorMsg,
|
||||
showCancel: false,
|
||||
confirmText: '确定'
|
||||
});
|
||||
} finally {
|
||||
// 重置读取状态
|
||||
this.isReading = false;
|
||||
|
||||
// 3秒后重置状态消息
|
||||
setTimeout(() => {
|
||||
if (!this.isReading) {
|
||||
this.statusMessage = '准备就绪';
|
||||
this.statusClass = 'status-ready';
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 复制NFC ID到剪贴板
|
||||
*/
|
||||
copyToClipboard() {
|
||||
if (this.nfcResult) {
|
||||
uni.setClipboardData({
|
||||
data: this.nfcResult,
|
||||
success: () => {
|
||||
uni.showToast({
|
||||
title: '已复制到剪贴板',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 检查NFC状态
|
||||
* @private
|
||||
*/
|
||||
_checkNFCStatus() {
|
||||
try {
|
||||
// 尝试初始化NFC适配器检查状态
|
||||
const main = plus.android.runtimeMainActivity();
|
||||
const NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');
|
||||
const nfcAdapter = NfcAdapter.getDefaultAdapter(main);
|
||||
|
||||
if (nfcAdapter == null) {
|
||||
this.statusMessage = '设备不支持NFC功能';
|
||||
this.statusClass = 'status-error';
|
||||
} else if (!nfcAdapter.isEnabled()) {
|
||||
this.statusMessage = 'NFC功能未开启,请在系统设置中开启';
|
||||
this.statusClass = 'status-warning';
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('NFC状态检查失败,可能在非Android环境');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 提供触觉反馈
|
||||
* @private
|
||||
* @param {string} type - 反馈类型: 'success', 'error'或默认
|
||||
*/
|
||||
_provideHapticFeedback(type = 'default') {
|
||||
try {
|
||||
// 在Android设备上提供震动反馈
|
||||
const VIBRATOR_SERVICE = 'vibrator';
|
||||
const Context = plus.android.importClass('android.content.Context');
|
||||
const main = plus.android.runtimeMainActivity();
|
||||
const vibrator = main.getSystemService(VIBRATOR_SERVICE);
|
||||
|
||||
// 根据类型设置不同的震动模式
|
||||
if (vibrator) {
|
||||
if (type === 'success') {
|
||||
// 成功震动模式: 短震动
|
||||
vibrator.vibrate(100);
|
||||
} else if (type === 'error') {
|
||||
// 错误震动模式: 长震动
|
||||
vibrator.vibrate(300);
|
||||
} else {
|
||||
// 默认震动模式: 轻微震动
|
||||
vibrator.vibrate(50);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// 如果设备不支持震动或没有权限,忽略错误
|
||||
console.log('无法提供震动反馈:', e.message);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 播放提示音
|
||||
* @private
|
||||
*/
|
||||
_playBeepSound() {
|
||||
try {
|
||||
// 使用系统默认提示音
|
||||
const AudioManager = plus.android.importClass('android.media.AudioManager');
|
||||
const ToneGenerator = plus.android.importClass('android.media.ToneGenerator');
|
||||
const main = plus.android.runtimeMainActivity();
|
||||
|
||||
const toneGen = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
|
||||
toneGen.startTone(ToneGenerator.TONE_PROP_BEEP);
|
||||
} catch (e) {
|
||||
// 如果无法播放提示音,忽略错误
|
||||
console.log('无法播放提示音:', e.message);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 添加状态历史记录
|
||||
* @private
|
||||
* @param {string} message - 状态消息
|
||||
*/
|
||||
_addStatusHistory(message) {
|
||||
const timestamp = new Date().toLocaleTimeString();
|
||||
this.statusHistory.push(`[${timestamp}] ${message}`);
|
||||
// 只保留最近10条记录
|
||||
if (this.statusHistory.length > 10) {
|
||||
this.statusHistory.shift();
|
||||
}
|
||||
console.log(`[NFC状态] ${message}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 触摸开始事件处理(用于长按等手势识别)
|
||||
* @private
|
||||
*/
|
||||
touchStart(event) {
|
||||
this.touchStartTime = Date.now();
|
||||
this.touchStartX = event.touches[0].clientX;
|
||||
this.touchStartY = event.touches[0].clientY;
|
||||
},
|
||||
|
||||
/**
|
||||
* 触摸结束事件处理(用于长按等手势识别)
|
||||
* @private
|
||||
*/
|
||||
touchEnd(event) {
|
||||
// 可以在这里添加手势识别逻辑
|
||||
// 例如:长按识别、滑动检测等
|
||||
const touchEndTime = Date.now();
|
||||
const touchEndX = event.changedTouches[0].clientX;
|
||||
const touchEndY = event.changedTouches[0].clientY;
|
||||
|
||||
// 计算触摸时间和移动距离
|
||||
const touchDuration = touchEndTime - this.touchStartTime;
|
||||
const distanceX = Math.abs(touchEndX - this.touchStartX);
|
||||
const distanceY = Math.abs(touchEndY - this.touchStartY);
|
||||
|
||||
// 长按检测(超过500ms且移动距离小于10px)
|
||||
if (touchDuration > 500 && distanceX < 10 && distanceY < 10) {
|
||||
console.log('长按操作');
|
||||
// 长按可以触发特殊功能,如显示详细信息
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
padding: 32rpx;
|
||||
background-color: #f5f5f5;
|
||||
/* 增加背景纹理,提升平板视觉体验 */
|
||||
background-image: linear-gradient(45deg, rgba(0, 0, 0, 0.02) 25%, transparent 25%, transparent 75%, rgba(0, 0, 0, 0.02) 75%, rgba(0, 0, 0, 0.02)),
|
||||
linear-gradient(45deg, rgba(0, 0, 0, 0.02) 25%, transparent 25%, transparent 75%, rgba(0, 0, 0, 0.02) 75%, rgba(0, 0, 0, 0.02));
|
||||
background-size: 200rpx 200rpx;
|
||||
background-position: 0 0, 100rpx 100rpx;
|
||||
}
|
||||
|
||||
/* 横屏布局 */
|
||||
.content.landscape-layout {
|
||||
/* 横屏时优化内容区布局 */
|
||||
max-width: 960rpx;
|
||||
margin: 0 auto;
|
||||
/* 为横屏模式添加微妙的阴影效果 */
|
||||
box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.05);
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
border-radius: 16rpx;
|
||||
padding: 40rpx;
|
||||
backdrop-filter: blur(5rpx);
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 48rpx;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #212121;
|
||||
/* 平板适配:增加文字阴影提升可读性 */
|
||||
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
padding: 32rpx;
|
||||
}
|
||||
|
||||
/* NFC按钮 - 平板适配:按钮高度不小于60px */
|
||||
.nfc-button {
|
||||
width: 600rpx;
|
||||
height: 120rpx;
|
||||
line-height: 120rpx;
|
||||
font-size: 36rpx;
|
||||
background-color: #1976D2;
|
||||
color: white;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 48rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/* 平板适配:增加按钮阴影和触摸反馈 */
|
||||
box-shadow: 0 4rpx 12rpx rgba(25, 118, 210, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 水波纹效果 - 符合Android设计规范 */
|
||||
.nfc-button::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(255, 255, 255, 0.3);
|
||||
transform: translate(-50%, -50%);
|
||||
transition: width 0.6s, height 0.6s;
|
||||
}
|
||||
|
||||
.nfc-button:active::after {
|
||||
width: 120%;
|
||||
height: 120%;
|
||||
}
|
||||
|
||||
.nfc-button:active {
|
||||
background-color: #1565C0;
|
||||
transform: translateY(2rpx);
|
||||
box-shadow: 0 2rpx 6rpx rgba(25, 118, 210, 0.3);
|
||||
}
|
||||
|
||||
.nfc-button[disabled] {
|
||||
background-color: #90CAF9;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* 加载动画 */
|
||||
.loading-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
border: 4rpx solid rgba(255, 255, 255, 0.3);
|
||||
border-top: 4rpx solid white;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.status-section {
|
||||
margin-bottom: 32rpx;
|
||||
padding: 24rpx 32rpx;
|
||||
border-radius: 8rpx;
|
||||
background-color: white;
|
||||
min-width: 500rpx;
|
||||
text-align: center;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.status-ready {
|
||||
color: #616161;
|
||||
}
|
||||
|
||||
.status-waiting {
|
||||
color: #1976D2;
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% { opacity: 1; }
|
||||
50% { opacity: 0.7; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
.status-success {
|
||||
color: #4CAF50;
|
||||
}
|
||||
|
||||
.status-error {
|
||||
color: #F44336;
|
||||
}
|
||||
|
||||
.status-warning {
|
||||
color: #FF9800;
|
||||
}
|
||||
|
||||
.result-section {
|
||||
background-color: white;
|
||||
padding: 32rpx;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 32rpx;
|
||||
min-width: 500rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.result-section:hover {
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.result-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.result-label {
|
||||
font-size: 28rpx;
|
||||
color: #757575;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
min-width: 120rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
font-size: 24rpx;
|
||||
background-color: #E3F2FD;
|
||||
color: #1976D2;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
|
||||
.copy-button:active {
|
||||
background-color: #BBDEFB;
|
||||
}
|
||||
|
||||
.result-value {
|
||||
font-size: 36rpx;
|
||||
font-family: monospace;
|
||||
color: #212121;
|
||||
word-break: break-all;
|
||||
line-height: 1.5;
|
||||
padding: 16rpx;
|
||||
background-color: #FAFAFA;
|
||||
border-radius: 6rpx;
|
||||
border: 1rpx solid #EEEEEE;
|
||||
}
|
||||
|
||||
.instruction {
|
||||
margin-top: 32rpx;
|
||||
background-color: white;
|
||||
padding: 32rpx;
|
||||
border-radius: 8rpx;
|
||||
min-width: 500rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.instruction-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #212121;
|
||||
margin-bottom: 16rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.instruction-text {
|
||||
font-size: 28rpx;
|
||||
color: #757575;
|
||||
line-height: 1.6;
|
||||
display: block;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 40rpx;
|
||||
padding: 24rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer-text {
|
||||
font-size: 24rpx;
|
||||
color: #9E9E9E;
|
||||
}
|
||||
|
||||
/* 平板横屏适配 */
|
||||
@media screen and (orientation: landscape) {
|
||||
/* 横屏时优化元素排布 */
|
||||
.container {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
/* 在横屏模式下,核心操作区放在右侧,便于右手操作 */
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding-top: 40rpx;
|
||||
min-height: calc(100vh - 100rpx);
|
||||
}
|
||||
|
||||
/* 横屏时增大按钮点击区域 */
|
||||
.nfc-button {
|
||||
width: 500rpx;
|
||||
height: 130rpx;
|
||||
line-height: 130rpx;
|
||||
/* 放在屏幕右侧,便于右手操作 */
|
||||
align-self: flex-end;
|
||||
margin-right: 60rpx;
|
||||
}
|
||||
|
||||
/* 状态区域也放在右侧 */
|
||||
.status-section {
|
||||
min-width: 600rpx;
|
||||
align-self: flex-end;
|
||||
margin-right: 60rpx;
|
||||
}
|
||||
|
||||
/* 结果区域在横屏时更宽,方便查看完整信息 */
|
||||
.result-section {
|
||||
min-width: 800rpx;
|
||||
margin: 32rpx auto;
|
||||
}
|
||||
|
||||
/* 操作指南放在左侧,不干扰核心操作区 */
|
||||
.instruction {
|
||||
position: absolute;
|
||||
left: 40rpx;
|
||||
top: 180rpx;
|
||||
min-width: 400rpx;
|
||||
max-width: 450rpx;
|
||||
padding: 24rpx;
|
||||
background-color: rgba(255, 255, 255, 0.95);
|
||||
}
|
||||
|
||||
/* 底部信息在横屏时放在左侧底部 */
|
||||
.footer {
|
||||
position: absolute;
|
||||
left: 40rpx;
|
||||
bottom: 30rpx;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
/* 安卓平板特殊适配 */
|
||||
@media (min-width: 768px) and (min-height: 500px) {
|
||||
/* 优化触控体验:确保所有可点击元素至少有48px x 48px的点击区域 */
|
||||
.nfc-button {
|
||||
min-height: 120rpx; /* 约等于48px在rpx中的值 */
|
||||
min-width: 300rpx;
|
||||
touch-action: manipulation; /* 防止双击缩放,提高点击响应速度 */
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
min-height: 80rpx;
|
||||
min-width: 160rpx;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
/* 平板上增大字体和间距,提升可读性 */
|
||||
.title {
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
|
||||
.result-value {
|
||||
letter-spacing: 2rpx;
|
||||
font-size: 42rpx; /* 在平板上进一步增大ID显示字体 */
|
||||
padding: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 大型平板适配(10英寸以上) */
|
||||
@media (min-width: 1024px) {
|
||||
.container {
|
||||
padding: 48rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 64rpx;
|
||||
}
|
||||
|
||||
.nfc-button {
|
||||
width: 700rpx;
|
||||
height: 150rpx;
|
||||
line-height: 150rpx;
|
||||
font-size: 44rpx;
|
||||
}
|
||||
|
||||
.status-section,
|
||||
.result-section {
|
||||
min-width: 900rpx;
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
/* 大型平板上,优化内容区的最大宽度,避免内容过宽影响阅读 */
|
||||
.content {
|
||||
max-width: 70vw;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
/* 适配不同尺寸的平板 */
|
||||
@media screen and (min-width: 768px) {
|
||||
.title {
|
||||
font-size: 56rpx;
|
||||
}
|
||||
|
||||
.nfc-button {
|
||||
width: 700rpx;
|
||||
height: 140rpx;
|
||||
line-height: 140rpx;
|
||||
font-size: 40rpx;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
.result-value {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -6,7 +6,9 @@
|
||||
:leftFlag="true" :rightFlag="true"
|
||||
>
|
||||
<template #right>
|
||||
<view class="head-right" @click="handleQuestion">
|
||||
<!-- 状态是4-已完成 5-已过期的不能再问题上报了 -->
|
||||
<block v-if="optionObj.taskStatus==5||optionObj.taskStatus==4"></block>
|
||||
<view v-else class="head-right" @click="handleQuestion">
|
||||
<view class="btn-yellow">
|
||||
<img :src="'static/images/polling/icon-repair.png'" class="img-repair" />新建问题上报
|
||||
</view>
|
||||
@@ -92,7 +94,7 @@
|
||||
<view>{{ item.pointName }}</view>
|
||||
</view>
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<view class="r-right" @click.stop="initNFC">
|
||||
<view class="r-right" @click.stop="initNFC(item,index)">
|
||||
<img :src="'static/images/polling/icon-NFCcode.png'" class="img-nfc" /> 开始识别
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
@@ -156,8 +158,10 @@
|
||||
</block>
|
||||
<view class="report-border" :style="{borderColor:index<optionObj.pointList.length-1?'#E7E7E7':'#fff'}"></view>
|
||||
</view>
|
||||
<view class="btn-submit">
|
||||
<button type="primary" @click="handleSubmit" :loading="submitLoading">提交</button>
|
||||
<!-- 状态是4-已完成 5-已过期的不能再修改了 -->
|
||||
<block v-if="optionObj.taskStatus==5||optionObj.taskStatus==4"></block>
|
||||
<view v-else class="btn-submit">
|
||||
<button type="primary" @click="handleSubmit" :loading="submitLoading" >提交</button>
|
||||
</view>
|
||||
</block>
|
||||
<view v-else class="no-data">
|
||||
@@ -195,11 +199,20 @@
|
||||
></customShowModal>
|
||||
|
||||
<!-- 图片放大 -->
|
||||
<mediaPreview :visible="isVisible" :url="mediaUrl" @close="handlePreviewClose"></mediaPreview>
|
||||
<mediaPreview :visible="isVisible"
|
||||
:url="mediaUrl"
|
||||
@close="handlePreviewClose"
|
||||
></mediaPreview>
|
||||
|
||||
<!-- NFC 弹窗 -->
|
||||
<NFCTemplate v-if="nfcShow" ref="nfcTemplateRef"
|
||||
@close="nfcClose"
|
||||
@confirm="nfcConfirm"
|
||||
></NFCTemplate>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref,onMounted,onUnmounted,nextTick,computed,reactive } from 'vue'
|
||||
import { ref,onMounted,onUnmounted,nextTick,computed,reactive,getCurrentInstance } from 'vue'
|
||||
import { onLoad,onHide} from '@dcloudio/uni-app';
|
||||
import { MINIO_KEY } from '@/enums/cacheEnums';
|
||||
import customHeader from '@/components/customHeader.vue';
|
||||
@@ -208,14 +221,13 @@ import multipleSelect from "@/components/multipleSelect.vue";
|
||||
import pollingShowModal from "@/components/pollingShowModal.vue";
|
||||
import customShowModal from "@/components/customShowModal.vue"
|
||||
import mediaPreview from "@/components/mediaPreview.vue"
|
||||
import NFCTemplate from "@/components/NFCTemplate.vue"
|
||||
import { parseTime } from '@/utils/datetime.js';
|
||||
import { formatTaskStatus } from '@/utils/status.js';
|
||||
import { taskGroupDetail,submitResult,minioUpload } from '@/api/polling.js'
|
||||
import {compressImageUni} from '@/utils/common.js'
|
||||
// import {uploadFileMinio} from '@/utils/minio.js'
|
||||
// #ifdef APP-PLUS
|
||||
let m1CardModule = uni.requireNativePlugin("LF-Sense-Card-M1")
|
||||
// #endif
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
let taskId = ref(undefined);
|
||||
let groupId = ref(undefined);
|
||||
@@ -227,6 +239,8 @@ onLoad(option => {
|
||||
|
||||
minioObj = JSON.parse(uni.getStorageSync(MINIO_KEY) || "\{\}")
|
||||
// console.log(minioObj)
|
||||
|
||||
|
||||
})
|
||||
|
||||
// 下拉刷新
|
||||
@@ -431,15 +445,29 @@ const handlePreviewClose=()=>{
|
||||
// nfc 处理
|
||||
let cardUID = ref('');
|
||||
let cardValue = ref('');
|
||||
const initNFC = async(item) => {
|
||||
m1CardModule.openNativeSenseCard({
|
||||
'keyA': 'TestKey',
|
||||
'sector': 0,
|
||||
'block': 0
|
||||
},ret => {
|
||||
cardUID.value = ret.uid
|
||||
cardValue.value = ret.code
|
||||
})
|
||||
let nfcShow = ref(false);
|
||||
const nfcTemplateRef = ref(null);
|
||||
// optionObj.pointList
|
||||
let nfcIndex = ref(0);
|
||||
const initNFC = async(item,index) => {
|
||||
nfcShow.value = true;
|
||||
nfcIndex.value=index;
|
||||
// uni.navigateTo({url:'/pages/business/polling/nfcTest/index'})
|
||||
// #ifdef APP-PLUS
|
||||
setTimeout(()=>{
|
||||
// console.log("nfcTemplateRef==",nfcTemplateRef.value)
|
||||
if (nfcTemplateRef.value) {
|
||||
nfcTemplateRef.value.listenNFCStatus();
|
||||
}
|
||||
},500)
|
||||
// #endif
|
||||
}
|
||||
const nfcClose = async(item) => {
|
||||
nfcShow.value = false;
|
||||
}
|
||||
const nfcConfirm=(result)=>{
|
||||
console.log("confirm=>",result)
|
||||
optionObj.pointList[nfcIndex].resultContent = result
|
||||
}
|
||||
|
||||
// 扫二维码
|
||||
@@ -576,6 +604,7 @@ onUnmounted(() => {
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
.scroll-h{
|
||||
/* #ifdef APP-PLUS */
|
||||
height:calc(100vh - 78px) !important;
|
||||
|
||||
Reference in New Issue
Block a user