Files
school-developer/src/views/basic/basicstudent/components/StudentDetail.vue
yaojian c611c3e720 1
2026-03-13 11:41:26 +08:00

1172 lines
43 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-dialog title="学生详情" v-model="visible" :close-on-click-modal="false" draggable width="1200px" top="5vh">
<div v-loading="loading" class="student-detail-container">
<!-- 左侧导航 -->
<div class="detail-sidebar">
<el-menu :default-active="activeTab" @select="handleMenuSelect">
<el-menu-item index="basic">
<el-icon><User /></el-icon>
<span>基本信息</span>
</el-menu-item>
<el-menu-item index="education">
<el-icon><School /></el-icon>
<span>教育经历</span>
</el-menu-item>
<el-menu-item index="family">
<el-icon><HomeFilled /></el-icon>
<span>家庭信息</span>
</el-menu-item>
<el-menu-item index="major">
<el-icon><Briefcase /></el-icon>
<span>专业信息</span>
</el-menu-item>
<el-menu-item index="class">
<el-icon><Grid /></el-icon>
<span>班级信息</span>
</el-menu-item>
<el-menu-item index="adult">
<el-icon><Document /></el-icon>
<span>成教信息</span>
</el-menu-item>
</el-menu>
</div>
<!-- 右侧内容 -->
<div class="detail-content">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="140px">
<!-- 基本信息 -->
<div v-show="activeTab === 'basic'" class="detail-panel">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="姓名" prop="realName" :rules="formRules.realName">
<el-input v-model="formData.realName" placeholder="请输入姓名" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="曾用名" prop="oldName">
<el-input v-model="basicInfo.oldName" placeholder="请输入曾用名" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="性别" prop="gender" :rules="formRules.gender">
<el-select v-model="formData.gender" placeholder="请选择性别" clearable style="width: 100%">
<el-option label="男" value="1" />
<el-option label="女" value="0" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="身份证号" prop="idCard" :rules="formRules.idCard">
<el-input v-model="basicInfo.idCard" placeholder="请输入身份证号" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="出生日期" prop="birthday" :rules="formRules.birthday">
<el-date-picker
v-model="basicInfo.birthday"
type="date"
placeholder="请选择出生日期"
value-format="YYYY-MM-DD HH:mm:ss"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="民族" prop="national" :rules="formRules.national">
<el-select v-model="basicInfo.national" placeholder="请选择民族" filterable clearable style="width: 100%">
<el-option v-for="item in nationalList" :key="item.nationCode" :label="item.nationName" :value="item.nationCode" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="政治面貌" prop="politicsStatus" :rules="formRules.politicsStatus">
<el-select v-model="basicInfo.politicsStatus" placeholder="请选择政治面貌" clearable style="width: 100%">
<el-option v-for="item in politicsStatusList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="籍贯" prop="householdAddress" :rules="formRules.householdAddress">
<el-input v-model="formData.householdAddress" placeholder="请输入籍贯" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="本人电话" prop="phone" :rules="formRules.phone">
<el-input v-model="basicInfo.phone" placeholder="请输入本人电话" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="电子邮箱" prop="email">
<el-input v-model="basicInfo.email" placeholder="请输入电子邮箱" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="QQ号/微信号" prop="qq">
<el-input v-model="basicInfo.qq" placeholder="请输入QQ号/微信号" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="退伍军人" prop="veteran" :rules="formRules.veteran">
<el-select v-model="basicInfo.veteran" placeholder="请选择" clearable style="width: 100%">
<el-option v-for="item in veteranStatusList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="辨色力" prop="colourSense">
<el-select v-model="basicInfo.colourSense" placeholder="请选择辨色力" clearable style="width: 100%">
<el-option v-for="item in eyeStatusList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="裸眼视力(左)" prop="eyeLeft">
<el-input v-model="basicInfo.eyeLeft" placeholder="请输入" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="裸眼视力(右)" prop="eyeRight">
<el-input v-model="basicInfo.eyeRight" placeholder="请输入" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="身高(cm)" prop="height">
<el-input-number v-model="basicInfo.height" :min="0" :max="300" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="体重(kg)" prop="weight">
<el-input-number v-model="basicInfo.weight" :min="0" :max="300" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="既往病史" prop="seekText">
<el-input v-model="basicInfo.seekText" placeholder="请输入既往病史" clearable />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="本人特长" prop="advantage">
<el-input v-model="basicInfo.advantage" type="textarea" :rows="2" placeholder="请输入本人特长" />
</el-form-item>
</el-col>
</el-row>
</div>
<!-- 教育经历 -->
<div v-show="activeTab === 'education'" class="detail-panel">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="入学前文化程度" prop="education" :rules="formRules.education">
<el-select v-model="educationInfo.education" placeholder="请选择" clearable style="width: 100%">
<el-option v-for="item in preSchoolEducationList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="中考分数" prop="examScore">
<el-input-number v-model="educationInfo.examScore" :min="0" :max="1000" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="中考准考证号" prop="examNo">
<el-input v-model="educationInfo.examNo" placeholder="请输入中考准考证号" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="本校借读学年" prop="temporaryyeYear">
<el-input v-model="educationInfo.temporaryyeYear" placeholder="请输入" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="入学前毕业学校" prop="schoolName">
<el-input v-model="educationInfo.schoolName" placeholder="请输入入学前毕业学校" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="毕业学校省市" prop="schoolProvince">
<el-select v-model="educationInfo.schoolProvince" placeholder="请选择" clearable filterable style="width: 100%">
<el-option v-for="item in schoolProvinceList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="曾任职务" prop="position">
<el-input v-model="educationInfo.position" type="textarea" :rows="2" placeholder="请输入曾任职务" />
</el-form-item>
</el-col>
</el-row>
</div>
<!-- 家庭信息 -->
<div v-show="activeTab === 'family'" class="detail-panel">
<el-divider content-position="left">家庭基本信息</el-divider>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="户口详细地址" prop="householdAddress" :rules="formRules.homeHouseholdAddress">
<el-input v-model="homeInfo.householdAddress" placeholder="请输入户口详细地址" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="户口性质" prop="householdProperties" :rules="formRules.householdProperties">
<el-select v-model="homeInfo.householdProperties" placeholder="请选择" clearable style="width: 100%">
<el-option v-for="item in householdPropertiesList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="是否租住" prop="isTemp" :rules="formRules.isTemp">
<el-select v-model="homeInfo.isTemp" placeholder="请选择" clearable style="width: 100%">
<el-option v-for="item in isTempList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="居住详细地址" prop="liveAddress" :rules="formRules.liveAddress">
<el-input v-model="homeInfo.liveAddress" placeholder="请输入居住详细地址" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="家庭主要收入来源" prop="incomeSource" :rules="formRules.incomeSource">
<el-select v-model="homeInfo.incomeSource" placeholder="请选择" clearable style="width: 100%">
<el-option v-for="item in incomeSourceList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="家庭年收入(万)" prop="incomeMoney" :rules="formRules.incomeMoney">
<el-input-number v-model="homeInfo.incomeMoney" :min="0" :precision="2" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="家庭人均收入(万)" prop="incomePerMoney" :rules="formRules.incomePerMoney">
<el-input-number v-model="homeInfo.incomePerMoney" :min="0" :precision="2" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="是否低保" prop="homeDifficulty" :rules="formRules.homeDifficulty">
<el-select v-model="homeInfo.homeDifficulty" placeholder="请选择" clearable style="width: 100%">
<el-option v-for="item in homeDifficultyList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="共同居住人" prop="livewith">
<el-input v-model="homeInfo.livewith" placeholder="请输入" clearable />
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">
家庭成员列表
<el-button type="primary" size="small" icon="Plus" @click="handleAddFamilyMember" style="margin-left: 10px">新增成员</el-button>
</el-divider>
<el-table :data="homeDetailList" border style="width: 100%" max-height="300">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="appellation" label="关系" width="140">
<template #default="scope">
<el-select v-model="scope.row.appellation" placeholder="请选择关系" size="small" style="width: 100%">
<el-option v-for="item in familyMemberTypeList" :key="item.value" :label="item.label" :value="item.label" />
</el-select>
</template>
</el-table-column>
<el-table-column prop="realName" label="姓名" width="100">
<template #default="scope">
<el-input v-model="scope.row.realName" placeholder="姓名" size="small" />
</template>
</el-table-column>
<el-table-column prop="tel" label="手机号" width="130">
<template #default="scope">
<el-input v-model="scope.row.tel" placeholder="手机号" size="small" />
</template>
</el-table-column>
<el-table-column prop="idCard" label="身份证号" width="180">
<template #default="scope">
<el-input v-model="scope.row.idCard" placeholder="身份证号" size="small" />
</template>
</el-table-column>
<el-table-column prop="workAddress" label="工作单位" min-width="150">
<template #default="scope">
<el-input v-model="scope.row.workAddress" placeholder="工作单位" size="small" />
</template>
</el-table-column>
<el-table-column prop="politicsStatus" label="政治面貌" width="120">
<template #default="scope">
<el-select v-model="scope.row.politicsStatus" placeholder="政治面貌" size="small" style="width: 100%">
<el-option v-for="item in politicalFamilyList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</template>
</el-table-column>
<el-table-column prop="health" label="身体状况" width="100">
<template #default="scope">
<el-input v-model="scope.row.health" placeholder="身体状况" size="small" />
</template>
</el-table-column>
<el-table-column label="操作" width="140" align="center" fixed="right">
<template #default="scope">
<el-button link type="primary" icon="Check" @click="handleSaveFamilyMember(scope.row, scope.$index)" :loading="scope.row._saving">保存</el-button>
<el-button link type="danger" icon="Delete" @click="handleDeleteFamilyMember(scope.$index)" />
</template>
</el-table-column>
</el-table>
<div v-if="homeDetailList.length === 0" class="empty-tip">暂无家庭成员信息点击上方按钮新增</div>
</div>
<!-- 专业信息 -->
<div v-show="activeTab === 'major'" class="detail-panel">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="入学日期" prop="enterDate">
<el-date-picker v-model="majorInfo.enterDate" type="date" placeholder="请选择入学日期" value-format="YYYY-MM-DD HH:mm:ss" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="学院">
<el-input v-model="formData.deptName" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="专业名称">
<el-input v-model="formData.majorName" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="学号">
<el-input v-model="formData.stuNo" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="学籍号" prop="schoolRollNumber">
<el-input v-model="majorInfo.schoolRollNumber" placeholder="请输入学籍号" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="学籍" prop="schoolRoll">
<el-input v-model="majorInfo.schoolRoll" placeholder="请输入学籍" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="状态" prop="studentStatus">
<el-select v-model="majorInfo.studentStatus" placeholder="请选择状态" clearable style="width: 100%">
<el-option v-for="item in studentStatusList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="培养层次" prop="majorLevel">
<el-select v-model="majorInfo.majorLevel" placeholder="请选择培养层次" clearable style="width: 100%">
<el-option v-for="item in majorLevelList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="学制" prop="majorYears">
<el-input v-model="majorInfo.majorYears" placeholder="请输入学制" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="学习形式" prop="studyType">
<el-input v-model="majorInfo.studyType" placeholder="请输入学习形式" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="联院学号" prop="unionStuNo">
<el-input v-model="majorInfo.unionStuNo" placeholder="请输入联院学号" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="中技证号" prop="middleNumber">
<el-input v-model="majorInfo.middleNumber" placeholder="请输入中技证号" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="中技段结束时间" prop="middleTime">
<el-date-picker v-model="majorInfo.middleTime" type="date" placeholder="请选择" value-format="YYYY-MM-DD" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="高技证号" prop="highNumber">
<el-input v-model="majorInfo.highNumber" placeholder="请输入高技证号" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="高技段结束时间" prop="highTime">
<el-date-picker v-model="majorInfo.highTime" type="date" placeholder="请选择" value-format="YYYY-MM-DD" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="技师证号" prop="technicianNumber">
<el-input v-model="majorInfo.technicianNumber" placeholder="请输入技师证号" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="毕业证号" prop="graduateNumber">
<el-input v-model="formData.graduateNumber" placeholder="请输入毕业证号" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="毕业时间" prop="graduateDate">
<el-date-picker v-model="majorInfo.graduateDate" type="date" placeholder="请选择毕业时间" value-format="YYYY-MM-DD" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="结业时间" prop="pauseDate">
<el-date-picker v-model="majorInfo.pauseDate" type="date" placeholder="请选择结业时间" value-format="YYYY-MM-DD" style="width: 100%" />
</el-form-item>
</el-col>
</el-row>
</div>
<!-- 班级信息 -->
<div v-show="activeTab === 'class'" class="detail-panel">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="班级名称">
<el-input v-model="formData.className" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="班号" prop="classNo">
<el-input v-model="majorInfo.classNo" placeholder="请输入班号" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="教室位置" prop="classRoomPosition">
<el-input v-model="majorInfo.classRoomPosition" placeholder="请输入教室位置" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="就读方式" prop="isRoomNo">
<el-input v-model="majorInfo.isRoomNo" placeholder="请输入就读方式" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="班主任">
<el-input :value="formData.teacherRealName || majorInfo.teacherRealName" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="班主任联系电话" prop="teacherTel">
<el-input v-model="majorInfo.teacherTel" placeholder="请输入班主任联系电话" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="宿舍号">
<el-input v-model="formData.roomNo" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="宿舍联系电话" prop="dormBuildingPhone">
<el-input v-model="majorInfo.dormBuildingPhone" placeholder="请输入宿舍联系电话" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="中职卡开户行" prop="bankName">
<el-input v-model="majorInfo.bankName" placeholder="请输入中职卡开户行" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="中职卡号" prop="bankCard">
<el-input v-model="majorInfo.bankCard" placeholder="请输入中职卡号" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="社保卡开户行" prop="socialBank">
<el-input v-model="majorInfo.socialBank" placeholder="请输入社保卡开户行" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="社保卡号" prop="socialBankNo">
<el-input v-model="majorInfo.socialBankNo" placeholder="请输入社保卡号" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="停车证号">
<el-input v-model="formData.parkingNo" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="班级QQ群号" prop="classQq">
<el-input v-model="majorInfo.classQq" placeholder="请输入班级QQ群号" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="年级" prop="currentGrade">
<el-input v-model="majorInfo.currentGrade" placeholder="请输入年级" clearable />
</el-form-item>
</el-col>
</el-row>
</div>
<!-- 成教信息 -->
<div v-show="activeTab === 'adult'" class="detail-panel">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="成教学院" prop="schoolName">
<el-input v-model="adultInfo.schoolName" placeholder="请输入成教学院" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="成教学历" prop="adultEducation">
<el-input v-model="adultInfo.adultEducation" placeholder="请输入成教学历" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="成教考试号" prop="adultExamNo">
<el-input v-model="adultInfo.adultExamNo" placeholder="请输入成教考试号" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="成教入籍日期" prop="adultEnterDate">
<el-date-picker v-model="adultInfo.adultEnterDate" type="date" placeholder="请选择成教入籍日期" value-format="YYYY-MM-DD" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="成教学号" prop="adultNo">
<el-input v-model="adultInfo.adultNo" placeholder="请输入成教学号" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="成教专业" prop="adultMajorName">
<el-input v-model="adultInfo.adultMajorName" placeholder="请输入成教专业" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="成教计算机成绩" prop="computerScore">
<el-input v-model="adultInfo.computerScore" placeholder="请输入成教计算机成绩" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="成教英语成绩" prop="englishScore">
<el-input v-model="adultInfo.englishScore" placeholder="请输入成教英语成绩" clearable />
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false"> </el-button>
<el-button type="primary" @click="handleSave" :loading="saveLoading" :disabled="loading"> </el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts" name="StudentDetailDialog">
import { ref, reactive } from 'vue';
import { User, School, HomeFilled, Briefcase, Grid, Document } from '@element-plus/icons-vue';
import { getStudentInfoDetail, saveStu } from '/@/api/basic/basicstudent';
import { addObj as addHomeDetail, delObj as delHomeDetail } from '/@/api/basic/studenthomedetail';
import { getNationalList } from '/@/api/basic/basicnation';
import { getPoliticsStatusDict } from '/@/api/basic/basicpoliticsstatusbase';
import { getDicts, queryDictByTypeList } from '/@/api/admin/dict';
import { useMessage } from '/@/hooks/message';
import request from '/@/utils/request';
import {editObj} from "/@/api/basic/basicstudentinfo";
// 定义变量内容
const visible = ref(false);
const loading = ref(false);
const saveLoading = ref(false);
const activeTab = ref('basic');
const formRef = ref();
// 字典数据
const nationalList = ref<any[]>([]);
const politicsStatusList = ref<any[]>([]);
const familyMemberTypeList = ref<any[]>([]);
const politicalFamilyList = ref<any[]>([]); // 家庭成员政治面貌
// 多字典查询结果
const eyeStatusList = ref<any[]>([]); // 辨色力
const veteranStatusList = ref<any[]>([]); // 是否退伍军人
const preSchoolEducationList = ref<any[]>([]); // 入学前文化程度
const schoolProvinceList = ref<any[]>([]); // 毕业学校省市
const householdPropertiesList = ref<any[]>([]); // 户口性质
const isTempList = ref<any[]>([]); // 是否租住
const incomeSourceList = ref<any[]>([]); // 家庭主要收入来源
const homeDifficultyList = ref<any[]>([]); // 是否低保
const majorLevelList = ref<any[]>([]); // 专业培养层次
const studentStatusList = ref<any[]>([]); // 学生状态
// 学生数据
const formData = reactive<any>({
id: '',
stuNo: '',
realName: '',
gender: '',
householdAddress: '',
classCode: '',
className: '',
deptName: '',
majorName: '',
graduateNumber: '',
parkingNo: '',
roomNo: '',
teacherRealName: '',
});
const basicInfo = reactive<any>({
id: '',
stuNo: '',
createBy: '',
createTime: '',
oldName: '',
idCard: '',
birthday: '',
politicsStatus: '',
national: '',
colourSense: '',
eyeLeft: '',
eyeRight: '',
height: null,
weight: null,
careType: '',
phone: '',
veteran: '',
seekText: '',
advantage: '',
religiousBelief: '',
isLower: '',
email: '',
qq: '',
socialBank: '',
socialBankNo: '',
});
const educationInfo = reactive<any>({
id: '',
stuNo: '',
education: '',
examScore: null,
examNo: '',
temporaryyeYear: '',
schoolName: '',
schoolProvince: '',
position: '',
});
const homeInfo = reactive<any>({
id: '',
stuNo: '',
householdAddress: '',
householdProperties: '',
liveAddress: '',
isTemp: '',
incomeSource: '',
incomeMoney: null,
incomePerMoney: null,
homeDifficulty: '',
livewith: '',
fatherName: '',
fatherPhone: '',
fatcherIdCard: '',
fatherWorkAddress: '',
matherName: '',
matherPhone: '',
matherIdCard: '',
matherWorkAddress: '',
});
const homeDetailList = ref<any[]>([]);
const majorInfo = reactive<any>({
id: '',
stuNo: '',
enterDate: '',
schoolRollNumber: '',
schoolRoll: '',
studentStatus: '',
majorLevel: '',
majorYears: '',
studyType: '',
unionStuNo: '',
middleNumber: '',
middleTime: '',
highNumber: '',
highTime: '',
technicianNumber: '',
graduateDate: '',
pauseDate: '',
bankCard: '',
bankName: '',
socialBank: '',
socialBankNo: '',
classNo: '',
classRoomPosition: '',
isRoomNo: '',
teacherRealName: '',
teacherTel: '',
dormBuildingPhone: '',
classQq: '',
currentGrade: '',
});
const adultInfo = reactive<any>({
id: '',
stuNo: '',
schoolName: '',
adultEducation: '',
adultExamNo: '',
adultEnterDate: '',
adultNo: '',
adultMajorName: '',
computerScore: '',
englishScore: '',
});
// 表单校验规则 - 根据图片红色必填标记
const formRules = {
// 基本信息必填
realName: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
gender: [{ required: true, message: '请选择性别', trigger: 'change' }],
idCard: [
{ required: true, message: '请输入身份证号', trigger: 'blur' },
{ pattern: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/, message: '身份证号格式不正确', trigger: 'blur' },
],
birthday: [{ required: true, message: '请选择出生日期', trigger: 'change' }],
national: [{ required: true, message: '请选择民族', trigger: 'change' }],
politicsStatus: [{ required: true, message: '请选择政治面貌', trigger: 'change' }],
householdAddress: [{ required: true, message: '请输入籍贯', trigger: 'blur' }],
phone: [{ required: true, message: '请输入本人电话', trigger: 'blur' }],
veteran: [{ required: true, message: '请选择是否退伍军人', trigger: 'change' }],
// 教育经历必填
education: [{ required: true, message: '请选择入学前文化程度', trigger: 'change' }],
// 家庭信息必填
homeHouseholdAddress: [{ required: true, message: '请输入户口详细地址', trigger: 'blur' }],
householdProperties: [{ required: true, message: '请选择户口性质', trigger: 'change' }],
isTemp: [{ required: true, message: '请选择是否租住', trigger: 'change' }],
liveAddress: [{ required: true, message: '请输入居住详细地址', trigger: 'blur' }],
incomeSource: [{ required: true, message: '请选择家庭主要收入来源', trigger: 'change' }],
incomeMoney: [{ required: true, message: '请输入家庭年收入', trigger: 'blur' }],
incomePerMoney: [{ required: true, message: '请输入家庭人均收入', trigger: 'blur' }],
homeDifficulty: [{ required: true, message: '请选择是否低保', trigger: 'change' }],
fatherName: [{ required: true, message: '请输入父亲姓名', trigger: 'blur' }],
fatherPhone: [{ required: true, message: '请输入父亲手机号', trigger: 'blur' }],
matherName: [{ required: true, message: '请输入母亲姓名', trigger: 'blur' }],
matherPhone: [{ required: true, message: '请输入母亲手机号', trigger: 'blur' }],
};
// 菜单选择
const handleMenuSelect = (index: string) => {
activeTab.value = index;
};
// 重置数据
const resetData = () => {
Object.keys(formData).forEach((key) => {
formData[key] = '';
});
Object.keys(basicInfo).forEach((key) => {
basicInfo[key] = key === 'height' || key === 'weight' ? null : '';
});
Object.keys(educationInfo).forEach((key) => {
educationInfo[key] = key === 'examScore' ? null : '';
});
Object.keys(homeInfo).forEach((key) => {
homeInfo[key] = key === 'incomeMoney' || key === 'incomePerMoney' ? null : '';
});
Object.keys(majorInfo).forEach((key) => {
majorInfo[key] = '';
});
Object.keys(adultInfo).forEach((key) => {
adultInfo[key] = '';
});
homeDetailList.value = [];
};
// 打开弹窗
const openDialog = async (rowData: any) => {
visible.value = true;
activeTab.value = 'basic';
resetData();
// 加载字典数据
await loadDictData();
// 加载详情数据
if (rowData?.stuNo) {
await loadDetailData(rowData.stuNo);
}
};
// 加载字典数据
const loadDictData = async () => {
try {
// 获取民族列表
const nationalRes = await getNationalList();
console.log('民族接口返回:', nationalRes);
if (nationalRes && Array.isArray(nationalRes)) {
nationalList.value = nationalRes;
} else if (nationalRes && nationalRes.data && Array.isArray(nationalRes.data)) {
nationalList.value = nationalRes.data;
}
// 获取政治面貌列表
const politicsRes = await getPoliticsStatusDict();
console.log('政治面貌接口返回:', politicsRes);
if (politicsRes && Array.isArray(politicsRes)) {
politicsStatusList.value = politicsRes;
} else if (politicsRes && politicsRes.data && Array.isArray(politicsRes.data)) {
politicsStatusList.value = politicsRes.data;
}
// 多字典查询 - 一次性获取所有字典
const dictTypes = [
'family_member_type', // 家庭成员关系
'political_family', // 家庭成员政治面貌
'color_discrimination', // 辨色力
'veteran_status', // 是否退伍军人
'pre_school_education', // 入学前文化程度
'school_province', // 毕业学校省市
'house_hold_properties', // 户口性质
'is_temp', // 是否租住
'income_source', // 家庭主要收入来源
'home_difficulty', // 是否低保
'basic_major_level', // 专业培养层次
'student_status', // 学生状态
];
const dictRes = await queryDictByTypeList(dictTypes);
if (dictRes) {
const dictMap = dictRes;
// 家庭成员关系类型
if (dictMap['family_member_type'] && Array.isArray(dictMap['family_member_type'])) {
familyMemberTypeList.value = dictMap['family_member_type'].map((item: any) => ({
label: item.label,
value: item.value,
}));
}
// 家庭成员政治面貌
if (dictMap['political_family'] && Array.isArray(dictMap['political_family'])) {
politicalFamilyList.value = dictMap['political_family'].map((item: any) => ({
label: item.label,
value: item.value,
}));
}
// 辨色力
if (dictMap['color_discrimination'] && Array.isArray(dictMap['color_discrimination'])) {
eyeStatusList.value = dictMap['color_discrimination'].map((item: any) => ({
label: item.label,
value: item.value,
}));
}
// 是否退伍军人
if (dictMap['veteran_status'] && Array.isArray(dictMap['veteran_status'])) {
veteranStatusList.value = dictMap['veteran_status'].map((item: any) => ({
label: item.label,
value: item.value,
}));
}
// 入学前文化程度
if (dictMap['pre_school_education'] && Array.isArray(dictMap['pre_school_education'])) {
preSchoolEducationList.value = dictMap['pre_school_education'].map((item: any) => ({
label: item.label,
value: item.value,
}));
}
// 毕业学校省市
if (dictMap['school_province'] && Array.isArray(dictMap['school_province'])) {
schoolProvinceList.value = dictMap['school_province'].map((item: any) => ({
label: item.label,
value: item.value,
}));
}
// 户口性质
if (dictMap['house_hold_properties'] && Array.isArray(dictMap['house_hold_properties'])) {
householdPropertiesList.value = dictMap['house_hold_properties'].map((item: any) => ({
label: item.label,
value: item.value,
}));
}
// 是否租住
if (dictMap['is_temp'] && Array.isArray(dictMap['is_temp'])) {
isTempList.value = dictMap['is_temp'].map((item: any) => ({
label: item.label,
value: item.value,
}));
}
// 家庭主要收入来源
if (dictMap['income_source'] && Array.isArray(dictMap['income_source'])) {
incomeSourceList.value = dictMap['income_source'].map((item: any) => ({
label: item.label,
value: item.value,
}));
}
// 是否低保
if (dictMap['home_difficulty'] && Array.isArray(dictMap['home_difficulty'])) {
homeDifficultyList.value = dictMap['home_difficulty'].map((item: any) => ({
label: item.label,
value: item.value,
}));
}
// 专业培养层次
if (dictMap['basic_major_level'] && Array.isArray(dictMap['basic_major_level'])) {
majorLevelList.value = dictMap['basic_major_level'].map((item: any) => ({
label: item.label,
value: item.value,
}));
}
// 学生状态
if (dictMap['student_status'] && Array.isArray(dictMap['student_status'])) {
studentStatusList.value = dictMap['student_status'].map((item: any) => ({
label: item.label,
value: item.value,
}));
}
}
} catch (err) {
console.error('加载字典数据失败', err);
}
};
// 加载详情数据
const loadDetailData = async (stuNo: string) => {
loading.value = true;
try {
const res = await getStudentInfoDetail({ stuNo });
if (res.data && res.data.records && res.data.records.length > 0) {
const data = res.data.records[0];
// 主数据
Object.keys(formData).forEach((key) => {
if (data[key] !== undefined) {
formData[key] = data[key];
}
});
// 基本信息
const basic = data.basicStudentInfoDetailVO || data.basicStudentInfo || {};
Object.keys(basicInfo).forEach((key) => {
if (basic[key] !== undefined) {
basicInfo[key] = basic[key];
}
});
// 教育经历
const education = data.basicStudentEducation || {};
Object.keys(educationInfo).forEach((key) => {
if (education[key] !== undefined) {
educationInfo[key] = education[key];
}
});
// 家庭信息
const home = data.basicStudentHome || {};
Object.keys(homeInfo).forEach((key) => {
if (home[key] !== undefined) {
homeInfo[key] = home[key];
}
});
homeDetailList.value = data.homeDetailList || [];
// 专业/班级信息
const major = data.basicStudentMajorClassVO || data.basicStudentMajorClass || {};
Object.keys(majorInfo).forEach((key) => {
if (major[key] !== undefined) {
majorInfo[key] = major[key];
}
});
// 成教信息
const adult = data.basicStudentAdultEducation || {};
Object.keys(adultInfo).forEach((key) => {
if (adult[key] !== undefined) {
adultInfo[key] = adult[key];
}
});
}
} catch (err: any) {
console.error('获取学生详情失败', err);
useMessage().error(err.msg || '获取学生详情失败');
} finally {
loading.value = false;
}
};
// 新增家庭成员
const handleAddFamilyMember = () => {
homeDetailList.value.push({
id: '',
stuNo: formData.stuNo,
appellation: '',
realName: '',
tel: '',
idCard: '',
workAddress: '',
politicsStatus: '',
health: '',
_saving: false,
});
};
// 保存单个家庭成员
const handleSaveFamilyMember = async (row: any, index: number) => {
// 验证必填字段
if (!row.realName) {
useMessage().warning('请输入姓名');
return;
}
if (!row.appellation) {
useMessage().warning('请输入关系');
return;
}
row._saving = true;
try {
const saveData = {
...row,
stuNo: formData.stuNo,
};
if (row.id) {
// 更新已有记录 - 使用putObj
await request({
url: '/basic/studenthomedetail',
method: 'put',
data: saveData
});
} else {
// 新增记录
const res = await addHomeDetail(saveData);
// 更新id避免重复新增
if (res.data) {
homeDetailList.value[index].id = res.data.id || res.data;
}
}
useMessage().success('保存成功');
} catch (err: any) {
useMessage().error(err.msg || '保存失败');
} finally {
row._saving = false;
}
};
// 删除家庭成员
const handleDeleteFamilyMember = async (index: number) => {
const member = homeDetailList.value[index];
if (member.id) {
try {
await delHomeDetail(member.id);
useMessage().success('删除成功');
} catch (err: any) {
useMessage().error(err.msg || '删除失败');
return;
}
}
homeDetailList.value.splice(index, 1);
};
// 保存
const handleSave = async () => {
if (!formRef.value) return;
// 手动验证必填字段因为数据分散在多个reactive对象中
const errors: string[] = [];
// 基本信息必填验证
if (!formData.realName) errors.push('请输入姓名');
if (!formData.gender) errors.push('请选择性别');
if (!basicInfo.idCard) errors.push('请输入身份证号');
if (!basicInfo.birthday) errors.push('请选择出生日期');
if (!basicInfo.national) errors.push('请选择民族');
if (!basicInfo.politicsStatus) errors.push('请选择政治面貌');
if (!formData.householdAddress) errors.push('请输入籍贯');
if (!basicInfo.phone) errors.push('请输入本人电话');
if (!basicInfo.veteran) errors.push('请选择是否退伍军人');
// 教育经历必填验证
if (!educationInfo.education) errors.push('请选择入学前文化程度');
// 家庭信息必填验证
if (!homeInfo.householdAddress) errors.push('请输入户口详细地址');
if (!homeInfo.householdProperties) errors.push('请选择户口性质');
if (!homeInfo.isTemp) errors.push('请选择是否租住');
if (!homeInfo.liveAddress) errors.push('请输入居住详细地址');
if (!homeInfo.incomeSource) errors.push('请选择家庭主要收入来源');
if (homeInfo.incomeMoney === null || homeInfo.incomeMoney === undefined || homeInfo.incomeMoney === '') errors.push('请输入家庭年收入');
if (homeInfo.incomePerMoney === null || homeInfo.incomePerMoney === undefined || homeInfo.incomePerMoney === '') errors.push('请输入家庭人均收入');
if (!homeInfo.homeDifficulty) errors.push('请选择是否低保');
if (errors.length > 0) {
useMessage().warning(errors[0]);
return;
}
saveLoading.value = true;
try {
// 构建保存数据
const saveData: any = {
...formData,
basicStudentInfo: { ...basicInfo },
basicStudentInfoDetailVO: { ...basicInfo },
basicStudentEducation: { ...educationInfo },
basicStudentHome: { ...homeInfo },
homeDetailList: homeDetailList.value.filter((item) => !item.id), // 只传新增的
basicStudentMajorClassVO: { ...majorInfo },
basicStudentAdultEducation: { ...adultInfo },
};
await editObj(saveData);
useMessage().success('保存成功');
visible.value = false;
} catch (err: any) {
useMessage().error(err.msg || '保存失败');
} finally {
saveLoading.value = false;
}
};
// 暴露方法给父组件
defineExpose({
openDialog,
});
</script>
<style lang="scss" scoped>
.student-detail-container {
display: flex;
min-height: 500px;
max-height: 70vh;
.detail-sidebar {
width: 180px;
border-right: 1px solid #e4e7ed;
flex-shrink: 0;
.el-menu {
border-right: none;
}
.el-menu-item {
height: 50px;
line-height: 50px;
&.is-active {
background-color: #ecf5ff;
}
}
}
.detail-content {
flex: 1;
padding: 0 20px;
overflow-y: auto;
.detail-panel {
padding: 10px 0;
}
}
}
.empty-tip {
text-align: center;
padding: 20px;
color: #909399;
}
:deep(.el-divider__text) {
display: flex;
align-items: center;
}
</style>