记录一下自己开发中遇到的问题方便再次碰到时能快速解决。目录前端树形菜单结构多页面切换缓存异步处理实际使用下载小程序UniappQuestionsQ1:AutoCAD绘制逻辑没有问题绘制出来的结果和预期相差很多错误原因及解决方案Q2、uniapp扫描二维码get请求通过路由传参时参数有#号等特殊字符串Q3、前端取值一直报未定义Q4、在移动端判断时一直不能正确进入Q5、记录一下之前的加载dwg格式的cad图纸Q6、向windows系统部署时没有U盘硬盘辅助常用工具前端树形菜单结构splitpanes组件splitpanes :horizontalthis.$store.getters.device mobile classdefault-theme pane size16 el-col div classhead-container el-input v-modelprojectName placeholder请输入培训项目 clearable sizesmall prefix-iconel-icon-search stylemargin-bottom: 20px / /div div classhead-container el-tree :dataprojectOptions :propsdefaultProps :expand-on-click-nodefalse :filter-node-methodfilterNode reftree node-keyid default-expand-all highlight-current node-clickhandleNodeClick / /div /el-col /pane /splitpanes多页面切换缓存//类似rediskey-value使用时记得及时清空 //赋值 localStorage.setItem(examAnswers, JSON.stringify(this.userAnswers)); //取值 localStorage.removeItem(examAnswers);异步处理async/await当一个异步任务的执行需要依赖另一个异步任务的结果时我们一般会将两个异步任务嵌套起来。async和await是 ES2017 中引入的、用于简化 JavaScript 异步编程的语法糖。它们的核心目的是让我们能用同步代码的写法来编写异步操作从而让代码更清晰、更易读、更易维护。async关键字用于声明一个函数是异步函数。await关键字只能在async函数内部使用。它用于等待一个 Promise 对象完成 。当await一个 Promise 时它会暂停当前async函数的执行直到这个 Promise 完成。await只会暂停它所在的async函数的执行而不会阻塞整个 JavaScript 线程。浏览器的主线程仍然可以处理其他事件如 UI 渲染、用户交互。如果多个异步操作之间没有依赖关系不要一个一个地await这样会导致不必要的等待。应该让它们并行执行。// 串行执行总耗时 ~2000ms async function serial() { const result1 await fetch(url1); // 假设耗时1000ms const result2 await fetch(url2); // 假设耗时1000ms } // 并行执行总耗时 ~1000ms async function parallel() { const promise1 fetch(url1); const promise2 fetch(url2); const [result1, result2] await Promise.all([promise1, promise2]); }实际使用async loadClassDetail(classId) { try { const params { trainingClassId: classId }; // 一次性并发执行所有不相关的API调用 const [res1, coursesRes, dataRes, contentRes, noticeRes, examRes] await Promise.all([ getInfoByTrainingClassId(classId), // 班级基本信息 getMajorInfoById(classId), // 培训课程 getMajorFilesInfoById(classId), // 培训资料 listByClassId(params), // 培训计划 listByStudentIdAndClassId(params), // 通知 getExamScheduleByStudentId(params) // 考试安排 ]); // 处理班级基本信息 const info res1.data; this.classDetail { category: { special: 特设培训, regular: 常规培训, custom: 定制培训 } [info.signUpCategory], project: info.trainingProjectName, classNumber: info.trainingClassCode, className: info.trainingClassName, year: info.trainingYear, term: info.trainingSession, startDate: info.startDate, endDate: info.endDate, trainingRegion: info.trainingRegion, trainingAddress: info.trainingAddress, trainingLocation: info.trainingVenue, actualTrainingLocation: info.actualTrainingVenue, headTeacher1: info.headTeacher1Name, headTeacher2: info.headTeacher2Name, }; // 处理培训课程 const coursesInfo coursesRes.data; this.classDetail.courses coursesInfo.map(item ({ name: item.courseName, type: item.courseType, })); // 处理培训资料 const dataInfo dataRes.data; this.classDetail.trainingMaterials dataInfo.map(item ({ name: item.fileName, filePath: item.filePath, })); // 处理培训内容 const contentInfo contentRes.rows; this.classDetail.trainingContent contentInfo.map(item ({ location: item.scheduleAddress, teacher: item.teacherName || , startTime: item.scheduleStartTime, endTime: item.scheduleEndTime, })); // 处理通知 const noticeInfo noticeRes.rows; this.classDetail.notifications noticeInfo.map(item ({ publishTime: item.sendTime, content: item.noticeContent, })); // 处理考试安排 const examInfo examRes.rows; this.classDetail.examArrangement examInfo.map(item ({ startTime: item.examStartTime, endTime: item.examEndTime, duration: item.examDuration, address: item.examLocation, method: item.examPathway, passScore: item.examPassScore, releaseImmediately: item.ifReleaseResultsImmediately 1, allowRetake: item.ifAgreeAutomaticExam 1, examTimes: item.examTimes, })); this.$forceUpdate(); } catch (error) { console.error(加载班级详情失败:, error); } }, loadAllDicts() { const dictPromises [ getDicts(pxzx_zjlx), getDicts(rylx), getDicts(pub_xb), getDicts(pub_mz), getDicts(pxzx_xl), getDicts(administrative_area), getDicts(unit_nature), getDicts(training_type), getDicts(payment_status), getDicts(record_status), ]; Promise.all(dictPromises) .then((responses) { this.dictData.zjlxOptions responses[0].data; this.dictData.userTypeOptions responses[1].data; this.dictData.sexOptions responses[2].data; this.dictData.nationOptions responses[3].data; this.dictData.educationOptions responses[4].data; this.dictData.administrativeAreaOptions responses[5].data; this.dictData.unitNatureOptions responses[6].data; this.dictData.trainingTypeOptions responses[7].data; this.dictData.paymentStatusOptions responses[8].data; this.dictData.recordStatusOptions responses[9].data; console.log(this.dictData); }) .catch((error) { console.error(字典数据加载失败:, error); }); },上传FileUpload refpaymentVoucherFileUpload :fileType[ jpg, jpeg, png, gif, pdf, doc, docx, ] :fileSize10 :limit1 :isShowTiptrue upload-successhandleVoucherUploadSuccess upload-errorhandleVoucherUploadError upload-finishhandleVoucherUploadFinish / div v-ifuploading classuploading-tip正在上传.../div /** * 处理凭证文件上传成功 */ handleVoucherUploadSuccess(response, file, fileList) { this.uploading false; this.$message.success(上传成功); // 更新表单数据 this.transferPayFormData.voucherUrl response.url; this.transferPayFormData.voucherName file.name; // 更新表单数据将完整URL转换为相对路径格式 if (response.url) { // 提取相对路径 const urlObj new URL(response.url, window.location.origin); this.transferPayFormData.voucherUrl urlObj.pathname; } }, /** * 处理凭证上传失败 */ handleVoucherUploadError(err, file, fileList) { this.uploading false; this.$message.error(上传失败请重试); }, /** * 处理凭证上传完成 */ handleVoucherUploadFinish(response, file, fileList) { this.uploading false; },里面有获取上传路径和对于路径的处理部分。下载vueel-button typeprimary sizesmall clickdownloadTemplate 下载模板 /el-button downloadTemplate() { const filePath /static/实操考试信息.xlsx; this.$download.saveAs(filePath, 实操考试信息导入模板.xlsx); },uniapp中下载与vue不同不能直接调用浏览器的savefile方法下载文件需要处理对于后端不能下载的内容可以使用html2canvas实现下载downloadFile(item) { uni.downloadFile({ url: item.filePath, success: (res) { if (res.statusCode 200) { // 下载成功 #ifdef H5 // H5环境下文件已经下载到浏览器默认目录不需要保存直接提示 uni.showToast({ title: 下载成功, icon: success }); #else // 非H5环境保存到本地 uni.saveFile({ tempFilePath: res.tempFilePath, success: function(saveRes) { uni.showToast({ title: 下载成功, icon: success }); }, fail: function(err) { console.error(保存文件失败:, err); uni.showToast({ title: 保存文件失败, icon: none }); } }); #endif } }, fail: (err) { uni.showToast({ title: 下载失败, icon: none }); console.error(下载失败:, err); } }); }小程序Uniapponload方法中可以获取页面加载时的内容比如另一个页面跳转传过来的参数也可以在这里面执行数据的预加载。onLoad(option) { console.log(页面参数:, option); // 获取 url 和 classId 参数 const url option.url || ; const id option.classId || ; this.tempClassId id; },QuestionsQ1:AutoCAD绘制逻辑没有问题绘制出来的结果和预期相差很多// 计算角度参数 double jj layer.fwj - baseAngle; double deltaAngle Math.Abs(layer.fwj - layer.angle) * Math.PI / 180.0; // 计算地层厚度 double layerThickness layer.EndDepth - layer.StartDepth; // 计算偏移量 double dx layerThickness * Math.Cos(deltaAngle); double dy layerThickness * Math.Sin(deltaAngle); // 根据方位角调整方向 if (jj 0) { dx -Math.Abs(dx); dy -Math.Abs(dy); } else { dx -Math.Abs(dx); dy Math.Abs(dy); } // 计算终点坐标 Point3d layerEnd new Point3d( currentPoint.X dx, currentPoint.Y dy, 0 );错误原因及解决方案计算deltaAngle 时忘记转弧度Math.PI / 180.0直接拿着算出来的值进行计算Q2、uniapp扫描二维码get请求通过路由传参时参数有#号等特殊字符串对前端发送的请求进行转码将请求转为16进制//示例 //转码前 http://localhost:9090/#/pages/internalTrainingCourse/checkIn/checkIn?classCheckinId3 //转码后 http://localhost:8001/createLogoQRCode?urlhttp%3A%2F%2Flocalhost%3A9090%2F%23%2Fpages%2FinternalTrainingCourse%2FcheckIn%2FcheckIn%3FclassCheckinId%3D3Q3、前端取值一直报未定义从this.$router后面链式获取参数时一直未定义解决一层一层取值进入到需要拿值得那一层Q4、在移动端判断时一直不能正确进入// 清理字符串去除可能的引号 let examType String(this.tempExamType); // 去除首尾的引号 examType examType.replace(/^[]|[]$/g, ).trim(); console.log(清理后的examType:, examType); if (examType 1) { console.log(调用正常考试接口); apiCall classExam(this.tempTrainClassId); } else if (examType 2) { console.log(调用模拟考试接口); apiCall classExamSimulation(this.tempTrainClassId); } else { console.log(未知考试类型默认调用正常考试接口, examType); apiCall classExam(this.tempTrainClassId); }Q5、记录一下之前的加载dwg格式的cad图纸这个之前搞出来一次很长时间没搞忘记了具体解决办法用autocad或者其他工具将拿到的dwg格式的图纸首先去除掉图纸上面的杂乱干扰信息然后另存为dxf格式用global mapper打开dxf文件导出为我这里使用的cesiumjs加载的格式选择的kml/kmz然后使用 Cesium.KmlDataSource.load 加载Q6、向windows系统部署时没有U盘硬盘辅助1、powershell调出命令2、net use \\192.168.33.70\C$ /user:用户名 密码 登录3、robocopy F:\AboutProduction\1 \\ip\C$\ay_server\ay_tran 2.txt 复制文件(文件夹将文件名换为/E)装操作系统给空服务器安装Linux参考地址https://www.cnblogs.com/mozhiyan/articles/19247933/ventoy常用工具因为之前系统盘损坏过想了想还是把一些常用好用的工具整理一下放在这里记录一下。//阿里图标库 https://www.iconfont.cn/search/index?searchTypeiconpage1fromCollection-1 //一个免费的抠图工具 https://tool.lu/cutout/ //科学计算器 https://www.desmos.com/scientific?langzh-CN //ai导航 https://www.aig123.com/#term-27-43 //项目管理工具--甘特图--zzplan https://zz-plan.com/login //cesium官网 https://cesium.com/learn/ //Ant Design Vue https://2x.antdv.com/components/overview-cn/ //uniapp https://uniapp.dcloud.net.cn/api/ //简历制作 https://www.jianliben.com/account/login?redirecthttps://www.jianliben.com/profile
日常开发及bug总结
发布时间:2026/5/18 12:13:04
记录一下自己开发中遇到的问题方便再次碰到时能快速解决。目录前端树形菜单结构多页面切换缓存异步处理实际使用下载小程序UniappQuestionsQ1:AutoCAD绘制逻辑没有问题绘制出来的结果和预期相差很多错误原因及解决方案Q2、uniapp扫描二维码get请求通过路由传参时参数有#号等特殊字符串Q3、前端取值一直报未定义Q4、在移动端判断时一直不能正确进入Q5、记录一下之前的加载dwg格式的cad图纸Q6、向windows系统部署时没有U盘硬盘辅助常用工具前端树形菜单结构splitpanes组件splitpanes :horizontalthis.$store.getters.device mobile classdefault-theme pane size16 el-col div classhead-container el-input v-modelprojectName placeholder请输入培训项目 clearable sizesmall prefix-iconel-icon-search stylemargin-bottom: 20px / /div div classhead-container el-tree :dataprojectOptions :propsdefaultProps :expand-on-click-nodefalse :filter-node-methodfilterNode reftree node-keyid default-expand-all highlight-current node-clickhandleNodeClick / /div /el-col /pane /splitpanes多页面切换缓存//类似rediskey-value使用时记得及时清空 //赋值 localStorage.setItem(examAnswers, JSON.stringify(this.userAnswers)); //取值 localStorage.removeItem(examAnswers);异步处理async/await当一个异步任务的执行需要依赖另一个异步任务的结果时我们一般会将两个异步任务嵌套起来。async和await是 ES2017 中引入的、用于简化 JavaScript 异步编程的语法糖。它们的核心目的是让我们能用同步代码的写法来编写异步操作从而让代码更清晰、更易读、更易维护。async关键字用于声明一个函数是异步函数。await关键字只能在async函数内部使用。它用于等待一个 Promise 对象完成 。当await一个 Promise 时它会暂停当前async函数的执行直到这个 Promise 完成。await只会暂停它所在的async函数的执行而不会阻塞整个 JavaScript 线程。浏览器的主线程仍然可以处理其他事件如 UI 渲染、用户交互。如果多个异步操作之间没有依赖关系不要一个一个地await这样会导致不必要的等待。应该让它们并行执行。// 串行执行总耗时 ~2000ms async function serial() { const result1 await fetch(url1); // 假设耗时1000ms const result2 await fetch(url2); // 假设耗时1000ms } // 并行执行总耗时 ~1000ms async function parallel() { const promise1 fetch(url1); const promise2 fetch(url2); const [result1, result2] await Promise.all([promise1, promise2]); }实际使用async loadClassDetail(classId) { try { const params { trainingClassId: classId }; // 一次性并发执行所有不相关的API调用 const [res1, coursesRes, dataRes, contentRes, noticeRes, examRes] await Promise.all([ getInfoByTrainingClassId(classId), // 班级基本信息 getMajorInfoById(classId), // 培训课程 getMajorFilesInfoById(classId), // 培训资料 listByClassId(params), // 培训计划 listByStudentIdAndClassId(params), // 通知 getExamScheduleByStudentId(params) // 考试安排 ]); // 处理班级基本信息 const info res1.data; this.classDetail { category: { special: 特设培训, regular: 常规培训, custom: 定制培训 } [info.signUpCategory], project: info.trainingProjectName, classNumber: info.trainingClassCode, className: info.trainingClassName, year: info.trainingYear, term: info.trainingSession, startDate: info.startDate, endDate: info.endDate, trainingRegion: info.trainingRegion, trainingAddress: info.trainingAddress, trainingLocation: info.trainingVenue, actualTrainingLocation: info.actualTrainingVenue, headTeacher1: info.headTeacher1Name, headTeacher2: info.headTeacher2Name, }; // 处理培训课程 const coursesInfo coursesRes.data; this.classDetail.courses coursesInfo.map(item ({ name: item.courseName, type: item.courseType, })); // 处理培训资料 const dataInfo dataRes.data; this.classDetail.trainingMaterials dataInfo.map(item ({ name: item.fileName, filePath: item.filePath, })); // 处理培训内容 const contentInfo contentRes.rows; this.classDetail.trainingContent contentInfo.map(item ({ location: item.scheduleAddress, teacher: item.teacherName || , startTime: item.scheduleStartTime, endTime: item.scheduleEndTime, })); // 处理通知 const noticeInfo noticeRes.rows; this.classDetail.notifications noticeInfo.map(item ({ publishTime: item.sendTime, content: item.noticeContent, })); // 处理考试安排 const examInfo examRes.rows; this.classDetail.examArrangement examInfo.map(item ({ startTime: item.examStartTime, endTime: item.examEndTime, duration: item.examDuration, address: item.examLocation, method: item.examPathway, passScore: item.examPassScore, releaseImmediately: item.ifReleaseResultsImmediately 1, allowRetake: item.ifAgreeAutomaticExam 1, examTimes: item.examTimes, })); this.$forceUpdate(); } catch (error) { console.error(加载班级详情失败:, error); } }, loadAllDicts() { const dictPromises [ getDicts(pxzx_zjlx), getDicts(rylx), getDicts(pub_xb), getDicts(pub_mz), getDicts(pxzx_xl), getDicts(administrative_area), getDicts(unit_nature), getDicts(training_type), getDicts(payment_status), getDicts(record_status), ]; Promise.all(dictPromises) .then((responses) { this.dictData.zjlxOptions responses[0].data; this.dictData.userTypeOptions responses[1].data; this.dictData.sexOptions responses[2].data; this.dictData.nationOptions responses[3].data; this.dictData.educationOptions responses[4].data; this.dictData.administrativeAreaOptions responses[5].data; this.dictData.unitNatureOptions responses[6].data; this.dictData.trainingTypeOptions responses[7].data; this.dictData.paymentStatusOptions responses[8].data; this.dictData.recordStatusOptions responses[9].data; console.log(this.dictData); }) .catch((error) { console.error(字典数据加载失败:, error); }); },上传FileUpload refpaymentVoucherFileUpload :fileType[ jpg, jpeg, png, gif, pdf, doc, docx, ] :fileSize10 :limit1 :isShowTiptrue upload-successhandleVoucherUploadSuccess upload-errorhandleVoucherUploadError upload-finishhandleVoucherUploadFinish / div v-ifuploading classuploading-tip正在上传.../div /** * 处理凭证文件上传成功 */ handleVoucherUploadSuccess(response, file, fileList) { this.uploading false; this.$message.success(上传成功); // 更新表单数据 this.transferPayFormData.voucherUrl response.url; this.transferPayFormData.voucherName file.name; // 更新表单数据将完整URL转换为相对路径格式 if (response.url) { // 提取相对路径 const urlObj new URL(response.url, window.location.origin); this.transferPayFormData.voucherUrl urlObj.pathname; } }, /** * 处理凭证上传失败 */ handleVoucherUploadError(err, file, fileList) { this.uploading false; this.$message.error(上传失败请重试); }, /** * 处理凭证上传完成 */ handleVoucherUploadFinish(response, file, fileList) { this.uploading false; },里面有获取上传路径和对于路径的处理部分。下载vueel-button typeprimary sizesmall clickdownloadTemplate 下载模板 /el-button downloadTemplate() { const filePath /static/实操考试信息.xlsx; this.$download.saveAs(filePath, 实操考试信息导入模板.xlsx); },uniapp中下载与vue不同不能直接调用浏览器的savefile方法下载文件需要处理对于后端不能下载的内容可以使用html2canvas实现下载downloadFile(item) { uni.downloadFile({ url: item.filePath, success: (res) { if (res.statusCode 200) { // 下载成功 #ifdef H5 // H5环境下文件已经下载到浏览器默认目录不需要保存直接提示 uni.showToast({ title: 下载成功, icon: success }); #else // 非H5环境保存到本地 uni.saveFile({ tempFilePath: res.tempFilePath, success: function(saveRes) { uni.showToast({ title: 下载成功, icon: success }); }, fail: function(err) { console.error(保存文件失败:, err); uni.showToast({ title: 保存文件失败, icon: none }); } }); #endif } }, fail: (err) { uni.showToast({ title: 下载失败, icon: none }); console.error(下载失败:, err); } }); }小程序Uniapponload方法中可以获取页面加载时的内容比如另一个页面跳转传过来的参数也可以在这里面执行数据的预加载。onLoad(option) { console.log(页面参数:, option); // 获取 url 和 classId 参数 const url option.url || ; const id option.classId || ; this.tempClassId id; },QuestionsQ1:AutoCAD绘制逻辑没有问题绘制出来的结果和预期相差很多// 计算角度参数 double jj layer.fwj - baseAngle; double deltaAngle Math.Abs(layer.fwj - layer.angle) * Math.PI / 180.0; // 计算地层厚度 double layerThickness layer.EndDepth - layer.StartDepth; // 计算偏移量 double dx layerThickness * Math.Cos(deltaAngle); double dy layerThickness * Math.Sin(deltaAngle); // 根据方位角调整方向 if (jj 0) { dx -Math.Abs(dx); dy -Math.Abs(dy); } else { dx -Math.Abs(dx); dy Math.Abs(dy); } // 计算终点坐标 Point3d layerEnd new Point3d( currentPoint.X dx, currentPoint.Y dy, 0 );错误原因及解决方案计算deltaAngle 时忘记转弧度Math.PI / 180.0直接拿着算出来的值进行计算Q2、uniapp扫描二维码get请求通过路由传参时参数有#号等特殊字符串对前端发送的请求进行转码将请求转为16进制//示例 //转码前 http://localhost:9090/#/pages/internalTrainingCourse/checkIn/checkIn?classCheckinId3 //转码后 http://localhost:8001/createLogoQRCode?urlhttp%3A%2F%2Flocalhost%3A9090%2F%23%2Fpages%2FinternalTrainingCourse%2FcheckIn%2FcheckIn%3FclassCheckinId%3D3Q3、前端取值一直报未定义从this.$router后面链式获取参数时一直未定义解决一层一层取值进入到需要拿值得那一层Q4、在移动端判断时一直不能正确进入// 清理字符串去除可能的引号 let examType String(this.tempExamType); // 去除首尾的引号 examType examType.replace(/^[]|[]$/g, ).trim(); console.log(清理后的examType:, examType); if (examType 1) { console.log(调用正常考试接口); apiCall classExam(this.tempTrainClassId); } else if (examType 2) { console.log(调用模拟考试接口); apiCall classExamSimulation(this.tempTrainClassId); } else { console.log(未知考试类型默认调用正常考试接口, examType); apiCall classExam(this.tempTrainClassId); }Q5、记录一下之前的加载dwg格式的cad图纸这个之前搞出来一次很长时间没搞忘记了具体解决办法用autocad或者其他工具将拿到的dwg格式的图纸首先去除掉图纸上面的杂乱干扰信息然后另存为dxf格式用global mapper打开dxf文件导出为我这里使用的cesiumjs加载的格式选择的kml/kmz然后使用 Cesium.KmlDataSource.load 加载Q6、向windows系统部署时没有U盘硬盘辅助1、powershell调出命令2、net use \\192.168.33.70\C$ /user:用户名 密码 登录3、robocopy F:\AboutProduction\1 \\ip\C$\ay_server\ay_tran 2.txt 复制文件(文件夹将文件名换为/E)装操作系统给空服务器安装Linux参考地址https://www.cnblogs.com/mozhiyan/articles/19247933/ventoy常用工具因为之前系统盘损坏过想了想还是把一些常用好用的工具整理一下放在这里记录一下。//阿里图标库 https://www.iconfont.cn/search/index?searchTypeiconpage1fromCollection-1 //一个免费的抠图工具 https://tool.lu/cutout/ //科学计算器 https://www.desmos.com/scientific?langzh-CN //ai导航 https://www.aig123.com/#term-27-43 //项目管理工具--甘特图--zzplan https://zz-plan.com/login //cesium官网 https://cesium.com/learn/ //Ant Design Vue https://2x.antdv.com/components/overview-cn/ //uniapp https://uniapp.dcloud.net.cn/api/ //简历制作 https://www.jianliben.com/account/login?redirecthttps://www.jianliben.com/profile