简介:一份面向计算机相关专业毕业设计或小程序开发初学者的完整项目源码。该系统涵盖用户权限管理、仓库出入库与预警、采购审批及供应商管理、销售扣减与退货入库等核心业务,并配套首页库存展示、销售金额折线图、应用模块与个人中心等页面,有助于理解企业级管理系统的完整业务流程与微信小程序端实现方式。资源共519个文件,包括102个js逻辑文件、94个json配置、93个wxss样式、81个wxml页面结构及67个ts脚本等,另含界面图片与说明文档,包体仅1.5MB,结构清晰便于按模块研读。已有898人学习下载,适合用于毕业设计参考、项目二次开发或小程序技能提升。压缩包内目录组织规整,可直接导入开发者工具运行调试,帮助读者从需求分析到代码实现形成系统认知。
1. 为什么企业生产管理要先落在微信小程序上
制造型企业的数字化改造,最容易死在第一步:不是因为算法不够先进,而是因为一线工人根本不愿意用。传统 PC 端 MES 系统功能再全,车间里没有空闲的电脑,或者说有电脑也没人愿意跑到工位旁录入数据,于是生产报工、工序流转、设备点检这些核心动作,最终都退化成了纸质单据。微信小程序恰好是解决这个问题的天然载体,用户不需要额外安装 App,扫码即用,轻量化到一个界面只做一件事,学习成本接近零。而企业生产管理系统真正的难点不在于前端页面漂不漂亮,而在于如何把多部门、多角色的流程串起来,同时保证数据准确和操作可追溯。
一个基于微信小程序的企业生产管理系统,典型做法是小程序做员工端和看板端,后端用 Spring Boot 这类框架提供 API,数据库负责存储生产工单、库存、质量等核心数据。小程序端负责的是高频、轻量的操作,比如扫码报工、工序确认、异常上报,而后台负责的是重逻辑和权限控制。这种架构的好处是把最困难的车间落地问题交给最容易被接受的工具,同时不让业务逻辑被小程序的包体积和渲染性能绑架。适合的人群很明确:制造企业的 IT 部门、做数字化转型的服务商、以及正在做相关课题开发的工程师。你不需要从零发明一套理念,只需要把成熟的生产管理流程,按照微信小程序的技术约束重新组织一遍。
2. 微信小程序端的功能拆法与登录态设计
2.1 先梳理生产管理的核心业务模块
企业生产管理系统的需求通常分散在计划、执行、质量、设备、库存五个域,但落到小程序端,真正适合移动操作的不是全部,而是与现场行为强相关的部分。我一般会把功能拆成四组:工单执行组(接收任务、报工、流转)、质量组(巡检、不合格品记录)、物料组(领料、退料、盘点)、设备组(点检、维修申报)。这种分法最直接的理由是,每个组对应一类角色,每个角色在小程序里只需要看到自己的待办事项,不需要理解整体业务。
在数据库设计层面,这些功能会映射到几张核心表:生产工单表(含工单号、产品编码、计划数量、状态)、工序流转表(含工单号、工序号、操作人、开始时间、结束时间)、报工记录表(含工单号、工序号、报工数量、工时、设备号)、质量检验表(含工单号、检验项、结果、检验员)、库存操作表(含物料编码、类型、数量、关联单号)。表与表之间通过工单号或物料编码关联,不搞复杂的继承关系,这样后续排查数据问题时最省力。
小程序端的每个业务模块,内部结构都按照微信小程序的标准分包模式组织。分包的意义在于,生产管理小程序常常有几十个页面,如果全部塞进主包,首屏加载会明显变慢。建议主包只放登录、首页、个人中心三个页面,其余按业务分组放到 subpackages 里。比如 production 分包放工单执行相关页面,quality 分包放质量相关页面,这样用户从首页进入某个功能时才动态加载对应代码,体验会顺畅很多。
2.2 微信登录与后端 Token 体系如何衔接
小程序的登录不能直接使用微信返回的 code 作为会话凭证,code 的有效期只有五分钟且只能使用一次。正确做法是用 wx.login 获取临时 code,然后调用后端接口换取自定义登录态。这个自定义登录态我建议使用 JWT,而不是简单的 session 存储,因为生产管理系统常常需要支持多端并发,JWT 的无状态特性在扩容和权限校验时更友好。
wx.login({ success: async (res) => { if (res.code) { const loginRes = await request({ url: '/api/auth/login', method: 'POST', data: { code: res.code } }); const { token, userInfo } = loginRes.data; wx.setStorageSync('token', token); wx.setStorageSync('userInfo', userInfo); } } });后端在收到 code 后,先调用微信的 jscode2session 接口拿到 openid 和 session_key,再根据 openid 查询或创建用户记录,最后生成 JWT 返回给前端。这里的核心参数是 JWT 的过期时间,生产管理系统不建议像普通电商那样设置七天,因为车间操作涉及品质追溯,一般建议两小时过期,配合小程序的静默续期机制来维持会话。所谓静默续期,是指小程序端在每次请求拦截器里判断 token 剩余有效期,如果小于三十分钟,就主动调用刷新接口获取新 token。
请求拦截器是保证后端接口安全的关键一环,因为小程序前端的所有网络请求都从同一个工具函数发出,在这里统一注入 token 和错误处理最有效率。每次请求前从 storage 中读取 token,放到 header 的 Authorization 字段里;遇到 401 响应时,清除本地登录状态并跳转到登录页,而不是让每个页面各自处理错误。这样做的额外好处是,当后端接口出现权限问题时,你可以在拦截器里统一收集日志,定位是哪些接口被异常访问。
wx.login 的常见坑与处理
使用 wx.login 时机要放在 App.onLaunch 中还是页面中,这个细节直接影响登录成功率。如果放在 onLaunch 中,可能遇到页面已经渲染但登录还没完成的情况,所以我会在页面级调用 wx.login,或者用 Promise 封装后统一 await。另一个容易忽略的点是,同一个微信用户在不同小程序下的 openid 不同,如果你在开发环境中切换过 AppID,用户数据可能发生错乱,解决方法是后端以 openid 作为用户唯一标识,而不是使用微信昵称或手机号。
3. 从零搭建生产管理小程序项目的完整步骤
3.1 创建项目与基础目录结构设计
搭建微信小程序企业生产管理系统,推荐直接使用微信开发者工具创建原生小程序项目,而不是先跑 uniapp 再编译到微信端。原因是生产管理系统依赖大量微信原生能力,比如扫码、蓝牙打印、地图定位,原生项目对这些 API 的支持最直接。项目名称建议使用英文小写加连字符,比如 production-mp,因为小程序的项目名会出现在编译输出路径中,中文名在 CI/CD 流水线中容易造成编码问题。
# 使用微信开发者工具的命令行工具创建项目 cli create --project production-mp --appid wx你的AppID --type miniProgram # 项目根目录结构示意 production-mp/ ├── app.js ├── app.json ├── app.wxss ├── pages/ │ ├── login/ │ ├── workbench/ │ └── profile/ ├── subpackages/ │ ├── order/ │ ├── quality/ │ ├── material/ │ └── device/ ├── utils/ │ ├── request.js │ └── auth.js └── static/ └── icons/app.json 是全局配置文件,在这个文件里声明页面路由、窗口样式和分包信息。生产管理系统的页面数量通常在二十到三十个之间,因此分包配置必须在这里完成。一个值得注意的参数是lazyCodeLoading: "requiredComponents",这个配置可以让小程序按需注入代码,减少启动时间,尤其当页面引用了大量自定义组件时,效果非常明显。
3.2 用 code 换 token 的完整链路与后端接口约定
前端在获取到 wx.login 返回的 code 之后,请求后端接口,后端通过 HTTP 请求微信接口换区 openid,这是整个登录链路的关键环节。代码示例如下:
# 后端使用 Java 实现 jscode2session 的典型写法 String url = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code"; RestTemplate restTemplate = new RestTemplate(); String response = restTemplate.getForObject(url, String.class); // 响应示例: {"openid":"oXXXXX","session_key":"tXXXXX","expires_in":7200}这里最需要重视的参数是 expires_in,微信返回的 session_key 有效期与小程序前后端交互时长没有直接关系,它只在需要解密用户敏感信息时才会用到。如果你的系统需要获取用户手机号,需要在小程序端通过 button 组件配合open-type="getPhoneNumber"获取手机号 code,再由后端调用接口换取真实手机号,而不是尝试用 session_key 手动解密,后者是过时的做法。
// 小程序端获取手机号的推荐实现 <button open-type="getPhoneNumber" bindgetphonenumber="handlePhoneNumber"> 获取手机号 </button> handlePhoneNumber(e) { if (e.detail.code) { request({ url: '/api/auth/phone', method: 'POST', data: { code: e.detail.code } }).then(res => { this.setData({ phone: res.data.phone }); }); } }在生产环境中,这个手机号通常会与工号绑定,作为用户登录后的补充身份信息,用于计件工资计算或考核追溯。注意在真机调试时,获取手机号必须使用已认证的小程序账号,开发版和体验版有不同限制,通常开发版可以获取到测试手机号,体验版则必须要真实手机号授权。
3.3 首页工作台与角色权限控制
生产管理系统的小程序首页通常不叫首页,而叫工作台。工作台的核心是让不同角色登录后看到不同的功能入口,工人看到的是我的任务和扫码报工,车间主任看到的是生产进度和异常处理,仓库管理员看到的是领料和入库。这个差异用前端条件渲染可以实现,但不建议所有权限逻辑都放在前端,因为小程序代码可以被反编译,前端权限只能作为体验优化,真正的权限拦截必须在后端完成。
// 工作台菜单的动态渲染 const roleMenus = { worker: ['task', 'report', 'quality_report'], supervisor: ['task_manage', 'progress', 'exception', 'statistics'], warehouse: ['material_in', 'material_out', 'inventory'] }; function getMenusByRole(role) { return roleMenus[role] || ['task']; }菜单配置建议放在后端接口返回,而不是写死在前端,这样当管理后台调整权限时,小程序端不需要发版就能同步更新。权限粒度上,生产管理系统建议至少做到按钮级别,因为同一页面不同角色可能需要看不同字段。比如报工页面,工人只能看自己的报工记录,车间主任可以看整个班组的报工记录,这个过滤逻辑放在后端的 SQL 查询中通过传入的 user_id 或 department_id 参数来完成。
4. 生产管理系统的后端接口设计与核心参数调优
4.1 工单分配与任务列表接口的性能考量
小程序端每次进入任务列表页时,都会请求后端获取工单数据,这个接口的响应速度直接影响工人的使用耐心。我在设计这个接口时,会强制要求后端返回的数据包含分页信息,而不是一次返回全量数据。一个常见的参数设计是 page 和 pageSize,pageSize 默认设置为 20,前端采用触底加载的方式翻页。这里很多人会犯一个错误:翻页后直接拼接数组而不去重,导致重复数据出现,正确做法是使用工单号作为唯一键进行去重。
-- 工单列表查询的核心 SQL,注意状态过滤和分页 SELECT wo.work_order_no, wo.product_code, wo.plan_qty, wo.completed_qty, wo.status, wo.priority, wo.deadline FROM work_order wo WHERE wo.status = #{status} AND wo.workshop_id = #{workshopId} ORDER BY wo.priority DESC, wo.deadline ASC LIMIT #{offset}, #{pageSize}这个查询要注意的细节是排序字段的组合,先用 priority 降序保证紧急工单排在最前,再用 deadline 升序让最早到期的工单靠前。如果工单表数据量超过十万条,建议在 status 和 workshop_id 上建立联合索引,否则随着数据增长,查询会越来越慢。在小程序端的任务列表页,还要考虑下拉刷新的频率,一般设置为用户手指松开后立即请求,并且要避免在短时间内重复触发,通过 loading 状态锁来防止重复请求。
4.2 报工接口的事务与数据一致性方案
报工是企业生产管理系统中数据变更最频繁的操作,因为它直接关联到工单完成数量的累计和员工计件工资的核算。后端实现报工接口时,必须使用数据库事务来保证一致性。一个完整的报工动作包含三个操作:插入报工记录、更新工单完成数量、更新员工当日产量,这三个操作必须全部成功或全部失败。
@Transactional(rollbackFor = Exception.class) public ReportResult reportProduction(ReportRequest request) { // 1. 校验工单是否存在且状态为进行中 WorkOrder order = workOrderMapper.selectByNo(request.getOrderNo()); if (order == null || !"IN_PROGRESS".equals(order.getStatus())) { throw new BusinessException("工单不存在或不在执行状态"); } // 2. 插入报工记录 ReportRecord record = new ReportRecord(); record.setOrderNo(request.getOrderNo()); record.setProcessNo(request.getProcessNo()); record.setQuantity(request.getQuantity()); record.setWorkerId(request.getWorkerId()); reportMapper.insert(record); // 3. 乐观锁更新工单完成数量 int updated = workOrderMapper.increaseCompletedQty( request.getOrderNo(), request.getQuantity(), order.getCompletedQty()); if (updated == 0) { throw new OptimisticLockException("工单数据已被其他人修改,请刷新重试"); } return new ReportResult(true, "报工成功"); }这个接口的关键点在于第 3 步使用了乐观锁机制,更新工单完成数量时,SQL 会拼接WHERE completed_qty = #{oldCompletedQty},如果两个工人同时报工,后提交的人会更新失败并收到提示。这样做比使用 synchronized 锁或悲观锁更高效,因为它不会阻塞正常请求,只在冲突真正发生时让一个请求失败重试。微信小程序端的用户在收到失败提示后,只需要点击重试按钮即可,因为前端的请求数据没有丢失。
报工接口还有一个细节值得说明,就是操作时间和设备信息的获取。操作时间不要依赖前端传入的时间戳,而应该在后端使用服务器当前时间,因为前端设备的时间可能不准确,会导致报表统计出现误差。设备信息在扫码报工时自动获取,如果在没有设备码的场景下报工,可以将设备字段置空,但需要在报工记录中添加备注,方便后续追溯。
报工记录与计件工资的联动
生产管理系统中报工数据往往会直接关联到工资核算,所以报工记录一旦提交,应该不允许随意修改。如果确实发生误操作,不建议提供修改功能,而是提供红冲功能,即新建一条负数数量的报工记录来冲抵原来的记录,同时在备注中写明冲抵原因。这种做法在实际生产中称为红冲单,是财务和人事都认可的规范流程,也符合操作可追溯的要求。
4.3 小程序端网络请求的封装与超时参数设置
小程序的网络请求必须封装在统一的工具类中,因为生产管理系统涉及大量接口调用,统一管理 header、超时时间、错误提示才能保证一致的用户体验。前端封装时你可能会遇到this.setData({ userinfo.nickname: that.data.nickname })这样的变量命名困惑,其本质是对象键名不能动态拼接的问题,正确做法是先构建完整对象再 setData。
// 封装的请求工具,注意超时时间和错误处理 const request = (options) => { const token = wx.getStorageSync('token'); return new Promise((resolve, reject) => { wx.request({ url: `${BASE_URL}${options.url}`, method: options.method || 'GET', data: options.data || {}, timeout: 15000, header: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, success: (res) => { if (res.statusCode === 200) { resolve(res.data); } else if (res.statusCode === 401) { wx.removeStorageSync('token'); wx.redirectTo({ url: '/pages/login/index' }); } else { wx.showToast({ title: res.data.message || '请求失败', icon: 'none' }); reject(res); } }, fail: (err) => { wx.showToast({ title: '网络异常,请检查网络后重试', icon: 'none' }); reject(err); } }); }); };超时时间 15 秒是我在实际项目中常用的值,对于生产管理系统的普通接口来说,如果超过 15 秒还没返回,大概率是后端出了性能问题,这时候继续等待没有意义。但有一个例外:批量导入或导出 Excel 的接口,这类操作在数据量较大时可能耗时较长,如果也用 15 秒超时,大概率会失败。处理方式是为这类接口单独设置 timeout 参数,或者改为异步任务模式,用户提交请求后先返回任务编号,处理完成后通过模板消息或小程序订阅消息通知用户。> 提示:在小程序管理后台可以配置 request 合法域名,开发阶段可以勾选不校验合法域名,但发布前必须配置真实域名且要求 HTTPS。
5. 小程序端的图片、附件与长列表处理
5.1 拍照上传生产单据与 wx.env.USER_DATA_PATH 的正确用法
生产管理场景中,工人经常需要拍照上传生产单据或质量问题照片。微信小程序的拍照上传流程相对简单,先通过 wx.chooseMedia 获取临时文件路径,然后调用 wx.uploadFile 将文件传输到后端。这里最容易出问题的是临时文件和持久化文件的区别,临时文件路径在小程序运行期间有效,退出后就会被清理,所以需要在上传成功后删除本地临时文件。
// 拍照并上传附件 async function uploadAttachment() { const res = await wx.chooseMedia({ count: 1, mediaType: ['image'], sourceType: ['camera', 'album'] }); const tempFilePath = res.tempFiles[0].tempFilePath; const savedPath = `${wx.env.USER_DATA_PATH}/attachment_${Date.now()}.jpg`; // 将临时文件保存到用户数据目录 await wx.getFileSystemManager().saveFile({ tempFilePath: tempFilePath, filePath: savedPath }); // 执行上传 wx.uploadFile({ url: `${BASE_URL}/api/file/upload`, filePath: savedPath, name: 'file', formData: { orderNo: 'MO20250101001', type: 'quality_issue' }, success: (uploadRes) => { const result = JSON.parse(uploadRes.data); wx.showToast({ title: '上传成功', icon: 'success' }); } }); }这里有一个在生产环境中非常实用的参数:wx.env.USER_DATA_PATH。这个路径是微信为每个小程序分配的用户数据存储目录,App 卸载后数据会随之清除。如果你需要把附件持久化保存,不要依赖这个路径,而是要确保后端接收到文件后存入自己的文件服务器或对象存储中。在本地调试时,你也可以通过文件管理器直接打开这个目录查看已保存的文件,方便确认上传逻辑是否正确。
5.2 长按拖拽排序与多图预览的界面实现
车间主管在调整生产任务优先级时,常常希望直接通过拖拽调整任务列表的顺序,而不是进入编辑页面修改优先级数字。微信小程序原生的 movable-area 和 movable-view 可以实现简单的拖拽排序,但它在长列表上性能不太理想。更讨巧的方案是通过模拟,使用触摸事件记录手指位置,通过计算当前手指移动的偏移量来动态更新列表项的位置。
// 长按拖拽排序的核心逻辑 onLongPress(e) { const index = e.currentTarget.dataset.index; this.setData({ dragIndex: index, isDragging: true }); }, onTouchMove(e) { if (!this.data.isDragging) return; const touchY = e.touches[0].clientY; const currentIndex = this.data.dragIndex; const items = this.data.taskList; // 根据手指位置判断是否需要交换 const targetIndex = Math.floor(touchY / this.data.itemHeight); if (targetIndex !== currentIndex && targetIndex >= 0 && targetIndex < items.length) { const newItems = [...items]; const temp = newItems[currentIndex]; newItems[currentIndex] = newItems[targetIndex]; newItems[targetIndex] = temp; this.setData({ taskList: newItems, dragIndex: targetIndex }); } }拖拽排序实现后,需要在小程序端把新的顺序同步到后端,否则页面刷新又会恢复原状。同步时机不应该放在每次拖拽交换时,而是放在 touchend 事件中一次性提交最终顺序,这样可以减少请求次数。后端接口只需要接收一个工单号数组,按照数组顺序更新每个工单的 sort 字段即可。图片预览则使用 wx.previewImage,在查看质量问题时按住图片可以放大观察细节,这个功能是质量检验人员的刚需,配合长按保存图片的功能,可以方便地把问题截图发到内部工作群。
5.3 长列表渲染的优化策略:避免下拉卡顿
生产管理系统的任务列表有可能超过一百条,如果直接用 setData 渲染全部数据,小程序页面会明显卡顿。微信官方建议使用 recycle-view 组件实现长列表优化,但它在自定义组件中的使用有额外的依赖成本。对于生产管理系统,我建议优先采用分页加载加数据节流的方案:每次只渲染二十条数据,滚动到底部时加载下一页,并在数据更新时使用this.setData({ list: [...this.data.list, ...newData] })的方式追加数据。
// 分页加载的代码片段 onReachBottom() { if (this.data.loading || this.data.isEnd) return; this.setData({ loading: true }); const nextPage = this.data.page + 1; request({ url: '/api/workorder/list', data: { page: nextPage, pageSize: 20, status: 'IN_PROGRESS' } }).then(res => { const newList = res.data.list; this.setData({ list: this.data.list.concat(newList), page: nextPage, isEnd: res.data.isEnd, loading: false }); }); }关键参数是 isEnd,后端根据 pageSize 和当前已返回条数来判断是否还有更多数据。当后端返回的条数小于 pageSize 时,说明已经到末页,前端可以把 isEnd 置为 true,后续不再触发请求。这种数据加载模式还有一个额外的好处,就是减少内存占用量,微信小程序在 Android 设备上的内存限制比较严格,一次加载过多数据容易导致页面被系统回收。
6. 质量追溯查询与导出 Excel 的落地技巧
6.1 通过工单号追溯全流程记录的界面设计
企业生产管理系统的价值在出现质量问题时最能体现。当客户反馈某批次产品存在缺陷,管理者需要快速定位是哪个工序出了问题、哪个设备产生的、哪个工人操作的。在小程序端实现追溯查询,通常的做法是提供一个扫码入口,扫描产品上的二维码或输入工单号,然后以时间线的形式展示该工单从投料、生产、检验到入库的全部操作记录。
// 追溯查询的请求参数 request({ url: '/api/trace/query', method: 'POST', data: { workOrderNo: 'MO20250101001', productCode: 'P10086', batchNo: 'B20250101' } }).then(res => { this.setData({ timeline: res.data.timeline, qualityRecords: res.data.qualityRecords, equipmentLogs: res.data.equipmentLogs }); });后端在接到追溯请求后,需要关联查询多张表,这是一个相对重的操作。追溯接口的 SQL 通常会涉及 work_order、process_record、quality_inspection、equipment_log 四张表的联查。为了提升查询速度,建议在产品编码和批次号上建立联合索引,同时把查询结果做一次对象组装后返回给前端,避免前端发起多次请求。
6.2 将报工与质量数据导出为 Excel 的实用方案
微信小程序本身没有直接导出 Excel 的能力,常规做法是小程序端发起导出请求,后端生成 Excel 文件后返回文件下载地址,再通过小程序端的wx.downloadFile下载到手机,或者通过openDocument直接打开预览。考虑到微信小程序包体积有限,不建议引入 xlsx 这样的第三方库在前端生成 Excel,而是用后端的 Apache POI 或 EasyExcel 来生成。
// 后端生成 Excel 的简化实现 EasyExcel.write(outputStream, ReportExportVO.class) .sheet("报工记录") .doWrite(reportList);导出接口需要注意一个性能问题:当导出数据量超过一万条时,同步导出会让用户等待很久,而且容易超时。比较好的做法是设定导出上限,默认单次导出不超过五千条,并且在前端页面上明确提示用户按日期范围筛选后再导出。如果必须支持大数据量导出,可以改成异步导出,用户点击导出后后端立即返回一个任务 ID,小程序轮询任务状态,处理完成后推送下载链接。
导出参数的筛选逻辑
在导出接口的参数设计上,生产管理系统的核心筛选条件通常包括三个维度:时间范围、工单状态、产品编码。时间范围不要用字符串拼接,而是使用时间戳或 ISO 格式,后端统一转换为标准时间。导出文件的命名建议包含日期和筛选条件,例如20250601_报工明细_全部.xlsx,这样用户下载多个文件时不会混淆。> 提示:使用wx.downloadFile下载文件时,需要在小程序后台配置 downloadFile 合法域名,否则真机环境下会提示域名不合法无法下载。
6.3 微信订阅消息在异常通知中的应用
生产管理系统的一个重要场景是异常通知,例如设备故障、质量不合格、工单超时。传统做法是依赖工人主动刷新页面查看,但这样时效性太差。微信小程序的订阅消息可以解决这个问题,用户在小程序内授权订阅后,后端可以在特定事件触发时向用户推送一次性订阅消息。订阅消息的授权时机很关键,不能一进小程序就弹窗索要授权,而应该放在用户执行某类操作时,例如点击上报异常后顺便请求订阅,这样用户接受的意愿更高。
// 订阅消息的授权请求 wx.requestSubscribeMessage({ tmplIds: ['模板ID_设备异常通知'], success: (res) => { if (res['模板ID_设备异常通知'] === 'accept') { // 用户同意订阅,允许后端推送该类型的消息 } } });订阅消息每一条都需要用户确认授权,这对系统设计提出了个很实际的要求:将不同类型的通知拆分成多个模板,用户在需要的场景下授予对应的模板权限,不要把所有通知合并成一个模板。通过订阅消息在异常发生的第一时间触达相关人员,生产管理系统的价值会有显著提升。在实际部署时,上述所有能力还需要经过真机调试、体验版测试、线上版本发布三个环节的验证,确保在不同版本微信客户端上的兼容性。
本文还有配套的精品资源,点击获取