• [VUE3] Element Plus 增删拆改页组件拆解


    [VUE3] Element Plus 增删拆改页组件拆解

    组件拆解思路

    https://procomponents.ant.design/components/table/?current=1&pageSize=5

    img

    一般按照我的理解,各部分功能区主要放置的东西如下所示。

    • 高级筛选栏:筛选条件 、重置、搜索

    • 标题栏:例如新建、导入数据、导出数据、批量操作等与表格多行操作相关的按钮等

    • 表格区域:表格数据、表格单行操作等

    • 分页栏:控制pageNo、pageSize等

    除了这几部分功能区,一般地,我个人还会再加上一些modal(对话框)、drawer(抽屉)

    • Modal:增加、编辑、或查看详情操作,内嵌表单form
    • Drawer:增加、编辑、或查看详情操作,内嵌表单form

    img

    config.js:整个组件的一些配置

    BtnGroup组件:对应”标题栏“

    Index.vue:核心,是其他组件的共同父组件,统一处理数据,负责布局和接收并处理子组件传递的事件,总调度

    SearchCom:对应“高级筛选栏”

    TableCom:对应”表格区域“

    index.less:组件中样式统一编写处

    AddOrEditNidal:增加或编辑的modal组件

    DetailModal.vue:查看详情的modal组件

    ExportModal.vue:导出数据的modal组件

    还有一个分页的组件,一般放在components共用:

    Pageable.vue:负责分页

    整体布局大致如下:

    img

    img

    简单示例demo

    Index.vue

    <template>
        <div>
            <SearchCom ref="searchComRef" @search="handleSearch" @refresh="handleRefresh">SearchCom>
            <BtnGroup style="margin-top: 15px" @btnEvent="handleBtnEvent">BtnGroup>
    
            <TableCom
                style="margin-top: 15px"
                :loading="tableLoading"
                :pageData="pageData"
                @changePage="handleChangePage"
                @triggerEvent="handleTriggerEvent"
            >TableCom>
    
            <DetailDrawer>DetailDrawer>
            <AddOrEditModal
                ref="addOrEditModalRef"
                @ok="addOrEditOk"
                @cancel="addOrEditCancel"
                :open-option="addOrEditOpenOption"
            >AddOrEditModal>
    
            <BulkAddModal
                ref="bulkAddModalRef"
                @ok="bulkAddOk"
                @cancel="bulkAddCancel"
                :open-option="bulkAddOpenOption"
            >BulkAddModal>
        div>
    template>
    
    <script setup>
    import BtnGroup from './BtnGroup.vue';
    import SearchCom from './SearchCom.vue';
    import TableCom from './TableCom.vue';
    import AddOrEditModal from './AddOrEditModal.vue';
    import DetailDrawer from './DetailDrawer.vue';
    import BulkAddModal from './BulkAddModal.vue';
    
    import { ref, provide, unref, onMounted } from 'vue';
     
    import { checkResp } from '@/utils/utils';
    import { ElMessage } from 'element-plus';
    import {
        netDelPackage,
        netGetPackageList,
        netSavePackage,
        netUploadPackage,
        netUpdatePackage
    } from '@/http/modules/softPackageManage';
    
    // ---------------------------表格相关模块--------------------------
    const pageData = ref({
        size: 10,
        content: [],
        number: 0,
        totalElements: 2,
        totalPages: 1
    });
    const pageSize = ref(10);
    const tableLoading = ref(false);
    const searchComRef = ref(null);
    const searchFields = ref({});
    const handleSearch = fields => {
        console.log('父组件接收到fields');
        console.log(fields);
        searchFields.value = fields;
        getResultList();
    };
    
    const handleRefresh = () => {
        // 清空父子组件的fields
        searchComRef['value'].clearForm();
        searchFields['value'] = {};
        getResultList();
    };
    
    // 获取结果列表
    const getResultList = async (pageNum, pSize) => {
        tableLoading.value = true;
    
        const params = {
            pageNo: pageNum || 1,
            pageSize: pSize || pageSize.value,
            ...unref(searchFields)
        };
    
        try {
            const resp = await netGetPackageList({}, params);
    
            if (checkResp(resp)) {
                console.log(resp);
                pageData.value = resp.data;
            }
        } catch (e) {
            ElMessage.error(`获取数据失败`);
        } finally {
            tableLoading.value = false;
        }
    };
    
    // 翻页
    const handleChangePage = (pageNum, pSize) => {
        // const { pageNum, pSize } = payload;
        console.log('父组件接收到了页面变化');
        console.log(pageNum, pSize);
        getResultList(pageNum, pSize);
    };
    
    // 详情 删除 等
    const handleTriggerEvent = (eventType, record) => {
        console.log('父组件接收到了事件触发');
        console.log(eventType, record);
    
        switch (eventType) {
            case 'edit':
                handleRecordEdit(record);
                break;
            case 'delete':
                handleRecordDel(record.id);
                break;
        }
    };
    
    // -------------------------------------------弹框相关------------------------------------
    
    // ------------------------------------新增或编辑框------------------------------
    const addOrEditModalRef = ref(null);
    const addOrEditOpenOption = ref({
        openType: 'add',
        visible: false,
        loading: false,
        model: {}
    });
    
    const addOrEditOk = async fields => {
        console.log('父组件接收到了fields');
        console.log(fields);
    
        try {
            let resp;
    
            if (addOrEditOpenOption['value'].openType === 'add') {
                resp = await netSavePackage(fields);
            } else if (addOrEditOpenOption['value'].openType === 'edit') {
                resp = await netUpdatePackage(fields);
            }
    
            if (checkResp(resp)) {
                ElMessage.success(`操作成功`);
                addOrEditModalRef['value'].clearForm();
                addOrEditCancel();
    
                // 刷新一下
                handleRefresh();
            }
        } catch (e) {
            ElMessage.error(`操作失败`);
        } finally {
        }
    };
    
    const addOrEditCancel = () => {
        console.log('取消了');
        addOrEditOpenOption.value.visible = false;
    };
    
    // ----------------------------------批量上传框------------------------------
    const bulkAddModalRef = ref(null);
    const bulkAddOpenOption = ref({
        openType: 'add',
        visible: false,
        loading: false,
        model: {}
    });
    
    const bulkAddOk = async fields => {
        console.log('父组件接收到了fields');
        console.log(fields);
    
        const formData = new FormData();
    
        fields.files.forEach(item => {
            formData.append('file', item.raw);
        });
    
        try {
            const resp = await netUploadPackage(formData);
            if (checkResp(resp)) {
                console.log(resp);
                ElMessage.success(`上传成功`);
                bulkAddModalRef['value'].clearForm();
                bulkAddCancel();
            }
        } catch (e) {
            ElMessage.error(`上传失败`);
        } finally {
        }
    };
    
    const bulkAddCancel = () => {
        console.log('取消了');
        bulkAddOpenOption.value.visible = false;
    };
    
    // -------------------------------点击button,打开框----------------------------------------
    const handleAdd = () => {
        addOrEditOpenOption.value.openType = 'add';
        addOrEditOpenOption.value.visible = true;
    };
    
    const handleEdit = record => {
        addOrEditOpenOption.value.openType = 'edit';
        addOrEditOpenOption.value.visible = true;
        addOrEditOpenOption.value.model = { ...record };
    };
    
    const handleBulkAdd = () => {
        bulkAddOpenOption.value.openType = 'add';
        bulkAddOpenOption.value.visible = true;
    };
    
    // -------------------------------------button group----------------------------------
    const handleBtnEvent = btnType => {
        console.log('父组件收到了btnType');
        console.log(btnType);
    
        switch (btnType) {
            case 'add':
                handleAdd();
                break;
            case 'edit':
                handleEdit();
                break;
            case 'bulkAdd':
                handleBulkAdd();
                break;
        }
    };
    
    // ---------------------------------针对record(一行数据)的操作---------------------------------
    const handleRecordEdit = record => {
        addOrEditOpenOption.value.openType = 'edit';
        addOrEditOpenOption.value.visible = true;
        addOrEditOpenOption.value.model = { ...record };
    };
    
    const handleRecordDel = async id => {
        try {
            const resp = await netDelPackage({
                id
            });
            if (checkResp(resp)) {
                ElMessage.success(`操作成功`);
    
                // 刷新一下
                handleRefresh();
            }
        } catch (e) {
            ElMessage.error(`操作失败`);
        } finally {
        }
    };
    
    // -------------------------------------页面生命周期-------------------------------------
    const init = () => {
        handleRefresh();
    };
    
    onMounted(() => {
        init();
    });
    script>
    
    <style scoped lang="less">
    @import './index.less';
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277

    SearchCom.vue

    <template>
        
        <el-form
            style="width: 98%; margin: 0 auto"
            ref="searchFormRef"
            :model="searchForm"
            :rules="searchRules"
            label-position="center"
        >
            <el-row :gutter="50">
                
                <el-col :span="7">
                    <el-form-item label="产品" prop="productIds">
                        <el-select
                            :loading="productLoading"
                            style="width: 85%"
                            v-model="searchForm.productIds"
                            placeholder="请选择"
                            multiple
                            clearable
                        >
                            <el-option v-for="item in productList" :key="item.id" :value="item.id" :label="item.productName"
                                >{{ item.productName }}
                            el-option>
                        el-select>
                        <SvgIcon style="margin-left: 10px" icon-class="icon-shuaxin" @click="()=> handleRefresh('product')">SvgIcon>
                    el-form-item>
                el-col>
    
                
                <el-col :span="8">
                    <el-form-item label="起止时间" prop="startToEnd">
                        <el-date-picker
                            style="width: 100%"
                            v-model="searchForm.startToEnd"
                            :shortcuts="timeShortcuts"
                            type="daterange"
                            range-separator=""
                            start-placeholder="开始日期"
                            end-placeholder="结束日期"
                            value-format="YYYY-MM-DD"
                        />
                    el-form-item>
                el-col>
    
                <el-col>
                    
                    <div style="display: flex; justify-content: flex-end">
                        <el-button type="primary" @click="handleSearch" icon="el-icon-search">搜索el-button>
                        <el-button @click="handleRefresh" icon="el-icon-refresh">重置el-button>
                    div>
                el-col>
            el-row>
        el-form>
    template>
    
    <script setup>
    import { onMounted, ref, unref } from 'vue';
    import SvgIcon from '@/components/SvgIcon.vue';
    import { useRoute } from 'vue-router';
    import { checkResp } from '@/utils/utils';
    import { netGetProductList, netGetProjectList, netGetSoftPackageList } from '@/http/modules/ExecutionStatistic';
    import { timeShortcuts } from './config';
    import { cloneDeep } from 'loadsh';
    
    const route = useRoute();
    const emit = defineEmits(['search', 'reset']);
    const searchFormRef = ref(null);
    const searchForm = ref({
        startToEnd: [],
       
    
        // 产品id(多个)
        productIds: '',
    
       
    });
    const searchRules = ref({
        productIds: [
            {
                required: false
            }
        ]
    });
    
    const handleSearch = async () => {
        // 校验搜索表单
        const form = unref(searchFormRef);
        let fields = unref(searchForm);
    
        // 校验表单
        if (!form) return;
        const valid = await form.validate();
        if (!valid) {
            console.log('error submit!');
            return;
        }
    
        // 校验通过后的处理
        fields = cloneDeep(fields);
       
    
        if (fields.startToEnd.length === 2) {
            const startFrom = fields.startToEnd[0];
            const endTo = fields.startToEnd[1];
    
            fields.startFrom = startFrom;
            fields.endTo = endTo;
        } else {
            fields.startFrom = null;
            fields.endTo = null;
        }
        delete fields.startToEnd;
    
        console.log('ok submit', fields);
    
        emit('search', fields);
    };
    
    // ----------------------------表单初始化相关--------------------------------
     
    // 产品
    const productList = ref([]);
    const productLoading = ref(false);
    const queryProductList = () => {
        netGetProductList().then(resp => {
            if (checkResp(resp)) {
                console.log(resp);
                productList.value = resp.data;
            }
        });
    };
        
        
    // 刷新 
    const handleRefresh = type => {
        switch(type){
            case 'product':
                searchForm.value.productIds = []
                queryProductList()
        }
    }
        
    // ---------------------------------刷新数据---------------------------------
    const handleRefresh = () => {
        // 重置表单
        searchFormRef['value'].resetFields();
        emit('reset');
    };
    
    // ----------------------------------页面初始化----------------------------------
    const init = () => {
        if (productList.value.length < 1) {
            queryProductList();
        }
    };
    
    onMounted(() => {
        init();
    });
    script>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162

    BtnGroup.vue

    <template>
        <div>
            <el-button @click="emit('btnEvent', 'add')" icon="el-icon-plus">新增el-button>
            <el-button @click="emit('btnEvent', 'bulkAdd')" icon="el-icon-upload">批量上传el-button>
        div>
    template>
    
    <script setup>
    	const emit = defineEmits(['btnEvent']);
    script>
    
    <style scoped>style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    TableCom.vue

    <template>
        <div>
            
            <el-table
                :data="pageData['content']"
                border
                v-loading="loading"
                :element-loading-svg="svg"
                class="custom-loading-svg"
                element-loading-svg-view-box="-10, -10, 50, 50"
            >
                <el-table-column width="80" label="序号" align="center" show-overflow-tooltip>
                    <template #default="scope">
                        {{ scope.$index + 1 }}
                    template>
                el-table-column>
    
                <el-table-column label="名称" min-width="100" prop="name" align="center" show-overflow-tooltip>
                el-table-column>
     
    
                
                <el-table-column fixed="right" label="操作" width="220" align="center">
                    <template #default="{ row }">
                        
                        
                        
    
                        <el-popconfirm
                            style="margin-left: 10px"
                            confirmButtonText="确认"
                            cancelButtonText="取消"
                            @confirm="handleEventTrigger('delete', row)"
                            icon="el-icon-warning"
                            iconColor="red"
                            title="确定删除吗?"
                        >
                            <template #reference>
                                <el-button type="danger" size="mini" icon="el-icon-delete">删除el-button>
                            template>
                        el-popconfirm>
                    template>
                el-table-column>
            el-table>
    
            
            <pageable
                :isPageSet="true"
                :total="pageData['totalElements']"
                :current-page="pageData['number'] + 1"
                :page-size="pageData['size']"
                @change="handlePageChange"
            >pageable>
        div>
    template>
    
    <script setup>
    // 引入部分
    import { onMounted, ref, reactive, unref } from 'vue';
    import Pageable from '@/components/Pageable.vue';
    
    // 基础声明部分
    const svg = `
            
          `;
    
    const props = defineProps({
        pageData: {
            type: Object,
            default: () => ({})
        },
        pageSize: {
            type: Number,
            default: 10
        },
        loading: {
            type: Boolean,
            default: false
        }
    });
    
    const emit = defineEmits(['changePage', 'triggerEvent']);
    
    // 表格展示相关
    const handlePageChange = (pageNum, pSize) => {
        console.log(pageNum, pSize);
        emit('changePage', pageNum, pSize);
    };
    
    // 事件触发
    const handleEventTrigger = (eventType, record) => {
        emit('triggerEvent', eventType, record);
    };
    
    // 初始化函数
    const init = () => {};
    
    // --------------------------生命周期相关-------------------------
    onMounted(() => {
        init();
    });
    script>
    
    <style>
    .top-helper {
        padding: 10px 0;
    }
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116

    Pageable.vue

    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    config.js

    /**
     * 获取本月第一天
     */
    const getNowMonthFirst = () => {
        const date = new Date();
        date.setDate(1);
        return date;
    };
    
    /**
     * 获取本月最后一天
     */
    const getNowMonthLast = () => {
        const date = new Date();
        return new Date(date.getFullYear(), date.getMonth() + 1, 0);
    };
    
    //本周第一天
    function weekFirst() {
        return new Date(new Date().getTime() - 3600 * 1000 * 24 * (new Date().getDay() - 1));
    }
    
    // 本周最后一天
    function weekLast() {
        return new Date(new Date().getTime() + 3600 * 1000 * 24 * (7 - new Date().getDay()));
    }
    
    export const timeShortcuts = [
        {
            text: '当前周',
            value: () => {
                const start = weekFirst();
                const end = weekLast();
    
                return [start, end];
            }
        },
        {
            text: '当前月',
            value: () => {
                const start = getNowMonthFirst();
                const end = getNowMonthLast();
    
                return [start, end];
            }
        },
        {
            text: '最近一周',
            value: () => {
                const end = new Date();
                const start = new Date();
                start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
                return [start, end];
            }
        },
        {
            text: '最近一月',
            value: () => {
                const end = new Date();
                const start = new Date();
                start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
                return [start, end];
            }
        },
        {
            text: '最近三个月',
            value: () => {
                const end = new Date();
                const start = new Date();
                start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
                return [start, end];
            }
        },
        {
            text: '所有',
            value: () => {
                return [null, null];
            }
        }
    ];
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    AddOrEditModal.vue

    <template>
        
        <el-dialog v-model="openOption.visible" :title="openOption.openType === 'add' ? '新增' : '编辑'" width="60%">
            <el-skeleton :loading="openOption.loading" animated>
                <el-form ref="formRef" :model="form" :rules="rules" :label-width="formLabelWidth" status-icon>
                    <el-form-item label="名称" prop="name">
                        <el-input style="width: 90%" v-model="form.name" />
                    el-form-item>
                el-form>
            el-skeleton>
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="handleCancel">取消el-button>
                    <el-button type="primary" @click="handleConfirm">确认el-button>
                span>
            template>
        el-dialog>
    template>
    
    <script setup>
        import { onMounted, ref, unref, watch, toRefs } from 'vue';
        import axios from '@/http/axios';
        import { checkResp } from '@/utils/utils';
        import SvgIcon from '@/components/SvgIcon.vue';
        // --------------------------定义部分----------------------------
        const props = defineProps({
            // 打开类型  新增 编辑
            openOption: {
                type: Object,
                default: () => ({
                    openType: 'add',
                    visible: false,
                    loading: false,
                    model: {}
                })
            }
        });
    
        const emit = defineEmits(['ok', 'cancel']);
    
        // 基础声明部分
        const formLabelWidth = '150px';
        const { openOption } = toRefs(props);
    
        // svg图
        const svg = `
            
          `;
    
        // 表单
        const form = ref({
            name: '',
            code: '',
            version: '',
            applicableModel: '',
            businessType: ''
        });
        const formRef = ref(null);
        const rules = ref({
            name: [
                {
                    required: true,
                    message: '不能为空',
                    trigger: 'blur'
                }
            ],
        });
    
        // -----------表单查询相关-----------------
        // -------示例:单选下拉 产品列表------------
        const productionList = ref([]);
        const productionLoading = ref(false);
        const netGetProductionList = async () => {
            productionLoading.value = true;
            try {
                const resp = await axios.get('/controller/products/list', {
                    params: {
                        pageNo: 1,
                        pageSize: 999
                    }
                });
    
                if (checkResp(resp)) {
                    productionList.value = resp.data.content;
                }
            } catch (e) {
                console.log('error');
            } finally {
                productionLoading.value = false;
            }
        };
        const handleProductionRefresh = () => {
            console.log('处理产品列表刷新');
            form.value.productId = '';
            netGetProductionList();
        };
    
        // ---------------确认和取消---------------------
        const handleCancel = () => {
            emit('cancel');
        };
    
        // 确认提交
        const handleConfirm = () => {
            const fields = unref(form);
    
            // 校验表单
            if (!formRef) return;
            formRef['value'].validate(valid => {
                console.log(valid, fields);
                if (valid) {
                    // 校验通过
                    console.log('ok submit', fields);
                    emit('ok', fields);
                } else {
                    console.log('error submit!');
                }
            });
        };
    
        // 清空表单
        const clearForm = () => {
            console.log('clearForm');
            formRef['value'].resetFields();
        };
    
        // 页面初始化函数
        const init = () => {};
    
        watch(
            () => props.openOption.visible,
            newVal => {
                console.log('监控到弹窗的打开和关闭');
                console.log(newVal);
                if (newVal) {
                    if (productionList.value.length < 1) {
                        handleProductionRefresh();
                    }
    
                    setTimeout(() => {
                        console.log('nextTick');
                        console.log(openOption);
                        if (openOption['value'].openType === 'edit') {
                            console.log('有modal传进来');
                            console.log(openOption['value'].model);
    
                            const model = openOption['value'].model;
    
                            form.value = { ...model };
                        }
                    });
                }
            }
        );
    
        // ---------------------------生命周期相关-------------------------
        onMounted(() => {
            init();
        });
    
        // 对外暴露
        defineExpose({
            clearForm
        });
    script>
    
    <style scoped>style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
  • 相关阅读:
    Spring扩展接口(2):BeanDefinitionRegistryPostProcessor
    FPGA领域顶级学术会议
    代码随想录算法训练营第三十一天| 455 分发饼干 376 摆动序列 53 最大子数组和
    Qt入门(八)——Qt打包(将Qt文件可以在别的Windows系统下运行)
    使用 Linux 15 年后,我重新回到 Windows:感觉非常糟糕
    毕业设计-图像绘制系统设计( Matlab机器人工具箱综合应用)
    如何远程控制别人电脑进行技术支持?
    7.1.3 Selenium的用法2
    拓端tecdat|R语言社区主题检测算法应用案例
    ADRC自抗扰控制从Simulink仿真到PLC控制实现
  • 原文地址:https://blog.csdn.net/qq_41996454/article/details/126855442