近期项目上遇到的一些功能;字符串比对(diffjs)、打印功能(printJS)、两端布局中间可拖拽功能实现

iwEcAqNqcGcDAQTREgAF0Q2ABrBIbfSiALVuPAY5KtIYz7wAB9MAAAAArMmCsQgACaJpbQoAC9IAOGgk.jpg_720x720q90.jpg

(买了辆公路车,五一从北京出发骑行了一趟天津,10h,150km。很累但很爽,哈哈。路上看到了很多骑友,而且居然还有骑共享单车去天津的!看样子像是学生,实在佩服。)

前言

也是好久没更新文章了,一直说要学习来着,主要是下班时间和周末经不住游戏和短视频小姐姐的‘诱惑’,常常沉迷于二者,还是自律性太差了,以后争取每天学习一段时间。话说,jym每天下班都会干什么?不会吧,不会吧,不会都在内卷吧,欢迎评论区留言。

ok,言归正传,近期项目组开了一个新项目,用的是vue3+vite的框架,近期项目也是快完工了,正好抽时间总结一下,遇到的一些需求和解决方法。如果jym近期遇到了或者以后可能会遇到相似的需求,可以借鉴参考下。

字符串比对(diffjs)

先展示一下最终的效果

1168e7fdd7d54b98a8154f4d651562dcd62a5a5ea79d776d67149cb9460e18f7QzpcVXNlcnNcREVMTFxBcHBEYXRhXFJvYW1pbmdcRGluZ1RhbGtcMjg5ODg4NzM0NV92MlxJbWFnZUZpbGVzXDE3MTYzNDg2Njc1NDBfMzQ0OEQ2NzctQUQyMS00YmVkLUI5OTItNkVCQzkyRTJEM0Q2LnBuZw==.png
我们这个项目做的是一个流程,就是有一些数据,一些人可以去更改这些数据,但是更改完数据以后需要发起流程去审批,通过以后这条数据才会真正被修改。

那么审批人就需要知道发起人都修改了哪些数据,这就有了如图所示的需求。更改后的数据需要和原数据去比对,如果是新增的数据需要标红,删除的数据需要标红加删除线。

我这边用到了diffjs这个插件。数据上,后端返回了两个对象,oldData和newData,我们需要拿到两个data里相同字段的值进行比对,返回比对后的结果,就是用span标签包裹起来,然后用v-html去渲染。

代码实现:

import * as Diff from 'diff';

// 比较两个字符串,变化的标红,删除的加删除线
export const diffFun = (oldValue:string, newValue:string) => {
  const testStr = Diff.diffChars(oldValue, newValue);
  let str = '';
  testStr.forEach((item:any) => {
    if (item.added) {
      str = `${str}<span style="color:red;">${item.value}</span>`;
    } else if (item.removed) {
      str = `${str}<span style="color:red;text-decoration: line-through;">${item.value}</span>`;
    } else {
      str = `${str}${item.value}`;
    }
  });
  return str;
};

打印(printJS)

9a60a4d6e2427a5528d11891e265f37789d0954e2ff09939cc92df33dad0880bQzpcVXNlcnNcREVMTFxBcHBEYXRhXFJvYW1pbmdcRGluZ1RhbGtcMjg5ODg4NzM0NV92MlxJbWFnZUZpbGVzXDE3MTYzNTY4MjE4ODhfODlGMUVFNzctNkY4Ni00NDgwLTg4OTUtRDIxNkVGNzFBRUFFLnBuZw==.png

打印功能使用到了,printJS这个插件,printable是要打印的数据,field是要打印数据的字段名,displayName是要打印数据的表头名,columnSize可以设置列宽,但是会挤压最后一列。

import printJS from 'print-js';
// 打印函数
const printFun = async () => {
  printJS({
    printable: [...tableData], // 要打印的数据
    properties: [
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称', columnSize: '20%' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' },
      { field: 'name', displayName: '名称' }
    ],
    type: 'json',
    scanStyles: false, // 不适用默认样式
    repeatTableHeader: false, // 打印json表头只显示在第一页
    gridHeaderStyle: 'border: 1px solid #909399;text-align:center;', // 表格头样式
    gridStyle: 'border: 1px solid #909399; text-align:center;', // 表哥体样式
    style: '@page{size:auto;margin: 0cm 1cm 0cm 1cm;}'// 去除页眉页脚
    // style:'@media print{@page {size:landscape}}' //横行打印
  });
};

两端布局中间可拖拽功能实现

GIF.gif

相关代码逻辑:

<template>
    <div :style="{height:that.height}" class="box">
    <el-row :gutter="10">
    <div style="width: 20%" class="left">
      <div class="resize" title="左右侧边栏"></div>
      <el-card :style="{height:treeHeight,overflow: 'auto'}">
        left
      </el-card>
    </div>
    <div style="width: 80%;" class="right">
      <el-card :style="{height:treeHeight,overflow: 'auto'}">
        right
      </el-card>
    </div>
    </el-row>
    </div>
</template>

<script>
// 左右拖动事件
function dragControllerLR () {
  const resize = document.getElementsByClassName('resize') as any;
  const left = document.getElementsByClassName('left') as any;
  const right = document.getElementsByClassName('right') as any;
  const box = document.getElementsByClassName('box') as any;
  for (let i = 0; i < resize.length; i++) {
    resize[i].onmousedown = function (e:any) {
    // 颜色改变提醒
      resize[i].style.background = '#818181';
      const startX = e.clientX;
      resize[i].left = resize[i].offsetLeft;

      // 鼠标拖动事件
      document.onmousemove = function (e) {
        const endX = e.clientX;
        let moveLen = resize[i].left + (endX - startX); // (endx-startx)=移动的距离。resize[0].left+移动的距离=左边区域最后的宽度
        const maxT = box[0].clientWidth - resize[i].offsetWidth; // 容器宽度 - 左边区域的宽度 = 右边区域的宽度

        if (moveLen < 50) moveLen = 50; // 左边区域的最小宽度为50px
        if (moveLen > maxT - 150) moveLen = maxT - 150; // 右边区域最小宽度为150px

        resize[i].style.left = moveLen; // 设置左侧区域的宽度

        for (let j = 0; j < left.length; j++) {
          left[j].style.width = moveLen + 'px';
          right[0].style.width = box[0].clientWidth - moveLen + 'px';
        }
      };

      // 鼠标松开事件
      document.onmouseup = function (evt) {
      // 颜色恢复
        resize[i].style.background = '#d6d6d6';
        document.onmousemove = null;
        document.onmouseup = null;
        resize[i].releaseCapture && resize[i].releaseCapture(); // 当你不在需要继续获得鼠标消息就要应该调用ReleaseCapture()释放掉
      };
      resize[i].setCapture && resize[i].setCapture(); // 该函数在属于当前线程的指定窗口里设置鼠标捕获
    };
  };
}

// 在组件挂载完成后,调用dragControllerLR函数
onMounted(() => {
  dragControllerLR();
});
</script>

<style scoped>
.box{
  width: 100%;
}
  /* 拖拽区div样式 */
  .resize {
    cursor: w-resize;
    float: right;
    position: relative;
    top: 45%;
    background-color: #d6d6d6;
    border-radius: 5px;
    margin-top: -10px;
    width: 10px;
    height: 50px;
    background-size: cover;
    background-position: center;
    font-size: 32px;
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
  }
</style>
最后放上几张骑行时拍的照片

iwEcAqNqcGcDAQTREgAF0Q2ABrD0zBqFOX4jCQY5KtVcxjsAB9MAAAAArMmCsQgACaJpbQoBC9IARv0T.jpg_720x720q90.jpg

iwEcAqNqcGcDAQTREgAF0Q2ABrBSAW-n_l9SzgY5KtxxFZgAB9MAAAAArMmCsQgACaJpbQoBC9IAQ3-A.jpg_720x720q90.jpg

iwEcAqNqcGcDAQTREgAF0Q2ABrDhhIxscQccgAY5KtlOTukAB9MAAAAArMmCsQgACaJpbQoBC9IARl-K.jpg_720x720q90.jpg

iwEdAqNqcGcDAQTREgAF0Q2ABrCDPPeoicbU5AY5WL-ozMgAB9MAAAAArMmCsQgACaJpbQoBC9IATFHX.jpg_720x720q90.jpg

iwEcAqNqcGcDAQTREgAF0Q2ABrAJ0Is4to4yywY5WMwhMrEAB9MAAAAArMmCsQgACaJpbQoBC9IAYI9v.jpg_720x720q90.jpg

iwEcAqNqcGcDAQTREgAF0Q2ABrBUBoy4QhlMOwY5WMbwKRgAB9MAAAAArMmCsQgACaJpbQoBC9IAUAdr.jpg_720x720q90.jpg

lQDPKIKghLh9XXHNDYDNEgCw0JT9og9W8h8GOVi7Q1MbAA_4608_3456.jpg_720x720q90.jpg

iwEcAqNqcGcDAQTRBDgF0QlgBrDmB_5eLTrf4wY5KtQfsJQAB9MAAAAArMmCsQgACaJpbQoAC9IAB8fw.jpg_720x720q90.jpg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值