camera: restore 4.0 and introduce 5.0
@ -246,7 +246,6 @@ async function submit_image(qrcode, angle, image_data_url) {
|
|||||||
var nick_name = get_query("nick_name");
|
var nick_name = get_query("nick_name");
|
||||||
var realip = get_query("realip");
|
var realip = get_query("realip");
|
||||||
var phonemodel = get_query("phonemodel");
|
var phonemodel = get_query("phonemodel");
|
||||||
var skip_angle_check = get_query("skip_angle_check");
|
|
||||||
var data = {
|
var data = {
|
||||||
emblem_id,
|
emblem_id,
|
||||||
nick_name,
|
nick_name,
|
||||||
@ -255,7 +254,6 @@ async function submit_image(qrcode, angle, image_data_url) {
|
|||||||
angle,
|
angle,
|
||||||
phonemodel,
|
phonemodel,
|
||||||
image_data_url,
|
image_data_url,
|
||||||
skip_angle_check,
|
|
||||||
log: debug_logs.join("\n"),
|
log: debug_logs.join("\n"),
|
||||||
};
|
};
|
||||||
var r = await fetch("https://themblem.com/api/v1/qr-verify/", {
|
var r = await fetch("https://themblem.com/api/v1/qr-verify/", {
|
||||||
|
|||||||
@ -479,10 +479,10 @@ function createWasm() {
|
|||||||
function receiveInstance(instance, module) {
|
function receiveInstance(instance, module) {
|
||||||
var exports = instance.exports;
|
var exports = instance.exports;
|
||||||
Module["asm"] = exports;
|
Module["asm"] = exports;
|
||||||
wasmMemory = Module["asm"]["Kb"];
|
wasmMemory = Module["asm"]["Tb"];
|
||||||
updateGlobalBufferAndViews(wasmMemory.buffer);
|
updateGlobalBufferAndViews(wasmMemory.buffer);
|
||||||
wasmTable = Module["asm"]["Nb"];
|
wasmTable = Module["asm"]["Wb"];
|
||||||
addOnInit(Module["asm"]["Lb"]);
|
addOnInit(Module["asm"]["Ub"]);
|
||||||
removeRunDependency("wasm-instantiate");
|
removeRunDependency("wasm-instantiate");
|
||||||
}
|
}
|
||||||
addRunDependency("wasm-instantiate");
|
addRunDependency("wasm-instantiate");
|
||||||
@ -3869,215 +3869,224 @@ function intArrayFromString(stringy, dontAddNull, length) {
|
|||||||
|
|
||||||
var asmLibraryArg = {
|
var asmLibraryArg = {
|
||||||
"K": ___cxa_allocate_exception,
|
"K": ___cxa_allocate_exception,
|
||||||
"y": ___cxa_begin_catch,
|
"z": ___cxa_begin_catch,
|
||||||
"wb": ___cxa_current_primary_exception,
|
"Bb": ___cxa_current_primary_exception,
|
||||||
"Ja": ___cxa_decrement_exception_refcount,
|
"La": ___cxa_decrement_exception_refcount,
|
||||||
"F": ___cxa_end_catch,
|
"F": ___cxa_end_catch,
|
||||||
"b": ___cxa_find_matching_catch_2,
|
"b": ___cxa_find_matching_catch_2,
|
||||||
"n": ___cxa_find_matching_catch_3,
|
"n": ___cxa_find_matching_catch_3,
|
||||||
"C": ___cxa_find_matching_catch_4,
|
"x": ___cxa_find_matching_catch_4,
|
||||||
"L": ___cxa_free_exception,
|
"M": ___cxa_free_exception,
|
||||||
"Ia": ___cxa_increment_exception_refcount,
|
"Ka": ___cxa_increment_exception_refcount,
|
||||||
"Ea": ___cxa_rethrow,
|
"Fa": ___cxa_rethrow,
|
||||||
"vb": ___cxa_rethrow_primary_exception,
|
"Ab": ___cxa_rethrow_primary_exception,
|
||||||
"J": ___cxa_throw,
|
"J": ___cxa_throw,
|
||||||
"xb": ___cxa_uncaught_exceptions,
|
"Cb": ___cxa_uncaught_exceptions,
|
||||||
"e": ___resumeException,
|
"e": ___resumeException,
|
||||||
"Ka": ___syscall_fcntl64,
|
"Ma": ___syscall_fcntl64,
|
||||||
"Cb": ___syscall_ioctl,
|
"Hb": ___syscall_ioctl,
|
||||||
"La": ___syscall_open,
|
"Na": ___syscall_open,
|
||||||
"Ga": _abort,
|
"Ia": _abort,
|
||||||
"Ha": _clock_gettime,
|
"Ja": _clock_gettime,
|
||||||
"Bb": _emscripten_get_heap_max,
|
"Gb": _emscripten_get_heap_max,
|
||||||
"tb": _emscripten_memcpy_big,
|
"yb": _emscripten_memcpy_big,
|
||||||
"ub": _emscripten_resize_heap,
|
"zb": _emscripten_resize_heap,
|
||||||
"zb": _environ_get,
|
"Eb": _environ_get,
|
||||||
"Ab": _environ_sizes_get,
|
"Fb": _environ_sizes_get,
|
||||||
"na": _fd_close,
|
"ra": _fd_close,
|
||||||
"Ma": _fd_read,
|
"Oa": _fd_read,
|
||||||
"pb": _fd_seek,
|
"tb": _fd_seek,
|
||||||
"oa": _fd_write,
|
"sa": _fd_write,
|
||||||
"a": _getTempRet0,
|
"a": _getTempRet0,
|
||||||
"Z": invoke_di,
|
"_": invoke_di,
|
||||||
"v": invoke_dii,
|
"w": invoke_dii,
|
||||||
"V": invoke_diii,
|
"X": invoke_diii,
|
||||||
"o": invoke_fi,
|
"p": invoke_fi,
|
||||||
"I": invoke_fii,
|
"I": invoke_fii,
|
||||||
"Da": invoke_fiii,
|
"Ea": invoke_fiii,
|
||||||
"Ib": invoke_fiiii,
|
"Nb": invoke_fiiii,
|
||||||
"Oa": invoke_fiiiii,
|
"Qa": invoke_fiiiii,
|
||||||
"X": invoke_fiiiiii,
|
"Y": invoke_fiiiiii,
|
||||||
"r": invoke_i,
|
"r": invoke_i,
|
||||||
"c": invoke_ii,
|
"c": invoke_ii,
|
||||||
"R": invoke_iid,
|
"S": invoke_iid,
|
||||||
"ma": invoke_iif,
|
"qa": invoke_iif,
|
||||||
"T": invoke_iifff,
|
"U": invoke_iifff,
|
||||||
"mb": invoke_iifii,
|
"pb": invoke_iifii,
|
||||||
"d": invoke_iii,
|
"d": invoke_iii,
|
||||||
"j": invoke_iiii,
|
"j": invoke_iiii,
|
||||||
"la": invoke_iiiidd,
|
"pa": invoke_iiiidd,
|
||||||
"va": invoke_iiiidi,
|
"xa": invoke_iiiidi,
|
||||||
"D": invoke_iiiidii,
|
"A": invoke_iiiidii,
|
||||||
"Hb": invoke_iiiiff,
|
"Mb": invoke_iiiiff,
|
||||||
"m": invoke_iiiii,
|
"m": invoke_iiiii,
|
||||||
"xa": invoke_iiiiid,
|
"ya": invoke_iiiiid,
|
||||||
"da": invoke_iiiiidii,
|
"fa": invoke_iiiiidii,
|
||||||
"p": invoke_iiiiii,
|
"o": invoke_iiiiii,
|
||||||
"s": invoke_iiiiiii,
|
"s": invoke_iiiiiii,
|
||||||
"Eb": invoke_iiiiiiif,
|
"Jb": invoke_iiiiiiif,
|
||||||
"ka": invoke_iiiiiiii,
|
"na": invoke_iiiiiiii,
|
||||||
"H": invoke_iiiiiiiii,
|
"H": invoke_iiiiiiiii,
|
||||||
"Qa": invoke_iiiiiiiiii,
|
"Sa": invoke_iiiiiiiiii,
|
||||||
"ha": invoke_iiiiiiiiiii,
|
"V": invoke_iiiiiiiiiii,
|
||||||
"ca": invoke_iiiiiiiiiiii,
|
"ea": invoke_iiiiiiiiiiii,
|
||||||
"nb": invoke_iiiiij,
|
"rb": invoke_iiiiij,
|
||||||
"sb": invoke_j,
|
"xb": invoke_j,
|
||||||
"qb": invoke_jii,
|
"vb": invoke_jii,
|
||||||
"rb": invoke_jiii,
|
"wb": invoke_jiii,
|
||||||
"ob": invoke_jiiii,
|
"sb": invoke_jiiii,
|
||||||
"t": invoke_v,
|
"u": invoke_v,
|
||||||
"ib": invoke_vdiii,
|
"lb": invoke_vdiii,
|
||||||
"ab": invoke_vffi,
|
"bb": invoke_vffi,
|
||||||
"Xa": invoke_vfi,
|
"Ya": invoke_vfi,
|
||||||
"i": invoke_vi,
|
"i": invoke_vi,
|
||||||
"N": invoke_vidi,
|
"R": invoke_vid,
|
||||||
"U": invoke_vididdii,
|
"O": invoke_vidi,
|
||||||
"Aa": invoke_vidii,
|
"W": invoke_vididdii,
|
||||||
"Gb": invoke_viffffffff,
|
"Ba": invoke_vidii,
|
||||||
"S": invoke_vifi,
|
"Lb": invoke_viffffffff,
|
||||||
"sa": invoke_vifii,
|
"T": invoke_vifi,
|
||||||
|
"Va": invoke_vifii,
|
||||||
"g": invoke_vii,
|
"g": invoke_vii,
|
||||||
"l": invoke_viid,
|
"l": invoke_viid,
|
||||||
"lb": invoke_viidf,
|
"qb": invoke_viidd,
|
||||||
|
"nb": invoke_viidf,
|
||||||
"G": invoke_viididii,
|
"G": invoke_viididii,
|
||||||
"bb": invoke_viidiiid,
|
"Ga": invoke_viidiiid,
|
||||||
"W": invoke_viidiiiii,
|
"ga": invoke_viidiiiii,
|
||||||
"Pa": invoke_viifff,
|
"Ra": invoke_viifff,
|
||||||
"ra": invoke_viifffiiii,
|
"Ua": invoke_viifffiiii,
|
||||||
"qa": invoke_viiffifi,
|
"Ta": invoke_viiffifi,
|
||||||
"Ya": invoke_viifii,
|
"Za": invoke_viifii,
|
||||||
"Fb": invoke_viifiifi,
|
"Kb": invoke_viifiifi,
|
||||||
"fa": invoke_viifiifii,
|
"ha": invoke_viifiifii,
|
||||||
"Y": invoke_viifiiiiiii,
|
"Z": invoke_viifiiiiiii,
|
||||||
"h": invoke_viii,
|
"h": invoke_viii,
|
||||||
"Q": invoke_viiid,
|
"L": invoke_viiid,
|
||||||
"w": invoke_viiidd,
|
"v": invoke_viiidd,
|
||||||
"A": invoke_viiiddi,
|
"C": invoke_viiiddi,
|
||||||
"z": invoke_viiidi,
|
"B": invoke_viiidi,
|
||||||
"Ua": invoke_viiiff,
|
"kb": invoke_viiidii,
|
||||||
"Va": invoke_viiifi,
|
"Sb": invoke_viiiff,
|
||||||
"pa": invoke_viiifii,
|
"Wa": invoke_viiifi,
|
||||||
|
"ta": invoke_viiifii,
|
||||||
"k": invoke_viiii,
|
"k": invoke_viiii,
|
||||||
"M": invoke_viiiid,
|
"N": invoke_viiiid,
|
||||||
"db": invoke_viiiidd,
|
"db": invoke_viiiidd,
|
||||||
"kb": invoke_viiiidi,
|
"ub": invoke_viiiiddi,
|
||||||
"ya": invoke_viiiidid,
|
"ob": invoke_viiiidf,
|
||||||
"Ba": invoke_viiiidiidiiiiiii,
|
"oa": invoke_viiiidi,
|
||||||
"ta": invoke_viiiif,
|
"za": invoke_viiiidid,
|
||||||
"Jb": invoke_viiiiffi,
|
"Ca": invoke_viiiidiidiiiiiii,
|
||||||
"Wa": invoke_viiiifi,
|
"va": invoke_viiiif,
|
||||||
"Ca": invoke_viiiifiifiiiiiii,
|
"Ob": invoke_viiiiffi,
|
||||||
"_a": invoke_viiiifiiifiii,
|
"Xa": invoke_viiiifi,
|
||||||
|
"Da": invoke_viiiifiifiiiiiii,
|
||||||
|
"$a": invoke_viiiifiiifiii,
|
||||||
"f": invoke_viiiii,
|
"f": invoke_viiiii,
|
||||||
"ja": invoke_viiiiid,
|
"ma": invoke_viiiiid,
|
||||||
"ea": invoke_viiiiifi,
|
"ba": invoke_viiiiidi,
|
||||||
|
"jb": invoke_viiiiidiii,
|
||||||
|
"ua": invoke_viiiiifi,
|
||||||
"q": invoke_viiiiii,
|
"q": invoke_viiiiii,
|
||||||
"Fa": invoke_viiiiiiddi,
|
"Ha": invoke_viiiiiiddi,
|
||||||
"ia": invoke_viiiiiidi,
|
"ka": invoke_viiiiiidi,
|
||||||
"hb": invoke_viiiiiidiii,
|
"la": invoke_viiiiiidiii,
|
||||||
"Ra": invoke_viiiiiif,
|
"Pb": invoke_viiiiiif,
|
||||||
"$a": invoke_viiiiiifiiiiiifiii,
|
"ab": invoke_viiiiiifiiiiiifiii,
|
||||||
"u": invoke_viiiiiii,
|
"t": invoke_viiiiiii,
|
||||||
"jb": invoke_viiiiiiiddi,
|
"mb": invoke_viiiiiiiddi,
|
||||||
"Za": invoke_viiiiiiifiiiifiii,
|
"_a": invoke_viiiiiiifiiiifiii,
|
||||||
"ua": invoke_viiiiiiifiiiiiifiii,
|
"wa": invoke_viiiiiiifiiiiiifiii,
|
||||||
"x": invoke_viiiiiiii,
|
"y": invoke_viiiiiiii,
|
||||||
"_": invoke_viiiiiiiidd,
|
"$": invoke_viiiiiiiidd,
|
||||||
"$": invoke_viiiiiiiidf,
|
"aa": invoke_viiiiiiiidf,
|
||||||
"Db": invoke_viiiiiiiif,
|
"Ib": invoke_viiiiiiiif,
|
||||||
"B": invoke_viiiiiiiii,
|
"D": invoke_viiiiiiiii,
|
||||||
"fb": invoke_viiiiiiiiidd,
|
"fb": invoke_viiiiiiiiidd,
|
||||||
"eb": invoke_viiiiiiiiiddi,
|
"eb": invoke_viiiiiiiiiddi,
|
||||||
"Sa": invoke_viiiiiiiiiffiii,
|
"Qb": invoke_viiiiiiiiiffiii,
|
||||||
"E": invoke_viiiiiiiiii,
|
"E": invoke_viiiiiiiiii,
|
||||||
"za": invoke_viiiiiiiiiiddi,
|
"Aa": invoke_viiiiiiiiiiddi,
|
||||||
"ga": invoke_viiiiiiiiiifii,
|
"ia": invoke_viiiiiiiiiifii,
|
||||||
"O": invoke_viiiiiiiiiii,
|
"P": invoke_viiiiiiiiiii,
|
||||||
"wa": invoke_viiiiiiiiiiiii,
|
"ja": invoke_viiiiiiiiiiiii,
|
||||||
"cb": invoke_viiiiiiiiiiiiii,
|
"cb": invoke_viiiiiiiiiiiiii,
|
||||||
"ba": invoke_viiiiiiiiiiiiiii,
|
"da": invoke_viiiiiiiiiiiiiii,
|
||||||
"Ta": invoke_viiiiiiiiiiiiiiii,
|
"Rb": invoke_viiiiiiiiiiiiiiii,
|
||||||
"gb": invoke_viiiiiiiiiiiiiiiiiiidi,
|
"hb": invoke_viiiiiiiiiiiiiiiiiiidi,
|
||||||
"P": _llvm_eh_typeid_for,
|
"ib": invoke_viiiiiiiiiiiiiiiiiiidii,
|
||||||
"aa": _setTempRet0,
|
"gb": invoke_viiiiiiiiiiiiiiiiiiiiiiiiiiii,
|
||||||
"yb": _strftime_l,
|
"Q": _llvm_eh_typeid_for,
|
||||||
"Na": _time
|
"ca": _setTempRet0,
|
||||||
|
"Db": _strftime_l,
|
||||||
|
"Pa": _time
|
||||||
};
|
};
|
||||||
|
|
||||||
var asm = createWasm();
|
var asm = createWasm();
|
||||||
|
|
||||||
var ___wasm_call_ctors = Module["___wasm_call_ctors"] = function() {
|
var ___wasm_call_ctors = Module["___wasm_call_ctors"] = function() {
|
||||||
return (___wasm_call_ctors = Module["___wasm_call_ctors"] = Module["asm"]["Lb"]).apply(null, arguments);
|
return (___wasm_call_ctors = Module["___wasm_call_ctors"] = Module["asm"]["Ub"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
var _qrtool_angle = Module["_qrtool_angle"] = function() {
|
var _qrtool_angle = Module["_qrtool_angle"] = function() {
|
||||||
return (_qrtool_angle = Module["_qrtool_angle"] = Module["asm"]["Mb"]).apply(null, arguments);
|
return (_qrtool_angle = Module["_qrtool_angle"] = Module["asm"]["Vb"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
var _malloc = Module["_malloc"] = function() {
|
var _malloc = Module["_malloc"] = function() {
|
||||||
return (_malloc = Module["_malloc"] = Module["asm"]["Ob"]).apply(null, arguments);
|
return (_malloc = Module["_malloc"] = Module["asm"]["Xb"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
var _free = Module["_free"] = function() {
|
var _free = Module["_free"] = function() {
|
||||||
return (_free = Module["_free"] = Module["asm"]["Pb"]).apply(null, arguments);
|
return (_free = Module["_free"] = Module["asm"]["Yb"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
var ___errno_location = Module["___errno_location"] = function() {
|
var ___errno_location = Module["___errno_location"] = function() {
|
||||||
return (___errno_location = Module["___errno_location"] = Module["asm"]["Qb"]).apply(null, arguments);
|
return (___errno_location = Module["___errno_location"] = Module["asm"]["Zb"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
var stackSave = Module["stackSave"] = function() {
|
var stackSave = Module["stackSave"] = function() {
|
||||||
return (stackSave = Module["stackSave"] = Module["asm"]["Rb"]).apply(null, arguments);
|
return (stackSave = Module["stackSave"] = Module["asm"]["_b"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
var stackRestore = Module["stackRestore"] = function() {
|
var stackRestore = Module["stackRestore"] = function() {
|
||||||
return (stackRestore = Module["stackRestore"] = Module["asm"]["Sb"]).apply(null, arguments);
|
return (stackRestore = Module["stackRestore"] = Module["asm"]["$b"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
var stackAlloc = Module["stackAlloc"] = function() {
|
var stackAlloc = Module["stackAlloc"] = function() {
|
||||||
return (stackAlloc = Module["stackAlloc"] = Module["asm"]["Tb"]).apply(null, arguments);
|
return (stackAlloc = Module["stackAlloc"] = Module["asm"]["ac"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
var _setThrew = Module["_setThrew"] = function() {
|
var _setThrew = Module["_setThrew"] = function() {
|
||||||
return (_setThrew = Module["_setThrew"] = Module["asm"]["Ub"]).apply(null, arguments);
|
return (_setThrew = Module["_setThrew"] = Module["asm"]["bc"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
var ___cxa_can_catch = Module["___cxa_can_catch"] = function() {
|
var ___cxa_can_catch = Module["___cxa_can_catch"] = function() {
|
||||||
return (___cxa_can_catch = Module["___cxa_can_catch"] = Module["asm"]["Vb"]).apply(null, arguments);
|
return (___cxa_can_catch = Module["___cxa_can_catch"] = Module["asm"]["cc"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
var ___cxa_is_pointer_type = Module["___cxa_is_pointer_type"] = function() {
|
var ___cxa_is_pointer_type = Module["___cxa_is_pointer_type"] = function() {
|
||||||
return (___cxa_is_pointer_type = Module["___cxa_is_pointer_type"] = Module["asm"]["Wb"]).apply(null, arguments);
|
return (___cxa_is_pointer_type = Module["___cxa_is_pointer_type"] = Module["asm"]["dc"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
var dynCall_j = Module["dynCall_j"] = function() {
|
var dynCall_j = Module["dynCall_j"] = function() {
|
||||||
return (dynCall_j = Module["dynCall_j"] = Module["asm"]["Xb"]).apply(null, arguments);
|
return (dynCall_j = Module["dynCall_j"] = Module["asm"]["ec"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
var dynCall_jiii = Module["dynCall_jiii"] = function() {
|
var dynCall_jiii = Module["dynCall_jiii"] = function() {
|
||||||
return (dynCall_jiii = Module["dynCall_jiii"] = Module["asm"]["Yb"]).apply(null, arguments);
|
return (dynCall_jiii = Module["dynCall_jiii"] = Module["asm"]["fc"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
var dynCall_jii = Module["dynCall_jii"] = function() {
|
var dynCall_jii = Module["dynCall_jii"] = function() {
|
||||||
return (dynCall_jii = Module["dynCall_jii"] = Module["asm"]["Zb"]).apply(null, arguments);
|
return (dynCall_jii = Module["dynCall_jii"] = Module["asm"]["gc"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
var dynCall_jiiii = Module["dynCall_jiiii"] = function() {
|
var dynCall_jiiii = Module["dynCall_jiiii"] = function() {
|
||||||
return (dynCall_jiiii = Module["dynCall_jiiii"] = Module["asm"]["_b"]).apply(null, arguments);
|
return (dynCall_jiiii = Module["dynCall_jiiii"] = Module["asm"]["hc"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
var dynCall_iiiiij = Module["dynCall_iiiiij"] = function() {
|
var dynCall_iiiiij = Module["dynCall_iiiiij"] = function() {
|
||||||
return (dynCall_iiiiij = Module["dynCall_iiiiij"] = Module["asm"]["$b"]).apply(null, arguments);
|
return (dynCall_iiiiij = Module["dynCall_iiiiij"] = Module["asm"]["ic"]).apply(null, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
function invoke_iiiiii(index, a1, a2, a3, a4, a5) {
|
function invoke_iiiiii(index, a1, a2, a3, a4, a5) {
|
||||||
@ -4212,6 +4221,28 @@ function invoke_vii(index, a1, a2) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function invoke_viiiiddi(index, a1, a2, a3, a4, a5, a6, a7) {
|
||||||
|
var sp = stackSave();
|
||||||
|
try {
|
||||||
|
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6, a7);
|
||||||
|
} catch (e) {
|
||||||
|
stackRestore(sp);
|
||||||
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
_setThrew(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function invoke_viidd(index, a1, a2, a3, a4) {
|
||||||
|
var sp = stackSave();
|
||||||
|
try {
|
||||||
|
getWasmTableEntry(index)(a1, a2, a3, a4);
|
||||||
|
} catch (e) {
|
||||||
|
stackRestore(sp);
|
||||||
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
_setThrew(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function invoke_i(index) {
|
function invoke_i(index) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
@ -4234,6 +4265,50 @@ function invoke_iifii(index, a1, a2, a3, a4) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function invoke_dii(index, a1, a2) {
|
||||||
|
var sp = stackSave();
|
||||||
|
try {
|
||||||
|
return getWasmTableEntry(index)(a1, a2);
|
||||||
|
} catch (e) {
|
||||||
|
stackRestore(sp);
|
||||||
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
_setThrew(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function invoke_viiiidf(index, a1, a2, a3, a4, a5, a6) {
|
||||||
|
var sp = stackSave();
|
||||||
|
try {
|
||||||
|
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6);
|
||||||
|
} catch (e) {
|
||||||
|
stackRestore(sp);
|
||||||
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
_setThrew(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function invoke_iiiiiii(index, a1, a2, a3, a4, a5, a6) {
|
||||||
|
var sp = stackSave();
|
||||||
|
try {
|
||||||
|
return getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6);
|
||||||
|
} catch (e) {
|
||||||
|
stackRestore(sp);
|
||||||
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
_setThrew(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function invoke_vid(index, a1, a2) {
|
||||||
|
var sp = stackSave();
|
||||||
|
try {
|
||||||
|
getWasmTableEntry(index)(a1, a2);
|
||||||
|
} catch (e) {
|
||||||
|
stackRestore(sp);
|
||||||
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
_setThrew(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function invoke_viiiiiiddi(index, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
|
function invoke_viiiiiiddi(index, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
@ -4267,6 +4342,17 @@ function invoke_viidf(index, a1, a2, a3, a4) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function invoke_viidiiid(index, a1, a2, a3, a4, a5, a6, a7) {
|
||||||
|
var sp = stackSave();
|
||||||
|
try {
|
||||||
|
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6, a7);
|
||||||
|
} catch (e) {
|
||||||
|
stackRestore(sp);
|
||||||
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
_setThrew(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function invoke_v(index) {
|
function invoke_v(index) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
@ -4289,10 +4375,10 @@ function invoke_viiiii(index, a1, a2, a3, a4, a5) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function invoke_iiiiiii(index, a1, a2, a3, a4, a5, a6) {
|
function invoke_viiiiidi(index, a1, a2, a3, a4, a5, a6, a7) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
return getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6);
|
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6, a7);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
stackRestore(sp);
|
stackRestore(sp);
|
||||||
if (e !== e + 0 && e !== "longjmp") throw e;
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
@ -4300,10 +4386,21 @@ function invoke_iiiiiii(index, a1, a2, a3, a4, a5, a6) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function invoke_viiiiii(index, a1, a2, a3, a4, a5, a6) {
|
function invoke_viiidi(index, a1, a2, a3, a4, a5) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6);
|
getWasmTableEntry(index)(a1, a2, a3, a4, a5);
|
||||||
|
} catch (e) {
|
||||||
|
stackRestore(sp);
|
||||||
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
_setThrew(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function invoke_viiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
|
||||||
|
var sp = stackSave();
|
||||||
|
try {
|
||||||
|
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6, a7, a8, a9);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
stackRestore(sp);
|
stackRestore(sp);
|
||||||
if (e !== e + 0 && e !== "longjmp") throw e;
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
@ -4322,6 +4419,17 @@ function invoke_viiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function invoke_viiiiii(index, a1, a2, a3, a4, a5, a6) {
|
||||||
|
var sp = stackSave();
|
||||||
|
try {
|
||||||
|
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6);
|
||||||
|
} catch (e) {
|
||||||
|
stackRestore(sp);
|
||||||
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
_setThrew(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function invoke_iif(index, a1, a2) {
|
function invoke_iif(index, a1, a2) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
@ -4344,17 +4452,6 @@ function invoke_iid(index, a1, a2) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function invoke_viiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
|
|
||||||
var sp = stackSave();
|
|
||||||
try {
|
|
||||||
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6, a7, a8, a9);
|
|
||||||
} catch (e) {
|
|
||||||
stackRestore(sp);
|
|
||||||
if (e !== e + 0 && e !== "longjmp") throw e;
|
|
||||||
_setThrew(1, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function invoke_iiiidd(index, a1, a2, a3, a4, a5) {
|
function invoke_iiiidd(index, a1, a2, a3, a4, a5) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
@ -4465,17 +4562,6 @@ function invoke_viiiidi(index, a1, a2, a3, a4, a5, a6) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function invoke_dii(index, a1, a2) {
|
|
||||||
var sp = stackSave();
|
|
||||||
try {
|
|
||||||
return getWasmTableEntry(index)(a1, a2);
|
|
||||||
} catch (e) {
|
|
||||||
stackRestore(sp);
|
|
||||||
if (e !== e + 0 && e !== "longjmp") throw e;
|
|
||||||
_setThrew(1, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function invoke_vidii(index, a1, a2, a3, a4) {
|
function invoke_vidii(index, a1, a2, a3, a4) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
@ -4509,17 +4595,6 @@ function invoke_viiiiiiiddi(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function invoke_viiidi(index, a1, a2, a3, a4, a5) {
|
|
||||||
var sp = stackSave();
|
|
||||||
try {
|
|
||||||
getWasmTableEntry(index)(a1, a2, a3, a4, a5);
|
|
||||||
} catch (e) {
|
|
||||||
stackRestore(sp);
|
|
||||||
if (e !== e + 0 && e !== "longjmp") throw e;
|
|
||||||
_setThrew(1, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function invoke_viiiid(index, a1, a2, a3, a4, a5) {
|
function invoke_viiiid(index, a1, a2, a3, a4, a5) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
@ -4685,6 +4760,17 @@ function invoke_iiiidii(index, a1, a2, a3, a4, a5, a6) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function invoke_viiidii(index, a1, a2, a3, a4, a5, a6) {
|
||||||
|
var sp = stackSave();
|
||||||
|
try {
|
||||||
|
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6);
|
||||||
|
} catch (e) {
|
||||||
|
stackRestore(sp);
|
||||||
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
_setThrew(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function invoke_iiiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
|
function invoke_iiiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
@ -4696,6 +4782,28 @@ function invoke_iiiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function invoke_viiiiidiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
|
||||||
|
var sp = stackSave();
|
||||||
|
try {
|
||||||
|
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6, a7, a8, a9);
|
||||||
|
} catch (e) {
|
||||||
|
stackRestore(sp);
|
||||||
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
_setThrew(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function invoke_viiiiiiiiiiiiiiiiiiidii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22) {
|
||||||
|
var sp = stackSave();
|
||||||
|
try {
|
||||||
|
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22);
|
||||||
|
} catch (e) {
|
||||||
|
stackRestore(sp);
|
||||||
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
_setThrew(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function invoke_viiiiiiiiiiiiiiiiiiidi(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21) {
|
function invoke_viiiiiiiiiiiiiiiiiiidi(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
@ -4718,6 +4826,17 @@ function invoke_viiiiiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function invoke_viiiiiiiiiiiiiiiiiiiiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28) {
|
||||||
|
var sp = stackSave();
|
||||||
|
try {
|
||||||
|
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28);
|
||||||
|
} catch (e) {
|
||||||
|
stackRestore(sp);
|
||||||
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
_setThrew(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function invoke_viiiiiiiiidd(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) {
|
function invoke_viiiiiiiiidd(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
@ -4773,17 +4892,6 @@ function invoke_viiiiiiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function invoke_viidiiid(index, a1, a2, a3, a4, a5, a6, a7) {
|
|
||||||
var sp = stackSave();
|
|
||||||
try {
|
|
||||||
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6, a7);
|
|
||||||
} catch (e) {
|
|
||||||
stackRestore(sp);
|
|
||||||
if (e !== e + 0 && e !== "longjmp") throw e;
|
|
||||||
_setThrew(1, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function invoke_fii(index, a1, a2) {
|
function invoke_fii(index, a1, a2) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
|
|||||||
2
web/public/camera-5.0/Makefile
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
deploy:
|
||||||
|
rsync -zrP * oci:/data/emblem-camera/
|
||||||
2
web/public/camera-5.0/camera-4.0/Makefile
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
deploy:
|
||||||
|
rsync -zrP * oci:/data/emblem-camera/
|
||||||
85
web/public/camera-5.0/camera-4.0/css/loading.css
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
.lds-roller {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
.lds-roller div {
|
||||||
|
animation: lds-roller 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
||||||
|
transform-origin: 40px 40px;
|
||||||
|
}
|
||||||
|
.lds-roller div:after {
|
||||||
|
content: " ";
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #666;
|
||||||
|
margin: -4px 0 0 -4px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(1) {
|
||||||
|
animation-delay: -0.036s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(1):after {
|
||||||
|
top: 63px;
|
||||||
|
left: 63px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(2) {
|
||||||
|
animation-delay: -0.072s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(2):after {
|
||||||
|
top: 68px;
|
||||||
|
left: 56px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(3) {
|
||||||
|
animation-delay: -0.108s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(3):after {
|
||||||
|
top: 71px;
|
||||||
|
left: 48px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(4) {
|
||||||
|
animation-delay: -0.144s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(4):after {
|
||||||
|
top: 72px;
|
||||||
|
left: 40px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(5) {
|
||||||
|
animation-delay: -0.18s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(5):after {
|
||||||
|
top: 71px;
|
||||||
|
left: 32px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(6) {
|
||||||
|
animation-delay: -0.216s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(6):after {
|
||||||
|
top: 68px;
|
||||||
|
left: 24px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(7) {
|
||||||
|
animation-delay: -0.252s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(7):after {
|
||||||
|
top: 63px;
|
||||||
|
left: 17px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(8) {
|
||||||
|
animation-delay: -0.288s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(8):after {
|
||||||
|
top: 56px;
|
||||||
|
left: 12px;
|
||||||
|
}
|
||||||
|
@keyframes lds-roller {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
464
web/public/camera-5.0/camera-4.0/css/main.css
Normal file
@ -0,0 +1,464 @@
|
|||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family:Tahoma,Verdana,STHeiTi,simsun,sans-serif;
|
||||||
|
}
|
||||||
|
div.debug {
|
||||||
|
position: absolute;
|
||||||
|
left: 5px;
|
||||||
|
bottom: 5px;
|
||||||
|
width: 80%;
|
||||||
|
height: 50%;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 2px dashed rgba(50, 255, 50, 0.5);
|
||||||
|
background-color: rgba(0, 50, 0, 0.7);
|
||||||
|
padding: 1rem;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 12px;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
.hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
video.preview {
|
||||||
|
object-fit: cover;
|
||||||
|
position: fixed;
|
||||||
|
top: -1%;
|
||||||
|
left: -1%;
|
||||||
|
width: 102%;
|
||||||
|
height: 102%;
|
||||||
|
z-index: -1000;
|
||||||
|
border: 1px solid yellow;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
div.debug canvas {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
div.bottomfixed {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
bottom: 0;
|
||||||
|
height: 90px;
|
||||||
|
background-color: #171616;
|
||||||
|
text-align: center;
|
||||||
|
border-top: 1px solid #ef4823;
|
||||||
|
}
|
||||||
|
|
||||||
|
.play.button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.1rem 1.2rem 0.1rem 1.4rem;
|
||||||
|
margin-right: 0.2rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
background-color: #707070;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.bottomfixed .action.highlight .play.button {
|
||||||
|
background-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.bottomfixed .action img {
|
||||||
|
height: 14px;
|
||||||
|
width: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.bottomfixed .action {
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #707070;
|
||||||
|
width: 49%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.bottomfixed .action.highlight {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.camoverlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
clear: both;
|
||||||
|
font-size: 0;
|
||||||
|
width: 100%;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
top: 18vw;
|
||||||
|
}
|
||||||
|
div.camoverlay img.qrmarkers {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.lower.text {
|
||||||
|
top: 4%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.progress {
|
||||||
|
width: 70%;
|
||||||
|
margin: 0.2rem 0 0 0;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #eee;
|
||||||
|
font-size: 18px;
|
||||||
|
color: black;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
div.progress-text {
|
||||||
|
color: #333;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
div.progress-bar {
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #ef4823;
|
||||||
|
width: 0%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
div.upper.overlay {
|
||||||
|
position: relative;
|
||||||
|
height: 100vmin;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.lower.overlay {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
div.debug .buttons {
|
||||||
|
margin: 0 0 0.3rem 0;
|
||||||
|
}
|
||||||
|
div.debug .buttons button {
|
||||||
|
height: 2rem;
|
||||||
|
margin: 0 5px 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#loading {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
background-color: white;
|
||||||
|
z-index: 10000;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas#output_img {
|
||||||
|
position: absolute;
|
||||||
|
right: 5px;
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.bordered {
|
||||||
|
padding: 0.2rem;
|
||||||
|
border: 1px dashed yellow;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 0.2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.output {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip {
|
||||||
|
position: absolute;
|
||||||
|
width: 100vmin;
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
animation: bounce 1s ease-in-out infinite; /* Adjust the duration as needed */
|
||||||
|
top: -60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip .tooltiptext {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 110px;
|
||||||
|
background-color: #ef4823;
|
||||||
|
color: #fff;
|
||||||
|
padding: 12px 0;
|
||||||
|
border-radius: 10px;
|
||||||
|
z-index: 1;
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip:hover .tooltiptext {
|
||||||
|
}
|
||||||
|
.tooltip .tooltiptext::after {
|
||||||
|
content: " ";
|
||||||
|
position: absolute;
|
||||||
|
top: 100%; /* At the bottom of the tooltip */
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -5px;
|
||||||
|
border-width: 5px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: #ef4823 transparent transparent transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bounce {
|
||||||
|
0%, 100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(10px); /* Adjust the bounce height as needed */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: fixed;
|
||||||
|
background-color: rgba(0, 0, 0, 0.9);
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .panel {
|
||||||
|
position: relative;
|
||||||
|
width: 80vmin;
|
||||||
|
height: 80%;
|
||||||
|
margin: 10vmin auto;
|
||||||
|
background-image: linear-gradient(0deg, #8b8986 0%, #414141 36%, #414141 92%, #515151 100%);
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .actions {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
bottom: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions button {
|
||||||
|
display: inline-block;
|
||||||
|
width: 35%;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 0.4rem 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.service {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
border: 1px solid #676767;
|
||||||
|
background-color: #858585;
|
||||||
|
color: #a7a7a7;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.back {
|
||||||
|
border: 1px solid rgba(239, 72, 35, 0.7);
|
||||||
|
color: rgba(239, 72, 35, 0.7);
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.back img.return {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.serviceqr {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
padding-top: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.serviceqr .imgbox {
|
||||||
|
display: block;
|
||||||
|
margin: auto;
|
||||||
|
width: 60vmin;
|
||||||
|
height: 60vmin;
|
||||||
|
padding: 3vmin;
|
||||||
|
background-color: #eee;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.serviceqr .title {
|
||||||
|
position: absolute;
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
color: #eee;
|
||||||
|
margin: 30px auto;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.serviceqr img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyfailed {
|
||||||
|
text-align: center;
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyfailed .title {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyfailed .hints {
|
||||||
|
margin-top: 80px;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyfailed .hints div {
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyfailed .circle {
|
||||||
|
height: 20vmin;
|
||||||
|
width: 20vmin;
|
||||||
|
color: #666;
|
||||||
|
font-size: 15vmin;
|
||||||
|
margin: 10vmin auto 1rem;;
|
||||||
|
background-color: #ddd;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyspin {
|
||||||
|
position: absolute;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 101;
|
||||||
|
width: 100vmin;
|
||||||
|
height: 100vmax;
|
||||||
|
background-color: rgba(0, 0, 0, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyspin .spinner {
|
||||||
|
position: absolute; /* Position the image absolutely */
|
||||||
|
width: 100vmin;
|
||||||
|
height: 100vmin;
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: center;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyspin img {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-and-shrink {
|
||||||
|
animation: spin-and-shrink 3s linear forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin-and-shrink {
|
||||||
|
0% {
|
||||||
|
transform: rotate(-90deg) scale(5.5)
|
||||||
|
}
|
||||||
|
10% {
|
||||||
|
transform: rotate(0deg) scale(2.0)
|
||||||
|
}
|
||||||
|
33% {
|
||||||
|
transform: rotate(90deg) scale(1.0);
|
||||||
|
}
|
||||||
|
66% {
|
||||||
|
transform: rotate(2000deg) scale(0.5);
|
||||||
|
}
|
||||||
|
99% {
|
||||||
|
transform: rotate(3600deg) scale(0.2);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(3600deg) scale(0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-only {
|
||||||
|
animation: spin-only 0.3s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin-only {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg) scale(0.2);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg) scale(0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyspin .loading {
|
||||||
|
color: #ccc;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
margin: 110vmin auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.scanguide {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#hint {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 10px auto;
|
||||||
|
padding: 12px 40px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
|
color: #eee;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.qrarc {
|
||||||
|
position: absolute;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 76vw;
|
||||||
|
height: 76vw;
|
||||||
|
margin: 20vw 12vw;
|
||||||
|
animation: qrarc-anime 1.2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.qrarc img.arc {
|
||||||
|
position: absolute;
|
||||||
|
width: 15%;
|
||||||
|
height: 15%;
|
||||||
|
opacity: 0.9;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.qrarc img.arc.topright {
|
||||||
|
right: 0;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
div.qrarc img.arc.bottomleft {
|
||||||
|
bottom: 0;
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
div.qrarc img.arc.bottomright {
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@keyframes qrarc-anime {
|
||||||
|
0% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
web/public/camera-5.0/camera-4.0/images/arc.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
web/public/camera-5.0/camera-4.0/images/black.png
Normal file
|
After Width: | Height: | Size: 637 B |
BIN
web/public/camera-5.0/camera-4.0/images/camoverlay.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
web/public/camera-5.0/camera-4.0/images/flash-button.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
web/public/camera-5.0/camera-4.0/images/play-button.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
web/public/camera-5.0/camera-4.0/images/qrmarkers.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
web/public/camera-5.0/camera-4.0/images/return.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
web/public/camera-5.0/camera-4.0/images/right-arrow.png
Normal file
|
After Width: | Height: | Size: 389 B |
BIN
web/public/camera-5.0/camera-4.0/images/spinner.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
139
web/public/camera-5.0/camera-4.0/index.html
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="description" content="WebRTC code samples">
|
||||||
|
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1, maximum-scale=1">
|
||||||
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
|
<base target="_blank">
|
||||||
|
<title>AI验真</title>
|
||||||
|
<link rel="stylesheet" href="css/main.css">
|
||||||
|
<link rel="stylesheet" href="css/loading.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="loading" id="loading">
|
||||||
|
<div>
|
||||||
|
<div class="lds-roller"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
AI摄像头加载中...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="container">
|
||||||
|
<div>
|
||||||
|
<div class="camoverlay">
|
||||||
|
<div class="upper overlay">
|
||||||
|
<div>
|
||||||
|
<div class="qrarc">
|
||||||
|
<img class="topleft arc" src="images/arc.png" />
|
||||||
|
<img class="topright arc" src="images/arc.png" />
|
||||||
|
<img class="bottomleft arc" src="images/arc.png" />
|
||||||
|
<img class="bottomright arc" src="images/arc.png" />
|
||||||
|
</div>
|
||||||
|
<img class="qrmarkers" src="images/qrmarkers.png" alt=""/>
|
||||||
|
</div>
|
||||||
|
<div class="hint wrapper">
|
||||||
|
<div id="hint" class="upper text" onclick="debug_countdown()">
|
||||||
|
对齐定位点
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<video class="preview" id="video" autoplay muted playsinline></video>
|
||||||
|
</div>
|
||||||
|
<div class="bottomfixed">
|
||||||
|
<div class="play action" onclick="show_modal('scanguide')">
|
||||||
|
<img
|
||||||
|
class="play"
|
||||||
|
src="images/play-button.png"
|
||||||
|
/>
|
||||||
|
验证演示
|
||||||
|
</div>
|
||||||
|
<div class="torch action" onclick="toggle_torch()">
|
||||||
|
<img
|
||||||
|
class="torch"
|
||||||
|
src="images/flash-button.png"
|
||||||
|
/>
|
||||||
|
开启补光
|
||||||
|
</div>
|
||||||
|
<div class="hidden tooltip"><span class="tooltiptext">遇到困难?</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="hidden debug" id="debug_div">
|
||||||
|
<div class="buttons">
|
||||||
|
<button onclick="location.reload()">reload</button>
|
||||||
|
<button onclick="set_zoom(4)">4x zoom</button>
|
||||||
|
<button onclick="set_zoom(2)">2x zoom</button>
|
||||||
|
<button onclick="wx_submit('debug')">WX OK</button>
|
||||||
|
<button onclick="torch_onoff()">Torch</button>
|
||||||
|
<button onclick="hide_debug()">Hide</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<canvas class="hidden" id="original" width="2000" height="2000">
|
||||||
|
</canvas>
|
||||||
|
<canvas class="hidden" id="grayscale" width="2000" height="2000">
|
||||||
|
</canvas>
|
||||||
|
</div>
|
||||||
|
<div id="logs" class="bordered">
|
||||||
|
</div>
|
||||||
|
<div class="bordered">
|
||||||
|
Caps: <span id="caps"></span>
|
||||||
|
</div>
|
||||||
|
<div class="bordered">
|
||||||
|
Constraints: <span id="cons"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal hidden">
|
||||||
|
<div class="panel">
|
||||||
|
<div class="scanguide hidden">
|
||||||
|
<div id="scanguide">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="serviceqr hidden">
|
||||||
|
<div class="imgbox">
|
||||||
|
<img id="service_img" src="https://emblem-resources.oss-accelerate.aliyuncs.com/service-qr2.png" alt=""/>
|
||||||
|
</div>
|
||||||
|
<div class="title">
|
||||||
|
长按识别二维码,添加人工客服
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="verifyfailed hidden">
|
||||||
|
<div class="circle">
|
||||||
|
!
|
||||||
|
</div>
|
||||||
|
<div class="title">验证未通过</div>
|
||||||
|
<div class="hints">
|
||||||
|
<div>
|
||||||
|
请按照验证指引
|
||||||
|
</div>
|
||||||
|
<div>重新验证</div>
|
||||||
|
<div>
|
||||||
|
-
|
||||||
|
</div>
|
||||||
|
<div>如反复验证仍无法通过</div>
|
||||||
|
<div>请联系人工客服</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="actions">
|
||||||
|
<button onclick="show_modal('serviceqr')" class="service">人工客服</button>
|
||||||
|
<button onclick="hide_modal()" class="back">
|
||||||
|
<img class="return" src="images/return.png" alt=""/>
|
||||||
|
采集</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="verifyspin hidden">
|
||||||
|
<div class="spinner">
|
||||||
|
<img src="images/spinner.png" class="spin-image spin-and-shrink">
|
||||||
|
</div>
|
||||||
|
<div class="loading">
|
||||||
|
Loading
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
|
||||||
|
<script type="text/javascript" src="js/lottie.min.js"></script>
|
||||||
|
<script type="text/javascript" src="js/main.js"></script>
|
||||||
|
<script type="text/javascript" src="js/qrtool.web.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
web/public/camera-5.0/camera-4.0/js/lottie.min.js
vendored
Normal file
409
web/public/camera-5.0/camera-4.0/js/main.js
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
var debug_taps = 0;
|
||||||
|
var debug_logs = [];
|
||||||
|
var track;
|
||||||
|
var frame_width;
|
||||||
|
var frame_height;
|
||||||
|
var scanguide_anime;
|
||||||
|
var busy = false;
|
||||||
|
const max_inflight = 5;
|
||||||
|
var should_check_auto_torch = true;
|
||||||
|
var done_checking_auto_torch = false;
|
||||||
|
var camera_sensitivity = 1.0;
|
||||||
|
var camera_capabilities = null;
|
||||||
|
|
||||||
|
var Module = {
|
||||||
|
onRuntimeInitialized: start,
|
||||||
|
};
|
||||||
|
|
||||||
|
function get_query(key) {
|
||||||
|
const qs = window.location.search;
|
||||||
|
const params = new URLSearchParams(qs);
|
||||||
|
return params.get(key) || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_debug() {
|
||||||
|
const debug_div = document.getElementById("debug_div");
|
||||||
|
debug_div.classList.remove("hidden");
|
||||||
|
}
|
||||||
|
function hide_debug() {
|
||||||
|
const debug_div = document.getElementById("debug_div");
|
||||||
|
debug_div.classList.add("hidden");
|
||||||
|
}
|
||||||
|
function debug_countdown() {
|
||||||
|
debug_taps += 1;
|
||||||
|
if (debug_taps > 10) {
|
||||||
|
show_debug();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide_loading() {
|
||||||
|
const loading = document.getElementById("loading");
|
||||||
|
loading.classList.add("hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_stream(stream) {
|
||||||
|
const video = document.querySelector('video');
|
||||||
|
const videoTracks = stream.getVideoTracks();
|
||||||
|
debug_log(`total video tracks: ${videoTracks.length} Using video device: ${videoTracks[0].label}`);
|
||||||
|
window.stream = stream; // make variable available to browser console
|
||||||
|
video.srcObject = stream;
|
||||||
|
video.play();
|
||||||
|
track = videoTracks[0];
|
||||||
|
camera_capabilities = track.getCapabilities();
|
||||||
|
const caps = document.getElementById("caps");
|
||||||
|
caps.innerHTML = JSON.stringify(camera_capabilities);
|
||||||
|
const settings = track.getSettings();
|
||||||
|
console.log(settings);
|
||||||
|
const canvas = document.getElementById("original");
|
||||||
|
frame_width = settings.width;
|
||||||
|
frame_height = settings.height;
|
||||||
|
video.width = frame_width;
|
||||||
|
video.height = frame_height;
|
||||||
|
canvas.width = frame_width;
|
||||||
|
canvas.height = frame_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleError(error) {
|
||||||
|
debug_log(error);
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
function debug_log(msg) {
|
||||||
|
debug_logs.push(Date.now() / 1000 + ": " + msg);
|
||||||
|
const nentries = 20;
|
||||||
|
while (debug_logs.length > nentries) {
|
||||||
|
debug_logs.shift();
|
||||||
|
}
|
||||||
|
var output = "";
|
||||||
|
for (var l of debug_logs) {
|
||||||
|
output = `<div>${l}</div>` + output;
|
||||||
|
}
|
||||||
|
console.log(msg);
|
||||||
|
const di = document.getElementById("logs");
|
||||||
|
di.innerHTML = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function start_camera(e) {
|
||||||
|
try {
|
||||||
|
const constraints = window.constraints = {
|
||||||
|
audio: false,
|
||||||
|
video: {
|
||||||
|
facingMode: "environment",
|
||||||
|
focusDistance: 0.12,
|
||||||
|
focusMode: "manual",
|
||||||
|
width: { ideal: 2000 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const supportedConstraints = navigator.mediaDevices.getSupportedConstraints();
|
||||||
|
const cons = document.getElementById("cons");
|
||||||
|
cons.innerHTML = JSON.stringify(supportedConstraints);
|
||||||
|
debug_log(navigator.userAgent);
|
||||||
|
|
||||||
|
const stream = await navigator.mediaDevices.getUserMedia(constraints);
|
||||||
|
handle_stream(stream);
|
||||||
|
const zoom = get_query("zoom");
|
||||||
|
if (zoom) {
|
||||||
|
set_zoom(zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
handleError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_emblem_qr_pattern(p)
|
||||||
|
{
|
||||||
|
if (p.search(/code=[0-9a-zA-Z]+/) >= 0) return true;
|
||||||
|
if (p.search(/c=[0-9a-zA-Z]+/) >= 0) return true;
|
||||||
|
if (p.search(/https:\/\/xy.ltd\/v\/[0-9a-zA-Z]+/) >= 0) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_hint_text(r) {
|
||||||
|
var qr_is_valid = false;
|
||||||
|
if (r.qrcode && r.qrcode.length > 0) {
|
||||||
|
qr_is_valid = is_emblem_qr_pattern(r.qrcode);
|
||||||
|
if (!qr_is_valid) {
|
||||||
|
return "无效编码";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (qr_is_valid) {
|
||||||
|
var err = r.err || "";
|
||||||
|
if (err.includes("margin too small")) {
|
||||||
|
return "对齐定位点";
|
||||||
|
} else if (err.includes("energy check failed") || err.includes("cannot detect angle")) {
|
||||||
|
return "移近一点";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "对齐定位点";
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_frame() {
|
||||||
|
try {
|
||||||
|
do_handle_frame();
|
||||||
|
} catch (e) {
|
||||||
|
debug_log("handle frame exception: " + e);
|
||||||
|
}
|
||||||
|
setTimeout(handle_frame, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
function do_handle_frame() {
|
||||||
|
if (busy) return;
|
||||||
|
const canvas = document.getElementById("original");
|
||||||
|
const video = document.getElementById("video");
|
||||||
|
|
||||||
|
canvas.width = video.width;
|
||||||
|
canvas.height = video.height;
|
||||||
|
|
||||||
|
canvas.style.width = video.width / 4 + "px";
|
||||||
|
canvas.style.height = video.height / 4 + "px";
|
||||||
|
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
ctx.drawImage(video, 0, 0);
|
||||||
|
const id = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||||
|
console.log(Module);
|
||||||
|
var buf = Module._malloc(id.data.length * id.data.BYTES_PER_ELEMENT);
|
||||||
|
Module.HEAPU8.set(id.data, buf);
|
||||||
|
var r = Module.ccall('qrtool_angle', 'string', ['number', 'number', 'number', 'number', 'number'], [buf, id.width, id.height, 0, camera_sensitivity]);
|
||||||
|
Module._free(buf);
|
||||||
|
debug_log(r);
|
||||||
|
const res = JSON.parse(r);
|
||||||
|
const is_valid_pattern = res.qrcode && res.qrcode.length && is_emblem_qr_pattern(res.qrcode);
|
||||||
|
if (res.qrcode && should_check_auto_torch) {
|
||||||
|
start_check_auto_torch(res.qrcode);
|
||||||
|
}
|
||||||
|
if (done_checking_auto_torch && is_valid_pattern && res.ok) {
|
||||||
|
var data_url = canvas.toDataURL("image/jpeg", 1.0);
|
||||||
|
submit_image(res.qrcode, res.angle, data_url);
|
||||||
|
} else {
|
||||||
|
pending_hint = make_hint_text(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function start_check_auto_torch(qrcode)
|
||||||
|
{
|
||||||
|
should_check_auto_torch = false;
|
||||||
|
var r = await fetch("https://themblem.com/api/v1/check-auto-torch/?qrcode=" + encodeURIComponent(qrcode), {
|
||||||
|
method: "GET",
|
||||||
|
});
|
||||||
|
var d = await r.json();
|
||||||
|
debug_log(JSON.stringify(d));
|
||||||
|
if (d.enable_auto_torch && !torch) {
|
||||||
|
toggle_torch();
|
||||||
|
}
|
||||||
|
camera_sensitivity = d.camera_sensitivity || 1.0;
|
||||||
|
setTimeout(() => {
|
||||||
|
done_checking_auto_torch = true;
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_zoom(zoom) {
|
||||||
|
if (camera_capabilities.zoom) {
|
||||||
|
debug_log("set zoom by applying constraints");
|
||||||
|
track.applyConstraints({advanced: [ {zoom} ]});
|
||||||
|
} else {
|
||||||
|
debug_log("set zoom by scaling video element");
|
||||||
|
add_style_by_query("video.preview", "transform", `scale(${zoom})`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let torch = false;
|
||||||
|
function toggle_torch() {
|
||||||
|
torch = !torch;
|
||||||
|
track.applyConstraints({advanced: [ {torch: torch} ]});
|
||||||
|
if (torch) {
|
||||||
|
add_class_by_query(".bottomfixed .torch.action", "highlight");
|
||||||
|
} else {
|
||||||
|
remove_class_by_query(".bottomfixed .torch.action", "highlight");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_spinner() {
|
||||||
|
remove_class_by_query('.verifyspin', 'hidden');
|
||||||
|
remove_class_by_query('.spin-image', 'spin-only');
|
||||||
|
remove_class_by_query('.spin-image', 'spin-and-shrink');
|
||||||
|
setTimeout(() => {
|
||||||
|
add_class_by_query('.spin-image', 'spin-and-shrink');
|
||||||
|
setTimeout(() => {
|
||||||
|
remove_class_by_query('.spin-image', 'spin-and-shrink');
|
||||||
|
add_class_by_query('.spin-image', 'spin-only');
|
||||||
|
}, 3000);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide_spinner() {
|
||||||
|
add_class_by_query('.verifyspin', 'hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submit_image(qrcode, angle, image_data_url) {
|
||||||
|
busy = true;
|
||||||
|
var begin = Date.now();
|
||||||
|
show_spinner();
|
||||||
|
debug_log(`submit: qrcode: ${qrcode} angle: ${angle}`);
|
||||||
|
try {
|
||||||
|
// TODO: pass these parameters from query string
|
||||||
|
var emblem_id = get_query("emblem_id");
|
||||||
|
var nick_name = get_query("nick_name");
|
||||||
|
var realip = get_query("realip");
|
||||||
|
var phonemodel = get_query("phonemodel");
|
||||||
|
var skip_angle_check = get_query("skip_angle_check");
|
||||||
|
var data = {
|
||||||
|
emblem_id,
|
||||||
|
nick_name,
|
||||||
|
realip,
|
||||||
|
qrcode,
|
||||||
|
angle,
|
||||||
|
phonemodel,
|
||||||
|
image_data_url,
|
||||||
|
skip_angle_check,
|
||||||
|
log: debug_logs.join("\n"),
|
||||||
|
};
|
||||||
|
var r = await fetch("https://themblem.com/api/v1/qr-verify/", {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
});
|
||||||
|
var d = await r.json();
|
||||||
|
debug_log(JSON.stringify(d));
|
||||||
|
if (d.serial_code) {
|
||||||
|
if (wx) {
|
||||||
|
var delay = 3000 - (Date.now() - begin);
|
||||||
|
setTimeout(() => {
|
||||||
|
if (get_query("ai_chat_mode")) {
|
||||||
|
wx.miniProgram.redirectTo({
|
||||||
|
url: '/pages/chat/chat?serial_code=' + d.serial_code,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
wx.miniProgram.redirectTo({
|
||||||
|
url: '/pages/productinfo/productinfo?serial_code=' + d.serial_code,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, delay > 0 ? delay : 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.show_modal('verifyfailed');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debug_log(`submission error: ${e}`);
|
||||||
|
this.show_modal('verifyfailed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var pending_hint = null;
|
||||||
|
|
||||||
|
function update_hint() {
|
||||||
|
var now = Date.now();
|
||||||
|
if (pending_hint) {
|
||||||
|
const hint_dev = document.getElementById("hint");
|
||||||
|
hint_dev.innerHTML = pending_hint;
|
||||||
|
pending_hint = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
console.log("start");
|
||||||
|
setTimeout(handle_frame, 100);
|
||||||
|
hide_loading();
|
||||||
|
if (get_query("debug")) {
|
||||||
|
show_debug();
|
||||||
|
}
|
||||||
|
setInterval(update_hint, 1000);
|
||||||
|
setTimeout(() => {
|
||||||
|
show_tooltip();
|
||||||
|
}, 15000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_tooltip() {
|
||||||
|
remove_class_by_query(".tooltip", "hidden");
|
||||||
|
add_class_by_query(".bottomfixed .action", "highlight");
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide_tooltip() {
|
||||||
|
add_class_by_query(".tooltip", "hidden");
|
||||||
|
remove_class_by_query(".bottomfixed .action", "highlight");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function init_scanguide() {
|
||||||
|
var r = await fetch('https://emblem-resources.oss-cn-guangzhou.aliyuncs.com/scan-guide-1080x1920-3.json');
|
||||||
|
var d = await r.json();
|
||||||
|
console.log("start scanguide", d);
|
||||||
|
const elem = document.getElementById("scanguide");
|
||||||
|
scanguide_anime = bodymovin.loadAnimation({
|
||||||
|
container: elem,
|
||||||
|
animationData: d,
|
||||||
|
// path: 'data.json',
|
||||||
|
renderer: 'svg',
|
||||||
|
loop: true,
|
||||||
|
autoplay: true,
|
||||||
|
name: "Scan guide",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_style_by_query(query, property, style) {
|
||||||
|
var list = document.querySelectorAll(query);
|
||||||
|
for (var i = 0; i < list.length; ++i) {
|
||||||
|
list[i].style[property] = style;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_class_by_query(query, to_add) {
|
||||||
|
var list = document.querySelectorAll(query);
|
||||||
|
for (var i = 0; i < list.length; ++i) {
|
||||||
|
list[i].classList.add(to_add);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_class_by_query(query, to_remove) {
|
||||||
|
var list = document.querySelectorAll(query);
|
||||||
|
for (var i = 0; i < list.length; ++i) {
|
||||||
|
list[i].classList.remove(to_remove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var modals = ['serviceqr', 'scanguide', 'verifyfailed', 'verifyspin'];
|
||||||
|
|
||||||
|
function hide_modal() {
|
||||||
|
busy = false;
|
||||||
|
scanguide_anime.stop();
|
||||||
|
add_class_by_query(".modal", "hidden");
|
||||||
|
hide_tooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_modal(which) {
|
||||||
|
busy = true;
|
||||||
|
hide_tooltip();
|
||||||
|
hide_spinner();
|
||||||
|
add_class_by_query(".verifyspin", "hidden");
|
||||||
|
remove_class_by_query(".modal", "hidden");
|
||||||
|
remove_class_by_query('.actions', 'hidden');
|
||||||
|
for (var m of modals) {
|
||||||
|
add_class_by_query('.' + m, 'hidden');
|
||||||
|
}
|
||||||
|
if (which == 'scanguide') {
|
||||||
|
scanguide_anime.goToAndPlay(0);
|
||||||
|
remove_class_by_query('.scanguide', 'hidden');
|
||||||
|
}
|
||||||
|
if (which == 'serviceqr') {
|
||||||
|
remove_class_by_query('.serviceqr', 'hidden');
|
||||||
|
add_class_by_query('.actions', 'hidden');
|
||||||
|
}
|
||||||
|
if (which == 'verifyfailed') {
|
||||||
|
remove_class_by_query('.verifyfailed', 'hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_service_qr_img() {
|
||||||
|
var tid = get_query('tenant');
|
||||||
|
var url = '/api/v1/service-qr/?tenant=' + tid;
|
||||||
|
const elem = document.getElementById("service_img");
|
||||||
|
elem.src = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
start_camera();
|
||||||
|
init_scanguide();
|
||||||
|
set_service_qr_img();
|
||||||
|
})();
|
||||||
5344
web/public/camera-5.0/camera-4.0/js/qrtool.web.js
Normal file
BIN
web/public/camera-5.0/camera-4.0/js/qrtool.web.wasm
Executable file
BIN
web/public/camera-5.0/camera-4.0/js/qrtool.web.wasm.br
Executable file
BIN
web/public/camera-5.0/camera-4.0/video/emblem-anime-short.mp4
Normal file
85
web/public/camera-5.0/css/loading.css
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
.lds-roller {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
.lds-roller div {
|
||||||
|
animation: lds-roller 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
||||||
|
transform-origin: 40px 40px;
|
||||||
|
}
|
||||||
|
.lds-roller div:after {
|
||||||
|
content: " ";
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #666;
|
||||||
|
margin: -4px 0 0 -4px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(1) {
|
||||||
|
animation-delay: -0.036s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(1):after {
|
||||||
|
top: 63px;
|
||||||
|
left: 63px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(2) {
|
||||||
|
animation-delay: -0.072s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(2):after {
|
||||||
|
top: 68px;
|
||||||
|
left: 56px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(3) {
|
||||||
|
animation-delay: -0.108s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(3):after {
|
||||||
|
top: 71px;
|
||||||
|
left: 48px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(4) {
|
||||||
|
animation-delay: -0.144s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(4):after {
|
||||||
|
top: 72px;
|
||||||
|
left: 40px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(5) {
|
||||||
|
animation-delay: -0.18s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(5):after {
|
||||||
|
top: 71px;
|
||||||
|
left: 32px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(6) {
|
||||||
|
animation-delay: -0.216s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(6):after {
|
||||||
|
top: 68px;
|
||||||
|
left: 24px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(7) {
|
||||||
|
animation-delay: -0.252s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(7):after {
|
||||||
|
top: 63px;
|
||||||
|
left: 17px;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(8) {
|
||||||
|
animation-delay: -0.288s;
|
||||||
|
}
|
||||||
|
.lds-roller div:nth-child(8):after {
|
||||||
|
top: 56px;
|
||||||
|
left: 12px;
|
||||||
|
}
|
||||||
|
@keyframes lds-roller {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
464
web/public/camera-5.0/css/main.css
Normal file
@ -0,0 +1,464 @@
|
|||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family:Tahoma,Verdana,STHeiTi,simsun,sans-serif;
|
||||||
|
}
|
||||||
|
div.debug {
|
||||||
|
position: absolute;
|
||||||
|
left: 5px;
|
||||||
|
bottom: 5px;
|
||||||
|
width: 80%;
|
||||||
|
height: 50%;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 2px dashed rgba(50, 255, 50, 0.5);
|
||||||
|
background-color: rgba(0, 50, 0, 0.7);
|
||||||
|
padding: 1rem;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 12px;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
.hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
video.preview {
|
||||||
|
object-fit: cover;
|
||||||
|
position: fixed;
|
||||||
|
top: -1%;
|
||||||
|
left: -1%;
|
||||||
|
width: 102%;
|
||||||
|
height: 102%;
|
||||||
|
z-index: -1000;
|
||||||
|
border: 1px solid yellow;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
div.debug canvas {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
div.bottomfixed {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
bottom: 0;
|
||||||
|
height: 90px;
|
||||||
|
background-color: #171616;
|
||||||
|
text-align: center;
|
||||||
|
border-top: 1px solid #ef4823;
|
||||||
|
}
|
||||||
|
|
||||||
|
.play.button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.1rem 1.2rem 0.1rem 1.4rem;
|
||||||
|
margin-right: 0.2rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
background-color: #707070;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.bottomfixed .action.highlight .play.button {
|
||||||
|
background-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.bottomfixed .action img {
|
||||||
|
height: 14px;
|
||||||
|
width: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.bottomfixed .action {
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #707070;
|
||||||
|
width: 49%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.bottomfixed .action.highlight {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.camoverlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
clear: both;
|
||||||
|
font-size: 0;
|
||||||
|
width: 100%;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
top: 18vw;
|
||||||
|
}
|
||||||
|
div.camoverlay img.qrmarkers {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.lower.text {
|
||||||
|
top: 4%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.progress {
|
||||||
|
width: 70%;
|
||||||
|
margin: 0.2rem 0 0 0;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #eee;
|
||||||
|
font-size: 18px;
|
||||||
|
color: black;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
div.progress-text {
|
||||||
|
color: #333;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
div.progress-bar {
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #ef4823;
|
||||||
|
width: 0%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
div.upper.overlay {
|
||||||
|
position: relative;
|
||||||
|
height: 100vmin;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.lower.overlay {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
div.debug .buttons {
|
||||||
|
margin: 0 0 0.3rem 0;
|
||||||
|
}
|
||||||
|
div.debug .buttons button {
|
||||||
|
height: 2rem;
|
||||||
|
margin: 0 5px 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#loading {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
background-color: white;
|
||||||
|
z-index: 10000;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas#output_img {
|
||||||
|
position: absolute;
|
||||||
|
right: 5px;
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.bordered {
|
||||||
|
padding: 0.2rem;
|
||||||
|
border: 1px dashed yellow;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 0.2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.output {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip {
|
||||||
|
position: absolute;
|
||||||
|
width: 100vmin;
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
animation: bounce 1s ease-in-out infinite; /* Adjust the duration as needed */
|
||||||
|
top: -60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip .tooltiptext {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 110px;
|
||||||
|
background-color: #ef4823;
|
||||||
|
color: #fff;
|
||||||
|
padding: 12px 0;
|
||||||
|
border-radius: 10px;
|
||||||
|
z-index: 1;
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip:hover .tooltiptext {
|
||||||
|
}
|
||||||
|
.tooltip .tooltiptext::after {
|
||||||
|
content: " ";
|
||||||
|
position: absolute;
|
||||||
|
top: 100%; /* At the bottom of the tooltip */
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -5px;
|
||||||
|
border-width: 5px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: #ef4823 transparent transparent transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bounce {
|
||||||
|
0%, 100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(10px); /* Adjust the bounce height as needed */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: fixed;
|
||||||
|
background-color: rgba(0, 0, 0, 0.9);
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .panel {
|
||||||
|
position: relative;
|
||||||
|
width: 80vmin;
|
||||||
|
height: 80%;
|
||||||
|
margin: 10vmin auto;
|
||||||
|
background-image: linear-gradient(0deg, #8b8986 0%, #414141 36%, #414141 92%, #515151 100%);
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .actions {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
bottom: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions button {
|
||||||
|
display: inline-block;
|
||||||
|
width: 35%;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 0.4rem 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.service {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
border: 1px solid #676767;
|
||||||
|
background-color: #858585;
|
||||||
|
color: #a7a7a7;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.back {
|
||||||
|
border: 1px solid rgba(239, 72, 35, 0.7);
|
||||||
|
color: rgba(239, 72, 35, 0.7);
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.back img.return {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.serviceqr {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
padding-top: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.serviceqr .imgbox {
|
||||||
|
display: block;
|
||||||
|
margin: auto;
|
||||||
|
width: 60vmin;
|
||||||
|
height: 60vmin;
|
||||||
|
padding: 3vmin;
|
||||||
|
background-color: #eee;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.serviceqr .title {
|
||||||
|
position: absolute;
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
color: #eee;
|
||||||
|
margin: 30px auto;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.serviceqr img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyfailed {
|
||||||
|
text-align: center;
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyfailed .title {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyfailed .hints {
|
||||||
|
margin-top: 80px;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyfailed .hints div {
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyfailed .circle {
|
||||||
|
height: 20vmin;
|
||||||
|
width: 20vmin;
|
||||||
|
color: #666;
|
||||||
|
font-size: 15vmin;
|
||||||
|
margin: 10vmin auto 1rem;;
|
||||||
|
background-color: #ddd;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyspin {
|
||||||
|
position: absolute;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 101;
|
||||||
|
width: 100vmin;
|
||||||
|
height: 100vmax;
|
||||||
|
background-color: rgba(0, 0, 0, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyspin .spinner {
|
||||||
|
position: absolute; /* Position the image absolutely */
|
||||||
|
width: 100vmin;
|
||||||
|
height: 100vmin;
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: center;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyspin img {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-and-shrink {
|
||||||
|
animation: spin-and-shrink 3s linear forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin-and-shrink {
|
||||||
|
0% {
|
||||||
|
transform: rotate(-90deg) scale(5.5)
|
||||||
|
}
|
||||||
|
10% {
|
||||||
|
transform: rotate(0deg) scale(2.0)
|
||||||
|
}
|
||||||
|
33% {
|
||||||
|
transform: rotate(90deg) scale(1.0);
|
||||||
|
}
|
||||||
|
66% {
|
||||||
|
transform: rotate(2000deg) scale(0.5);
|
||||||
|
}
|
||||||
|
99% {
|
||||||
|
transform: rotate(3600deg) scale(0.2);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(3600deg) scale(0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin-only {
|
||||||
|
animation: spin-only 0.3s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin-only {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg) scale(0.2);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg) scale(0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.verifyspin .loading {
|
||||||
|
color: #ccc;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
margin: 110vmin auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.scanguide {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#hint {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 10px auto;
|
||||||
|
padding: 12px 40px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
|
color: #eee;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.qrarc {
|
||||||
|
position: absolute;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 76vw;
|
||||||
|
height: 76vw;
|
||||||
|
margin: 20vw 12vw;
|
||||||
|
animation: qrarc-anime 1.2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.qrarc img.arc {
|
||||||
|
position: absolute;
|
||||||
|
width: 15%;
|
||||||
|
height: 15%;
|
||||||
|
opacity: 0.9;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.qrarc img.arc.topright {
|
||||||
|
right: 0;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
div.qrarc img.arc.bottomleft {
|
||||||
|
bottom: 0;
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
div.qrarc img.arc.bottomright {
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@keyframes qrarc-anime {
|
||||||
|
0% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
web/public/camera-5.0/images/arc.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
web/public/camera-5.0/images/black.png
Normal file
|
After Width: | Height: | Size: 637 B |
BIN
web/public/camera-5.0/images/camoverlay.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
web/public/camera-5.0/images/flash-button.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
web/public/camera-5.0/images/play-button.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
web/public/camera-5.0/images/qrmarkers.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
web/public/camera-5.0/images/return.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
web/public/camera-5.0/images/right-arrow.png
Normal file
|
After Width: | Height: | Size: 389 B |
BIN
web/public/camera-5.0/images/spinner.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
139
web/public/camera-5.0/index.html
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="description" content="WebRTC code samples">
|
||||||
|
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1, maximum-scale=1">
|
||||||
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
|
<base target="_blank">
|
||||||
|
<title>AI验真</title>
|
||||||
|
<link rel="stylesheet" href="css/main.css">
|
||||||
|
<link rel="stylesheet" href="css/loading.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="loading" id="loading">
|
||||||
|
<div>
|
||||||
|
<div class="lds-roller"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
AI摄像头加载中...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="container">
|
||||||
|
<div>
|
||||||
|
<div class="camoverlay">
|
||||||
|
<div class="upper overlay">
|
||||||
|
<div>
|
||||||
|
<div class="qrarc">
|
||||||
|
<img class="topleft arc" src="images/arc.png" />
|
||||||
|
<img class="topright arc" src="images/arc.png" />
|
||||||
|
<img class="bottomleft arc" src="images/arc.png" />
|
||||||
|
<img class="bottomright arc" src="images/arc.png" />
|
||||||
|
</div>
|
||||||
|
<img class="qrmarkers" src="images/qrmarkers.png" alt=""/>
|
||||||
|
</div>
|
||||||
|
<div class="hint wrapper">
|
||||||
|
<div id="hint" class="upper text" onclick="debug_countdown()">
|
||||||
|
对齐定位点
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<video class="preview" id="video" autoplay muted playsinline></video>
|
||||||
|
</div>
|
||||||
|
<div class="bottomfixed">
|
||||||
|
<div class="play action" onclick="show_modal('scanguide')">
|
||||||
|
<img
|
||||||
|
class="play"
|
||||||
|
src="images/play-button.png"
|
||||||
|
/>
|
||||||
|
验证演示
|
||||||
|
</div>
|
||||||
|
<div class="torch action" onclick="toggle_torch()">
|
||||||
|
<img
|
||||||
|
class="torch"
|
||||||
|
src="images/flash-button.png"
|
||||||
|
/>
|
||||||
|
开启补光
|
||||||
|
</div>
|
||||||
|
<div class="hidden tooltip"><span class="tooltiptext">遇到困难?</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="hidden debug" id="debug_div">
|
||||||
|
<div class="buttons">
|
||||||
|
<button onclick="location.reload()">reload</button>
|
||||||
|
<button onclick="set_zoom(4)">4x zoom</button>
|
||||||
|
<button onclick="set_zoom(2)">2x zoom</button>
|
||||||
|
<button onclick="wx_submit('debug')">WX OK</button>
|
||||||
|
<button onclick="torch_onoff()">Torch</button>
|
||||||
|
<button onclick="hide_debug()">Hide</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<canvas class="hidden" id="original" width="2000" height="2000">
|
||||||
|
</canvas>
|
||||||
|
<canvas class="hidden" id="grayscale" width="2000" height="2000">
|
||||||
|
</canvas>
|
||||||
|
</div>
|
||||||
|
<div id="logs" class="bordered">
|
||||||
|
</div>
|
||||||
|
<div class="bordered">
|
||||||
|
Caps: <span id="caps"></span>
|
||||||
|
</div>
|
||||||
|
<div class="bordered">
|
||||||
|
Constraints: <span id="cons"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal hidden">
|
||||||
|
<div class="panel">
|
||||||
|
<div class="scanguide hidden">
|
||||||
|
<div id="scanguide">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="serviceqr hidden">
|
||||||
|
<div class="imgbox">
|
||||||
|
<img id="service_img" src="https://emblem-resources.oss-accelerate.aliyuncs.com/service-qr2.png" alt=""/>
|
||||||
|
</div>
|
||||||
|
<div class="title">
|
||||||
|
长按识别二维码,添加人工客服
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="verifyfailed hidden">
|
||||||
|
<div class="circle">
|
||||||
|
!
|
||||||
|
</div>
|
||||||
|
<div class="title">验证未通过</div>
|
||||||
|
<div class="hints">
|
||||||
|
<div>
|
||||||
|
请按照验证指引
|
||||||
|
</div>
|
||||||
|
<div>重新验证</div>
|
||||||
|
<div>
|
||||||
|
-
|
||||||
|
</div>
|
||||||
|
<div>如反复验证仍无法通过</div>
|
||||||
|
<div>请联系人工客服</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="actions">
|
||||||
|
<button onclick="show_modal('serviceqr')" class="service">人工客服</button>
|
||||||
|
<button onclick="hide_modal()" class="back">
|
||||||
|
<img class="return" src="images/return.png" alt=""/>
|
||||||
|
采集</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="verifyspin hidden">
|
||||||
|
<div class="spinner">
|
||||||
|
<img src="images/spinner.png" class="spin-image spin-and-shrink">
|
||||||
|
</div>
|
||||||
|
<div class="loading">
|
||||||
|
Loading
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
|
||||||
|
<script type="text/javascript" src="js/lottie.min.js"></script>
|
||||||
|
<script type="text/javascript" src="js/main.js"></script>
|
||||||
|
<script type="text/javascript" src="js/qrtool.web.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
web/public/camera-5.0/js/lottie.min.js
vendored
Normal file
409
web/public/camera-5.0/js/main.js
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
var debug_taps = 0;
|
||||||
|
var debug_logs = [];
|
||||||
|
var track;
|
||||||
|
var frame_width;
|
||||||
|
var frame_height;
|
||||||
|
var scanguide_anime;
|
||||||
|
var busy = false;
|
||||||
|
const max_inflight = 5;
|
||||||
|
var should_check_auto_torch = true;
|
||||||
|
var done_checking_auto_torch = false;
|
||||||
|
var camera_sensitivity = 1.0;
|
||||||
|
var camera_capabilities = null;
|
||||||
|
|
||||||
|
var Module = {
|
||||||
|
onRuntimeInitialized: start,
|
||||||
|
};
|
||||||
|
|
||||||
|
function get_query(key) {
|
||||||
|
const qs = window.location.search;
|
||||||
|
const params = new URLSearchParams(qs);
|
||||||
|
return params.get(key) || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_debug() {
|
||||||
|
const debug_div = document.getElementById("debug_div");
|
||||||
|
debug_div.classList.remove("hidden");
|
||||||
|
}
|
||||||
|
function hide_debug() {
|
||||||
|
const debug_div = document.getElementById("debug_div");
|
||||||
|
debug_div.classList.add("hidden");
|
||||||
|
}
|
||||||
|
function debug_countdown() {
|
||||||
|
debug_taps += 1;
|
||||||
|
if (debug_taps > 10) {
|
||||||
|
show_debug();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide_loading() {
|
||||||
|
const loading = document.getElementById("loading");
|
||||||
|
loading.classList.add("hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_stream(stream) {
|
||||||
|
const video = document.querySelector('video');
|
||||||
|
const videoTracks = stream.getVideoTracks();
|
||||||
|
debug_log(`total video tracks: ${videoTracks.length} Using video device: ${videoTracks[0].label}`);
|
||||||
|
window.stream = stream; // make variable available to browser console
|
||||||
|
video.srcObject = stream;
|
||||||
|
video.play();
|
||||||
|
track = videoTracks[0];
|
||||||
|
camera_capabilities = track.getCapabilities();
|
||||||
|
const caps = document.getElementById("caps");
|
||||||
|
caps.innerHTML = JSON.stringify(camera_capabilities);
|
||||||
|
const settings = track.getSettings();
|
||||||
|
console.log(settings);
|
||||||
|
const canvas = document.getElementById("original");
|
||||||
|
frame_width = settings.width;
|
||||||
|
frame_height = settings.height;
|
||||||
|
video.width = frame_width;
|
||||||
|
video.height = frame_height;
|
||||||
|
canvas.width = frame_width;
|
||||||
|
canvas.height = frame_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleError(error) {
|
||||||
|
debug_log(error);
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
function debug_log(msg) {
|
||||||
|
debug_logs.push(Date.now() / 1000 + ": " + msg);
|
||||||
|
const nentries = 20;
|
||||||
|
while (debug_logs.length > nentries) {
|
||||||
|
debug_logs.shift();
|
||||||
|
}
|
||||||
|
var output = "";
|
||||||
|
for (var l of debug_logs) {
|
||||||
|
output = `<div>${l}</div>` + output;
|
||||||
|
}
|
||||||
|
console.log(msg);
|
||||||
|
const di = document.getElementById("logs");
|
||||||
|
di.innerHTML = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function start_camera(e) {
|
||||||
|
try {
|
||||||
|
const constraints = window.constraints = {
|
||||||
|
audio: false,
|
||||||
|
video: {
|
||||||
|
facingMode: "environment",
|
||||||
|
focusDistance: 0.12,
|
||||||
|
focusMode: "manual",
|
||||||
|
width: { ideal: 2000 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const supportedConstraints = navigator.mediaDevices.getSupportedConstraints();
|
||||||
|
const cons = document.getElementById("cons");
|
||||||
|
cons.innerHTML = JSON.stringify(supportedConstraints);
|
||||||
|
debug_log(navigator.userAgent);
|
||||||
|
|
||||||
|
const stream = await navigator.mediaDevices.getUserMedia(constraints);
|
||||||
|
handle_stream(stream);
|
||||||
|
const zoom = get_query("zoom");
|
||||||
|
if (zoom) {
|
||||||
|
set_zoom(zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
handleError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_emblem_qr_pattern(p)
|
||||||
|
{
|
||||||
|
if (p.search(/code=[0-9a-zA-Z]+/) >= 0) return true;
|
||||||
|
if (p.search(/c=[0-9a-zA-Z]+/) >= 0) return true;
|
||||||
|
if (p.search(/https:\/\/xy.ltd\/v\/[0-9a-zA-Z]+/) >= 0) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_hint_text(r) {
|
||||||
|
var qr_is_valid = false;
|
||||||
|
if (r.qrcode && r.qrcode.length > 0) {
|
||||||
|
qr_is_valid = is_emblem_qr_pattern(r.qrcode);
|
||||||
|
if (!qr_is_valid) {
|
||||||
|
return "无效编码";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (qr_is_valid) {
|
||||||
|
var err = r.err || "";
|
||||||
|
if (err.includes("margin too small")) {
|
||||||
|
return "对齐定位点";
|
||||||
|
} else if (err.includes("energy check failed") || err.includes("cannot detect angle")) {
|
||||||
|
return "移近一点";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "对齐定位点";
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_frame() {
|
||||||
|
try {
|
||||||
|
do_handle_frame();
|
||||||
|
} catch (e) {
|
||||||
|
debug_log("handle frame exception: " + e);
|
||||||
|
}
|
||||||
|
setTimeout(handle_frame, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
function do_handle_frame() {
|
||||||
|
if (busy) return;
|
||||||
|
const canvas = document.getElementById("original");
|
||||||
|
const video = document.getElementById("video");
|
||||||
|
|
||||||
|
canvas.width = video.width;
|
||||||
|
canvas.height = video.height;
|
||||||
|
|
||||||
|
canvas.style.width = video.width / 4 + "px";
|
||||||
|
canvas.style.height = video.height / 4 + "px";
|
||||||
|
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
ctx.drawImage(video, 0, 0);
|
||||||
|
const id = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||||
|
console.log(Module);
|
||||||
|
var buf = Module._malloc(id.data.length * id.data.BYTES_PER_ELEMENT);
|
||||||
|
Module.HEAPU8.set(id.data, buf);
|
||||||
|
var r = Module.ccall('qrtool_angle', 'string', ['number', 'number', 'number', 'number', 'number'], [buf, id.width, id.height, 0, camera_sensitivity]);
|
||||||
|
Module._free(buf);
|
||||||
|
debug_log(r);
|
||||||
|
const res = JSON.parse(r);
|
||||||
|
const is_valid_pattern = res.qrcode && res.qrcode.length && is_emblem_qr_pattern(res.qrcode);
|
||||||
|
if (res.qrcode && should_check_auto_torch) {
|
||||||
|
start_check_auto_torch(res.qrcode);
|
||||||
|
}
|
||||||
|
if (done_checking_auto_torch && is_valid_pattern && res.ok) {
|
||||||
|
var data_url = canvas.toDataURL("image/jpeg", 1.0);
|
||||||
|
submit_image(res.qrcode, res.angle, data_url);
|
||||||
|
} else {
|
||||||
|
pending_hint = make_hint_text(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function start_check_auto_torch(qrcode)
|
||||||
|
{
|
||||||
|
should_check_auto_torch = false;
|
||||||
|
var r = await fetch("https://themblem.com/api/v1/check-auto-torch/?qrcode=" + encodeURIComponent(qrcode), {
|
||||||
|
method: "GET",
|
||||||
|
});
|
||||||
|
var d = await r.json();
|
||||||
|
debug_log(JSON.stringify(d));
|
||||||
|
if (d.enable_auto_torch && !torch) {
|
||||||
|
toggle_torch();
|
||||||
|
}
|
||||||
|
camera_sensitivity = d.camera_sensitivity || 1.0;
|
||||||
|
setTimeout(() => {
|
||||||
|
done_checking_auto_torch = true;
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_zoom(zoom) {
|
||||||
|
if (camera_capabilities.zoom) {
|
||||||
|
debug_log("set zoom by applying constraints");
|
||||||
|
track.applyConstraints({advanced: [ {zoom} ]});
|
||||||
|
} else {
|
||||||
|
debug_log("set zoom by scaling video element");
|
||||||
|
add_style_by_query("video.preview", "transform", `scale(${zoom})`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let torch = false;
|
||||||
|
function toggle_torch() {
|
||||||
|
torch = !torch;
|
||||||
|
track.applyConstraints({advanced: [ {torch: torch} ]});
|
||||||
|
if (torch) {
|
||||||
|
add_class_by_query(".bottomfixed .torch.action", "highlight");
|
||||||
|
} else {
|
||||||
|
remove_class_by_query(".bottomfixed .torch.action", "highlight");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_spinner() {
|
||||||
|
remove_class_by_query('.verifyspin', 'hidden');
|
||||||
|
remove_class_by_query('.spin-image', 'spin-only');
|
||||||
|
remove_class_by_query('.spin-image', 'spin-and-shrink');
|
||||||
|
setTimeout(() => {
|
||||||
|
add_class_by_query('.spin-image', 'spin-and-shrink');
|
||||||
|
setTimeout(() => {
|
||||||
|
remove_class_by_query('.spin-image', 'spin-and-shrink');
|
||||||
|
add_class_by_query('.spin-image', 'spin-only');
|
||||||
|
}, 3000);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide_spinner() {
|
||||||
|
add_class_by_query('.verifyspin', 'hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submit_image(qrcode, angle, image_data_url) {
|
||||||
|
busy = true;
|
||||||
|
var begin = Date.now();
|
||||||
|
show_spinner();
|
||||||
|
debug_log(`submit: qrcode: ${qrcode} angle: ${angle}`);
|
||||||
|
try {
|
||||||
|
// TODO: pass these parameters from query string
|
||||||
|
var emblem_id = get_query("emblem_id");
|
||||||
|
var nick_name = get_query("nick_name");
|
||||||
|
var realip = get_query("realip");
|
||||||
|
var phonemodel = get_query("phonemodel");
|
||||||
|
var skip_angle_check = get_query("skip_angle_check");
|
||||||
|
var data = {
|
||||||
|
emblem_id,
|
||||||
|
nick_name,
|
||||||
|
realip,
|
||||||
|
qrcode,
|
||||||
|
angle,
|
||||||
|
phonemodel,
|
||||||
|
image_data_url,
|
||||||
|
skip_angle_check,
|
||||||
|
log: debug_logs.join("\n"),
|
||||||
|
};
|
||||||
|
var r = await fetch("https://themblem.com/api/v1/qr-verify/", {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
});
|
||||||
|
var d = await r.json();
|
||||||
|
debug_log(JSON.stringify(d));
|
||||||
|
if (d.serial_code) {
|
||||||
|
if (wx) {
|
||||||
|
var delay = 3000 - (Date.now() - begin);
|
||||||
|
setTimeout(() => {
|
||||||
|
if (get_query("ai_chat_mode")) {
|
||||||
|
wx.miniProgram.redirectTo({
|
||||||
|
url: '/pages/chat/chat?serial_code=' + d.serial_code,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
wx.miniProgram.redirectTo({
|
||||||
|
url: '/pages/productinfo/productinfo?serial_code=' + d.serial_code,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, delay > 0 ? delay : 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.show_modal('verifyfailed');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debug_log(`submission error: ${e}`);
|
||||||
|
this.show_modal('verifyfailed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var pending_hint = null;
|
||||||
|
|
||||||
|
function update_hint() {
|
||||||
|
var now = Date.now();
|
||||||
|
if (pending_hint) {
|
||||||
|
const hint_dev = document.getElementById("hint");
|
||||||
|
hint_dev.innerHTML = pending_hint;
|
||||||
|
pending_hint = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
console.log("start");
|
||||||
|
setTimeout(handle_frame, 100);
|
||||||
|
hide_loading();
|
||||||
|
if (get_query("debug")) {
|
||||||
|
show_debug();
|
||||||
|
}
|
||||||
|
setInterval(update_hint, 1000);
|
||||||
|
setTimeout(() => {
|
||||||
|
show_tooltip();
|
||||||
|
}, 15000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_tooltip() {
|
||||||
|
remove_class_by_query(".tooltip", "hidden");
|
||||||
|
add_class_by_query(".bottomfixed .action", "highlight");
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide_tooltip() {
|
||||||
|
add_class_by_query(".tooltip", "hidden");
|
||||||
|
remove_class_by_query(".bottomfixed .action", "highlight");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function init_scanguide() {
|
||||||
|
var r = await fetch('https://emblem-resources.oss-cn-guangzhou.aliyuncs.com/scan-guide-1080x1920-3.json');
|
||||||
|
var d = await r.json();
|
||||||
|
console.log("start scanguide", d);
|
||||||
|
const elem = document.getElementById("scanguide");
|
||||||
|
scanguide_anime = bodymovin.loadAnimation({
|
||||||
|
container: elem,
|
||||||
|
animationData: d,
|
||||||
|
// path: 'data.json',
|
||||||
|
renderer: 'svg',
|
||||||
|
loop: true,
|
||||||
|
autoplay: true,
|
||||||
|
name: "Scan guide",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_style_by_query(query, property, style) {
|
||||||
|
var list = document.querySelectorAll(query);
|
||||||
|
for (var i = 0; i < list.length; ++i) {
|
||||||
|
list[i].style[property] = style;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_class_by_query(query, to_add) {
|
||||||
|
var list = document.querySelectorAll(query);
|
||||||
|
for (var i = 0; i < list.length; ++i) {
|
||||||
|
list[i].classList.add(to_add);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_class_by_query(query, to_remove) {
|
||||||
|
var list = document.querySelectorAll(query);
|
||||||
|
for (var i = 0; i < list.length; ++i) {
|
||||||
|
list[i].classList.remove(to_remove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var modals = ['serviceqr', 'scanguide', 'verifyfailed', 'verifyspin'];
|
||||||
|
|
||||||
|
function hide_modal() {
|
||||||
|
busy = false;
|
||||||
|
scanguide_anime.stop();
|
||||||
|
add_class_by_query(".modal", "hidden");
|
||||||
|
hide_tooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_modal(which) {
|
||||||
|
busy = true;
|
||||||
|
hide_tooltip();
|
||||||
|
hide_spinner();
|
||||||
|
add_class_by_query(".verifyspin", "hidden");
|
||||||
|
remove_class_by_query(".modal", "hidden");
|
||||||
|
remove_class_by_query('.actions', 'hidden');
|
||||||
|
for (var m of modals) {
|
||||||
|
add_class_by_query('.' + m, 'hidden');
|
||||||
|
}
|
||||||
|
if (which == 'scanguide') {
|
||||||
|
scanguide_anime.goToAndPlay(0);
|
||||||
|
remove_class_by_query('.scanguide', 'hidden');
|
||||||
|
}
|
||||||
|
if (which == 'serviceqr') {
|
||||||
|
remove_class_by_query('.serviceqr', 'hidden');
|
||||||
|
add_class_by_query('.actions', 'hidden');
|
||||||
|
}
|
||||||
|
if (which == 'verifyfailed') {
|
||||||
|
remove_class_by_query('.verifyfailed', 'hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_service_qr_img() {
|
||||||
|
var tid = get_query('tenant');
|
||||||
|
var url = '/api/v1/service-qr/?tenant=' + tid;
|
||||||
|
const elem = document.getElementById("service_img");
|
||||||
|
elem.src = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
start_camera();
|
||||||
|
init_scanguide();
|
||||||
|
set_service_qr_img();
|
||||||
|
})();
|
||||||