被老板怼后,我为uni-app项目引入环境标志

前情

最近公司在规划一个全新项目,但是又对项目前景有些怀疑,于是想做一个项目获客验证的运营活动,就是为了决定后续项目可行性和投入规模。

注:时间都宝贵,如果不想浪费时间看一些无聊的事情原委的,只想了解环境标志是怎么回事的,可直接跳到实现环境标志段即可

测试正式难区分

小程序的发包流程的,在HBuilder X上点击发行-小程序就会自动打生产包,同时唤起小程序IDE,再通过IDE点点测测后没啥问题就再通过小程序IDE的上传版本上传代码包到小程序后台,此时可以查看体验版,体验版码给到测试验收没啥问题后,再走提审流程,审核通过后就可以发到线上

我负责的前一个小程序因为因为测试和生产的配置数据相差比较大,一眼就能区分当前是在测试还是在生产,这样在上传包的时候就能轻松区分当前接口是否是在生产环境,我现在负责的小程序首页只是一个入口页,和生产是一模一样的,我平时上传包的时候是看一下目前运行的代码目录来区分是在开发还是在生产的

一坑又一坑

项目其实在上线前2天就已经测试差不太多,但卡在一个前置条件,我们活动需要依赖支付宝的芝麻免押,又因为我们的项目流程因各种原因被支付宝打回,所以项目流程一直在调整,后面为了申请免押,直到芝麻免押过审一直反复提了4版,最后一版是产品完全推倒重新做的需求稿,我在开发这一版的时候我重新牵了一个新分支,因为过审后这一版是直接废掉的,因为老板一直在催,我于加急调整需求,在开发到80%的时候,产品突然找到我说芝麻免押过审了,我现在手上的需求可以搁置,让我重新回滚到正常的那一版(掉坑1)。

支付宝小程序和别的小程序不一样,它是按迭代来做小程序版本管理的,在反复的提版中我因为有一版刚刚走完了提审迭代到了待发布状态,此时产品又提了修改点,我于是就废掉了这一迭代,调整需求后重新新提了一个迭代,走了提审,提审后,我看着迭代列表中刚刚那个没走完的迭代一直那么显眼,我看着它总感觉不爽,于是我就删除了它(掉坑2)

此次活动主入口是在抖音小程序,在抖音上下单后,通过短信携带链接发送给用户,用户点击短信唤起支付宝小程序完成余下芝麻免押流程,在走通测试后,服务端做了下正式服商品配置,因为此次活动较紧急没有做配置后台,于是服务端把测试服商品调整为了和正式库一样的配置,方便到时上线直接更新(掉坑3)

被怼

因抖音小程序活动的测试数据被服务端同步和正式库数据成了一样,当我在做最后发版验收的时候,怎么都支付不了,我和服务端二个都自查了代码,也连调了好一会也没有找到问题原因,最后还是找的抖音客服才知道是因为测试库对支付是有金额限制的,不能大太,只能是小金额,具体经过详见我的博文:抖音小程序支付错误码141211

祸不单行,在做支付宝发包的时候,不知道因为什么原因,导致支付宝小程序IDE没法自动迭代,具体经过可以查看我的博文:支付宝小程序IDE版本迭代异常

直到晚上22点多二个问题都还没有解决,而此时老板一直在问进度,说今晚一定要上线......

抖音小程序因为线上是可以支付,我们于是说先不管测试支付不了的问题,先提生产版,等审核过了直接去线上验证,有问题直接回滚

支付宝因为前面提了几版用于申请芝麻免押能力,而正式上线是要去掉这些,产品让我回滚代码到正常版,而此时我理解的是上面新拉的调整分支不用,直接回到主分支再提一版即可,其实这里是错的,因为主分支也加了一些小修改用于申请芝麻免押能力。

还有个致命问题就是支付宝小程序IDE无法上传版本,找了支付宝技术人员,他们也没有找到问题,在我多次要求能不能先不管问题,先通过别的方式先绕过这个问题先提版本再说,支付宝技术人员教我手动建迭代试试,此时已经晚上11点了,我急忙忙的去手动新建迭代,此时IDE可以下拉选择到新建迭代了,也就临时绕过问题可以发包了,同时向支付宝技术人员要求能不能走个加急审核,支付宝说可以,此时我一心只想尽快提审版本,于是乎就提了审,几分钟内就过了审,我也点了发包,终于松了一口气

但是没过几分钟产品跑过来说回退的版本是错的,带了芝麻免押审核的一些调整,又过了一会,测试又跑过来说发的版本有问题一直报订单不存在,我当时就蒙了,因为我只是切了下分支,主分支原先就是验证通过的,直到BOSS跑过来说,线上的商品价格怎么有1块的,是不是发错环境了,我此时意识到问题了,我在上传版本的时候因为紧急忘了确认当前是生产还是测试了,因当时电脑上测试和生产同时跑着,我一急就点错了,BOSS此时很不耐烦的说,你写小程序也有这么久了,怎么还会出现这种问题,一会抖音支付不了,一会又包错包,我此时尴尬到了极点,我于是加紧了提了一版,幸运提此次提版审核也十来分钟就过了,顺利的发了包

此时已经晚上11.30分,过了晚上11点就没有地铁了,我打的的士,在的士上我反复在想为什么会犯这种低级错,生产和测试包都能提错,我想到平时自己发包都是通过看代码路径来判断是否是生产和测试的,如果不急的情况下,是不会有问题的,但是事情一紧急就会忘记去确认代码路径,我此时想到应该给项目引入环境标志,一眼就能看出当前是什么环境,避免因手忙脚乱导致发错环境。

引入环境标志

环境标示-日志

想到的第一种方式是通过打印日志,在日志中标志出当前服务端地址,打印普通的日志不是十分显眼的,很容易被淹没,我于是选择打印一个定制化的彩色日志,效果如下:

关键代码如下:

jsx 复制代码
import { BASE_URL } from '@/config/http';

/**
 * 环境日志打印
 */
export const initEnvLog = () => {
  uni.$off('envlog');
  uni.$on('envlog', () => {
    console.log(`%c--- 项目环境 ----:%c${process.env.NODE_ENV} ${BASE_URL.split('//')[1]}`, 'color:white;background:blue;padding:6px;', 'color:red;background:white;padding:6px;');
  })
}

任何地方只要调用uni.$emit('envlog')即可在控制台打印环境日志

环境标志-页面标示

为什么做了日志环境标示还要做页面标示,为了开发调试需求一般都会在控制台打印非常多的日志,像我现在的项目,为了能快速发现服务端接口问题,我在封装通用接口请求的时候,默认会把请求信息和接口响应信息全打印

还有一些别的开发日志,控制台是很丰富,虽然日志标志已经做成鹤立鸡群,一眼可以看出,但还是有很大可能日志会被淹没,于是想到做一个页面标志

我把它封装成组件并全局注册,在所有页面都使用此组件即可,为了不影响测试测试,同时为该标志增加了拖动功能,可以手动依靠在页面任一位置,同时还把项目彩蛋页入口也加到上面,如果你快速点击按钮6次+,就会让你选择是隐藏标志,还是跳彩蛋页,有了页面标志,就算你一时急,没有查看日志。页面上一个大大的测试服是逃不掉你我们眼镜的,组件代码如下:

jsx 复制代码
<template>
    <image 
        class="env-log" 
        v-if="isShow"
        @click="handleClick" 
        @touchstart="handleTouchStart"
        @touchmove="handleTouchMove"
        @touchend="handleTouchEnd"
        :style="{ transform: `translate(${position.x}px, ${position.y}px)` }"
        src="data:image/webp;base64,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" 
        mode="aspectFit" 
    />
</template>

<script setup>
    import { ref, onMounted, nextTick } from 'vue';

  const clickCount = ref(0);
  const isShow = ref(false);

    // 拖拽相关状态
    const isDragging = ref(false);
    const startTouch = ref({ x: 0, y: 0 });
    const position = ref({ x: 0, y: 0 });
    const startPosition = ref({ x: 0, y: 0 });

  // 连续点击6次隐藏环境标志
  let timer = null;
    const handleClick = () => {
        // 如果是拖拽状态,不处理点击事件
        if (isDragging.value) return;

        clickCount.value += 1;
    clearTimeout(timer);
    timer = setTimeout(() => {
      clickCount.value = 0;
    }, 1000);
        if (clickCount.value > 6) {
      uni.showModal({
        title: '',
        content: '请选择操作',
        cancelText: '隐藏标志',
        confirmText: '彩蛋',
        success: (res) => {
          if (res.confirm) {
            uni.navigateTo({
              url: '/other/egg/egg'
            })
          } else {
            isShow.value = false;
          }
        }
      })
        }
    }

    // 触摸开始
    const handleTouchStart = (e) => {
        e.preventDefault();
        isDragging.value = false;
        const touch = e.touches[0];
        startTouch.value = {
            x: touch.clientX,
            y: touch.clientY
        };
        startPosition.value = { ...position.value };
    }

            // 触摸移动
    const handleTouchMove = (e) => {
        e.preventDefault();
        if (!startTouch.value) return;

        const touch = e.touches[0];
        const deltaX = touch.clientX - startTouch.value.x;
        const deltaY = touch.clientY - startTouch.value.y;

        // 如果移动距离超过5px,认为是拖拽
        if (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5) {
            isDragging.value = true;
        }

        if (isDragging.value) {
            const newX = startPosition.value.x + deltaX;
            const newY = startPosition.value.y + deltaY;

            // 获取窗口尺寸进行边界限制
            const systemInfo = uni.getSystemInfoSync();
            const screenWidth = systemInfo.screenWidth;
            const windowHeight = systemInfo.windowHeight; // 使用窗口高度而不是屏幕高度
            const imageWidth = 121; // rpx转px大约是屏幕宽度的1/750 * 121
            const imageHeight = 96;
            const realImageWidth = (screenWidth / 750) * imageWidth;
            const realImageHeight = (screenWidth / 750) * imageHeight;

            // 边界限制
            const maxX = screenWidth - realImageWidth;
            const maxY = windowHeight - realImageHeight;

            position.value = {
                x: Math.max(0, Math.min(newX, maxX)),
                y: Math.max(0, Math.min(newY, maxY))
            };
        }
    }

    // 触摸结束
    const handleTouchEnd = (e) => {
        e.preventDefault();
        startTouch.value = { x: 0, y: 0 };

        // 延迟重置拖拽状态,避免触发点击事件
        setTimeout(() => {
            isDragging.value = false;
        }, 100);
    }

  onMounted(() => {
    if ((process && process.env && process.env.NODE_ENV === 'development') || import.meta.env.MODE === 'development') {
      isShow.value = true;

            // 初始化位置到右下角
            nextTick(() => {
                const systemInfo = uni.getSystemInfoSync();
                const screenWidth = systemInfo.screenWidth;
                const windowHeight = systemInfo.windowHeight; // 使用窗口高度而不是屏幕高度
                const imageWidth = 121;
                const imageHeight = 96;
                const realImageWidth = (screenWidth / 750) * imageWidth;
                const realImageHeight = (screenWidth / 750) * imageHeight;

                position.value = {
                    x: screenWidth - realImageWidth,
                    y: windowHeight - realImageHeight - 100 // 距离底部100px,基于窗口高度
                };
            });
    } else {
      isShow.value = false;
    }
  })

</script>

<style lang="scss">
.env-log {
    width: 121rpx;
    height: 96rpx;
  position: fixed;
  top: 0;
  left: 0;
  opacity: 0.65;
  z-index: 9999;
    transition: none; // 拖拽时不要过渡动画
    user-select: none; // 防止选中
}
</style>

引入的环境标志效果如下:

期望

有的人一定会说为了一个判断环境特意封一个组件,有点杀鸡用牛刀,解决问题的方法有千千万,能解决你当下问题的方法,就是好的方法

我期望的做法的,我想后续封装一个vite插件,通过插件注入日志组件,生产环境直接丢掉,这样不会为生产带去多余的代码同时也是一劳永逸的事,不像现在还要手动插入

如果你有更棒的解决方案,欢迎你留言分享,一起学习进步

相关推荐
sasaraku.30 分钟前
serviceWorker缓存资源
前端
RadiumAg2 小时前
记一道有趣的面试题
前端·javascript
yangzhi_emo2 小时前
ES6笔记2
开发语言·前端·javascript
yanlele2 小时前
我用爬虫抓取了 25 年 5 月掘金热门面试文章
前端·javascript·面试
The_era_achievs_hero2 小时前
微信小程序71~80
微信小程序·小程序
中微子3 小时前
React状态管理最佳实践
前端
米粒宝的爸爸3 小时前
uniapp在app端,在导航栏设置自定义按钮
uni-app
烛阴3 小时前
void 0 的奥秘:解锁 JavaScript 中 undefined 的正确打开方式
前端·javascript
中微子3 小时前
JavaScript 事件与 React 合成事件完全指南:从入门到精通
前端
Hexene...3 小时前
【前端Vue】如何实现echarts图表根据父元素宽度自适应大小
前端·vue.js·echarts