当前位置: 首页 > article >正文

H3m-Blog

H3m-Blog

一、项目介绍

1.1 项目介绍

一个基于SpringBoot和Vue3的博客系统,博客名称来源于陈奕迅于2009年发布的粤语专辑《H3M》

h3m

1.2 技术架构

主要技术栈: SpringBoot2 + Vue3 + MySQL8.0

1.3 主要功能

内容丰富,尽情体验~

二、快速开始

  1. 运行h3m-blog.sql文件,创建数据库

  2. 修改blog/src/main/resources/application.yml 中的配置内容,主要包括:

    ( 1 ) 数据库账号密码: username,password

    ( 2 )redis 相关配置,如果有密码自行添加password

  3. 在idea中打开H3m-Blog-back项目文件,等待Maven加载好依赖项,启动BlogAplication.

  4. VsCode中打开H3m-Blog-front文件夹,安装前端依赖并启动前端项目

    npm install
    npm run dev
    
  5. 修改图床请求头,这里我使用的是https://imglt.com/ 图床,大家可以自行注册这个网站然后获取自己的tokens,然后填入即可. 在src\utils\axios.config.js中。

    在这里插入图片描述

  6. 打开 http://127.0.0.1:5174/ 开启博客之旅~

FAQs:

  1. 默认的账号与密码

​ 所有现有的用户的密码都是1234,管理员账户为 EasonChan

  1. 接口文档

    https://apifox.com/apidoc/shared-b5658688-b374-4473-a046-a902bfc6b711

三、数据库设计

在这里插入图片描述

四、前端

1. 前端主要使用到的一些依赖插件:
"dependencies": {
    "@DatatracCorporation/markdown-it-mermaid": "npm:@datatraccorporation/markdown-it-mermaid@^0.5.0",
    "@element-plus/icons-vue": "^2.3.1",
    "axios": "^1.7.7",
    "clipboard": "^2.0.11",
    "element-plus": "^2.8.4",
    "highlight.js": "^11.10.0",
    "jquery": "^3.7.1",
    "js-md5": "^0.7.3",
    "markdown-it": "^14.1.0",
    "markdown-it-abbr": "^1.0.4",
    "markdown-it-container": "^3.0.0",
    "markdown-it-deflist": "^2.1.0",
    "markdown-it-emoji": "^2.0.0",
    "markdown-it-footnote": "^3.0.3",
    "markdown-it-ins": "^3.0.1",
    "markdown-it-mark": "^3.0.1",
    "markdown-it-sub": "^1.0.0",
    "markdown-it-sup": "^1.0.0",
    "markdown-it-task-lists": "^2.1.1",
    "markdown-it-toc": "^1.1.0",
    "markdown-it-toc-done-right": "^4.2.0",
    "mavon-editor": "^3.0.0-beta",
    "pinia": "^2.2.4",
    "pinia-plugin-persistedstate": "^4.1.1",
    "vue": "^3.4.37",
    "vue-easy-lightbox": "^1.19.0",
    "vue-router": "^4.4.5"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.1.2",
    "less": "^4.2.0",
    "sass": "^1.80.3",
    "sass-loader": "^16.0.2",
    "vite": "^5.4.1"
  }
2. mavonEditor

这是一个富文本编辑器,github网站:https://github.com/hinesboy/mavonEditor

在这里插入图片描述

3. markdown-it

GitHub 官网:https://github.com/markdown-it/markdown-it?tab=readme-ov-file#markdown-it-

配置如下:

import MarkdownIt from "markdown-it";
import emoji from "markdown-it-emoji";
import deflist from "markdown-it-deflist";
import abbr from "markdown-it-abbr";
import footnote from "markdown-it-footnote";
import ins from "markdown-it-ins";
import mark from "markdown-it-mark";
import taskLists from "markdown-it-task-lists";
import container from "markdown-it-container";
import toc from "markdown-it-toc-done-right";
import mermaid from "@DatatracCorporation/markdown-it-mermaid";

var config = {
  html: true,
  xhtmlOut: true,
  breaks: true,
  langPrefix: "lang-",
  linkify: false,
  typographer: true,
  quotes: "“”‘’",
};
let markdownIt = new MarkdownIt(config);

markdownIt
  .use(emoji)
  .use(deflist)
  .use(abbr)
  .use(footnote)
  .use(ins)
  .use(mark)
  .use(taskLists)
  .use(container)
  .use(container, "hljs-left")
  .use(container, "hljs-center")
  .use(container, "hljs-right")
  .use(toc)
  .use(mermaid);

export default markdownIt;

4. mathjax

这是一个用于美化数学公式的脚本

/**
 * 异步载入 MathJax 脚本
 */
export function injectMathJax() {
  if (!window.MathJax) {
    const script = document.createElement("script");
    script.src =
      "https://cdn.bootcdn.net/ajax/libs/mathjax/3.2.0/es5/tex-chtml.js";
    script.async = true;
    document.head.appendChild(script);
  }
}

/**
 * 初始化 MathJax
 * @param options 自定义 MathJax 配置
 * @param callback 当 MathJax 脚本载入完毕时
 */
export function initMathJax(options = {}, callback) {
  injectMathJax();
  const defaultConfig = {
    tex: {
      inlineMath: [["$", "$"]],
      displayMath: [["$$", "$$"]],
      processEnvironments: true,
      processRefs: true,
    },
    options: {
      skipHtmlTags: ["noscript", "style", "textarea", "pre", "code"],
      ignoreHtmlClass: "tex2jax_ignore",
    },
    startup: {
      pageReady: () => {
        callback && callback();
      },
    },
    svg: {
      fontCache: "global",
    },
  };
  const mergeConfig = Object.assign({}, defaultConfig, options);
  window.MathJax = mergeConfig;
}

/**
 * 渲染指定容器中的数学公式
 * @param {string} el 需要被渲染的容器
 * @returns Promise
 */
export function renderByMathjax(el) {
  if (!window.MathJax || !window.MathJax.version) {
    return;
  }

  el = [...document.querySelectorAll(el)];

  return new Promise((resolve, reject) => {
    window.MathJax.typesetPromise(el)
      .then(() => {
        resolve(void 0);
      })
      .catch((err) => reject(err));
  });
}

用法:

import { initMathJax, renderByMathjax } from "@/utils/mathjax";
initMathJax({}, () => {
        renderByMathjax(".article-content");
        renderByMathjax(".comment-item-content");
      });
  1. 代码块美化

    主要用到的就是highlight.js

在这里插入图片描述

​ index.js:

import "./index.less";
import "highlight.js/styles/atom-one-dark.css";
import $ from "jquery";
import hljs from "highlight.js/lib/core";
import javascript from "highlight.js/lib/languages/javascript";
import vbscript from "highlight.js/lib/languages/vbscript";
import python from "highlight.js/lib/languages/python";
import matlab from "highlight.js/lib/languages/matlab";
import csharp from "highlight.js/lib/languages/csharp";
import shell from "highlight.js/lib/languages/shell";
import vhdl from "highlight.js/lib/languages/vhdl";
import java from "highlight.js/lib/languages/java";
import css from "highlight.js/lib/languages/css";
import xml from "highlight.js/lib/languages/xml";
import sql from "highlight.js/lib/languages/sql";
import cpp from "highlight.js/lib/languages/cpp";
import c from "highlight.js/lib/languages/c";
import ClipboardJS from "clipboard";

hljs.registerLanguage("javascript", javascript);
hljs.registerLanguage("vbscript", vbscript);
hljs.registerLanguage("python", python);
hljs.registerLanguage("matlab", matlab);
hljs.registerLanguage("csharp", csharp);
hljs.registerLanguage("shell", shell);
hljs.registerLanguage("vhdl", vhdl);
hljs.registerLanguage("java", java);
hljs.registerLanguage("html", xml);
hljs.registerLanguage("xml", xml);
hljs.registerLanguage("css", css);
hljs.registerLanguage("sql", sql);
hljs.registerLanguage("cpp", cpp);
hljs.registerLanguage("c", c);

hljs.configure({ ignoreUnescapedHTML: true });

/**
 * 高亮代码块
 * @param {Element} element 包含 pre code 代码块的元素
 */
function highlightCode(element) {
  const codeEls = element.querySelectorAll("pre code");
  codeEls.forEach((el) => {
    hljs.highlightElement(el);
  });
}

/**
 * 给代码块添加行号
 * @param {Element} element 包含 pre code 代码块的元素
 */
function buildLineNumber(element) {
  let $codes = $(element).find("pre code");
  if (!$codes.length) {
    return false;
  }

  $.each($codes, (_, code) => {
    if (!$(code).hasClass("hljsln")) {
      $(code).addClass("hljsln");
      $(code).html(addLineNumbersFor($(code).html()));
      var $lastNum = $("span[data-num]:last");
      if (!$lastNum.html()) {
        $lastNum.remove();
      }
    }
  });
}

function addLineNumbersFor(html) {
  var text = html.replace(/<span[^>]*>|<\/span>/g, "");
  if (/\r|\n$/.test(text)) {
    html += '<span class="ln-eof"></span>';
  }
  var num = 1;
  html = html.replace(/\r\n|\r|\n/g, function (a) {
    num++;
    return a + '<span class="ln-num" data-num="' + num + '"></span>';
  });
  html = '<span class="ln-num" data-num="1"></span>' + html;
  html = '<span class="ln-bg"></span>' + html;
  return html;
}

/**
 * 给代码块添加复制按钮
 * @param {Element} element 包含 pre code 代码块的元素
 */
function buildCopyButton(element) {
  let $pres = $(element).find("pre");
  if (!$pres.length) return;

  $pres.each(function () {
    var t = $(this).children("code").text();

    // 创建按钮
    var btn = $('<span class="copy">复制</span>').attr(
      "data-clipboard-text",
      t
    );

    $(this).prepend(btn);

    var c = new ClipboardJS(btn[0]);
    c.on("success", function () {
      btn.addClass("copyed").text("复制成功");
      setTimeout(function () {
        btn.text("复制").removeClass("copyed");
      }, 1000);
    });
    c.on("error", function () {
      btn.text("复制失败");
    });
  });
}

/**
 * 创建代码块
 * @param {string} selector 包含 pre code 的元素选择器
 */
function buildCodeBlock(selector) {
  let elements = document.querySelectorAll(selector);
  for (let element of elements) {
    highlightCode(element);
    buildLineNumber(element);
    buildCopyButton(element);
  }
}

export default buildCodeBlock;

index.less:

.hljs,
.hljsln {
    display: block;
    overflow-x: auto;
    padding: 0.7em 1em 0.7em 3em !important;
    background: #282c34 !important;
    border: 1px solid #282c34 !important;
    color: #bababa;
    font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace !important;
    font-size: 14px !important;
    position: relative;

    /* 代码块不换行 */
    white-space: pre;
    word-break: normal;

    &::-webkit-scrollbar {
        height: 4px;
    }
}

.hljs.ln-hide {
    padding: 0.7em 1em 0.7em 1em !important;
}

.ln-bg {
    position: absolute;
    z-index: 1;
    top: 0;
    left: 0;
    width: 37px;
    height: 100%;
    background: #282c34;
    border-radius: 7px 0px 0px 7px;
}

.ln-num {
    position: absolute;
    z-index: 2;
    left: 0;
    width: 37px;
    text-align: center;
    display: inline-block;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;

    &::before {
        color: #999;
        font-style: normal;
        font-weight: normal;
        text-align: center;
        content: attr(data-num);
    }
}

.hljs-comment,
.hljs-quote {
    color: #5c6370;
    font-style: italic;
}

.hljs-doctag,
.hljs-keyword,
.hljs-formula {
    color: #c678dd;
}

.hljs-section,
.hljs-name,
.hljs-selector-tag,
.hljs-deletion,
.hljs-subst {
    color: #e06c75;
}

.hljs-literal {
    color: #56b6c2;
}

.hljs-string,
.hljs-regexp,
.hljs-addition,
.hljs-attribute,
.hljs-meta-string {
    color: #98c379;
}

.class_ {
    color: #e5c07b !important;
}

.hljs-attr {
    color: #d19a66 !important;
}

.hljs-attr,
.hljs-variable,
.hljs-template-variable,
.hljs-type,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo,
.hljs-number {
    color: #d19a66;
}

.hljs-symbol,
.hljs-bullet,
.hljs-link,
.hljs-meta,
.hljs-selector-id,
.hljs-title {
    color: #61afef;
}

.hljs-emphasis {
    font-style: italic;
}

.hljs-strong {
    font-weight: bold;
}

.hljs-link {
    text-decoration: underline;
}

.hljs-built_in {
    color: #56b6c2;
}

.hljs-tag .hljs-name {
    color: #e06c75
}

.hljs-tag {
    color: #bababa;
}

.hljs-attribute,
.hljs-doctag,
.hljs-keyword,
.hljs-meta .hljs-keyword,
.hljs-name,
.hljs-selector-tag,
.hljs-title {
    font-weight: normal !important;
}

.hljs-punctuation {
    color: #bababa;
}

.hljs::-webkit-scrollbar,
.hljsln::-webkit-scrollbar {
    height: 3px;
}

.article-content pre,
.comment-item-content pre {
    position: relative;

    &>span {
        position: absolute;
        top: 0;
        right: 0;
        border-radius: 3px;
        padding: 3px 10px;
        font-size: 12px;
        font-family: Lato, PingFang SC, Microsoft YaHei, sans-serif;
        font-weight: normal;
        background: #fff;
        color: #000;
        cursor: pointer;
        opacity: 0;
        margin: 8px 10px;
        transition: all 0.3s;
        z-index: 5;

        &:hover {
            background: #ddd;
        }
    }

    &:hover>span {
        opacity: 1;
        transition: opacity 0.25s;
    }
}

使用示例:

import buildCodeBlock from "@/utils/code-block";  // 导入
// 直接应用于元素类上即可
buildCodeBlock(".article-content");
5. text-effect

在这里插入图片描述

一个文字动画效果特效
在这里插入图片描述

index.css

.particletext {
    text-align: center;
    font-size: 48px;
    position: relative;
}

.particletext.bubbles>.particle {
    opacity: 0;
    position: absolute;
    background-color: rgba(241, 240, 154, 0.849);
    /* background-color: rgba(33, 150, 243, 0.5); */
    animation: bubbles 3s ease-in infinite;
    border-radius: 100%;
}

.particletext.hearts>.particle {
    opacity: 0;
    position: absolute;
    background-color: #cc2a5d;
    animation: hearts 3s ease-in infinite;
}

.particletext.hearts>.particle:before,
.particletext.hearts>.particle:after {
    position: absolute;
    content: '';
    border-radius: 100px;
    top: 0px;
    left: 0px;
    width: 100%;
    height: 100%;
    background-color: #cc2a5d;
}

.particletext.hearts>.particle:before {
    transform: translateX(-50%);
}

.particletext.hearts>.particle:after {
    transform: translateY(-50%);
}

.particletext.lines>.particle {
    position: absolute;
    background-color: rgba(244, 67, 54, 0.5);
    animation: lines 3s linear infinite;
}

.particletext.confetti>.particle {
    opacity: 0;
    position: absolute;
    animation: confetti 3s ease-in infinite;
}

.particletext.confetti>.particle.c1 {
    background-color: rgba(76, 175, 80, 0.5);
}

.particletext.confetti>.particle.c2 {
    background-color: rgba(156, 39, 176, 0.5);
}

.particletext.sunbeams>.particle {
    position: absolute;
    background-color: rgba(253, 216, 53, 0.5);
    animation: sunbeams 3s linear infinite;
}

@keyframes bubbles {
    0% {
        opacity: 0;
    }

    20% {
        opacity: 1;
        transform: translate(0, -20%);
    }

    100% {
        opacity: 0;
        transform: translate(0, -1000%);
    }
}

@keyframes hearts {
    0% {
        opacity: 0;
        transform: translate(0, 0%) rotate(45deg);
    }

    20% {
        opacity: 0.8;
        transform: translate(0, -20%) rotate(45deg);
    }

    100% {
        opacity: 0;
        transform: translate(0, -1000%) rotate(45deg);
    }
}

@keyframes lines {

    0%,
    50%,
    100% {
        transform: translateY(0%);
    }

    25% {
        transform: translateY(100%);
    }

    75% {
        transform: translateY(-100%);
    }
}

@keyframes confetti {
    0% {
        opacity: 0;
        transform: translateY(0%) rotate(0deg);
    }

    10% {
        opacity: 1;
    }

    35% {
        transform: translateY(-800%) rotate(270deg);
    }

    80% {
        opacity: 1;
    }

    100% {
        opacity: 0;
        transform: translateY(2000%) rotate(1440deg);
    }
}

@keyframes sunbeams {
    0% {
        transform: translateY(40%) rotate(0deg);
    }

    50% {
        transform: translateY(-40%) rotate(180deg);
    }

    100% {
        transform: translateY(40%) rotate(360deg);
    }

    0%,
    14%,
    17%,
    43%,
    53%,
    71%,
    80%,
    94%,
    100% {
        opacity: 0;
    }

    6%,
    15%,
    24%,
    28%,
    48%,
    55%,
    78%,
    82%,
    99% {
        opacity: 1;
    }
}

index.js

import "./index.css"
import $ from 'jquery'

/**
 * 生成粒子效果
 */
function createParticles() {
    bubbles();
    hearts();
    lines();
    confetti();
    sunbeams();
}


function bubbles() {
    $.each($(".particletext.bubbles"), function () {
        var bubblecount = ($(this).width() / 50) * 10;
        for (var i = 0; i <= bubblecount; i++) {
            var size = ($.rnd(20, 50) / 10);
            $(this).append('<span class="particle" style="top:' + $.rnd(20, 80) + '%; left:' + $.rnd(0, 95) + '%;width:' + size + 'px; height:' + size + 'px;animation-delay: ' + ($.rnd(0, 30) / 10) + 's;"></span>');
        }
    });
}

function hearts() {
    $.each($(".particletext.hearts"), function () {
        var heartcount = ($(this).width() / 50) * 5;
        for (var i = 0; i <= heartcount; i++) {
            var size = ($.rnd(60, 120) / 10);
            $(this).append('<span class="particle" style="top:' + $.rnd(20, 80) + '%; left:' + $.rnd(0, 95) + '%;width:' + size + 'px; height:' + size + 'px;animation-delay: ' + ($.rnd(0, 30) / 10) + 's;"></span>');
        }
    });
}

function lines() {
    $.each($(".particletext.lines"), function () {
        var linecount = ($(this).width() / 50) * 10;
        for (var i = 0; i <= linecount; i++) {
            $(this).append('<span class="particle" style="top:' + $.rnd(-30, 30) + '%; left:' + $.rnd(-10, 110) + '%;width:' + $.rnd(1, 3) + 'px; height:' + $.rnd(20, 80) + '%;animation-delay: -' + ($.rnd(0, 30) / 10) + 's;"></span>');
        }
    });
}

function confetti() {
    $.each($(".particletext.confetti"), function () {
        var confetticount = ($(this).width() / 50) * 10;
        for (var i = 0; i <= confetticount; i++) {
            $(this).append('<span class="particle c' + $.rnd(1, 2) + '" style="top:' + $.rnd(10, 50) + '%; left:' + $.rnd(0, 100) + '%;width:' + $.rnd(6, 8) + 'px; height:' + $.rnd(3, 4) + 'px;animation-delay: ' + ($.rnd(0, 30) / 10) + 's;"></span>');
        }
    });
}


function sunbeams() {
    $.each($(".particletext.sunbeams"), function () {
        var linecount = ($(this).width() / 50) * 10;
        for (var i = 0; i <= linecount; i++) {
            $(this).append('<span class="particle" style="top:' + $.rnd(-50, 0) + '%; left:' + $.rnd(0, 100) + '%;width:' + $.rnd(1, 3) + 'px; height:' + $.rnd(80, 160) + '%;animation-delay: -' + ($.rnd(0, 30) / 10) + 's;"></span>');
        }
    });
}

$.rnd = function (m, n) {
    m = parseInt(m);
    n = parseInt(n);
    return Math.floor(Math.random() * (n - m + 1)) + m;
}


export default createParticles


使用示例:

<template>
  <div class="cover">
    <div class="title particletext bubbles" v-if="title">
      {{ title }}
    </div>
    <div class="slot particletext bubbles" v-else>   // 使用即可
      <slot></slot>
    </div>
    <div class="text">{{ text }}</div>
  </div>
</template>
<script setup>
import createParticles from "@/utils/text-effect";  // 导入
import { onMounted, defineProps } from "vue";

const props = defineProps({
  title: {
    type: String,
  },
  text: {
    type: String,
  },
});

onMounted(() => {  
  createParticles();   // 加载
});
</script>

五、后端

主要技术:Jwt+SpringSecurity+redis+MyBatis-plus 项目遵守三层架构设计规范。

<dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.24</version>
            </dependency>

            <dependency>
                <groupId>com.mysql</groupId>
                <artifactId>mysql-connector-j</artifactId>
                <version>8.0.31</version>
            </dependency>

            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.33</version>
            </dependency>
            <!---jwt依赖 -->
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>0.9.1</version>
            </dependency>
            <dependency>
                <groupId>com.auth0</groupId>
                <artifactId>java-jwt</artifactId>
                <version>3.19.2</version>
            </dependency>
            <!-- 如果jdk>8-->
            <dependency>
                <groupId>javax.xml.bind</groupId>
                <artifactId>jaxb-api</artifactId>
                <version>2.3.1</version>
            </dependency>

            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.5.1</version>
            </dependency>

            <dependency>
                <groupId>com.aliyun.oss</groupId>
                <artifactId>aliyun-sdk-oss</artifactId>
                <version>3.10.2</version>
            </dependency>

            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>easyexcel</artifactId>
                <version>3.0.5</version>
            </dependency>

            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger2</artifactId>
                <version>2.9.2</version>
            </dependency>

            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger-ui</artifactId>
                <version>2.9.2</version>
            </dependency>

            <dependency>
                <groupId>com.sun.xml.bind</groupId>
                <artifactId>jaxb-impl</artifactId>
                <version>2.3.0</version>
            </dependency>
            <dependency>
                <groupId>com.sun.xml.bind</groupId>
                <artifactId>jaxb-core</artifactId>
                <version>2.3.0</version>
            </dependency>
            <dependency>
                <groupId>javax.activation</groupId>
                <artifactId>activation</artifactId>
                <version>1.1.1</version>
            </dependency>

六、页面展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


http://www.kler.cn/news/367121.html

相关文章:

  • 自旋锁原理及基于原子引用手写自旋锁
  • 解码专业术语——应用系统开发项目中的专业词汇解读
  • python项目实战——多线程爬虫
  • 虚拟现实在制造业中的应用
  • 《复旦学报(自然科学版)》
  • logback日志脱敏后异步写入文件
  • ctfshow(55,56)--RCE/命令执行漏洞--无字母RCE与强制文件上传RCE
  • Python浪漫之画一个圆月亮
  • sqlserver用ip登录
  • 基于SSM的儿童众筹救助系统设计与实现
  • 喜讯 | 创邻科技杭州电子科技大学联合实验室揭牌成立!
  • fiddler总结
  • 单片机原理及应用(新改)
  • 说一说QWidget
  • 解决JeecgBoot微服务通过Gateway访问Swagger资源出现“Knife4j文档请求异常”
  • 【记录】Excel 公式|(一)根据某列内容和关键词列,自动生成当前行的关键词分类名称
  • leetcode 498.对角线遍历
  • 常用的无穷小等价替换
  • HRCE第二次实验
  • K8S系列-Kubernetes网络
  • Vue3的Composition组合式API(readonly与shallowReadonly函数、toRaw与markRaw函数、customRef函数)
  • [ComfyUI]与 FLUX.1[dev] 一样优秀的商业用途模型 OpenFLUX.1 现已面世!
  • 常用sql
  • 记录下docker部署gitlab-ce-17.5版本及客户端git拉取方式配置
  • AI视频!OpenAI发布最新模型sCM,开启图像、音频、视频、三维模型AI新时代
  • 【C++进阶】深入STL之list:模拟实现深入理解List与迭代器