【實戰】十一、看板頁面及任務組頁面開發(一) —— React17+React Hook+TS4 最佳實踐,仿 Jira 企業級項目(二十三)

文章目錄

    • 一、項目起航:項目初始化與配置
    • 二、React 與 Hook 應用:實現項目列表
    • 三、TS 應用:JS神助攻 - 強類型
    • 四、JWT、用戶認證與異步請求
    • 五、CSS 其實很簡單 - 用 CSS-in-JS 添加樣式
    • 六、用戶體驗優化 - 加載中和錯誤狀態處理
    • 七、Hook,路由,與 URL 狀態管理
    • 八、用戶選擇器與項目編輯功能
    • 九、深入React 狀態管理與Redux機制
    • 十、用 react-query 獲取數據,管理緩存
    • 十一、看板頁面及任務組頁面開發
      • 1.看板列表開發準備工作
      • 2.看板列表初步開發
      • 3.添加task, bug 圖標


學習內容來源:React + React Hook + TS 最佳實踐-慕課網


相對原教程,我在學習開始時(2023.03)采用的是當前最新版本:

版本
react & react-dom^18.2.0
react-router & react-router-dom^6.11.2
antd^4.24.8
@commitlint/cli & @commitlint/config-conventional^17.4.4
eslint-config-prettier^8.6.0
husky^8.0.3
lint-staged^13.1.2
prettier2.8.4
json-server0.17.2
craco-less^2.0.0
@craco/craco^7.1.0
qs^6.11.0
dayjs^1.11.7
react-helmet^6.1.0
@types/react-helmet^6.1.6
react-query^6.1.0
@welldone-software/why-did-you-render^7.0.1
@emotion/react & @emotion/styled^11.10.6

具體配置、操作和內容會有差異,“坑”也會有所不同。。。


一、項目起航:項目初始化與配置

  • 一、項目起航:項目初始化與配置

二、React 與 Hook 應用:實現項目列表

  • 二、React 與 Hook 應用:實現項目列表

三、TS 應用:JS神助攻 - 強類型

  • 三、 TS 應用:JS神助攻 - 強類型

四、JWT、用戶認證與異步請求

  • 四、 JWT、用戶認證與異步請求(上)

  • 四、 JWT、用戶認證與異步請求(下)

五、CSS 其實很簡單 - 用 CSS-in-JS 添加樣式

  • 五、CSS 其實很簡單 - 用 CSS-in-JS 添加樣式(上)

  • 五、CSS 其實很簡單 - 用 CSS-in-JS 添加樣式(下)

六、用戶體驗優化 - 加載中和錯誤狀態處理

  • 六、用戶體驗優化 - 加載中和錯誤狀態處理(上)

  • 六、用戶體驗優化 - 加載中和錯誤狀態處理(中)

  • 六、用戶體驗優化 - 加載中和錯誤狀態處理(下)

七、Hook,路由,與 URL 狀態管理

  • 七、Hook,路由,與 URL 狀態管理(上)

  • 七、Hook,路由,與 URL 狀態管理(中)

  • 七、Hook,路由,與 URL 狀態管理(下)

八、用戶選擇器與項目編輯功能

  • 八、用戶選擇器與項目編輯功能(上)

  • 八、用戶選擇器與項目編輯功能(下)

九、深入React 狀態管理與Redux機制

  • 九、深入React 狀態管理與Redux機制(一)

  • 九、深入React 狀態管理與Redux機制(二)

  • 九、深入React 狀態管理與Redux機制(三)

  • 九、深入React 狀態管理與Redux機制(四)

  • 九、深入React 狀態管理與Redux機制(五)

十、用 react-query 獲取數據,管理緩存

  • 十、用 react-query 獲取數據,管理緩存(上)

  • 十、用 react-query 獲取數據,管理緩存(下)

十一、看板頁面及任務組頁面開發

1.看板列表開發準備工作

之前的項目詳情進入看板頁的路由有個小問題,點擊瀏覽器返回按鈕回不去,原因如下:

  • 路由列表是棧結構,每訪問一個路由都會 push 一個新路由進去,當點擊返回,就會將上一個路由置于棧頂;而進入項目詳情頁(從'projects''projects/1')默認重定向子路由是看板頁(projects/1/viewboard),返回上一個路由時,默認又會重定向到看板頁路由。列表棧示例如下:
  • ['projects', 'projects/1', 'projects/1/viewboard']

接下來解決一下這個問題,編輯 src\screens\ProjectDetail\index.tsx (重定向標簽新增屬性 replace,在重定向時直接替換原路由):

...
export const ProjectDetail = () => {return (<div>...<Routes>...<Route index element={<Navigate to="viewboard" replace/>} /></Routes></div>);
};

為了方便后續類型統一調用,將 src\screens\ProjectList\components\List.tsxinterface Project 提取到 src\types 目錄下

視頻中 是用 WebStorm ,博主用的是 VSCode:

  • 在需要重構的變量上右擊,選擇重構(快捷鍵 Ctrl + Shift + R),選擇 Move to a new file,默認同變量名的文件會創建在當前文件所在同一級目錄下,其他引用位置也相應改變,涉及引用位置:
    • src\utils\project.ts
    • src\screens\ProjectList\components\SearchPanel.tsx
    • src\screens\ProjectList\components\List.tsx
  • 拖動新生成的文件到 src\types 目錄下,可以看到其他引用位置也相應改變
  • 相關功能文檔:TypeScript Programming with Visual Studio Code

src\screens\ProjectList\components\SearchPanel.tsxinterface User 也執行同樣操作,涉及引用位置:

  • src\screens\ProjectList\components\SearchPanel.tsx
  • src\screens\ProjectList\components\List.tsx
  • src\auth-provider.ts
  • src\context\auth-context.tsx
  • src\utils\use-users.ts

看板頁還需要以下兩個類型,新建一下:

  • src\types\Viewboard.ts:
export interface Viewboard {id: number;name: string;projectId: number;
}
  • src\types\Task.ts
export interface Task {id: number;name: string;projectId: number;processorId: number; // 經辦人taskGroupId: number; // 任務組kanbanId: number;typeId: number;      // bug or tasknote: string;
}

接下來創建數據請求的 hook:

src\utils\viewboard.ts:

import { cleanObject } from "utils";
import { useHttp } from "./http";
import { Viewboard } from "types/Viewboard";
import { useQuery } from "react-query";export const useViewboards = (param?: Partial<Viewboard>) => {const client = useHttp();return useQuery<Viewboard[]>(["viewboards", param], () =>client("kanbans", { data: cleanObject(param || {}) }));
};

src\utils\task.ts:

import { cleanObject } from "utils";
import { useHttp } from "./http";
import { Task } from "types/Task";
import { useQuery } from "react-query";export const useTasks = (param?: Partial<Task>) => {const client = useHttp();return useQuery<Task[]>(["tasks", param], () =>client("tasks", { data: cleanObject(param || {}) }));
};

2.看板列表初步開發

接下來開始開發看板列表,展示需要用到項目數據,可以提取一個從 url 獲取 projectId,再用 id 獲取項目數據的 hook

新建 src\screens\ViewBoard\utils.ts

import { useLocation } from "react-router"
import { useProject } from "utils/project"export const useProjectIdInUrl = () => {const { pathname } = useLocation()const id = pathname.match(/projects\/(\d+)/)?.[1]return Number(id)
}export const useProjectInUrl = () => useProject(useProjectIdInUrl())export const useViewBoardSearchParams = () => ({projectId: useProjectIdInUrl()})export const useViewBoardQueryKey = () => ['viewboards', useViewBoardSearchParams()]export const useTasksSearchParams = () => ({projectId: useProjectIdInUrl()})export const useTasksQueryKey = () => ['tasks', useTasksSearchParams()]

注意:每一個 useXXXQueryKey 都要確保返回值第一項 與后續列表請求 useXXXuseQuery 的第一個參數保持一致,否則后續增刪改都無法正常自動重新請求列表,問題排查比較困難

為看板定制一個展示列組件(任務列表),供每個類型來使用

新建 src\screens\ViewBoard\components\ViewboardCloumn.tsx

import { Viewboard } from "types/Viewboard";
import { useTasks } from "utils/task";
import { useTasksSearchParams } from "../utils";export const ViewboardColumn = ({viewboard}:{viewboard: Viewboard}) => {const { data: allTasks } = useTasks(useTasksSearchParams())const tasks = allTasks?.filter(task => task.kanbanId === viewboard.id)return <div><h3>{viewboard.name}</h3>{tasks?.map(task => <div key={task.id}>{task.name}</div>)}</div>
}

編輯 src\screens\ViewBoard\index.tsx

import { useDocumentTitle } from "utils";
import { useViewboards } from "utils/viewboard";
import { useProjectInUrl, useViewBoardSearchParams } from "./utils";
import { ViewboardColumn } from "./components/ViewboardCloumn"
import styled from "@emotion/styled";export const ViewBoard = () => {useDocumentTitle('看板列表')const {data: currentProject} = useProjectInUrl()const {data: viewboards, } = useViewboards(useViewBoardSearchParams())return <div><h1>{currentProject?.name}看板</h1><ColumnsContainer>{viewboards?.map(vbd => <ViewboardColumn viewboard={vbd} key={vbd.id}/>)}</ColumnsContainer></div>;
};const ColumnsContainer = styled.div`display: flex;overflow: hidden;margin-right: 2rem;
`

通過代碼可知:viewboards.map 后 ViewboardColumn 渲染多次,其中 useTasks 也同時執行多次,但是仔細看瀏覽器開發者工具可發現,相應請求并沒有執行多次,而是只執行了一次,這是因為 react-query 的緩存機制(默認兩秒內發送的多個key相同且的參數相同的請求只執行最后一次)

訪問看板列表可看到如下內容且三種狀態任務橫向排列即為正常:

待完成
管理登錄界面開發開發中
管理注冊界面開發
權限管理界面開發
UI開發
自測已完成
單元測試
性能優化

3.添加task, bug 圖標

任務的類型接口并不直接返回,而是只返回一個 typeId,并不能明確標識任務類型,需要單獨訪問接口來獲取具體任務類型

新建 src\types\TaskType.ts

export interface TaskType {id: number;name: string;
}

新建 src\utils\task-type.ts

import { useHttp } from "./http";
import { useQuery } from "react-query";
import { TaskType } from "types/TaskType";export const useTaskTypes = () => {const client = useHttp();return useQuery<TaskType[]>(["taskTypes"], () =>client("tasks"));
};

將以下兩個 svg 文件拷貝到 src\assets

bug.svg
在這里插入圖片描述

<svg xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xlinkHref="http://www.w3.org/1999/xlink"><!-- Generator: Sketch 3.5.2 (25235) - http://www.bohemiancoding.com/sketch --><title>bug</title><desc>Created with Sketch.</desc><defs/><g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage"><g id="bug" sketch:type="MSArtboardGroup"><g id="Bug" sketch:type="MSLayerGroup" transform="translate(1.000000, 1.000000)"><rect id="Rectangle-36" fill="#E5493A" sketch:type="MSShapeGroup" x="0" y="0" width="14" height="14" rx="2"/><path d="M10,7 C10,8.657 8.657,10 7,10 C5.343,10 4,8.657 4,7 C4,5.343 5.343,4 7,4 C8.657,4 10,5.343 10,7" id="Fill-2" fill="#FFFFFF" sketch:type="MSShapeGroup"/></g></g></g>
</svg>

task.svg
在這里插入圖片描述

<svg xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" width="16px" height="16px" viewBox="0 0 16 16" version="1.1"><!-- Generator: Sketch 3.5.2 (25235) - http://www.bohemiancoding.com/sketch --><title>task</title><desc>Created with Sketch.</desc><defs/><g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage"><g id="task" sketch:type="MSArtboardGroup"><g id="Task" sketch:type="MSLayerGroup" transform="translate(1.000000, 1.000000)"><rect id="Rectangle-36" fill="#4BADE8" sketch:type="MSShapeGroup" x="0" y="0" width="14" height="14" rx="2"/><g id="Page-1" transform="translate(4.000000, 4.500000)" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" sketch:type="MSShapeGroup"><path d="M2,5 L6,0" id="Stroke-1"/><path d="M2,5 L0,3" id="Stroke-3"/></g></g></g></g>
</svg>

直接使用可能會有如下報錯:

Compiled with problems:XERROR in ./src/assets/task.svgModule build failed (from ./node_modules/@svgr/webpack/lib/index.js):
SyntaxError: unknown file: Namespace tags are not supported by default. React's JSX doesn't support namespace tags. You can set `throwIfNamespace: false` to bypass this warning.

skety:type 這種類型的標簽屬性改成 sketchType 駝峰這樣才能被 JSX 接受。

  • 編譯有問題: ./src/assets/bug.svg 中的錯誤-慕課網
  • reactjs - SyntaxError: unknown: Namespace tags are not supported by default - Stack Overflow

svg 文件 修改后的源碼如下:

  • bug.svg
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xlinkHref="http://www.w3.org/1999/xlink" xmlnsSketch="http://www.bohemiancoding.com/sketch/ns"><!-- Generator: Sketch 3.5.2 (25235) - http://www.bohemiancoding.com/sketch --><title>bug</title><desc>Created with Sketch.</desc><defs></defs><g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketchType="MSPage"><g id="bug" sketchType="MSArtboardGroup"><g id="Bug" sketchType="MSLayerGroup" transform="translate(1.000000, 1.000000)"><rect id="Rectangle-36" fill="#E5493A" sketchType="MSShapeGroup" x="0" y="0" width="14" height="14" rx="2"></rect><path d="M10,7 C10,8.657 8.657,10 7,10 C5.343,10 4,8.657 4,7 C4,5.343 5.343,4 7,4 C8.657,4 10,5.343 10,7" id="Fill-2" fill="#FFFFFF" sketchType="MSShapeGroup"></path></g></g></g>
</svg>
  • task.svg
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg"xmlnsSketch="http://www.bohemiancoding.com/sketch/ns"><!-- Generator: Sketch 3.5.2 (25235) - http://www.bohemiancoding.com/sketch --><title>task</title><desc>Created with Sketch.</desc><defs></defs><g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketchType="MSPage"><g id="task" sketchType="MSArtboardGroup"><g id="Task" sketchType="MSLayerGroup" transform="translate(1.000000, 1.000000)"><rect id="Rectangle-36" fill="#4BADE8" sketchType="MSShapeGroup" x="0" y="0" width="14" height="14" rx="2"></rect><g id="Page-1" transform="translate(4.000000, 4.500000)" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" sketchType="MSShapeGroup"><path d="M2,5 L6,0" id="Stroke-1"></path><path d="M2,5 L0,3" id="Stroke-3"></path></g></g></g></g>
</svg>

編輯 src\screens\ViewBoard\components\ViewboardCloumn.tsx(引入圖標,并美化):

import { Viewboard } from "types/Viewboard";
import { useTasks } from "utils/task";
import { useTasksSearchParams } from "../utils";
import { useTaskTypes } from "utils/task-type";
import taskIcon from "assets/task.svg";
import bugIcon from "assets/bug.svg";
import styled from "@emotion/styled";
import { Card } from "antd";const TaskTypeIcon = ({ id }: { id: number }) => {const { data: taskTypes } = useTaskTypes();const name = taskTypes?.find((taskType) => taskType.id === id)?.name;if (!name) {return null;}return <img alt='task-icon' src={name === "task" ? taskIcon : bugIcon} />;
};export const ViewboardColumn = ({ viewboard }: { viewboard: Viewboard }) => {const { data: allTasks } = useTasks(useTasksSearchParams());const tasks = allTasks?.filter((task) => task.kanbanId === viewboard.id);return (<Container><h3>{viewboard.name}</h3><TasksContainer>{tasks?.map((task) => (<Card style={{marginBottom: '0.5rem'}} key={task.id}><div>{task.name}</div><TaskTypeIcon id={task.id} /></Card>))}</TasksContainer></Container>);
};export const Container = styled.div`min-width: 27rem;border-radius: 6px;background-color: rgb(244, 245, 247);display: flex;flex-direction: column;padding: .7rem .7rem 1rem;margin-right: 1.5rem;
`const TasksContainer = styled.div`overflow: scroll;flex: 1;::-webkit-scrollbar {display: none;}
`

查看效果:
效果圖


部分引用筆記還在草稿階段,敬請期待。。。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/39401.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/39401.shtml
英文地址,請注明出處:http://en.pswp.cn/news/39401.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

c語言每日一練(8)

前言&#xff1a;每日一練系列&#xff0c;每一期都包含5道選擇題&#xff0c;2道編程題&#xff0c;博主會盡可能詳細地進行講解&#xff0c;令初學者也能聽的清晰。每日一練系列會持續更新&#xff0c;暑假時三天之內必有一更&#xff0c;到了開學之后&#xff0c;將看學業情…

【javaweb】學習日記Day1 - HTML CSS入門

目錄 一、圖片標簽 ① 絕對路徑 1.絕對磁盤路徑 2.絕對網絡路徑 ② 相對路徑 &#xff08;推薦&#xff09; 二、標題標簽 三、水平線標簽 四、標題樣式 1、CSS引入樣式 ① 行內樣式 ② 內嵌樣式 ③ 外嵌樣式 2、CSS選擇器 ① 元素選擇器 ② id選擇器 ③…

Hadoop+Python+Django+Mysql熱門旅游景點數據分析系統的設計與實現(包含設計報告)

系統闡述的是使用熱門旅游景點數據分析系統的設計與實現&#xff0c;對于Python、B/S結構、MySql進行了較為深入的學習與應用。主要針對系統的設計&#xff0c;描述&#xff0c;實現和分析與測試方面來表明開發的過程。開發中使用了 django框架和MySql數據庫技術搭建系統的整體…

Python批量給excel文件加密

有時候我們需要定期給公司外部發郵件&#xff0c;在自動化發郵件的時候需要對文件進行加密傳輸。本文和你一起來探索用python給單個文件和批量文件加密。 ?? python自動化發郵件可參考【干貨】用Python每天定時發送監控郵件。 文章目錄 一、安裝pypiwin32包二、定義給excel加…

【Docker】Docker使用之容器技術發展史

&#x1f3ac; 博客主頁&#xff1a;博主鏈接 &#x1f3a5; 本文由 M malloc 原創&#xff0c;首發于 CSDN&#x1f649; &#x1f384; 學習專欄推薦&#xff1a;LeetCode刷題集 &#x1f3c5; 歡迎點贊 &#x1f44d; 收藏 ?留言 &#x1f4dd; 如有錯誤敬請指正&#xff0…

【Unity】UI的一些簡單知識

Canvas 新建一個Canvas Render Mode Canvas 中有一個Render Mode&#xff08;渲染模式&#xff09;&#xff0c;有三種渲染模式: Screen Space-Overlay &#xff08;屏幕空間&#xff09;Screen Space-Camara 、 World Space 其中&#xff0c;Space- Overlay是默認顯示在…

使用Spring Boot和Redis實現用戶IP接口限流的詳細指南

系列文章目錄 文章目錄 系列文章目錄前言一、準備工作二、編寫限流過濾器三、配置Redis四、測試接口限流總結 前言 在高并發場景下&#xff0c;為了保護系統免受惡意請求的影響&#xff0c;接口限流是一項重要的安全措施。本文將介紹如何使用Spring Boot和Redis來實現用戶IP的…

數據統計與可視化的Dash應用程序

在數據分析和可視化領域&#xff0c;Dash是一個強大的工具&#xff0c;它結合了Python中的數據處理庫&#xff08;如pandas&#xff09;和交互式可視化庫&#xff08;如Plotly&#xff09;以及Web應用程序開發框架。本文將介紹如何使用Dash創建一個簡單的數據統計和可視化應用程…

移動端網頁中的前端視頻技術探索

引言 隨著移動設備的普及和網絡速度的提升&#xff0c;移動端網頁中的視頻播放已經成為了越來越重要的功能需求。本篇博客將介紹一些在移動端網頁中實現前端視頻播放的技術探索&#xff0c;并提供詳細的代碼示例。 1. 基本視頻標簽 在移動端網頁中實現視頻播放最基本的方法就…

【C++學習手札】一文帶你初識運算符重載

食用指南&#xff1a;本文在有C基礎的情況下食用更佳 &#x1f340;本文前置知識&#xff1a; C類 ??今日夜電波&#xff1a;クリームソーダとシャンデリア—Edo_Ame江戶糖 1:20 ━━━━━━?&#x1f49f;──────── 3:40 …

ID3 決策樹

西瓜數據集D如下: 編號色澤根蒂敲聲紋理臍部觸感好瓜1青綠蜷縮濁響清晰凹陷硬滑是2烏黑蜷縮沉悶清晰凹陷硬滑是3烏黑蜷縮濁響清晰凹陷硬滑是4青綠蜷縮沉悶清晰凹陷硬滑是5淺白蜷縮濁響清晰凹陷硬滑是6青綠稍蜷濁響清晰稍凹軟粘是7烏黑稍蜷濁響稍糊稍凹軟粘是8烏黑稍蜷濁響清晰…

idea cannot download sources 解決方法

問題 點擊class文件右上角下載源碼失敗 解決方案 找到idea terminal 控制臺cd 至maven工程執行 mvn dependency:resolve -Dclassifiersources

【IMX6ULL驅動開發學習】04.應用程序和驅動程序數據傳輸和交互的4種方式:非阻塞、阻塞、POLL、異步通知

一、數據傳輸 1.1 APP和驅動 APP和驅動之間的數據訪問是不能通過直接訪問對方的內存地址來操作的&#xff0c;這里涉及Linux系統中的MMU&#xff08;內存管理單元&#xff09;。在驅動程序中通過這兩個函數來獲得APP和傳給APP數據&#xff1a; copy_to_usercopy_from_user …

24屆近3年上海電力大學自動化考研院校分析

今天給大家帶來的是上海電力大學控制考研分析 滿滿干貨&#xff5e;還不快快點贊收藏 一、上海電力大學 學校簡介 上海電力大學&#xff08;Shanghai University of Electric Power&#xff09;&#xff0c;位于上海市&#xff0c;是中央與上海市共建、以上海市管理為主的全日…

stack 、 queue的語法使用及底層實現以及deque的介紹【C++】

文章目錄 stack的使用queue的使用適配器queue的模擬實現stack的模擬實現deque stack的使用 stack是一種容器適配器&#xff0c;具有后進先出&#xff0c;只能從容器的一端進行元素的插入與提取操作 #include <iostream> #include <vector> #include <stack&g…

Layui列表復選框根據條件禁用

// 禁用客服回訪id有值的復選框res.data.forEach(function (item, i) {if (item.feedbackEmpId) {let index res.data[i][LAY_TABLE_INDEX];$(".layui-table tr[data-index"index"] input[typecheckbox]").prop(disabled,true);$(".layui-table tr[d…

【WebRTC---源碼篇】(二十四)GCC獲取碼率后的分配

RtpTransportControllerSend::PostUpdates 配置碼率 // Contains updates of network controller comand state. Using optionals to // indicate whether a member has been updated. The array of probe clusters // should be used to send out probes if not empty. // 包…

【SpringBoot】89、SpringBoot中使用@Transactional進行事務管理

事務是一組組合成邏輯工作單元的操作,雖然系統中可能會出錯,但事務將控制和維護事務中每個操作的一致性和完整性。 1、SpringBoot 引用說明 新建的 Spring Boot 項目中,一般都會引用 spring-boot-starter 或者 spring-boot-starter-web,而這兩個起步依賴中都已經包含了對…

EV 錄屏修復小工具

參考這篇文章, EV錄制文件損壞-修復方法, 我用 C# 寫了一個小程序. 倉庫: github.com/SlimeNull/EvRepair 下載: github.com/SlimeNull/EvRepair/Releases 鏡像: gitee.com/slimenull/EvRepair/releases 覺得還不錯的話, 點個星星 推薦使用的幾個理由: 內嵌 ffmpeg 和 recov…

Linux學習之初識Linux

目錄 一.Linux的發展歷史及概念 1.什么是Linux UNIX發展的歷史&#xff1a; Linux發展歷史&#xff1a; 2. 開源 商業化發行版本 二. 如何搭建Linux環境 Linux 環境的搭建方式主要有三種&#xff1a; 1. 直接安裝在物理機上 2. 使用虛擬機軟件 3. 使用云服務器 三. …