移动端浏览器的扫描二维码实现(vue-qrcode-reader与jsQR方式)
1. 实现功能
类似扫一扫的功能,自动识别到画面中的二维码并进行识别,也可以选择从相册中上传。
2. 涉及到的一些插件介绍
vue-qrcode-reader
一组用于检测和解码二维码的Vue.js组件
jsQR
一个纯粹的javascript二维码阅读库,该库接收原始图像,并将定位、提取和解析在其中找到的任何二维码。
zxing-wasm
ZXing-C++ WebAssembly 作为带有类型的 ES/CJS 模块。读/写 web、node、bun 和 deno 中的条形码。
2. vite项目配置本地开发使用https访问
安装basicSsl
pnpm i @vitejs/plugin-basic-ssl
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import basicSsl from '@vitejs/plugin-basic-ssl'// https://vitejs.dev/config/
export default defineConfig({plugins: [vue(), basicSsl()],server: {host: '0.0.0.0',https: true},resolve: {alias: {'@': path.resolve(__dirname, 'src')}}
})
3. 方式一:vue-qrcode-reader实现
npm install vue-qrcode-reader
🔍vue-qrcode-reader Api 介绍
<template><div><qrcode-streamclass="qrcode-wrap":torch="torch"v-memo="[torch]":constraints="selectedConstraints":track="paintBoundingBox"@error="onError"@detect="onDetect"@camera-on="onCameraReady"><div v-if="isSupportTorch" class="torch-wrap"><div class="torch" @click="() => (torch = !torch)"><div class="flash-light" v-if="torch"><MdiFlashlightOff style="width: 36px; height: 36px" /></div><div class="flash-light" v-else><MdiFlashlight style="width: 36px; height: 36px" /></div>{{ torch ? "关闭闪光灯" : "打开闪光灯" }}</div></div><div class="photo-wrap"><div class="photo" @click="handleOpenFile"><el-icon size="20"><PictureFilled /></el-icon></div><div class="color-[#fff]">相册</div></div></qrcode-stream></div>
</template>
<script setup lang="ts">
// https://gruhn.github.io/vue-qrcode-reader/api/QrcodeStream.html
import { QrcodeStream } from "vue-qrcode-reader";
import { PictureFilled } from "@element-plus/icons-vue";
import MdiFlashlight from "~icons/mdi/flashlight";
import MdiFlashlightOff from "~icons/mdi/flashlight-off";
import { ElMessage } from "element-plus";
import { fileOpen } from "browser-fs-access";
import _ from "lodash";const error = ref("");
const cameraIsReady = ref(false);
const isSupportTorch = ref(false); // 是否支持闪光灯
const torch = ref(false); // 闪光灯状态
// 相机配置选项: 'user'|'environment' (默认:environment)
const selectedConstraints = ref({ facingMode: "environment" });// 检测到二维码后绘制画布类型
function paintBoundingBox(detectedCodes: any, ctx: CanvasRenderingContext2D) {for (const detectedCode of detectedCodes) {const {boundingBox: { x, y, width, height },} = detectedCode;ctx.lineWidth = 2;ctx.strokeStyle = "#007bff";// 绘制边框矩形ctx.strokeRect(x, y, width, height);}
}async function onCameraReady(capabilities: any) {// NOTE: on iOS we can't invoke `enumerateDevices` before the user has given// camera access permission. `QrcodeStream` internally takes care of// requesting the permissions. The `camera-on` event should guarantee that this// has happened.try {isSupportTorch.value = !!capabilities.torch;cameraIsReady.value = true;error.value = "";} catch (error) {onError(error);cameraIsReady.value = false;}
}
// 错误提示
function onError(err: any) {error.value = `[${err.name}]: `;if (err.name === "NotAllowedError") {error.value += "you need to grant camera access permission";} else if (err.name === "NotFoundError") {error.value += "no camera on this device";} else if (err.name === "NotSupportedError") {error.value += "secure context required (HTTPS, localhost)";} else if (err.name === "NotReadableError") {error.value += "is the camera already in use?";} else if (err.name === "OverconstrainedError") {error.value += "installed cameras are not suitable";} else if (err.name === "StreamApiNotSupportedError") {error.value += "Stream API is not supported in this browser";} else if (err.name === "InsecureContextError") {error.value +="Camera access is only permitted in secure context. Use HTTPS or localhost rather than HTTP.";} else {error.value += err.message;}ElMessage.warning(error.value);
}
// 用户摄像头的流后
function onDetect(detectedCodes: any) {if (detectedCodes.length > 0) {onDecode(detectedCodes[0]?.rawValue);}
}const emit = defineEmits(["on-success"]);// 解码(交给父组件处理:进行网络请求)
function onDecode(text: string) {emit("on-success", text);
}
// 文件转成base64
const processFile = async (file: any) => {let reader = new FileReader();reader.readAsDataURL(file);reader.onload = (e) => {let base64String = e.target?.result as string ||'';// 此处可对该base64进行获取赋值传入后端, 如果有直接上传文件的接口就可以直接传文件onDecode(base64String)};
};
// 打开图片选择
async function handleOpenFile() {try {const file = await fileOpen({ mimeTypes: ["image/*"] }).catch(() => null);if (!file) return;// 计算文件的大小const fileSizeMb = _.round(file.size / 1024 / 1024, 2);// 文件大小不能超过 10MBconst limitSizeMb = 10;if (fileSizeMb > limitSizeMb) {return ElMessage.warning(`图片大小限制 ${limitSizeMb}MB`);}processFile(file)} catch (error) {console.log(`[log] - handleOpenUploadIcon - error:`, error);}
}
</script>
<style scoped>
.qrcode-wrap {position: fixed !important;top: 0;right: 0;bottom: 0;left: 0;width: 100vw;height: 100vh;z-index: 1 !important;background: rgba(0, 0, 0, 0.5);
}
.torch-wrap {width: 18.75rem;height: 12.5rem;position: fixed !important;left: 50%;top: 50%;transform: translate(-50%, -30%);z-index: 20;
}.torch {position: fixed;bottom: -6.25rem;left: 50%;transform: translateX(-50%);z-index: 20;color: #fff;display: flex;flex-direction: column;align-items: center;
}
.photo-wrap {position: fixed;bottom: 2.875rem;left: 2.875rem;display: flex;flex-direction: column;align-items: center;gap: 6px;
}.photo {height: 3.125rem;width: 3.125rem;background-color: rgba(250, 250, 250, 0.8);border-radius: 50%;display: grid;place-items: center;cursor: pointer;
}
</style>
browser-fs-access 这个包需要提前下载
pnpm i browser-fs-access
如果需要在离线的环境解析二维码,则需要使用zxing-wasm,在上面文件的js部分添加以下代码:
// 该文件由zxing-wasm项目构建而来
import wasmFile from './zxing_reader.wasm?url';// !为了离线加载
// https://github.com/gruhn/vue-qrcode-reader/issues/354
setZXingModuleOverrides({locateFile: (path: string, prefix: any) => {if (path.endsWith('.wasm')) {return wasmFile;}return prefix + path;},
});
✨ 该部分完整Demo代码在该文件夹下:Demo (二维码实现之vue-qrcode-reader)
4. 方式二:jsQR实现
🔍Canvas的基本介绍与使用
<template><div><div class="canvasBox"><div class="box"><div class="line"></div><div class="angle"></div></div><div v-if="isUseTorch" class="box2"><div class="track" @click="openTrack"><div class="flash-light" v-if="trackStatus"><MdiFlashlightOff style="width: 36px; height: 36px" /></div><div class="flash-light" v-else><MdiFlashlight style="width: 36px; height: 36px" /></div>{{ trackStatus ? "关闭闪光灯" : "打开闪光灯" }}</div></div><div class="photo-wrap"><div class="photo" @click="handleClickFile"><el-icon size="20"><inputclass="hide_file"ref="fileRef"type="file"accept="image/*;"@change="getFile"/><PictureFilled /></el-icon></div><div class="color-[#fff]">相册</div></div></div></div>
</template><script setup lang="ts">
// https://github.com/cozmo/jsQR
import jsQR from "jsqr";
import { PictureFilled } from "@element-plus/icons-vue";
import MdiFlashlight from "~icons/mdi/flashlight";
import MdiFlashlightOff from "~icons/mdi/flashlight-off";
import { ElMessage } from "element-plus";
import _ from "lodash";const props = withDefaults(defineProps<{// environment 后摄像头 user 前摄像头exact?: "environment" | "user";// whole 全屏 half 半屏size?: "whole" | "half";// 清晰度: fasle 正常 true 高清definition?: boolean;}>(),{exact: "environment",size: "whole",definition: false,}
);
const video = ref();
const canvas2d = ref();
const canvasWidth = ref(520);
const canvasHeight = ref(500);
const c = ref();
const track = ref();
const isUseTorch = ref(false);
const trackStatus = ref(false);
const fileRef = ref();onMounted(() => {const windowWidth = window.screen.availWidth;const windowHeight = window.screen.availHeight;canvasWidth.value = windowWidth;canvasHeight.value = windowHeight;nextTick(() => {video.value = document.createElement("video");c.value = document.createElement("canvas");c.value.id = "c";c.value.width = canvasWidth.value;c.value.height = canvasHeight.value;c.value.style.width = "100%";document.querySelector(".canvasBox")?.append(c.value);openScan();});
});onUnmounted(() => {closeCamera();
});
// 开始扫描
async function openScan() {try {let width = canvasHeight.value;width = props.size === "whole" ? width : width * 0.5;width = props.definition ? width * 1.6 : width;let height = canvasWidth.value;height = props.definition ? height * 1.6 : height;const videoParam = {audio: false,video: {facingMode: { exact: props.exact }, //强制使用摄像头类型width,height,},};// 获取用户摄像头的视频流const stream = await navigator.mediaDevices.getUserMedia(videoParam);if (stream) {video.value.srcObject = stream;video.value.setAttribute("playsinline", true); //内联播放video.value.play();requestAnimationFrame(tick);// 返回所有的媒体内容流的轨道列表track.value = stream.getVideoTracks()?.[0];setTimeout(() => {// 检测摄像头是否支持闪光灯isUseTorch.value = track.value.getCapabilities().torch || null;}, 500);}} catch (error) {ElMessage.warning("设备不支持,请检查是否允许摄像头权限!");console.log("获取本地设备(摄像头)---失败", error);}
}
function closeCamera() {if (video.value.srcObject) {video.value.srcObject.getTracks().forEach((track: any) => {track.stop();});}
}
function tick() {if (video.value.readyState === video.value.HAVE_ENOUGH_DATA) {canvasHeight.value = video.value.videoHeight;canvasWidth.value = video.value.videoWidth;c.value.width = canvasWidth.value;c.value.height = canvasHeight.value;if (canvas2d.value === undefined) {canvas2d.value = c.value.getContext("2d");}canvas2d.value.drawImage(video.value,0,0,canvasWidth.value,canvasHeight.value);const imageData = canvas2d.value.getImageData(0,0,canvasWidth.value,canvasHeight.value);// 解析二维码数据const code = jsQR(imageData.data, imageData.width, imageData.height, {inversionAttempts: "dontInvert",});if (!_.isEmpty(code)) {drawLine(code.location.topLeftCorner,code.location.topRightCorner,"#FF3B58");drawLine(code.location.topRightCorner,code.location.bottomRightCorner,"#FF3B58");drawLine(code.location.bottomRightCorner,code.location.bottomLeftCorner,"#FF3B58");drawLine(code.location.bottomLeftCorner,code.location.topLeftCorner,"#FF3B58");if (code.data) {getData(code.data);}}}requestAnimationFrame(tick);
}
function drawLine(begin: any, end: any, color: string) {canvas2d.value.beginPath();canvas2d.value.moveTo(begin.x, begin.y);canvas2d.value.lineTo(end.x, end.y);canvas2d.value.lineWidth = 4;canvas2d.value.strokeStyle = color;canvas2d.value.stroke();
}
const emit = defineEmits(["on-success"]);function getData(data: string) {emit("on-success", data);closeCamera();
}function openTrack() {trackStatus.value = !trackStatus.value;track.value.applyConstraints({advanced: [{ torch: trackStatus.value }],});
}
const handleClickFile = () => {fileRef.value.click();
};
const getFile = (e: any) => {const file = e.target.files[0];emit("on-success", file);closeCamera();
};
</script><style scoped>
.flash-light {display: grid;place-content: center;margin-bottom: 6px;
}.photo-wrap {position: fixed;bottom: 2.875rem;left: 2.875rem;display: flex;flex-direction: column;align-items: center;gap: 6px;
}.photo {height: 3.125rem;width: 3.125rem;background-color: rgba(250, 250, 250, 0.8);border-radius: 50%;display: grid;place-items: center;cursor: pointer;
}.hide_file {display: none;
}page {background-color: #333333;
}.canvasBox {width: 100vw;position: relative;top: 0;bottom: 0;left: 0;right: 0;background-image: linear-gradient(0deg,transparent 24%,rgba(32, 255, 77, 0.1) 25%,rgba(32, 255, 77, 0.1) 26%,transparent 27%,transparent 74%,rgba(32, 255, 77, 0.1) 75%,rgba(32, 255, 77, 0.1) 76%,transparent 77%,transparent),linear-gradient(90deg,transparent 24%,rgba(32, 255, 77, 0.1) 25%,rgba(32, 255, 77, 0.1) 26%,transparent 27%,transparent 74%,rgba(32, 255, 77, 0.1) 75%,rgba(32, 255, 77, 0.1) 76%,transparent 77%,transparent);background-size: 3rem 3rem;background-position: -1rem -1rem;z-index: 10;background-color: #1110;
}.box {width: 11.9375rem;height: 11.9375rem;position: absolute;left: 50%;top: 50%;transform: translate(-50%, -80%);overflow: hidden;border: 0.1rem solid rgba(0, 255, 51, 0.2);z-index: 11;
}.line {height: calc(100% - 2px);width: 100%;background: linear-gradient(180deg, rgba(0, 255, 51, 0) 43%, #00ff33 211%);border-bottom: 3px solid #00ff33;transform: translateY(-100%);animation: radar-beam 2s infinite alternate;animation-timing-function: cubic-bezier(0.53, 0, 0.43, 0.99);animation-delay: 1.4s;
}.box:after,
.box:before,
.angle:after,
.angle:before {content: "";display: block;position: absolute;width: 3vw;height: 3vw;z-index: 12;border: 0.2rem solid transparent;
}.box:after,
.box:before {top: 0;border-top-color: #00ff33;
}.angle:after,
.angle:before {bottom: 0;border-bottom-color: #00ff33;
}.box:before,
.angle:before {left: 0;border-left-color: #00ff33;
}.box:after,
.angle:after {right: 0;border-right-color: #00ff33;
}@keyframes radar-beam {0% {transform: translateY(-100%);}100% {transform: translateY(0);}
}.box2 {width: 18.75rem;height: 12.5rem;position: absolute;left: 50%;top: 50%;transform: translate(-50%, -80%);z-index: 20;
}.track {position: absolute;bottom: -6.25rem;left: 50%;transform: translateX(-50%);z-index: 20;color: #fff;display: flex;flex-direction: column;align-items: center;
}
</style>
✨该部分完整Demo代码在该文件夹下:Demo (二维码实现之jsQR)
5. 总结
方式一结合vue-qrcode-reade
r的封装性更强且识别二维码速度更快。
方式二接近了vue-qrcode-reader
的底层实现过程。
实际项目开发中更推荐方式一,兼容性与稳定性会更好些。
相关文章:
移动端浏览器的扫描二维码实现(vue-qrcode-reader与jsQR方式)
1. 实现功能 类似扫一扫的功能,自动识别到画面中的二维码并进行识别,也可以选择从相册中上传。 2. 涉及到的一些插件介绍 vue-qrcode-reader 一组用于检测和解码二维码的Vue.js组件 jsQR 一个纯粹的javascript二维码阅读库,该库接收原始…...
android中调用onnxruntime框架
创建空白项目 安装Android Studio及创建空白项目参考:【安卓Java原生开发学习记录】一、安卓开发环境的搭建与HelloWorld(详细图文解释)_安卓原生开发-CSDN博客 切记:build configuration language 一定选择Groovy!官…...
【机器学习】与【数据挖掘】技术下【C++】驱动的【嵌入式】智能系统优化
目录 一、嵌入式系统简介 二、C在嵌入式系统中的优势 三、机器学习在嵌入式系统中的挑战 四、C实现机器学习模型的基本步骤 五、实例分析:使用C在嵌入式系统中实现手写数字识别 1. 数据准备 2. 模型训练与压缩 3. 模型部署 六、优化与分析 1. 模型优化 模…...
Apollo9.0 PNC源码学习之Control模块(二)
前面文章:Apollo9.0 PNC源码学习之Control模块(一) 本文将对具体控制器以及原理做一个剖析 1 PID控制器 1.1 PID理论基础 如下图所示,PID各参数(Kp,Ki,Kd)的作用: 任何闭环控制系统的首要任务是要稳、准、快的响…...
直线度测量仪发展历程!
直线度测量仪的发展历程可以概括为以下几个关键阶段: 拉钢丝法: 早期直线度测量的简单直观方法,利用钢丝受重力自然下垂的原理来测量直线度误差。 随着机械设备的大型化和测量精度要求的提高,该方法逐渐无法满足要求,正…...
09-spring的bean创建流程(一)
文章目录 spring中bean的创建流程finishBeanFactoryInitialization(beanFactory)beanFactory.preInstantiateSingletons();getMergedLocalBeanDefinition(beanName);流程实现FactoryBean接口,里面的对象实例化过程 spring中bean的创建流程 finishBeanFactoryInitialization(be…...
spring中基于setting和构造器的注入方式
Spring中可以通过setting和构造器两种方式进行依赖注入。 1.基于setting的注入方式(Setter Injection): 实现方式:在类中添加对应的属性以及对应的setter方法,在配置文件中使用<property>元素进行注入。 示例代码…...
爬虫基本原理?介绍|实现|问题解决
爬虫基本原理: 模拟用户行为: 网络爬虫(Web Crawler)是一种自动化的程序,它模拟人类用户访问网站的方式,通过发送HTTP/HTTPS请求到服务器以获取网页内容。 请求与响应: 爬虫首先构建并发送带有…...
DevOps的原理及应用详解(六)
本系列文章简介: 在当今快速变化的商业环境中,企业对于软件交付的速度、质量和安全性要求日益提高。传统的软件开发和运维模式已经难以满足这些需求,因此,DevOps(Development和Operations的组合)应运而生&a…...
手撸 串口交互命令行 及 AT应用层协议解析框架
在嵌入式系统开发中,命令行接口(CLI)和AT命令解析是常见的需求。CLI提供了方便的调试接口,而AT命令则常用于模块间的通信控制。本文将介绍如何手动实现一个串口交互的命令行及AT应用层协议解析框架,适用于FreeRTOS系统…...
Redis几种部署模式介绍
Redis 提供了几种不同的部署模式,以满足不同的使用场景和可用性需求。这些模式包括单机模式、主从复制、哨兵模式和集群模式。下面我将简要介绍每种模式的特点和用途: 单机模式: 描述:单个 Redis 服务器实例运行在一台机器上&…...
【STM32HAL库学习】定时器功能、时钟以及各种模式理解
一、文章目的 记录自己从学习了定时器理论->代码实现使用定时->查询数据手册,加深了对定时器的理解以及该过程遇到了的一些不清楚的知识。 上图为参考手册里通用定时器框图,关于定时器各种情况的工作都在上面了,在理论学习和实际应用后…...
3588麒麟系统硬解码实战
目录 安装rockchip-mpp deb 查找头文件 .pro文件添加 检查库是否已安装 error: stdlib.h: No such file or directory ffmpeg 查找ffmpeg路径: 查找FFmpeg库和头文件的位置 使用pkg-config工具查找FFmpeg路径 ok的ffmpeg配置: ffmpeg查看是否支持libx264 ffmpeg …...
十二 nginx中location重写和匹配规则
十二 location匹配规则 ^~ ~ ~* !~ !~* /a / 内部服务跳转 十三 nginx地址重写rewrite if rewrite set return 13.1 if 应用环境 server location -x 文件是否可执行 $args $document_rot $host $limit_rate $remote_addr $server_name $document_uri if …...
python的视频处理FFmpeg库使用
FFmpeg 是一个强大的多媒体处理工具,用于录制、转换和流式传输音频和视频。它支持几乎所有的音频和视频格式,并且可以在各种平台上运行。FFmpeg 在 Python 中的使用可以通过调用其命令行工具或使用专门的库如 ffmpeg-python。以下是详细介绍如何在 Python 中使用 FFmpeg,包括…...
接口测试时, 数据Mock为何如此重要?
一、为什么要mock 工作中遇到以下问题,我们可以使用mock解决: 1、无法控制第三方系统某接口的返回,返回的数据不满足要求 2、某依赖系统还未开发完成,就需要对被测系统进行测试 3、有些系统不支持重复请求,或有访问…...
未授权与绕过漏洞
1、Laravel Framework 11 - Credential Leakage(CVE-2024-29291)认证泄漏 导航这个路径storage/logs/laravel.log搜索以下信息: PDO->__construct(mysql:host 2、 Flowise 1.6.5 - Authentication Bypass(CVE-2024-31621&am…...
云原生周刊:Kubernetes 十周年 | 2024.6.11
开源项目推荐 Kubernetes Goat Kubernetes Goat 是一个故意设计成有漏洞的 Kubernetes 集群环境,旨在通过交互式实践场地来学习并练习 Kubernetes 安全性。 kube-state-metrics (KSM) kube-state-metrics 是一个用于收集 Kubernetes 集群状态信息的开源项目&…...
ClickHouse内幕(1)数据存储与过滤机制
本文主要讲述ClickHouse中的数据存储结构,包括文件组织结构和索引结构,以及建立在其基础上的数据过滤机制,从Part裁剪到Mark裁剪,最后到基于SIMD的行过滤机制。 数据过滤机制实质上是构建在数据存储格式之上的算法,所…...
1.Mongodb 介绍及部署
MongoDB 是一个开源的文档导向数据库,采用NoSQL(非关系型数据库)的设计理念。MongoDB是一个基于分布式文件存储的数据库。 分布式文件存储是一种将文件数据分布式的存储在多台计算机上。MongoDB是一款强大的文档导向数据库,适合处…...
Java 技巧:如何获取字符串中最后一个英文逗号后面的内容
在日常的Java编程中,处理字符串是非常常见的任务之一。有时我们需要从一个字符串中截取特定部分,例如获取最后一个英文逗号后的内容。这篇文章将详细介绍如何使用Java来实现这一需求,并提供一个示例代码来演示其实现过程。 需求分析 假设我们…...
玩转微服务-GateWay
目录 一. 背景二. API网关1. 概念2. API网关定义3. API网关的四大职能4. API网关分类5. 开源API网关介绍6. 开源网关的选择 三. Spring Cloud Gateway1. 文档地址2. 三个核心概念3. 工作流程4. 运行原理4.1 路由原理4.2 RouteLocator 5. Predicate 断言6. 过滤器 Filter6.1. 过…...
Amortized bootstrapping via Automorphisms
参考文献: [MS18] Micciancio D, Sorrell J. Ring packing and amortized FHEW bootstrapping. ICALP 2018: 100:1-100:14.[GPV23] Guimares A, Pereira H V L, Van Leeuwen B. Amortized bootstrapping revisited: Simpler, asymptotically-faster, implemented. …...
【人工智能】ChatGPT基本工作原理
ChatGPT 是由 OpenAI 开发的一种基于深度学习技术的自然语言处理模型,它使用了名为 GPT(Generative Pre-trained Transformer)的架构。GPT 模型是一种基于 Transformer 架构的预训练语言模型,它通过大量的文本数据进行预训练&…...
The First项目报告:Stargate Finance重塑跨链金融的未来
Stargate Finance是一个基于LayerZero协议的去中心化金融平台,自2022年3月由LayerZero Labs创建以来,一直致力于为不同区块链之间的资产转移提供高效、低成本的解决方案。凭借其独特的跨链技术和丰富的DeFi服务,Stargate Finance已成为连接不…...
Python魔法之旅-魔法方法(22)
目录 一、概述 1、定义 2、作用 二、应用场景 1、构造和析构 2、操作符重载 3、字符串和表示 4、容器管理 5、可调用对象 6、上下文管理 7、属性访问和描述符 8、迭代器和生成器 9、数值类型 10、复制和序列化 11、自定义元类行为 12、自定义类行为 13、类型检…...
公司面试题总结(三)
13.说说你对 BOM 的理解,常见的 BOM 对象你了解哪些? BOM (Browser Object Model),浏览器对象模型, ⚫ 提供了独立于内容与浏览器窗口进行交互的对象 ⚫ 其作用就是跟浏览器做一些交互效果 ⚫ 比如如何进行页面的后退&…...
PLSQL 报错 could not locate oci.dll
0、确保PLSQL已激活。 1、在PLSQL安装包内搜索oci.dll,如果没有搜到需要下载 链接:https://pan.baidu.com/s/1HOfKAEFfuAGYACjfcwqJ1g 提取码:6evh 2、打开PLSQL,设置oci.dll的路径 ps:PLSQL安装包 链接ÿ…...
【方案+源码】智慧园区建设方案
智慧园区一体化运营管理平台建设方案旨在通过集成先进的信息技术,实现园区的智能化、高效化、绿色化管理。该平台整合了物联网、大数据、云计算等技术,为园区提供全方位、一体化的运营服务。 方案包括智能监控、能源管理、安防系统、停车管理、物业管理等…...
Java操作数据库 —— JDBC ① 基础篇
我走我的路,有人拦也走,没人陪也走 —— 24.6.7 JDBC JDBC就是使用Java语言操作关系型数据库的一套API 一、JDBC简介 JDBC 概念 JDBC 就是使用Java语言操作关系型数据库的一套API 全称:(Java DataBase Connectivity)意为Java 数据库连接 JDBC 本质: ①…...
公司让做网站违法/十大技能培训机构排名
Apple在 WWDC 上宣布,将向iOS 14.6、iPadOS 14.6、macOS 11.4 和tvOS 14.6及以上的用户提供空间音频和无损音频。 Apple 表示,在发布时将会提供超过 2000 万首无损质量的歌曲,到 2021 年底,整个 Apple Music 目录中将会提供超过 …...
做商城网站要什么手续/赣州seo外包
导语:算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。下面是YJBYS小编收集整理的有关计算机算法的英语词汇,欢迎参考!Median and Selection 中位数Generating Pe…...
一个公司多个网站做优化/推广平台
1. net start/stop w3svc这个command主要用于开启/停止服务 www service this command is used to start or stop www service. it commonly uses to reset w3svc after the IIS configuration is modified. notes: 不要w3svc和当个website搞混了。如果net stop w3sv…...
四方区企业型网站建设/百度一下官网首页百度
网易vip邮箱多少钱?163邮箱名字怎么起高端?邮箱名字的后缀每家邮箱都是固定的,但是前缀是可以设置的,无论是短位、寓意邮箱号都可以注册,tom邮箱每个月都会有特殊靓号的推出。 163vip邮箱登陆入口: 极致安…...
中国建设银行官网网站首页/做网站的流程与步骤
推荐阅读: 这套Github上40Kstar学习笔记,可以帮你搞定95%以上的Java面试 毫不夸张的说,这份SpringBoot学习指南能解决你遇到的98%的问题 给跪了!这套万人期待的 SQL 成神之路PDF,终于开源了 Java 5 新特性 1. 泛型…...
做网站公司联系方式页面/沧州网站建设推广
https://blog.csdn.net/qq_40996741/article/details/108654408...