vue3【組件封裝】超級表單 S-form.vue

最終效果

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

代碼實現

components/SUI/S-form.vue

<script lang="ts" setup>
import type { FormInstance } from "element-plus";// 使用索引簽名定義對象類型
type GenericObject = {[key: string]: any;
};const props = defineProps<{Model?: GenericObject;disabled?: boolean;hideHandle?: boolean;saveAPI?: string;saveOK?: () => void;local_save?: (formData: GenericObject) => void;cancel?: () => void;colNum?: number;action?: string;PageConfig?: GenericObject;
}>();const formData = defineModel<GenericObject>({});const formItemConfigList = computed(() => {let result: any = [];if (props.Model) {for (const [key, value] of Object.entries(props.Model)) {let temp_value = JSON.parse(JSON.stringify(value));// 解析 -- 必填if ("require" in temp_value && temp_value.require) {if ("formRules" in temp_value &&temp_value.formRules &&Array.isArray(temp_value.formRules)) {temp_value.formRules.push({required: true,message: "請輸入" + temp_value.label,});} else {temp_value.formRules = [{required: true,message: "請輸入" + temp_value.label,},];}}result.push({prop: key,...(temp_value as object),});}}return result;
});const group_formItemConfigList_Obj = computed(() => {let result: any = {};if (props.PageConfig && props.PageConfig.formGrouped) {let final_formItemConfigList: any[] = [];formItemConfigList.value.forEach((formItemConfig: any) => {if (!(formItemConfig.formHide &&(formItemConfig.formHide === "all" ||(Array.isArray(formItemConfig.formHide) &&formItemConfig.formHide.includes(props.action))))) {final_formItemConfigList.push(formItemConfig);}});result = groupBy(final_formItemConfigList,"group",props.PageConfig.groupName_default);}return result;
});const activeGroups: string[] = Object.keys(group_formItemConfigList_Obj.value);const pageData = reactive<{localFomrData: GenericObject;
}>({localFomrData: formData.value || {},
});const { localFomrData } = toRefs(pageData);const formRef = ref<FormInstance>();const callbackMessage = ref({show: false,valid: true,content: "",
});// 按鈕 -- 保存
const submitForm = (formEl: FormInstance | undefined) => {if (!formEl) return;formEl.validate(async (valid) => {if (valid) {if (props.local_save) {props.local_save(pageData.localFomrData);return;}try {await $fetch(`/api${props.saveAPI}`, {body: pageData.localFomrData,method: "POST",});callbackMessage.value = {show: true,valid: true,content: "操作成功",};if (props.saveOK) {props.saveOK();}} catch (e: any) {callbackMessage.value = {show: true,valid: false,content: e.data.message,};}} else {console.log("提交報錯!");}});
};// 將方法暴露給父組件
defineExpose({submitForm,localFomrData,formRef,
});
</script>
<template><div class="relative mt-10"><el-scrollbar max-height="460px" class="px10"><el-formref="formRef":inline="true":model="localFomrData":disabled="props.disabled"><el-collapsev-if="props.PageConfig && props.PageConfig.formGrouped"v-model="activeGroups"><el-collapse-item:name="group"v-for="(formItemConfigList, group) in group_formItemConfigList_Obj":key="group"><template #title><div class="font-bold text-14px">{{ group }}</div></template><S-formRow:formItemConfigList="formItemConfigList":colNum="props.colNum":action="props.action"v-model="localFomrData":disabled="props.disabled"><templatev-for="formItemConfig in formItemConfigList.filter((item:any) => item.type === 'custom')":key="formItemConfig.prop"#[formItemConfig.prop]><slot :name="formItemConfig.prop" /></template></S-formRow></el-collapse-item></el-collapse><S-formRowv-else:formItemConfigList="formItemConfigList":colNum="props.colNum":action="props.action":disabled="props.disabled"v-model="localFomrData"><templatev-for="formItemConfig in formItemConfigList.filter((item:any) => item.type === 'custom')":key="formItemConfig.prop"#[formItemConfig.prop]><slot :name="formItemConfig.prop" /></template></S-formRow></el-form></el-scrollbar><div class="flex justify-center p4" v-if="!props.disabled && !hideHandle"><el-button @click="props.cancel">取消</el-button><el-button type="primary" @click="submitForm(formRef)">保存</el-button></div><S-msgWin :msg="callbackMessage" /></div>
</template>

components/SUI/S-formRow.vue

<script lang="ts" setup>
import { ref, onMounted } from "vue";
import { defineAsyncComponent } from "vue";const props = defineProps<{formItemConfigList: any;colNum?: number;action?: string;disabled?: boolean;
}>();const localFomrData = defineModel<any>({});// 標記客戶端環境
const isClient = ref(false);// 動態導入組件,禁用SSR
const AvatarCropper = defineAsyncComponent({loader: () => import("~/components/SUI/S-avatar.vue"),suspensible: false, // 關鍵:禁止在服務端渲染該組件,使用 suspensible 替代 ssr
});onMounted(() => {isClient.value = true; // 確保在客戶端掛載后才顯示組件
});
</script>
<template><el-row :sapn="24"><template v-for="formItemConfig in formItemConfigList"><el-colv-if="!(formItemConfig.formHide &&(formItemConfig.formHide === 'all' ||(Array.isArray(formItemConfig.formHide) &&formItemConfig.formHide.includes(props.action))))":span="formItemConfig.span || (props.colNum && 24 / props.colNum) || 12":key="formItemConfig.prop"><el-form-item:label="formItemConfig.label":label-width="160":rules="formItemConfig.formRules":prop="formItemConfig.prop"><el-date-pickerv-if="formItemConfig.type === 'date'"v-model="localFomrData[formItemConfig.prop as string]"type="date"placeholder="選擇日期"v-bind="formItemConfig"/><el-input-numberv-else-if="formItemConfig.type === 'number'"v-model="localFomrData[formItemConfig.prop as string]"v-bind="formItemConfig"controls-position="right"class="w-220px!"><template #suffix><span>{{ formItemConfig.unit }}</span></template></el-input-number><el-switchv-else-if="formItemConfig.type === 'switch'"v-model="localFomrData[formItemConfig.prop as string]"v-bind="formItemConfig"class="w-220px!"/><el-selectv-else-if="formItemConfig.type === 'select'"v-model="localFomrData[formItemConfig.prop as string]"filterableclearable:multiple="formItemConfig.multSelect"class="w-220px!"placeholder=""><el-optionv-for="item in formItemConfig.options || []":key="item.value":label="item.label":value="item.value"/></el-select><el-tree-selectv-else-if="formItemConfig.type === 'treeSelect'"v-model="localFomrData[formItemConfig.prop as string]":data="formItemConfig.treeData":render-after-expand="false"class="w-220px!"filterableclearable:node-key="formItemConfig.key"default-expand-all/><AvatarCropperv-else-if="isClient && formItemConfig.type === 'avatar'":disabled="(formItemConfig.formDisable &&formItemConfig.formDisable.includes(props.action)) ||props.disabled"v-model="localFomrData[formItemConfig.prop as string]"/><template v-else-if="formItemConfig.type === 'custom'"><slot :name="formItemConfig.prop" /></template><el-inputv-elsev-model="localFomrData[formItemConfig.prop as string]"v-bind="formItemConfig"class="w-220px!":type="formItemConfig.type || 'text'":disabled="formItemConfig.formDisable &&formItemConfig.formDisable.includes(props.action)":autosize="formItemConfig.autosize || { minRows: 2, maxRows: 4 }"show-word-limit/></el-form-item></el-col></template></el-row>
</template>

相關組件

頭像 S-avatar.vue

https://blog.csdn.net/weixin_41192489/article/details/149716009

消息彈窗 S-msgWin.vue

https://blog.csdn.net/weixin_41192489/article/details/149717948

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

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

相關文章

Android Studio Memory Monitor內存分析核心指標詳解

Depth、Native Size、Shallow Size、Retained Size 解析 一、指標定義與對比指標定義計算邏輯重要性Shallow Size對象自身實例占用的內存基本類型字段大小 引用指針 內存對齊對象的基礎內存成本Retained Size回收該對象可釋放的總內存量&#xff08;含所有依賴對象&#xff0…

vue中使用wavesurfer.js繪制波形圖和頻譜圖(支持.pcm)

新的實現方式&#xff1a;vue使用Canvas繪制頻譜圖 安裝wavesurfer.js npm install wavesurfer.js第一版&#xff1a; 組件特點&#xff1a; 一次性加載好所有的數據&#xff1b; <template><div class"audio-visualizer-container"><div class&…

go mod教程、go module

什么是go mod go mod 是go語言的包管理工具&#xff0c;類似java 的maven&#xff0c;go mod的出現可以告別goPath&#xff0c;使用go module來管理項目&#xff0c;有了go mod賬號就不需要非得把項目放到gopath/src目錄下了&#xff0c;你可以在磁盤的任何位置新建一個項目 go…

150-SWT-MCNN-BiGRU-Attention分類預測模型等!

150-SWT-MCNN-BiGRU-Attention分類預測模型!基于多尺度卷積神經網絡(MCNN)雙向長短期記憶網絡(BiGRU)注意力機制(Attention)的分類預測模型&#xff0c;matlab代碼&#xff0c;直接運行使用&#xff01;1、模型介紹&#xff1a;針對傳統方法在噪聲環境下診斷精度低的問題&#…

MySQL數據一致性與主從延遲深度解析:從內核機制到生產實踐

在高并發分布式系統中&#xff0c;數據一致性與復制延遲如同硬幣的兩面。本文深入剖析MySQL持久化機制與主從同步原理&#xff0c;并提供可落地的調優方案。一、數據持久化核心機制&#xff1a;雙日志協同 1. Redo Log&#xff1a;崩潰恢復的生命線刷新策略&#xff08;innodb_…

【I】題目解析

目錄 單選題 多選題 判斷題 單選題 1.reg[7:0]A; A2hFF;則A&#xff08;&#xff09; A.8b11111110 B.8b03 C.8b00000011 D.8b11111111 C 2hFF實際上等效于2位二進制2b11&#xff0c;賦值給8位寄存器A之后&#xff0c;低位賦值&#xff0c;高位補0 A8b00000011 AMD FPG…

《Foundation 面板:設計、功能與最佳實踐解析》

《Foundation 面板:設計、功能與最佳實踐解析》 引言 在當今數字化時代,用戶界面(UI)設計的重要性不言而喻。其中,Foundation 面板作為一種流行的前端框架,因其靈活性和高效性而被眾多開發者所青睞。本文將深入解析 Foundation 面板的設計理念、功能特點以及最佳實踐,…

React服務端渲染 Next 使用詳解

1. Next.js 概述 Next.js 是一個基于 React 的開源框架&#xff0c;專注于服務器端渲染&#xff08;SSR&#xff09;和靜態站點生成&#xff08;SSG&#xff09;&#xff0c;提供開箱即用的 SSR 功能&#xff0c;簡化 React 應用的開發與部署。 2. Next.js 的核心特性 SSR 支…

Deforum Stable Diffusion,輕松實現AI視頻生成自由!

摘要&#xff1a; 你是否曾被那些充滿想象力、畫面流暢的AI視頻所震撼&#xff1f;你是否也想親手創造出屬于自己的AI動畫&#xff1f;本文將為你提供一份“保姆級”的詳盡教程&#xff0c;從環境配置到參數調整&#xff0c;一步步帶你復現強大的Deforum Stable Diffusion模型&…

不同環境安裝配置redis

不同環境安裝配置redis windows 環境安裝redis redis所有下載地址 windows版本redis下載&#xff08;GitHub&#xff09;&#xff1a; https://github.com/tporadowski/redis/releases &#xff08;推薦使用&#xff09;https://github.com/MicrosoftArchive/redis/releases]官…

匯川Easy系列PLC算法系列(回溯法ST語言實現)

Easy系列PLC 3次多項式軌跡插補算法 Easy系列PLC 3次多項式軌跡插補算法(完整ST代碼)_plc連續插補算法-CSDN博客文章瀏覽閱讀122次。INbExecuteBOOLOFFOFF不保持1INrStartPosREAL0.0000000.000000不保持起始位置unit2INrEndPosREAL0.0000000.000000不保持結束位置unit3INrStar…

Linux C:構造數據類型

目錄 一、結構體&#xff08;struct&#xff09; 1.1類型定義 1.2 結構體變量定義 1.3 結構體元素初始化 1.4 結構體成員訪問 1.5 結構體的存儲&#xff08;內存對齊&#xff09; 1.6 結構體傳參 本文主要記錄了C語言中構造數據類型部分的內容&#xff0c;今天暫時只寫了…

Python:self

在Python面向對象編程中&#xff0c;self是一個指向類實例自身的引用參數&#xff1a;?1. 本質與作用??身份標識?&#xff1a;self是類實例化后對象的"身份證"&#xff0c;代表當前實例本身&#xff0c;用于區分不同實例的屬性和方法??自動傳遞?&#xff1a;調…

【SpringMVC】SpringMVC的概念、創建及相關配置

什么是SpringMVC 概述 中文翻譯版&#xff1a;Servlet 棧的 Web 應用 Spring MVC是Spring Framework的一部分&#xff0c;是基于Java實現MVC的輕量級Web框架。 查看官方文檔&#xff1a;https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/web.h…

淺談存儲過程

問題引入 面試的時候有時候會問到知不知道存儲過程&#xff0c;用沒用過&#xff1f; 是什么 存儲過程&#xff08;Stored Procedure&#xff09;是在大型數據庫系統中&#xff0c;一組為了完成特定功能的SQL 語句集&#xff0c;它存儲在數據庫中&#xff0c;一次編譯后永久…

maven optional 功能詳解

前言 最近參與了一個項目,使用maven管理依賴.項目拆分了很多模塊.然后交個多個團隊各自開發.最后在一個項目骨架中,把各自的模塊引入進來,一起啟動. 后來隨著項目的深入.引入的jar包變多.發現 jar包太多,編譯太慢, 打包之后的war包非常大.這種情況就可以使用optional來優化什么…

Python基礎--Day04--流程控制語句

流程控制語句是計算機編程中用于控制程序執行流程的語句。它們允許根據條件來控制代碼的執行順序和邏輯&#xff0c;從而使程序能夠根據不同的情況做出不同的決策。流程控制實現了更復雜和靈活的編程邏輯。 順序語句 順序語句是按照編寫的順序依次執行程序中的代碼。代碼會按照…

【同濟大學】雙速率自動駕駛架構LeAD:端到端+LLM,CARLA實測93%路線完成率,性能SOTA!

近年來&#xff0c;隨著端到端的技術快速發展將自動駕駛帶到了一個新高度&#xff0c;并且取得了非常亮眼的成績。由于感知限制和極端長尾場景下訓練數據覆蓋不足&#xff0c;模型在高密度復雜交通場景下和不規則交通情況下的處理能力不足&#xff0c;導致在開放道路上大規模部…

github與git新手教程(快速訪問github)

0 序言 作為一個開發者&#xff0c;你必須知道github和git是什么&#xff0c;怎么使用。 github是一個存儲代碼等資源的遠程倉庫&#xff0c;一個大型項目往往需要很多人共同協作開發&#xff0c;而大家如何協同開發的進度與分工等要求需要有一個統一開放保存代碼的平臺。git…

Windows環境下安裝Python和PyCharm

可以只安裝PyCharm嗎&#xff1f;不可以&#xff01;&#xff01;&#xff01; 開發Python應用程序需要同時安裝Python和PyCharm。Python是一種編程語言&#xff0c;PyCharm是一個專門為Python開發設計的集成開發環境&#xff0c;提供豐富的功能以簡化編碼過程。 一、前期準備…