diff --git a/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/student/controller/PgStudentController.java b/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/student/controller/PgStudentController.java index 457690c..e1ab7a1 100644 --- a/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/student/controller/PgStudentController.java +++ b/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/student/controller/PgStudentController.java @@ -1,8 +1,10 @@ package org.dromara.pangu.student.controller; import cn.dev33.satoken.annotation.SaCheckPermission; +import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; 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.enums.BusinessType; 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.service.IPgSchoolService; 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.service.IPgStudentService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.ArrayList; import java.util.List; /** @@ -98,4 +102,26 @@ public class PgStudentController extends BaseController { public R> listByMemberId(@PathVariable Long memberId) { return R.ok(studentService.selectByMemberId(memberId)); } + + /** + * 下载学生导入模板 + */ + @GetMapping("/template") + public void downloadTemplate(HttpServletResponse response) { + // 创建示例数据,方便用户参考填写 + List 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); + } } diff --git a/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/student/domain/dto/StudentImportDto.java b/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/student/domain/dto/StudentImportDto.java new file mode 100644 index 0000000..baf8352 --- /dev/null +++ b/backend/ruoyi-modules/pangu-business/src/main/java/org/dromara/pangu/student/domain/dto/StudentImportDto.java @@ -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; +} diff --git a/frontend/ruoyi-ui/src/views/business/student/components/ImportDialog.vue b/frontend/ruoyi-ui/src/views/business/student/components/ImportDialog.vue index b00b547..e4230f6 100644 --- a/frontend/ruoyi-ui/src/views/business/student/components/ImportDialog.vue +++ b/frontend/ruoyi-ui/src/views/business/student/components/ImportDialog.vue @@ -16,8 +16,8 @@
1. 请先下载导入模板,按模板格式填写数据
2. 支持 xlsx、xls 格式文件,单次最多导入500条
- 3. 必填字段:姓名、学号、用户手机号、区域、学校、年级、班级
- 4. 若用户手机号已存在则挂载到已有用户,否则自动创建家长账号 + 3. 必填字段:姓名、学号、会员手机号、区域、学校、年级、班级
+ 4. 若会员手机号已存在则挂载到已有会员,否则自动创建家长账号
@@ -112,13 +112,33 @@ const uploadHeaders = computed(() => { const handleDownloadTemplate = async () => { downloadLoading.value = true try { - // 使用 window.open 直接下载 const baseApi = import.meta.env.VITE_APP_BASE_API || '' - const token = getToken() - const url = `${baseApi}/business/student/template?token=${encodeURIComponent(token)}` - window.open(url, '_blank') + // 使用 fetch 下载文件 + const response = await fetch(`${baseApi}/business/student/template`, { + 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) { - ElMessage.error('下载模板失败') + console.error('下载模板失败:', e) + ElMessage.error('下载模板失败,请重试') } finally { downloadLoading.value = false }