最近遇到的一些新奇角度的细节-2026.1.20更新
一、完整的vue文件一整个页面也能作为组件使用template !-- 修改订单页面 -- orderBase/orderBase /template script import orderBase from ./add.vue; export default { name: orderEdit, data() { return {}; }, components: { orderBase } }; /script主要是为了配置不同页面如修改、新增权限常用于新增修改长得差不多的页面二、 上传文件时本地修改会触发浏览器安全机制1.原因浏览器安全机制 net:ERR_UPLOAD_FILE_CHANGED用el-upload组件非自动上传时也会有这个问题2.解决方案// 判断是否修改了选择的文件 try { // 这里读取文件 // file文件是个对象按道理不能slice但是继承自blob // blob可以看成二进制字符串有slice方法 // blob得arrayBuffer会把二进制转成arraybuffer并且返回promise转得过程就要读取文件 await this.file.slice(0 ,1).arrayBuffer(); }catch (e) { this.$error(选择的文件已经修改请重新选择上传${e}); return; }三、修改页修改后能刷新上一个详情页详情页、修改页单开通常在使用window.opener的时候要去判断父窗口的状态如果父窗口被关闭或者更新就会出错解决办法是加上如下的验证 if(window.opener !window.opener.closed)if (window.opener !window.opener.closed) { window.opener.location.reload(); // 强制刷新父页 } setTimeout(() { window.close(); // 关闭当前页 }, 2000);注A列表页-B详情页-C修改页C提交后刷新B、关闭C如果在C页提交前用户把B页面手动关闭再在C页面提交B页面不存在也就不刷新了A页面也不会刷新。window.opener - Web API | MDN四、导入文件接口除了前端代码限制大小发布说明nginxand后端也要五、没有脱敏权限不能跳修改订单页面联系电话回显全明文系统的脱敏权限都是独立配置的。所以如A页面里有用到某些脱敏(明文)接口的话需要在A页面入口进行判断有无脱敏权限无脱敏权限提示”用户缺少脱敏权限请联系管理员进行配置”。哪怕有修改订单页面权限也不行脱敏权限是单独的要注意手动拦截。例如1.常见的就是这种修改手机号、身份证号等个人隐私信息。2.更常见的列表页面一般会在onMounted里调用查询接口获取列表数据要判断一下是否有查询权限再进行接口调用。五点五、脱敏如手机号注意是否有多个手机号脱敏的场景六、一些易忘小tips一ref和reactive一句话总结大多用ref(如数组、基本数据类型、简单对象等)复杂嵌套的对象考虑用reactive主要考虑到reactive声明的变量直接赋值会失去响应性。ps:哪怕用object.assign去赋值也要小心el-dialog/el-drawer等列表页展开渲染对应数据若存在类似于嵌套数组/对象用object.assign去赋值的时候要记得先清空再赋值——不然会数据显示错乱重叠。如const Arr1 reactive([{A:1},{B:1}]); Object.assign(Arr1,[{C:2}]);结果是[{C:2},{B:1}]二JSON.stringify()的一些注意点const obj { a: NaN, b: undefined, c: Infinity, d: -Infinity, e: null, f: function() {}, g: Symbol(sym), h: new Date(), i: [NaN, undefined, null] }; const jsonString JSON.stringify(obj, null, 2); console.log(jsonString); // 输出 // { // a: null, // c: null, // d: null, // e: null, // h: 2024-01-23T10:30:00.000Z, // i: [null, null, null] // } // 注意b、f、g 键被完全删除三Number() VS parseFloat()、parseInt()Number是 JavaScript 的构造函数用于将值转换为数字类型。它会尝试严格转换如果输入值无法完全转换为数字则返回NaN。Number(123abc); // 返回 NaN Number(123); // 返回 123 Number(true); // 返回 1 Number(null); // 返回 0parseFloat是全局函数专门用于解析字符串中的浮点数。它会忽略字符串开头的非数字字符并尽可能解析有效的数字部分。例如parseFloat(123abc); // 返回 123 parseFloat(abc123); // 返回 NaN parseFloat(12.34); // 返回 12.341.核心差异字符串处理方式不同Number要求整个字符串必须完全符合数字格式否则返回NaN。parseFloat会忽略开头的空格和无效字符并尽可能解析有效的数字部分。类型转换范围不同Number可以处理布尔值、null、undefined等其他类型。parseFloat仅针对字符串或可隐式转换为字符串的值。特殊值处理空字符串或纯空格字符串Number(); // 返回 0 parseFloat(); // 返回 NaN十六进制/八进制字符串Number(0x10); // 返回 16 parseFloat(0x10); // 返回 02.使用场景建议需要严格验证数字格式时如用户输入校验优先使用Number。解析包含非数字字符的字符串如 12px时使用parseFloat或parseInt。处理非字符串类型如布尔值、null时Number更合适。四小数乘/除法都存在精度丢失的问题最佳实践在处理需要高精度的小数时尤其是金钱永远不要直接使用float或double类型而是采用转换为整数运算或使用高精度计算库的方法。1.先转换成整数再乘就可以也就是用整数进行乘没问题的再除10、100、1000等回去的话大范围内是精确的小数字 ÷ 10ⁿ通常精确 ✅大数字 ÷ 10ⁿ可能不精确 ❌超大数字 ÷ 10ⁿ很可能不精确 ❌❌绝对精确的需求使用 BigInt 或专用数学库 ✅2.使用高精度计算库下面是用bigNumber.js库封装的精确版本加减乘除计算toFixed方法小区分 bigNumber的.toFixed()默认是正常的四舍五入 而普通number的toFixed()是银行家算法的四舍五入遇到5要看仔细 1. 先看5后面 → 有数字就进一 2. 后面没数字 → 看5前面的数字 - 前面是奇数1,3,5,7,9→ 进一 - 前面是偶数0,2,4,6,8→ 舍弃引入依赖// package.json dependencies: { bignumber.js: ^9.3.1, }封装使用import BigNumber from bignumber.js; /** * 校验只要是数字包含正负整数0以及正负浮点数就返回true */ function isNumber(val) { const regPos /^\d(\.\d)?$/; // 非负浮点数 const regNeg /^(-(([0-9]\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9])|([0-9]*[1-9][0-9]*)))$/; // 负浮点数 if (regPos.test(val) || regNeg.test(val)) { return true; } else { return false; } } /** * 乘法 * param {Number} num1 乘数 * param {Number} num2 乘数 * param {Number} digit 保留位数默认-1为高精度计算 * return {String} 返回相乘后的结果 */ dataMultiply (num1, num2, digit -1) { if (isNumber(num1) isNumber(num2)) { const num1Big new BigNumber(num1); const num2Big new BigNumber(num2); const calcValue num1Big.multipliedBy(num2Big); if (digit -1) { return calcValue.toString(); } else { return calcValue.toFixed(digit); } } else { return ; } }, /** * 除法 * param {Number} num1 被除数 * param {Number} num2 除数 * param {Number} digit 保留位数默认-1为高精度计算 * return {String} 返回相除后的结果 */ dataDivide (num1: number, num2: number, digit -1) { if (isNumber(num1) isNumber(num2)) { const num1Big new BigNumber(num1); const num2Big new BigNumber(num2); const calcValue num1Big.dividedBy(num2Big); if (digit -1) { return calcValue.toString(); } else { return calcValue.toFixed(digit); } } else { return ; } }, /** * 减法 * param {Number} num1 被减数 * param {Number} num2 减数 * param {Number} digit 保留位数默认传入-1为高精度计算 * return {String} 返回相减后的结果 */ dataMinus(num1: number, num2: number, digit -1) { if (isNumber(num1) isNumber(num2)) { const num1Big new BigNumber(num1); const num2Big new BigNumber(num2); const calcValue num1Big.minus(num2Big); if (digit -1) { return calcValue.toString(); } else { return calcValue.toFixed(digit); } } else { return ; } }, /** * 加法 * param {Number} num1 加数 * param {Number} num2 加数 * param {Number} digit 保留位数默认-1为高精度计算 * return {String} 返回相加后的结果 */ dataAdd(num1: number, num2: number, digit -1) { if (isNumber(num1) isNumber(num2)) { const num1Big new BigNumber(num1); const num2Big new BigNumber(num2); const calcValue num1Big.plus(num2Big); if (digit -1) { return calcValue.toString(); } else { return calcValue.toFixed(digit); } } else { return ; } },原因五 校验重复1.用Set实现时间复杂度O(n)平均情况因为Set的查找/插入是 O(1)空间复杂度O(n)利用Set数据结构的特性不允许重复元素。通过将元素添加到Set中可以快速判断是否已存在。// 检查xxx中是否有重复的 function checkDuplicateTransportFlows(transports: any[]): string | false { const { flows } transports; const seen new Setstring(); for (const { flowName } of flows) { if (seen.has(flowName)) { return flowName; } seen.add(flowName); } return false; }2.双层for循环时间复杂度O(n²)最坏情况需要比较所有对空间复杂度O(1)只用了少量变量两层循环逐一比较每对元素检查是否有重复。// 检查xxx中是否有重复的 function checkDuplicateTransportFlows(transports: any[]): string | false { const { flows } transports; for (let i 0; i flows.length; i) { for (let j i 1; j flows.length; j) { if (flows[i].flowName flows[j].flowName) { return flows[i].flowName; } } } return false; }七、用到的一些依赖库积累(一)UnocSS作用类似于 max-h-100px、overflow-y-auto、overflow-x-hidden等直接在元素的开始标签上写构建时工具UnoCSS 是一个即时原子 CSS 引擎它在构建时将类名转换为相应的 CSS 规则这些规则被打包到最终的 CSS 文件中。这意味着运行时不需要 UnoCSS 库本身。Vite 插件在 vite.config.ts 中UnoCSS 作为 Vite 插件被引入只在开发和构建阶段运行。参考效果效果地址1.引入依赖// package.json devDependencies: { unocss: ^0.34.1 }2.配置// vite.config.ts import Unocss from unocss/vite; import { presetAttributify, presetIcons, presetUno, transformerDirectives, transformerVariantGroup } from unocss; export default defineConfig({ resolve: { alias: { /: ${pathSrc}/ } }, css: { preprocessorOptions: { scss: { additionalData: use /styles/element/index.scss as *; } } }, plugins: [ vue(), createSvg(./src/icons/svg/), Components({ // allow auto load markdown components under ./src/components/ extensions: [vue, md], // allow auto import and register components used in markdown include: [/\.vue$/, /\.vue\?vue/, /\.md$/], resolvers: [ ElementPlusResolver({ importStyle: sass }) ], dts: src/components.d.ts }), AutoImports({ imports: [vue, vue-router] // 手动管理 }), // https://github.com/antfu/unocss // see unocss.config.ts for config Unocss({ presets: [ presetUno(), presetAttributify(), presetIcons({ scale: 1.2, warn: true }) ], transformers: [transformerDirectives(), transformerVariantGroup()] }), DefineOptions() ],3.使用运行时无依赖在 main.ts 中虽然引用了uno.css但这只是导入生成的样式文件而不是 UnoCSS 引擎本身// main.ts import uno.css;(二)element-plusElement Plus Playground 在线演示台https://element-plus.run/#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b3IpO1xuICBmbGV4OiAxO1xufVxuLmRlbW8tZGF0ZXRpbWUtcGlja2VyIC5ibG9jazpsYXN0LWNoaWxkIHtcbiAgYm9yZGVyLXJpZ2h0OiBub25lO1xufVxuLmRlbW8tZGF0ZXRpbWUtcGlja2VyIC5kZW1vbnN0cmF0aW9uIHtcbiAgZGlzcGxheTogYmxvY2s7XG4gIGNvbG9yOiB2YXIoLS1lbC10ZXh0LWNvbG9yLXNlY29uZGFyeSk7XG4gIGZvbnQtc2l6ZTogMTRweDtcbiAgbWFyZ2luLWJvdHRvbTogMjBweDtcbn1cbjwvc3R5bGUXG4iLCJpbXBvcnQtbWFwLmpzb24iOiJ7XG4gIFwiaW1wb3J0c1wiOiB7XG4gICAgXCJ2dWVcIjogXCJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL0B2dWUvcnVudGltZS1kb21AMy4yLjMxL2Rpc3QvcnVudGltZS1kb20uZXNtLWJyb3dzZXIuanNcIixcbiAgICBcIkB2dWUvc2hhcmVkXCI6IFwiaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9AdnVlL3NoYXJlZEAzLjIuMzEvZGlzdC9zaGFyZWQuZXNtLWJ1bmRsZXIuanNcIixcbiAgICBcImVsZW1lbnQtcGx1c1wiOiBcImh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vZWxlbWVudC1wbHVzQDIuMi4xNy9kaXN0L2luZGV4LmZ1bGwubWluLm1qc1wiLFxuICAgIFwiZWxlbWVudC1wbHVzL1wiOiBcImh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vZWxlbWVudC1wbHVzQDIuMi4xNy9cIixcbiAgICBcIkBlbGVtZW50LXBsdXMvaWNvbnMtdnVlXCI6IFwiaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9AZWxlbWVudC1wbHVzL2ljb25zLXZ1ZUAyL2Rpc3QvaW5kZXgubWluLmpzXCJcbiAgfSxcbiAgXCJzY29wZXNcIjoge31cbn0iLCJlbGVtZW50LXBsdXMuanMiOiJpbXBvcnQgRWxlbWVudFBsdXMgZnJvbSAnZWxlbWVudC1wbHVzJ1xuaW1wb3J0IHsgZ2V0Q3VycmVudEluc3RhbmNlIH0gZnJvbSAndnVlJ1xuXG5sZXQgaW5zdGFsbGVkID0gZmFsc2VcbmF3YWl0IGxvYWRTdHlsZSgpXG5cbmV4cG9ydCBmdW5jdGlvbiBzZXR1cEVsZW1lbnRQbHVzKCkge1xuICBpZiAoaW5zdGFsbGVkKSByZXR1cm5cbiAgY29uc3QgaW5zdGFuY2UgPSBnZXRDdXJyZW50SW5zdGFuY2UoKVxuICBpbnN0YW5jZS5hcHBDb250ZXh0LmFwcC51c2UoRWxlbWVudFBsdXMpXG4gIGluc3RhbGxlZCA9IHRydWVcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxvYWRTdHlsZSgpIHtcbiAgY29uc3Qgc3R5bGVzID0gWydodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2VsZW1lbnQtcGx1c0AyLjIuMTcvZGlzdC9pbmRleC5jc3MnLCAnaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9lbGVtZW50LXBsdXNAMi4yLjE3L3RoZW1lLWNoYWxrL2RhcmsvY3NzLXZhcnMuY3NzJ10ubWFwKChzdHlsZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGluaycpXG4gICAgICBsaW5rLnJlbCA9ICdzdHlsZXNoZWV0J1xuICAgICAgbGluay5ocmVmID0gc3R5bGVcbiAgICAgIGxpbmsuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIHJlc29sdmUpXG4gICAgICBsaW5rLmFkZEV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgcmVqZWN0KVxuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmQobGluaylcbiAgICB9KVxuICB9KVxuICByZXR1cm4gUHJvbWlzZS5hbGxTZXR0bGVkKHN0eWxlcylcbn0iLCJ0c2NvbmZpZy5qc29uIjoie1xuICBcImNvbXBpbGVyT3B0aW9uc1wiOiB7XG4gICAgXCJ0YXJnZXRcIjogXCJFU05leHRcIixcbiAgICBcImpzeFwiOiBcInByZXNlcnZlXCIsXG4gICAgXCJtb2R1bGVcIjogXCJFU05leHRcIixcbiAgICBcIm1vZHVsZVJlc29sdXRpb25cIjogXCJCdW5kbGVyXCIsXG4gICAgXCJ0eXBlc1wiOiBbXCJlbGVtZW50LXBsdXMvZ2xvYmFsLmQudHNcIl0sXG4gICAgXCJhbGxvd0ltcG9ydGluZ1RzRXh0ZW5zaW9uc1wiOiB0cnVlLFxuICAgIFwiYWxsb3dKc1wiOiB0cnVlLFxuICAgIFwiY2hlY2tKc1wiOiB0cnVlXG4gIH0sXG4gIFwidnVlQ29tcGlsZXJPcHRpb25zXCI6IHtcbiAgICBcInRhcmdldFwiOiAzLjNcbiAgfVxufVxuIiwiUGxheWdyb3VuZE1haW4udnVlIjoiPHNjcmlwdCBzZXR1cD5cbmltcG9ydCBBcHAgZnJvbSAnLi9BcHAudnVlJ1xuaW1wb3J0IHsgc2V0dXBFbGVtZW50UGx1cyB9IGZyb20gJy4vZWxlbWVudC1wbHVzLmpzJ1xuc2V0dXBFbGVtZW50UGx1cygpXG48L3NjcmlwdD5cblxuPHRlbXBsYXRlPlxuICA8QXBwIC8XG48L3RlbXBsYXRlPlxuIiwiX28iOnsidnVlVmVyc2lvbiI6IjMuMi4zMSIsImVwVmVyc2lvbiI6IjIuMi4xNyJ9fQhttps://element-plus.run/#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b3IpO1xuICBmbGV4OiAxO1xufVxuLmRlbW8tZGF0ZXRpbWUtcGlja2VyIC5ibG9jazpsYXN0LWNoaWxkIHtcbiAgYm9yZGVyLXJpZ2h0OiBub25lO1xufVxuLmRlbW8tZGF0ZXRpbWUtcGlja2VyIC5kZW1vbnN0cmF0aW9uIHtcbiAgZGlzcGxheTogYmxvY2s7XG4gIGNvbG9yOiB2YXIoLS1lbC10ZXh0LWNvbG9yLXNlY29uZGFyeSk7XG4gIGZvbnQtc2l6ZTogMTRweDtcbiAgbWFyZ2luLWJvdHRvbTogMjBweDtcbn1cbjwvc3R5bGUXG4iLCJpbXBvcnQtbWFwLmpzb24iOiJ7XG4gIFwiaW1wb3J0c1wiOiB7XG4gICAgXCJ2dWVcIjogXCJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL0B2dWUvcnVudGltZS1kb21AMy4yLjMxL2Rpc3QvcnVudGltZS1kb20uZXNtLWJyb3dzZXIuanNcIixcbiAgICBcIkB2dWUvc2hhcmVkXCI6IFwiaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9AdnVlL3NoYXJlZEAzLjIuMzEvZGlzdC9zaGFyZWQuZXNtLWJ1bmRsZXIuanNcIixcbiAgICBcImVsZW1lbnQtcGx1c1wiOiBcImh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vZWxlbWVudC1wbHVzQDIuMi4xNy9kaXN0L2luZGV4LmZ1bGwubWluLm1qc1wiLFxuICAgIFwiZWxlbWVudC1wbHVzL1wiOiBcImh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vZWxlbWVudC1wbHVzQDIuMi4xNy9cIixcbiAgICBcIkBlbGVtZW50LXBsdXMvaWNvbnMtdnVlXCI6IFwiaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9AZWxlbWVudC1wbHVzL2ljb25zLXZ1ZUAyL2Rpc3QvaW5kZXgubWluLmpzXCJcbiAgfSxcbiAgXCJzY29wZXNcIjoge31cbn0iLCJlbGVtZW50LXBsdXMuanMiOiJpbXBvcnQgRWxlbWVudFBsdXMgZnJvbSAnZWxlbWVudC1wbHVzJ1xuaW1wb3J0IHsgZ2V0Q3VycmVudEluc3RhbmNlIH0gZnJvbSAndnVlJ1xuXG5sZXQgaW5zdGFsbGVkID0gZmFsc2VcbmF3YWl0IGxvYWRTdHlsZSgpXG5cbmV4cG9ydCBmdW5jdGlvbiBzZXR1cEVsZW1lbnRQbHVzKCkge1xuICBpZiAoaW5zdGFsbGVkKSByZXR1cm5cbiAgY29uc3QgaW5zdGFuY2UgPSBnZXRDdXJyZW50SW5zdGFuY2UoKVxuICBpbnN0YW5jZS5hcHBDb250ZXh0LmFwcC51c2UoRWxlbWVudFBsdXMpXG4gIGluc3RhbGxlZCA9IHRydWVcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxvYWRTdHlsZSgpIHtcbiAgY29uc3Qgc3R5bGVzID0gWydodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2VsZW1lbnQtcGx1c0AyLjIuMTcvZGlzdC9pbmRleC5jc3MnLCAnaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9lbGVtZW50LXBsdXNAMi4yLjE3L3RoZW1lLWNoYWxrL2RhcmsvY3NzLXZhcnMuY3NzJ10ubWFwKChzdHlsZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGluaycpXG4gICAgICBsaW5rLnJlbCA9ICdzdHlsZXNoZWV0J1xuICAgICAgbGluay5ocmVmID0gc3R5bGVcbiAgICAgIGxpbmsuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIHJlc29sdmUpXG4gICAgICBsaW5rLmFkZEV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgcmVqZWN0KVxuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmQobGluaylcbiAgICB9KVxuICB9KVxuICByZXR1cm4gUHJvbWlzZS5hbGxTZXR0bGVkKHN0eWxlcylcbn0iLCJ0c2NvbmZpZy5qc29uIjoie1xuICBcImNvbXBpbGVyT3B0aW9uc1wiOiB7XG4gICAgXCJ0YXJnZXRcIjogXCJFU05leHRcIixcbiAgICBcImpzeFwiOiBcInByZXNlcnZlXCIsXG4gICAgXCJtb2R1bGVcIjogXCJFU05leHRcIixcbiAgICBcIm1vZHVsZVJlc29sdXRpb25cIjogXCJCdW5kbGVyXCIsXG4gICAgXCJ0eXBlc1wiOiBbXCJlbGVtZW50LXBsdXMvZ2xvYmFsLmQudHNcIl0sXG4gICAgXCJhbGxvd0ltcG9ydGluZ1RzRXh0ZW5zaW9uc1wiOiB0cnVlLFxuICAgIFwiYWxsb3dKc1wiOiB0cnVlLFxuICAgIFwiY2hlY2tKc1wiOiB0cnVlXG4gIH0sXG4gIFwidnVlQ29tcGlsZXJPcHRpb25zXCI6IHtcbiAgICBcInRhcmdldFwiOiAzLjNcbiAgfVxufVxuIiwiUGxheWdyb3VuZE1haW4udnVlIjoiPHNjcmlwdCBzZXR1cD5cbmltcG9ydCBBcHAgZnJvbSAnLi9BcHAudnVlJ1xuaW1wb3J0IHsgc2V0dXBFbGVtZW50UGx1cyB9IGZyb20gJy4vZWxlbWVudC1wbHVzLmpzJ1xuc2V0dXBFbGVtZW50UGx1cygpXG48L3NjcmlwdD5cblxuPHRlbXBsYXRlPlxuICA8QXBwIC8XG48L3RlbXBsYXRlPlxuIiwiX28iOnsidnVlVmVyc2lvbiI6IjMuMi4zMSIsImVwVmVyc2lvbiI6IjIuMi4xNyJ9fQ2.2.17版本的element-plus有个交互bug噗大家用的时候注意被测试抓到了太惨——日期选择器要点两下才弹出日历的bug(前后版本都是好的)