feat: 完善学生导入模板下载功能

1. 后端新增接口 /business/student/template
   - 使用 ExcelUtil 导出模板
   - 包含示例数据方便用户参考

2. 前端修复模板下载:
   - 使用 fetch 下载文件
   - 文字"用户手机号"改为"会员手机号"

3. 新增 StudentImportDto 导入数据对象
   - 字段:姓名、学号、会员手机号、区域、学校、年级、班级、性别、出生年月
This commit is contained in:
神码-方晓辉 2026-02-02 20:02:41 +08:00
parent 6784e32e1e
commit ca433d6ab9
3 changed files with 105 additions and 7 deletions

View File

@ -1,8 +1,10 @@
package org.dromara.pangu.student.controller; package org.dromara.pangu.student.controller;
import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.log.annotation.Log; import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType; import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
@ -12,11 +14,13 @@ import org.dromara.pangu.school.domain.PgSchool;
import org.dromara.pangu.school.domain.vo.SchoolTreeNode; import org.dromara.pangu.school.domain.vo.SchoolTreeNode;
import org.dromara.pangu.school.service.IPgSchoolService; import org.dromara.pangu.school.service.IPgSchoolService;
import org.dromara.pangu.student.domain.PgStudent; import org.dromara.pangu.student.domain.PgStudent;
import org.dromara.pangu.student.domain.dto.StudentImportDto;
import org.dromara.pangu.student.domain.vo.StudentVo; import org.dromara.pangu.student.domain.vo.StudentVo;
import org.dromara.pangu.student.service.IPgStudentService; import org.dromara.pangu.student.service.IPgStudentService;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@ -98,4 +102,26 @@ public class PgStudentController extends BaseController {
public R<java.util.List<PgStudent>> listByMemberId(@PathVariable Long memberId) { public R<java.util.List<PgStudent>> listByMemberId(@PathVariable Long memberId) {
return R.ok(studentService.selectByMemberId(memberId)); return R.ok(studentService.selectByMemberId(memberId));
} }
/**
* 下载学生导入模板
*/
@GetMapping("/template")
public void downloadTemplate(HttpServletResponse response) {
// 创建示例数据方便用户参考填写
List<StudentImportDto> sampleData = new ArrayList<>();
StudentImportDto sample = new StudentImportDto();
sample.setStudentName("张三");
sample.setStudentNo("2026001");
sample.setMemberPhone("13800138000");
sample.setRegionPath("湖北省-武汉市-硚口区");
sample.setSchoolName("武汉市第二中学");
sample.setGradeName("高一");
sample.setClassName("1班");
sample.setGender("");
sample.setBirthday("2010-01");
sampleData.add(sample);
ExcelUtil.exportExcel(sampleData, "学生导入模板", StudentImportDto.class, response);
}
} }

View File

@ -0,0 +1,52 @@
package org.dromara.pangu.student.domain.dto;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
/**
* 学生导入数据传输对象
*
* @author pangu
*/
@Data
@HeadRowHeight(25)
public class StudentImportDto {
@ExcelProperty(value = "姓名", index = 0)
@ColumnWidth(15)
private String studentName;
@ExcelProperty(value = "学号", index = 1)
@ColumnWidth(20)
private String studentNo;
@ExcelProperty(value = "会员手机号", index = 2)
@ColumnWidth(15)
private String memberPhone;
@ExcelProperty(value = "区域", index = 3)
@ColumnWidth(25)
private String regionPath;
@ExcelProperty(value = "学校", index = 4)
@ColumnWidth(25)
private String schoolName;
@ExcelProperty(value = "年级", index = 5)
@ColumnWidth(12)
private String gradeName;
@ExcelProperty(value = "班级", index = 6)
@ColumnWidth(10)
private String className;
@ExcelProperty(value = "性别", index = 7)
@ColumnWidth(8)
private String gender;
@ExcelProperty(value = "出生年月", index = 8)
@ColumnWidth(12)
private String birthday;
}

View File

@ -16,8 +16,8 @@
<div style="line-height: 1.8"> <div style="line-height: 1.8">
1. 请先下载导入模板按模板格式填写数据<br> 1. 请先下载导入模板按模板格式填写数据<br>
2. 支持 xlsxxls 格式文件单次最多导入500条<br> 2. 支持 xlsxxls 格式文件单次最多导入500条<br>
3. 必填字段姓名学号用户手机号区域学校年级班级<br> 3. 必填字段姓名学号会员手机号区域学校年级班级<br>
4. 用户手机号已存在则挂载到已有用户否则自动创建家长账号 4. 会员手机号已存在则挂载到已有会员否则自动创建家长账号
</div> </div>
</template> </template>
</el-alert> </el-alert>
@ -112,13 +112,33 @@ const uploadHeaders = computed(() => {
const handleDownloadTemplate = async () => { const handleDownloadTemplate = async () => {
downloadLoading.value = true downloadLoading.value = true
try { try {
// 使 window.open
const baseApi = import.meta.env.VITE_APP_BASE_API || '' const baseApi = import.meta.env.VITE_APP_BASE_API || ''
const token = getToken() // 使 fetch
const url = `${baseApi}/business/student/template?token=${encodeURIComponent(token)}` const response = await fetch(`${baseApi}/business/student/template`, {
window.open(url, '_blank') method: 'GET',
headers: {
'Authorization': 'Bearer ' + getToken()
}
})
if (!response.ok) {
throw new Error('下载失败')
}
const blob = await response.blob()
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = '学生导入模板.xlsx'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
ElMessage.success('模板下载成功')
} catch (e) { } catch (e) {
ElMessage.error('下载模板失败') console.error('下载模板失败:', e)
ElMessage.error('下载模板失败,请重试')
} finally { } finally {
downloadLoading.value = false downloadLoading.value = false
} }