新闻详情

新闻详情

首页 / 资讯中心 / 详情

微信小程序拍照授权与保存到本地:camera组件实战

发布时间:2026/9/30 9:23:25来源:尧图网络
微信小程序拍照授权与保存到本地:camera组件实战
微信小程序里做拍照功能这件事说难不难说简单也容易掉坑。我前后在三个项目里做过拍照上传模块从最早的wx.chooseImage一路写到今天的camera组件加CameraContext最深的感受是真正把人卡住的从来不是按下快门那一下而是授权链路和保存到本地这四个字的歧义。有人说的保存到本地是存进手机系统相册有人说的其实是存进小程序自己的沙箱文件系统这两者的 API、授权 scope、失败分支完全不一样教程里混着讲新手照着抄必然翻车。这篇就把微信小程序拍照功能、授权、保存到本地这三件事拆开讲透从方案选型到代码封装再到真机上踩过的那些坑尽量给到能直接抄的程度。不管你是刚接手小程序的新手还是写过几版但总在真机上被用户投诉的同学应该都能找到能用的部分。1. 先把需求拆清楚拍照、授权、保存到本地到底是哪三个问题很多人一上来就问拍照怎么存到本地这句话里其实藏着三个独立的技术问题找谁拿摄像头画面、拿画面之前要过几道授权、拿到的图往哪儿放。这三个问题的解法互相独立耦合在一起想就会乱。我习惯先把它们拆成三条线画在纸上再逐个击破。1.1 保存到本地的两种理解与对应 API本地在小程序语境里有两种完全不同的含义先确认清楚再动手能省掉一半返工。第一种是手机系统相册用户能在微信外面打开相册看到这张图。对应 API 是wx.saveImageToPhotosAlbum需要的授权 scope 是scope.writePhotosAlbum。这条路的特点是图片进了系统相册小程序删了图还在用户可以自己管理。第二种是小程序沙箱文件系统文件存在微信给这个小程序分配的私有目录里只有这个小程序自己能读写用户看不到。对应 API 是wx.getFileSystemManager().saveFile配合wx.env.USER_DATA_PATH指定路径。这条路适合做草稿、离线缓存、待上传队列。目标位置核心 API需要的授权用户可见容量限制手机系统相册wx.saveImageToPhotosAlbumscope.writePhotosAlbum可见受手机存储限制小程序沙箱FileSystemManager.saveFile无需额外授权不可见单小程序单用户约 10MB临时文件拍照结果takePhoto / chooseMedia 自动生成取决于来源不可见本次启动周期内有效这张表我建议贴在项目文档里团队里再有人说保存到本地的时候先问一句是上面哪一行。1.2 三套授权 scope 的分工与差异微信小程序的授权机制其实不复杂但细节差异很容易记混。拍照相关的 scope 有三个行为各不相同。scope.camera管的是摄像头使用权。用camera组件做自定义取景框时必须先拿到它否则组件直接黑屏或者触发binderror报insertCamera:fail auth deny之类的错误。这个 scope 的特点是不会自动弹窗需要开发者主动调wx.authorize引导这一点跟很多人的直觉相反。scope.writePhotosAlbum管的是往系统相册写图。这个 scope 相对友好直接调wx.saveImageToPhotosAlbum时微信会自动帮你弹授权框。但如果你提前用wx.authorize({scope: scope.writePhotosAlbum})先申请一遍反而可能拿到一个被拒的结果后面的保存直接失败。我的做法是不做前置申请直接调保存接口失败了再走补救分支。还有一个隐形的坑wx.chooseMedia的sourceType: [album]从相册选图不需要任何授权用户主动选图本身就是授权行为但sourceType: [camera]调起系统相机拍照需要scope.camera。同一个 API不同参数授权要求不一样这个细节在文档里藏得很深。1.3 两种拍照方案的选型对照明确了授权范围接下来是拍照本身的技术路线。目前主流就两条camera组件方案和wx.chooseMedia调起系统相机方案。camera组件方案是把取景画面嵌在自己的页面里你可以随意设计快门按钮、闪光灯开关、美颜入口甚至在上面叠 AI 识别的框。代价是原生组件页面布局和层级要额外处理需要自己管授权真机和工具的差异比较大。wx.chooseMedia方案是直接调起系统相机应用用户拍完点确认回到小程序。优点是三行代码搞定缺点是 UI 完全不可控用户还能顺手从相册挑一张。对比项camera 组件wx.chooseMediaUI 可控性完全可控完全不可控代码量较多需处理授权与生命周期极少授权要求必须 scope.camerasourceType 为 camera 时同样需要连续拍照体验顺畅无需页面跳转每次都要进出系统相机用户造假可能无法选择已有照片可切到相册选图适合场景打卡、证件、试穿、扫码通用上传、头像更换我的经验是需要连续拍、需要对画面做叠加、需要防止用户传图代替拍照就用 camera 组件只是普通上传直接 chooseMedia 别折腾。2. 授权链路的完整实现从首次询问到永久拒绝授权这块是出 bug 最多的地方因为它的状态是跨会话的——用户昨天拒绝了一次今天再进来状态还在。很多代码只在首次流程里测试通过一到老用户身上就崩。这里把状态机完整拆一遍。2.1 用 wx.getSetting 判断没问过和被拒过wx.getSetting返回的authSetting对象是整条链路的地基它有三种状态必须区分开authSetting[scope.camera] undefined从来没问过可以直接wx.authorize弹窗authSetting[scope.camera] true已授权直接用authSetting[scope.camera] false明确拒绝过再调wx.authorize会静默失败不弹任何框。第三种情况是最容易被忽略的。用户点了一次拒绝你后面再怎么调wx.authorize都像石沉大海日志里只有一行authorize:fail auth deny没有任何用户感知。所以判断逻辑必须写成没问过和被拒过两条完全不同的分支。function checkAuthState(scope) { return new Promise((resolve) { wx.getSetting({ success: (res) { const setting res.authSetting || {}; const value setting[scope]; resolve({ granted: value true, neverAsked: value undefined }); }, // getSetting 本身极少失败兜底当作未询问处理 fail: () resolve({ granted: false, neverAsked: true }) }); }); }注意fail分支的兜底策略。我见过有人把fail当成被拒绝结果在某些异常机型上直接跳到引导去设置页用户一脸茫然。2.2 wx.authorize 的正确调用位置与常见误用wx.authorize只能在从未询问过的时候用这是它唯一的有效场景。而且它有个隐藏约束必须在用户交互的调用链里触发页面onLoad里直接调部分基础库版本上不会弹窗。所以正确的时机是用户点了拍照按钮之后再去申请。还有一个常见误用是在 app.js 里统一申请所有权限。这个思路在浏览器里可能行得通在小程序里行不通——一次性申请一堆 scope用户很容易全部点拒绝然后整个小程序功能全废。分开申请、用到才申请通过率明显更高。function authorizeScope(scope) { return new Promise((resolve) { wx.authorize({ scope, success: () resolve(true), fail: () resolve(false) // 用户点了拒绝或系统异常 }); }); }2.3 wx.openSetting 与 button open-type 的配合用户明确拒绝后唯一能救回来的路径是引导他去设置页重新打开也就是wx.openSetting。这里有个版本分水岭基础库 2.3.0 之后wx.openSetting必须由用户点击行为触发否则调用无效。所以比起wx.showModal回调里偷偷调wx.openSetting我更推荐用button open-typeopenSetting这个原生按钮能力它天生就在用户点击链路上最稳。button open-typeopenSetting bindopensettingonOpenSetting classauth-btn 去设置页开启相机权限 /buttononOpenSetting(e) { // 不同基础库返回结构略有差异统一回读一次最保险 wx.getSetting({ success: (res) { if (res.authSetting[scope.camera]) { this.setData({ cameraReady: true }); } } }); }实测有个细节用open-typeopenSetting打开设置页用户开了权限返回后页面不会自动刷新状态一定要在onShow或者回调里重新getSetting一次否则用户会以为没生效反复点。2.4 隐私协议检查2023 年之后必须补的一课这一条是最近两年新增的很多老教程里没有。小程序平台对隐私接口做了统一管控相机、相册相关的调用都被纳入了用户隐私保护指引的覆盖范围。现在的流程变成两道门先过隐私协议再过 scope 授权。第一道门是后台配置。需要在小程序管理后台的用户隐私保护指引里勾选声明使用摄像头、相册仅写入等对应能力并且写清楚用途。没配置的话真机上调用相关接口会直接失败开发者工具里表现还不太一样很容易漏掉。第二道门是运行时。如果用户没同意过隐私协议触发隐私接口时会走微信官方的弹窗用户点同意后继续。如果你想自定义这个弹窗比如自己设计引导语可以用wx.onNeedPrivacyAuthorization加wx.requirePrivacyAuthorize接管然后在自己的弹窗里调用resolve({ event: agree })。// 在合适的时机主动触发一次隐私授权检查 if (wx.requirePrivacyAuthorize) { wx.requirePrivacyAuthorize({ success: () { /* 用户已同意可以继续业务 */ }, fail: () { /* 用户拒绝自行降级处理 */ } }); }注意这段代码要做能力判断老版本基础库上wx.requirePrivacyAuthorize是 undefined直接调会报错。我的习惯是所有新增 API 都套一层if (wx.xxx)一劳永逸。2.5 封装一个能直接抄的授权工具函数把上面四个小节拼起来就是一个完整的授权闭环。我通常封成一个公共模块页面里只调一个requestScope。// utils/auth.js function checkAuthState(scope) { return new Promise((resolve) { wx.getSetting({ success: (res) { const v (res.authSetting || {})[scope]; resolve({ granted: v true, neverAsked: v undefined }); }, fail: () resolve({ granted: false, neverAsked: true }) }); }); } function authorizeScope(scope) { return new Promise((resolve) { wx.authorize({ scope, success: () resolve(true), fail: () resolve(false) }); }); } function gotoSetting(scope, tipText) { return new Promise((resolve) { wx.showModal({ title: 需要相关权限, content: tipText || 请在设置页中开启权限后重试, confirmText: 去设置, success: (res) { if (!res.confirm) return resolve(false); wx.openSetting({ success: (s) resolve(s.authSetting[scope] true), fail: () resolve(false) }); } }); }); } export function requestScope(scope, tipText) { return checkAuthState(scope).then(({ granted, neverAsked }) { if (granted) return true; if (neverAsked) return authorizeScope(scope); return gotoSetting(scope, tipText); }); }调用侧就非常干净const ok await requestScope(scope.camera, 拍照需要使用摄像头请在设置中开启); if (!ok) return; // 继续拍照逻辑有一点要提醒gotoSetting里用showModal的success回调触发wx.openSetting在很多基础库版本上是可以拉起的但并不是所有版本都保证。如果你想把稳定性拉满就在 modal 确认后跳转到页面上的去设置按钮让用户再点一次。3. 拍照功能的落地方案授权通了接下来才是真正拍。这一章把camera组件方案和wx.chooseMedia方案都写一遍顺便处理压缩和连拍这两个必须面对的问题。3.1 camera 组件自定义取景页的完整结构camera是原生组件页面结构要稍微讲究一点。我一般把取景区做成全屏或者固定比例的块下面的工具栏跟在后面不要用绝对定位压在上面——虽然现在很多版本支持同层渲染可以在camera上面放普通view但在部分低版本机型上仍然会失效工具栏被盖住点不到。view classpage camera wx:if{{cameraReady}} classcamera device-position{{devicePosition}} flash{{flash}} resolutionhigh bindinitdoneonCameraInit binderroronCameraError /camera view wx:else classplaceholder正在准备摄像头.../view view classtoolbar button sizemini bindtapswitchCamera翻转/button button classshutter bindtaphandleTakePhoto拍照/button button sizemini bindtaptoggleFlash闪光灯/button /view /viewdevice-position只在front和back之间切flash可选auto、on、off、torchtorch是常亮手电模式晚上拍文档很好用resolution控制分辨率档位取值low、medium、high默认medium。binderror一定要接否则摄像头被别的应用占用了、设备不支持、权限出问题页面就是一片黑用户完全不知道发生了什么。onCameraError(e) { console.error(camera error, e.detail); wx.showToast({ title: 摄像头不可用, icon: none }); // 常见授权丢了、设备被占用、开发者工具没开摄像头 }3.2 CameraContext.takePhoto 的参数取舍与连拍加锁拍照动作通过wx.createCameraContext()拿到上下文再调takePhoto。const ctx wx.createCameraContext(); handleTakePhoto() { if (this.taking) return; // 连拍加锁 this.taking true; ctx.takePhoto({ quality: high, success: (res) { this.setData({ previewPath: res.tempImagePath }); this.afterCapture(res.tempImagePath); }, fail: (err) { console.error(takePhoto fail, err); wx.showToast({ title: 拍照失败请重试, icon: none }); }, complete: () { this.taking false; } }); }quality有三档直接决定文件体积。我的经验值high出来的图在 2MB 到 4MB 之间normal大概 800KB 到 1.5MBlow基本在 300KB 以内。如果只是做人脸打卡或者文字识别normal完全够用上传速度快一大截。连拍加锁这个细节非常关键。用户手快连点三下快门takePhoto会并发触发三次部分安卓机上会出现回调错乱甚至直接崩掉摄像头。用一个布尔量锁住complete里解锁是最简单有效的办法。另外拍照返回的tempImagePath是临时文件在小程序本次启动周期内有效退出小程序后可能被系统清理。如果你的业务逻辑里是先拍一堆最后统一上传记得拍完立刻转存到沙箱别指望临时文件活很久。3.3 wx.chooseMedia 的极简路径与适用边界不需要自定义 UI 的场景一个函数就够了。wx.chooseMedia({ count: 1, mediaType: [image], sourceType: [camera], // 只调起相机不给相册入口 sizeType: [compressed], // 让系统做一轮压缩 camera: back, success: (res) { const file res.tempFiles[0]; // file.tempFilePath、file.size、file.width、file.height }, fail: (err) { // 用户取消也是走 failerrMsg 里含 cancel if (!/cancel/i.test(err.errMsg)) { console.error(chooseMedia fail, err); } } });这里有几个实用参数值得记住sourceType只写[camera]时用户无法从相册选图适合打卡类的不可替代性拍照sizeType: [compressed]会让系统先压一道体积通常能降一半mediaType: [image, video]可以同时支持拍视频返回结构里会有duration和thumbTempFilePath。用户取消也会走 fail这是新手最容易误判的地方日志里天天刷errMsg: chooseMedia:fail cancel其实根本不是错误。用正则把cancel过滤掉日志会干净很多。3.4 图片压缩、方向与内存占用的处理不管走哪条路拿到图只要涉及上传或者长期保存压缩都是绕不开的。wx.compressImage是官方提供的能力参数是src、quality0 到 100、compressedWidth、compressedHeight。wx.compressImage({ src: tempPath, quality: 70, compressedWidth: 1280, // 宽高建议同时指定只传一个部分机型不生效 compressedHeight: 1280, success: (res) console.log(压缩后, res.tempFilePath), fail: (err) console.error(err) });质量给 70 到 80 是个比较甜的区间肉眼几乎看不出区别体积能降到原来的三分之一。宽度压到 1280 对绝大多数业务都够做海报或者打印的另说。方向问题要有心理准备。手机拍出来的 JPEG 通常带 EXIF 方向标记camera组件返回的结果一般已经处理好了但从相册选的老照片、或者经过多轮转存之后方向有可能不对。如果你后续要用canvas去画它比如加时间水印可能出现图片躺倒。稳妥做法是先wx.getImageInfo拿orientation和真实宽高再决定 canvas 的绘制参数。还有一点是内存。大图在 iOS 上解码会占大量内存连续拍十几张再统一预览很容易触发页面白屏甚至小程序重载。我的做法是拍完立刻压缩只保留压缩后的路径用于列表预览原图路径只在需要上传时临时持有。4. 保存到本地的两条路径与容量管理回到最开始那个歧义问题。这一章把两条路都走一遍顺带处理最烦人的容量和清理。4.1 写入小程序沙箱wx.env.USER_DATA_PATH 与 saveFile沙箱路径的关键是wx.env.USER_DATA_PATH这是小程序分配给你的私有目录根路径。注意是全大写的 USER_DATA_PATH。网上有不少代码写成wx.env.user_data_path拿到的是undefined拼出来的路径变成undefined/photo_1.jpgsaveFile直接报fail the path is invalid然后你对着文档看半天也看不出问题在哪。const fs wx.getFileSystemManager(); function saveToSandbox(tempFilePath) { const dir ${wx.env.USER_DATA_PATH}/photos; // 子目录要先建重复建会报错用 try 吞掉 try { fs.accessSync(dir); } catch (e) { fs.mkdirSync(dir, true); } const target ${dir}/photo_${Date.now()}.jpg; fs.saveFile({ tempFilePath, filePath: target, success: (res) { console.log(已保存到沙箱, res.savedFilePath); }, fail: (err) { console.error(saveFile fail, err); // 高频错误超出 10MB 上限 } }); }saveFile的filePath参数是在较新的基础库上才支持指定的2.10.0 起再早的版本只能由系统自动生成路径。如果你要兼容很老的基础库把最低版本号往上提一提会更省事。有个细节容易踩指定了filePath保存的文件不会出现在getSavedFileList的返回里。因为它直接落在了USER_DATA_PATH下属于普通文件得用fs.readdir来列用fs.unlink来删。而getSavedFileList和removeSavedFile管理的是saveFile不指定路径时保存的那批文件。两套体系别混着用否则会出现我明明存了文件列表却是空的这种诡异现象。4.2 写入系统相册wx.saveImageToPhotosAlbum 的失败分支存相册的代码看着简单失败分支才是重头戏。function saveToAlbum(filePath) { wx.saveImageToPhotosAlbum({ filePath, success: () { wx.showToast({ title: 已保存到相册, icon: none }); }, fail: async (err) { const msg err.errMsg || ; if (/auth deny|auth denied|authorize/i.test(msg)) { // 情况一小程序层 scope 被拒 const ok await requestScope( scope.writePhotosAlbum, 保存图片需要相册权限请在设置中开启 ); if (ok) saveToAlbum(filePath); } else if (/cancel/i.test(msg)) { // 情况二用户在授权弹窗上直接点了取消静默处理 return; } else if (/system deny|系统/i.test(msg)) { // 情况三系统层面微信没有相册权限 wx.showModal({ title: 无法保存, content: 请在手机设置中允许微信访问相册, showCancel: false }); } else { wx.showToast({ title: 保存失败请重试, icon: none }); } } }); }这三种失败要分开处理因为它们需要用户去的地方完全不同第一种去小程序的授权设置页第三种要去手机系统设置里改微信的权限第二种什么都不用做。我见过不少代码把三种情况都提示成保存失败用户反复点也没用最后直接给一星。另外两个实践经验保存动作最好紧跟在用户的点击行为之后中间别插太多异步操作部分安卓机型对调用时机比较敏感保存成功后不要同时弹 toast 和 modal一次一个就够了否则弹窗叠弹窗体验很差。4.3 10MB 上限下的容量统计与清理策略小程序沙箱的本地文件存储上限是10MB是单个用户单个小程序的额度。听起来不小但一张原图 3MB三张就满了。超出之后saveFile会报一个很明确的错误大意是文件存储容量已达上限。所以只要用了沙箱就必须配套一套清理逻辑。统计容量的做法是遍历目录累加文件大小。function calcSandboxUsage() { const fs wx.getFileSystemManager(); const dir ${wx.env.USER_DATA_PATH}/photos; return new Promise((resolve) { fs.readdir({ dirPath: dir, success: (res) { let total 0; res.files.forEach((name) { try { const stat fs.statSync(${dir}/${name}); if (stat.isFile stat.isFile()) total stat.size; } catch (e) {} }); resolve(total); // 单位字节 }, fail: () resolve(0) }); }); }清理策略我一般用双保险一是数量上限比如最多保留 50 张超了就按时间删最早的二是容量上限比如超过 8MB 就主动清到 6MB 以下。留 2MB 余量是为了避免边界情况下存不进去。function cleanupIfNeeded(maxCount 50, maxBytes 8 * 1024 * 1024) { const fs wx.getFileSystemManager(); const dir ${wx.env.USER_DATA_PATH}/photos; let files []; try { files fs.readdirSync(dir); } catch (e) { return; } const list files.map((name) { const full ${dir}/${name}; let size 0, mtime 0; try { const st fs.statSync(full); size st.size || 0; mtime st.lastModifiedTime || 0; } catch (e) {} return { full, size, mtime }; }).sort((a, b) a.mtime - b.mtime); // 老的在前 let total list.reduce((s, f) s f.size, 0); let count list.length; while (list.length (total maxBytes || count maxCount)) { const f list.shift(); try { fs.unlinkSync(f.full); } catch (e) {} total - f.size; count - 1; } }这段代码建议放在小程序启动时执行一遍或者在每次保存成功后跑一次。别等用户真的存满了才处理那时候用户已经在投诉了。5. 踩坑实录与排查速查表最后一章全是实战里攒下来的东西很多是文档上不会写、但真机上一定会遇到的。5.1 高频报错对照表现象 / 报错大概率原因处理方式camera 组件一片黑无任何提示未获得 scope.camera或开发者工具未授权摄像头走完整授权链路工具里检查摄像头权限insertCamera:fail auth deny同上用户拒绝过相机权限引导至设置页重新开启takePhoto fail: operateCamera:fail摄像头被其他应用占用或页面已隐藏检查 onHide 时机提示用户关闭其他应用saveImageToPhotosAlbum:fail auth denyscope.writePhotosAlbum 被拒或系统相册权限关闭分情况引导见 4.2 节saveFile:fail the path is invalidUSER_DATA_PATH 拼错、目录不存在检查大小写先 mkdirSync 建目录saveFile:fail exceed max size沙箱超出 10MB执行清理逻辑chooseMedia fail: cancel用户主动取消不是错误日志里过滤掉别当异常上报保存成功但相册里找不到安卓相册未刷新或保存到了非默认相册目录提示用户下拉刷新相册或重启相册应用首次进入不弹隐私协议后台未配置用户隐私保护指引去后台补齐声明拍照后列表白屏、小程序重载同时持有多张原图内存爆了拍完立即压缩只保留压缩图5.2 开发者工具与真机的表现差异这一块必须单独说因为它导致过太多次工具上好好的一上线就炸。开发者工具对摄像头是模拟的画面清晰度、闪光灯效果、takePhoto的耗时都和真机差得远。闪光灯相关的逻辑在工具上基本测不出来torch常亮模式在工具里也不一定表现正常。分辨率差异同样明显。工具里拿到的图往往偏小你以为 200KB 的图传得很好真机上一张 3MB接口直接超时。相册保存的行为在工具和真机上也不同。真机上还叠了一层系统权限用户可能在系统层级关掉微信访问相册这时小程序层面的 scope 还是true但保存依然失败——这也是我在 4.2 节里把系统拒绝单独列一个分支的原因。结论很简单拍照相关的功能开发者工具只用来验证代码逻辑通不通真机验证必须覆盖 iOS 和安卓各至少一台最好再加一台低端安卓机。低端机上的内存和性能问题旗舰机上是复现不出来的。5.3 几个能省时间的工程习惯第一条所有新增 API 都做能力判断。隐私相关的接口、wx.compressImage、resolution属性这些都在不同版本上线写代码时随手套一层if (wx.xxx)能帮你挡掉一批低版本报错。第二条相机页的生命周期要管住。camera组件在页面隐藏时会停止采集但如果你有onCameraFrame这类持续回调记得在onHide里主动停掉不然切到后台还在跑耗电会被用户感知到。第三条临时文件和持久文件分开管理。我习惯在文件名上做区分tmp_前缀的是本次会话用完就删keep_前缀的是用户明确要保留的。清理逻辑只动tmp_的用户的资料不会被误删。第四条拍照路径尽量只在一处生成。拍照、压缩、保存、上传这四步如果散落在不同页面各写一遍很快就会版本不一致。我一般把capture相关的逻辑收在一个 service 里页面只负责调 UI。最后分享一个小技巧如果业务对图片真实性有要求比如考勤打卡可以在camera的取景画面上叠一个当前时间的view让时间戳和水印框直接出现在画面里配合sourceType: [camera]限制入口基本能挡住用相册老图顶替的情况。这个方案比事后在图片上打水印更简单用户也没有绕过的空间。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

STM32F103 流水灯三种写法对比 + HAL 库按键中断控制(暂停/恢复) 2026/9/30 11:28:40

STM32F103 流水灯三种写法对比 + HAL 库按键中断控制(暂停/恢复)

STM32F103 流水灯三种写法对比 HAL 库按键中断控制(暂停/恢复) 写在前面:这次要交的是"用 HAL 库 按键中断控制流水灯"。 但在动手之前,我把同一个流水灯用三种方式各写了一遍 —— 直接操作寄存器、调用标准外设库、…

阅读更多 →
ESXi 7.0 服务器虚拟化部署全流程:从U盘引导到管理网络配置 2026/9/30 11:28:25

ESXi 7.0 服务器虚拟化部署全流程:从U盘引导到管理网络配置

简介:这是一份面向服务器运维、虚拟化管理员与IT基础架构人员的PDF技术资料,聚焦VMware vSphere ESXi 7.0从零开始的完整安装部署流程。读者可据此在物理服务器上快速搭建裸金属虚拟化平台,并掌握管理网络、IPv4地址等基础配置,适…

阅读更多 →
生产排产PMC的4种经典算法:最短工期、最早交货期、Slack、CR值 2026/9/30 11:28:18

生产排产PMC的4种经典算法:最短工期、最早交货期、Slack、CR值

很多PMC每天最头疼的,不是不会排计划,而是所有人都觉得自己的订单最急。 销售说客户催得厉害,老板说这个客户不能丢,生产说换线太频繁,采购说关键料还没到,仓库说半成品堆不下。 最后PMC夹在中间&#xff0…

阅读更多 →
合并两个有序链表:迭代、递归与原地合并的面试全攻略 2026/9/30 11:28:18

合并两个有序链表:迭代、递归与原地合并的面试全攻略

1. 这道题为什么值得反复刷:合并有序链表的本质与常见误区 如果只让我推荐三道链表入门题,LeetCode 21“合并两个有序链表”一定在其中。它的题干极短:给定两个升序链表 list1 和 list2 ,把它们合并成一个新的升序链表并返回。…

阅读更多 →
RL-10-赵-Actor-Critic03:DPG03【Deterministic Actor-Critic】【梯度优化:θₜ₊₁=θₜ+αᶿ∇ᶿμ(sₜ)(∇ₐqᵤ(sₜ,a))|a=μ(sₜ)】 2026/9/30 11:28:11

RL-10-赵-Actor-Critic03:DPG03【Deterministic Actor-Critic】【梯度优化:θₜ₊₁=θₜ+αᶿ∇ᶿμ(sₜ)(∇ₐqᵤ(sₜ,a))|a=μ(sₜ)】

二、The algorithm of deterministic actor-critic 基于policy gradient,the gradient-ascent algorithm就可以最大化 J ( θ ) J(\theta)

阅读更多 →
【从零写一个CAD 03】三个 double 值得单独一个类吗:把视图变换抽成 View 2026/9/30 11:28:11

【从零写一个CAD 03】三个 double 值得单独一个类吗:把视图变换抽成 View

🫧 励志不掉头发的内向程序员:个人主页✨️ 个人专栏: 《C语言》《Linux学习》🌅偶尔悲伤,偶尔被幸福所完善 👓️博主简介: 文章目录前言一、先看看这几个数现在住在哪二、这三个数的问题不是"多"&#xff0…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉