文章目錄
-
- 概要
- 表單組件封裝
- 彈窗組件調用表單組件
- 頁面列表調用查詢表單
?
表單組件封裝
?組件代碼
<template><el-formref="ruleFormRef"class="elForm":inline="true":rules="rules":model="TableList"label-width="150"><template v-if="fromlist.isInput">//父組件傳遞的數據對象<template v-for="(item, key, index) in fromlist.listData"><!-- 輸入框 --><el-form-item:prop="key":label="item.title"v-if="item.type == 'input' && item.show":key="index"><el-input:disabled="item.disabled"v-model="TableList[key]":clearable="item.clearable":placeholder="'請輸入' + item.title":suffix-icon="item.icon":style="{ width: fromlist.with }"/></el-form-item><!-- 密碼框 --><el-form-item:prop="key":label="item.title"v-if="item.type == 'password' && item.show":key="index"><el-inputv-model="TableList[key]":clearable="item.clearable":placeholder="'請輸入' + item.title":suffix-icon="item.icon":style="{ width: fromlist.with }"/></el-form-item><!-- 下拉框 --><el-form-item:prop="key":key="item.show":label="item.title"v-if="item.type == 'select' && item.show"><el-selectcollapse-tagsl-selectv-model="TableList[key]":max-collapse-tags="1":filterable="item.filterable":multiple="item.multiple":clearable="item.clearable":placeholder="'請輸入' + item.title":style="{ width: fromlist.with }"><span v-if="item.children.constructor === Object"><el-optionv-for="(value, key) in item.children":key="key":label="value":value="key"></el-option></span><span v-if="item.children.constructor === Array"><el-optionv-for="(item, key) in item.children":key="key":label="item.label"v-html="item.label2 ? item.label2 : item.label":value="item.value"></el-option></span></el-select></el-form-item><!-- 開始時間 --><el-form-item:prop="key":key="item.show":label="item.title"v-if="item.type == 'time' && item.show"><el-date-pickerv-model="TableList[key]"type="datetimerange"start-placeholder="Date"end-placeholder="End Date"date-format="YYYY/MM/DD"time-format="hh:mm:ss"value-format="YYYY-MM-DD HH:mm:ss":style="{ width: fromlist.with }"/></el-form-item><!-- 年月日時分秒 --><el-form-itemclass="daterange_dom":prop="key":key="item.show":label="item.title"v-if="item.type == 'picker' && item.show"><el-date-pickerv-model="TableList[key]"type="daterange"start-placeholder="開始時間"end-placeholder="結束時間"value-format="YYYY-MM-DD":default-value="[new Date(2010, 9, 1), new Date(2010, 10, 1)]":style="{ width: fromlist.with }"/></el-form-item><!-- 單選框 --><el-form-item:prop="key":label="item.title"v-if="item.type == 'radio' && item.show":key="index"><el-radio-groupv-model="TableList[key]"v-for="(res, index) in item.children"><el-radio-button:label="item.children[index].value">{{item.children[index].label}}</el-radio-button></el-radio-group></el-form-item><!-- 單選 --><el-form-item:prop="key":label="item.title"v-if="item.type == 'radio1' && item.show"><el-radio-groupv-model="TableList[key]"v-for="(val, index) in item.children"><el-radio :label="item.children[index].value" >{{item.children[index].label}}</el-radio></el-radio-group></el-form-item><!-- 文本框 --><el-form-item:prop="key":label="item.title"v-if="item.type == 'textarea' && item.show":key="index"><el-inputtype="textarea"v-model="TableList[key]":clearable="item.clearable":placeholder="'請輸入' + item.title":suffix-icon="item.icon":style="{ width: fromlist.with }"/></el-form-item></template><!-- 操作按鈕 --><el-form-itemid="form_But"style="display: block"v-if="fromlist.index !== '2'"><div class="form_But_div"><el-button type="primary" @click="onSubmit(ruleFormRef)">查詢</el-button><Buttonplain:title="'重置'"@click="ResetForm(ruleFormRef)":pattern="'centre'"/><el-linkv-if="isshow"class="Rigth_ellink"@click="handelClickShow(show, fromlist)":underline="false"><span><span v-show="!show">展開</span><span v-show="show">合并</span></span><span class="show_icon"><Icons:theme="'outline'":size="24":is="!show ? 'expand-down-one' : 'fold-up-one'"/></span></el-link></div></el-form-item></template></el-form>
</template><script setup lang="ts">
import ElementResizeDetectorMaker from "element-resize-detector";
import {reactive,defineProps,ref,getCurrentInstance,onMounted,defineExpose,
} from "vue";
import { User } from "@element-plus/icons-vue";
import { Icons } from "@/components";
import { Button } from "@/components";
const { proxy } = getCurrentInstance();
//接收父級彈窗組件傳遞過來的數據
const props = defineProps(["fromlist", "Radio", "submitValue"]);const data = ref({});
//(列表頁面),顯示查詢參數是否顯示 true為顯示 show將動態賦值給fromlist數據對象中傳遞過來的查詢參數,根據上面template的判斷,是否顯示
let show = ref(false);
//(列表頁面,顯示查詢參數的數量(比如輸入框等等)
let DomNumber = ref(0);
//(彈窗表單) 接收彈窗組件傳遞過來的頁面查詢的數據對象
let fromlist = ref(props.fromlist);
//表單組件ref
const ruleFormRef = ref(null);//(彈窗表單)定義表單組件的校驗,彈窗表單中使用
const rules = reactive(getRulesList(fromlist.value.listData))
//(彈窗表單)定義綁定在表單中的數據接收對象, rules 和 TableList中對應上才能校驗。
let TableList = reactive(TableListParameter(fromlist.value.listData))//(彈窗表單)根據彈窗組件傳遞過來的數據類型,重新定義表單接收輸入數據的對象。
function TableListParameter(params:object) {let list = {}for(const key in params){list[key] = params[key].value}return list
} //(彈窗表單)根據彈窗組件傳遞過來的數據類型,動態定義表單校驗規則。
function getRulesList(params:type) {let list = {}for (const key in params) {if(params[key].required){let data = []//判斷傳遞過來的參數類型是輸入框還是下拉框switch (params[key].type) {case 'input':data = [{required: true, message: `請輸入${params[key].title}`, trigger: 'blur' }]break;case 'select':data = [{required: true, message: `請選擇${params[key].title}`, trigger: 'change' }]break;}list[key] = data}}return list
}//(列表頁面)emit 父子組件通信,UserSearch是父組件傳定義接收子組件傳遞接收數據的方法
const emit = defineEmits([`UserSearch`]);
//(列表頁面判斷是否顯示表單組件中的 (查詢) (重置) 按鈕,彈窗表單組件是不現實的
let isshow = ref(false);
onMounted(() => {//(列表頁面 判斷是否傳遞過來的是表單查詢,如果是就調用顯示查詢參數方法 type:tabulation 表示列表頁面if (props.fromlist.listData &&props.fromlist.isInput &&props.fromlist.type == 'tabulation' ) {OnToPage();} else {//(彈窗表單)proxy.$PublicAPI.UpdataFormList(props.fromlist.listData);}});
//(彈窗表單) 將子組件 變量、方法 拋出,父組件可以直接電泳
defineExpose({TableList,ResetForm,FormresetFields
});//(列表頁面)列表查詢控制查詢參數的顯示隱藏,如果查詢參數超過2行內容,多的隱藏,此方法點擊展開可展示全部查詢參數,折疊就只顯示兩行的查詢參數
function handelClickShow(type: boolean) {show.value = !show.value;UpPorpsData(fromlist, show.value);
}
//(列表頁面) 進入頁面,定義請求參數顯示兩行方法
function OnToPage() {let erd = ElementResizeDetectorMaker();let jianshiDom = document.querySelector(".elForm");let butDom =(document.querySelector("#form_But").offsetHeight + 8) * 5 + 8 + "px";document.getElementsByTagName("body")[0].style.setProperty("--input_Width", butDom);erd.listenTo(jianshiDom, (ele) => {let inputWidth = jianshiDom?.children[0].offsetWidth;let OneContentWidth = Math.floor(jianshiDom.offsetWidth / inputWidth);DomNumber.value = OneContentWidth * 2;UpPorpsData(fromlist, show.value);});
}
//(列表頁面)根據上面的方法,多出兩行的查詢參數對象定義show為false使元素隱藏起來
function UpPorpsData(data: type, type: boolean) {let forKey = Object.keys(data.value.listData);if (type) {forKey.map((itme, index, key) => {data.value.listData[itme].show = true;});} else {forKey.map((itme, index) => {let kk = DomNumber.value;if (kk < Object.keys(fromlist.value.listData).length) {isshow.value = true;if (kk > 0) {if (index < kk) {data.value.listData[itme].show = true;} else {data.value.listData[itme].show = false;}}} else {isshow.value = false;data.value.listData[itme].show = true;}});}return data.value;
}//(列表頁面) 列表中點擊查詢,傳遞給父組件,proxy.$store.rou_Name 獲取到的當前路由如:/user 將改變為:User ,此行就是 UserSearch ,這是在user頁面中引用了表單組件 @UserSearch 定義接收子組件傳遞回來的方法。TableList:提交給父組件的數據,submit:點擊的按鈕類型(查詢按鈕) resetting :點擊的按鈕類型(重置按鈕)
async function onSubmit(formEl: FormInstance | undefined) {emit(`${proxy.$store.rou_Name}Search`, TableList, "submit");
}function FormresetFields() {ruleFormRef.value.resetFields();}//重置
function ResetForm(formEl: FormInstance | undefined) {if (!ruleFormRef) return;//清空輸入的內容ruleFormRef.value.resetFields();emit(`${proxy.$store.rou_Name}Search`, TableList, "resetting");
}
</script><style >
:root {--input_Width: 500px;
}
</style><style scoped lang="less" >
::v-deep.elForm {padding: 8px 16px 0px 16px;background: white;position: relative;max-height: var(--input_Width) !important;overflow: hidden;overflow-y: auto;
}::v-deep .el-input,
.el-select {height: 32px !important;
}::v-deep .el-input .el-input__wrapper {height: 32px !important;
}::v-deep .el-input__wrapper:hover,
::v-deep .el-select__wrapper:hover {box-shadow: 0 0 0 1px var(--theme_background) inset !important;
}::v-deep.el-button {min-width: 88px;height: 32px;
}::v-deep.el-form--inline .el-form-item {margin-right: 14px !important;
}::v-deep.Button {margin-left: 29px !important;
}.form_But {height: 32px;position: absolute;right: -27px;
}
::v-deep .el-form-item__content {display: flex;justify-content: end;// width: 248px;
}
.Rigth_ellink {min-width: 88px;display: flex;
}
.show_icon {display: flex;justify-content: center;align-items: center;margin-left: 3px;
}
::v-deep(.el-form-item) {margin-bottom: 8px;
}#form_But {width: 398px;
}
.form_But_div {display: flex;align-items: center;
}
::v-deep .el-form-item {margin-bottom: 8px;
}::v-deep.el-button--primary {background: var(--secondary_but_Backgroun) !important;color: var(--theme_background) !important;border: 1px solid var(--secondary_but_border);
}::v-deep.el-button--primary:hover {border: 1px solid var(--theme_background);
}
::v-deep.el-button--primary:active {border: 1px solid var(--secondary_but_Click);
}
::v-deep .el-range__icon {float: none !important;position: absolute !important;right: 10px !important;
}::v-deep(.el-input__prefix) {display: none;
}
::v-deep(.el-radio-button__inner) {border-radius: 20px !important;
}
</style>
彈窗組件調用
<template><div><el-dialog:title="props.FormList.title"v-model="drawer"width="40%":before-close="handleClose"><div class="dialog"><!--props.FormList 父組件傳遞的表單渲染組件數據 --><FromData:fromlist="props.FormList":Radio="Radio"ref="formDataRef"></FromData></div><template #footer><span class="dialog-footer"><el-button @click="handleClose">取 消</el-button><el-button type="primary" @click="submit()">確 定</el-button></span></template></el-dialog></div>
</template><script setup lang="ts">
import { ref, watch, getCurrentInstance, defineProps, onMounted,defineExpose } from "vue";import { FromData } from "@/components";
const { proxy } = getCurrentInstance();
import bus from "@/mitt";
import router from "/src/router/index";
//接收調用彈窗組件傳遞過來的參數
const props = defineProps(["FormList"]);
//點擊彈窗可傳給調用彈窗頁面的接受方法
const emit = defineEmits(['UserPopUpWindow','ConfigPopUpWindow'])
// 彈窗默認打開,調用組件的頁面中控制彈窗組件的顯示隱藏即可
const drawer = ref(true);
const title = ref("");
const fromlist = ref({});
const submitValue = ref("");
// 創建一個 ref 來引用子組件
const formDataRef = ref(null);
const Radio = ref({});
//彈窗確認按鈕
const submit = () => {//formDataRef 表單組件ref ,因為表單組件中拋出了方法或者變量數據,在這里可以直接調用const childComponent = formDataRef.value;if (childComponent && childComponent.TableList) {const list = childComponent.TableList;//提交給調用彈窗組件的頁面emit(`${proxy.$store.rou_Name}PopUpWindow`,list,childComponent,props.FormList.type)}
};onMounted(() => {
});//關閉彈窗
const handleClose = () => {//調用表單組件中的重置操作formDataRef.value.FormresetFields()emit(`${proxy.$store.rou_Name}PopUpWindow`, false)
};
</script><style lang="less" scoped>
.dialog {width: 90%;margin: 10px auto 0 auto;
}
::v-deep(.el-dialog) {--el-dialog-padding-primary: 5px 0 0 0;
}
::v-deep(.el-dialog__header) {border-bottom: 1px solid #ccc;line-height: 40px !important;
}
::v-deep(.el-dialog__title) {margin-left: 16px;
}
::v-deep .elForm {max-height: 100% !important;
}
::v-deep .el-form-item {margin-bottom: 20px;
}
::v-deep .el-form-item__content,
::v-deep .el-input,
::v-deep.el-select {height: 40px !important;
}
::v-deep .el-input__inner {line-height: 40px !important;
}
::v-deep(.el-radio-group:nth-child(2)) {margin-left: 20px;
}
::v-deep(.el-dialog__footer) {border-top: 1px solid #ccc;padding: 10px 15px 10px 0;
}
</style>
頁面調用表單組
<template><div class="box"><div class="title">WEB權限 <span>列表</span></div><div class="contet"> <div class="button"><div ><Button :type="'primary'" @click="handleClickUp('expand')" :icon="'plus'" :title="'展開'" :pattern="'centre'" /><Button :type="'primary'" @click="handleClickUp('retract')" :icon="'plus'" :title="'收起'" :pattern="'centre'" /><Button :type="'primary'" @click="handelSubmit" :icon="'plus'" :title="'保存'" :pattern="'centre'" /><Button plain :title="'刷新'" @click="clickRefresh" :pattern="'centre'" :icon="'download'"/></div><div><Button :type="'primary'" @click="handelCreateConfig" :icon="'plus'" :title="'新增'" :pattern="'centre'" /></div></div><!-- 樹狀結構 --><div class="Tree" ><Tree :isUp="isUp" ref="treelist" :treeApiObject="treeApiObject" @ConfigTree="ConfigTree" /></div></div> <!-- 新增編輯彈出框 --><PopUpWindow :FormList="FormList" @ConfigPopUpWindow="ConfigPopUpWindow" v-if="PopUpWindowShow" ></PopUpWindow></div>
</template><script lang="ts" setup>import { Button ,Tree , PopUpWindow, } from "@/components";import { onMounted, ref } from "vue";import useCurrentInstance from "@/hooks/useCurrentInstance";
const { proxy } = useCurrentInstance();const isUp = ref({number : 0,type : ''})const treelist = ref(null)const treeApiObject = ref({deleteUrl:'/system/permission/delete',editUrl :'/system/permission/edit'})const PopUpWindowShow = ref(false)
//定義傳遞給const FormList = ref({index:'2',formInline:true,isInput:true,type:'create',title:'新增權限',with:'448px',listData:{"parent_id":{title:'父級',type:'select',clearable:true,required:true,value:'',children:[]},"permission_type":{title:'權限類型',type:'select',required:true,clearable:true,value:'',children:[{label:"菜單",value:1},{label:"列表",value:2},{label:"按鈕",value:3},]},"name":{ title:'名稱',type:'input',required:true,clearable:true,value:'',},"slug":{ title:'權限標識',type:'input',required:true,clearable:true,value:'',}, "guard_name":{ title:'規則',type:'input',disabled:true,clearable:true,value:'web',}, "web_path":{ title:'前端訪問路徑',type:'input',required:true,clearable:true,value:'',}, }
})const resettingFormList = ref(null)onMounted(()=>{
getSessingStorageList()})function handleClickUp(type:string) {isUp.value.type = typeif(type == 'expand'){isUp.value.number += 1}else{isUp.value.number += 1}}function clickRefresh() {treelist.value.GetTreeList()}function handelSubmit() {let list:number[] = []proxy.$PublicAPI.UpdataTreeList(treelist.value.data,list)proxy.$project_interface.SaveTreeList({"permission_data":list}).then(res=>{console.log('res',res);})}
//點擊新增 傳遞首次進入的數據類型function handelCreateConfig() {PopUpWindowShow.value = true}//這個是獲取添加彈窗表單的下拉數據function getSessingStorageList() {let list:number[] = []let navlist = [{id:0,hidden:1,name:'系統',order:2,Permissions:1,web_path:'',children:JSON.parse(sessionStorage.getItem('NavList'))}]proxy.$PublicAPI.UpdataSelectTree(navlist,list,1)console.log('list',list);FormList.listData['parent_id'].children = listresettingFormList.value = JSON.parse(JSON.stringify(FormList.value)) }//接收菜單樹狀點擊編輯傳遞過來的數據
function ConfigTree(params:object){FormList.value.title = '編輯權限'FormList.value.type = 'edit'FormList.value.listData['id'] = {value:params.id}for (const key in params) {for (const index in FormList.value.listData) {if(index == key){if(FormList.value.listData[index].type == 'select'){FormList.value.listData[index].value = parseInt(params[key])}else{FormList.value.listData[index].value = params[key]}}}}PopUpWindowShow.value = true
}//根據彈窗組件傳遞過來的數據來判斷是點擊了取消還是確認,并做出相應的處理function ConfigAxios(params:object, subset:object,type:string) {let apiName = ''if(type == 'create'){apiName = 'Createconfig'}else if(type == 'edit'){apiName = 'Editconfig'}proxy.$project_interface[apiName](params).then(res=>{if(res.code == 200){subset.ResetForm()PopUpWindowShow.value = falseclickRefresh()}})}//接收彈窗關閉傳遞過來的數據function ConfigPopUpWindow(params:boolean,subset:object,type:string) {if(typeof(params) == 'boolean'){PopUpWindowShow.value= paramsFormList.value = JSON.parse(JSON.stringify(resettingFormList.value))}else{ConfigAxios(params,subset,type)}}
</script><style scoped lang="less">.box{width: 99%;height: 100%;margin: auto;.title{font-size: 24px;letter-spacing: 0.1em;color: var(--PublicFonteColor);span{color:var(--Nav_Font_Color);font-size:var(--Nav_FontSize) ;}}.contet{margin-top: 18px;width: 100%;background: white;.button{display: flex;justify-content: space-between;padding: 16px 0;border-bottom:1px solid #ccc;div {padding: 0 5px;display: flex;}}.Tree{padding: 16px 10px;}}}
</style>