emblemscanner: native wasm works
This commit is contained in:
parent
7c7c94fa7b
commit
adb87f27b5
@ -19,7 +19,8 @@ This is a WeChat Mini Program called "徵象" (emblem-scanner) for QR code scann
|
|||||||
**Key Components:**
|
**Key Components:**
|
||||||
- Camera system with device-specific zoom rules fetched from API
|
- Camera system with device-specific zoom rules fetched from API
|
||||||
- WebAssembly-based QR processing in worker thread for performance
|
- WebAssembly-based QR processing in worker thread for performance
|
||||||
- Dual camera modes: native camera (`pages/camera/`) and web view (`pages/camwebview/`)
|
- New emblemscanner (`pages/emblemscanner/`) for unified QR scanning experience
|
||||||
|
- Legacy camera page (`pages/camera/`) kept for reference to worker integration
|
||||||
- Upload and verification system connecting to themblem.com API
|
- Upload and verification system connecting to themblem.com API
|
||||||
|
|
||||||
**Global Data:**
|
**Global Data:**
|
||||||
|
|||||||
@ -3,12 +3,9 @@
|
|||||||
"pages/index/index",
|
"pages/index/index",
|
||||||
"pages/camera/camera",
|
"pages/camera/camera",
|
||||||
"pages/emblemscanner/emblemscanner",
|
"pages/emblemscanner/emblemscanner",
|
||||||
|
"pages/productinfo/productinfo",
|
||||||
"pages/test_result_page/test_result_page",
|
"pages/test_result_page/test_result_page",
|
||||||
"pages/debugentry/debugentry",
|
|
||||||
"pages/debuguploaded/debuguploaded",
|
|
||||||
"pages/camwebview/camwebview",
|
|
||||||
"pages/camentry/camentry",
|
"pages/camentry/camentry",
|
||||||
"pages/test/test",
|
|
||||||
"pages/article/article",
|
"pages/article/article",
|
||||||
"pages/nav/nav",
|
"pages/nav/nav",
|
||||||
"pages/chat/chat",
|
"pages/chat/chat",
|
||||||
|
|||||||
@ -274,8 +274,8 @@ Page({
|
|||||||
// this is from the debug backend sigifying the upload has succeeded
|
// this is from the debug backend sigifying the upload has succeeded
|
||||||
// we have no product info to show here because "ok" is the only returned information
|
// we have no product info to show here because "ok" is the only returned information
|
||||||
// just show a temporary page
|
// just show a temporary page
|
||||||
info("redirecting to debuguploaded");
|
info("redirecting to test result page");
|
||||||
wx.redirectTo({ url: '/pages/debuguploaded/debuguploaded' })
|
wx.redirectTo({ url: '/pages/test_result_page/test_result_page?qr_code=' + encodeURIComponent(upload_result.qr_code || 'unknown') })
|
||||||
} else {
|
} else {
|
||||||
this.show_verifyfailed();
|
this.show_verifyfailed();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,99 +0,0 @@
|
|||||||
// pages/camwebview/camwebview.js
|
|
||||||
|
|
||||||
import {
|
|
||||||
get_camera_rule,
|
|
||||||
get_phone_model,
|
|
||||||
} from '../../utils.js'
|
|
||||||
|
|
||||||
function make_query(zoom, ai_chat_mode) {
|
|
||||||
var gd = getApp().globalData;
|
|
||||||
var ret = "zoom=" + zoom;
|
|
||||||
var ui = wx.getStorageSync('userinfo');
|
|
||||||
ret += "&phonemodel=" + encodeURIComponent(get_phone_model());
|
|
||||||
ret += "&realip=" + (gd.real_ip || "");
|
|
||||||
ret += "&emblem_id=" + (ui.emblem_id || "");
|
|
||||||
ret += "&nick_name=" + encodeURIComponent(ui.nickName || "");
|
|
||||||
ret += "&tenant=" + (gd.tenant_id || "");
|
|
||||||
ret += "&tk=" + Date.now();
|
|
||||||
if (ai_chat_mode) {
|
|
||||||
ret += "&ai_chat_mode=" + ai_chat_mode;
|
|
||||||
}
|
|
||||||
console.log(ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
Page({
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面的初始数据
|
|
||||||
*/
|
|
||||||
data: {
|
|
||||||
emblem_camera_url: null,
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面加载
|
|
||||||
*/
|
|
||||||
onLoad(options) {
|
|
||||||
var ai_chat_mode = options.ai_chat_mode;
|
|
||||||
get_camera_rule(null, (rule) => {
|
|
||||||
// we should have rules loaded, so this is effectively sync, before instantiating Page
|
|
||||||
var zoom = rule.zoom;
|
|
||||||
this.setData({
|
|
||||||
emblem_camera_url: "https://themblem.com/camera-5.0/?" + make_query(zoom, ai_chat_mode),
|
|
||||||
});
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面初次渲染完成
|
|
||||||
*/
|
|
||||||
onReady() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面显示
|
|
||||||
*/
|
|
||||||
onShow() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面隐藏
|
|
||||||
*/
|
|
||||||
onHide() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面卸载
|
|
||||||
*/
|
|
||||||
onUnload() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面相关事件处理函数--监听用户下拉动作
|
|
||||||
*/
|
|
||||||
onPullDownRefresh() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面上拉触底事件的处理函数
|
|
||||||
*/
|
|
||||||
onReachBottom() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户点击右上角分享
|
|
||||||
*/
|
|
||||||
onShareAppMessage() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
on_message(e) {
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@ -1 +0,0 @@
|
|||||||
<web-view wx:if="{{ emblem_camera_url }}" src="{{ emblem_camera_url }}"></web-view>
|
|
||||||
@ -1 +0,0 @@
|
|||||||
/* pages/camwebview/camwebview.wxss */
|
|
||||||
@ -1,72 +0,0 @@
|
|||||||
// pages/debugentry/debugentry.js
|
|
||||||
|
|
||||||
import {
|
|
||||||
goto_camera,
|
|
||||||
} from '../../utils.js'
|
|
||||||
|
|
||||||
Page({
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面的初始数据
|
|
||||||
*/
|
|
||||||
data: {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面加载
|
|
||||||
*/
|
|
||||||
onLoad(options) {
|
|
||||||
getApp().globalData.debug = true;
|
|
||||||
goto_camera(true);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面初次渲染完成
|
|
||||||
*/
|
|
||||||
onReady() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面显示
|
|
||||||
*/
|
|
||||||
onShow() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面隐藏
|
|
||||||
*/
|
|
||||||
onHide() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面卸载
|
|
||||||
*/
|
|
||||||
onUnload() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面相关事件处理函数--监听用户下拉动作
|
|
||||||
*/
|
|
||||||
onPullDownRefresh() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面上拉触底事件的处理函数
|
|
||||||
*/
|
|
||||||
onReachBottom() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户点击右上角分享
|
|
||||||
*/
|
|
||||||
onShareAppMessage() {
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"usingComponents": {}
|
|
||||||
}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
<view>Emblem debug entry</view>
|
|
||||||
@ -1 +0,0 @@
|
|||||||
/* pages/debugentry/debugentry.wxss */
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
// pages/debuguploaded/debuguploaded.js
|
|
||||||
|
|
||||||
import {
|
|
||||||
goto_camera,
|
|
||||||
} from '../../utils.js'
|
|
||||||
|
|
||||||
Page({
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面的初始数据
|
|
||||||
*/
|
|
||||||
data: {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面加载
|
|
||||||
*/
|
|
||||||
onLoad(options) {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面初次渲染完成
|
|
||||||
*/
|
|
||||||
onReady() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面显示
|
|
||||||
*/
|
|
||||||
onShow() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面隐藏
|
|
||||||
*/
|
|
||||||
onHide() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面卸载
|
|
||||||
*/
|
|
||||||
onUnload() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面相关事件处理函数--监听用户下拉动作
|
|
||||||
*/
|
|
||||||
onPullDownRefresh() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面上拉触底事件的处理函数
|
|
||||||
*/
|
|
||||||
onReachBottom() {
|
|
||||||
|
|
||||||
},
|
|
||||||
goto_camera() {
|
|
||||||
goto_camera(true);
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"usingComponents": {}
|
|
||||||
}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
<view class="container">
|
|
||||||
<view class="alert">
|
|
||||||
已上传数据到调试后端
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<button class="primary" bindtap="goto_camera">返回到采集页面</button>
|
|
||||||
</view>
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
view.container {
|
|
||||||
padding-top: 100rpx;
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
view.alert {
|
|
||||||
margin: 0 1rem 1rem;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 1rem;
|
|
||||||
background-color: #eee;
|
|
||||||
}
|
|
||||||
@ -34,6 +34,16 @@ const {
|
|||||||
is_emblem_qr_pattern
|
is_emblem_qr_pattern
|
||||||
} = require('./libemblemscanner.js');
|
} = require('./libemblemscanner.js');
|
||||||
|
|
||||||
|
// Import upload functionality for verification (self-contained)
|
||||||
|
const {
|
||||||
|
upload_image_data_urls
|
||||||
|
} = require('./upload.js');
|
||||||
|
|
||||||
|
// Import precheck utilities for image processing
|
||||||
|
const {
|
||||||
|
data_url_from_frame
|
||||||
|
} = require('../../precheck.js');
|
||||||
|
|
||||||
// Import QR processing module
|
// Import QR processing module
|
||||||
const {
|
const {
|
||||||
load_qrtool,
|
load_qrtool,
|
||||||
@ -72,7 +82,6 @@ Page({
|
|||||||
debug_image_data_url: '',
|
debug_image_data_url: '',
|
||||||
debug_last_result: null,
|
debug_last_result: null,
|
||||||
qrtool_ready: false,
|
qrtool_ready: false,
|
||||||
frame_processing_started: false,
|
|
||||||
// Frame processing statistics
|
// Frame processing statistics
|
||||||
frames_processed: 0,
|
frames_processed: 0,
|
||||||
frames_skipped: 0,
|
frames_skipped: 0,
|
||||||
@ -83,8 +92,8 @@ Page({
|
|||||||
camera_rule: null,
|
camera_rule: null,
|
||||||
use_web_view: false,
|
use_web_view: false,
|
||||||
emblem_camera_url: null,
|
emblem_camera_url: null,
|
||||||
// State machine: initializing -> loading -> scanning -> verifying -> result
|
// State machine: loading_rules -> loading_qrtool -> init_camera -> scanning -> verifying -> result
|
||||||
app_state: 'initializing', // 'initializing', 'loading', 'scanning_camera', 'scanning_webview', 'verifying', 'result'
|
app_state: 'loading_rules', // 'loading_rules', 'loading_qrtool', 'init_camera', 'scanning', 'webview_scanning', 'verifying', 'result'
|
||||||
scan_mode: 'unknown', // 'camera', 'webview'
|
scan_mode: 'unknown', // 'camera', 'webview'
|
||||||
no_web_view: false // Override web-view rule, force native camera
|
no_web_view: false // Override web-view rule, force native camera
|
||||||
},
|
},
|
||||||
@ -99,20 +108,23 @@ Page({
|
|||||||
no_web_view: no_web_view
|
no_web_view: no_web_view
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Initialize image collection for verification
|
||||||
this.image_data_urls = [];
|
this.image_data_urls = [];
|
||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
const enable_debug = options.debug || options.scene == 'debug' || false;
|
const enable_debug = options.debug || options.scene == 'debug' || false;
|
||||||
|
|
||||||
|
// Step 1: Initialize system and get phone model
|
||||||
this.initializeSystem(enable_debug);
|
this.initializeSystem(enable_debug);
|
||||||
this.initializeQRTool();
|
|
||||||
this.fetchRealIP();
|
this.fetchRealIP();
|
||||||
this.fetchTenantID();
|
this.fetchTenantID();
|
||||||
|
|
||||||
|
// Step 2: Load camera rules based on phone model
|
||||||
this.loadCameraRules();
|
this.loadCameraRules();
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchRealIP() {
|
fetchRealIP() {
|
||||||
fetch_real_ip((err, ip) => {
|
fetch_real_ip((_err, ip) => {
|
||||||
this.setData({ real_ip: ip });
|
this.setData({ real_ip: ip });
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -129,8 +141,9 @@ Page({
|
|||||||
if (is_qrtool_ready()) {
|
if (is_qrtool_ready()) {
|
||||||
this.setData({ qrtool_ready: true });
|
this.setData({ qrtool_ready: true });
|
||||||
this.addDebugMessage('QRTool WASM loaded and ready');
|
this.addDebugMessage('QRTool WASM loaded and ready');
|
||||||
this.transitionToState('loading');
|
|
||||||
this.startFrameProcessingMaybe();
|
// Step 4: QRTool loaded, now initialize camera
|
||||||
|
this.startCameraInit();
|
||||||
} else {
|
} else {
|
||||||
setTimeout(checkReady, 100);
|
setTimeout(checkReady, 100);
|
||||||
}
|
}
|
||||||
@ -152,8 +165,8 @@ Page({
|
|||||||
console.log(`Phone model: ${phone_model}, Using native camera mode`);
|
console.log(`Phone model: ${phone_model}, Using native camera mode`);
|
||||||
},
|
},
|
||||||
|
|
||||||
loadCameraRules() {
|
loadCameraRules(max_zoom = null) {
|
||||||
get_camera_rule(null, (rule) => {
|
get_camera_rule(max_zoom, (rule) => {
|
||||||
console.log('Camera rule loaded:', rule);
|
console.log('Camera rule loaded:', rule);
|
||||||
|
|
||||||
const should_use_webview = rule.web_view && !this.data.no_web_view;
|
const should_use_webview = rule.web_view && !this.data.no_web_view;
|
||||||
@ -178,18 +191,41 @@ Page({
|
|||||||
this.addDebugMessage(`Camera rule: zoom=${rule.zoom}, web_view=${rule.web_view}${this.data.no_web_view ? ' (NO_WEB_VIEW)' : ''}`);
|
this.addDebugMessage(`Camera rule: zoom=${rule.zoom}, web_view=${rule.web_view}${this.data.no_web_view ? ' (NO_WEB_VIEW)' : ''}`);
|
||||||
|
|
||||||
if (should_use_webview) {
|
if (should_use_webview) {
|
||||||
|
// Step 3a: Go directly to webview scanning (no QRTool needed)
|
||||||
this.startWebviewScanning();
|
this.startWebviewScanning();
|
||||||
} else {
|
} else {
|
||||||
this.startCameraScanning();
|
// Step 3b: Load QRTool for camera mode
|
||||||
|
this.addDebugMessage('Starting QRTool initialization');
|
||||||
|
this.transitionToState('loading_qrtool');
|
||||||
|
this.initializeQRTool();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onCameraReady(e) {
|
onCameraReady(e) {
|
||||||
console.log('Camera ready', e);
|
console.log('Camera ready', e);
|
||||||
|
|
||||||
|
// Get max zoom from camera initialization
|
||||||
|
let max_zoom = null;
|
||||||
|
if (e && e.detail && e.detail.maxZoom) {
|
||||||
|
max_zoom = e.detail.maxZoom;
|
||||||
|
this.setData({
|
||||||
|
max_zoom: max_zoom
|
||||||
|
});
|
||||||
|
this.addDebugMessage(`Camera max zoom: ${max_zoom}`);
|
||||||
|
}
|
||||||
|
|
||||||
this.camera_context = wx.createCameraContext();
|
this.camera_context = wx.createCameraContext();
|
||||||
this.addDebugMessage('Camera initialized for WASM processing');
|
this.addDebugMessage('Camera context created');
|
||||||
this.startFrameProcessingMaybe();
|
|
||||||
|
// Step 5: Set up initial zoom and start scanning
|
||||||
|
if (this.data.camera_rule) {
|
||||||
|
this.setupCameraZoom(this.data.camera_rule);
|
||||||
|
this.addDebugMessage('Initial zoom set up');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 6: Transition to scanning (which also starts frame processing)
|
||||||
|
this.startCameraScanning();
|
||||||
},
|
},
|
||||||
|
|
||||||
onCameraError(e) {
|
onCameraError(e) {
|
||||||
@ -249,6 +285,39 @@ Page({
|
|||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up camera zoom functionality similar to camera.js
|
||||||
|
*/
|
||||||
|
setupCameraZoom(rule) {
|
||||||
|
if (!this.camera_context) {
|
||||||
|
this.addDebugMessage('Cannot setup zoom: camera context not ready');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('setupCameraZoom called:', rule);
|
||||||
|
const zoom = rule.zoom;
|
||||||
|
const initial_zoom = 2;
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
zoom: initial_zoom,
|
||||||
|
rule_zoom: zoom
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addDebugMessage(`Camera set initial zoom to ${initial_zoom}x, will zoom in to ${zoom}x when QR is found`);
|
||||||
|
this.camera_context.setZoom({ zoom: initial_zoom });
|
||||||
|
|
||||||
|
// Set up zoom-in behavior when QR is found
|
||||||
|
this.on_qr_found = () => {
|
||||||
|
this.addDebugMessage(`QR found, zoom to ${zoom}x`);
|
||||||
|
this.camera_context.setZoom({ zoom: zoom });
|
||||||
|
this.setData({
|
||||||
|
zoom: zoom,
|
||||||
|
qrmarkers_class: '',
|
||||||
|
qrarc_class: 'lg'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State Machine: Transition to new state
|
* State Machine: Transition to new state
|
||||||
*/
|
*/
|
||||||
@ -263,33 +332,28 @@ Page({
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State: Loading -> Scanning (Camera)
|
* State: Loading -> Init Camera (prepare camera context)
|
||||||
*/
|
*/
|
||||||
startCameraScanning() {
|
startCameraInit() {
|
||||||
this.transitionToState('scanning_camera', 'camera');
|
this.transitionToState('init_camera', 'camera');
|
||||||
this.setData({
|
this.setData({
|
||||||
hint_text: '查找二维码',
|
hint_text: '初始化相机...',
|
||||||
busy: false
|
busy: true
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start frame processing if both QRTool and camera are ready
|
* State: Init Camera -> Scanning (Camera)
|
||||||
|
* Also starts frame processing since all conditions are implied to be ready
|
||||||
*/
|
*/
|
||||||
startFrameProcessingMaybe() {
|
startCameraScanning() {
|
||||||
// Already started, nothing to do
|
this.transitionToState('scanning', 'camera');
|
||||||
if (this.data.frame_processing_started) {
|
this.setData({
|
||||||
return;
|
hint_text: '查找二维码',
|
||||||
}
|
busy: false
|
||||||
|
});
|
||||||
// Check if both are ready
|
|
||||||
if (!this.data.qrtool_ready || !this.camera_context) {
|
|
||||||
const qrStatus = this.data.qrtool_ready ? 'ready' : 'not ready';
|
|
||||||
const cameraStatus = this.camera_context ? 'ready' : 'not ready';
|
|
||||||
this.addDebugMessage(`Cannot start frame processing - QRTool: ${qrStatus}, Camera: ${cameraStatus}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Start frame processing - all conditions are implied to be ready at this point
|
||||||
this.addDebugMessage('Starting camera frame listener');
|
this.addDebugMessage('Starting camera frame listener');
|
||||||
this.lastFrameTime = 0;
|
this.lastFrameTime = 0;
|
||||||
|
|
||||||
@ -300,23 +364,21 @@ Page({
|
|||||||
|
|
||||||
// Start the listener
|
// Start the listener
|
||||||
this.listener.start();
|
this.listener.start();
|
||||||
|
|
||||||
// Mark as started
|
|
||||||
this.setData({ frame_processing_started: true });
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Camera frame callback - receives live camera frames
|
* Camera frame callback - receives live camera frames
|
||||||
*/
|
*/
|
||||||
onCameraFrame(frame) {
|
onCameraFrame(frame) {
|
||||||
// Only process frames when in camera scanning state and QRTool is ready
|
// Only process frames when in camera scanning state and QRTool is ready
|
||||||
if (this.data.app_state !== 'scanning_camera' || !this.data.qrtool_ready) {
|
if (this.data.app_state !== 'scanning') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Throttle frame processing to avoid overwhelming the system
|
// Throttle frame processing to avoid overwhelming the system
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
if (this.lastFrameTime && (now - this.lastFrameTime) < 200) {
|
if (this.lastFrameTime && (now - this.lastFrameTime) < 100) {
|
||||||
this.setData({
|
this.setData({
|
||||||
frames_skipped: this.data.frames_skipped + 1
|
frames_skipped: this.data.frames_skipped + 1
|
||||||
});
|
});
|
||||||
@ -349,7 +411,7 @@ Page({
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
this.handleQRResult(result);
|
this.handleQRResult(result, frame);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.addDebugMessage(`Frame processing error: ${error.message}`);
|
this.addDebugMessage(`Frame processing error: ${error.message}`);
|
||||||
@ -374,7 +436,7 @@ Page({
|
|||||||
/**
|
/**
|
||||||
* Handle QR processing result
|
* Handle QR processing result
|
||||||
*/
|
*/
|
||||||
handleQRResult(result) {
|
handleQRResult(result, frame) {
|
||||||
// Update debug info if available
|
// Update debug info if available
|
||||||
if (result.debug_data_url) {
|
if (result.debug_data_url) {
|
||||||
this.setData({
|
this.setData({
|
||||||
@ -385,10 +447,21 @@ Page({
|
|||||||
// Generate hint text
|
// Generate hint text
|
||||||
const hint = make_hint_text(result);
|
const hint = make_hint_text(result);
|
||||||
|
|
||||||
// Check if we have a valid QR code
|
// Check if we have a valid QR code that's ready for upload (like camera.js)
|
||||||
if (result.qrcode && result.valid_pattern && result.ok) {
|
// don't require ok as we only care about the view has a valid qrcode in it
|
||||||
this.addDebugMessage(`QR detected: ${result.qrcode}`);
|
// zooming in so that it's more likely to be clear enough for upload
|
||||||
this.onQRCodeDetected(result.qrcode);
|
if (!this.data.qr_found && result.qrcode && result.valid_pattern && is_emblem_qr_pattern(result.qrcode)) {
|
||||||
|
this.addDebugMessage(`QR detected and ready: ${result.qrcode}`);
|
||||||
|
|
||||||
|
// Trigger zoom-in if function is set up
|
||||||
|
if (this.on_qr_found) {
|
||||||
|
this.on_qr_found();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onQRCodeDetected(result.qrcode, frame);
|
||||||
|
this.setData({
|
||||||
|
qr_found: true
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// Update hint for user guidance
|
// Update hint for user guidance
|
||||||
this.setData({ hint_text: hint });
|
this.setData({ hint_text: hint });
|
||||||
@ -400,23 +473,88 @@ Page({
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle successful QR code detection
|
* Handle successful QR code detection - collect images from "ok" frames and verify
|
||||||
*/
|
*/
|
||||||
onQRCodeDetected(qrCode) {
|
onQRCodeDetected(qrCode, frameData) {
|
||||||
// Start verification process
|
// Convert frame data to data URL for upload (only called for "ok" frames)
|
||||||
this.startVerifying();
|
if (frameData) {
|
||||||
|
const dataUrl = data_url_from_frame(frameData.width, frameData.height, frameData.data);
|
||||||
|
this.image_data_urls.push(dataUrl);
|
||||||
|
this.addDebugMessage(`Collected ${this.image_data_urls.length}/3 good images`);
|
||||||
|
}
|
||||||
|
|
||||||
// Simulate verification delay, then go to result
|
// Need 3 "ok" frames before verification (like camera.js)
|
||||||
setTimeout(() => {
|
if (this.image_data_urls.length >= 3) {
|
||||||
this.goToResult(qrCode);
|
this.addDebugMessage('3 good images collected, starting verification');
|
||||||
}, 2000);
|
this.startVerifying();
|
||||||
|
this.submitImageForVerification(this.image_data_urls, qrCode);
|
||||||
|
this.image_data_urls = []; // Reset for next scan
|
||||||
|
}
|
||||||
|
// If less than 3 images, continue scanning to collect more
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State: Loading -> Scanning (Web-view)
|
* Submit images for verification like camera.js
|
||||||
|
*/
|
||||||
|
submitImageForVerification(dataUrls, qrCode) {
|
||||||
|
this.addDebugMessage('Submitting images for verification');
|
||||||
|
const begin = Date.now();
|
||||||
|
|
||||||
|
const success = (res) => {
|
||||||
|
this.addDebugMessage(`Upload success, code: ${res.statusCode}`);
|
||||||
|
if (res.statusCode === 200) {
|
||||||
|
let resp;
|
||||||
|
if (typeof res.data === "string") {
|
||||||
|
resp = JSON.parse(res.data);
|
||||||
|
} else {
|
||||||
|
resp = res.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store verification response
|
||||||
|
getApp().globalData.verify_resp = resp;
|
||||||
|
|
||||||
|
if (resp.serial_code) {
|
||||||
|
// Let verification animation run for a bit, then show result
|
||||||
|
const delay = 3000 - (Date.now() - begin);
|
||||||
|
setTimeout(() => {
|
||||||
|
this.goToResult(qrCode, resp.serial_code);
|
||||||
|
}, delay > 0 ? delay : 0);
|
||||||
|
} else {
|
||||||
|
this.showVerifyFailed();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.showVerifyFailed();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fail = (e) => {
|
||||||
|
this.addDebugMessage(`Upload failed: ${JSON.stringify(e)}`);
|
||||||
|
this.showVerifyFailed();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Store global data like camera.js
|
||||||
|
const gd = getApp().globalData;
|
||||||
|
gd.image_data_urls = dataUrls;
|
||||||
|
gd.qr_code = qrCode;
|
||||||
|
|
||||||
|
upload_image_data_urls(dataUrls, success, fail, "emblemscanner verification");
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show verification failed modal
|
||||||
|
*/
|
||||||
|
showVerifyFailed() {
|
||||||
|
this.setData({
|
||||||
|
show_modal: 'verifyfailed',
|
||||||
|
hint_text: '验证失败'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State: Loading Rules -> Webview Scanning
|
||||||
*/
|
*/
|
||||||
startWebviewScanning() {
|
startWebviewScanning() {
|
||||||
this.transitionToState('scanning_webview', 'webview');
|
this.transitionToState('webview_scanning', 'webview');
|
||||||
this.setData({
|
this.setData({
|
||||||
hint_text: '查找二维码',
|
hint_text: '查找二维码',
|
||||||
busy: false
|
busy: false
|
||||||
@ -437,12 +575,16 @@ Page({
|
|||||||
/**
|
/**
|
||||||
* State: Any -> Result (jump to return page)
|
* State: Any -> Result (jump to return page)
|
||||||
*/
|
*/
|
||||||
goToResult(qrCode) {
|
goToResult(qrCode, serialCode) {
|
||||||
this.transitionToState('result');
|
this.transitionToState('result');
|
||||||
|
|
||||||
if (this.data.return_page) {
|
if (this.data.return_page) {
|
||||||
wx.navigateTo({
|
// Pass both qr_code and serial_code parameters like camera-5.1 does
|
||||||
url: `${this.data.return_page}?qr_code=${encodeURIComponent(qrCode)}`,
|
// serialCode comes from server verification response
|
||||||
|
const url = `${this.data.return_page}?qr_code=${encodeURIComponent(qrCode)}&serial_code=${encodeURIComponent(serialCode)}`;
|
||||||
|
|
||||||
|
wx.redirectTo({
|
||||||
|
url: url,
|
||||||
success: () => {
|
success: () => {
|
||||||
this.addDebugMessage(`Navigated to: ${this.data.return_page}`);
|
this.addDebugMessage(`Navigated to: ${this.data.return_page}`);
|
||||||
},
|
},
|
||||||
@ -475,8 +617,7 @@ Page({
|
|||||||
frames_skipped: 0,
|
frames_skipped: 0,
|
||||||
total_processing_time: 0,
|
total_processing_time: 0,
|
||||||
avg_processing_time_ms: 0,
|
avg_processing_time_ms: 0,
|
||||||
last_frame_time_ms: 0,
|
last_frame_time_ms: 0
|
||||||
frame_processing_started: false
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Reset frame timing
|
// Reset frame timing
|
||||||
|
|||||||
@ -1,18 +1,36 @@
|
|||||||
<view class="wrapper">
|
<view class="wrapper">
|
||||||
<!-- STATE: INITIALIZING -->
|
<!-- STATE: LOADING_RULES -->
|
||||||
<view wx:if="{{ app_state == 'initializing' }}" class="loading-spinner">
|
<view wx:if="{{ app_state == 'loading_rules' }}" class="loading-spinner">
|
||||||
|
<view class="spinner"></view>
|
||||||
|
<text>加载相机规则...</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- STATE: LOADING_QRTOOL -->
|
||||||
|
<view wx:if="{{ app_state == 'loading_qrtool' }}" class="loading-spinner">
|
||||||
<view class="spinner"></view>
|
<view class="spinner"></view>
|
||||||
<text>初始化QR工具...</text>
|
<text>初始化QR工具...</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- STATE: LOADING -->
|
<!-- STATE: INIT_CAMERA -->
|
||||||
<view wx:if="{{ app_state == 'loading' }}" class="loading-spinner">
|
<block wx:if="{{ app_state == 'init_camera' }}">
|
||||||
<view class="spinner"></view>
|
<!-- Show camera without overlays during initialization -->
|
||||||
<text>初始化相机...</text>
|
<view class="osd">
|
||||||
</view>
|
<view class="upper" bindtap="debug_tap">
|
||||||
|
{{ hint_text }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- STATE: SCANNING_CAMERA -->
|
<!-- WeChat native camera -->
|
||||||
<block wx:if="{{ app_state == 'scanning_camera' }}">
|
<camera class="camera"
|
||||||
|
flash="{{ camera_flash }}"
|
||||||
|
frame-size="medium"
|
||||||
|
bindinitdone="onCameraReady"
|
||||||
|
binderror="onCameraError">
|
||||||
|
</camera>
|
||||||
|
</block>
|
||||||
|
|
||||||
|
<!-- STATE: SCANNING -->
|
||||||
|
<block wx:if="{{ app_state == 'scanning' }}">
|
||||||
<!-- QR targeting arcs overlay -->
|
<!-- QR targeting arcs overlay -->
|
||||||
<view class="qrarc {{ qrarc_class }}">
|
<view class="qrarc {{ qrarc_class }}">
|
||||||
<image class="topleft arc" src="./assets/arc.png"></image>
|
<image class="topleft arc" src="./assets/arc.png"></image>
|
||||||
@ -42,8 +60,8 @@
|
|||||||
</camera>
|
</camera>
|
||||||
</block>
|
</block>
|
||||||
|
|
||||||
<!-- STATE: SCANNING_WEBVIEW -->
|
<!-- STATE: WEBVIEW_SCANNING -->
|
||||||
<block wx:if="{{ app_state == 'scanning_webview' }}">
|
<block wx:if="{{ app_state == 'webview_scanning' }}">
|
||||||
<!-- Web-view camera (no overlays) -->
|
<!-- Web-view camera (no overlays) -->
|
||||||
<web-view src="{{ emblem_camera_url }}"
|
<web-view src="{{ emblem_camera_url }}"
|
||||||
bindmessage="on_webview_message">
|
bindmessage="on_webview_message">
|
||||||
@ -144,8 +162,8 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- Bottom action controls (only for camera scanning) -->
|
<!-- Bottom action controls (for camera init and scanning) -->
|
||||||
<view wx:if="{{ app_state == 'scanning_camera' }}" class="bottomfixed">
|
<view wx:if="{{ app_state == 'init_camera' || app_state == 'scanning' }}" class="bottomfixed">
|
||||||
<view class="actions">
|
<view class="actions">
|
||||||
<view class="half {{ show_tip ? 'brighter' : '' }}" bindtap="show_scanguide">
|
<view class="half {{ show_tip ? 'brighter' : '' }}" bindtap="show_scanguide">
|
||||||
<view class="icon">
|
<view class="icon">
|
||||||
@ -194,7 +212,7 @@
|
|||||||
<view wx:if="{{ show_modal == 'verifyfailed' }}" class="modal">
|
<view wx:if="{{ show_modal == 'verifyfailed' }}" class="modal">
|
||||||
<view class="modal-content">
|
<view class="modal-content">
|
||||||
<text>验证失败</text>
|
<text>验证失败</text>
|
||||||
<button bindtap="restart_camera">重新扫描</button>
|
<button bindtap="restartScanning">重新扫描</button>
|
||||||
<button bindtap="show_service">联系客服</button>
|
<button bindtap="show_service">联系客服</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -206,7 +224,7 @@
|
|||||||
<view>1. 将QR码置于框内</view>
|
<view>1. 将QR码置于框内</view>
|
||||||
<view>2. 保持稳定</view>
|
<view>2. 保持稳定</view>
|
||||||
<view>3. 确保光线充足</view>
|
<view>3. 确保光线充足</view>
|
||||||
<button bindtap="restart_camera">开始扫描</button>
|
<button bindtap="close_modal">开始扫描</button>
|
||||||
<button bindtap="show_service">联系客服</button>
|
<button bindtap="show_service">联系客服</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -10,7 +10,6 @@ var qrtool_ready = false;
|
|||||||
function load_qrtool() {
|
function load_qrtool() {
|
||||||
var m = require('./qrtool.wx.js');
|
var m = require('./qrtool.wx.js');
|
||||||
m.onRuntimeInitialized = () => {
|
m.onRuntimeInitialized = () => {
|
||||||
console.log("QRTool runtime initialized");
|
|
||||||
qrtool_ready = true;
|
qrtool_ready = true;
|
||||||
qrtool = m;
|
qrtool = m;
|
||||||
}
|
}
|
||||||
@ -28,39 +27,17 @@ function is_qrtool_ready() {
|
|||||||
*/
|
*/
|
||||||
function process_frame(width, height, image_data, camera_sensitivity, enable_debug = false) {
|
function process_frame(width, height, image_data, camera_sensitivity, enable_debug = false) {
|
||||||
if (!qrtool_ready) {
|
if (!qrtool_ready) {
|
||||||
console.log("qrtool not ready");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('process_frame called:', {
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
data_type: typeof image_data,
|
|
||||||
data_constructor: image_data ? image_data.constructor.name : 'undefined',
|
|
||||||
data_length: image_data ? image_data.length : 'undefined',
|
|
||||||
data_byteLength: image_data ? image_data.byteLength : 'undefined',
|
|
||||||
bytes_per_element: image_data ? image_data.BYTES_PER_ELEMENT : 'undefined',
|
|
||||||
camera_sensitivity,
|
|
||||||
enable_debug
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Copy frame data to avoid TOCTOU
|
// Copy frame data to avoid TOCTOU
|
||||||
var uca1 = new Uint8ClampedArray(image_data);
|
var uca1 = new Uint8ClampedArray(image_data);
|
||||||
var uca = new Uint8ClampedArray(uca1);
|
var uca = new Uint8ClampedArray(uca1);
|
||||||
|
|
||||||
console.log('Frame data copied:', {
|
|
||||||
uca_length: uca.length,
|
|
||||||
uca_bytes_per_element: uca.BYTES_PER_ELEMENT
|
|
||||||
});
|
|
||||||
|
|
||||||
var buf = qrtool._malloc(uca.length * uca.BYTES_PER_ELEMENT);
|
var buf = qrtool._malloc(uca.length * uca.BYTES_PER_ELEMENT);
|
||||||
qrtool.HEAPU8.set(uca, buf);
|
qrtool.HEAPU8.set(uca, buf);
|
||||||
|
|
||||||
console.log('Buffer allocated:', {
|
|
||||||
buffer_size: uca.length * uca.BYTES_PER_ELEMENT
|
|
||||||
});
|
|
||||||
|
|
||||||
var dot_area_buf = 0;
|
var dot_area_buf = 0;
|
||||||
var debug_data_url = null;
|
var debug_data_url = null;
|
||||||
|
|
||||||
@ -75,8 +52,6 @@ function process_frame(width, height, image_data, camera_sensitivity, enable_deb
|
|||||||
[buf, width, height, dot_area_buf, camera_sensitivity || 1]
|
[buf, width, height, dot_area_buf, camera_sensitivity || 1]
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log('qrtool_angle result:', result_str);
|
|
||||||
|
|
||||||
if (enable_debug && dot_area_buf) {
|
if (enable_debug && dot_area_buf) {
|
||||||
const dot_area_size = 32;
|
const dot_area_size = 32;
|
||||||
const da_len = dot_area_size * dot_area_size * uca.BYTES_PER_ELEMENT * 4;
|
const da_len = dot_area_size * dot_area_size * uca.BYTES_PER_ELEMENT * 4;
|
||||||
|
|||||||
71
scanner/pages/emblemscanner/upload.js
Normal file
71
scanner/pages/emblemscanner/upload.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
function upload_image_data_urls(image_data_urls, success, fail, log) {
|
||||||
|
do_upload(image_data_urls, success, fail, log);
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_auto_torch(qrcode, cb) {
|
||||||
|
var gd = getApp().globalData;
|
||||||
|
var url = gd.server_url + '/api/v1/check-auto-torch/?qrcode=' + encodeURIComponent(qrcode);
|
||||||
|
console.log("check_auto_torch:", url);
|
||||||
|
const fail = (e) => {
|
||||||
|
console.log("failed to check auto torch", e);
|
||||||
|
cb(false, null);
|
||||||
|
};
|
||||||
|
const success = (res) => {
|
||||||
|
if (res.statusCode == 200) {
|
||||||
|
var resp;
|
||||||
|
console.log(res.data);
|
||||||
|
if (typeof res.data == "string") {
|
||||||
|
resp = JSON.parse(res.data);
|
||||||
|
} else {
|
||||||
|
resp = res.data;
|
||||||
|
}
|
||||||
|
cb(resp.enable_auto_torch, resp.camera_sensitivity);
|
||||||
|
} else {
|
||||||
|
console.log("failed to check auto torch", res.data);
|
||||||
|
cb(false, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
wx.request({
|
||||||
|
url,
|
||||||
|
method: "GET",
|
||||||
|
success,
|
||||||
|
fail,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function do_upload(image_data_urls, success, fail, log) {
|
||||||
|
var ui = wx.getStorageSync('userinfo');
|
||||||
|
var gd = getApp().globalData;
|
||||||
|
var fd = {
|
||||||
|
emblem_id: ui.emblem_id,
|
||||||
|
nick_name: ui.nickName,
|
||||||
|
realip: gd.real_ip,
|
||||||
|
qrcode: gd.qr_code,
|
||||||
|
angle: 0,
|
||||||
|
phonemodel: gd.phone_model,
|
||||||
|
image_data_urls,
|
||||||
|
use_roi_verify: 1,
|
||||||
|
log,
|
||||||
|
};
|
||||||
|
var ci = gd.caller_info;
|
||||||
|
if (ci && ci.token) {
|
||||||
|
fd.token = ci.token;
|
||||||
|
}
|
||||||
|
var url = gd.server_url + '/api/v1/qr-verify/';
|
||||||
|
console.log("wx.request", url, fd.qrcode, fd.angle, fd.phonemodel, fd.realip);
|
||||||
|
wx.request({
|
||||||
|
url,
|
||||||
|
method: "POST",
|
||||||
|
header: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
data: JSON.stringify(fd),
|
||||||
|
success,
|
||||||
|
fail,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
upload_image_data_urls,
|
||||||
|
check_auto_torch,
|
||||||
|
};
|
||||||
@ -128,7 +128,9 @@ Page({
|
|||||||
|
|
||||||
goto_camera: function () {
|
goto_camera: function () {
|
||||||
this.getUserProfile(() => {
|
this.getUserProfile(() => {
|
||||||
goto_camera(false);
|
wx.navigateTo({
|
||||||
|
url: '/pages/emblemscanner/emblemscanner?return_page=/pages/test_result_page/test_result_page'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -1,37 +1,44 @@
|
|||||||
|
// pages/productinfo/productinfo.js
|
||||||
// pages/test/test.js
|
|
||||||
Page({
|
Page({
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page initial data
|
* Page initial data
|
||||||
*/
|
*/
|
||||||
data: {
|
data: {
|
||||||
|
url: null,
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lifecycle function--Called when page load
|
* Lifecycle function--Called when page load
|
||||||
*/
|
*/
|
||||||
onLoad(options) {
|
onLoad(options) {
|
||||||
|
var base_url = getApp().globalData.server_url + '/api/product-info/';
|
||||||
|
var url = base_url + options.serial_code + '/';
|
||||||
|
console.log(url);
|
||||||
|
this.setData({
|
||||||
|
url: url,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lifecycle function--Called when page is initially rendered
|
* Lifecycle function--Called when page is initially rendered
|
||||||
*/
|
*/
|
||||||
onReady() {
|
onReady() {
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lifecycle function--Called when page show
|
* Lifecycle function--Called when page show
|
||||||
*/
|
*/
|
||||||
onShow() {
|
onShow() {
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lifecycle function--Called when page hide
|
* Lifecycle function--Called when page hide
|
||||||
*/
|
*/
|
||||||
onHide() {
|
onHide() {
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
1
scanner/pages/productinfo/productinfo.wxml
Normal file
1
scanner/pages/productinfo/productinfo.wxml
Normal file
@ -0,0 +1 @@
|
|||||||
|
<web-view wx:if="{{ url }}" src="{{url}}"></web-view>
|
||||||
1
scanner/pages/productinfo/productinfo.wxss
Normal file
1
scanner/pages/productinfo/productinfo.wxss
Normal file
@ -0,0 +1 @@
|
|||||||
|
/* pages/productinfo/productinfo.wxss */
|
||||||
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"usingComponents": {
|
|
||||||
"verifyspin": "/components/verifyspin/verifyspin",
|
|
||||||
"verifyfailed": "/components/verifyfailed/verifyfailed",
|
|
||||||
"scanguide": "/components/scanguide/scanguide",
|
|
||||||
"servicemodal": "/components/servicemodal/servicemodal"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
<text>a</text>
|
|
||||||
<text>b</text>
|
|
||||||
@ -77,18 +77,16 @@ function get_camera_rule(max_zoom, cb) {
|
|||||||
|
|
||||||
function goto_camera(redirect, opts) {
|
function goto_camera(redirect, opts) {
|
||||||
var query = opts || "";
|
var query = opts || "";
|
||||||
get_camera_rule(null, (rule) => {
|
// Route to emblemscanner with return page for product info
|
||||||
console.log("camera rule:", rule);
|
var url = "/pages/emblemscanner/emblemscanner?return_page=/pages/productinfo/productinfo";
|
||||||
var url = "/pages/camera/camera?" + query;
|
if (query) {
|
||||||
if (rule.web_view) {
|
url += "&" + query;
|
||||||
url = "/pages/camwebview/camwebview?" + query;
|
}
|
||||||
}
|
if (redirect) {
|
||||||
if (redirect) {
|
wx.redirectTo({ url });
|
||||||
wx.redirectTo({ url });
|
} else {
|
||||||
} else {
|
wx.navigateTo({ url });
|
||||||
wx.navigateTo({ url });
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function make_new_session_id() {
|
function make_new_session_id() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user