基于element-plus的Dialog选择控件

翻看之前工程师写的vue2的代码,很多都是复制、粘贴,也真是搞不懂,明明可以写一个控件,不就可以重复使用。很多前端总喜欢element搞一下,ant-design也搞一下,有啥意义,控件也不是自己写的,积木也没有搭好。

选中之后将值带回去

先看看组件代码

ts 复制代码
<template>
    <el-input v-model="inputLabel" @click="showSub">
        <template #suffix>
            <i class="iconfont iconicon2-081"></i>
        </template>
    </el-input>

    <BaseDialog ref="dialog" title="选择会计科目" width="470px" :visible='visible' :showClose="true" 
        @beforeClose="visible=false">
        <el-tabs v-model="subjectName" >
            <el-tab-pane v-for="(item,index) in subjectTabs" :key="index" :name='item.name' :label="item.title" :value="index" class="tabPane">
            <el-tree :data="categoryTree[index]" node-key="id" default-expand-all highlight-current :expand-on-click-node='false' @node-click="handleSubjectClick" :props="defaultSubjecTreeProps"
            style="height: 380px;overflow-y: auto;">
                <template #default="{ node,data }">
                    <span class="custom-tree-node">
                        <i :class="data.children.length>0 ? 'iconfont iconicon2-08' : 'iconfont iconicon2-11' "></i>
                        {{ node.label }}
                    </span>
                </template>
            </el-tree>
            </el-tab-pane>
        </el-tabs>
        <template #footer>
            <div  class="dialog-footer">
                <el-button type="primary" @click="cancelDialog">返 回</el-button>
            </div>
        </template>
    </BaseDialog>
</template>
<script lang="ts" setup>
import {ref,getCurrentInstance,computed,onMounted,watch } from 'vue'
import BaseDialog from '@/components/base/BaseDialog.vue';
import { useAppStore } from '@/store'
import { de } from 'element-plus/es/locale';
const { proxy }: any = getCurrentInstance();
const appStore = useAppStore()
const userInfo = computed(() => appStore.userInfo)
const curAccountSet = computed(() => appStore.curAccountSet)
const defaultSubjecTreeProps = ref({children: 'children',label: 'label'})
const inputProps = ref({label:'name',value:'id'})
const inputLabel = ref('')
const emits = defineEmits(['update:modelValue','change'])
const visible = ref(false)
const props = defineProps<{
    modelValue:{},
}>()
const showSub = () =>{
    visible.value = true;
}
const subjectName = ref(1)
const subjectTabs = ref(curAccountSet.value?.accountingStandard=='1'?[
    {title: "资产", name: 1,},
    {title: "负债", name: 2,},
    {title: "权益", name: 3,},
    {title: "成本", name: 4,},
    {title: "损益", name: 5,},
]:[
    {title: "资产", name: 1,},
    {title: "负债", name: 2,},
    {title: "共同", name: 3,},
    {title: "权益", name: 4,},
    {title: "成本", name: 5,},
    {title: "损益", name: 6,},
])
const categoryTree = ref([])
const getCategoryTree = async (cate) =>{
    const res = await proxy.$api.acc.accountsubject.list({asId:curAccountSet.value.accId,category:cate});
    if (res.success){
        categoryTree.value[cate - 1] = res.data;
    } else{
        proxy.$message.error(res.msg);
    }
}
const handleSubjectClick = (data) => {
    if (proxy.$_.isEmpty(data.children)){
        inputLabel.value = data.name
        emits('update:modelValue',{value:data.id,label:data.name})
        visible.value = false
    }
}
const cancelDialog = () =>{
    visible.value = false;
}
watch(()=>props.modelValue,(newVal,oldVal)=>{
    if (!proxy.$_.isEmpty(newVal)){
        inputLabel.value = newVal['label']
    }
},{immediate:true,deep:true})
onMounted(()=>{
    getCategoryTree(1);
    getCategoryTree(2);
    getCategoryTree(3);
    getCategoryTree(4);
    getCategoryTree(5);
})
</script>

控件使用比较简单了

html 复制代码
<el-form-item label="应付账款" prop="yfzk">
                            <acc-account-subject v-model="orderForm.yfzk"></acc-account-subject>
                        </el-form-item>

但是在保存和加载的时候需要特殊处理,因为控件的值是{value:data.id,label:data.name}

保存之前,需要做一次深拷贝,不能直接修改orderForm.value,因为双向绑定,页面的数据会改变。

ts 复制代码
const convertParams = () =>{
    debugger
    let params = proxy.$tool.deepClone({...orderForm.value})
    // 应收账款
    params['yszk'] = orderForm.value['yszk']?.value || ''
    params['yszkName'] = orderForm.value['yszk']?.label || ''
  
    return params;
}
const save = async () => {
    orderRef.value?.validate(async valid=>{
        if (valid){
            isLoading.value = true
            const params = convertParams()
            const res = await proxy.$api.setting.psiAccConfig.save(params)
            if (res.success){
                isLoading.value = false;
                proxy.$message.success(res.msg);
            } else{
                isLoading.value = false;
                proxy.$message.error(res.msg);
            }
        }
    })
}

页面加载的时候也需要做一下处理,还是因为数据结构的缘故

ts 复制代码
const load = async () => {
    const res = await proxy.$api.setting.psiAccConfig.load({asId:userInfo.value.currentAsId})
    if (res.success){
        isLoading.value = false;
        orderForm.value = res.data;
        // 应收张狂
        if (orderForm.value['yszkName']){
            orderForm.value['yszk'] = {label:orderForm.value['yszkName'],value:orderForm.value['yszk']}
        }
        }
    } else{
        isLoading.value = false;
        proxy.$message.error(res.msg);
    }
}
相关推荐
赢乐7 天前
深度剖析:前端如何驾驭海量数据,实现流畅渲染的多种途径
element-plus·虚拟滚动·前端分页·分批渲染·大量数据的渲染·settimeout定时器·滚动触底加载数据
爱分享的Hayes小朋友18 天前
关于element-plus中el-select自定义标签及样式的问题
前端·javascript·vue3·element-plus
会做梦的辣条鱼1 个月前
vue3全局封装table分页
前端·vue.js·前端框架·element-plus·vue3.0·组件封装·pagination
何日成熟2 个月前
element-plus 工作经验总结
前端·vue.js·element-plus
哇,女前端哎!2 个月前
vue3实现电子签名的方法
前端框架·vue3·canvas·element-plus·vuesignaturepad
nothing_more_than2 个月前
自定义表单元素组件内容变化触发ElForm重新校验
前端·vue.js·element-plus
bfbshs_ddd3 个月前
[已解决]Vue3+Element-plus使用el-dialog对话框无法显示
vue·dom·element-plus·el-dialog
程序员偏安5 个月前
从零搭建Vue3 + Typescript + Pinia + Vite + Tailwind CSS + Element Plus开发脚手架
vue.js·typescript·vite·element-plus·tailwind css