Day20-前端Web案例——部門管理

目錄

  • 部門管理
  • 1. 前后端分離開發
  • 2. 準備工作
  • 2.1 創建Vue項目
    • 2.2 安裝依賴
    • 2.3 精簡項目
  • 3. 頁面布局
    • 3.1 介紹
    • 3.2 整體布局
    • 3.3 左側菜單
  • 4. Vue Router
    • 4.1 介紹
    • 4.2 入門
    • 4.3 案例
    • 4.4 首頁制作
  • 5. 部門管理
    • 5.1部門列表
      • 5.1.1. 基本布局
      • 5.1.2 加載數據
      • 5.1.3 程序優化
    • 5.2 新增部門
    • 5.3 修改部門
      • 5.3.1 查詢回顯
      • 5.3.2 保存修改
    • 5.4 刪除部門
    • 5.5 表單校驗
      • 5.5.1 ElementPlus 參考
      • 5.5.2 實現

部門管理

在前面的課程中,我們學習了Vue工程化的基礎內容、TS、ElementPlus,那接下來呢,我們要通過一個案例,加強大家對于Vue項目的理解,并掌握Vue項目的開發。 這個案例呢,就是我們之前所做的Tlias智能學習輔助系統。

在這里插入圖片描述

在這個案例中,我們主要完成 部門管理員工管理 的功能開發。 而今天呢,我們先來完成部門管理的功能開發,而在完成部門管理的功能開發之前,先需要完成基礎的準備工作。 所以今天的課程安排如下:

  • 前后端分類開發
  • 準備工作
  • 頁面布局
  • Vue-Router
  • 部門管理

1. 前后端分離開發

在之前的課程中,我們介紹過,現在的企業項目開發有2種開發模式:前后臺混合開發前后臺分離開發

前后臺混合開發,顧名思義就是前臺后臺代碼混在一起開發。這種開發模式有如下缺點:

  • 溝通成本高:后臺人員發現前端有問題,需要找前端人員修改,前端修改成功,再交給后臺人員使用
  • 分工不明確:后臺開發人員需要開發后臺代碼,也需要開發部分前端代碼。很難培養專業人才
  • 不便管理:所有的代碼都在一個工程中
  • 難以維護:前端代碼更新,和后臺無關,但是需要整個工程包括后臺一起重新打包部署。

所以我們目前基本都是采用的前后臺分離開發方式,如下圖所示:

在這里插入圖片描述

我們將原先的工程分為前端工程和后端工程這2個工程,然后前端工程交給專業的前端人員開發,后端工程交給專業的后端人員開發。

前端頁面需要數據,可以通過發送異步請求,從后臺工程獲取。但是,我們前后臺是分開來開發的,那么前端人員怎么知道后臺返回數據的格式呢?后端人員開發,怎么知道前端人員需要的數據格式呢?

所以針對這個問題,我們前后臺統一制定一套規范!我們前后臺開發人員都需要遵循這套規范開發,這就是我們的接口文檔

那么接口文檔的內容怎么來的呢?是我們后臺開發者根據產品經理提供的產品原型和需求文檔所撰寫出來的。

那么基于前后臺分離開發的模式下,我們后臺開發者開發一個功能的具體流程如何呢?如下圖所示:

在這里插入圖片描述

  1. 需求分析:首先我們需要閱讀需求文檔,分析需求,理解需求。
  2. 接口定義:查詢接口文檔中關于需求的接口的定義,包括地址,參數,響應數據類型等等
  3. 前后臺并行開發:各自按照接口文檔進行開發,實現需求
  4. 測試:前后臺開發完了,各自按照接口文檔進行測試
  5. 前后段聯調測試:前段工程請求后端工程,測試功能

2. 準備工作

2.1 創建Vue項目

在自己工作目錄下,運行 cmd 打開命令行,運行如下指令,來創建vue項目【

npm init vue@latest

在這里插入圖片描述

2.2 安裝依賴

1). 在命令行中執行如下命令,為創建好的Vue項目安裝 ElementPlus、Axios 的依賴。

npm install element-plus --save
npm install axios

2). 為創建好的 Vue項目 配置ElementPlus (參照官網),在 main.ts 中引入如下配置信息 【注意:是追加如下內容】:

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/es/locale/lang/zh-cn'import * as ElementPlusIconsVue from '@element-plus/icons-vue'//引入ElementPlus的Icon組件
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {app.component(key, component)
}
app.use(ElementPlus, {locale: zhCn})app.mount('#app')

最終完整的 main.ts 文件內容如下:

import { createApp } from 'vue'
import { createPinia } from 'pinia'import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import './assets/main.css'import zhCn from 'element-plus/es/locale/lang/zh-cn'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'const app = createApp(App)for (const [key, component] of Object.entries(ElementPlusIconsVue)) {app.component(key, component)
}
app.use(createPinia())
app.use(router)
app.use(ElementPlus, {locale: zhCn})app.mount('#app')

3). 在 env.d.ts 中引入ElementPlus的語言包(可不做)

declare module 'element-plus/es/locale/lang/zh-cn'

2.3 精簡項目

由于基于Vue腳手架創建的項目里面攜帶了很多的多余的Vue組件。 并準備對應的組件存放目錄 。

  • 刪除 components 目錄中的vue文件
  • 刪除 views 目錄中的vue文件
  • 清空根組件文件 App.vue 中的內容,只保留基礎的vue組件文件的結構標簽 <script> <template> <style>

在這里插入圖片描述

3. 頁面布局

3.1 介紹

我們在制作一個頁面的時候,一定是先關注整體的頁面布局,然后再關注具體的細節處理 。 所以這一小節,我們就先來完成頁面的整體布局。

在這里插入圖片描述

我們會看到,整個頁面分為這么三個部分:
①. 頁頭部分
②. 側邊欄
③. 主區域

而要完成這樣的頁面布局,我們其實是可以借助于 ElementPlus 中提供的 Container布局容器 來實現:

在這里插入圖片描述

Container布局容器,用于布局的容器組件,方便快速搭建頁面的基本結構:

<el-container>:外層容器。 當子元素中包含 <el-header><el-footer> 時,全部子元素會垂直上下排列, 否則會水平左右排列。
<el-header>:頂欄容器。
<el-aside>:側邊欄容器。
<el-main>:主要區域容器。
<el-footer>:底欄容器。

而針對于我們當前案例的頁面布局,基本的結構如下:

在這里插入圖片描述

提示:當 <el-container> 子元素中包含 <el-header> <el-footer> 時,全部子元素會垂直上下排列, 否則會水平左右排列。

3.2 整體布局

我們可以參照 ElementPlus 的官方網站中的 布局,拷貝其源碼,然后對其做一個改造。 具體參照的源碼如下:
在這里插入圖片描述

1). 在 src/views 目錄下,再創建一個子目錄 layout ,在其中新建一個頁面,頁面命名為:index.vue
2). 在 index.vue 中準備好基礎的組件結構后,就可以將代碼直接復制到 <template> </template> 標簽中。

<script setup lang="ts"></script><template><div class="common-layout"><el-container><!-- 頂欄 - header --><el-header>Header</el-header><!-- 左側菜單 & 主區域 --><el-container><el-aside width="200px">Aside</el-aside><el-main>Main</el-main></el-container></el-container></div>
</template><style scoped></style>

然后,我們先根據頁面原型中的布局顯示進行調整。 先完成頂欄部分的制作,具體的代碼如下:

<script setup lang="ts"></script><template><div class="common-layout"><el-container><!-- 頂欄 - header --><el-header class="header"><span class="title">Tlias智能學習輔助系統</span><span class="right_tool"><a href=""><el-icon><EditPen /></el-icon> 修改密碼 &nbsp;&nbsp;&nbsp;&nbsp;</a><a href=""><el-icon><SwitchButton /></el-icon> 退出登錄&nbsp;&nbsp;&nbsp;&nbsp;</a></span></el-header><!-- 左側菜單 & 主區域 --><el-container><el-aside width="200px">Aside</el-aside><el-main>Main</el-main></el-container></el-container></div>
</template><style scoped>
.header {background-image: linear-gradient(to right, #e70cc5, #e94dcf, #eb6fd8, #ec8bdf, #eea5e6);line-height: 60px;
}.title {color: white;font-size: 35px;font-family: 楷體;}.right_tool {float: right;
}a {text-decoration: none;color: white;
}
</style>

最終的頂欄布局效果如下所示:

在這里插入圖片描述

3.3 左側菜單

頂欄布局完畢之后,接下來,我們再來完成左側菜單欄的制作。 左側菜單欄的制作,也不需要我們自己實現,其實在 ElementPlus 中已經提供了對應的菜單組件,我們可以直接參考【PS: 其實就是復制過來,參考頁面原型和需求,將其改造成我們需要的樣子就可以了】。

參考代碼的出處如下:

在這里插入圖片描述

然后就可以參考其提供的源碼,復制到我們的側邊欄部分 <el-aside> ... </el-aside>,然后根據我們案例的需要進行改造,改造成我們需要的樣子即可。

最終左側菜單欄的代碼如下:

<!-- 左側菜單 -->
<el-aside width="200px" class="aside"><el-scrollbar><el-menu router><!-- 首頁菜單 --><el-menu-item index="/index"><el-icon><Promotion /></el-icon> 首頁</el-menu-item><!-- 班級管理菜單 --><el-sub-menu index="/manage"><template #title><el-icon><Menu /></el-icon> 班級學員管理</template><el-menu-item index="/clazz"><el-icon><HomeFilled /></el-icon>班級管理</el-menu-item><el-menu-item index="/stu"><el-icon><UserFilled /></el-icon>學員管理</el-menu-item></el-sub-menu><!-- 系統信息管理 --><el-sub-menu index="/system"><template #title><el-icon><Tools /></el-icon>系統信息管理</template><el-menu-item index="/dept"><el-icon><HelpFilled /></el-icon>部門管理</el-menu-item><el-menu-item index="/emp"><el-icon><Avatar /></el-icon>員工管理</el-menu-item></el-sub-menu><!-- 數據統計管理 --><el-sub-menu index="/report"><template #title><el-icon><Histogram /></el-icon>數據統計管理</template><el-menu-item index="/empReport"><el-icon><InfoFilled /></el-icon>員工信息統計</el-menu-item><el-menu-item index="/stuReport"><el-icon><Share /></el-icon>學員信息統計</el-menu-item><el-menu-item index="/log"><el-icon><Document /></el-icon>日志信息統計</el-menu-item></el-sub-menu></el-menu></el-scrollbar>
</el-aside>

并在 <style></style> 中添加如下樣式:

.aside {border: 1px solid #ccc;height: 690px;width: 220px;
}

最終,瀏覽器打開的效果如下:

在這里插入圖片描述
到目前為止,layout/index.vue 中的內容如下:

<script setup lang="ts"></script><template><div class="common-layout"><el-container><!-- 頂欄 - header --><el-header class="header"><span class="title">Tlias智能學習輔助系統</span><span class="right_tool"><a href=""><el-icon><EditPen /></el-icon> 修改密碼 &nbsp;&nbsp;&nbsp;&nbsp;</a><a href=""><el-icon><SwitchButton /></el-icon> 退出登錄&nbsp;&nbsp;&nbsp;&nbsp;</a></span></el-header><!-- 左側菜單 & 主區域 --><el-container><!-- 左側菜單 --><el-aside width="200px" class="aside"><el-scrollbar><el-menu router><!-- 首頁菜單 --><el-menu-item index="/index"><el-icon><Promotion /></el-icon> 首頁</el-menu-item><!-- 班級管理菜單 --><el-sub-menu index="/manage"><template #title><el-icon><Menu /></el-icon> 班級學員管理</template><el-menu-item index="/clazz"><el-icon><HomeFilled /></el-icon>班級管理</el-menu-item><el-menu-item index="/stu"><el-icon><UserFilled /></el-icon>學員管理</el-menu-item></el-sub-menu><!-- 系統信息管理 --><el-sub-menu index="/system"><template #title><el-icon><Tools /></el-icon>系統信息管理</template><el-menu-item index="/dept"><el-icon><HelpFilled /></el-icon>部門管理</el-menu-item><el-menu-item index="/emp"><el-icon><Avatar /></el-icon>員工管理</el-menu-item></el-sub-menu><!-- 數據統計管理 --><el-sub-menu index="/report"><template #title><el-icon><Histogram /></el-icon>數據統計管理</template><el-menu-item index="/empReport"><el-icon><InfoFilled /></el-icon>員工信息統計</el-menu-item><el-menu-item index="/stuReport"><el-icon><Share /></el-icon>學員信息統計</el-menu-item><el-menu-item index="/log"><el-icon><Document /></el-icon>日志信息統計</el-menu-item></el-sub-menu></el-menu></el-scrollbar></el-aside><el-main>Main</el-main></el-container></el-container></div>
</template><style scoped>
.header {background-image: linear-gradient(to right, #e70cc5, #e94dcf, #eb6fd8, #ec8bdf, #eea5e6);line-height: 60px;
}.title {color: white;font-size: 35px;font-family: 楷體;}.right_tool {float: right;
}a {text-decoration: none;color: white;
}.aside {border: 1px solid #ccc;height: 690px;width: 220px;
}
</style>

目前,我們點擊左側的菜單,右側主區域展示的內容,還不能做到動態變化。 那應該如何做到動態變化呢 ?

在這里插入圖片描述

那要完成這個功能效果,我們就需要用到Vue生態中的路由 Vue-Router

4. Vue Router

4.1 介紹

在這里插入圖片描述

  • Vue Router:Vue的官方路由。 為Vue提供富有表現力、可配置的、方便的路由。
  • Vue中的路由,主要定義的是路徑與組件之間的對應關系。

比如,我們打開一個網站,點擊左側菜單,地址欄的地址發生變化。 地址欄地址一旦發生變化,在主區域顯示對應的頁面組件。

在這里插入圖片描述
在這里插入圖片描述
VueRouter主要由以下三個部分組成,如下所示:
在這里插入圖片描述

  • VueRouter:路由器類,根據路由請求在路由視圖中動態渲染選中的組件
  • <router-link>:請求鏈接組件,瀏覽器會解析成<a>
  • <router-view>:動態視圖組件,用來渲染展示與路由路徑對應的組件

4.2 入門

介紹完了VueRouter之后,接下來,我們就通過一個入門程序,來演示一下VueRouter的使用。

1). 安裝 vue-router (創建Vue項目時,可以選擇)

npm install vue-router@4

2). 在 main.ts 入口文件中進行配置,加入如下配置

import router from './router'//..... 創建完vue的應用實例后,調用app.use
app.use(router)

3). 在 src/views 目錄下再定義一個文件夾,在文件夾中再創建一個 vue 組件文件

在這里插入圖片描述

4). 定義路由
src/router/index.ts 中定義路由表信息,在其中主要是定義請求路徑與組件之間的對應關系。 完整的文件內容如下:

import { createRouter, createWebHistory } from 'vue-router'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: '/',name: 'home',component: () => import('../views/layout/index.vue')},{path: '/index',name: 'index',component: () => import('../views/index/index.vue')}]
})export default router

5). 在 App.vue 根組件中,定義 <RouterView></RouterView> 標簽

該標簽將用于顯示,訪問的請求路徑對應的組件。

<script setup lang="ts"></script><template><RouterView></RouterView>
</template><style scoped></style>

6). 測試
瀏覽器訪問請求路徑 http://127.0.0.1:5173/index,展示如下頁面內容(該頁面內容,就是我們在 index/index.vue 中定義的頁面內容):

在這里插入圖片描述

瀏覽器訪問請求路徑 http://127.0.0.1:5173/,展示如下頁面內容 (該頁面內容,就是我們在 layout/index.vue 中定義的頁面內容):

在這里插入圖片描述

到此,我們發現,我們請求不同的請求路徑,就可以在頁面中顯示不同的組件。具體的訪問流程如下:

在這里插入圖片描述

4.3 案例

那接下來,我們就要基于 VueRouter 來完成點擊 左側菜單,動態切換主展示區域內容的動態效果。

1). 準備案例的空頁面

在這里插入圖片描述

<script setup lang="ts"></script><template>班級管理|學生管理|員工管理|部門管理|首頁展示
</template><style scoped></style>

2). 在 src/router/index.ts 中配置路由信息

這里我們用到了Vue中的嵌套路由,具體定義方式,主要是在配置路由信息時,通過children 來描述。如你所見,children 配置只是另一個路由數組,就像 routes 本身一樣。因此,你可以根據自己的需要,不斷地嵌套視圖。

import { createRouter, createWebHistory } from 'vue-router'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: '/',name: 'home',component: () => import('../views/layout/index.vue'),redirect: '/index',children: [{path: 'index',name: 'index',component: () => import('../views/index/index.vue') //首頁},{path: 'emp',name: 'emp',component: () => import('../views/emp/index.vue') //員工管理},{path: 'dept',name: 'dept',component: () => import('../views/dept/index.vue') //部門管理},{path: 'clazz',name: 'clazz',component: () => import('../views/clazz/index.vue') //班級管理},{path: 'stu',name: 'stu',component: () => import('../views/stu/index.vue') //學員管理}]}]
})export default router

3). 完善左側菜單欄 layout/index.vue,菜單欄關聯路由

在這里插入圖片描述

菜單關聯了路由之后,我們點擊對應的菜單,就會根據菜單的唯一標識 index,在地址欄中請求訪問對應的地址。

4). 在Vue組件中,動態展示與路由對應的組件 。

需要在 layout/index.vue 中的 <el-main></el-main> 中添加動態路由視圖組件 <RouterView></RouterView> 。如下:

<!-- 主展示區域 -->
<el-main><RouterView></RouterView>
</el-main>

最終完整的 layout/index.vue 代碼如下:

<script setup lang="ts"></script><template><div class="common-layout"><el-container><!-- 頂欄 - header --><el-header class="header"><span class="title">Tlias智能學習輔助系統</span><span class="right_tool"><a href=""><el-icon><EditPen /></el-icon> 修改密碼 &nbsp;&nbsp;&nbsp;&nbsp;</a><a href=""><el-icon><SwitchButton /></el-icon> 退出登錄&nbsp;&nbsp;&nbsp;&nbsp;</a></span></el-header><!-- 左側菜單 & 主區域 --><el-container><!-- 左側菜單 --><el-aside width="200px" class="aside"><el-scrollbar><el-menu router><!-- 首頁菜單 --><el-menu-item index="/index"><el-icon><Promotion /></el-icon> 首頁</el-menu-item><!-- 班級管理菜單 --><el-sub-menu index="/manage"><template #title><el-icon><Menu /></el-icon> 班級學員管理</template><el-menu-item index="/clazz"><el-icon><HomeFilled /></el-icon>班級管理</el-menu-item><el-menu-item index="/stu"><el-icon><UserFilled /></el-icon>學員管理</el-menu-item></el-sub-menu><!-- 系統信息管理 --><el-sub-menu index="/system"><template #title><el-icon><Tools /></el-icon>系統信息管理</template><el-menu-item index="/dept"><el-icon><HelpFilled /></el-icon>部門管理</el-menu-item><el-menu-item index="/emp"><el-icon><Avatar /></el-icon>員工管理</el-menu-item></el-sub-menu><!-- 數據統計管理 --><el-sub-menu index="/report"><template #title><el-icon><Histogram /></el-icon>數據統計管理</template><el-menu-item index="/empReport"><el-icon><InfoFilled /></el-icon>員工信息統計</el-menu-item><el-menu-item index="/stuReport"><el-icon><Share /></el-icon>學員信息統計</el-menu-item><el-menu-item index="/log"><el-icon><Document /></el-icon>日志信息統計</el-menu-item></el-sub-menu></el-menu></el-scrollbar></el-aside><!-- 主展示區域 --><el-main><RouterView></RouterView></el-main></el-container></el-container></div>
</template><style scoped>
.header {background-image: linear-gradient(to right, #e70cc5, #e94dcf, #eb6fd8, #ec8bdf, #eea5e6);line-height: 60px;
}.title {color: white;font-size: 35px;font-family: 楷體;}.right_tool {float: right;
}a {text-decoration: none;color: white;
}.aside {border: 1px solid #ccc;height: 690px;width: 220px;
}
</style>

5). 測試
在這里插入圖片描述
在這里插入圖片描述

4.4 首頁制作

其實首頁,我們只需要展示一張圖片即可。 直接在 index/index.vue 中引入一張圖片即可,具體代碼如下:

<script setup lang="ts"></script><template><img src="@/assets/index.png">
</template><style scoped></style>

最終效果如下:

在這里插入圖片描述

5. 部門管理

部門管理的頁面內容,寫在 src/views/dept/index.vue 中。

5.1部門列表

5.1.1. 基本布局

首先,根據頁面原型、需求說明、接口文檔,先完成頁面的基本布局 。 可以參考 ElementPlus 中的組件,拷貝過來適當做一個改造。

在這里插入圖片描述

部門管理組件 src/views/dept/index.vue 具體的頁面布局代碼如下:

<script setup lang="ts">
import {ref} from 'vue'
import type { DeptModelArray } from '@/api/model/model'//聲明列表展示數據
let tableData = ref<DeptModelArray>([])
</script><template><h1>部門管理</h1><el-button type="primary" style="float: right" @click="">+ 新增</el-button><br><br><!-- 部門數據表格 --><el-table :data="tableData" border style="width: 100%"><el-table-column type="index" label="序號"  width="80"  align="center"/><el-table-column prop="name" label="部門名稱" width="250"  align="center"/><el-table-column prop="updateTime" label="最后操作時間" width="300"  align="center"/><el-table-column label="操作"  align="center"><template #default="scope"><el-button size="small" type="primary" @click="">修改</el-button><el-button size="small" type="danger"  @click="">刪除</el-button></template></el-table-column></el-table>
</template><style scoped></style>

表格中每一列展示的屬性 prop 都是根據接口文檔來的,接口文檔返回什么樣的數據,我們就安裝對應的數據格式進行解析。

5.1.2 加載數據

根據需求,需要在新增、修改、刪除部門之后,加載最新的部門數據。 在打開頁面之后,也需要自動加載部門數據。 那接下來,我們就需要基于axios發送異步請求,動態獲取數據。

需要在 src/views/dept/index.vue 中增加如下代碼,在頁面加載完成發送異步請求(https://mock.apifox.com/m1/3161925-0-default/depts),動態加載的Axios。

<script setup lang="ts">
import {ref, onMounted} from 'vue'
import type { DeptModelArray } from '@/api/model/model'
import axios from 'axios'//聲明列表展示數據
let tableData = ref<DeptModelArray>([])//動態加載數據-查詢部門
const queryAll = async () => {const result = await axios.get('https://mock.apifox.com/m1/3161925-0-default/depts')tableData.value = result.data.data
}//鉤子函數
onMounted(() => {queryAll()
})
</script>

添加代碼后,最終 src/views/dept/index.vue 代碼如下:

<script setup lang="ts">
import {ref, onMounted} from 'vue'
import type { DeptModelArray } from '@/api/model/model'
import axios from 'axios'//聲明列表展示數據
let tableData = ref<DeptModelArray>([])//動態加載數據-查詢部門
const queryAll = async () => {const result = await axios.get('https://mock.apifox.com/m1/3161925-0-default/depts')tableData.value = result.data.data
}//鉤子函數
onMounted(() => {queryAll()
})
</script><template><h1>部門管理</h1><el-button type="primary" style="float: right" @click="">+ 新增</el-button><br><br><!-- 部門數據表格 --><el-table :data="tableData" border style="width: 100%"><el-table-column type="index" label="序號"  width="80"  align="center"/><el-table-column prop="name" label="部門名稱" width="250"  align="center"/><el-table-column prop="updateTime" label="最后操作時間" width="300"  align="center"/><el-table-column label="操作"  align="center"><template #default="scope"><el-button size="small" type="primary" @click="">修改</el-button><el-button size="small" type="danger"  @click="">刪除</el-button></template></el-table-column></el-table>
</template><style scoped></style>

代碼編寫完成之后,打開瀏覽器進行測試 ,我們可以看到數據可以正常的查詢出來,并展示在頁面中。

在這里插入圖片描述

思考:直接在Vue組件中,基于axios發送異步請求,存在什么問題?

在這里插入圖片描述

我們剛才在完成部門列表查詢時,是直接基于axios發送異步請求,直接將接口的請求地址放在組件文件 .vue 中。 而如果開發一個大型的項目,組件文件可能會很多很多很多,如果前端開發完畢,進行前后端聯調測試了,需要修改請求地址,那么此時,就需要找到每一個 .vue 文件,然后挨個修改。 所以上述的代碼,雖然實現了動態加載數據的功能。 但是存在以下問題:

  • 請求路徑難以維護
  • 數據解析繁瑣

5.1.3 程序優化

1). 為了解決上述問題,我們在前端項目開發時,通常會定義一個請求處理的工具類 - src/utils/request.ts 。 在這個工具類中,對axios進行了封裝。 具體代碼如下:

import axios from 'axios'//創建axios實例對象
const request = axios.create({baseURL: '/api',timeout: 600000
})//axios的響應 response 攔截器
request.interceptors.response.use((response) => { //成功回調return response.data},(error) => { //失敗回調return Promise.reject(error)}
)export default request

2). 而與服務端進行異步交互的邏輯,通常會按模塊,封裝在一個單獨的API中,如:src/api/dept.ts

import request from "@/utils/request"
import type { ResultModel } from "./model/model"//列表查詢
export const queryAllApi = () => request.get<any, ResultModel>('/depts')

3). 修改 src/views/dept/index.vue 中的代碼

現在就不需要每次直接調用axios發送異步請求了,只需要將我們定義的對應模塊的API導入進來,就可以直接使用了。

<script setup lang="ts">
import {ref, onMounted} from 'vue'
import type { DeptModelArray } from '@/api/model/model'
import {queryAllApi} from '@/api/dept'//聲明列表展示數據
let tableData = ref<DeptModelArray>([])//動態加載數據-查詢部門
const queryAll = async () => {const result = await queryAllApi()tableData.value = result.data
}//鉤子函數
onMounted(() => {queryAll()
})
</script>

做完上面這三部之后,我們打開瀏覽器發現,并不能訪問到接口數據。原因是因為,目前請求路徑不對。

在這里插入圖片描述

4). 在 vite.config.ts 中配置前端請求服務器的信息

在服務器中配置代理proxy的信息,并在配置代理時,執行目標服務器。 以及url路徑重寫的規則。

在這里插入圖片描述

  server: {proxy: {'/api': {target: 'http://localhost:8080',secure: false,changeOrigin: true,rewrite: (path) => path.replace(/^\/api/, ''),}}}

添加位置如下所示:

在這里插入圖片描述

然后,我們就可以啟動服務器端的程序,進行測試了(測試時,記得將之前編寫的登錄校驗的過濾器、攔截器、AOP程序全部注釋掉)。

在這里插入圖片描述

5.2 新增部門

接下來,我們再來完成新增部門的功能實現。

1). 在 src/views/dept/index.vue 中完成頁面布局,并編寫交互邏輯,完成數據綁定。

完整代碼如下:

<script setup lang="ts">
import {ref, onMounted} from 'vue'
import type { DeptModelArray, DeptModel } from '@/api/model/model'
import {queryAllApi, addApi} from '@/api/dept'
import { ElMessage } from 'element-plus';//聲明列表展示數據
let tableData = ref<DeptModelArray>([])//動態加載數據-查詢部門
const queryAll = async () => {const result = await queryAllApi()tableData.value = result.data
}//鉤子函數
onMounted(() => {queryAll()
})//新增部門
const dialogFormVisible = ref<boolean>(false) 
const deptForm = ref<DeptModel>({name: ''})
const formTitle = ref<string>('')//點擊新增按鈕觸發的函數
const add = () => {formTitle.value = '新增部門'dialogFormVisible.value = truedeptForm.value = {name: ''}
}//點擊保存按鈕-發送異步請求
const save = async () => {const result = await addApi(deptForm.value)if(result.code){ElMessage.success('操作成功')}else{ElMessage.error(result.msg)}dialogFormVisible.value = falsequeryAll()
}</script><template><h1>部門管理</h1><el-button type="primary" style="float: right" @click="add">+ 新增</el-button><br><br><!-- 部門數據表格 --><el-table :data="tableData" border style="width: 100%"><el-table-column type="index" label="序號"  width="80"  align="center"/><el-table-column prop="name" label="部門名稱" width="250"  align="center"/><el-table-column prop="updateTime" label="最后操作時間" width="300"  align="center"/><el-table-column label="操作"  align="center"><template #default="scope"><el-button size="small" type="primary" @click="">修改</el-button><el-button size="small" type="danger"  @click="">刪除</el-button></template></el-table-column></el-table><!-- 新增部門 / 修改部門對話框 --><el-dialog v-model="dialogFormVisible" :title="formTitle" width="30%"><el-form :model="deptForm"><el-form-item label="部門名稱" label-width="80px"><el-input v-model="deptForm.name" autocomplete="off" /></el-form-item></el-form><template #footer><span class="dialog-footer"><el-button @click="dialogFormVisible = false">取消</el-button><el-button type="primary" @click="save">確定</el-button></span></template></el-dialog></template><style scoped></style>

2). 在 src/api/dept.ts 中增加如下代碼

//添加部門
export const addApi = (dept:DeptModel) => request.post<any, ResultModel>('/depts', dept)

目前 src/api/dept.ts 文件中完整代碼如下:

import request from "@/utils/request"
import type { DeptModel, ResultModel } from "./model/model"//列表查詢
export const queryAllApi = () => request.get<any, ResultModel>('/depts')//添加部門
export const addApi = (dept:DeptModel) => request.post<any, ResultModel>('/depts', dept)

打開瀏覽器進行測試,效果如下:

在這里插入圖片描述

在這里插入圖片描述

5.3 修改部門

對于修改操作,通常會分為兩步進行:

  1. 查詢回顯
  2. 保存修改

在這里插入圖片描述

交互邏輯:

  1. 點擊 編輯 按鈕,根據ID進行查詢,彈出對話框,完成頁面回顯展示。(查詢回顯)
  2. 點擊 確定 按鈕,保存修改后的數據,完成數據更新操作。(保存修改)

5.3.1 查詢回顯

1). 在 src/api/dept.ts 中定義根據id查詢的請求

//根據ID查詢
export const queryInfoApi = (id:number) => request.get(`/depts/${id}`)

2). 在 src/views/dept/index.vue 中添加根據ID查詢回顯的邏輯

為修改按鈕綁定事件 <template></template>:

<el-button size="small" type="primary" @click="update(scope.row.id)">修改</el-button>

<script> </script> 添加JS邏輯:

//修改部門-查詢回顯
const update = async (id:number) => {formTitle.value = '修改部門'dialogFormVisible.value = truedeptForm.value = {name: ''}const result = await queryInfoApi(id)deptForm.value = result.data
}

到目前為止,完整的 src/views/dept/index.vue 代碼如下:

<script setup lang="ts">
import {ref, onMounted} from 'vue'
import type { DeptModelArray, DeptModel } from '@/api/model/model'
import {queryAllApi, addApi, queryInfoApi} from '@/api/dept'
import { ElMessage } from 'element-plus';//聲明列表展示數據
let tableData = ref<DeptModelArray>([])//動態加載數據-查詢部門
const queryAll = async () => {const result = await queryAllApi()tableData.value = result.data
}//鉤子函數
onMounted(() => {queryAll()
})//新增部門
const dialogFormVisible = ref<boolean>(false) 
const deptForm = ref<DeptModel>({name: ''})
const formTitle = ref<string>('')//點擊新增按鈕觸發的函數
const add = () => {formTitle.value = '新增部門'dialogFormVisible.value = truedeptForm.value = {name: ''}
}//點擊保存按鈕-發送異步請求
const save = async () => {const result = await addApi(deptForm.value)if(result.code){ElMessage.success('操作成功')}else{ElMessage.error(result.msg)}dialogFormVisible.value = falsequeryAll()
}//修改部門-查詢回顯
const update = async (id:number) => {formTitle.value = '修改部門'dialogFormVisible.value = truedeptForm.value = {name: ''}const result = await queryInfoApi(id)deptForm.value = result.data
}</script><template><h1>部門管理</h1><el-button type="primary" style="float: right" @click="add">+ 新增</el-button><br><br><!-- 部門數據表格 --><el-table :data="tableData" border style="width: 100%"><el-table-column type="index" label="序號"  width="80"  align="center"/><el-table-column prop="name" label="部門名稱" width="250"  align="center"/><el-table-column prop="updateTime" label="最后操作時間" width="300"  align="center"/><el-table-column label="操作"  align="center"><template #default="scope"><el-button size="small" type="primary" @click="update(scope.row.id)">修改</el-button><el-button size="small" type="danger"  @click="">刪除</el-button></template></el-table-column></el-table><!-- 新增部門 / 修改部門對話框 --><el-dialog v-model="dialogFormVisible" :title="formTitle" width="30%"><el-form :model="deptForm"><el-form-item label="部門名稱" label-width="80px"><el-input v-model="deptForm.name" autocomplete="off" /></el-form-item></el-form><template #footer><span class="dialog-footer"><el-button @click="dialogFormVisible = false">取消</el-button><el-button type="primary" @click="save">確定</el-button></span></template></el-dialog></template><style scoped></style>

5.3.2 保存修改

由于 新增部門 和 修改部門使用的是同一個Dialog對話框,當前點擊 “確定” 按鈕的時候,有可能執行的是新增操作,也有可能是修改操作。

在這里插入圖片描述

那應該如何辨別到底是新增,還是修改操作呢 ?

其實,我們只需要根據 deptForm 對象的id屬性值,來判斷即可。 如果沒有id,則是新增操作 ;如果有id,則是修改操作。

所以,保存修改功能實現如下:

1). 在 src/api/dept.ts 中增加如下修改部門的請求

//修改部門
export const updateApi = (dept:DeptModel) => request.put<any, ResultModel>('/depts', dept)

2). 在 src/views/dept/index.vue 中完善(修改) save 函數的邏輯

//點擊保存按鈕-發送異步請求
const save = async () => {let result = null;if(deptForm.value.id){result = await updateApi(deptForm.value) //有id, 執行修改操作}else {result = await addApi(deptForm.value) //沒有id, 執行新增操作}if(result.code){ElMessage.success('操作成功')}else{ElMessage.error(result.msg)}dialogFormVisible.value = falsequeryAll()
}

5.4 刪除部門

1). 在 src/api/dept.ts 中增加如下刪除部門的請求

//刪除部門
export const deleteApi = (id:number) => request.delete<any, ResultModel>(`/depts?id=${id}`)

2). 在 src/views/dept/index.vue 中為什么 刪除 按鈕綁定事件

<el-button size="small" type="danger"  @click="deleteById(scope.row.id)">刪除</el-button>

3). 在 src/views/dept/index.vue 編寫根據ID刪除數據的函數

//刪除部門
const deleteById =async (id:number) => {//彈出確認框ElMessageBox.confirm('您確認刪除此部門嗎? ', '確認刪除').then( async () => {let result = await deleteApi(id)if(result.code){ //成功ElMessage.success('刪除成功')queryAll()}else {ElMessage.error(result.msg)}}).catch(() => {ElMessage.info('取消刪除')})
}

打開瀏覽器做一個測試:

在這里插入圖片描述
在這里插入圖片描述

5.5 表單校驗

目前,我們已經基本完成了部門管理的增刪改查操作。 接下來,我們對部門管理的功能進行,最后一塊完善工作,增加表單校驗。 從頁面原型中,我們可以看到,新增部門的時候部門名稱,不能為空,而且長度得在2-10之間。

在這里插入圖片描述

5.5.1 ElementPlus 參考

Form 組件允許你驗證用戶的輸入是否符合規范,來幫助你找到和糾正錯誤。Form 組件提供了表單驗證的功能,只需為 rules 屬性傳入約定的驗證規則,并將 form-Itemprop 屬性設置為需要驗證的特殊鍵值即可。

在這里插入圖片描述

5.5.2 實現

1). 定義表單校驗規則

//定義表單校驗規則
const deptFormRef = ref<FormInstance>()
const rules = ref<FormRules<DeptModel>>({name: [{ required: true, message: '部門名稱不能為空', trigger: 'blur' },{ min: 2, max: 10, message: '部門名稱長度在2-10個字之間', trigger: 'blur' },]
})

2). 將表單校驗規則與表單綁定

為表單 <el-form> 綁定 rules 屬性綁定表單校驗規則 。 為每一個表單項,指定 prop 屬性,設置為需要驗證的屬性名。

在這里插入圖片描述

3). 表單提交時,校驗表單,校驗通過,則允許提交表單。

修改save方法的邏輯,需要加入表單校驗的邏輯。

//點擊保存按鈕-發送異步請求
const save = async (form:FormInstance | undefined) => {if(!form) return;await form.validate(async (valid) => {if (valid) {let result = null;if(deptForm.value.id){result = await updateApi(deptForm.value)}else {result = await addApi(deptForm.value)}if(result.code){ElMessage.success('操作成功')}else{ElMessage.error(result.msg)}dialogFormVisible.value = falsequeryAll()}})
}

4). 重置表單校驗結果

//重置表單校驗結果
const resetForm = (formEl: FormInstance | undefined) => {if (!formEl) returnformEl.resetFields()
}

然后在點擊 “新增” / “修改” 按鈕的時候,調用 resetForm 函數,重置表單校驗結果。

在這里插入圖片描述

最終,部門管理的完整代碼如下:

1). src/api/dept.ts

import request from "@/utils/request"
import type { DeptModel, ResultModel } from "./model/model"//列表查詢
export const queryAllApi = () => request.get<any, ResultModel>('/depts')//添加部門
export const addApi = (dept:DeptModel) => request.post<any, ResultModel>('/depts', dept)//根據ID查詢
export const queryInfoApi = (id:number) => request.get(`/depts/${id}`)//修改部門
export const updateApi = (dept:DeptModel) => request.put<any, ResultModel>('/depts', dept)//刪除部門
export const deleteApi = (id:number) => request.delete<any, ResultModel>(`/depts?id=${id}`)

2). src/views/dept/index.vue

<script setup lang="ts">
import {ref, onMounted} from 'vue'
import type { DeptModelArray, DeptModel } from '@/api/model/model'
import {queryAllApi, addApi, queryInfoApi, updateApi, deleteApi} from '@/api/dept'
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus';//聲明列表展示數據
let tableData = ref<DeptModelArray>([])//動態加載數據-查詢部門
const queryAll = async () => {const result = await queryAllApi()tableData.value = result.data
}//鉤子函數
onMounted(() => {queryAll()
})//新增部門
const dialogFormVisible = ref<boolean>(false) 
const deptForm = ref<DeptModel>({name: ''})
const formTitle = ref<string>('')//點擊新增按鈕觸發的函數
const add = () => {formTitle.value = '新增部門'dialogFormVisible.value = truedeptForm.value = {name: ''}
}//點擊保存按鈕-發送異步請求
const save = async (form:FormInstance | undefined) => {if(!form) return;await form.validate(async (valid) => {if (valid) {let result = null;if(deptForm.value.id){result = await updateApi(deptForm.value)}else {result = await addApi(deptForm.value)}if(result.code){ElMessage.success('操作成功')}else{ElMessage.error(result.msg)}dialogFormVisible.value = falsequeryAll()}})
}//修改部門-查詢回顯
const update = async (id:number) => {formTitle.value = '修改部門'dialogFormVisible.value = truedeptForm.value = {name: ''}const result = await queryInfoApi(id)deptForm.value = result.data
}//刪除部門
const deleteById =async (id:number) => {//彈出確認框ElMessageBox.confirm('您確認刪除此部門嗎? ', '確認刪除').then( async () => {let result = await deleteApi(id)if(result.code){ //成功ElMessage.success('刪除成功')queryAll()}else {ElMessage.error(result.msg)}}).catch(() => {ElMessage.info('取消刪除')})
}//定義表單校驗規則
const deptFormRef = ref<FormInstance>()
const rules = ref<FormRules<DeptModel>>({name: [{ required: true, message: '部門名稱不能為空', trigger: 'blur' },{ min: 2, max: 10, message: '部門名稱長度在2-10個字之間', trigger: 'blur' },]
})//重置表單校驗結果
const resetForm = (form: FormInstance | undefined) => {if (!form) returnform.resetFields()
}
</script><template><h1>部門管理</h1><el-button type="primary" style="float: right" @click="add(); resetForm(deptFormRef);">+ 新增</el-button><br><br><!-- 部門數據表格 --><el-table :data="tableData" border style="width: 100%"><el-table-column type="index" label="序號"  width="80"  align="center"/><el-table-column prop="name" label="部門名稱" width="250"  align="center"/><el-table-column prop="updateTime" label="最后操作時間" width="300"  align="center"/><el-table-column label="操作"  align="center"><template #default="scope"><el-button size="small" type="primary" @click="update(scope.row.id); resetForm(deptFormRef);">修改</el-button><el-button size="small" type="danger"  @click="deleteById(scope.row.id)">刪除</el-button></template></el-table-column></el-table><!-- 新增部門 / 修改部門對話框 --><el-dialog v-model="dialogFormVisible" :title="formTitle" width="30%"><el-form :model="deptForm" :rules="rules" ref="deptFormRef"><el-form-item label="部門名稱" label-width="80px" prop="name"><el-input v-model="deptForm.name" autocomplete="off" /></el-form-item></el-form><template #footer><span class="dialog-footer"><el-button @click="dialogFormVisible = false; resetForm(deptFormRef);">取消</el-button><el-button type="primary" @click="save(deptFormRef)">確定</el-button></span></template></el-dialog></template><style scoped></style>

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

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

相關文章

Android java 設計封裝增強型WebView組件

Android java 設計封裝增強型WebView組件&#xff08;兼容Android 4.4&#xff09; * 特性&#xff1a; * 1. 全生命周期管理 * 2. 智能硬件加速 * 3. 鏈式配置API * 4. 安全下載管理 * 5. 全屏視頻支持 public class EnhancedWebView extends WebView {private CustomWebChrom…

vue 點擊放大,圖片預覽效果

背景&#xff1a; 在使用vue框架element組件的背景下&#xff0c;我們對圖片的展示需要點擊放大(單張)&#xff1b;如果是多張圖片&#xff0c;要支持左右滑動查看多張圖片(多張)。 單張圖片放大&#xff0c;el-image圖片組件&#xff0c;或者原生的img標簽。 多張圖片放大&…

HTTP代理的全面解讀:什么是HTTP代理?HTTP代理的工作原理

在互聯網大潮中&#xff0c;每一個請求和返回數據的背后&#xff0c;都離不開傳輸協議的支持&#xff0c;而HTTP協議無疑是最熟悉的網絡通信基礎之一。當我們談到HTTP代理時&#xff0c;它不僅讓瀏覽網絡變得更高效&#xff0c;也為數據采集以及全球性遠程任務提供了解決方案。…

學習筆記--基于Sa-Token 實現Java項目單點登錄+同端互斥檢測

目錄 同端互斥登錄 單點登錄SSO 架構選型 模式二: URL重定向傳播 前后端分離 整體流程 準備工作 搭建客戶端 搭建認證中心SSO Server 環境配置 開放認證接口 啟動類 跨域處理 同端互斥登錄 同端互斥登陸 模塊 同端互斥登錄指&#xff1a;同一類型設備上只允許單地…

本地生活服務APP開發,市場發展全新商業機遇

隨著移動互聯網的快速發展&#xff0c;人們的消費和生活習慣發生了巨大改變&#xff0c;本地生活服務市場迎來了發展爆發期&#xff01;從外賣、團購等&#xff0c;人們越來越依賴通過手機APP解決日常生活中的各種需求。對于企業而言&#xff0c;一款完善、多樣、便捷的本地生活…

當科技業成為系統性壓榨的絞肉機

深夜的硅谷辦公室依然燈火通明&#xff0c;鍵盤敲擊聲此起彼伏。一位程序員在Slack上收到主管的緊急需求&#xff1a;“這個功能明早必須上線。”他苦笑一聲&#xff0c;關掉手機里名為“緩解焦慮”的冥想App——這已是本周第三次被迫服用公司提供的“心靈解藥”。此刻&#xf…

代碼隨想錄算法訓練營第五十六天 | 108.冗余連接 109.冗余連接II

108. 冗余連接 卡碼網題目鏈接&#xff08;ACM模式&#xff09;(opens new window) 題目描述 有一個圖&#xff0c;它是一棵樹&#xff0c;他是擁有 n 個節點&#xff08;節點編號1到n&#xff09;和 n - 1 條邊的連通無環無向圖&#xff08;其實就是一個線形圖&#xff09;…

什么是索引?為什么要使用B樹作為索引數據結構?

MySQL的事務特性 1.原子性:原子性就是這個事件要么執行完,要么沒執行,不會存在中間狀態,與C中華那個加鎖避免多線程競爭是一個道理; 2.一致性:保持事件的操作對象雙方某數據之和是不變的,就以轉賬為例,A轉給B100塊,那么A的余額多100,B的余額就必須少100; 3.隔離性:隔離就是獨…

pyqt5報錯:qt.qpa.plugin: Could not find the Qt platform plugin “xcb“(已解決)

我在使用pyqt庫的時候報錯&#xff1a; qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in \ "/mnt/private_disk/anaconda3/envs/aot-manip/lib/python3.8/site-packages/PyQt5/Qt5/plugins/platforms" even though it was found. This ap…

AI大模型全攻略:原理 · 部署 · Prompt · 場景應用

?? AI大模型全攻略:原理 部署 Prompt 場景應用 本文從基礎原理到實踐部署,再到 Prompt 工程與典型應用案例,全方位解析 AI 大模型的學習路徑與使用方法,適合開發者、產品經理、技術愛好者等不同背景讀者。 ?? 一、什么是 AI 大模型? AI 大模型(Large Language Mo…

2024年MathorCup數學建模D題量子計算在礦山設備配置及運營中的建模應用解題文檔與程序

2024年第十四屆MathorCup高校數學建模挑戰賽 D題 量子計算在礦山設備配置及運營中的建模應用 原題再現&#xff1a; 隨著智能技術的發展&#xff0c;智慧礦山的概念越來越受到重視。越來越多的設備供應商正在向智慧礦山整體解決方案供應商轉型&#xff0c;是否具備提供整體解…

Flink 流處理框架的核心特性

文章目錄 事件時間支持Flink狀態編程一、狀態的類型1. 托管狀態&#xff08;Managed State&#xff09;2. 原始狀態&#xff08;Raw State&#xff09; 二、狀態的管理和容錯 Flink端到端的一致性1、檢查點機制2、冪等3、事務 水位線窗口操作1、窗口類型2、窗口操作的時間語義 …

交換機(access端口)

任務&#xff1a;對access有更深入的理解 通過網盤分享的文件&#xff1a;交換機&#xff08;access&#xff09;.zip 鏈接: https://pan.baidu.com/s/1cMC6Na_1PLo6zOHazFplQQ?pwd23a5 提取碼: 23a5 SW1 <Huawei>sys [Huawei]dis vlan The total number of vlans …

《鳥哥的Linux私房菜基礎篇》---5 vim 程序編輯器

目錄 一、vim程序編輯器的簡介 二、命令模式快捷鍵&#xff08;默認模式&#xff09; 1、光標移動 2、編輯操作 3、搜索與替換 三、插入模式快捷鍵 四、底行模式快捷鍵&#xff08;按&#xff1a;進入&#xff09; 五、高級技巧 1、分屏操作 2、多文件編輯 3、可視化…

AI大白話(四):自然語言處理——AI是如何理解和生成人類語言的?

??引言: 專欄:《AI大白話》 AI大白話(一):5分鐘了解AI到底是什么? AI大白話(二):機器學習——AI是怎么“學習“的? AI大白話(三):深度學習——AI的‘大腦‘是如何構建的? 大家好!歡迎回到"AI大白話"系列。前面我們聊了AI的基本概念、機器學習的原理…

擴展卡爾曼濾波

1.非線性系統的線性化 標準卡爾曼濾波 適用于線性化系統&#xff0c;擴展卡爾曼濾波 則擴展到了非線性系統&#xff0c;核心原理就是將非線性系統線性化&#xff0c;主要用的的知識點是 泰勒展開&#xff08;我另外一篇文章的鏈接&#xff09;&#xff0c;如下是泰勒展開的公式…

安裝unsloth

我在llamafactory微調LLM&#xff0c;簡單測了一些&#xff08;很不精準&#xff09;&#xff0c;加速方法中unsloth比flash_attention速度快了40%&#xff0c;顯存占用減少15%&#xff1b; 創建虛擬環境&#xff1a;conda create -n env_name python3.10, 然后conda activate…

關于 51 單片機顯示多個數碼管時出現殘影

殘影現象&#xff1a; 出現殘影代碼&#xff1a; #include <REGX52.H> #include <INTRINS.H> void Delayxms(unsigned int x) //11.0592MHz {while(x){unsigned char i, j;_nop_();i 2;j 199; do{while (--j);} while (--i);x--;} } void DisplayDigitalNumb…

STM32學習筆記之常用外設接口(原理篇)

&#x1f4e2;&#xff1a;如果你也對機器人、人工智能感興趣&#xff0c;看來我們志同道合? &#x1f4e2;&#xff1a;不妨瀏覽一下我的博客主頁【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸對你有幫助&#xff0c;可點贊 &#x1f44d;…

InnoDB 引擎核心知識點

InnoDB 引擎核心知識點 6.1 邏輯存儲結構 表空間&#xff08;Tablespace&#xff09;&#xff1a;所有數據邏輯上存儲在一個表空間中&#xff0c;物理上可能由多個文件組成。段&#xff08;Segment&#xff09;&#xff1a;分為數據段&#xff08;B樹葉子節點&#xff09;、索引…