在线代码编辑器

在线代码编辑器

    • 文章说明
    • 前台核心代码
    • 后台核心代码
    • 效果展示
    • 源码下载

文章说明

采用Java结合vue3设计实现的在线代码编辑功能,支持在线编辑代码、运行代码,同时支持导入文件,支持图片识别,支持复制代码,可将代码导出为图片

暂时还未添加图片代码识别导入的功能,然后目前Linux版本下安装C#的编译器我还没找到好的方案,这个C#代码运行在Linux环境下暂时有点问题

目前对于代码安全方面还未添加校验,只作为简单的学习使用,存在着不小的风险,后续会考虑新开坑,书写更完善的在线编辑器

目前的这个结果展示的编码方面还有一些问题,主要是控制台输入、命令行以及文件本身的编码会有不一致的情况,有些难整,后续考虑采用新方案给这个问题解决一下

前台核心代码

前台主要采用 md-editor-v3 编辑器作为代码编辑区域,虽然没有提示功能,但是展示效果上会好一些,然后运行的时候调用后台接口,采用Java调用cmd命令行来实现代码的运行

其中代码下载为图片采用的是对dom对象进行下载,采用html2canvas来实现,会有一些小bug,不过效果感觉还可以

前台核心代码

<script setup>
import {MdEditor, MdPreview} from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
import 'md-editor-v3/lib/preview.css';
import {computed, onBeforeMount, reactive, ref, watch} from "vue";
import html2canvas from "html2canvas";
import {
  confirm,
  downloadFileToLocalByUrl,
  exportCommon,
  getRequest,
  loading,
  message,
  postRequest,
  prompt
} from "@/util";

const data = reactive({
  language: "",
  codeText: "",
  inputText: "",
  displayText: "",
  exportDialogVisible: false,
  exportImgUrl: "",
  uploadExist: true,
});

const languageList = [
  "Java",
  "Python",
  "Javascript",
  "C",
  "C++",
  "C#",
];

const codeText = computed(() => {
  return "```" + data.language + "\n" + data.codeText + "\n```"
});

function exportCodeToImg() {
  const displayContent = document.getElementsByClassName("display-content")[0];
  data.exportDialogVisible = true;
  html2canvas(displayContent, {}).then((canvas) => {
    data.exportImgUrl = canvas.toDataURL('image/png');
  });
}

function exportCode() {
  prompt("导出代码文件", "导出代码文件名称", data.language + "_" + new Date().toLocaleString() + ".txt", (value) => {
    exportCommon(data.codeText, value);
  });
}

function exportCodeToImgConfirm() {
  prompt("导出代码图片", "导出代码图片名称", data.language + "_" + new Date().toLocaleString() + ".png", (value) => {
    downloadFileToLocalByUrl(data.exportImgUrl, value);
    data.exportDialogVisible = false;
  });
}

function reset() {
  confirm("确认清空吗,包括代码区域、控制台文件输入以及结果展示区域?", () => {
    data.codeText = "";
    data.inputText = "";
    data.displayText = "";
  });
}

function run() {
  if (!data.language) {
    message("请先选择编程语言", "warning");
    return;
  }
  const loadingInstance = loading("运行中...");
  postRequest("/codeRunner/run", null, {
    language: data.language,
    codeText: data.codeText,
    inputText: data.inputText,
  }).then((res) => {
    loadingInstance.close();
    if (res.data.code === 200) {
      data.displayText = res.data.data;
      message("代码运行成功", "success");
    } else if (res.data.code === 500) {
      message("代码运行失败", "error");
    }
  })
}

const languageText = {};

onBeforeMount(async () => {
  for (let i = 0; i < languageList.length; i++) {
    languageText[languageList[i]] = await getLanguageDefaultText(languageList[i]);
  }
});

async function getLanguageDefaultText(language) {
  const res = await getRequest("/codeRunner/getDefaultText", {
    language
  });
  if (res.data.code === 200) {
    return res.data.data;
  } else if (res.data.code === 500) {
    message(language + "语言默认代码获取失败", "error");
  }
}

watch(() => data.language, (newValue, oldValue) => {
  if (data.codeText) {
    languageText[oldValue] = data.codeText;
  }
  data.codeText = languageText[data.language];
});

const uploadFileRef = ref();

function uploadFile(event) {
  const loadingInstance = loading("导入中...");
  const file = event.target.files[0];
  const reader = new FileReader();
  reader.readAsText(file, 'utf8');
  data.uploadExist = false;
  reader.onload = () => {
    loadingInstance.close();
    const codeText = reader.result.toString();
    data.uploadExist = true;
    if (!codeText) {
      message("导出文件内容为空", "warning");
      return;
    }
    data.codeText = codeText;
  }
}

function singleImport() {
  if (!data.language) {
    message("请先选择编程语言", "warning");
    return;
  }
  if (!data.uploadExist) {
    return;
  }
  uploadFileRef.value.click();
}
</script>

<template>
  <div class="container">
    <div class="tool-bar">
      <div class="row">
        <el-select v-model="data.language" placeholder="请选择编程语言" style="width: 80%">
          <template v-for="item in languageList" :key="item">
            <el-option :label="item" :value="item"/>
          </template>
        </el-select>
      </div>
      <div class="row" style="margin-top: -0.5rem">
        <el-button type="primary" @click="run">运行</el-button>
        <el-button type="danger" @click="reset">清空</el-button>
        <el-button type="danger" @click="singleImport">导入代码</el-button>
        <input v-if="data.uploadExist" ref="uploadFileRef" accept=".txt,.java,.py,.js,.c,.cpp,.cs" style="display: none"
               type="file" @change="uploadFile($event)">
      </div>
      <div class="row" style="margin-top: -0.5rem">
        <el-button type="primary" @click="exportCode">导出代码</el-button>
        <el-button type="danger" @click="exportCodeToImg">下载为图片</el-button>
      </div>
    </div>
    <div class="content-container">
      <div class="editor-content">
        <MdEditor v-model="data.codeText" :preview="false" :toolbars="[]" placeholder="代码输入区域"
                  style="height: 100%; width: 100%" theme="dark"/>
      </div>
      <div class="display-content">
        <MdPreview v-model="codeText" :show-code-row-number="false" style="height: 100%; width: 100%"/>
      </div>
      <div class="input-content">
        <MdEditor v-model="data.inputText" :preview="false" :toolbars="[]" placeholder="控制台文件输入区域"
                  style="height: 100%; width: 100%" theme="dark"/>
      </div>
      <div class="result-content">
        <MdEditor v-model="data.displayText" :preview="false" :toolbars="[]" placeholder="结果展示区域" read-only
                  style="height: 100%; width: 100%" theme="dark"/>
      </div>
    </div>
  </div>

  <el-dialog v-model="data.exportDialogVisible" title="代码下载为图片" width="90%">
    <img :src="data.exportImgUrl" alt="" style="width: 100%; height: auto"/>
    <template #footer>
      <el-button type="primary" @click="data.exportDialogVisible = false">取消</el-button>
      <el-button type="danger" @click="exportCodeToImgConfirm">确认</el-button>
    </template>
  </el-dialog>
</template>

<style lang="scss">
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

.container {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;

  .tool-bar {
    height: 9rem;
    background-color: #282c34;
    border-bottom: 0.1rem solid gray;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    user-select: none;

    .row {
      width: 100%;
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: center;
    }
  }

  .content-container {
    flex: 1;
    overflow: auto;
    display: flex;
    flex-direction: column;

    &::-webkit-scrollbar {
      width: 0;
      height: 0;
    }

    .md-editor-footer {
      display: none;
    }

    .cm-scroller {
      background-color: #282c34;
    }

    .editor-content {
      height: fit-content;
      border-bottom: 0.1rem solid gray;
    }

    .display-content {
      height: fit-content;
      border-bottom: 0.1rem solid gray;

      .md-editor-preview-wrapper {
        padding: 0;
      }

      .md-editor-code {
        margin: 0;
      }

      .md-editor-code-head {
        border-radius: 0 !important;
      }

      code {
        border-radius: 0 !important;
        white-space: pre-wrap;
      }
    }

    .input-content {
      flex: 1;
      background-color: #282c34;
      border-bottom: 0.1rem solid gray;
    }

    .result-content {
      flex: 1;
      background-color: #282c34;
    }
  }
}
</style>

后台核心代码

后台采用命令行运行代码,在Java、C、C++、C#,代码运行时会需要多步骤进行,目前采用的都是将代码写入到指定文件,然后采用指定命令运行绝对路径的文件,限制较大,后续考虑运行项目的形式,可以更加方便的解决文件编码问题以及代码运行问题

Java调用cmd运行代码工具类

package com.boot.util;

import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;

import static com.boot.util.DefaultConfig.*;
import static com.boot.util.LanguageType.*;

/**
 * @author bbyh
 * @date 2023/2/27 0027 15:10
 */
@Slf4j
public class ExecUtil {
    public static String exec(String language, String codeText, String inputText) throws Exception {
        File codeTextInputFile = new File(LANGUAGE_INPUT_FILE_MAP.get(language));
        if (codeTextInputFile.exists()) {
            try (FileOutputStream outputStream = new FileOutputStream(codeTextInputFile)) {
                outputStream.write(codeText.getBytes(StandardCharsets.UTF_8));
            }
        }
        File inputTextInputFile = new File(INPUT_TEXT_PUT_FILE);
        if (inputTextInputFile.exists()) {
            try (FileOutputStream outputStream = new FileOutputStream(inputTextInputFile)) {
                outputStream.write(inputText.getBytes(StandardCharsets.UTF_8));
            }
        }

        if (judgeLinux()) {
            int exeCode = execLinux(language);
            logCodeTextRunLog(language, codeText, inputText, exeCode);
        } else if (judgeWindows()) {
            int exeCode = execWindows(language);
            logCodeTextRunLog(language, codeText, inputText, exeCode);
        }
        String[] outputFileNames = {ERROR_OUTPUT_FILE, OUTPUT_FILE};
        for (String outputFileName : outputFileNames) {
            File outputFile = new File(outputFileName);
            if (outputFile.exists()) {
                try (FileInputStream inputStream = new FileInputStream(outputFile)) {
                    byte[] buf = new byte[1024 * 1024];
                    int read = inputStream.read(buf);
                    if (read >= 0) {
                        String result = new String(buf, 0, read);
                        String encoding = getEncoding(result);
                        if (!"".equals(encoding)) {
                            return new String(buf, 0, read, encoding);
                        }
                    }
                }
            }
        }
        return "";
    }

    private static void logCodeTextRunLog(String language, String codeText, String inputText, int exeCode) {
        log.info("运行时间:{}", new Date());
        log.info("编程语言:{}", language);
        log.info("运行代码:{}", codeText);
        log.info("运行输入:{}", inputText);
        log.info("运行结果:{}", exeCode);
    }

    private static int execLinux(String language) throws Exception {
        switch (language) {
            case JAVA:
                if (execLinuxCommand("javac " + JAVA_INPUT_FILE + " > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE) == 0) {
                    int start = JAVA_INPUT_FILE.lastIndexOf("/") + 1;
                    int end = JAVA_INPUT_FILE.lastIndexOf(".");
                    String javaClassFileName = JAVA_INPUT_FILE.substring(start, end);
                    return execLinuxCommand("java -classpath " + LINUX_PREFIX + " " + javaClassFileName + " < " + INPUT_TEXT_PUT_FILE + " > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE);
                }
                return 0;
            case PYTHON:
                return execLinuxCommand("python " + PYTHON_INPUT_FILE + " < " + INPUT_TEXT_PUT_FILE + " > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE);
            case JAVASCRIPT:
                return execLinuxCommand("node " + JAVASCRIPT_INPUT_FILE + " < " + INPUT_TEXT_PUT_FILE + " > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE);
            case C:
                if (execLinuxCommand("gcc " + C_INPUT_FILE + " -o " + LINUX_PREFIX + "a.exe > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE) == 0) {
                    return execLinuxCommand(LINUX_PREFIX + "a.exe < " + INPUT_TEXT_PUT_FILE + " > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE);
                }
                return 0;
            case C_PLUS_PLUS:
                if (execLinuxCommand("g++ " + C_PLUS_PLUS_INPUT_FILE + " -o " + LINUX_PREFIX + "a.exe > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE) == 0) {
                    return execLinuxCommand(LINUX_PREFIX + "a.exe < " + INPUT_TEXT_PUT_FILE + "> " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE);
                }
                return 0;
            case C_SHARP:
                if (execLinuxCommand("csc /out:" + LINUX_PREFIX.replaceAll("/", "\\\\") + "a.exe "
                        + C_SHARP_INPUT_FILE.replaceAll("/", "\\\\") + " > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE) == 0) {
                    return execLinuxCommand(LINUX_PREFIX + "a.exe < " + INPUT_TEXT_PUT_FILE + " > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE);
                }
                return 0;
        }
        return 0;
    }

    private static int execLinuxCommand(String command) throws Exception {
        ArrayList<String> commandList = new ArrayList<>();
        commandList.add("/bin/sh");
        commandList.add("-c");
        commandList.add(command);
        Process exec = Runtime.getRuntime().exec(commandList.toArray(new String[0]));
        return exec.waitFor();
    }

    private static int execWindows(String language) throws Exception {
        switch (language) {
            case JAVA:
                if (execWindowsCommand("javac " + JAVA_INPUT_FILE + " > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE) == 0) {
                    int start = JAVA_INPUT_FILE.lastIndexOf("/") + 1;
                    int end = JAVA_INPUT_FILE.lastIndexOf(".");
                    String javaClassFileName = JAVA_INPUT_FILE.substring(start, end);
                    return execWindowsCommand("java -classpath " + WINDOWS_PREFIX + " " + javaClassFileName + " < " + INPUT_TEXT_PUT_FILE + " > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE);
                }
                break;
            case PYTHON:
                return execWindowsCommand("python " + PYTHON_INPUT_FILE + " < " + INPUT_TEXT_PUT_FILE + " > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE);
            case JAVASCRIPT:
                return execWindowsCommand("node " + JAVASCRIPT_INPUT_FILE + " < " + INPUT_TEXT_PUT_FILE + " > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE);
            case C:
                if (execWindowsCommand("gcc " + C_INPUT_FILE + " -o " + WINDOWS_PREFIX + "a.exe > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE) == 0) {
                    return execWindowsCommand(WINDOWS_PREFIX + "a.exe < " + INPUT_TEXT_PUT_FILE + " > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE);
                }
                return 0;
            case C_PLUS_PLUS:
                if (execWindowsCommand("g++ " + C_PLUS_PLUS_INPUT_FILE + " -o " + WINDOWS_PREFIX + "a.exe > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE) == 0) {
                    return execWindowsCommand(WINDOWS_PREFIX + "a.exe < " + INPUT_TEXT_PUT_FILE + " > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE);
                }
                return 0;
            case C_SHARP:
                if (execWindowsCommand("csc /out:" + WINDOWS_PREFIX.replaceAll("/", "\\\\") + "a.exe "
                        + C_SHARP_INPUT_FILE.replaceAll("/", "\\\\") + " > " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE) == 0) {
                    return execWindowsCommand(WINDOWS_PREFIX + "a.exe < " + INPUT_TEXT_PUT_FILE + "> " + OUTPUT_FILE + " 2> " + ERROR_OUTPUT_FILE);
                }
                return 0;
        }
        return 0;
    }

    private static int execWindowsCommand(String command) throws Exception {
        Process exec = Runtime.getRuntime().exec("cmd /c " + command);
        return exec.waitFor();
    }

    public static Boolean judgeWindows() {
        return System.getProperty("os.name").toLowerCase().contains("windows");
    }

    public static Boolean judgeLinux() {
        return System.getProperty("os.name").toLowerCase().contains("linux");
    }

    public static String getEncoding(String str) throws Exception {
        String[] encodes = {"UTF-8", "GBK"};
        for (String encode : encodes) {
            if (str.equals(new String(str.getBytes(encode), encode))) {
                return encode;
            }
        }
        return "";
    }

}

效果展示

运行Java代码
在这里插入图片描述

运行Python代码
在这里插入图片描述

运行JavaScript代码
在这里插入图片描述

运行C语言代码
在这里插入图片描述

运行C++代码
在这里插入图片描述

运行C#代码
在这里插入图片描述

将代码下载为图片
在这里插入图片描述

源码下载

在线代码编辑器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/886027.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《RabbitMQ篇》基本概念介绍

MQ功能 解耦 MQ允许不同系统或组件之间松散耦合。发送者和接收者不需要直接连接&#xff0c;从而提高了系统的灵活性和可维护性。异步处理 使用MQ可以实现异步消息传递&#xff0c;发送者可以将消息放入队列后立即返回&#xff0c;不必等待接收者处理。这提高了系统的响应速度…

Kafka学习笔记(一)Kafka基准测试、幂等性和事务、Java编程操作Kafka

文章目录 前言4 Kafka基准测试4.1 基于1个分区1个副本的基准测试4.2 基于3个分区1个副本的基准测试4.3 基于1个分区3个副本的基准测试 5 Java编程操作Kafka5.1 引入依赖5.2 向Kafka发送消息5.3 从Kafka消费消息5.4 异步使用带有回调函数的生产消息 6 幂等性6.1 幂等性介绍6.2 K…

【BurpSuite】SQL注入 | SQL injection(1-2)

&#x1f3d8;️个人主页&#xff1a; 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 【BurpSuite】SQL注入 | SQL injection&#xff08;1-2&#xff09; 实验一 Lab: SQL injection vulnerability in WHERE clause…

基于微信的乐室预约小程序+ssm(lw+演示+源码+运行)

摘 要 随着社会的发展&#xff0c;社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和mysql数据库来完成对系统的设计。整个…

字体文件压缩

技术点 npm、html、font-spider 实现原理 个人理解&#xff1a;先引入原先字体&#xff0c;然后重置字符为空&#xff0c;根据你自己填充文字、字符等重新生成字体文件&#xff0c;因此在引入的时候务必添加自己使用的文字、字符等&#xff01;&#xff01;&#xff01; 实…

TDengine 流计算与窗口机制的深度解析:揭示计数窗口的关键作用

在 TDengine 3.2.3.0 版本中&#xff0c;我们针对流式计算新增了计数窗口&#xff0c;进一步优化了流式数据处理的能力。本文将为大家解读流式计算与几大窗口的关系&#xff0c;并针对新增的计数窗口进行详细的介绍&#xff0c;帮助大家进一步了解 TDengine 流式计算&#xff0…

解决MySQL报Incorrect datetime value错误

目录 一、前言二、问题分析三、解决方法 一、前言 欢迎大家来到权权的博客~欢迎大家对我的博客进行指导&#xff0c;有什么不对的地方&#xff0c;我会及时改进哦~ 博客主页链接点这里–>&#xff1a;权权的博客主页链接 二、问题分析 这个错误通常出现在尝试将一个不…

沂机管理系统/data/Ajax.aspx接口存在SQL注入漏洞

漏洞描述 沂机管理系统/data/Ajax.aspx接口存在SQL注入漏洞&#xff0c;攻击者可以获取服务器权限 漏洞复现 body"后台管理系统演示版" POC GET /data/Ajax.aspx?methodlog_list&page1&limit20&fkey1&fdate12024-10-0100%3A00%3A00&fdate2…

Postgresql源码(136)syscache/relcache 缓存及失效机制

相关 《Postgresql源码&#xff08;45&#xff09;SysCache内存结构与搜索流程分析》 0 总结速查 syscache&#xff1a;缓存系统表的行。通用数据结构&#xff0c;可以缓存一切数据&#xff08;hash dlist&#xff09;。可以分别缓存单行和多行查询。 syscache使用CatCache数…

AI 对话工具汇总

&#x1f423;个人主页 可惜已不在 &#x1f424;这篇在这个专栏AI_可惜已不在的博客-CSDN博客 &#x1f425;有用的话就留下一个三连吧&#x1f63c; 目录 前言: 正文: 前言: 在科技飞速发展的时代&#xff0c;AI 对话正逐渐成为我们获取信息、交流思想的新方式。它以强…

算法笔记(四)——模拟

算法笔记&#xff08;四&#xff09;——模拟 文章目录 算法笔记&#xff08;四&#xff09;——模拟替换所有的问号提莫攻击Z字形变换外观数列数青蛙 模拟算法就是根据题目的要求&#xff0c;题目让干神马就做神马&#xff0c;一步一步来 替换所有的问号 题目&#xff1a;替换…

初识TCP/IP协议

回顾上文 来回顾一下TCP协议的特性&#xff0c;有一道比较经典的题&#xff1a;如何使用UDP实现可靠传输&#xff0c;通过应用程序的代码&#xff0c;完成可靠传输的过程&#xff1f; 原则&#xff0c;TCO有啥就吹啥&#xff0c;引入滑动窗口&#xff0c;引入流量控制&#x…

【RabbitMQ——具体使用场景】

1. 异步 1.1 同步异步的问题&#xff08;串行&#xff09; 串行方式&#xff1a;将订单信息写入数据库成功后&#xff0c;发送注册邮件&#xff0c;再发送注册短信。以上三个任务全部完成后&#xff0c;返回给客户端 public void makeOrder(){// 1 :保存订单 orderService.…

排水系统C++

题目&#xff1a; 样例解释&#xff1a; 1 号结点是接收口&#xff0c;4,5 号结点没有排出管道&#xff0c;因此是最终排水口。 1 吨污水流入 1 号结点后&#xff0c;均等地流向 2,3,5 号结点&#xff0c;三个结点各流入 1/3 吨污水。 2 号结点流入的 1/3​ 吨污水将均等地流向…

nginx打包部署前端vue项目全过程【保姆级教程】

&#x1f939;‍♀️潜意识起点&#xff1a;个人主页 &#x1f399;座右铭&#xff1a;得之坦然&#xff0c;失之淡然。 &#x1f48e;擅长领域&#xff1a;前端 是的&#xff0c;我需要您的&#xff1a; &#x1f9e1;点赞❤️关注&#x1f499;收藏&#x1f49b; 是我持…

【JavaScript】Bit:组件驱动开发的新时代

Bit 是一个现代化的开发工具&#xff0c;帮助开发者通过组件驱动的方式进行软件开发和协作。它旨在解决开发大型系统时的常见挑战&#xff0c;如组件的复用性、独立性和协作性问题。通过 Bit&#xff0c;开发团队可以更加轻松地共享、管理和维护可复用的代码组件&#xff0c;同…

初识算法 · 双指针(2)

目录 前言&#xff1a; 盛最多水的容器 题目解析&#xff1a; 算法原理&#xff1a; 算法编写&#xff1a; 有效三角形的个数 题目解析&#xff1a; 算法原理&#xff1a; 算法编写&#xff1a; 前言&#xff1a; 本文介绍两个题目&#xff0c;盛最多水的容器和有效三…

Jenkins: fontconfig head is null, check your fonts or fonts configuration;

​ 在部署jenkins第一次启动时遇到如下报错&#xff1a; 一大串报错&#xff0c;看的让人脑瓜疼。。。静静地分析一下日志&#xff0c;发现第一行报错信息&#xff1a; fontconfig head is null, check your fonts or fonts configuration。 这是个什么鬼&#xff0c;我也不…

师生健康信息管理:SpringBoot技术突破

第4章 系统设计 4.1 系统体系结构 师生健康信息管理系统的结构图4-1所示&#xff1a; 图4-1 系统结构 登录系统结构图&#xff0c;如图4-2所示&#xff1a; 图4-2 登录结构图 师生健康信息管理系统结构图&#xff0c;如图4-3所示。 图4-3 师生健康信息管理系统结构图 4.2…

linux文件编程_文件

1. 文件编程概述 之前在windows中对文件的操作是&#xff1a;打开文档—>编辑文档—>保存文档—>关闭文档 我们的Linux文件编程主要是利用代码对文件进行操作&#xff1a;文件创建、打开、编辑等自动化执行等 在Linux我们要使用编程调用api函数的方式进行文档的编辑…