业务导向功能实现

231 阅读9分钟

持续更新中

概览

富文本组件

使用的插件是tinymce

安装依赖

npm install --save "@tinymce/tinymce-vue@^5"

页面

addPlatform.vue

模板部分:

<template>
    <Editor
      :api-key="apiKey"
      :init="initConfig"
       v-model="editeContent"
     />
</template>

逻辑部分:

import Editor from '@tinymce/tinymce-vue'
const apiKey = ref('lg9kxl5afdfwpfcrogrv5ewn9vdhm6q4vwhu6d1qyiebrhn5')
const initConfig = ref({
  menubar: false, // 不显示任何菜单栏
  language: 'zh_CN',
  plugins: 'anchor autolink hr charmap codesample emoticons image link lists media searchreplace table visualblocks wordcount checklist mediaembed casechange export formatpainter pageembed linkchecker a11ychecker tinymcespellchecker permanentpen powerpaste advtable advcode editimage advtemplate mentions tableofcontents footnotes mergetags autocorrect typography inlinecss markdown fullscreen',
  toolbar: [
    'blocks blockquote | bold underline italic forecolor backcolor | fontsize fontfamily lineheight | bullist numlist checklist | alignleft',
    'alignright | emoticons link image | table codesample hr | undo redo | fullscreen '
  ],
  // 设置行高
  line_height_formats: '1 1.2 1.4 1.6 2'
})
const editeContent = ref('')

图片上传

addPlatform.vue

const apiKey = ref('lg9kxl5afdfwpfcrogrv5ewn9vdhm6q4vwhu6d1qyiebrhn5')
const initConfig = ref({
  menubar: false, // 不显示任何菜单栏
  language: 'zh_CN',
  plugins: 'anchor autolink hr charmap codesample emoticons image link lists media searchreplace table visualblocks wordcount linkchecker fullscreen',
  toolbar: [
    'blocks blockquote | bold underline italic forecolor backcolor | fontsize fontfamily lineheight | bullist numlist | alignleft',
    'alignright | emoticons link image | table codesample hr | undo redo | fullscreen '
  ],
  line_height_formats: '1 1.2 1.4 1.6 2',
  images_file_types: 'jpeg,png,jpg,svg,webp',
  file_picker_types: 'image',
  automatic_uploads: true,
  // 用于自定义处理文件选择和上传的逻辑
  file_picker_callback: (cb) => {
    const input = document.createElement('input');
    input.setAttribute('type', 'file');
    input.setAttribute('accept', 'image/*');

    input.addEventListener('change', (e) => {
      let file
      const fileInput = e.target as HTMLInputElement;
      if (fileInput.files && fileInput.files.length > 0) {
            file = fileInput.files[0];
        } else {
          // 处理没有文件或文件列表为空的情况
          console.error('选择的不是文件');
        }

      const reader = new FileReader();
      reader.addEventListener('load', () => {
        /*
          Note: Now we need to register the blob in TinyMCEs image blob
          registry. In the next release this part hopefully won't be
          necessary, as we are looking to handle it internally.
        */
        const id = 'blobid' + (new Date()).getTime();
        
        const blobCache =  tinymce.activeEditor.editorUpload.blobCache;
        const base64 = (reader.result as string)?.split(',')[1];
        const blobInfo = blobCache.create(id, file, base64);
        blobCache.add(blobInfo);

        /* call the callback and populate the Title field with the file name */
        cb(blobInfo.blobUri(), { title: file.name });
      });
      reader.readAsDataURL(file);
    });

    input.click();
  }
})

ts报错

问题原因:由于tinymce变量是被npm挂载到window下面的,所以ts找不到。

解决方法:在项目的 src 目录下创建一个 typings.d.ts 文件

typings.d.ts

// global.d.ts 或 typings.d.ts
declare var tinymce: any; // 或者更具体的类型定义

域名问题

这个组件如果访问需要配合域名的,否则无法访问。

添加域名:www.tiny.cloud/my-account/…

大屏开发

高德地图

效果图

整体代码

<template>
  <div id="mapEcharts" style="width: 100%;height: 600px;"></div>
</template>

<script>
  export default {
    name: 'MapView',
    mounted() {
      this.draw();
    },
    methods:{
      draw(){
        // 初始化地图
        var map = new AMap.Map('mapEcharts', {
            zoom: 8, // 初始地图级别
            center: [116.39,39.9], // 地图中心点坐标
        });

        // 示例点数据
        var points = [
            [116.41,40.92],
            [116.42,39.91],
        ];

        // 定义一个全局变量来保存当前打开的信息窗口,以便在鼠标移出时关闭
        let currentInfoWindow = null;
        // 在地图上添加散点并绑定事件
        points.forEach((point,index) => {
          const marker = new AMap.Marker({
            position: point,
          });
          marker.setMap(map);
          // 绑定mouseover事件
          AMap.Event.addListener(marker, 'mouseover', () => {
            // 如果之前有打开的信息窗口,先关闭它
            if (currentInfoWindow) {
              currentInfoWindow.close();
            }
            
            // 创建新的信息窗口
            const infoWindow = new AMap.InfoWindow({
              content: `<div style="background-color: white;">这是第${index + 1}个点的详细信息</div><br>454`,
              offset: new AMap.Pixel(0, -30), // 设置信息窗口偏移量
            });
            
            // 打开信息窗口
            infoWindow.open(map, marker.getPosition());
            currentInfoWindow = infoWindow; // 更新当前信息窗口引用
          });

          // 绑定mouseout事件以关闭信息窗口
          AMap.Event.addListener(marker, 'mouseout', () => {
            if (currentInfoWindow) {
              currentInfoWindow.close();
              currentInfoWindow = null;
            }
          });
        });
    }
  }
}
</script>

<style scoped>
</style>

注意

  1. 监听事件的写法:
  • 如果是引入了高德地图的2.0版本,Event是大写,AMap.Event.addListener

  • 如果是引入了高德地图的1.4版本,event是小写,AMap.event.addListener

  1. 地图样式

与百度地图不同,高德地图是在控制台配置上去的,发布完自定义地图,在代码里定义一个id,样式自动更新。

第一步,配置地图

配置地图的步骤:

  1. 访问高德地图开放平台的官网:lbs.amap.com/
  2. 登录你的高德地图账号。
  3. 在顶部导航栏中找到“开发工具”或“开发者工具”,通常在页面的右上角。
  4. 在“开发工具”下拉菜单中选择“自定义地图样式”或类似的选项。
  5. 这里你应该能看到地图样式编辑器,可以创建、编辑和管理你的自定义地图样式。

如果你仍然找不到入口,建议直接在高德地图开放平台的首页搜索“自定义地图样式”或查看官方文档,以获取最新的接入指南。同时,确保你拥有有效的高德地图开发者账号,因为一些高级功能可能需要付费或申请权限。

第二步,引入安全密钥

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <div id="app"></div>
    <!-- 安全密钥 -->
    <script>
      window._AMapSecurityConfig = {
        securityJsCode: 'aa6d5d2d1b665c87f77869e3d9371ce8'
      };
    </script>
    <script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=ab0cf27461eccdad490ccc839563c368"></script>
  </body>
</html>

SSE

什么场景下使用SSE?

  1. 实时数据展示: 如果大屏需要实时展示从服务器端获取的数据,比如股票价格、传感器数据、实时分析数据或物联网设备的状态更新,SSE 可以实现实时推送这些数据到客户端,而无需客户端频繁地轮询服务器。
  2. 低延迟数据更新: SSE 提供了较低的延迟数据传输方式,这对于需要及时更新信息的大屏应用非常有用。例如,在监控系统中,可能需要快速反应最新的警报或事件。
  3. 单向数据流: 当大屏应用只需要接收数据而不发送数据到服务器时,SSE 是一个很好的选择。这是因为 SSE 设计为单向通信,即服务器到客户端的数据推送。
  4. 资源限制环境: 对于资源受限的环境,如移动设备或某些嵌入式系统,SSE 可能比 WebSocket 更节省资源,因为它使用 HTTP 协议,可以更容易地通过现有的代理和防火墙。
  5. 简单部署和维护: SSE 相对容易实现和维护,因为它使用标准的 HTTP 连接,不需要像 WebSocket 那样设置特殊的握手协议。

然而,SSE 也有一些局限性,例如:

  • 单向通信:它只支持从服务器到客户端的数据流,如果需要双向通信,则应考虑使用 WebSocket。
  • 浏览器兼容性:尽管现代浏览器广泛支持 SSE,但在一些旧版或特定的浏览器中可能不支持,这可能需要额外的兼容性处理。

如何使用SSE?

原理:主要涉及创建一个EventSource对象并监听其事件。

步骤1: 创建 EventSource 对象

首先,你需要创建一个 EventSource 对象,传入你的服务器端点URL作为参数。这个URL应该返回SSE格式的数据流。

const eventSource = new EventSource('/api/sse-endpoint');

步骤2: 监听事件

接下来,你需要监听 message 事件,这是当服务器推送数据时触发的事件。你也可以监听 openerror 事件来处理连接状态的变化。

eventSource.addEventListener('message', function(event) {
    // 解析 event.data,通常它是一个 JSON 字符串
    const data = JSON.parse(event.data);
    
    // 根据数据更新大屏界面
    updateDisplay(data);
});

// 连接打开时触发
eventSource.addEventListener('open', function(event) {
    console.log('SSE connection opened.');
});

// 错误处理
eventSource.addEventListener('error', function(event) {
    if (event.target.readyState === EventSource.CLOSED) {
        console.error('SSE connection closed.');
    } else {
        console.error('SSE error occurred.');
    }
});

步骤3: 数据处理与显示

message 事件的回调函数中,你需要解析接收到的数据,并根据数据更新大屏的显示。这通常涉及到将JSON字符串转换为JavaScript对象,然后更新DOM元素。

function updateDisplay(data) {
    // 更新DOM元素,例如:
    document.getElementById('sensor-value').innerText = data.value;
}

步骤4: 关闭 EventSource

在不再需要接收数据时,记得关闭 EventSource 对象以释放资源。

eventSource.close();

完整示例代码

// 创建 EventSource 对象
const eventSource = new EventSource('/api/sse-endpoint');

// 监听 'message' 事件
eventSource.addEventListener('message', function(event) {
    const data = JSON.parse(event.data);
    updateDisplay(data);
});

// 连接打开时触发
eventSource.addEventListener('open', function(event) {
    console.log('SSE connection opened.');
});

// 错误处理
eventSource.addEventListener('error', function(event) {
    if (event.target.readyState === EventSource.CLOSED) {
        console.error('SSE connection closed.');
    } else {
        console.error('SSE error occurred.');
    }
});

// 数据处理与显示
function updateDisplay(data) {
    document.getElementById('sensor-value').innerText = data.value;
}

// 关闭 EventSource
// 在适当的时机调用
eventSource.close();

确保你的服务器端正确设置了SSE格式的数据流,通常是以 text/event-stream 的Content-Type进行响应,并且每条数据都以 data: 开头,后跟数据内容。

Excel导出功能

第一步:安装依赖库

首先需要安装 xlsx

npm install xlsx --save

第二步:编写业务代码

假设你有一个HTML表格,并且想要将其内容导出到Excel文件中,你可以使用以下JavaScript代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Export Table to Excel</title>
    <script src="https://unpkg.com/xlsx@0.17.0/dist/xlsx.full.min.js"></script>
</head>
<body>
    <table id="sampleTable">
        <thead>
            <tr>
                <th>Name</th>
                <th>Age</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>John Doe</td>
                <td>30</td>
            </tr>
            <tr>
                <td>Jane Doe</td>
                <td>25</td>
            </tr>
        </tbody>
    </table>
    <button onclick="exportTableToExcel()">Export to Excel</button>

    <script>
        function exportTableToExcel() {
            var table = document.getElementById('sampleTable');
            var wb = XLSX.utils.table_to_book(table, { sheet: "Sheet JS" });
            return XLSX.write(wb, { bookType: 'xlsx', type: 'binary' });
        }
    </script>
</body>
</html>

解释:

  • var wb = XLSX.utils.table_to_book(table, { sheet: "Sheet JS" });,使用了 xlsx 库中的 table_to_book 函数,作用是将HTML表格转换成一个Excel工作簿对象 (wb),该函数接收两个参数:
    • 第一个参数是表格元素 (table)。
    • 第二个参数是一个配置对象,其中的 sheet 属性指定了输出的Excel工作表的名字。这里设置为 "Sheet JS"。
  • return XLSX.write(wb, { bookType: 'xlsx', type: 'binary' });,使用 XLSX.write 函数将工作簿对象 (wb) 写入到一个Excel文件中,作用是返回一个字符串,该字符串包含了Excel文件的内容。它接收两个参数:
    • 第一个参数是工作簿对象 (wb)。
    • 第二个参数是一个配置对象,包含以下属性:
      • bookType: 指定输出文件的类型。这里设置为 'xlsx',意味着输出的是 .xlsx 文件格式。
      • type: 指定输出文件的数据格式。这里设置为 'binary',意味着输出的数据是以二进制字符串的形式。

第三步:触发下载

你需要添加一些额外的代码来触发文件的下载:

function exportTableToExcel() {
    var table = document.getElementById('sampleTable');
    var wb = XLSX.utils.table_to_book(table, { sheet: "Sheet JS" });
    var wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' });

    function s2ab(s) {
        var buf = new ArrayBuffer(s.length);
        var view = new Uint8Array(buf);
        for (var i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
        return buf;
    }

    saveAs(new Blob([s2ab(wbout)], {type: 'application/octet-stream'}), 'test.xlsx');
}

// 引入 FileSaver.js 用于保存文件
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>

这里我们使用了 FileSaver.js 库来处理文件的保存,因此还需要引入这个库。这样当用户点击按钮时,就会触发Excel文件的下载。

解释:

  • s2ab是辅助函数,这个辅助函数用于将二进制字符串 (s) 转换成 ArrayBuffer 对象。它通过遍历字符串中的每个字符,将其转换成对应的字节,并存储在一个 Uint8Array 中,然后返回这个 Uint8Array 所关联的 ArrayBuffer
  • saveAs(new Blob([s2ab(wbout)], {type: 'application/octet-stream'}), 'test.xlsx'),主要作用是触发浏览器文件下载流程,它会触发浏览器的文件下载对话框,让用户能够保存文件。接收两个参数:
    • 第一个参数是一个 Blob 对象,它包含要下载的数据。这里使用 s2ab(wbout) 将Excel文件数据转换成 ArrayBuffer 并包装成 Blob。
    • 第二个参数是下载文件的名称,这里是 'test.xlsx'

小结

这段代码的功能是从HTML页面中获取一个特定的表格,将其转换为Excel文件,并自动触发下载。最终用户会看到一个名为 test.xlsx 的文件,里面包含了原始表格的数据。如果需要在实际环境中运行此代码,请确保已经正确加载了必要的库(例如 xlsxFileSaver.js),并且HTML页面中存在相应的表格元素。