vue3中,渲染动态表单(三)——梳理动态表单的几种类型、树结构表格row-key、父子传值之props、emit和defineEmits & ElLoading组件用法和post请求动态地址

vue3中,渲染动态表单(三)——梳理动态表单的几种类型、树结构表格row-key、父子传值之props、emit和defineEmits & ElLoading组件用法和post请求动态地址

效果图

1-主页面

在这里插入图片描述

2-树结构表格

在这里插入图片描述

3-新增

在这里插入图片描述

4-编辑

在这里插入图片描述

1、主页

index.vue

<span class="text-btn" @click="edit(scope.row)">定义申请表</span>

<script>
const edit = (row: any) => {
    console.log(row);
    router.push('/myCenter/defineForm')
}
</script>
2、定义申请表管理

src\views\myCenter\applyForm\components\defineForm.vue

<!--
@Description 申请表管理 - 定义申请表
@author wdd
@date 2023/12/13
-->
<template>
    <centerHead title="定义申请表"></centerHead>
    <div class="content">
        <div class="left">
            <el-button type="primary" @click="add">新增</el-button>
            <el-table ref="tableRef" border class="table-style" :data="tableData" lazy :load="treeLoad" row-key="id"
                stripe style="width: 100%; margin-bottom: 20px"
                :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" @selection-change="handleChange">
                <el-table-column prop="name" align="center" label="字段名称"></el-table-column>
                <el-table-column prop="prop" align="center" label="字段参数"></el-table-column>
                <el-table-column prop="type" align="center" label="字段类型"></el-table-column>
                <el-table-column prop="rules" align="center" label="是否必填"></el-table-column>
                <el-table-column prop="placeholder" align="center" label="提示语"></el-table-column>
                <el-table-column prop="sort" align="center" label="字段序号"></el-table-column>
                <el-table-column prop="hasChildren" align="center" label="是否有子集"></el-table-column>
                <el-table-column label="操作" align="right" width="160">
                    <template #default="scope">
                        <span class="text-btn" v-if="scope.row.hasChildren"
                            @click="edit('addChild',scope.row)">新增子项</span>
                        <span class="text-btn" @click="edit('edit',scope.row)">编辑</span>
                        <span class="del-btn" @click="onDelete(scope.row)">删除</span>
                    </template>
                </el-table-column>
            </el-table>
            <div>
                <el-button type="primary" @click="onSave">提交</el-button>
                <el-button type="primary" @click="see">生成预览</el-button>
            </div>
            <FieldInfo v-if="showField" v-model:dialogVisible="showField" :info-data="fieldInfo"
                @emit-confirm="confirmOk" />
            <ExampleInfo v-if="showExample" v-model:dialogVisible="showExample" :info-data="exampleInfo"
                @emit-confirm="exampleOk" />
        </div>
    </div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import FieldInfo from './fieldInfo.vue'
import ExampleInfo from './exampleInfo.vue'
const router = useRouter();
const tableData = ref([{
    id: 1,
    name: '姓名',
    prop: 'name',
    type: '输入框',
    rules: '是',
    placeholder: '请输入',
    sort: 1,
    hasChildren: false
}, {
    id: 2,
    name: '性别',
    prop: 'sex',
    type: '下拉框',
    rules: '是',
    placeholder: '请选择',
    sort: 2,
    hasChildren: false
}, {
    id: 3,
    name: '备注',
    prop: 'notes',
    type: '多行文本',
    rules: '否',
    placeholder: '请输入',
    sort: 3,
    hasChildren: false
}, {
    id: 4,
    name: '手机号',
    prop: 'telephone',
    type: '手机',
    rules: '是',
    placeholder: '请输入',
    sort: 4,
    hasChildren: false
}, {
    id: 5,
    name: '身份证号',
    prop: 'IDCard',
    type: '身份证号',
    rules: '否',
    placeholder: '请输入',
    sort: 5,
    hasChildren: false
}, {
    id: 6,
    name: '邮箱',
    prop: 'email',
    type: '邮箱',
    rules: '否',
    placeholder: '请输入',
    sort: 6,
    hasChildren: false
}, {
    id: 7,
    name: '年龄',
    prop: 'age',
    type: '数字',
    rules: '否',
    placeholder: '请输入',
    sort: 7,
    hasChildren: false
}, {
    id: 8,
    name: '金额',
    prop: 'money',
    type: '数字',
    rules: '否',
    placeholder: '请输入',
    sort: 8,
    hasChildren: false
}, {
    id: 9,
    name: '作品来源',
    prop: 'source',
    type: '单选',
    rules: '是',
    sort: 9,
    hasChildren: false
}, {
    id: 10,
    name: '项目属性',
    prop: 'attribute',
    type: '多选',
    rules: '是',
    sort: 10,
    hasChildren: false
}, {
    id: 11,
    name: '年度',
    prop: 'year',
    type: '年度',
    rules: '是',
    placeholder: '请选择',
    sort: 11,
    hasChildren: false
}, {
    id: 12,
    name: '月份',
    prop: 'month',
    type: '年月',
    placeholder: '请选择',
    rules: '是',
    sort: 12,
    hasChildren: false
}, {
    id: 13,
    name: '出生日期',
    prop: 'birthday',
    type: '日期',
    placeholder: '请选择',
    rules: '是',
    sort: 13,
    hasChildren: false
}])
const showField = ref(false)
const fieldInfo = ref({})
const add = () => {
    showField.value = true
    fieldInfo.value = {
        // id: fieldId,
        typeName: 'add'
    }
}
const confirmOk = () => {
    tableData.value = []
    // getList()
}
const edit = (type: any, row: any) => {
    showField.value = true
    row.typeName = type
    // row.fieldId = directoryId
    fieldInfo.value = { ...row }
    router.push('/myCenter/defineForm')
}
// 懒加载
const treeLoad = (tree, treeNode, resolve) => {
    setTimeout(() => {
        const params = {
            pid: tree.id,
        }
        const dataList = ref([])
        maps.set(tree.id, { tree, treeNode, resolve })
        post(constant.ieopCollaborate + '/collaborate/directory/list', params).then((res) => {
            const data = res.data.data || []
            data.forEach((el) => {
                if (el.hasChildren) {
                    el.children = null
                }
            })
            dataList.value = data
            resolve(dataList.value)
        })
    }, 200)
}
// 批量删除
const ids = ref([])
const handleChange = (val: any) => {
    ids.value = val.map((item: any) => item.id)
}
const onDelete = (row: any) => {
    console.log(row);
    ElMessageBox.confirm('此操作将删除该费率, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
    }).then(() => {
        ElMessage.success('删除成功!')
        history.go(0)
    }).catch(() => {
        ElMessage.error('删除失败!')
    })
}

const showExample = ref(false)
const exampleInfo = ref({})
const see = () => {
    showExample.value = true
    exampleInfo.value = {
        // id: fieldId,
        // typeName: 'add'
    }
}
const exampleOk = () => {
    // tableData.value = []
    // getList()
}
const onSave = () => { }
</script>
<style lang="scss" scoped>
.content {
    margin-top: 20px;
    margin-right: 20px;
    width: 90%;
    .text-btn {
        font-size: 12px;
        color: #409EFF;
        margin-left: 4px;
        cursor: pointer;
    }
    .del-btn {
        font-size: 12px;
        color: #F56C6C;
        margin-left: 4px;
        cursor: pointer;
    }
    .el-button {
        float: right;
        margin: 0 0 10px 10px;
    }
    .left {
        padding-left: 16px;
        .el-table {
            margin: 20px 0;
        }
    }
}
</style>
3、新增申请表字段

src\views\myCenter\applyForm\components\fieldInfo.vue

<!--
@Description 申请表管理 - 定义申请表 - 新增/编辑字段弹框
@author wdd
@date 2023/12/14
-->
<template>
    <div>
        <el-dialog :title="titleText" v-model="dialogVisible" :close-on-press-escape="false"
            :close-on-click-modal="false" width="36%">
            <div style="padding-right:40px">
                <el-form label-width="100px" ref="formRef" :model="formInline">
                    <el-form-item label="字段名称:" prop="name" :rules="{
                      required: true,
                      message: '请输入',
                      trigger: 'blur',
                    }">
                        <el-input v-model="formInline.name"></el-input>
                    </el-form-item>
                    <el-form-item label="字段参数:" prop="prop" :rules="{
                      required: true,
                      message: '请输入',
                      trigger: 'blur',
                    }">
                        <el-input v-model="formInline.prop"></el-input>
                    </el-form-item>
                    <!-- 动态表单类型 typeList -->
                    <el-form-item label="字段类型:" prop="type" :rules="{
                      required: true,
                      message: '请输入',
                      trigger: 'blur',
                    }">
                        <el-select v-model="formInline.type" placeholder="请选择" style="width:100%">
                            <el-option v-for="item in typeList" :key="item.value" :label="item.label"
                                :value="item.value">
                            </el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="是否必填:" prop="rules">
                        <el-radio-group v-model="formInline.rules" class="ml-4">
                            <!-- <el-radio label="1" size="large">是</el-radio>
                        <el-radio label="2" size="large">否</el-radio> -->
                            <el-radio :label="'是'">是</el-radio>
                            <el-radio :label="'否'">否</el-radio>
                        </el-radio-group>
                    </el-form-item>
                    <el-form-item label="字段序号:" prop="sort" :rules="{
                      required: true,
                      message: '请输入',
                      trigger: 'blur',
                    }">
                        <el-input placeholder="请输入大于0的正整数" @input="changeSort" v-model="formInline.sort"></el-input>
                    </el-form-item>
                    <el-form-item label="提示语:" prop="placeholder">
                        <el-select style="width:100%" v-model="formInline.placeholder">
                            <el-option value="请输入" label="请输入"></el-option>
                            <el-option value="请选择" label="请选择"></el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item v-if="formInline.hasChildren" label="是否有子集:" prop="hasChildren">
                        <el-radio-group v-model="formInline.hasChildren" class="ml-4">
                            <el-radio :label="true">是</el-radio>
                            <el-radio :label="false">否</el-radio>
                        </el-radio-group>
                    </el-form-item>
                </el-form>
            </div>
            <template #footer>
                <span slot="footer" class="dialog-footer">
                    <el-button link type="primary" @click="dialogVisible = false">取消</el-button>
                    <el-button type="primary" @click="confirm()">确定</el-button>
                </span>
            </template>
        </el-dialog>
    </div>
</template>
<script lang="ts" setup>
import { ref, defineProps, defineEmits, computed, watch, inject } from 'vue';
import { post } from "@/utils/path.js";
import { ElLoading, ElMessage } from "element-plus";
const formRef = ref()
const dataObj = ref()
const titleText = ref('')
const constant = inject('constant')
const formInline = ref({
    name: '',
    prop: '',
    type: '',
    sort: '',
    rules: '否',
    placeholder: '',
    hasChildren: false,
})

// 动态表单类型
const typeList = ref([
    {
        label: "输入框",
        value: "text"
    }, {
        label: "数字",
        value: "number"
    }, {
        label: "下拉框",
        value: "select"
    }, {
        label: "日期",
        value: "date"
    }, {
        label: "年月",
        value: "month"
    }, {
        label: "年度",
        value: "year"
    }, {
        label: "起止日期",
        value: "datetimerange"
    },
    // {
    //   label:"富文本框",
    //   value:"editor"
    // },
    {
        label: "单选",
        value: "radio"
    }, {
        label: "多选",
        value: "checkbox"
    }, {
        label: "手机",
        value: "telephone"
    }, {
        label: "邮箱",
        value: "email"
    }, {
        label: "身份证",
        value: "IDCard"
    },
    // {
    //   label:"list集合",
    //   value:"list"
    // },
    // {
    //     label: "封面",
    //     value: "thumb"
    // }, 
    {
        label: "附件",
        value: "file"
    }, {
        label: "多行文本",
        value: "textarea"
    },
    // {
    //   label:"视频",
    //   value:"video"
    // },
    // {
    //     label: "电话",
    //     value: "phone"
    // }, 

])
const props = defineProps({
    infoData: {
        default: null,
        type: Object,
    },
    dialogVisible: {
        type: Boolean,
        default() {
            return false
        },
    },
})
//监听方法
const emit = defineEmits(['emit-confirm', 'update:dialogVisible'])
const dialogVisible = computed({
    get: () => props.dialogVisible,
    set: (val) => emit('update:dialogVisible', val),
})
watch(
    () => props.dialogVisible,
    (newVal) => {
        if (newVal) {
            dataObj.value = JSON.parse(JSON.stringify(props.infoData))
            if (dataObj.value.typeName == 'add') {
                titleText.value = '新增字段'
            }

            if (dataObj.value.typeName == 'addChild') {
                formInline.value.pid = dataObj.value.id
                formInline.value.hasChildren = dataObj.value.hasChildren
                titleText.value = '新增子项'
            }
            if (dataObj.value.typeName == 'edit') {
                formInline.value = { ...dataObj.value }
                formInline.value.id = dataObj.value.id
                titleText.value = '编辑字段'
            }
        }
    },
    { immediate: true }
)
const changeSort = (val: any) => {
    const pattern = /^[1-9][0-9]*$/
    if (!pattern.test(val)) {
        formInline.value.sort = ''
    }
}
const confirm = async () => {
    await formRef.value.validate((valid: any) => {
        if (!valid) {
            return
        } else {
            const loading = ElLoading.service({
                lock: true,
                text: 'Loading',
                background: 'rgba(0, 0, 0, 0.7)',
            })
            const params = {
                ...formInline.value
            }
            const url = dataObj.value.typeName == 'addChild' ? '/collaborate/directory/add' : '/collaborate/directory/addRoot'
            const urlInfo = dataObj.value.typeName == 'edit' ? '/collaborate/directory/update' : url
            post(constant.ieopCollaborate + urlInfo, params).then((res) => {
                const { code } = res.data
                if (code == '200') {
                    loading.close()
                    ElMessage.success(dataObj.value.typeName == 'edit' ? '修改成功' : '新增成功')
                    emit('update:dialogVisible', false)
                    formInline.value = {}
                    emit('emit-confirm')
                } else {
                    loading.close()
                    ElMessage.error(res.message)
                    emit('update:dialogVisible', false)
                }
            })
                .catch(() => {
                    loading.close()
                })
        }
    })
}
</script>
4、引用文件

src\utils\path.js

import request from "./request";
import { getApiUrl } from "@/utils/tool";
const baseUrl = getApiUrl();
// 通用请求
export  function post(url, params = {}){
  const  data  =  request.post(baseUrl + url, params);
  // const data  =  request.post(url, params);
  return data
}
export  function get(url, params = {}){
  const  data  =  request.get(baseUrl + url);
  return data
}

src\utils\tool.js

export function getApiUrl(v) {
  return process.env.VUE_APP_API_HOST
}

})
}
})
}


#### 4、引用文件

src\utils\path.js

```js
import request from "./request";
import { getApiUrl } from "@/utils/tool";
const baseUrl = getApiUrl();
// 通用请求
export  function post(url, params = {}){
  const  data  =  request.post(baseUrl + url, params);
  // const data  =  request.post(url, params);
  return data
}
export  function get(url, params = {}){
  const  data  =  request.get(baseUrl + url);
  return data
}

src\utils\tool.js

export function getApiUrl(v) {
  return process.env.VUE_APP_API_HOST
}
  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值