当前位置: 首页 > 工具软件 > Guns > 使用案例 >

guns常用功能整理

马弘和
2023-12-01

guns常用功能整理

一、ajax接口请求(常用)

1.1:引入插件库
import axios from 'axios';
1.2:调用即可
axios({

​    url: 接口路径,

​    method: 请求方式,

   }).then(回调方法)

> 或者

 fetch(路径, {

​    method: 请求方法

   })

​ .then(回调)

二、es6模块调用

import { 方法名 } from 调用路径;

2.1:当前文件下使用
function debounce(){

// axios

}

export default{

debounce,

}
2.2:封装的代码暴露出去

三、创建template模板

3.1:html节点创建模板
<template #examine="{record }">

​      <a-space>

​              <a @click="examine(record.fileName)">查看</a>

​      </a-space>

​     </template>
3.2:常用于表格元素增加slots

slots: { customRender: ‘examine’ }

四、封装文件上传代码

4.1:利用es6导入导出原理,新建一个js文件
>static async blobDownload(url, params,filename) {

  if (params === undefined) {

   params = {};

  }

  if(filename === undefined){

   filename = '导出文件.xlsx'

  }

  const form = params

  axios({ // 用axios发送post请求

   method: 'post',

   url: url,

   data: form,

   responseType: 'blob' // 表明返回服务器返回的数据类型

  }).then((res) => { // 处理返回的文件流

​    const content = res.data

​    const blob = new Blob([content])

​    if ('download' in document.createElement('a')) { // 非IE下载

​     const elink = document.createElement('a')

​     elink.download = filename

​     elink.style.display = 'none'

​     elink.href = URL.createObjectURL(blob)

​     document.body.appendChild(elink)

​     elink.click()

​     URL.revokeObjectURL(elink.href) // 释放URL 对象

​     document.body.removeChild(elink)

​    } else { // IE10+下载

​     navigator.msSaveBlob(blob, filename)

​    }

​    return true

   })

 }
4.2:可以再次将接口调用代码进行封装,这样代码会更加简洁清晰
>static export(params,obj,name) {

  return Request.blobDownload('/ai-plus/bank/flow/task/result/excel?taskId='+params,obj,name);

 }
4.3:调用方法
export(record.jobId, record.jobName)

记住方法一定要导出才能够调用

五、图片的放大缩小以及移动切换

5.1:实现拖拽,主要是获取它当前的位置
let oImg = e.target;
      let disX = e.clientX - oImg.offsetLeft;
      let disY = e.clientY - oImg.offsetTop;
      document.onmousemove = e => {
        e.preventDefault();
        let left = e.clientX - disX;
        let top = e.clientY - disY;
        document.querySelector('.moveImage').style.left = left + 'px';
        document.querySelector('.moveImage').style.top = top + 'px';
      };
      document.onmouseup = () => {
        document.onmousemove = null;
        document.onmouseup = null;
      };
5.2:图片放大也是通过当前位置以及它的长宽来进行处理
let nowScrollTop = document.getElementById('masks').scrollTop;
      let nowScrollLeft = document.getElementById('masks').scrollLeft;
      if (nowScrollTop - (offsetY - pdfObj.imgOffsetY) >= 0) {
        document.getElementById('masks').scrollTop = nowScrollTop - (offsetY - pdfObj.imgOffsetY);
      }
      if (nowScrollLeft - (offsetX - pdfObj.imgOffsetX) >= 0) {
        document.getElementById('masks').scrollLeft = nowScrollLeft - (offsetX - pdfObj.imgOffsetX);
      }
5.3:图片的切换主要通过获取数组对应的下标以及其他信息
if (this.mainImgUrl.indexOf(imgUrl) !== -1) {
        let index = this.mainImgUrl.indexOf(imgUrl);
        this.mianImage(this.showMainImgUrl[index - 1], index - 1);
      } else {
        let index = this.detailImgUrl.indexOf(imgUrl);
        this.detailImage(this.showDetailImgUrl[index - 1], index - 1);
      }

具体可参照ai+后台管理系统sku文件

六、websocket长连接

6.1:获取长连接地址并继承
 websocket = new WebSocket('ws://172.168.30.5:8089/biSocket/1513721148340064257');
6.2:接着在websocket自带的方法体里面进行数据的回调以及错误判断
websocket.onopen = function () {
        console.log('连接已经建立');
      };
      websocket.onmessage = function (e) {
        getMessage(e);
      };
      websocket.onerror = function () {
        netWorkOutAge.value = true;
        console.log('发生错误');
        console.log('onerror发送成功');
        heartCheck.start();
      };
      websocket.onclose = function (e) {
        console.log('websocket 断开: ' + e.code + ' ' + e.reason + ' ' + e.wasClean);
        netWorkOutAge.value = true;
        document.querySelector('.main').setAttribute('style', 'opacity:0.4');
        console.log('onclose发送成功');
        //断开网络后连接网络刷新请求
        console.log('断开连接后发送成功');
        //连接关闭启动定时任务 五秒后在创建
        heartCheck.start();
      };
6.3:值得注意的点是,长连接需要保持一直通信,所以前端要不断发请求,类似于心跳机制,保证前后端连接不断开
//定时器 只执行一次的那种 只是为了限制重连频率 = =
    let heartCheck = {
      timeout: 5000, //重连时间
      timeoutObj: null,
      start: function () {
        this.timeoutObj = setTimeout(function () {
          websocket.send("{'messageType': 'ROBOT_CURRENT_JOB_ACK'}");
          getSocket(); //重新创建 websocket 对象并赋值
        }, this.timeout);
      }
    };

保证不断开的原理就是设置定时器,具体可看mro-bi-fronted这个项目代码

七、右侧固定导航栏

7.1:下载tocbot插件并且引用
import * as tocbot from 'tocbot';
7.2:直接初始化
tocbot.init({
                tocSelector: '.allTitles',
                contentSelector: '.content_left',
                ignoreSelector: 'js-toc-ignore',
                headingSelector: 'h1',
                scrollSmooth: true,
                hasInnerContainers: false,
                headingsOffset: 80,
                scrollSmoothOffset: true,
                fixedSidebarOffset: 'auto',
                scrollEndCallback: function() {
                  window.tocPhase = null;
                },
                onclick: function() {
                  window.tocPhase = true;
                }
              });

注意一定要注意它的执行栈的执行顺序,在异步中使用该方法

https://blog.csdn.net/cune1359/article/details/106844182

官方文档

八、文字高亮

文字高亮不仅后端可以处理,前端也可以处理

8.1:es6封装高亮代码
export function highLightTableMsg(msg, highLightStr) {
    if (msg == null) {
        msg = ''
    }
    if (highLightStr == null) {
      highLightStr = ''
    }
    if (msg instanceof Object) {
      msg = JSON.stringify(msg)
    }
    if (highLightStr instanceof Object) {
      highLightStr = JSON.stringify(highLightStr)
    }
    if (!(msg instanceof String)) {
      msg = msg.toString()
    }
    if (!(highLightStr instanceof String)) {
      highLightStr = highLightStr.toString()
    }
    var htmlStr = ''
    if (highLightStr.length > 0) {
      if (msg.indexOf(highLightStr) !== -1) {
        assemblyStr(msg, highLightStr)
      } else {
        htmlStr = '<span>' + msg + '</span>'
      }
    } else {
      htmlStr = '<span>' + msg + '</span>'
    }
    function assemblyStr(msgAssembly, highLightAssembly) {
      if (msgAssembly.indexOf(highLightAssembly) !== -1) {
        var length = highLightAssembly.length
        var start = msgAssembly.indexOf(highLightAssembly)
        htmlStr = htmlStr + '<span>' + msgAssembly.substring(0, start) + '</span>' + '<span class="log-hight-light" style="color:#C92B2F">' + highLightAssembly + '</span>'
        msgAssembly = msgAssembly.substring(start + length, msgAssembly.length)
        assemblyStr(msgAssembly, highLightAssembly)
      } else {
        htmlStr = htmlStr + '<span>' + msgAssembly + '</span>'
      }
    }
    return htmlStr
  }
8.2:调用执行即可
import { highLightTableMsg } from '../../utils/highLight';
highLightTableMsg(val, searchValue); //查询结果标红

两个参数分别对应标题和文本

九、输入框防抖

9.1:下载lodash-es插件

import { debounce } from ‘lodash-es’;

9.2:以下为防抖代码
//防抖防止多次调用
    const filterOption = debounce(async value => {
      let allDataValue = await axios.get(`store/mall/list?storeName=${value}`);
      if (allDataValue.data.code === '00000') {
        if (allDataValue.data.data.length > 0) {
          allDataValue.data.data.forEach(() => {
            dataValue.value = allDataValue.data.data.map(element => ({
              value: element.storeName,
              storeId: element.storeId
            }));
          });
          storeArr.push(...allDataValue.data.data)
          fetch.value = true;
        } else {
          fetch.value = false;
        }
      }
    }, 300);
9.3:运用到当前的输入框组件当中
<a-select
          show-search
          placeholder="请输入店铺名称"
          style="width: 300px"
          :default-active-first-option="false"
          :show-arrow="false"
          :not-found-content="fetch ? undefined : '搜索内容不存在'"
          @search="filterOption"
          :getPopupContainer="
            triggerNode => {
              return triggerNode.parentNode || document.body;
            }
          "
          :options="dataValue"
          @change="handleChange"
        >
          <template v-if="fetch" #notFoundContent>
            <a-spin size="small"></a-spin>
          </template>
        </a-select>

10、table组件常用

10.1:数据表格table https://www.antdv.com/components/table/#Table官方文档
10.2:组件常用
<ele-pro-table
          ref="table"
          row-key="brandId"
          :datasource="url"
          :columns="columns"
          :where="where"
          @change="tablaChange"
          v-model:selection="selection"
          :scroll="{ x: 'max-content' }"
        >
        </ele-pro-table>

组件自带的有分页,请求地址,还有页码点击的事件

比如说@change事件就代表获取当前页数
tablaChange(pagination) {
      this.pageNo = pagination.current;
    }
10.3:表头设置
const columns = [
      {
        title: '商城订单编号',
        dataIndex: 'ordersSn'
      },
      {
        title: 'orderId',
        dataIndex: 'omsSn'
      },
      {
        title: 'OMS推送状态',
        dataIndex: 'omsCreateStatus',
        customRender: record => {
          return record.record.omsCreateStatus == 1 ? '推送成功' : '推送失败';
        }
      },
      {
        title: '下单企业名称',
        dataIndex: 'companyName'
      },
      {
        title: '下单用户名称',
        dataIndex: 'memberName'
      },
      {
        title: '用户联系电话',
        dataIndex: 'memberMobile'
      },
      {
        title: '商城订单状态',
        dataIndex: 'ordersStateName'
      },
      {
        title: '订单金额',
        dataIndex: 'ordersAmount'
      },
      
      {
        title: '支付方式',
        dataIndex: 'payment',
        customRender: record => {
          return record.text == 0 ? '在线支付' : record.text == 1 ? '线下支付' : '账期支付';
        }
      },
      {
        title: '下单时间',
        dataIndex: 'createTime',
        // customRender: ({ item }) => moment(item).format('YYYY-MM-DD:HH:MM:SS')
      },
      {
        title: '操作',
        key: 'action',
        width: 150,
        align: 'center',
        slots: { customRender: 'action' }
      }
    ];
10.4:表格内容体里面要设置动态的数据或者是是否可操作可以使用插槽的方式
在当前表头设置
customRender: record => {
          return record.text == 0 ? '在线支付' : record.text == 1 ? '线下支付' : '账期支付';
        }
其次就可以生成模板在文本当中
<!-- table操作栏按钮 -->
          <template #action="{ record }">
            <a-space>
              <a @click="openEdit(record)">详情</a>
              <a-divider type="vertical" />
              <a-popconfirm
                v-if="record.omsCreateStatus !== 1"
                title="是否确定要重新推送"
                ok-text="是"
                cancel-text="否"
                @confirm="confirm(record.ordersId)"
                @cancel="cancel"
              >
                <a href="#">重新推送</a>
              </a-popconfirm>
            </a-space>
          </template>

提示:局部刷新表格可以通过ajax请求的原理,增加一个loading框让用户以为是在刷新界面

11、弹出层

弹出层主要是父与子之间的通信,利用父传子的原理

11.1:将需要设为弹窗的组件置于父组件当中
调用子组件
import { BrandApi } from '@/api/BrandApi';
生成模板即可
<!-- 编辑弹窗 -->
  <brand-edit v-model:visible="showEdit" :data="current" @done="reload" />

可以看出,‘ :’是父组件传给子组件的值;‘@’是传递的一种方法回调

11.2:子组件接收参数
emits: ['done', 'update:visible'],
  inject: ['reload'],
  props: {
    // 弹窗是否打开
    visible: Boolean,
    // 修改回显的数据
    data: Object
  },

不了解的小伙伴可以看看这篇博客

http://events.jianshu.io/p/be840cc0fa6a

11.3:子组件当中多为输入框回显以及下拉框的形式

一般来说,会先都是通过v-model双向绑定来实现的

其次,回显得注意那些为必填非必填的情况

// 表单验证规则
     const rules = {
        showImage: [{ required: true, message: '请输入品牌图片', type: 'string', trigger: 'blur' }],
        brandName: [{ required: true, message: '请输入品牌名称', type: 'string', trigger: 'blur' }],
        registerNumber: [{ required: true, message: '请输入商标注册号', type: 'string', trigger: 'blur' }]
      },

常见的坑

一、下拉框脱离文本

在根节点添加这个方法即可
:getPopupContainer="
                (triggerNode) => {
                return triggerNode.parentNode || document.body
                }"

二、在guns系统当中路由跳转数据不更新,watch和computed都不管用?

直接使用unUpdated生命周期即可

三、在使用长连接或者其他需要使用到setInterval或者setTimeout时处理完毕时一定要终止它,否则长时间不处理会导致内存溢出,界面卡死

说明

我们系统主要是用vue3.x加上ant-design插件库为了方便代码维护

vue3.x

https://cn.vuejs.org/

ant-design

https://www.antdv.com/components/overview

 类似资料: