二维码扫码页面、安全工器具识别页面还原
This commit is contained in:
parent
bd4ff86fdf
commit
32e84fff8d
|
|
@ -100,7 +100,7 @@
|
|||
</uni-forms>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<!-- 隐藏的canvas用于图片处理 -->
|
||||
<canvas
|
||||
|
|
@ -112,6 +112,42 @@
|
|||
<ElectronicSeal v-else v-show="codeData.maId" :maCode="codeData?.maCode" :maId="codeData?.maId" :devType="2" />
|
||||
</div>
|
||||
</view>
|
||||
<!-- 相机预览页面 -->
|
||||
<view v-if="showCamera" class="camera-container">
|
||||
<!-- 顶部提示 -->
|
||||
<view class="top-tip" style="color: red; text-align: center;margin-top: 30px;">
|
||||
<text class="tip-text">请将识别编码置于取景框内,完成扫描</text>
|
||||
</view>
|
||||
<!-- 取景框 -->
|
||||
<view class="viewfinder-container">
|
||||
</view>
|
||||
|
||||
<!-- 底部控制区 -->
|
||||
<view class="bottom-controls">
|
||||
<view class="control-btn" @click="closeCamera">
|
||||
<text class="control-icon">✕</text>
|
||||
</view>
|
||||
<view class="photo-btn" @click="takePicture" :class="{ 'taking': isTaking, 'disabled': isFocusing }">
|
||||
<view class="photo-btn-inner"></view>
|
||||
</view>
|
||||
<view class="control-btn" @click="openGallery">
|
||||
<text class="control-icon">📷</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载提示 -->
|
||||
<view v-if="isProcessing" class="loading-overlay">
|
||||
<view class="loading-content">
|
||||
<view class="loading-spinner"></view>
|
||||
<text class="loading-text">正在识别中...</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="custom-toast"
|
||||
:class="{'show': isShow, 'top': position === 'top', 'bottom': position === 'bottom'}"
|
||||
ref="toast">
|
||||
{{ message }}
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -155,61 +191,532 @@ export default {
|
|||
screenWidth: null,
|
||||
}
|
||||
},
|
||||
onBackPress(options) {
|
||||
console.log("进了-----")
|
||||
// 相机打开时处理返回事件
|
||||
if (this.showCamera) {
|
||||
console.log('关闭相机...');
|
||||
try {
|
||||
this.stopCamera();
|
||||
} catch (error) {
|
||||
console.error('关闭相机出错:', error);
|
||||
} finally {
|
||||
this.showCamera = false;
|
||||
this.cameraStarted = false;
|
||||
this.resetFocusState();
|
||||
}
|
||||
return true; // 阻止默认返回行为
|
||||
}
|
||||
// 其他情况下允许默认返回
|
||||
return false;
|
||||
},
|
||||
onShow() {
|
||||
this.initializeCordova();
|
||||
// 获取设备信息用于相机配置
|
||||
this.getDeviceInfo();
|
||||
},
|
||||
onHide() {
|
||||
this.cleanup();
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.cleanup();
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 打开 OCR 插件识别页面
|
||||
*/
|
||||
show(message, position = 'top', duration = 2000) {
|
||||
this.message = message
|
||||
this.position = position
|
||||
this.isShow = true
|
||||
setTimeout(() => {
|
||||
this.isShow = false
|
||||
}, duration)
|
||||
},
|
||||
handleIsOverToday() {
|
||||
if (!this.codeData.nextCheckTime) {
|
||||
this.isOverToday = true
|
||||
} else {
|
||||
const now = Date.now()
|
||||
const nextCheckTimestamp = new Date(this.codeData.nextCheckTime).getTime()
|
||||
this.isOverToday = nextCheckTimestamp <= now
|
||||
console.log('🚀 ~ isOverToday ~ :', this.isOverToday)
|
||||
}
|
||||
},
|
||||
// 获取设备信息
|
||||
getDeviceInfo() {
|
||||
try {
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
console.log('设备信息:', systemInfo);
|
||||
this.systemInfo = systemInfo;
|
||||
// 获取屏幕高度和宽度
|
||||
const screenHeight = systemInfo.screenHeight; // 屏幕高度:1000
|
||||
const screenWidth = systemInfo.screenWidth; // 屏幕宽度:600
|
||||
this.screenHeight = screenHeight;
|
||||
this.screenWidth = screenWidth;
|
||||
} catch (error) {
|
||||
console.error('获取设备信息失败:', error);
|
||||
}
|
||||
},
|
||||
|
||||
// 初始化Cordova - 改进版本
|
||||
initializeCordova() {
|
||||
console.log('开始初始化Cordova...');
|
||||
this.pluginCheckRetries = 0;
|
||||
// 清除之前的超时
|
||||
if (this.deviceReadyTimeout) {
|
||||
clearTimeout(this.deviceReadyTimeout);
|
||||
}
|
||||
// 如果Cordova已经准备好,直接检查插件
|
||||
if (this.isCordovaReady()) {
|
||||
this.onDeviceReady();
|
||||
return;
|
||||
}
|
||||
// 监听deviceready事件
|
||||
document.addEventListener('deviceready', this.onDeviceReady, false);
|
||||
// 设置超时,防止无限等待
|
||||
this.deviceReadyTimeout = setTimeout(() => {
|
||||
console.warn('Cordova初始化超时,尝试直接检查插件');
|
||||
this.checkCameraPlugin();
|
||||
}, 5000);
|
||||
},
|
||||
|
||||
// 检查Cordova是否准备好
|
||||
isCordovaReady() {
|
||||
return !!(window.cordova && (
|
||||
document.readyState === 'complete' ||
|
||||
window.cordova.platformId
|
||||
));
|
||||
},
|
||||
|
||||
// 设备准备就绪
|
||||
onDeviceReady() {
|
||||
console.log('Cordova设备准备就绪');
|
||||
// 清除超时
|
||||
if (this.deviceReadyTimeout) {
|
||||
clearTimeout(this.deviceReadyTimeout);
|
||||
this.deviceReadyTimeout = null;
|
||||
}
|
||||
// 移除事件监听器,避免重复调用
|
||||
document.removeEventListener('deviceready', this.onDeviceReady);
|
||||
// 检查相机插件
|
||||
this.checkCameraPlugin();
|
||||
},
|
||||
|
||||
// 检查相机插件 - 改进版本
|
||||
checkCameraPlugin() {
|
||||
console.log(`检查相机插件... (尝试 ${this.pluginCheckRetries + 1}/${this.maxRetries})`);
|
||||
// 按优先级检查插件可用性
|
||||
const pluginAvailable = this.getCameraPlugin();
|
||||
if (pluginAvailable) {
|
||||
console.log('相机插件可用:', pluginAvailable);
|
||||
this.cameraReady = true;
|
||||
return;
|
||||
}
|
||||
this.pluginCheckRetries++;
|
||||
if (this.pluginCheckRetries < this.maxRetries) {
|
||||
// 递增延迟重试
|
||||
const delay = Math.min(1000 * this.pluginCheckRetries, 5000);
|
||||
console.log(`插件未就绪,${delay}ms后重试...`);
|
||||
setTimeout(() => {
|
||||
this.checkCameraPlugin();
|
||||
}, delay);
|
||||
} else {
|
||||
console.error('相机插件检查失败,已达到最大重试次数');
|
||||
this.cameraReady = false;
|
||||
uni.showToast({
|
||||
title: '相机插件初始化失败',
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 获取相机插件引用 - 改进版本
|
||||
getCameraPlugin() {
|
||||
// 按照插件注册的实际路径检查
|
||||
const possiblePaths = [
|
||||
() => window.CameraPreview // 全局注册的路径
|
||||
];
|
||||
for (let getPlugin of possiblePaths) {
|
||||
try {
|
||||
const plugin = getPlugin();
|
||||
if (plugin && typeof plugin.startCamera === 'function') {
|
||||
console.log('找到相机插件:', plugin);
|
||||
return plugin;
|
||||
}
|
||||
} catch (e) {
|
||||
// 忽略访问错误,继续尝试下一个路径
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
// 打开相机 - 改进版本
|
||||
async openCamera() {
|
||||
console.log("启动 Cordova OCR 插件...");
|
||||
console.log('尝试打开相机...');
|
||||
this.codeData = {}
|
||||
if (!this.cameraReady) {
|
||||
// 再次尝试检查插件
|
||||
this.checkCameraPlugin();
|
||||
if (!this.cameraReady) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '相机插件未准备好,请确保应用已正确安装相机插件,或尝试重启应用',
|
||||
showCancel: false
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
// 显示相机界面
|
||||
this.showCamera = true;
|
||||
// 等待UI更新
|
||||
await this.$nextTick();
|
||||
// 初始化相机
|
||||
await this.initCamera();
|
||||
} catch (error) {
|
||||
console.error('打开相机失败:', error);
|
||||
this.showCamera = false;
|
||||
uni.showToast({
|
||||
title: error.message || '打开相机失败',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 初始化相机 - 关键修改
|
||||
// 初始化相机 - 调整坐标计算
|
||||
async initCamera() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const CameraPreview = this.getCameraPlugin();
|
||||
if (!CameraPreview) {
|
||||
reject(new Error('相机插件不可用'));
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取整个相机包装器的尺寸
|
||||
const cameraWrapper = document.querySelector('.viewfinder-container');
|
||||
if (!cameraWrapper) {
|
||||
reject(new Error('找不到相机容器'));
|
||||
return;
|
||||
}
|
||||
|
||||
const rect = cameraWrapper.getBoundingClientRect();
|
||||
const options = {
|
||||
x: rect.left,
|
||||
y: rect.top,
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
camera: CameraPreview.CAMERA_DIRECTION?.BACK || 'back',
|
||||
tapPhoto: false,
|
||||
previewDrag: false,
|
||||
toBack: false, // 确保相机在WebView上层
|
||||
alpha: 1,
|
||||
tapFocus: true,
|
||||
disableExifHeaderStripping: false
|
||||
};
|
||||
console.log('相机配置:', options);
|
||||
CameraPreview.startCamera(
|
||||
options,
|
||||
(result) => {
|
||||
console.log('相机启动成功:', result);
|
||||
this.cameraStarted = true;
|
||||
resolve();
|
||||
},
|
||||
(error) => {
|
||||
console.error('相机启动失败:', error);
|
||||
this.cameraStarted = false;
|
||||
reject(new Error(`相机启动失败: ${error}`));
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
// 点击聚焦
|
||||
tapToFocus(x, y) {
|
||||
const CameraPreview = this.getCameraPlugin();
|
||||
if (CameraPreview && this.cameraStarted) {
|
||||
CameraPreview.tapToFocus(
|
||||
x,
|
||||
y,
|
||||
() => console.log('聚焦成功'),
|
||||
(error) => console.error('聚焦失败', error)
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// 关闭相机
|
||||
async closeCamera() {
|
||||
console.log('关闭相机...');
|
||||
try {
|
||||
await this.stopCamera();
|
||||
} catch (error) {
|
||||
console.error('关闭相机出错:', error);
|
||||
} finally {
|
||||
this.showCamera = false;
|
||||
this.cameraStarted = false;
|
||||
this.resetFocusState();
|
||||
}
|
||||
},
|
||||
|
||||
// 重置聚焦状态
|
||||
resetFocusState() {
|
||||
this.isFocusing = false;
|
||||
this.focusSuccess = false;
|
||||
this.showFocusIndicator = false;
|
||||
if (this.focusTimeout) {
|
||||
clearTimeout(this.focusTimeout);
|
||||
this.focusTimeout = null;
|
||||
}
|
||||
},
|
||||
|
||||
// 停止相机
|
||||
async stopCamera() {
|
||||
if (!this.cameraStarted) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const CameraPreview = this.getCameraPlugin();
|
||||
if (!CameraPreview) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
CameraPreview.stopCamera(
|
||||
() => {
|
||||
console.log('相机已停止');
|
||||
this.cameraStarted = false;
|
||||
resolve();
|
||||
},
|
||||
(error) => {
|
||||
console.error('停止相机失败:', error);
|
||||
this.cameraStarted = false;
|
||||
resolve(); // 即使失败也继续
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
// 拍照 - 添加聚焦逻辑
|
||||
async takePicture() {
|
||||
if (!this.cameraStarted || this.isTaking || this.isFocusing) {
|
||||
if (this.isFocusing) {
|
||||
uni.showToast({
|
||||
title: '正在聚焦,请稍候...',
|
||||
icon: 'none',
|
||||
duration: 1000
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('开始拍照流程...');
|
||||
this.isTaking = true;
|
||||
|
||||
try {
|
||||
// 引入插件
|
||||
var ocr = require('cordova/plugin/ocrcream');
|
||||
|
||||
// 启动识别(你的后端识别服务地址)
|
||||
ocr.startOCR("http://sgwpdm.ah.sgcc.com.cn/iws/jiju-api/material/app/ocr/getOcrCode", async (result) => {
|
||||
console.log("OCR 识别结果:", result);
|
||||
|
||||
try {
|
||||
// 有些插件返回字符串,要判断并解析
|
||||
if (typeof result === 'string') {
|
||||
result = JSON.parse(result);
|
||||
}
|
||||
|
||||
if (!result.code) {
|
||||
result = JSON.parse(decryptWithSM4(result.data));
|
||||
} else {
|
||||
result = result.data;
|
||||
}
|
||||
|
||||
const { data: resData } = result;
|
||||
if (resData.code === 0 && resData.data.result) {
|
||||
this.queryCodeParams.maCode = resData.data.result;
|
||||
await this.getCode();
|
||||
uni.showToast({
|
||||
title: '识别成功',
|
||||
icon: 'success'
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '识别失败,请重试',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("识别结果解析异常:", e);
|
||||
uni.showToast({
|
||||
title: '识别失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
const CameraPreview = this.getCameraPlugin();
|
||||
if (!CameraPreview) {
|
||||
throw new Error('相机插件不可用');
|
||||
}
|
||||
// 拍照前先进行聚焦
|
||||
console.log('拍照前聚焦...');
|
||||
console.log('开始拍照...');
|
||||
CameraPreview.takePicture({
|
||||
width: this.screenWidth,
|
||||
height: this.screenHeight,
|
||||
quality: 50
|
||||
}, async (base64PictureData) => {
|
||||
console.log('拍照返回数据', base64PictureData);
|
||||
await this.processImage(base64PictureData);
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("调用 OCR 插件失败:", err);
|
||||
} catch (error) {
|
||||
console.error('拍照过程出错:', error);
|
||||
uni.showToast({
|
||||
title: '设备不支持 OCR',
|
||||
title: error.message || '拍照失败',
|
||||
icon: 'none'
|
||||
});
|
||||
} finally {
|
||||
this.isTaking = false;
|
||||
}
|
||||
},
|
||||
|
||||
// 修改后的方法
|
||||
removeExifData(pureBase64) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
ctx.drawImage(img, 0, 0);
|
||||
|
||||
// 转换为dataURL然后提取纯base64部分
|
||||
const dataUrl = canvas.toDataURL('image/jpeg', 0.8);
|
||||
const cleanPureBase64 = dataUrl.split(',')[1]; // 去掉前缀
|
||||
resolve(cleanPureBase64);
|
||||
};
|
||||
|
||||
img.onerror = () => reject(new Error('图像加载失败'));
|
||||
|
||||
// 临时添加前缀用于加载
|
||||
img.src = `data:image/jpeg;base64,${pureBase64}`;
|
||||
});
|
||||
},
|
||||
|
||||
// 处理图片
|
||||
async processImage(imageData) {
|
||||
this.isProcessing = true;
|
||||
try {
|
||||
// base64PictureData 是纯base64(无前缀)
|
||||
const cleanBase64 = await this.removeExifData(imageData);
|
||||
// cleanBase64 也是纯base64(无前缀)
|
||||
|
||||
console.log('清理后的纯base64:', cleanBase64);
|
||||
console.log('开始OCR识别...');
|
||||
|
||||
uni.request({
|
||||
url: '/material/app/ocr/getOcrCode',
|
||||
method: 'POST',
|
||||
data: {
|
||||
image: cleanBase64,
|
||||
jiju_type: '',
|
||||
auth_lic: 'xIWDlaDVdijcBB4mjhGCPYk5Kvk8tHZJbUn+vW+ih15+MYx98e/PXyBmKL5gFcWMPznLgDA15QuSAnZQSLddwdy9HkZgtuQDEEZZ351Eyb1eiDUccUnyoSGIrNimbx5TooBNNPYqU4qJeFrPJXAqjBHzRrxoBxuR2CEGKQPgHC4='
|
||||
},
|
||||
header: {
|
||||
"Content-Type": "application/json;charset=UTF-8"
|
||||
},
|
||||
success: async (res) => {
|
||||
if (!res.data.code) {
|
||||
res = JSON.parse(decryptWithSM4(res.data))
|
||||
} else {
|
||||
res = res.data
|
||||
}
|
||||
const {data: resData} = res
|
||||
if (resData.code === 0) {
|
||||
if (resData.data.result) {
|
||||
this.queryCodeParams.maCode = resData.data.result
|
||||
await this.closeCamera();
|
||||
await this.getCode();
|
||||
await uni.showToast({
|
||||
title: '识别成功',
|
||||
icon: 'success'
|
||||
});
|
||||
} else {
|
||||
console.log('识别失败!' + resData.data.msg)
|
||||
this.show('识别失败!', 'bottom')
|
||||
}
|
||||
} else {
|
||||
this.show('识别失败!', 'bottom')
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
this.$refs.toast.show('请求失败!', 'bottom')
|
||||
},
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('图片处理或OCR识别失败:', error);
|
||||
uni.showToast({
|
||||
title: '识别失败,请重试',
|
||||
icon: 'none'
|
||||
});
|
||||
} finally {
|
||||
this.isProcessing = false;
|
||||
}
|
||||
},
|
||||
// 打开相册
|
||||
openGallery() {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sourceType: ['album'],
|
||||
success: (res) => {
|
||||
if (res.tempFilePaths && res.tempFilePaths.length > 0) {
|
||||
const filePath = res.tempFilePaths[0];
|
||||
|
||||
// 统一使用XMLHttpRequest处理
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', filePath, true);
|
||||
xhr.responseType = 'blob';
|
||||
xhr.onload = () => {
|
||||
if (xhr.status === 200) {
|
||||
const blob = xhr.response;
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
const base64 = e.target.result.split(',')[1];
|
||||
this.convertImageToBase64(base64);
|
||||
};
|
||||
reader.readAsDataURL(blob);
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error('选择图片失败:', error);
|
||||
uni.showToast({
|
||||
title: '选择图片失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
// 将图片转换为base64
|
||||
async convertImageToBase64(processedBase64) {
|
||||
this.isProcessing = true;
|
||||
try {
|
||||
console.log('相册base64数据', processedBase64);
|
||||
console.log('开始OCR识别...');
|
||||
|
||||
uni.request({
|
||||
url: '/material/app/ocr/getOcrCode',
|
||||
method: 'POST',
|
||||
data: {
|
||||
image: processedBase64,
|
||||
jiju_type: '',
|
||||
auth_lic: 'xIWDlaDVdijcBB4mjhGCPYk5Kvk8tHZJbUn+vW+ih15+MYx98e/PXyBmKL5gFcWMPznLgDA15QuSAnZQSLddwdy9HkZgtuQDEEZZ351Eyb1eiDUccUnyoSGIrNimbx5TooBNNPYqU4qJeFrPJXAqjBHzRrxoBxuR2CEGKQPgHC4='
|
||||
},
|
||||
header: {
|
||||
"Content-Type": "application/json;charset=UTF-8"
|
||||
},
|
||||
success: async (res) => {
|
||||
if (!res.data.code) {
|
||||
res = JSON.parse(decryptWithSM4(res.data))
|
||||
} else {
|
||||
res = res.data
|
||||
}
|
||||
console.log("res", res);
|
||||
console.log("res.data", res.data)
|
||||
const {data: resData} = res
|
||||
console.log("resData", resData)
|
||||
console.log("resData.data", resData.data)
|
||||
console.log("resData.code", resData.code)
|
||||
console.log("resData.data.result", resData.data.result)
|
||||
|
||||
if (resData.code === 0) {
|
||||
if (resData.data.result) {
|
||||
this.queryCodeParams.maCode = resData.data.result
|
||||
await this.closeCamera();
|
||||
await this.getCode();
|
||||
await uni.showToast({
|
||||
title: '识别成功',
|
||||
icon: 'success'
|
||||
});
|
||||
} else {
|
||||
this.show('识别失败!', 'bottom')
|
||||
}
|
||||
} else {
|
||||
this.show('识别失败!', 'bottom')
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.showToast({
|
||||
title: '请求失败:' + err.errMsg,
|
||||
icon: 'none',
|
||||
})
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('相册图片处理或OCR识别失败:', error);
|
||||
this.show('识别失败!', 'bottom')
|
||||
} finally {
|
||||
this.isProcessing = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -281,6 +788,35 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
// 清理资源
|
||||
cleanup() {
|
||||
console.log('清理资源...');
|
||||
if (this.cameraStarted) {
|
||||
const CameraPreview = this.getCameraPlugin();
|
||||
if (CameraPreview) {
|
||||
CameraPreview.stopCamera();
|
||||
}
|
||||
this.cameraStarted = false;
|
||||
}
|
||||
|
||||
// 清除超时
|
||||
if (this.deviceReadyTimeout) {
|
||||
clearTimeout(this.deviceReadyTimeout);
|
||||
this.deviceReadyTimeout = null;
|
||||
}
|
||||
if (this.focusTimeout) {
|
||||
clearTimeout(this.focusTimeout);
|
||||
this.focusTimeout = null;
|
||||
}
|
||||
// 移除事件监听
|
||||
document.removeEventListener('deviceready', this.onDeviceReady);
|
||||
// 停止相机
|
||||
if (this.cameraStarted) {
|
||||
this.stopCamera().catch(console.error);
|
||||
}
|
||||
// 重置聚焦状态
|
||||
this.resetFocusState();
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -299,9 +835,18 @@ export default {
|
|||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
.custom-toast.top { top: 0; }
|
||||
.custom-toast.bottom { bottom: 0; }
|
||||
.custom-toast.show { opacity: 1; }
|
||||
|
||||
.custom-toast.top {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.custom-toast.bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.custom-toast.show {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.page-container {
|
||||
display: flex;
|
||||
|
|
@ -356,6 +901,7 @@ export default {
|
|||
z-index: 3;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.control-btn {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
|
|
|
|||
|
|
@ -1,210 +1,217 @@
|
|||
<template>
|
||||
<view class="page-container">
|
||||
<!-- 表单信息区域 -->
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<!-- 表单信息区域 -->
|
||||
<scroll-view scroll-y style="height: 100vh;">
|
||||
<view class="outbound-btn" @click="scanStart"> 二维码扫描 </view>
|
||||
<!-- <ScanQrCode ref="scanQrCodeRef" @scanSuccess="handleScanSuccess" @scanError="handleScanError" />-->
|
||||
<view class="form-section">
|
||||
<view class="section-header">
|
||||
<text class="title">设备信息</text>
|
||||
</view>
|
||||
<view class="form-content">
|
||||
<uni-forms :model="formData" label-width="100" :border="true">
|
||||
<uni-forms-item label="设备类型:" name="maName">
|
||||
<span class="form-view">{{codeData.maName}}</span>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="规格型号:" name="maModel">
|
||||
<span class="form-view">{{codeData.maModel}}</span>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="二维码编码:" name="qrCode">
|
||||
<span class="form-view">{{codeData.qrCode}}</span>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="设备编码:" name="maCode">
|
||||
<span class="form-view">{{codeData.maCode}}</span>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="设备状态:" name="maStatus">
|
||||
<span class="form-view">{{codeData.maStatus}}</span>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="本次检修时间:" name="checkTimeSynch">
|
||||
<text class="form-view">{{codeData.thisCheckTime}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="下次检修时间:" name="nextCheckTimeSynch">
|
||||
<text class="form-view">{{codeData.nextCheckTime}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="出入库次数:" name="inOutNum">
|
||||
<text class="form-view">{{codeData.inOutNum}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="初次入库:" name="inTime">
|
||||
<text class="form-view">{{codeData.inTime}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="服务工程次数:" name="serviceNum">
|
||||
<text class="form-view">{{codeData.serviceNum}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="检验次数:" name="serviceNum">
|
||||
<text class="form-view">{{codeData.serviceNum}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="更换配件次数:" name="checkNum">
|
||||
<text class="form-view">{{codeData.checkNum}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="报废:" name="scrapTime">
|
||||
<text class="form-view">{{codeData.scrapTime}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="生产厂家:" name="maVender">
|
||||
<text class="form-view">{{codeData.maVender}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="领料单位:" name="leaseUnit">
|
||||
<text class="form-view">{{codeData.leaseUnit}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="领料工程:" name="leaseProject">
|
||||
<text class="form-view">{{codeData.leaseProject}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="领料时间:" name="leaseTime">
|
||||
<text class="form-view">{{codeData.leaseTime}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="退料单位:" name="backUnit">
|
||||
<text class="form-view">{{codeData.backUnit}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="退料工程:" name="backProject">
|
||||
<text class="form-view">{{codeData.backProject}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="退料时间:" name="backTime">
|
||||
<text class="form-view">{{codeData.backTime}}</text>
|
||||
</uni-forms-item>
|
||||
</uni-forms>
|
||||
</view>
|
||||
|
||||
<view class="outbound-btn" @click="scanStart"> 二维码扫描 </view>
|
||||
<ScanQrCode ref="scanQrCodeRef" @scanSuccess="handleScanSuccess" @scanError="handleScanError" />
|
||||
<view class="form-section">
|
||||
<view class="section-header">
|
||||
<text class="title">设备信息</text>
|
||||
</view>
|
||||
<view class="form-content">
|
||||
<uni-forms :model="formData" label-width="100" :border="true">
|
||||
<uni-forms-item label="设备类型:" name="maName">
|
||||
<span class="form-view">{{codeData.maName}}</span>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="规格型号:" name="maModel">
|
||||
<span class="form-view">{{codeData.maModel}}</span>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="二维码编码:" name="qrCode">
|
||||
<span class="form-view">{{codeData.qrCode}}</span>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="设备编码:" name="maCode">
|
||||
<span class="form-view">{{codeData.maCode}}</span>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="设备状态:" name="maStatus">
|
||||
<span class="form-view">{{codeData.maStatus}}</span>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="本次检修时间:" name="checkTimeSynch">
|
||||
<text class="form-view">{{codeData.thisCheckTime}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="下次检修时间:" name="nextCheckTimeSynch">
|
||||
<text class="form-view">{{codeData.nextCheckTime}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="出入库次数:" name="inOutNum">
|
||||
<text class="form-view">{{codeData.inOutNum}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="初次入库:" name="inTime">
|
||||
<text class="form-view">{{codeData.inTime}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="服务工程次数:" name="serviceNum">
|
||||
<text class="form-view">{{codeData.serviceNum}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="检验次数:" name="serviceNum">
|
||||
<text class="form-view">{{codeData.serviceNum}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="更换配件次数:" name="checkNum">
|
||||
<text class="form-view">{{codeData.checkNum}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="报废:" name="scrapTime">
|
||||
<text class="form-view">{{codeData.scrapTime}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="生产厂家:" name="maVender">
|
||||
<text class="form-view">{{codeData.maVender}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="领料单位:" name="leaseUnit">
|
||||
<text class="form-view">{{codeData.leaseUnit}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="领料工程:" name="leaseProject">
|
||||
<text class="form-view">{{codeData.leaseProject}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="领料时间:" name="leaseTime">
|
||||
<text class="form-view">{{codeData.leaseTime}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="退料单位:" name="backUnit">
|
||||
<text class="form-view">{{codeData.backUnit}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="退料工程:" name="backProject">
|
||||
<text class="form-view">{{codeData.backProject}}</text>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="退料时间:" name="backTime">
|
||||
<text class="form-view">{{codeData.backTime}}</text>
|
||||
</uni-forms-item>
|
||||
</uni-forms>
|
||||
</view>
|
||||
|
||||
<div v-if="isOverToday && codeData.nextCheckTime">该工器具已临近下次检验时间,请及时退还至机具(物流)分公司!</div>
|
||||
<ElectronicSeal v-else v-show="codeData.maId" :maCode="codeData?.maCode" :maId="codeData?.maId" :devType="2" />
|
||||
</view>
|
||||
|
||||
<div v-if="isOverToday && codeData.nextCheckTime">该工器具已临近下次检验时间,请及时退还至机具(物流)分公司!</div>
|
||||
<ElectronicSeal v-else v-show="codeData.maId" :maCode="codeData?.maCode" :maId="codeData?.maId" :devType="2" />
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onUnmounted } from 'vue'
|
||||
import { onLoad, onShow, } from '@dcloudio/uni-app'
|
||||
import { debounce } from 'lodash-es'
|
||||
import { debounce } from 'lodash-es'
|
||||
import ScanQrCode from '@/pages/devicesSearch/ScanQrCode.vue'
|
||||
import { getDeviceListAPI } from '@/services/picking/outbound.js'
|
||||
import ElectronicSeal from '@/components/ElectronicSeal/index.vue'
|
||||
const scanQrCodeRef = ref(null)
|
||||
|
||||
const queryParams = ref({})
|
||||
const formData = ref({})
|
||||
const formData = ref({})
|
||||
// 编码设备列表查询参数
|
||||
const queryCodeParams = ref({
|
||||
maCode: '',
|
||||
})
|
||||
const qrCodeScan = ref('')
|
||||
const codeData = ref({})
|
||||
const codeData = ref({})
|
||||
const isOverToday = ref(false)
|
||||
|
||||
// ✅ 使用全局 hwqrcodescan 对象(由 Cordova 注入)
|
||||
let hwqrcodescan = null
|
||||
if (typeof window !== 'undefined' && window.cordova) {
|
||||
try {
|
||||
hwqrcodescan = require('cordova/plugin/hwscan')
|
||||
} catch (e) {
|
||||
console.warn('HwQrcodeScan插件未正确加载', e)
|
||||
}
|
||||
}
|
||||
|
||||
// 页面加载完毕
|
||||
onLoad(() => {
|
||||
// 页面加载时可检测插件是否可用
|
||||
if (!hwqrcodescan) {
|
||||
console.warn('HwQrcodeScan 插件不可用,请检查 Android 端是否已集成')
|
||||
}
|
||||
onLoad((options) => {
|
||||
// scanStart()
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
})
|
||||
})
|
||||
|
||||
const handleIsOverToday = () => {
|
||||
console.log('🚀 ~ .nextCheckTime:', codeData.value.nextCheckTime)
|
||||
if (!codeData.value.nextCheckTime) {
|
||||
isOverToday.value = true
|
||||
} else {
|
||||
const now = Date.now()
|
||||
const nextCheckTimestamp = new Date(codeData.value.nextCheckTime).getTime()
|
||||
isOverToday.value = nextCheckTimestamp <= now
|
||||
// console.log('🚀 ~ isOverToday ~ :', nextCheckDate < today)
|
||||
}
|
||||
console.log('🚀 ~ .nextCheckTime:', codeData.value.nextCheckTime)
|
||||
if (!codeData.value.nextCheckTime) {
|
||||
isOverToday.value = true
|
||||
} else {
|
||||
const now = Date.now()
|
||||
const nextCheckTimestamp = new Date(codeData.value.nextCheckTime).getTime()
|
||||
isOverToday.value = nextCheckTimestamp <= now
|
||||
// console.log('🚀 ~ isOverToday ~ :', nextCheckDate < today)
|
||||
}
|
||||
}
|
||||
|
||||
// 扫码识别按钮点击事件
|
||||
// // 扫码识别按钮
|
||||
// const scanStart = () => {
|
||||
// qrCodeScan.value = ''
|
||||
// codeData.value = {}
|
||||
// if (scanQrCodeRef.value) {
|
||||
// scanQrCodeRef.value.scanQrCode()
|
||||
// }
|
||||
//
|
||||
// // 调试用 --↓
|
||||
// // qrCodeScan.value = '201807-00009'
|
||||
// // getMaInfoScan()
|
||||
// }
|
||||
// var mpaasScanModule = uni.requireNativePlugin("Mpaas-Scan-Module")
|
||||
// mpaasScanModule.mpaasScan({
|
||||
// // 扫码识别类型,参数可多选,qrCode、barCode,不设置,默认识别所有
|
||||
// 'scanType': ['qrCode','barCode'],
|
||||
// // 是否隐藏相册,默认false不隐藏
|
||||
// 'hideAlbum': false,
|
||||
// //ios需要设置这个参数,只支持中英文 zh-Hans、en,默认中文
|
||||
// 'language' : 'en',
|
||||
// //相册选择照片识别错误提示(ios)
|
||||
// 'failedMsg': '未识别到二维码,请重试',
|
||||
// //Android支持全屏需要设置此参数
|
||||
// 'screenType': 'full'
|
||||
// },(ret) => {
|
||||
// if(ret.resp_code==10){
|
||||
// uni.showToast({ title: '用户取消', icon: 'none' })
|
||||
// }
|
||||
// if(ret.resp_code==11){
|
||||
// uni.showToast({ title: '扫码失败', icon: 'none' })
|
||||
// }
|
||||
// if(ret.resp_code==1000){
|
||||
// // uni.showToast({ title: '成功', icon: 'none' })
|
||||
// qrCodeScan.value = ret.resp_result.split("qrcode=")[1]
|
||||
// if (qrCodeScan.value=="") {
|
||||
// uni.showToast({ title: '扫码识别失败', icon: 'none'})
|
||||
// }else{
|
||||
// getMaInfoScan()
|
||||
// }
|
||||
// }
|
||||
|
||||
// ✅ 新的扫码逻辑
|
||||
// })
|
||||
// }
|
||||
// 扫码识别按钮点击事件
|
||||
const scanStart = () => {
|
||||
qrCodeScan.value = ''
|
||||
codeData.value = {}
|
||||
|
||||
if (hwqrcodescan && typeof hwqrcodescan.startScan === 'function') {
|
||||
hwqrcodescan.startScan("QrCode", function (result) {
|
||||
console.log('扫码成功:', result)
|
||||
handleScanSuccess({ data: result })
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '扫码功能不可用,请确认已集成HwQrcodeScan插件',
|
||||
icon: 'none'
|
||||
})
|
||||
if (scanQrCodeRef.value) {
|
||||
scanQrCodeRef.value.scanQrCode()
|
||||
}
|
||||
|
||||
// 调试用:
|
||||
// 调试用 --↓
|
||||
// qrCodeScan.value = '201807-00009'
|
||||
// getMaInfoScan()
|
||||
}
|
||||
|
||||
// 处理扫描成功事件
|
||||
const handleScanSuccess = (result) => {
|
||||
console.log('🚀 ~ handleScanSuccess ~ result:', result)
|
||||
qrCodeScan.value = result?.data?.split('?qrcode=')[1] || result?.data || result
|
||||
console.log('🚀 ~ handleScanSuccess ~ qrCodeScan.value:', qrCodeScan.value)
|
||||
if (!qrCodeScan.value) {
|
||||
uni.showToast({ title: '扫码识别失败', icon: 'none' })
|
||||
} else {
|
||||
getMaInfoScan()
|
||||
}
|
||||
console.log('🚀 ~ handleScanSuccess ~ result:', result)
|
||||
qrCodeScan.value = result?.data?.split('?qrcode=')[1] || result?.data
|
||||
console.log('🚀 ~ handleScanSuccess ~ qrCodeScan.value:', qrCodeScan.value)
|
||||
if (qrCodeScan.value === '') {
|
||||
uni.showToast({ title: '扫码识别失败', icon: 'none' })
|
||||
} else {
|
||||
getMaInfoScan()
|
||||
}
|
||||
}
|
||||
|
||||
// 处理扫描失败事件
|
||||
const handleScanError = (error) => {
|
||||
console.error('扫描出错:', error.message)
|
||||
uni.showToast({ title: error.message, icon: 'none' })
|
||||
console.error('扫描出错:', error.message)
|
||||
uni.showToast({ title: error.message, icon: 'none' })
|
||||
}
|
||||
|
||||
//查看是否是该规格型号
|
||||
const getMaInfoScan = async () => {
|
||||
try {
|
||||
uni.showLoading({ title: '加载中...', mask: true })
|
||||
let param = {
|
||||
qrCode: qrCodeScan.value,
|
||||
}
|
||||
console.log(param)
|
||||
const res = await getDeviceListAPI(param)
|
||||
console.log(res)
|
||||
if (res.code === 200 && res.data) {
|
||||
codeData.value = res.data[0] || {}
|
||||
setTimeout(handleIsOverToday, 500)
|
||||
} else {
|
||||
uni.showToast({ title: res?.msg || '未查询到设备信息', icon: 'none' })
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('🚀 ~ getMaInfoScan ~ error:', error)
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
const getMaInfoScan = async () => {
|
||||
try {
|
||||
uni.showLoading({ title: '加载中...', mask: true })
|
||||
let param = {
|
||||
qrCode: qrCodeScan.value,
|
||||
}
|
||||
console.log(param)
|
||||
const res = await getDeviceListAPI(param)
|
||||
console.log(res)
|
||||
if (res.code == 200) {
|
||||
if (res.data) {
|
||||
codeData.value = res.data[0]
|
||||
setTimeout(() => {
|
||||
handleIsOverToday()
|
||||
}, 500)
|
||||
}else{
|
||||
uni.showToast({ title: res.data.msg, icon: 'none'})
|
||||
}
|
||||
} else {
|
||||
uni.showToast({ title: res.data.msg, icon: 'none' })
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('🚀 ~ getMaInfoScan ~ error:', error)
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -212,236 +219,236 @@ const getMaInfoScan = async () => {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
.uni-forms-item--border[data-v-4c3fe719] {
|
||||
margin-bottom: 0;
|
||||
padding: 0 0;
|
||||
border-top: 1px #eee solid;
|
||||
margin-bottom: 0;
|
||||
padding: 0 0;
|
||||
border-top: 1px #eee solid;
|
||||
}
|
||||
.page-container {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
background-color: #f7f8fa;
|
||||
padding: 24rpx;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
background-color: #f7f8fa;
|
||||
padding: 24rpx;
|
||||
|
||||
.table-list-item {
|
||||
background: #fff;
|
||||
padding: 32rpx;
|
||||
border-radius: 20rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||
.table-list-item {
|
||||
background: #fff;
|
||||
padding: 32rpx;
|
||||
border-radius: 20rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
// 表单样式
|
||||
:deep(.uni-forms) {
|
||||
.uni-forms-item {
|
||||
margin-bottom: 24rpx;
|
||||
padding: 0;
|
||||
|
||||
// 表单样式
|
||||
:deep(.uni-forms) {
|
||||
.uni-forms-item {
|
||||
margin-bottom: 24rpx;
|
||||
padding: 0;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.uni-forms-item__label {
|
||||
color: #8c8c8c;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
padding: 0;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.uni-forms-item__content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: unset;
|
||||
}
|
||||
}
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
// 编码按钮组
|
||||
.coding-btn {
|
||||
padding: 16rpx 0;
|
||||
background: linear-gradient(135deg, #4b8eff 0%, #3784fb 100%);
|
||||
border-radius: 12rpx;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
// 编码检索按钮特殊样式
|
||||
&.search-btn {
|
||||
padding: 12rpx 0;
|
||||
background: #fff;
|
||||
color: #ff9800;
|
||||
border: 2rpx solid rgba(255, 152, 0, 0.5);
|
||||
background: linear-gradient(to bottom, rgba(255, 152, 0, 0.05), rgba(255, 152, 0, 0.1));
|
||||
box-shadow: none;
|
||||
font-weight: 600;
|
||||
letter-spacing: 1rpx;
|
||||
|
||||
&:active {
|
||||
background: rgba(255, 152, 0, 0.15);
|
||||
border-color: rgba(255, 152, 0, 0.6);
|
||||
transform: translateY(1rpx);
|
||||
}
|
||||
}
|
||||
.uni-forms-item__label {
|
||||
color: #8c8c8c;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
padding: 0;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
// 编码列表样式
|
||||
:deep(.uni-row) {
|
||||
/* margin-bottom: 20rpx; */
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.uni-col-6 {
|
||||
color: #8c8c8c;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.cont {
|
||||
color: #262626;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
line-height: 1.8;
|
||||
}
|
||||
}
|
||||
|
||||
// 输入框样式
|
||||
:deep(.uni-easyinput__content) {
|
||||
background-color: #f7f8fa;
|
||||
border: 2rpx solid #e8e8e8;
|
||||
border-radius: 12rpx;
|
||||
height: 75rpx;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:focus-within {
|
||||
border-color: #3784fb;
|
||||
box-shadow: 0 0 0 2rpx rgba(55, 132, 251, 0.1);
|
||||
}
|
||||
|
||||
.uni-easyinput__content-input {
|
||||
font-size: 28rpx;
|
||||
color: #262626;
|
||||
}
|
||||
}
|
||||
|
||||
// 复选框样式
|
||||
:deep(checkbox) {
|
||||
.wx-checkbox-input {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 2rpx solid #e8e8e8;
|
||||
background: transparent;
|
||||
|
||||
&.wx-checkbox-input-checked {
|
||||
background: #3784fb;
|
||||
border-color: #3784fb;
|
||||
|
||||
&::before {
|
||||
font-size: 28rpx;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&.wx-checkbox-input-disabled {
|
||||
background: #f5f5f5;
|
||||
border-color: #e8e8e8;
|
||||
}
|
||||
}
|
||||
.uni-forms-item__content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 底部出库按钮
|
||||
.outbound-btn {
|
||||
width: 96%;
|
||||
height: 88rpx;
|
||||
margin: 10rpx auto;
|
||||
background: linear-gradient(135deg, #4b8eff 0%, #3784fb 100%);
|
||||
text-align: center;
|
||||
line-height: 88rpx;
|
||||
color: #fff;
|
||||
border-radius: 12rpx;
|
||||
font-size: 32rpx;
|
||||
// 编码按钮组
|
||||
.coding-btn {
|
||||
padding: 16rpx 0;
|
||||
background: linear-gradient(135deg, #4b8eff 0%, #3784fb 100%);
|
||||
border-radius: 12rpx;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
// 编码检索按钮特殊样式
|
||||
&.search-btn {
|
||||
padding: 12rpx 0;
|
||||
background: #fff;
|
||||
color: #ff9800;
|
||||
border: 2rpx solid rgba(255, 152, 0, 0.5);
|
||||
background: linear-gradient(to bottom, rgba(255, 152, 0, 0.05), rgba(255, 152, 0, 0.1));
|
||||
box-shadow: none;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
letter-spacing: 1rpx;
|
||||
|
||||
&:active {
|
||||
background: rgba(255, 152, 0, 0.15);
|
||||
border-color: rgba(255, 152, 0, 0.6);
|
||||
transform: translateY(1rpx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 编码列表样式
|
||||
:deep(.uni-row) {
|
||||
/* margin-bottom: 20rpx; */
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.uni-col-6 {
|
||||
color: #8c8c8c;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.cont {
|
||||
color: #262626;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
line-height: 1.8;
|
||||
}
|
||||
}
|
||||
|
||||
// 输入框样式
|
||||
:deep(.uni-easyinput__content) {
|
||||
background-color: #f7f8fa;
|
||||
border: 2rpx solid #e8e8e8;
|
||||
border-radius: 12rpx;
|
||||
height: 75rpx;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:focus-within {
|
||||
border-color: #3784fb;
|
||||
box-shadow: 0 0 0 2rpx rgba(55, 132, 251, 0.1);
|
||||
}
|
||||
|
||||
.uni-easyinput__content-input {
|
||||
font-size: 28rpx;
|
||||
color: #262626;
|
||||
}
|
||||
}
|
||||
|
||||
// 复选框样式
|
||||
:deep(checkbox) {
|
||||
.wx-checkbox-input {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 2rpx solid #e8e8e8;
|
||||
background: transparent;
|
||||
|
||||
&.wx-checkbox-input-checked {
|
||||
background: #3784fb;
|
||||
border-color: #3784fb;
|
||||
|
||||
&::before {
|
||||
font-size: 28rpx;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&.wx-checkbox-input-disabled {
|
||||
background: #f5f5f5;
|
||||
border-color: #e8e8e8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 底部出库按钮
|
||||
.outbound-btn {
|
||||
width: 96%;
|
||||
height: 88rpx;
|
||||
margin: 10rpx auto;
|
||||
background: linear-gradient(135deg, #4b8eff 0%, #3784fb 100%);
|
||||
text-align: center;
|
||||
line-height: 88rpx;
|
||||
color: #fff;
|
||||
border-radius: 12rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
}
|
||||
|
||||
// 加载提示文字
|
||||
.loading-text {
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
color: #8c8c8c;
|
||||
padding: 32rpx 0;
|
||||
letter-spacing: 1rpx;
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
color: #8c8c8c;
|
||||
padding: 32rpx 0;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
margin-bottom: 24rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||
|
||||
// 头部样式
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24rpx 32rpx;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
margin-bottom: 24rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
// 头部样式
|
||||
.section-header {
|
||||
&:active {
|
||||
background: #f7f8fa;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #262626;
|
||||
}
|
||||
}
|
||||
|
||||
// 表单内容区域
|
||||
.form-content {
|
||||
// max-height: 0;
|
||||
overflow: auto;
|
||||
transition: max-height 0.3s ease-out;
|
||||
|
||||
:deep(.uni-forms) {
|
||||
padding: 0 32rpx 32rpx;
|
||||
}
|
||||
|
||||
:deep(.uni-forms-item) {
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.uni-forms-item__label {
|
||||
color: #8c8c8c;
|
||||
}
|
||||
|
||||
.form-view {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24rpx 32rpx;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
background: #f7f8fa;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #262626;
|
||||
}
|
||||
}
|
||||
|
||||
// 表单内容区域
|
||||
.form-content {
|
||||
// max-height: 0;
|
||||
overflow: auto;
|
||||
transition: max-height 0.3s ease-out;
|
||||
|
||||
:deep(.uni-forms) {
|
||||
padding: 0 32rpx 32rpx;
|
||||
}
|
||||
|
||||
:deep(.uni-forms-item) {
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.uni-forms-item__label {
|
||||
color: #8c8c8c;
|
||||
}
|
||||
|
||||
.form-view {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #262626;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
color: #262626;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue