vue3子组件向父组件传值

javascript 复制代码
<template>
  <Dialog :title="dialogTitle" v-model="dialogVisible" width="1006px" class="dialogs">
    <el-form
      ref="formRef"
      :model="formData"
      :rules="formRules"
      label-width="100px"
      v-loading="formLoading"
    >
      <div style="padding: 8px 0; background: #f8fbff; margin-top: 10px">
       
        <el-row :gutter="24">
          <el-form-item label="学员姓名" prop="stsStudentName" class="student">
            <el-input v-model="formData.stsStudentName" placeholder="请输入学员姓名"  />
          </el-form-item>
          <el-form-item label="手机号" class="phone" prop="stsPhoneRealation">
            <el-input
              v-model="formData.stsPhone"
              placeholder="请输入手机号"
              class="input-with-select"
             
            >
              <template #prepend>
                <el-select
                  v-model="formData.stsPhoneRealation"
                  placeholder="家长"
                  style="width: 110px"
                >
                  <el-option
                    v-for="item in getStrDictOptions(DICT_TYPE.RELATIONSHIP)"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
              </template>
            </el-input>
          </el-form-item>
          <el-form-item label="当前年级" prop="stsSenior">
            <el-select v-model="formData.stsSenior" placeholder="请选择当前年级">
              <el-option
                v-for="dict in getStrDictOptions(DICT_TYPE.GRADE)"
                :key="dict.value"
                :label="dict.label"
                :value="dict.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="年龄" prop="stsAge">
            <el-input-number v-model="formData.stsAge" :step="2" />
          </el-form-item>
          <el-form-item label="性别" prop="stsSex">
            <el-select v-model="formData.stsSex" placeholder="请选择性别">
              <el-option
                v-for="dict in getStrDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
                :key="dict.value"
                :label="dict.label"
                :value="dict.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="出生日期" prop="stsBirthDate">
            <el-date-picker
              v-model="formData.stsBirthDate"
              type="date"
              format="YYYY-MM-DD"
              value-format="YYYY-MM-DD"
              placeholder="选择日期"
            />
          </el-form-item>
          <el-form-item label="备用手机号" class="stsAlterPhone" >
            <el-input
              v-model="formData.stsAlterPhone"
              placeholder="请输入手机号"
              class="input-with-select"
            >
              <template #prepend>
                <el-select
                  v-model="formData.stsAlterRealation"
                  placeholder="家长"
                  style="width: 110px"
                >
                  <el-option
                    v-for="item in getStrDictOptions(DICT_TYPE.RELATIONSHIP)"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
              </template>
            </el-input>
          </el-form-item>
        </el-row>
        <el-row :gutter="24">
        <el-form-item label="就读学校" prop="stsReadSchool">
          <el-input v-model="formData.stsReadSchool" placeholder="请输入就读学校" />
          </el-form-item>
          </el-row>
        <el-row :gutter="24">
            <el-form-item label="家庭住址" prop="stsHome" >
            <el-input v-model="formData.stsHome" placeholder="请输入家庭住址" />
          </el-form-item>
        </el-row>
      </div>
    </el-form>
    <template #footer>
      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
      <el-button @click="dialogVisible = false">取 消</el-button>
    </template>
  </Dialog>
</template>
<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { VisitManageApi, VisitManageVO,UserVO } from '@/api/sale/visitmanage'
import { useUserStore } from '@/store/modules/user'
import { InfoApi, InfoVO } from '@/api/study/info'
import * as UserApi from '@/api/system/user'
import { TotalStudentApi, TotalStudentVO } from '@/api/study/totalstudent'
const userStore = useUserStore()
/** 到访管理 表单 */
defineOptions({ name: 'VisitManageForm' })

const userList = ref<UserApi.UserVO[]>([]) // 用户列表

const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const formRules = reactive({
  stsStudentName: [{ required: true, message: '学员姓名不能为空', trigger: 'blur' }],
  stsPhoneRealation: [{ required: true, message: '关系不能为空', trigger: 'blur' }],
  stsPhone: [{ required: true, message: '手机号不能为空', trigger: 'blur' }],
  studentSource: [{ required: true, message: '学员来源不能为空', trigger: 'blur' }],
  intentionLevel: [{ required: true, message: '意向级别不能为空', trigger: 'blur' }],
  stsSenior: [{ required: true, message: '当前年级不能为空', trigger: 'blur' }],
  followUpType: [{ required: true, message: '跟进方式不能为空', trigger: 'blur' }]
})
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const formType = ref('') // 表单的类型:create - 新增;update - 修改
const formData = ref({
  id: undefined, // 主键id
  stsStudentName: undefined ,// 学员姓名
  stsAge: undefined, // 年龄
  stsSex: undefined, // 性别
  stsPhone: undefined ,// 手机号
  stsPhoneRealation: undefined , // 手机号关系
  stsBirthDate: undefined , // 出生日期
  stsSenior: undefined , // 当前年级
  stsSchool: undefined , // 就读学校
  stsAlterPhone: undefined , // 备用号码
  stsAlterRealation: undefined , // 备用号码关系
  stsHome: undefined , // 家庭地址
  stsWeixinStatus: undefined , // 绑定微信状态
  stsWeixinNumber: undefined , // 微信号
  stsReadClass: undefined , // 报读所在班级
  stsReadPhone: undefined , // 报读手机号
  stsReadSorce: undefined , // 报读课程
  stsDueDate: undefined , // 到期日期
  stsTeacher: undefined ,// 学管师
  stsPaySornumer: undefined , // 购买课程数量
  stsGiftSornum: undefined , // 赠送数量
  stsReturnNum: undefined , // 退转数量
  stsAttendClass: undefined , // 已上课数量
  stsSurplusNum: undefined , // 剩余数量
  stsAbsenceNum: undefined , // 缺课数量
  stsCanceldecimal: undefined , // 消课金额
  stsCorseRemain: undefined , // 剩余报课金额
  stsFollowPeople: undefined , // 跟进人
  stsFollowDate: undefined , // 跟进日期
  stsFollowText: undefined , // 跟进内容
  stsMethod: undefined , // 跟进方式
  stsFollowPhase: undefined , // 跟进阶段
  stsFollowNextdate: undefined , // 下次跟进日期
  stsRollTime: undefined , // 点名时间
  stsReadSchool: undefined , // 就读校区
  stsStartClass: undefined , // 上课开始日期
  stsEndDate: undefined , // 上课结束日期
  stsClassTeacher: undefined , // 任课教师
  stsClassStatus: undefined , // 到课状态
  stsMakeState: undefined , // 补课状态
 
 
})

const formRef = ref() // 表单 Ref


/** 打开弹窗 */
const open = async (type: string, id?: number) => {
  dialogVisible.value = true
  dialogTitle.value = t('action.' + type)
  formType.value = type
  resetForm()
  userList.value = await UserApi.getSimpleUserList()
  // 修改时,设置数据
  if (id) {
    formLoading.value = true
    try {
      formData.value = await VisitManageApi.getVisitManage(id)
    } finally {
      formLoading.value = false
    }
  }
  
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗

/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
  // 校验表单
  await formRef.value.validate()
  // 提交请求
  formLoading.value = true
  try {
    const data = formData.value as unknown as TotalStudentVO
    const studentId =   await TotalStudentApi.createTotalStudent(data)
      message.success(t('common.createSuccess'))
 // 发送操作成功的事件
    emit('success',studentId)

    dialogVisible.value = false
   
    console.log('studentId',studentId)
  } finally {
    formLoading.value = false
  }
}
/** 重置表单 */
const resetForm = () => {
  formData.value = {
    id: undefined, // 主键id
  stsStudentName: undefined ,// 学员姓名
  stsAge: undefined, // 年龄
  stsSex: undefined, // 性别
  stsPhone: undefined ,// 手机号
  stsPhoneRealation: undefined , // 手机号关系
  stsBirthDate: undefined , // 出生日期
  stsSenior: undefined , // 当前年级
  stsSchool: undefined , // 就读学校
  stsAlterPhone: undefined , // 备用号码
  stsAlterRealation: undefined , // 备用号码关系
  stsHome: undefined , // 家庭地址
  stsWeixinStatus: undefined , // 绑定微信状态
  stsWeixinNumber: undefined , // 微信号
  stsReadClass: undefined , // 报读所在班级
  stsReadPhone: undefined , // 报读手机号
  stsReadSorce: undefined , // 报读课程
  stsDueDate: undefined , // 到期日期
  stsTeacher: undefined ,// 学管师
  stsPaySornumer: undefined , // 购买课程数量
  stsGiftSornum: undefined , // 赠送数量
  stsReturnNum: undefined , // 退转数量
  stsAttendClass: undefined , // 已上课数量
  stsSurplusNum: undefined , // 剩余数量
  stsAbsenceNum: undefined , // 缺课数量
  stsCanceldecimal: undefined , // 消课金额
  stsCorseRemain: undefined , // 剩余报课金额
  stsFollowPeople: undefined , // 跟进人
  stsFollowDate: undefined , // 跟进日期
  stsFollowText: undefined , // 跟进内容
  stsMethod: undefined , // 跟进方式
  stsFollowPhase: undefined , // 跟进阶段
  stsFollowNextdate: undefined , // 下次跟进日期
  stsRollTime: undefined , // 点名时间
  stsReadSchool: undefined , // 就读校区
  stsStartClass: undefined , // 上课开始日期
  stsEndDate: undefined , // 上课结束日期
  stsClassTeacher: undefined , // 任课教师
  stsClassStatus: undefined , // 到课状态
  stsMakeState: undefined , // 补课状态
  }
  formRef.value?.resetFields()
}
</script>
<style scoped>
:deep(.input-textarea) {
  width: 950px !important;
}
.el-form-item {
  width: 47%;
}
:deep(.el-form-item__label) {
  width: 130px !important;
}
.bold {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #85afd5;
  text-align: center;
  margin-top: 5px;
  margin-left: -10px;
  color: #fff;
}
.btitle {
  line-height: 30px;
  margin-left: 10px;
  color: #84b0d5;
}
.tip {
  border: 1px solid #84b0d5;
  border-radius: 0 20px 20px 0;
  width: 140px;
  height: 30px;
  display: flex;
  margin-left: 30px;
  margin-bottom: 20px;
}
:deep(.el-input) {
  width: 100%;
}
:deep(.el-select) {
  width: 100%;
}
:deep(.el-select) {
  --el-select-width: 80%;
}
</style>

const emit = defineEmits(['success']) // 定义 success 事件,你也可以定义成别的名字,这里我定义为success;用于操作成功后的回调

emit('success',studentId),需要把你定义的事件名发射给父组件,还有你需要传的值,这里我需要传studentId;

javascript 复制代码
<template>
  <Dialog :title="dialogTitle" v-model="dialogVisible" width="1006px" class="dialogs">
    <el-form
      ref="formRef"
      :model="formData"
      :rules="formRules"
      label-width="100px"
      v-loading="formLoading"
    >
      <div style="padding: 8px 0; background: #f8fbff; margin-top: 10px">
        <div class="tip">
          <div class="bold">1</div>
          <span class="btitle">基本信息</span>
        </div>
        <el-row :gutter="24">
          <el-col :span="18">
            <el-form-item label="学员姓名" prop="studentId" class="sname">
              <el-select
                v-model="formData.studentId"
                filterable
                remote
                reserve-keyword
                placeholder="请输入学员姓名或手机号"
                :remote-method="remoteMethod"
                :loading="stuAllLoading"
                @change="findStudentSource"
              >
                <el-option
                  v-for="item in studentList"
                  :key="item.id"
                  :label="item.stsStudentName"
                  :value="item.id"
                >
                  <span style="float: left">{{ item.stsStudentName }}</span>
                  <span style="float: left; margin-left: 5px"
                    ><el-tag size="small">{{
                      getDictLabel(DICT_TYPE.STUDENT_STATUS, item.studentStatus)
                    }}</el-tag></span
                  >
                  <span style="float: right; color: #8492a6; font-size: 13px">{{
                    item.stsPhone
                  }}</span>
                </el-option>
              </el-select>
              <span
                style="
                  margin-left: 10px;
                  float: left;
                  color: #8492a6;
                  font-size: 13px;
                  display: flex;
                  width: 500px;
                "
                >学员未找到?去<el-button
                  type="primary"
                  plain
                  @click="openForm('create')"
                  v-hasPermi="['sale:visit-manage:create']"
                  link
                >
                  新增学员
                </el-button>
              </span>
            </el-form-item>
          </el-col>
        </el-row>
      </div>
      <div style="padding: 8px 0; background: #f8fbff; margin-top: 10px">
        <div class="tip">
          <div class="bold">2</div>
          <span class="btitle">到访记录</span>
        </div>
        <el-row :gutter="24">
          <el-form-item label="渠道" prop="studentSource">
            <el-select v-model="formData.studentSource" placeholder="请选择渠道">
              <el-option
                v-for="dict in getStrDictOptions(DICT_TYPE.SOURCE_STUDENT)"
                :key="dict.value"
                :label="dict.label"
                :value="dict.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="到访时间" prop="visitTime">
            <el-date-picker
              v-model="formData.visitTime"
              type="datetime"
              format="YYYY/MM/DD hh:mm"
              value-format="x"
              placeholder="选择到访时间"
            />
          </el-form-item>
          <!-- <el-form-item label="接待人员" prop="receptionPerson">
            <el-select v-model="formData.receptionPerson" placeholder="请选择跟进人">
              <el-option
                v-for="dict in userList"
                :key="dict.id"
                :label="dict.nickname"
                :value="dict.id"
              />
            </el-select>
          </el-form-item> -->
          <el-form-item label="是否试听" prop="listenStatus">
            <el-select v-model="formData.listenStatus" placeholder="请选择是否试听">
              <el-option
                v-for="dict in getStrDictOptions(DICT_TYPE.AUDITION_OR_NOT)"
                :key="dict.value"
                :label="dict.label"
                :value="dict.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="是否签约" prop="signUpStatus">
            <el-select v-model="formData.signUpStatus" placeholder="请选择是否签约">
              <el-option
                v-for="dict in getStrDictOptions(DICT_TYPE.SIGN_OR_NOT)"
                :key="dict.value"
                :label="dict.label"
                :value="dict.value"
              />
            </el-select>
          </el-form-item>
        </el-row>
        <el-row :gutter="24">
          <el-form-item label="备注" prop="remark" class="input-textarea">
            <el-input
              v-model="formData.remark"
              :rows="3"
              type="textarea"
              placeholder="请输入备注"
            />
          </el-form-item>
        </el-row>
      </div>
    </el-form>
    <template #footer>
      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
      <el-button @click="dialogVisible = false">取 消</el-button>
    </template>
  </Dialog>
  <!-- 表单弹窗:添加/修改 -->
  <VisitManageForm2 @success="handleSuccess" ref="formRef2" />
</template>
<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE, getDictLabel } from '@/utils/dict'
import { VisitManageApi, VisitManageVO } from '@/api/sale/visitmanage'
import { useUserStore } from '@/store/modules/user'
import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
import * as UserApi from '@/api/system/user'
import VisitManageForm2 from './VisitManageForm2.vue'
import { TotalStudentApi, TotalStudentVO } from '@/api/study/totalstudent'
const studentList = ref<TotalStudentVO[]>([]) // 学生列表
const userStore = useUserStore()
/** 到访管理 表单 */
defineOptions({ name: 'VisitManageForm' })
const stuAllLoading = ref(false) // 输入学员关键词加载
const userList = ref<UserApi.UserVO[]>([]) // 用户列表

const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const formRules = reactive({
  studentId: [{ required: true, message: '学员姓名不能为空', trigger: 'blur' }],
  studentSource: [{ required: true, message: '渠道不能为空', trigger: 'blur' }],
})
const handleSuccess = async (e: any) => {
  formData.value.studentId = e
  const dataStudent =  await TotalStudentApi.getTotalStudent(e)
  studentList.value = [dataStudent]

}
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const formType = ref('') // 表单的类型:create - 新增;update - 修改
const formData = ref({
  id: undefined,
  visitTime: undefined,
  receptionPerson: userStore.user.id,
  intentionLevel: undefined,
  listenStatus: undefined,
  signUpStatus: undefined,
  visitTimeBegin: undefined,
  visitTimeEnd: undefined,
  remark: undefined,
  studentId: undefined,
  studentSource: undefined
})

const formRef = ref() // 表单 Ref
const formRef2 = ref()

/** 添加/修改操作 */
const openForm = (type: string, id?: number) => {
  formRef2.value.open(type, id)
}
const findStudentSource = async (event) => {
  const data = await VisitManageApi.getVisitManageByStudentId(event)
  formData.value.studentSource = String(data)
}
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
  remoteMethod('')
  dialogVisible.value = true
  dialogTitle.value = t('action.' + type)
  formType.value = type
  resetForm()
  userList.value = await UserApi.getSimpleUserList()
  // 修改时,设置数据
  if (id) {
    formLoading.value = true
    try {
      formData.value = await VisitManageApi.getVisitManage(id)
    } finally {
      formLoading.value = false
    }
  }
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗

/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
  // 校验表单
  await formRef.value.validate()
  // 提交请求
  formLoading.value = true
  try {
    const data = formData.value as unknown as VisitManageVO
    if (formType.value === 'create') {
      await VisitManageApi.createVisitManage(data)
      message.success(t('common.createSuccess'))
    } else {
      await VisitManageApi.updateVisitManage(data)
      message.success(t('common.updateSuccess'))
    }
    dialogVisible.value = false
    // 发送操作成功的事件
    emit('success')
  } finally {
    formLoading.value = false
  }
}

/** 重置表单 */
const resetForm = () => {
  formData.value = {
    id: undefined,
    visitTime: undefined,
    receptionPerson: userStore.user.id,
    intentionLevel: undefined,
    listenStatus: undefined,
    signUpStatus: undefined,
    visitTimeBegin: undefined,
    visitTimeEnd: undefined,
    remark: undefined,
    studentId: undefined,
    studentSource: undefined
  }
  formRef.value?.resetFields()
}
const remoteMethod = async (query) => {
  stuAllLoading.value = true
  studentList.value = []
  stuAllLoading.value = false
  studentList.value = await TotalStudentApi.getSimpleUserList(query)
}
</script>
<style scoped>
:deep(.input-textarea) {
  width: 950px !important;
}
.el-form-item {
  width: 47%;
}
:deep(.el-form-item__label) {
  width: 130px !important;
}
.bold {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #85afd5;
  text-align: center;
  margin-top: 5px;
  margin-left: -10px;
  color: #fff;
}
.btitle {
  line-height: 30px;
  margin-left: 10px;
  color: #84b0d5;
}
.tip {
  border: 1px solid #84b0d5;
  border-radius: 0 20px 20px 0;
  width: 140px;
  height: 30px;
  display: flex;
  margin-left: 30px;
  margin-bottom: 20px;
}
:deep(.el-input) {
  width: 100%;
}
:deep(.el-select) {
  width: 100%;
}
:deep(.el-select) {
  --el-select-width: 80%;
}
:deep(.sname) {
  width: 100% !important;
}
:deep(.sname .el-form-item__content) {
  flex-wrap: nowrap;
}
</style>

<!-- 表单弹窗:添加/修改 -->

在这里接受子组件传来的值

<VisitManageForm2 @success="handleSuccess" ref="formRef2" />

这里接受到子组件传来的值可以做数据处理:

const handleSuccess = async (e: any) => {

formData.value.studentId = e

const dataStudent = await TotalStudentApi.getTotalStudent(e)

studentList.value = [dataStudent]

}

相关推荐
醉の虾10 分钟前
Vue3 使用v-for 渲染列表数据后更新
前端·javascript·vue.js
张小小大智慧18 分钟前
TypeScript 的发展与基本语法
前端·javascript·typescript
chusheng184032 分钟前
Java项目-基于SpringBoot+vue的租房网站设计与实现
java·vue.js·spring boot·租房·租房网站
游走于计算机中摆烂的1 小时前
启动前后端分离项目笔记
java·vue.js·笔记
幼儿园的小霸王1 小时前
通过socket设置版本更新提示
前端·vue.js·webpack·typescript·前端框架·anti-design-vue
疯狂的沙粒1 小时前
对 TypeScript 中高级类型的理解?应该在哪些方面可以更好的使用!
前端·javascript·typescript
码蜂窝编程官方2 小时前
【含开题报告+文档+PPT+源码】基于SpringBoot+Vue的虎鲸旅游攻略网的设计与实现
java·vue.js·spring boot·后端·spring·旅游
旭日猎鹰2 小时前
Flutter踩坑记录(二)-- GestureDetector+Expanded点击无效果
前端·javascript·flutter
乐闻x3 小时前
Vue.js 性能优化指南:掌握 keep-alive 的使用技巧
前端·vue.js·性能优化
一条晒干的咸魚3 小时前
【Web前端】创建我的第一个 Web 表单
服务器·前端·javascript·json·对象·表单