vue3封装表格弹框组件——表格单选、axios动态接口、toRefs()用法、loading自定义、表格内容超出高度滚动
1
2
1、点击页面
index.vue
<template> <div class="main-content"> <el-form ref="formRef" label-width="130" :model="formInline.formData"> <el-row> <el-col :span="6"> <el-form-item label="项目名称:" prop="prjName" :rules="{ required: true, message: '请选择项目', trigger: 'change', }" > <el-input v-model="formInline.formData.prjName" :disabled="route.query.type === 'view'" maxlength="100" placeholder="请输入" @click="handlePrjName" @input=" (e) => (formInline.formData.prjName = replaceCommonText(e)) " /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="牵头单位:" prop="leadUnitName"> <el-input v-model="formInline.formData.leadUnitName" disabled="false" maxlength="100" placeholder="请输入" @input=" (e) => (formInline.formData.leadUnitName = replaceCommonText(e)) " /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="项目负责人:" prop="prjHeadName"> <el-input v-model="formInline.formData.prjHeadName" disabled="false" maxlength="100" placeholder="请输入" @input=" (e) => (formInline.formData.prjHeadName = replaceCommonText(e)) " /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="系统内单位角色:" prop="innerRole"> <dictSelect v-model="formInline.formData.innerRole" :dictid="'sgCompRole'" disabled="false" /> </el-form-item> </el-col> </el-row> </el-form> <SelectProject v-if="dialogProject" v-model:dataType="dataType" v-model:dialogVisible="dialogProject" v-model:prjData="formInline.formData" :prj-category="2" :request-url="mediumExamSelectPrj" :selected="formInline.formData.prjCode" @emit-select="handleChooseData" /> </div> </template> <script setup> import SelectProject from "@/components/SelectProject"; import { mediumExamSelectPrj } from "@/api/project/couny"; const formInline = reactive({ formData: {}, }); const dialogProject = ref(false); const dataType = ref("project"); const handlePrjName = () => { dialogProject.value = true; }; const handleChooseData = (val) => { formInline.formData.prjId = val[0].id; }; </script> <style lang="scss" scoped></style>
2、主页弹框组件
src\app\science\components\SelectProject.vue
<!-- dialogVisible // 弹窗显隐 dataType // 弹窗数据类型 project项目数据 prjData // 选择后项目数据 prjCategory // 项目分类 1 公司级,2 国家级,3 各单位自管, 100可研申报 emit-select // 项目选择后回调方法 requestUrl // 新的项目请求接口 --> <template> <el-dialog v-model="dialogVisible" class="diaStyle" :modal="false" style="height: 80vh; overflow-y: auto" :title="dataType === 'project' ? '选择项目' : ''" > <el-form ref="formRef" class="inline-form" :inline="true" label-position="right" label-width="100px" :model="formInline" > <el-form-item label="项目名称:" prop="prjName"> <el-input v-model="formInline.prjName" maxlength="100" placeholder="请输入" :rules="[ { validator: validateCommonText, trigger: ['blur', 'change'], }, ]" @input="(e) => (formInline.prjName = replaceCommonText(e))" /> </el-form-item> <el-form-item label="牵头单位:" prop="leadUnit" :rules="[ { validator: validateCommonText, trigger: ['blur', 'change'], }, ]" > <unitSelect v-model="formInline.leadUnit" /> </el-form-item> <el-form-item class="search_btn" style="float: right"> <el-button v-throttle="3000" type="primary" @click="onSubmit"> 查询 </el-button> <el-button v-throttle="3000" plain type="primary" @click="resetForm"> 重置 </el-button> </el-form-item> </el-form> <el-table ref="multipleTable" border class="dialog-table" :data="tableData" highlight-current-row stripe @row-click="onSelect" @select-all="onSelectAll" @selection-change="selectItem" > <el-table-column width="55"> <template #default="{ row }"> <el-radio v-model="templateSelete" :label="row.id">{
{ '' }}</el-radio> </template> </el-table-column> <el-table-column label="项目名称" prop="prjName" /> <el-table-column label="牵头单位" prop="leadUnitName" /> <el-table-column label="项目负责人" prop="prjHeadName" /> <el-table-column label="经费分配"> <template #default="scope"> <el-input v-if="scope.row.editType" v-model="scope.row.fee" maxlength="100" @click="selectFunds(scope.$index, scope.row)" @input="(e) => (scope.row.fee = replaceCommonText(e))" /> <div v-else class="contain"> <p v-for="item in scope.row.yunitList" :key="item"> {
{ item.bearUnitName }}:{
{ item.payIn }} </p> </div> </template> </el-table-column> <el-table-column label="项目标签"> <template #default="{ row }"> <div v-if="!row.isEdit"> <span v-for="(item, index) in row.labelVOList" :key="item"> {
{ item.labelName }} <!-- 最后一个标签尾部没有逗号 --> <span v-if="index !== row.labelVOList.length - 1">,</span> </span> </div> <el-select v-else v-model="row.labelVOListV2" multiple placeholder="请选择" @change="selectChange" > <el-option v-for="item in option" :key="item.id" :label="item.labelName" :value="item.id" /> </el-select> </template> </el-table-column> </el-table> <el-pagination background :current-page="page.currentPage" layout="total,size,prev,pager,next,jumper" :page-size="page.pageSize" :total="page.total" @current-change="hanleCurrentChange" /> <template #footer> <div class="dialog-footer"> <el-button type="primary" @click="submitDialog">确定</el-button> <el-button plain type="primary" @click="cancelDialog">取消</el-button> </div> </template> </el-dialog> </template> <script setup> import { projectData, feasStuPage } from "@/api/project/couny"; import unitSelect from '@src/components/unitSelect' import { validateCommonText, replaceCommonText } from '@src/utils/validate' const multipleTable = ref(null) const formRef = ref(null) const multipleSelection = ref() const props = defineProps({ dialogVisible: { default: null, type: Boolean, }, selected: { default: '', type: String, }, dataType: { default: null, type: String, }, prjData: { default: null, type: Object, }, prjCategory: { default: null, type: Number, }, requestUrl: { default: null, type: Function, }, }) const { dataType, prjCategory, requestUrl } = toRefs(props) const emit = defineEmits([ 'update:dialogVisible', 'update:prjData', 'emit-select', ]) const dialogVisible = computed({ get: () => props.dialogVisible, set: (val) => emit('update:dialogVisible', val), }) const page = reactive({ pageSize: 10, currentPage: 1, total: 0, }) //const templateSelete = ref('') const templateSelete = ref(props.selected) const tableData = ref([]) //查询 const formInline = ref({ prjName: '', techFieldName: '', leadUnit: '', }) if (dialogVisible) { formInline.value = { prjName: '', techFieldName: '', leadUnit: '', } } //重置 const resetForm = () => { // if (!formEl) return formRef.value.resetFields() onLoad() } const onSubmit = async () => { page.currentPage = 1 onLoad() } const hanleCurrentChange = (val) => { page.currentPage = val onLoad() } const onLoad = async () => { const formData = { size: page.pageSize, current: page.currentPage, prjCategory: prjCategory.value, ...formInline.value, state: '4', } const loadingInstance = ElLoading.service({ lock: true, text: 'Loading', background: 'rgba(0, 0, 0, 0.7)', }) if (requestUrl.value) { await requestUrl .value(formData) .then((res) => { tableData.value = res.data.data page.pageSize = res.data.pageSize page.total = Number(res.data.total) page.currentPage = res.data.pageNumber loadingInstance.close() }) .catch(() => { loadingInstance.close() }) } else if (prjCategory.value == 100) { formData.processState = '4' formData.leadUnitId = formData.leadUnit await feasStuPage(formData) .then((res) => { res.data.records.forEach((el) => { el.leadUnitName = el.leadUnitId el.prjHeadName = el.headName }) tableData.value = res.data.records page.pageSize = res.data.pageSize page.total = res.data.total page.currentPage = res.data.pageNumber loadingInstance.close() }) .catch(() => { loadingInstance.close() }) } else { await projectData(formData) .then((res) => { tableData.value = res.data.records page.pageSize = res.data.pageSize page.total = res.data.total page.currentPage = res.data.pageNumber loadingInstance.close() tableData.value.forEach((el) => { if(el.prjCode == props.selected){ templateSelete.value = el.id multipleTable.value = [] multipleTable.value.push(el) } }) }) .catch(() => { loadingInstance.close() }) } } onLoad() const onSelectAll = () => { multipleTable.value.clearSelection() } //下拉 const selectChange = (val) => { console.log('val', val) } const selectItem = (rows) => { if (rows.length > 1) { const newRows = rows.filter((it, index) => { if (index === rows.length - 1) { multipleTable.value.toggleRowSelection(it, true) return true } else { multipleTable.value.toggleRowSelection(it, false) return false } }) multipleSelection.value = newRows } else { multipleSelection.value = rows } } const onSelect = (row) => { templateSelete.value = row.id multipleTable.value.clearSelection() multipleTable.value.toggleRowSelection(row, true) multipleSelection.value = [] multipleSelection.value.push(row) } const cancelDialog = () => { emit('update:dialogVisible', false) } const submitDialog = async () => { if (multipleSelection.value) { multipleSelection.value[0].prjId = multipleSelection.value[0].id emit('update:prjData', multipleSelection.value[0]) emit('update:dialogVisible', false) emit('emit-select', multipleSelection.value) } else { ElMessage.error('请选择项目') } } </script> <style lang="scss" scoped> .dialog-project { height: 80vh; overflow-y: auto; } .dialog-footer { text-align: center; } .contain { height: 70px !important; overflow-y: auto !important; //表格内容超出高度滚动 p { line-height: 14px; } } </style>
主页接口
import request from '@src/utils/request' import {
sciencePostUrl } from '@/config' //项目中期项目选择列表 export const mediumExamSelectPrj = (data) => {
return request({
url: `${
sciencePostUrl}/mediumExam/selectPrj`, method: 'post', data, }) } //变更管理-项目-选择项目审核通过的 export const projectData = (data) => {
return request({
url: `${
sciencePostUrl}/prjChange/queryItem`, method: 'post', data, }) } //可研申报-项目-选择项目审核通过的 export const feasStuPage = (data) => {
return request({
url: `${
sciencePostUrl}/feasStu/feasStuPage`, method: 'post', data, }) }
表单校验
src\utils\validate.ts
/ * @description form表单特定字符校验 * @param value * @returns {boolean} */ export function validateCommonText(rule: any, value: any, callback: any) {
const err: any = validatorSpecialCharacter(value) if (err) {
callback(new Error(err.message)) return } callback() } // 禁止输入框特殊字符校验 export function replaceCommonText(e: any) {
const err: any = validatorSpecialCharacter(e) if (err) {
ElMessage({
message: err.message, type: 'warning', }) const y = e.replace(e, '') return y } else {
return e } }
3、下拉组件
src\components\unitSelect.vue
<!-- modelValue //select的值 code值 disabled //是否编辑 contrUnitName //回显是select的name 值 change-unit //回调方法: 参数为选择后单位相关的数据 labelCode //二级单位数据传对应labelCode orgcode //组织树下拉数据筛选条件 --> <template> <div style="width: 100%"> <el-select v-if="labelCode" v-model="unitValue" :disabled="disabled" filterable placeholder="请选择单位" @change="selectUnitEvent" > <el-option v-for="item in companyLabelData" :key="item.id" :label="item.orgObjMdmName" :value="item.id" /> </el-select> <el-select v-else-if="orgcode" v-model="unitValue" :disabled="disabled" filterable placeholder="请选择单位" @change="selectUnitEvent" > <el-option v-for="item in companyData" :key="item.id" :label="item.orgObjMdmName" :value="item.id" /> </el-select> <el-select v-else v-model="unitValue" clearable :disabled="disabled" filterable :loading="loading" placeholder="请搜索单位" remote :remote-method="remoteMethod" reserve-keyword @change="selectUnitEvent" > <template #prefix> <el-icon class="el-input__icon"><search /></el-icon> </template> <el-option v-for="item in companyData" :key="item.id" :label="item.orgObjMdmName" :value="item.id" /> </el-select> </div> </template> <script setup> import { getUnits, getLabelUnits } from '@src/api/common/base' import { Search } from '@element-plus/icons-vue' const props = defineProps({ modelValue: { default: null, type: Number, }, contrUnitName: { default: null, type: String, }, labelCode: { default: null, type: Array, }, disabled: { default: false, type: Boolean, }, orgcode: { default: '', type: String, }, }) const ruleForm = ref({ orgObjMdmNameLike: '', current: '1', size: 100, }) const { labelCode, disabled, orgcode } = toRefs(props) const emit = defineEmits(['update:modelValue', 'change-unit']) const companyData = ref() const companyLabelData = ref() onMounted(() => { watch( () => props.modelValue, (newVal) => { if (newVal) { nextTick(() => { if (props?.labelCode && !companyLabelData.value?.length) { getLabelUnitsList() } else if (props?.orgcode && !companyData.value?.length) { getUnitsList() } else if (!props.orgcode) { companyData.value = [ { orgObjMdmName: props.contrUnitName, id: props.modelValue, }, ] } }) } }, { immediate: true } ) }) //接口文档调取 const getUnitsList = async () => { ruleForm.value.porgObjCodeInner = orgcode.value const pattern = /[_]$/ if (!pattern.test(ruleForm.value.orgObjMdmNameLike)) { await getUnits(ruleForm.value).then((res) => { companyData.value = res.data.list }) } } const getLabelUnitsList = async () => { await getLabelUnits({ labelCode: labelCode.value }).then((res) => { companyLabelData.value = res.data }) } if (labelCode.value && labelCode.value.length) { getLabelUnitsList() } else if (orgcode.value && orgcode.value.length) { getUnitsList() } const unitValue = toRef(props, 'modelValue') const selectUnitEvent = (val) => { emit('update:modelValue', val) let obj if (labelCode.value && labelCode.value.length) { obj = val ? companyLabelData.value.find(function (item) { return item.id === val }) : { id: '', orgObjMdmName: '' } } else { obj = val ? companyData.value.find(function (item) { return item.id === val }) : { id: '', orgObjMdmName: '' } } emit('change-unit', obj) } //过滤筛选关键字数据 const loading = ref(false) const remoteMethod = (query) => { if (query) { ruleForm.value.orgObjMdmNameLike = query loading.value = true setTimeout(() => { loading.value = false getUnitsList() }, 200) } else { companyData.value = [] } } </script>
单位接口
src\api\common\base.js
import request from '@src/utils/request' //枚举值查询 process.env.VUE_APP_URL--> apiUrl const configInfo = sessionStorage.getItem('configInfo') || '{}' const apiUrl = JSON.parse(configInfo)?.baseApiUrl || 'http://27.86.34.99/kjapi' //模糊搜索单位下来数据 export const getUnits = (data) => {
return request({
url: `${
apiUrl}/srbm-bas-mdm-front/member/feignDataRel/org/page`, method: 'post', data, }) } //二级单位数据 export const getLabelUnits = (data) => {
return request({
url: `${
apiUrl}/srbm-bas-mdm-front/member/feignDataRel/org/search`, method: 'post', data, }) }
到此这篇vue3封装表格弹框组件——表格单选、axios动态接口、toRefs()用法、loading自定义、表格内容超出高度滚动的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/qdvuejs/10766.html