2 24.封装组合式API特性 列表分页搜索增删改

  • 通用列表搜索组件封装

    • 列表

    • 分页

    • 搜索

    • 删除

    • 修改、状态修改

    • 创建

src/composables/useCommon.js

import { reactive, ref, computed } from 'vue'
import { toast } from '~/composables/util'

// 列表、分页、搜索、删除、修改状态
export function useInitTable(opt = {}){
    let searchForm = null
    let resetSearchFrom = null
    if(opt.searchForm){
        searchForm = reactive({ ...opt.searchForm })
        resetSearchFrom = ()=> {
            for (const key in opt.searchForm ) {
                searchForm[key] = opt.searchForm[key];
            }
            getData()
        }
    }
        

    
    // 加载动画
    const tableData = ref([])
    const loading = ref(false)
    

    // 分页
    const currentPage = ref(1)
    const total = ref(0)
    const limit = ref(10)
        
    // 获取数据
    function getData(p = null){
        if (typeof p == "number"){
            currentPage.value = p
        }


        loading.value = true
        opt.getList(currentPage.value,searchForm)
        .then(res=>{
            if(opt.onGetListSuccess && typeof opt.onGetListSuccess == "function"){
                opt.onGetListSuccess(res)
            } else {
                // tableData.value = res.list.map(o=>{
                //     o.statusLoading = false
                //     return o
                // })
                tableData.value = res.list
                total.value = res.totalCount
                
            }

        }).finally(()=>{
            loading.value = false 
        })
    }

    getData()


    // 删除
    const handleDelete = (id)=> {
        loading.value = true
        opt.delete(id).then(res=>{
            toast('删除成功')
            getData()
        }).finally(()=>{
            loading.value = false
        })
    }

    // 修改状态
    const handleStatusChange = (status, row) =>{
        row.statusLoading = true
        opt.updateStatus(row.id,status)
        .then((res)=>{
            toast('修改状态成功')
            row.status = status
        }).finally(()=>{
            row.statusLoading = false
        })
    }


    return {
        searchForm,
        resetSearchFrom,
        tableData,
        loading,
        currentPage,
        total,
        limit,
        getData,
        handleDelete,
        handleStatusChange
    }

    
}


//新增,修改
export function useInitForm(opt = {}){
    // 表单部分
    const formDrawerRef = ref(null)
    const formRef = ref(null)
    const defaultForm = opt.form
    const form = reactive({})
    const rules = opt.rules || {}
    const editId = ref(0)
    const drawerTitle = computed(()=> editId.value ? "修改" : "新增")

    const handleSubmit = () => {
        formRef.value.validate((valid)=>{
            if(!valid) return 
    
            formDrawerRef.value.showLoading()
    
            const fun = editId.value ? opt.update(editId.value, form) : opt.create(form)
    
            fun.then(res=>{
                toast(drawerTitle.value + '成功')
    
                // 修改刷新当前页,添加刷新第一页
                opt.getData(editId.value ? false: 1)
                formDrawerRef.value.close()
            }).finally(()=>{
                formDrawerRef.value.hideLoading()
            })
    
        })
    }
    

    // 重置表单
    function resetForm(row=false){
        if(formRef.value) formRef.value.clearValidate()
        if(row){
            for(const key in defaultForm){
                form[key] = row[key]
            }
        }
    }

    // 新增
    const handleCreate = ()=>{
        editId.value = 0
        resetForm(defaultForm)
        formDrawerRef.value.open()
    }


    // 编辑
    const handleEdit = (row)=> {
        editId.value = row.id
        resetForm(row)
        formDrawerRef.value.open()
    }

    return {
        formDrawerRef,
        formRef,
        form,
        rules,
        editId,
        drawerTitle,
        handleSubmit,
        resetForm,
        handleCreate,
        handleEdit
    }
}
  • 传搜索参数调用

src/page/manager/list.vue


<script setup>
import {  ref} from 'vue'
import FormDrawer from '~/components/FormDrawer.vue';

import { getManagerList,updateManagerStatus,createManager,updateManager,deleteManager } from "~/api/manager"
import ChooseImage from '~/components/ChooseImage.vue'
import { useInitTable,useInitForm } from '~/composables/useCommon'

const roles = ref([])

const {
    searchForm,
    resetSearchFrom,
    tableData,
    loading,
    currentPage,
    total,
    limit,
    getData,
    handleDelete,
    handleStatusChange
} = useInitTable({
    searchForm: {
        keyword: ''
    },
    getList: getManagerList,
    onGetListSuccess: (res)=> {
        tableData.value = res.list.map(o=>{
            o.statusLoading = false
            return o
        })
        total.value = res.totalCount
        roles.value = res.roles
    },
    delete: deleteManager,
    updateStatus: updateManagerStatus
})


const {
    formDrawerRef,
    formRef,
    form,
    rules,
    drawerTitle,
    handleSubmit,
    handleCreate,
    handleEdit
} = useInitForm({
    form: {
        username:'',
        password: '',
        avatar: '',
        role_id: null,
        status: 1,
    },
    getData,
    update: updateManager,
    create: createManager
})





</script>
  • 无搜索参数调用

src/pages/notice/list.vue


<script setup>
import { getNoticeList,createNotice,updateNotice,deleteNotice } from "~/api/notice"
import FormDrawer from '~/components/FormDrawer.vue';
import { useInitTable,useInitForm } from '~/composables/useCommon'



const {
    tableData,
    loading,
    currentPage,
    total,
    limit,
    getData,
    handleDelete
} = useInitTable({
    rules: {
    title: [{
                required: true,
                message: '公告标题不能为空',
                trigger: 'blur',
            },],
        content: [{
                required: true,
                message: '公告内容不能为空',
                trigger: 'blur',
            },]
    },

    getList: getNoticeList,
    delete: deleteNotice,
})


const {
    formDrawerRef,
    formRef,
    form,
    rules,
    drawerTitle,
    handleSubmit,
    handleCreate,
    handleEdit
} = useInitForm({
    form: {
        title:'',
        content: ''
    },
    rules: {
        title: [{
                required: true,
                message: '公告标题不能为空',
                trigger: 'blur',
            },],
        content: [{
                required: true,
                message: '公告内容不能为空',
                trigger: 'blur',
            },]
    },

    getData,
    update: updateNotice,
    create: createNotice
})


</script>

Last updated