vue3中,父子组件props传函数写法-传动态接口 & 特殊字符校验 & 封装公共input组件

vue3中,父子组件props传函数写法-传动态接口 & 特殊字符校验 & 封装公共input组件

效果

在这里插入图片描述

代码
1、主页面

index.vue

<template>
  <div>
    <el-form ref="formRef" label-width="132px" :model="formInline">
      <el-form-item
        label="项目名称:"
        :rules="[
          {
            validator: validateCommonText,
            trigger: ['blur', 'change'],
          },
        ]"
      >
        <el-input
          v-model="formInline.prjName"
          :disabled="route.query.type === 'edit' || route.query.type === 'view'"
          maxlength="100"
          placeholder="请选择项目"
          @click="handlePrjName"
        >
          <template #prefix>
            <el-icon class="el-input__icon"><search /></el-icon>
          </template>
        </el-input>
      </el-form-item>
    </el-form>
    <SelectProject
      v-model:dataType="dataType"
      v-model:dialogVisible="dialogProject"
      v-model:prjData="formInline"
      :prj-category="1"
      :request-url="queryPrjNoPlan"
    />
  </div>
</template>
<script setup>
  import { queryPrjNoPlan } from "@/api/process/maven";
  import SelectProject from "@/components/SelectProject";
  import { validateCommonText } from "@src/utils/validate";
  const router = useRouter();
  const route = useRoute();
  const formRef = ref();
  const dataType = ref("project");
  const formInline = ref({
    prjName: "",
  });
  const dialogProject = ref(false);
  const handlePrjName = () => {
    dialogProject.value = true;
  };
</script>
接口文件

src\app\science\api\process\maven.js

import request from '@src/utils/request'
import { sciencePostUrl } from '@/config'

//选择项目
export const queryPrjNoPlan = (data) => {
  return request({
    url: `${sciencePostUrl}/supvis/queryPrjNoPlan`,
    method: 'post',
    data,
  })
}
方法文件

src\utils\validate.ts

/**
 * @description form表单特定字符校验
 * @param value
 * @returns {boolean}
 */
export function validateCommonText(rule: any, value: any, callback: any) {
  const noChars = "[`~!#$^&*\"()=|{}': ; ',\\[\\].<>/?~!#¥……&*()——|{}【】‘;:”“'。,、?]‘'@ /%"
  const v = value || ''

  for (let i = 0; i < noChars.length; i++) {
    const char = noChars[i]
    if (v.indexOf(char) != -1) {
      // callback(new Error('不能使用字符:' + noChars))
      callback(new Error('不能使用特殊字符'))
      return
    }
  }
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"
        :rules="[
          {
            validator: validateCommonText,
            trigger: ['blur', 'change'],
          },
        ]"
      >
        <el-input
          v-model="formInline.prjName"
          maxlength="100"
          placeholder="请输入"
        />
      </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 type="primary" @click="onSubmit">查询</el-button>
        <el-button plain type="primary" @click="resetForm">重置</el-button>
      </el-form-item>
    </el-form>
    <el-table
      ref="multipleTable"
      :data="tableData"
      highlight-current-row
      @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>
    <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>
      <span class="dialog-footer">
        <el-button plain type="primary" @click="cancelDialog">取消</el-button>
        <el-button type="primary" @click="submitDialog">确定</el-button>
      </span>
    </template>
  </el-dialog>
</template>
<script setup>
  import { projectData, feasStuPage } from '@/api/projectChange/index'
  import unitSelect from '@src/components/unitSelect'
  import { validateCommonText } from '@src/utils/validate'

  const multipleTable = ref(null)
  const formRef = ref(null)
  const multipleSelection = ref()

  const props = defineProps({
    dialogVisible: {
      default: null,
      type: Boolean,
    },
    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 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',
    }

    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
      })
    } 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
      })
    } 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
      })
    }
  }

  onLoad()
  const onSelectAll = () => {
    multipleTable.value.clearSelection()
  }

  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></style>
接口文件

src\app\science\api\projectChange\index.js

import request from '@src/utils/request'
import { sciencePostUrl } from '@/config'

//变更管理-项目-选择项目审核通过的
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,
  })
}
3、子组件界面

src\components\unitSelect.vuesrc\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.orgObjCode"
      />
    </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.orgObjCode"
      />
    </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.orgObjCode"
      />
    </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,
                  orgObjCode: 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.orgObjCode === val
          })
        : { orgObjCode: '', orgObjMdmName: '' }
    } else {
      obj = val
        ? companyData.value.find(function (item) {
            return item.orgObjCode === val
          })
        : { orgObjCode: '', 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.76.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,
  })
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值