基于element-plus和IndexedDB數據庫的基礎表單

本文介紹了基于Vue 3和Element Plus的表單項目配置頁面實現。頁面包含搜索欄、操作按鈕、數據表格和分頁組件,使用IndexedDB進行本地數據存儲。主要功能包括:1) 通過模糊查詢搜索項目;2) 分頁顯示項目數據;3) 添加/編輯/刪除項目操作。核心代碼展示了如何通過IndexedDB API實現數據查詢、分頁和模糊搜索,并采用響應式設計計算表格高度。技術棧包含Vue 3組合式API、Element Plus組件庫和IndexedDB數據庫操作。
在這里插入圖片描述
依賴安裝:

npm i idb
npm install element-plus --save
<template><div class="config-page"><!-- 面包屑 --><div class="breadcrumb-header">表單項目配置</div><!-- 搜索欄 --><div ref="searchRef" class="search-container"><el-form :model="searchForm" label-width="auto" class="search-form"><el-form-item label="項目名稱"><el-input v-model="searchForm.projectName" placeholder="請輸入項目名稱" /></el-form-item><el-form-item class="search-actions"><el-button type="primary" @click="handleSearch">查 詢</el-button><el-button @click="handleReset">重 置</el-button></el-form-item></el-form></div><!-- 操作欄 --><div class="operation-btns"><el-button @click="handleAdd">添 加</el-button></div><!-- table表格 --><div class="main" :style="{ height: tableHeight }"><el-table :data="tableData" stripe v-loading="loading" style="width: 100%;height: 100%"><el-table-column prop="projectName" label="項目名稱" /><el-table-column label="操作" width="120" fixed="right"><template #default="scope"><el-button link type="primary" @click="handleEdit(scope.row)">編輯</el-button><el-button link type="danger" @click="handleDelete(scope.row)">刪除</el-button></template></el-table-column></el-table></div><!-- 分頁 --><div class="footer"><el-pagination v-model:current-page="searchForm.currentPage" v-model:page-size="searchForm.pageSize":page-sizes="[10, 20, 50, 100, 200]" :total="total" layout="total, sizes, prev, pager, next, jumper"@current-change="handleCurrentChange" @size-change="handleSizeChange" /></div><el-dialog v-model="dialogVisible" :title="dialogTitle" width="500"><el-form ref="ruleFormRef" :model="form" label-width="auto" :rules="rules"><el-form-item label="項目名稱" prop="projectName"><el-input v-model="form.projectName" autocomplete="off" /></el-form-item></el-form><template #footer><div class="dialog-footer"><el-button @click="dialogVisible = false">取 消</el-button><el-button type="primary" @click="handleConfirm">確 定</el-button></div></template></el-dialog></div>
</template><script setup>
import { ref, useTemplateRef, onMounted, onBeforeUnmount } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { debounce } from 'lodash-es'
import { openDB } from 'idb'// 表格容器高度
const tableHeight = ref('auto')// 計算表格高度
const calculateTableHeight = () => {if (!searchRef.value) return// 面包屑高度const headerHeight = 41// 搜索欄高度const searchHeight = searchRef.value.offsetHeight// 操作按鈕欄高度const operationHeight = 56// 分頁高度const footerHeight = 56tableHeight.value = `calc(100% - ${headerHeight + searchHeight + operationHeight + footerHeight}px)`
}// 防抖的resize處理
const debouncedResize = debounce(() => {calculateTableHeight()
}, 200)// 查詢條件
const searchForm = ref({projectName: '',currentPage: 1,pageSize: 10
})const loading = ref(false)
const tableData = ref([])
const total = ref(0)// 獲取表格數據方法
const queryProjects = async (conditions = {}, pagination = {}) => {try {if (!db) await initDB()const { currentPage = 1, pageSize = 10 } = paginationconst { projectName = '' } = conditions// 開啟一個只讀事務const tx = db.transaction(STORE_NAME, 'readonly')// 并獲取指定對象存儲的引用const store = tx.objectStore(STORE_NAME)// 獲取總數和分頁查詢數據const skip = (currentPage - 1) * pageSizelet data = []let totalCount = 0if (projectName) {/*** 在IndexedDB數據庫中打開一個游標,用于遍歷或操作存儲對象中的數據。* 支持查詢、更新或刪除數據等操作*/let cursor = await store.openCursor()let matchedCount = 0while (cursor && data.length < pageSize) {const record = cursor.value// 模糊匹配項目名(不區分大小寫)if (record.projectName && record.projectName.toLowerCase().includes(projectName.toLowerCase())) {if (totalCount >= skip) {data.push(record)matchedCount++}totalCount++ // 統計總匹配數}cursor = await cursor.continue()}// 繼續遍歷剩余記錄以計算準確的總數while (cursor) {const record = cursor.valueif (record.projectName && record.projectName.toLowerCase().includes(projectName.toLowerCase())) {totalCount++}cursor = await cursor.continue()}} else {// 無項目名條件時,獲取總數并進行分頁查詢totalCount = await store.count()/*** 在IndexedDB數據庫中打開一個游標,用于遍歷或操作存儲對象中的數據。* 支持查詢、更新或刪除數據等操作*/let cursor = await store.openCursor()let count = 0while (cursor && data.length < pageSize) {if (count >= skip) {data.push(cursor.value)}count++cursor = await cursor.continue()}}return { data, totalCount }} catch (error) {console.error('查詢失敗:', error)throw error}
}// 獲取表格數據
const fetchTableData = async () => {try {loading.value = trueconst { data, totalCount } = await queryProjects({ projectName: searchForm.value.projectName },{currentPage: Math.max(1, searchForm.value.currentPage),pageSize: searchForm.value.pageSize})tableData.value = datatotal.value = totalCount} catch (error) {console.error('獲取數據失敗:', error)ElMessage.error('獲取數據失敗')} finally {loading.value = false}
}const searchRef = useTemplateRef('searchRef')
// 搜索
const handleSearch = () => {searchForm.value.currentPage = 1fetchTableData()
}// 重置
const handleReset = () => {searchForm.value = {projectName: '',currentPage: 1,pageSize: 10}fetchTableData()
}// current-page 改變時觸發
const handleCurrentChange = (val) => {searchForm.value.currentPage = valfetchTableData()
}// 分頁大小變化
const handleSizeChange = (size) => {searchForm.value.pageSize = sizefetchTableData()
}const dialogVisible = ref(false)
const dialogTitle = ref('添加')const ruleFormRef = useTemplateRef('ruleFormRef')
const form = ref({projectName: '',
})
const rules = {projectName: [{ required: true, message: '請輸入項目名稱', trigger: 'blur' }]
}const isAdd = ref(true)// 添加
const handleAdd = () => {form.value = {projectName: '',}isAdd.value = truedialogTitle.value = '添加'dialogVisible.value = true
}// 編輯
const handleEdit = (val) => {form.value = { ...val }isAdd.value = falsedialogTitle.value = '編輯'dialogVisible.value = true
}// 確定按鈕點擊事件
const handleConfirm = () => {ruleFormRef.value.validate(async (valid, fields) => {if (valid) {try {if (isAdd.value) {// 添加數據await db.add(STORE_NAME, {...form.value})ElMessage.success('添加成功')} else {// 編輯數據await db.put(STORE_NAME, { ...form.value })ElMessage.success('編輯成功')}dialogVisible.value = false// 重新獲取數據fetchTableData()} catch (error) {console.error('添加數據失敗:', error)if (error.name === 'ConstraintError') {ElMessage.error('該項目已存在')} else {ElMessage.error('添加失敗')}}} else {console.log('error submit!', fields)}})
}// 刪除
const handleDelete = ({ id }) => {console.log(id)ElMessageBox.confirm('是否確定刪除?',{confirmButtonText: '確定',cancelButtonText: '取消',type: 'warning',}).then(async () => {try {await db.delete(STORE_NAME, id)// 重新獲取數據fetchTableData()ElMessage({type: 'success',message: '刪除成功',})} catch (error) {ElMessage.error('刪除失敗')console.error('刪除失敗:', error)}}).catch(() => {ElMessage({type: 'info',message: '已取消',})})
}// 數據庫名稱
const DB_NAME = 'LowCodeAppDatabase'
// 對象存儲(數據庫表名稱)
const STORE_NAME = 'projects'
let db = null
// 初始化數據庫
const initDB = async () => {if (db) return dbtry {/*** DB_NAME:數據庫名稱* 1:數據庫版本號* 第三個參數是升級回調函數,在數據庫首次創建或版本升級時執行*/db = await openDB(DB_NAME, 1, {upgrade(db) {// 創建一個名為STORE_NAME的對象存儲, 設置id為主鍵,且自動遞增const store = db.createObjectStore(STORE_NAME, { keyPath: 'id', autoIncrement: true })// 在projectName字段上創建唯一索引, 以便查詢store.createIndex('projectName', 'projectName', { unique: true })}})console.log('數據庫初始化成功')return db} catch (err) {ElMessage.error('數據庫初始化失敗,請刷新頁面重試')console.error('數據庫初始化失敗:', err)}
}onMounted(async () => {try {// 初始化數據庫await initDB()// 初始化數據await fetchTableData()// 計算表格高度calculateTableHeight()window.addEventListener('resize', debouncedResize)} catch (error) {console.error('初始化失敗:', error)}
})onBeforeUnmount(() => {window.removeEventListener('resize', debouncedResize)
})</script><style scoped>
.config-page {width: 100%;height: 100%;display: flex;flex-direction: column;overflow: hidden;
}.breadcrumb-header {width: 100%;height: 41px;display: flex;align-items: center;border-bottom: 1px solid #e0e0e0;padding: 0 10px;color: #606266;
}.search-container {width: 100%;height: auto;border-bottom: 1px solid #e0e0e0;display: flex;flex-wrap: wrap;align-items: center;
}.main {padding: 0 10px 10px 10px;
}.operation-btns {width: 100%;height: 56px;display: flex;align-items: center;padding: 0 10px;
}.footer {width: 100%;height: 56px;display: flex;justify-content: flex-end;align-items: center;padding: 0 10px;border-top: 1px solid #e0e0e0;
}.search-form {width: 100%;display: flex;flex-wrap: wrap;padding-top: 10px;
}.el-form-item {margin: 0 10px 10px 10px;
}.search-actions {margin-left: auto;
}:deep(.el-table--fit .el-table__inner-wrapper:before) {display: none;
}
</style>

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

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

相關文章

paimon實時數據湖教程-主鍵表更新機制

在上一章&#xff0c;我們學習了 Paimon 如何保證每一次寫入的原子性和一致性。但數據倉庫的核心需求不僅是寫入&#xff0c;更重要的是更新。想象一個場景&#xff1a;我們需要實時更新用戶的最新信息&#xff0c;或者實時累加計算用戶的消費總額。傳統的 Hive 數據湖對此無能…

第十六屆藍橋杯青少組C++省賽[2025.8.9]第二部分編程題(4、矩陣圈層交錯旋轉)

參考程序&#xff1a;#include <bits/stdc.h> using namespace std;const int MAXN 105; int a[MAXN][MAXN];int main() {int n;if (!(cin >> n)) return 0;for (int i 0; i < n; i)for (int j 0; j < n; j)cin >> a[i][j];int layers n / 2; // 每…

【FastGTP?】[01] 使用 FastGPT 搭建簡易 AI 應用

簡易應用&#xff1a;英語單詞解釋 例句 1. 前言 FastGPT 是一個低代碼 AI 應用構建平臺&#xff0c;可以通過簡單配置快速創建自己的 AI 應用。 本文將帶你用 FastGPT 搭建一個 英語單詞解釋 例句 的 AI 工具&#xff0c;輸入英文單詞后&#xff0c;輸出&#xff1a; 單詞…

【Mysql語句練習】

MysqlMysql語句練習一、建庫建表二、插入數據三、查詢Mysql語句練習 一、建庫建表 1、創建數據庫mydb11_stu&#xff0c;并使用數據庫 # 創建數據庫mydb11_stu mysql> create database mydb11_stu; Query OK, 1 row affected (0.00 sec) # 使用數據庫 mysql> use mydb1…

用Python Scrapy征服網絡爬蟲(反爬技術深入剖析)

目錄 第1章:Scrapy是個啥?為什么它是你爬蟲路上的最佳拍檔? 1.1 Scrapy的核心亮點 1.2 啥時候用Scrapy? 1.3 安裝Scrapy 第2章:動手寫你的第一個Scrapy爬蟲 2.1 創建Scrapy項目 2.2 定義數據結構(Items) 2.3 編寫爬蟲邏輯 2.4 運行爬蟲 2.5 小技巧:調試爬蟲 …

解決Electron透明窗口點擊不影響其他應用

遇到的問題&#xff1a;在electron透明窗口點擊&#xff0c;影響窗口下的應用接受不到點擊事件解決方案&#xff1a;CSSIgnoreMouseEvents實現原理&#xff1a;主進程默認設置禁用目標窗口鼠標事件&#xff08;禁用之后能檢測到mousemove&#xff09;&#xff0c;UI進程檢測頁面…

C# 泛型(Generics)詳解

泛型是 C# 2.0 引入的核心特性&#xff0c;它允許在定義類、接口、方法、委托等時使用未指定的類型參數&#xff0c;在使用時再指定具體類型。這種機制可以顯著提高代碼的復用性、類型安全性和性能。一、泛型的核心概念類型參數化泛型允許將類型作為 "參數" 傳遞給類…

Spring中存在兩個相同的Bean是否會報錯?

第一種情況&#xff1a;使用XML的方式設置Bean&#xff0c;這種情況在Spring啟動時就會報錯&#xff0c;因為ID在Spring中是Bean的唯一標識&#xff0c;Spring容器在啟動時會校驗唯一性&#xff0c;一旦發現重復就會報錯。但是如果是在兩個不同的XML文件中定義兩個相同的Bean&a…

【新手入門】Android基礎知識(一):系統架構

目 錄 Android 系統架構圖 1. 應用 2. JAVA API 框架 3. 原生 C/C 庫 4. Android 運行時&#xff08;Android Runtime&#xff09; 5. 硬件抽象層 (HAL) 6. Linux 內核 參考資料 Android 系統架構圖 Android底層內核空間以Linux Kernel作為基石&#xff0c;上層用戶空…

晶振電路的負載電容、電阻參數設計

系列文章目錄 文章目錄系列文章目錄前言一、晶振主要參數二、有源與無源區別三、無源晶振四、有源晶振總結前言 在硬件電路的設計中&#xff0c;晶振電路是必不可少的&#xff0c;它充當了整個電路心臟的作用。在這個晶振電路的設計中負載電容、電阻參數的選型是很重要的&…

電腦上練打字用什么軟件最好:10款打字軟件評測

現在孩子們在電腦上練打字&#xff0c;軟件一搜一大把&#xff0c;可好多家長和老師都犯愁&#xff1a;到底哪個管用&#xff1f;我帶200多個小學生練過字&#xff0c;前前后后試了十款軟件&#xff0c;今天就掏心窩子說說——有的看著花哨其實沒用&#xff0c;有的專業是專業但…

第五天~提取Arxml的模板信息

?? ARXML模板信息提取:解鎖汽車軟件的樂高魔法 在汽車電子的世界里,AUTOSAR(汽車開放系統架構)如同無形的神經系統,而ARXML文件正是承載這套神經系統藍圖的數字載體。當工程師們需要批量創建或修改ECU(電子控制單元)配置時,模板信息提取便成為了一項至關重要的核心技…

react+antd+vite自動引入組件、圖標等

前言&#xff1a;react在使用antd的時候&#xff0c;也是需要每個組件都在界面上按需引入的&#xff0c;那能不能自動生成&#xff0c;按需使用呢&#xff1f;我們這里說一說這個。安裝插件&#xff0c;組件按需引入unplugin-antd-resolverunplugin-auto-importnpm install unp…

深度學習與遙感入門(六)|輕量化 MobileNetV2 高光譜分類

系列回顧&#xff1a; &#xff08;一&#xff09;CNN 基礎&#xff1a;高光譜圖像分類可視化全流程 &#xff08;二&#xff09;HybridNet&#xff08;CNNTransformer&#xff09;&#xff1a;提升全局感受野 &#xff08;三&#xff09;GCN 入門實戰&#xff1a;基于光譜 KNN…

第4節 神經網絡從公式簡化到卷積神經網絡(CNN)的進化之路

?? 深度學習的"玄學進化史" 從CNN用卷積層池化層處理圖片,循環網絡RNN如何利用上下文處理序列數據,到注意力機制讓Transformer橫空出世,現在的大語言模型已經能寫能畫能決策!每個新技巧都讓人驚呼"還能這么玩",難怪說深度學習像玄學——但這玄學,…

最新去水印小程序系統 前端+后端全套源碼 多套模版 免授權(源碼下載)

最新去水印小程序系統 前端后端全套源碼 多套模版 免授權 源碼下載&#xff1a;https://download.csdn.net/download/m0_66047725/91669468 更多資源下載&#xff1a;關注我

TCP Socket 編程實戰:實現簡易英譯漢服務

前言&#xff1a;TCP&#xff08;傳輸控制協議&#xff09;是一種面向連接、可靠的流式傳輸協議&#xff0c;與 UDP 的無連接特性不同&#xff0c;它通過三次握手建立連接、四次揮手斷開連接&#xff0c;提供數據確認、重傳機制&#xff0c;保證數據有序且完整傳輸。本文將基于…

CF566C Logistical Questions Solution

Description 給定一棵 nnn 個點的樹 TTT&#xff0c;點有點權 aia_iai?&#xff0c;邊有邊權 www. 定義 dist?(u,v)\operatorname{dist}(u,v)dist(u,v) 為 u→vu\to vu→v 的簡單路徑上的邊權和. 找到一個節點 uuu&#xff0c;使得 W∑i1ndist?(u,i)32aiW\sum\limits_{i1}^n…

聊天室全棧開發-保姆級教程(Node.js+Websocket+Redis+HTML+CSS)

前言 最近在學習websocket全雙工通信&#xff0c;想要做一個聯機小游戲&#xff0c;做游戲之前先做一個聊天室練練手。 跟著本篇博客&#xff0c;可以從0搭建一個屬于你自己的聊天室。 準備階段 什么人適合學習本篇文章&#xff1f; 答&#xff1a;前端開發者&#xff0c;有一…

后臺管理系統-2-vue3之路由配置和Main組件的初步搭建布局

文章目錄1 路由搭建1.1 路由創建(router/index.js)1.2 路由組件(views/Main.vue)1.3 路由引入并注冊(main.js)1.4 路由渲染(App.vue)2 element-plus的應用2.1 完整引入并注冊(main.js)2.2 示例應用(App.vue)3 ElementPlusIconsVue的應用3.1 圖標引入并注冊(main.js)3.2 示例應用…