📖WordPress产品防伪码查询,带扫码功能
在wordpress后台创建一个可以批量上传防伪码的功能,并且在前面使用form输入框查询防伪码是否有效
可批量上传防伪码,需要CSV + UTF-8,一次上传10W条数据,演示文件dd.csv
其中包含一个扫码的JS文件需要放到指定文件jsQR.min.js
//安装WpCode并输入以下代码,PHP // 创建防伪码数据库表 function create_auth_code_table() { global $wpdb; $table_name = $wpdb->prefix . 'auth_codes'; // 检查表是否已存在 if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) { // 表的字符集和校对规则 $charset_collate = $wpdb->get_charset_collate(); // 创建表的 SQL 语句 $sql = "CREATE TABLE $table_name ( id mediumint(9) NOT NULL AUTO_INCREMENT, auth_code varchar(255) NOT NULL, PRIMARY KEY (id) ) $charset_collate;"; // 引入 WordPress 的升级文件 require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); // 执行 SQL 语句 } } // 激活插件时创建数据库表 add_action('after_switch_theme', 'create_auth_code_table'); // 后端处理:验证防伪码是否有效 function verify_auth_code_ajax() { if (isset($_POST['auth_code'])) { $auth_code = sanitize_text_field($_POST['auth_code']); global $wpdb; // 查询防伪码是否存在 $result = $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM {$wpdb->prefix}auth_codes WHERE auth_code = %s", $auth_code) ); if ($result > 0) { // 防伪码有效 echo 'valid'; // 返回 "valid" 表示防伪码有效 } else { // 防伪码无效 echo 'invalid'; // 返回 "invalid" 表示防伪码无效 } } die(); // 结束 AJAX 请求 } add_action('wp_ajax_verify_auth_code', 'verify_auth_code_ajax'); // 管理员 AJAX 请求 add_action('wp_ajax_nopriv_verify_auth_code', 'verify_auth_code_ajax'); // 非管理员 AJAX 请求 // 前端验证防伪码功能 function verify_auth_code() { ?> <style> /* 表单区域 */ #searchForm{display:flex;gap:0px;flex-wrap: wrap;} #searchForm #scanBtn{padding: 8px 30px;font-size: 16px;border: none;cursor: pointer;border-radius: 0px 100px 100px 0px;display: flex;width: 20%;} #scanBtn svg {width: 35px;height: 35px;} #scanBtn{background:#000;color:#fff} /* 扫描层覆盖全屏,初始隐藏 */ #scanner{display:none;position:fixed;inset:0;background:#000} #scanner video,#scanner canvas{position:absolute;inset:0;width:100%;height:100%;object-fit:cover} .scan-box{ position:absolute;top:50%;left:50%; width:60vmin;height:60vmin; transform:translate(-50%,-50%); border:3px solid #ffeb3b;border-radius:8px;pointer-events:none; } </style> <script src="/wp-content/themes/woodmart2025-4-17/jsQR.min.js"></script> <form method="post" class="Verify_Form" onsubmit="return doSearch();" id="searchForm"> <input type="text" name="auth_code" id="auth_code" placeholder="Enter your security code" required/> <!-- 将提交按钮改为 button 元素,并加入 Font Awesome 图标 --> <button type="button" id="scanBtn"> <svg t="1750067170492" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2374" width="200" height="200"><path d="M928 544 96 544c-17.664 0-32-14.336-32-32s14.336-32 32-32l832 0c17.696 0 32 14.336 32 32S945.696 544 928 544zM832 928l-192 0c-17.696 0-32-14.304-32-32s14.304-32 32-32l192 0c17.664 0 32-14.336 32-32l0-160c0-17.696 14.304-32 32-32s32 14.304 32 32l0 160C928 884.928 884.928 928 832 928zM352 928 192 928c-52.928 0-96-43.072-96-96l0-160c0-17.696 14.336-32 32-32s32 14.304 32 32l0 160c0 17.664 14.368 32 32 32l160 0c17.664 0 32 14.304 32 32S369.664 928 352 928zM128 384c-17.664 0-32-14.336-32-32L96 192c0-52.928 43.072-96 96-96l160 0c17.664 0 32 14.336 32 32s-14.336 32-32 32L192 160C174.368 160 160 174.368 160 192l0 160C160 369.664 145.664 384 128 384zM896 384c-17.696 0-32-14.336-32-32L864 192c0-17.632-14.336-32-32-32l-192 0c-17.696 0-32-14.336-32-32s14.304-32 32-32l192 0c52.928 0 96 43.072 96 96l0 160C928 369.664 913.696 384 896 384z" fill="#ffffff" p-id="2375"></path></svg> </button> <button type="submit" id="verify_button">Click on the query</button> </form> <!-- ② 扫码层(点击扫码后显示) --> <div id="scanner"> <video id="video" playsinline muted></video> <canvas id="canvas"></canvas> <div class="scan-box"></div> </div> <script> // ======== 搜索逻辑 ======== function doSearch(){ const q = document.getElementById('auth_code').value.trim(); if(!q) return false; // 空值不搜索 submit(); return false; // 阻止表单默认提交 } function submit() { // 获取输入的防伪码 jQuery(document).ready(function($) { var auth_code = $('#auth_code').val(); // 发送 AJAX 请求 $.ajax({ url: '<?php echo admin_url('admin-ajax.php'); ?>', // WordPress AJAX URL method: 'POST', data: { action: 'verify_auth_code', // 后端处理的钩子 auth_code: auth_code, // 要验证的防伪码 }, success: function(response) { // 根据返回结果显示弹框 if (response === 'valid') { // 防伪码有效,显示"真的"弹框 if (typeof elementorProFrontend !== 'undefined') { console.log(1); elementorProFrontend.modules.popup.showPopup( { id: 933 } ); } else { alert("Elementor 前端 API 未加载!"); } } else if (response === 'invalid') { // 防伪码无效,显示"假的"弹框 if (typeof elementorProFrontend !== 'undefined') { console.log(2); elementorProFrontend.modules.popup.showPopup( { id: 936 } ); } else { alert("Elementor 前端 API 未加载!"); } } }, error: function() { alert('发生错误,请稍后再试。'); } }); }); } // ======== 扫码逻辑 ======== const scanBtn = document.getElementById('scanBtn'); const scanner = document.getElementById('scanner'); const video = document.getElementById('video'); const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); let scanning = false; let stream = null; // 用于稍后关闭摄像头 scanBtn.addEventListener('click', startScan); async function startScan(){ scanner.style.display = 'block'; // 显示扫描层 try{ stream = await navigator.mediaDevices.getUserMedia({video:{facingMode:'environment'}}); video.srcObject = stream; await video.play(); canvas.width = video.videoWidth; canvas.height = video.videoHeight; scanning = true; requestAnimationFrame(scanFrame); }catch(e){ alert('无法打开摄像头:'+e); scanner.style.display = 'none'; } } async function scanFrame(){ if(!scanning) return; ctx.drawImage(video,0,0,canvas.width,canvas.height); // 按可视扫描框裁剪像素 const box = document.querySelector('.scan-box'); const {left,top,width,height} = box.getBoundingClientRect(); const scaleX = canvas.width / window.innerWidth; const scaleY = canvas.height / window.innerHeight; const imgData = ctx.getImageData(left*scaleX, top*scaleY, width*scaleX, height*scaleY); const code = jsQR(imgData.data, imgData.width, imgData.height); if(code){ handleResult(code.data); }else{ requestAnimationFrame(scanFrame); } } function handleResult(text){ scanning = false; video.pause(); if(stream){ stream.getTracks().forEach(t => t.stop()); // 关闭摄像头 stream = null; } scanner.style.display = 'none'; // ③ 把结果回填搜索框并自动搜索 document.getElementById('auth_code').value = text.split('s=')[1]; doSearch(); } </script> <?php } add_shortcode('verify_auth_code', 'verify_auth_code'); // 添加后台菜单项 function add_verity_product_menu() { // 确保在后台页面时才添加菜单项 if (current_user_can('manage_options')) { add_menu_page( 'Verity Product', // 页面标题 'Verity Product', // 菜单名称 'manage_options', // 用户权限 'verity-product', // 菜单的 slug 'verity_product_page', // 显示页面的回调函数 'dashicons-upload', // 菜单图标 20 // 菜单位置 ); } } // 确保钩子正确执行 add_action('admin_menu', 'add_verity_product_menu'); // 后台页面内容:上传 CSV 文件并批量管理防伪码 function verity_product_page() { global $wpdb; $table_name = $wpdb->prefix . 'auth_codes'; // 每页显示的防伪码数量 $per_page = 10; // 获取当前页 $paged = isset($_GET['paged']) ? absint($_GET['paged']) : 1; $offset = ($paged - 1) * $per_page; // 获取防伪码数据(分页) $auth_codes = $wpdb->get_results( $wpdb->prepare("SELECT * FROM $table_name LIMIT %d OFFSET %d", $per_page, $offset) ); // 获取总记录数 $total_count = $wpdb->get_var("SELECT COUNT(*) FROM $table_name"); // 计算总页数 $total_pages = ceil($total_count / $per_page); // 处理删除操作 if (isset($_POST['action']) && $_POST['action'] == 'delete' && isset($_POST['auth_codes'])) { // 获取选中的防伪码 ID $auth_codes_to_delete = array_map('intval', $_POST['auth_codes']); // 删除选中的防伪码 $wpdb->query( "DELETE FROM $table_name WHERE id IN (" . implode(',', $auth_codes_to_delete) . ")" ); // 显示删除成功消息 echo '<div class="updated"><p>防伪码已删除。</p></div>'; echo '<script>window.location.reload();</script>'; // 刷新页面 } // 文件上传和处理 if (isset($_FILES['csv_file']) && $_FILES['csv_file']['error'] == 0) { // 获取文件信息 $file_tmp = $_FILES['csv_file']['tmp_name']; $file_name = $_FILES['csv_file']['name']; // 检查文件扩展名是否为 CSV $file_extension = pathinfo($file_name, PATHINFO_EXTENSION); if ($file_extension !== 'csv') { echo '<div class="error"><p>请上传 CSV 格式的文件!</p></div>'; return; } // 检查文件是否为 UTF-8 编码 $file_content = file_get_contents($file_tmp); if (!mb_check_encoding($file_content, 'UTF-8')) { echo '<div class="error"><p>文件必须是 UTF-8 编码!</p></div>'; return; } // 读取 CSV 文件并处理 if (($handle = fopen($file_tmp, "r")) !== FALSE) { $header = fgetcsv($handle); // 跳过文件头部 while (($data = fgetcsv($handle)) !== FALSE) { // 处理 CSV 文件数据 $auth_code = sanitize_text_field($data[0]); // 假设防伪码在第一列 // 插入数据到数据库 $wpdb->insert( $table_name, array('auth_code' => $auth_code), array('%s') ); } fclose($handle); } echo '<div class="updated"><p>CSV 文件已成功上传并保存!</p></div>'; echo '<script>window.location.reload();</script>'; } ?> <div class="wrap"> <h1>上传防伪码</h1> <!-- 上传表单 --> <form id="upload_form" method="post" enctype="multipart/form-data"> <input type="file" id="csv_file" name="csv_file" accept=".csv" /> <input type="submit" name="upload_csv" value="上传 CSV" class="button button-primary" /> </form> <!-- 显示上传进度 --> <div id="progress_wrapper" style="display: none;"> <label for="progress_bar">数据写入进度:</label> <progress id="progress_bar" value="0" max="100" style="width: 100%;"></progress> <p id="progress_text">0%</p> </div> <div id="upload_message"></div> <h2>防伪码管理</h2> <form method="post"> <table class="wp-list-table widefat fixed striped"> <thead> <tr> <th class="manage-column column-cb check-column"> <input type="checkbox" /> </th> <th class="manage-column">防伪码</th> </tr> </thead> <tbody> <?php foreach ($auth_codes as $auth_code) : ?> <tr> <th class="check-column"> <input type="checkbox" name="auth_codes[]" value="<?php echo $auth_code->id; ?>" /> </th> <td><?php echo esc_html($auth_code->auth_code); ?></td> </tr> <?php endforeach; ?> </tbody> </table> <div class="bulk-actions alignleft"> <select name="action"> <option value="-1">批量操作</option> <option value="delete">删除</option> </select> <input type="submit" value="应用" class="button action" /> </div> </form> <div class="tablenav"> <div class="tablenav-pages"> <?php echo paginate_links(array( 'total' => $total_pages, 'current' => $paged, 'format' => '?paged=%#%', 'prev_text' => '« 上一页', 'next_text' => '下一页 »', )); ?> </div> </div> </div> <?php }
🧐发表评论