parent
653987d860
commit
9b48594479
|
|
@ -49,3 +49,21 @@ export function teacherConfigRole(params: Record<string, any>) {
|
|||
export function teacherGetConfig() {
|
||||
return request.get({ url: '/teacher/get.config' })
|
||||
}
|
||||
|
||||
// 生成邀请码和二维码
|
||||
export function teacherGenerateInvitationCode(params: Record<string, any>) {
|
||||
return request.post({ url: '/teacher/generateInvitationCode', params })
|
||||
}
|
||||
|
||||
// 获取教师二维码图片URL
|
||||
export function teacherGetQrCodeUrl(params: Record<string, any>) {
|
||||
return request.get({ url: '/teacher/qrcode', params })
|
||||
}
|
||||
|
||||
// 获取教师二维码图片流(带鉴权,用于展示与下载)
|
||||
export function teacherGetQrCodeImage(params: Record<string, any>) {
|
||||
return request.get(
|
||||
{ url: '/teacher/qrcode/image', params, responseType: 'blob' },
|
||||
{ isReturnDefaultResponse: true }
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,8 +149,9 @@ export class Axios {
|
|||
requestOptions: opt
|
||||
}
|
||||
const { urlPrefix } = opt
|
||||
// 拼接请求前缀如api
|
||||
if (urlPrefix) {
|
||||
// 绝对 URL(如图片地址)不拼接前缀,直接使用
|
||||
const isAbsoluteUrl = typeof config.url === 'string' && /^https?:\/\//i.test(config.url)
|
||||
if (urlPrefix && !isAbsoluteUrl) {
|
||||
// 确保路径格式正确:/adminapi/xxx
|
||||
const url = config.url?.startsWith('/') ? config.url : `/${config.url}`
|
||||
axioxConfig.url = `/${urlPrefix}${url}`
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import com.mdd.common.entity.system.SystemRole;
|
|||
import com.mdd.common.validator.annotation.IDMust;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
|
@ -30,15 +32,15 @@ public class TeacherController {
|
|||
ITeacherService iTeacherService;
|
||||
|
||||
@GetMapping("/list")
|
||||
@ApiOperation(value="教师信息扩展列表")
|
||||
@ApiOperation(value = "教师信息扩展列表")
|
||||
public AjaxResult<PageResult<TeacherListedVo>> list(@Validated PageValidate pageValidate,
|
||||
@Validated TeacherSearchValidate searchValidate) {
|
||||
@Validated TeacherSearchValidate searchValidate) {
|
||||
PageResult<TeacherListedVo> list = iTeacherService.list(pageValidate, searchValidate);
|
||||
return AjaxResult.success(list);
|
||||
}
|
||||
|
||||
@GetMapping("/detail")
|
||||
@ApiOperation(value="教师信息扩展详情")
|
||||
@ApiOperation(value = "教师信息扩展详情")
|
||||
public AjaxResult<TeacherDetailVo> detail(@Validated @IDMust() @RequestParam("id") Integer id) {
|
||||
TeacherDetailVo detail = iTeacherService.detail(id);
|
||||
return AjaxResult.success(detail);
|
||||
|
|
@ -46,14 +48,14 @@ public class TeacherController {
|
|||
|
||||
@Log(title = "添加教师账号")
|
||||
@PostMapping("/add")
|
||||
@ApiOperation(value="添加教师账号", notes = "根据提供的角色id列表,为添加的教师账号选择角色")
|
||||
@ApiOperation(value = "添加教师账号", notes = "支持传入invitationCode(邀请码/二维码标识);根据提供的角色id列表,为添加的教师账号选择角色")
|
||||
public AjaxResult<Object> add(@Validated @RequestBody TeacherCreateValidate createValidate) {
|
||||
return iTeacherService.add(createValidate);
|
||||
}
|
||||
|
||||
@Log(title = "教师信息扩展编辑")
|
||||
@PostMapping("/edit")
|
||||
@ApiOperation(value="教师信息扩展编辑")
|
||||
@ApiOperation(value = "教师信息扩展编辑", notes = "支持更新invitationCode(邀请码/二维码标识)")
|
||||
public AjaxResult<Object> edit(@Validated @RequestBody TeacherUpdateValidate updateValidate) {
|
||||
iTeacherService.edit(updateValidate);
|
||||
return AjaxResult.success();
|
||||
|
|
@ -61,7 +63,7 @@ public class TeacherController {
|
|||
|
||||
@Log(title = "教师信息扩展删除")
|
||||
@PostMapping("/del")
|
||||
@ApiOperation(value="教师信息扩展删除")
|
||||
@ApiOperation(value = "教师信息扩展删除")
|
||||
public AjaxResult<Object> del(@Validated @RequestBody IdValidate idValidate) {
|
||||
iTeacherService.del(idValidate.getId());
|
||||
return AjaxResult.success();
|
||||
|
|
@ -81,4 +83,29 @@ public class TeacherController {
|
|||
iTeacherService.roleConfig(idValidate.getId());
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@Log(title = "生成邀请码")
|
||||
@PostMapping("/generateInvitationCode")
|
||||
@ApiOperation(value = "生成邀请码和二维码", notes = "为指定教师生成唯一的邀请码和二维码图片")
|
||||
public AjaxResult<Object> generateInvitationCode(@Validated @RequestBody IdValidate idValidate) {
|
||||
return iTeacherService.generateInvitationCode(idValidate.getId());
|
||||
}
|
||||
|
||||
@GetMapping("/qrcode")
|
||||
@ApiOperation(value = "获取二维码图片URL", notes = "获取指定教师的二维码图片访问地址")
|
||||
public AjaxResult<Object> getQrCodeUrl(@Validated @IDMust() @RequestParam("id") Integer id) {
|
||||
return iTeacherService.getQrCodeUrl(id);
|
||||
}
|
||||
|
||||
@GetMapping("/qrcode/image")
|
||||
@ApiOperation(value = "获取二维码图片流", notes = "带鉴权返回教师二维码图片,用于前端展示与下载")
|
||||
public ResponseEntity<byte[]> getQrCodeImage(@Validated @IDMust() @RequestParam("id") Integer id) {
|
||||
byte[] bytes = iTeacherService.getQrCodeImageBytes(id);
|
||||
if (bytes == null || bytes.length == 0) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.IMAGE_PNG)
|
||||
.body(bytes);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ import com.mdd.common.core.AjaxResult;
|
|||
import com.mdd.common.core.PageResult;
|
||||
import com.mdd.common.entity.system.SystemRole;
|
||||
|
||||
import javax.management.relation.Role;
|
||||
|
||||
/**
|
||||
* 教师信息扩展服务接口类
|
||||
* @author gyp
|
||||
|
|
@ -64,4 +62,30 @@ public interface ITeacherService {
|
|||
void roleConfig(Integer id);
|
||||
|
||||
AjaxResult<SystemRole> getRoleConfig();
|
||||
|
||||
/**
|
||||
* 生成邀请码和二维码
|
||||
*
|
||||
* @param teacherId 教师ID
|
||||
* @return AjaxResult<String> 返回生成的邀请码
|
||||
* @author gyp
|
||||
*/
|
||||
AjaxResult<Object> generateInvitationCode(Integer teacherId);
|
||||
|
||||
/**
|
||||
* 获取二维码图片URL
|
||||
*
|
||||
* @author gyp
|
||||
* @param teacherId 教师ID
|
||||
* @return AjaxResult<String> 返回二维码图片的绝对URL
|
||||
*/
|
||||
AjaxResult<Object> getQrCodeUrl(Integer teacherId);
|
||||
|
||||
/**
|
||||
* 获取二维码图片字节流(用于带鉴权的图片展示与下载)
|
||||
*
|
||||
* @param teacherId 教师ID
|
||||
* @return 图片字节数组,不存在时返回 null
|
||||
*/
|
||||
byte[] getQrCodeImageBytes(Integer teacherId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import com.mdd.common.mapper.user.UserMapper;
|
|||
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import com.mdd.common.util.*;
|
||||
import io.netty.util.internal.ThreadLocalRandom;
|
||||
|
|
@ -92,6 +93,8 @@ public class StudentInfoServiceImpl implements IStudentInfoService {
|
|||
"=:academicWarnings@academic_warnings:int",
|
||||
"=:isVerified@is_verified:int",
|
||||
"=:verifiedBy@verified_by:int",
|
||||
"=:recruitmentTeacherId@recruitment_teacher_id:int",
|
||||
"=:receptionTeacherId@reception_teacher_id:int",
|
||||
});
|
||||
|
||||
IPage<StudentInfo> iPage = studentInfoMapper.selectPage(new Page<>(page, limit), queryWrapper);
|
||||
|
|
@ -102,13 +105,27 @@ public class StudentInfoServiceImpl implements IStudentInfoService {
|
|||
BeanUtils.copyProperties(item, vo);
|
||||
vo.setVerifiedTime(TimeUtils.timestampToDate(item.getVerifiedTime()));
|
||||
|
||||
// 通过 student_id 关联查询基本信息获取 name
|
||||
// 通过 student_id 关联查询基本信息获取姓名及基础信息
|
||||
StudentBaseInfo baseInfo = studentBaseInfoMapper.selectOne(
|
||||
new QueryWrapper<StudentBaseInfo>()
|
||||
.eq("student_id", item.getStudentId())
|
||||
.last("limit 1"));
|
||||
if (baseInfo != null) {
|
||||
vo.setName(baseInfo.getName());
|
||||
vo.setGender(baseInfo.getGender());
|
||||
vo.setIdCard(baseInfo.getIdCard());
|
||||
vo.setPreviousSchool(baseInfo.getPreviousSchool());
|
||||
vo.setHeight(baseInfo.getHeight());
|
||||
vo.setWeight(baseInfo.getWeight());
|
||||
vo.setShoeSize(baseInfo.getShoeSize());
|
||||
}
|
||||
|
||||
// 转换创建时间和更新时间为字符串格式
|
||||
if (item.getCreateTime() != null) {
|
||||
vo.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(item.getCreateTime()));
|
||||
}
|
||||
if (item.getUpdateTime() != null) {
|
||||
vo.setUpdateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(item.getUpdateTime()));
|
||||
}
|
||||
|
||||
College college = collegeMapper.selectById(item.getCollegeId());
|
||||
|
|
|
|||
|
|
@ -16,36 +16,43 @@ import com.mdd.admin.vo.teacher.TeacherDetailVo;
|
|||
import com.mdd.common.core.AjaxResult;
|
||||
import com.mdd.common.core.PageResult;
|
||||
import com.mdd.common.entity.College;
|
||||
import com.mdd.common.entity.Config;
|
||||
import com.mdd.common.entity.Teacher;
|
||||
import com.mdd.common.entity.admin.Admin;
|
||||
import com.mdd.common.entity.admin.AdminRole;
|
||||
import com.mdd.common.entity.system.SystemRole;
|
||||
import com.mdd.common.entity.user.User;
|
||||
import com.mdd.common.mapper.CollegeMapper;
|
||||
import com.mdd.common.mapper.TeacherMapper;
|
||||
import com.mdd.common.mapper.admin.AdminMapper;
|
||||
import com.mdd.common.mapper.admin.AdminRoleMapper;
|
||||
import com.mdd.common.mapper.system.SystemRoleMapper;
|
||||
import com.mdd.common.exception.OperateException;
|
||||
import com.mdd.common.util.ConfigUtils;
|
||||
import com.mdd.common.util.QrCodeUtil;
|
||||
import com.mdd.common.util.RandomUtil;
|
||||
import com.mdd.common.util.TimeUtils;
|
||||
import com.mdd.common.util.ToolUtils;
|
||||
import com.mdd.common.util.UrlUtils;
|
||||
import com.mdd.common.util.YmlUtils;
|
||||
import com.google.zxing.WriterException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.management.relation.Role;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 教师信息扩展实现类
|
||||
*
|
||||
* @author gyp
|
||||
*/
|
||||
@Service
|
||||
public class TeacherServiceImpl implements ITeacherService {
|
||||
|
||||
|
||||
@Resource
|
||||
TeacherMapper teacherMapper;
|
||||
@Autowired
|
||||
|
|
@ -55,8 +62,6 @@ public class TeacherServiceImpl implements ITeacherService {
|
|||
@Autowired
|
||||
private AdminServiceImpl adminServiceImpl;
|
||||
@Autowired
|
||||
private AdminRoleMapper adminRoleMapper;
|
||||
@Autowired
|
||||
private AdminRoleServiceImpl adminRoleServiceImpl;
|
||||
@Autowired
|
||||
private SystemRoleMapper systemRoleMapper;
|
||||
|
|
@ -64,42 +69,48 @@ public class TeacherServiceImpl implements ITeacherService {
|
|||
/**
|
||||
* 教师信息扩展列表
|
||||
*
|
||||
* @author gyp
|
||||
* @param pageValidate 分页参数
|
||||
* @param pageValidate 分页参数
|
||||
* @param searchValidate 搜索参数
|
||||
* @return PageResult<TeacherListedVo>
|
||||
* @author gyp
|
||||
*/
|
||||
@Override
|
||||
public PageResult<TeacherListedVo> list(PageValidate pageValidate, TeacherSearchValidate searchValidate) {
|
||||
Integer page = pageValidate.getPage_no();
|
||||
Integer page = pageValidate.getPage_no();
|
||||
Integer limit = pageValidate.getPage_size();
|
||||
|
||||
QueryWrapper<Teacher> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.orderByDesc("id");
|
||||
queryWrapper.orderByDesc("teacher_id");
|
||||
|
||||
teacherMapper.setSearch(queryWrapper, searchValidate, new String[]{
|
||||
"=:adminId@admin_id:int",
|
||||
"like:name:str",
|
||||
"like:name@teacher_name:str",
|
||||
"=:teacherCode@teacher_code:str",
|
||||
"=:collegeId@college_id:int",
|
||||
"=:teacherStatus@teacher_status:int",
|
||||
"=:invitationCode@invitation_code:str",
|
||||
});
|
||||
|
||||
IPage<Teacher> iPage = teacherMapper.selectPage(new Page<>(page, limit), queryWrapper);
|
||||
|
||||
List<TeacherListedVo> list = new LinkedList<>();
|
||||
for(Teacher item : iPage.getRecords()) {
|
||||
for (Teacher item : iPage.getRecords()) {
|
||||
TeacherListedVo vo = new TeacherListedVo();
|
||||
BeanUtils.copyProperties(item, vo);
|
||||
// 映射主键:实体是teacherId,VO也是teacherId,BeanUtils会自动处理
|
||||
vo.setTeacherId(item.getTeacherId());
|
||||
// 显式设置教师工号,确保字段正确映射
|
||||
vo.setTeacherCode(item.getTeacherCode());
|
||||
// 兼容:前端列表使用name字段展示教师姓名,但教师表字段为teacher_name
|
||||
vo.setName(item.getTeacherName());
|
||||
// 设置二维码URL(转换为绝对URL)
|
||||
if (item.getQrcodeUrl() != null && !item.getQrcodeUrl().isEmpty()) {
|
||||
// 后台端静态资源映射:/adminapi/uploads/**,因此这里需走 admin 端的绝对路径转换
|
||||
vo.setQrcodeUrl(UrlUtils.toAdminAbsoluteUrl(item.getQrcodeUrl()));
|
||||
}
|
||||
vo.setCreateTime(TimeUtils.timestampToDate(item.getCreateTime()));
|
||||
vo.setUpdateTime(TimeUtils.timestampToDate(item.getUpdateTime()));
|
||||
College college = collegeMapper.selectById(vo.getCollegeId());
|
||||
if(college != null) vo.setCollegeName(college.getCollegeName());
|
||||
Admin admin = adminMapper.selectById(vo.getAdminId());
|
||||
if(admin != null) {
|
||||
vo.setName(admin.getName());
|
||||
vo.setTeacherCode(admin.getAccount());
|
||||
}
|
||||
if (college != null) vo.setCollegeName(college.getCollegeName());
|
||||
|
||||
list.add(vo);
|
||||
}
|
||||
|
|
@ -110,53 +121,59 @@ public class TeacherServiceImpl implements ITeacherService {
|
|||
/**
|
||||
* 教师信息扩展详情
|
||||
*
|
||||
* @author gyp
|
||||
* @param id 主键参数
|
||||
* @return Teacher
|
||||
* @author gyp
|
||||
*/
|
||||
@Override
|
||||
public TeacherDetailVo detail(Integer id) {
|
||||
Teacher model = teacherMapper.selectOne(
|
||||
new QueryWrapper<Teacher>()
|
||||
.eq("id", id)
|
||||
.last("limit 1"));
|
||||
.eq("teacher_id", id)
|
||||
.last("limit 1"));
|
||||
|
||||
Assert.notNull(model, "数据不存在");
|
||||
|
||||
TeacherDetailVo vo = new TeacherDetailVo();
|
||||
BeanUtils.copyProperties(model, vo);
|
||||
|
||||
|
||||
Admin admin = adminMapper.selectById(vo.getAdminId());
|
||||
if(admin != null) {
|
||||
vo.setName(admin.getName());
|
||||
vo.setTeacherCode(admin.getAccount());
|
||||
// 映射主键:实体是teacherId,VO也是teacherId,BeanUtils会自动处理
|
||||
vo.setTeacherId(model.getTeacherId());
|
||||
// 显式设置教师工号,确保字段正确映射
|
||||
vo.setTeacherCode(model.getTeacherCode());
|
||||
// 兼容:前端详情使用name字段展示教师姓名,但教师表字段为teacher_name
|
||||
vo.setName(model.getTeacherName());
|
||||
// 设置二维码URL(转换为绝对URL)
|
||||
if (model.getQrcodeUrl() != null && !model.getQrcodeUrl().isEmpty()) {
|
||||
// 后台端静态资源映射:/adminapi/uploads/**,因此这里需走 admin 端的绝对路径转换
|
||||
vo.setQrcodeUrl(UrlUtils.toAdminAbsoluteUrl(model.getQrcodeUrl()));
|
||||
}
|
||||
|
||||
College college = collegeMapper.selectById(vo.getCollegeId());
|
||||
if(college != null) vo.setCollegeName(college.getCollegeName());
|
||||
if (college != null) vo.setCollegeName(college.getCollegeName());
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 教师信息扩展新增
|
||||
*
|
||||
* @author gyp
|
||||
* @param createValidate 参数
|
||||
* @author gyp
|
||||
*/
|
||||
@Override
|
||||
public AjaxResult<Object> add(TeacherCreateValidate createValidate) {
|
||||
// 自动生成唯一教师工号,作为管理员账号 & 教师工号
|
||||
String teacherCode = generateTeacherCode();
|
||||
// 创建admin账号
|
||||
SystemAdminCreateValidate admin = new SystemAdminCreateValidate();
|
||||
admin.setAccount(createValidate.getTeacherCode());
|
||||
admin.setAccount(teacherCode);
|
||||
admin.setName(createValidate.getName());
|
||||
admin.setDisable(1);
|
||||
// 密码默认是电话号码后8位
|
||||
admin.setPassword(createValidate.getContactPhone().substring(3));
|
||||
int teacherRoleId;
|
||||
try{
|
||||
try {
|
||||
teacherRoleId = Integer.parseInt(ConfigUtils.get("teacher", "teacher_role_id"));
|
||||
}catch (NullPointerException e){
|
||||
} catch (NullPointerException e) {
|
||||
return AjaxResult.failed("未配置教师角色");
|
||||
}
|
||||
admin.setRoleId(Collections.singletonList(teacherRoleId));
|
||||
|
|
@ -169,12 +186,19 @@ public class TeacherServiceImpl implements ITeacherService {
|
|||
queryWrapper.eq("account", admin.getAccount());
|
||||
queryWrapper.isNull("delete_time");
|
||||
Admin admin1 = adminMapper.selectOne(queryWrapper);
|
||||
// 创建附属教师信息
|
||||
// 创建教师信息(注意:新表结构没有admin_id字段,所以不存储adminId)
|
||||
Teacher model = new Teacher();
|
||||
BeanUtils.copyProperties(createValidate, model);
|
||||
model.setAdminId(admin1.getId());
|
||||
model.setCreateTime(System.currentTimeMillis()/1000);
|
||||
model.setUpdateTime(System.currentTimeMillis()/1000);
|
||||
model.setTeacherName(createValidate.getName());
|
||||
model.setTeacherCode(teacherCode);
|
||||
model.setCollegeId(createValidate.getCollegeId());
|
||||
model.setContactPhone(createValidate.getContactPhone());
|
||||
model.setContactEmail(createValidate.getContactEmail());
|
||||
if (createValidate.getInvitationCode() != null && !createValidate.getInvitationCode().isEmpty()) {
|
||||
model.setInvitationCode(createValidate.getInvitationCode());
|
||||
}
|
||||
model.setTeacherStatus(1); // 默认在职
|
||||
model.setCreateTime(System.currentTimeMillis() / 1000);
|
||||
model.setUpdateTime(System.currentTimeMillis() / 1000);
|
||||
teacherMapper.insert(model);
|
||||
|
||||
return AjaxResult.success("添加信息成功");
|
||||
|
|
@ -183,24 +207,27 @@ public class TeacherServiceImpl implements ITeacherService {
|
|||
/**
|
||||
* 教师信息扩展编辑
|
||||
*
|
||||
* @author gyp
|
||||
* @param updateValidate 参数
|
||||
* @author gyp
|
||||
*/
|
||||
@Override
|
||||
public void edit(TeacherUpdateValidate updateValidate) {
|
||||
Teacher model = teacherMapper.selectOne(
|
||||
new QueryWrapper<Teacher>()
|
||||
.eq("id", updateValidate.getId())
|
||||
.last("limit 1"));
|
||||
.eq("teacher_id", updateValidate.getTeacherId())
|
||||
.last("limit 1"));
|
||||
|
||||
Assert.notNull(model, "数据不存在!");
|
||||
|
||||
model.setId(updateValidate.getId());
|
||||
model.setAdminId(updateValidate.getAdminId());
|
||||
model.setTeacherId(updateValidate.getTeacherId());
|
||||
model.setTeacherName(updateValidate.getName());
|
||||
model.setCollegeId(updateValidate.getCollegeId());
|
||||
model.setContactPhone(updateValidate.getContactPhone());
|
||||
model.setContactEmail(updateValidate.getContactEmail());
|
||||
model.setTeacherStatus(updateValidate.getTeacherStatus());
|
||||
if (updateValidate.getInvitationCode() != null) {
|
||||
model.setInvitationCode(updateValidate.getInvitationCode());
|
||||
}
|
||||
model.setUpdateTime(System.currentTimeMillis() / 1000);
|
||||
teacherMapper.updateById(model);
|
||||
}
|
||||
|
|
@ -208,52 +235,53 @@ public class TeacherServiceImpl implements ITeacherService {
|
|||
/**
|
||||
* 教师信息扩展删除
|
||||
*
|
||||
* @author gyp
|
||||
* @param id 主键ID
|
||||
* @author gyp
|
||||
*/
|
||||
@Override
|
||||
public void del(Integer id) {
|
||||
Teacher model = teacherMapper.selectOne(
|
||||
new QueryWrapper<Teacher>()
|
||||
.eq("id", id)
|
||||
.last("limit 1"));
|
||||
.eq("teacher_id", id)
|
||||
.last("limit 1"));
|
||||
|
||||
Assert.notNull(model, "数据不存在!");
|
||||
|
||||
teacherMapper.delete(new QueryWrapper<Teacher>().eq("id", id));
|
||||
teacherMapper.delete(new QueryWrapper<Teacher>().eq("teacher_id", id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置教师的角色的ID
|
||||
* */
|
||||
*/
|
||||
@Override
|
||||
public void roleConfig(Integer id) {
|
||||
QueryWrapper<AdminRole> queryWrapper = null;
|
||||
// 存放教师列表
|
||||
List<AdminRole> isTeacher = new ArrayList<>();
|
||||
int originalRoleId = -1; // 初始ID为-1,应该不会出现-1的ID
|
||||
try{
|
||||
try {
|
||||
// 查找原教师配置的所有教师
|
||||
originalRoleId = Integer.parseInt(ConfigUtils.get("teacher", "teacher_role_id"));
|
||||
List<AdminRole> adminRoleList = adminRoleServiceImpl.getAdminIdByRoleId(originalRoleId);
|
||||
isTeacher.addAll(adminRoleList);
|
||||
}catch (NullPointerException ignored){} // 忽视此处因为查找不到的报错
|
||||
} catch (NullPointerException ignored) {
|
||||
} // 忽视此处因为查找不到的报错
|
||||
|
||||
// 若配置不存在,会新建配置
|
||||
ConfigUtils.set("teacher","teacher_role_id",id.toString());
|
||||
ConfigUtils.set("teacher", "teacher_role_id", id.toString());
|
||||
|
||||
// 将原本的所有教师的角色ID更新
|
||||
if(!isTeacher.isEmpty()) {
|
||||
if (!isTeacher.isEmpty()) {
|
||||
// 对每个教师的角色重新分配
|
||||
for (AdminRole adminRole : isTeacher) {
|
||||
List<Integer> roleIds = adminRoleServiceImpl.getRoleIdAttr(adminRole.getAdminId());
|
||||
for(int i = 0; i < roleIds.size(); i++){
|
||||
for (int i = 0; i < roleIds.size(); i++) {
|
||||
// 替换原教师角色
|
||||
if(roleIds.get(i) == originalRoleId){
|
||||
if (roleIds.get(i) == originalRoleId) {
|
||||
roleIds.set(i, id);
|
||||
}
|
||||
// 删除重复分配
|
||||
else if(roleIds.get(i).equals(id)){
|
||||
else if (roleIds.get(i).equals(id)) {
|
||||
roleIds.remove(i);
|
||||
i--;
|
||||
}
|
||||
|
|
@ -275,15 +303,269 @@ public class TeacherServiceImpl implements ITeacherService {
|
|||
return AjaxResult.success(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一教师工号:T + 时间戳秒 + 3位随机数
|
||||
*/
|
||||
private String generateTeacherCode() {
|
||||
String code;
|
||||
do {
|
||||
code = "T" + (System.currentTimeMillis() / 1000) + RandomUtil.randomNumber(3);
|
||||
} while (teacherMapper.selectCount(new QueryWrapper<Teacher>().eq("teacher_code", code)) > 0);
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getNameById(Integer teacherId) {
|
||||
Teacher teacher = teacherMapper.selectById(teacherId);
|
||||
if(teacher == null){
|
||||
if (teacher == null) {
|
||||
return null;
|
||||
}
|
||||
Admin admin = adminMapper.selectById(teacher.getAdminId());
|
||||
if(admin == null){
|
||||
return teacher.getTeacherName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成邀请码和二维码
|
||||
*
|
||||
* @param teacherId 教师ID
|
||||
* @return AjaxResult<String> 返回生成的邀请码
|
||||
*/
|
||||
@Override
|
||||
public AjaxResult<Object> generateInvitationCode(Integer teacherId) {
|
||||
Teacher teacher = teacherMapper.selectOne(
|
||||
new QueryWrapper<Teacher>()
|
||||
.eq("teacher_id", teacherId)
|
||||
.last("limit 1"));
|
||||
|
||||
Assert.notNull(teacher, "教师不存在!");
|
||||
|
||||
// 生成唯一邀请码:INV + 时间戳(秒) + 6位随机字符串
|
||||
String invitationCode;
|
||||
do {
|
||||
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
String randomStr = ToolUtils.randomString(6).toUpperCase();
|
||||
invitationCode = "INV" + timestamp + randomStr;
|
||||
} while (teacherMapper.selectCount(
|
||||
new QueryWrapper<Teacher>()
|
||||
.eq("invitation_code", invitationCode)
|
||||
.ne("teacher_id", teacherId)) > 0);
|
||||
|
||||
// 生成二维码内容URL(预报名页面地址)
|
||||
String qrCodeContent = buildQrCodeUrl(invitationCode);
|
||||
|
||||
// 生成二维码图片并保存
|
||||
String qrcodeUrl = generateAndSaveQrCode(invitationCode, qrCodeContent, teacherId);
|
||||
|
||||
// 更新教师表的邀请码和二维码地址
|
||||
teacher.setInvitationCode(invitationCode);
|
||||
teacher.setQrcodeUrl(qrcodeUrl);
|
||||
teacher.setUpdateTime(System.currentTimeMillis() / 1000);
|
||||
teacherMapper.updateById(teacher);
|
||||
|
||||
return AjaxResult.success(invitationCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建二维码内容URL(预报名页面地址)
|
||||
*
|
||||
* @param invitationCode 邀请码
|
||||
* @return 完整的预报名页面URL
|
||||
*/
|
||||
private String buildQrCodeUrl(String invitationCode) {
|
||||
// 优先从配置中读取预报名H5地址(建议配置为 uniapp H5 根,如:https://xx.com/h5)
|
||||
String h5BaseUrl = ConfigUtils.get("pre_registration", "front_url", "");
|
||||
|
||||
if (h5BaseUrl == null || h5BaseUrl.isEmpty()) {
|
||||
// 如果没有单独配置,尝试从 yml 中读取 like.front-url
|
||||
String frontUrl = YmlUtils.get("like.front-url");
|
||||
if (frontUrl != null && !frontUrl.isEmpty()) {
|
||||
h5BaseUrl = frontUrl;
|
||||
} else {
|
||||
// 再退一步,使用当前请求域名
|
||||
h5BaseUrl = UrlUtils.getRequestUrl();
|
||||
}
|
||||
}
|
||||
|
||||
if (h5BaseUrl == null) {
|
||||
h5BaseUrl = "";
|
||||
}
|
||||
|
||||
// 移除末尾的斜杠,方便统一拼接
|
||||
while (h5BaseUrl.endsWith("/")) {
|
||||
h5BaseUrl = h5BaseUrl.substring(0, h5BaseUrl.length() - 1);
|
||||
}
|
||||
|
||||
String fullUrl;
|
||||
if (h5BaseUrl.contains("#/")) {
|
||||
// 如果已经配置了完整的 hash 路径(例如:https://xx.com/h5/#/pages/pre_registration/pre_registration)
|
||||
// 这里只负责追加或合并 invitationCode 参数
|
||||
if (h5BaseUrl.contains("?")) {
|
||||
fullUrl = h5BaseUrl + "&invitationCode=" + invitationCode;
|
||||
} else {
|
||||
fullUrl = h5BaseUrl + "?invitationCode=" + invitationCode;
|
||||
}
|
||||
} else {
|
||||
// 默认拼接为小程序路径(去除H5的hash模式,以便微信扫码直接进入小程序):
|
||||
// {h5BaseUrl}/pages/pre_registration/pre_registration?invitationCode=xxx
|
||||
fullUrl = h5BaseUrl
|
||||
/*+ "/pages/pre_registration/pre_registration.html"
|
||||
+ "?invitationCode=" + invitationCode*/;
|
||||
}
|
||||
|
||||
return fullUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成二维码图片并保存(方案B:本地存储,预留方案A:OSS上传)
|
||||
*
|
||||
* @param invitationCode 邀请码
|
||||
* @param qrCodeContent 二维码内容
|
||||
* @param teacherId 教师ID
|
||||
* @return 二维码图片的相对路径URL
|
||||
*/
|
||||
private String generateAndSaveQrCode(String invitationCode, String qrCodeContent, Integer teacherId) {
|
||||
try {
|
||||
// 二维码图片尺寸
|
||||
int qrCodeWidth = 300;
|
||||
int qrCodeHeight = 300;
|
||||
|
||||
// 获取存储引擎配置
|
||||
String engine = ConfigUtils.get("storage", "default", "local");
|
||||
engine = engine == null || engine.isEmpty() ? "local" : engine;
|
||||
|
||||
String qrcodeUrl;
|
||||
String date = TimeUtils.timestampToDate(TimeUtils.timestamp(), "yyyyMMdd");
|
||||
String fileName = "teacher_" + teacherId + "_" + invitationCode + ".png";
|
||||
String fileKey = date + "/" + fileName;
|
||||
|
||||
if ("local".equals(engine)) {
|
||||
// ========== 方案B:本地存储 ==========
|
||||
String directory = YmlUtils.get("like.upload-directory");
|
||||
if (directory == null || directory.isEmpty()) {
|
||||
throw new OperateException("请配置上传目录like.upload-directory");
|
||||
}
|
||||
|
||||
String folder = "qrcode/teacher";
|
||||
String savePath = (directory + folder + "/" + date).replace("\\", "/");
|
||||
File saveDir = new File(savePath);
|
||||
if (!saveDir.exists()) {
|
||||
if (!saveDir.mkdirs()) {
|
||||
throw new OperateException("创建二维码保存目录失败");
|
||||
}
|
||||
}
|
||||
|
||||
File qrCodeFile = new File(savePath, fileName);
|
||||
QrCodeUtil.generateQrCodeToFile(qrCodeContent, qrCodeWidth, qrCodeHeight, qrCodeFile.getAbsolutePath());
|
||||
|
||||
// 返回相对路径
|
||||
qrcodeUrl = folder + "/" + fileKey;
|
||||
|
||||
} else {
|
||||
// ========== 方案A:OSS上传(预留代码) ==========
|
||||
// 注意:OSS上传需要MultipartFile,这里需要将byte[]转换为临时文件再上传
|
||||
// 或者直接使用OSS的putObject方法上传字节流
|
||||
|
||||
// 方案A-1:使用临时文件上传(适用于所有OSS)
|
||||
File tempFile = File.createTempFile("qrcode_", ".png");
|
||||
try {
|
||||
QrCodeUtil.generateQrCodeToFile(qrCodeContent, qrCodeWidth, qrCodeHeight, tempFile.getAbsolutePath());
|
||||
|
||||
String folder = "qrcode/teacher";
|
||||
String ossKey = folder + "/" + fileKey;
|
||||
|
||||
if ("aliyun".equals(engine)) {
|
||||
// 阿里云OSS上传
|
||||
/*
|
||||
Map<String, String> config = ConfigUtils.getMap("storage", "aliyun");
|
||||
AliyunStorage aliyunStorage = new AliyunStorage(config);
|
||||
// 需要将File转换为MultipartFile或使用OSS的putObject方法
|
||||
// 这里使用OSS直接上传字节流的方式
|
||||
com.aliyun.oss.OSS ossClient = aliyunStorage.ossClient();
|
||||
try {
|
||||
ossClient.putObject(config.get("bucket"), ossKey, new FileInputStream(tempFile));
|
||||
qrcodeUrl = ossKey;
|
||||
} finally {
|
||||
ossClient.shutdown();
|
||||
}
|
||||
*/
|
||||
// TODO: 实现阿里云OSS上传逻辑
|
||||
qrcodeUrl = ossKey;
|
||||
} else if ("qiniu".equals(engine)) {
|
||||
// 七牛云上传
|
||||
// TODO: 实现七牛云上传逻辑
|
||||
qrcodeUrl = ossKey;
|
||||
} else if ("qcloud".equals(engine)) {
|
||||
// 腾讯云COS上传
|
||||
// TODO: 实现腾讯云COS上传逻辑
|
||||
qrcodeUrl = ossKey;
|
||||
} else {
|
||||
throw new OperateException("不支持的存储引擎: " + engine);
|
||||
}
|
||||
} finally {
|
||||
// 删除临时文件
|
||||
if (tempFile.exists()) {
|
||||
tempFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return qrcodeUrl;
|
||||
|
||||
} catch (WriterException | IOException e) {
|
||||
throw new OperateException("生成二维码失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取二维码图片URL
|
||||
*
|
||||
* @param teacherId 教师ID
|
||||
* @return AjaxResult<String> 返回二维码图片的绝对URL
|
||||
*/
|
||||
@Override
|
||||
public AjaxResult<Object> getQrCodeUrl(Integer teacherId) {
|
||||
Teacher teacher = teacherMapper.selectOne(
|
||||
new QueryWrapper<Teacher>()
|
||||
.eq("teacher_id", teacherId)
|
||||
.last("limit 1"));
|
||||
|
||||
Assert.notNull(teacher, "教师不存在!");
|
||||
|
||||
if (teacher.getQrcodeUrl() == null || teacher.getQrcodeUrl().isEmpty()) {
|
||||
return AjaxResult.failed("该教师尚未生成二维码,请先生成邀请码");
|
||||
}
|
||||
|
||||
// 转换为后台端可访问的绝对URL(/adminapi/uploads/**)
|
||||
String absoluteUrl = UrlUtils.toAdminAbsoluteUrl(teacher.getQrcodeUrl());
|
||||
return AjaxResult.success(absoluteUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getQrCodeImageBytes(Integer teacherId) {
|
||||
Teacher teacher = teacherMapper.selectOne(
|
||||
new QueryWrapper<Teacher>()
|
||||
.eq("teacher_id", teacherId)
|
||||
.last("limit 1"));
|
||||
if (teacher == null || teacher.getQrcodeUrl() == null || teacher.getQrcodeUrl().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
String engine = ConfigUtils.get("storage", "default", "local");
|
||||
engine = engine == null || engine.isEmpty() ? "local" : engine;
|
||||
if (!"local".equals(engine)) {
|
||||
return null;
|
||||
}
|
||||
String directory = YmlUtils.get("like.upload-directory");
|
||||
if (directory == null || directory.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
String path = teacher.getQrcodeUrl().startsWith("/") ? teacher.getQrcodeUrl() : "/" + teacher.getQrcodeUrl();
|
||||
String fullPath = (directory + path).replace("\\", "/");
|
||||
java.io.File file = new java.io.File(fullPath);
|
||||
if (!file.exists() || !file.isFile()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return java.nio.file.Files.readAllBytes(file.toPath());
|
||||
} catch (java.io.IOException e) {
|
||||
return null;
|
||||
}
|
||||
return admin.getName();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,9 @@ public class TeachingTaskServiceImpl implements ITeachingTaskService {
|
|||
Course course = courseMapper.selectById(courseId);
|
||||
Teacher teacher = teacherMapper.selectById(teacherId);
|
||||
Class clazz = classMapper.selectById(classId);
|
||||
Admin adminTeacher = adminMapper.selectById(teacher.getAdminId());
|
||||
Admin adminTeacher = adminMapper.selectOne(
|
||||
new QueryWrapper<Admin>()
|
||||
.eq("account", teacher.getTeacherCode()));
|
||||
Admin adminCreator = adminMapper.selectById(createdBy);
|
||||
Admin adminUpdater = adminMapper.selectById(updatedBy);
|
||||
vo.setSemesterName(semester.getSemesterName());
|
||||
|
|
@ -131,7 +133,9 @@ public class TeachingTaskServiceImpl implements ITeachingTaskService {
|
|||
Course course = courseMapper.selectById(courseId);
|
||||
Teacher teacher = teacherMapper.selectById(teacherId);
|
||||
Class clazz = classMapper.selectById(classId);
|
||||
Admin adminTeacher = adminMapper.selectById(teacher.getAdminId());
|
||||
Admin adminTeacher = adminMapper.selectOne(
|
||||
new QueryWrapper<Admin>()
|
||||
.eq("account", teacher.getTeacherCode()));
|
||||
vo.setSemesterName(semester.getSemesterName());
|
||||
vo.setCourseName(course.getCourseName());
|
||||
vo.setClassName(clazz.getClassName());
|
||||
|
|
@ -248,7 +252,7 @@ public class TeachingTaskServiceImpl implements ITeachingTaskService {
|
|||
for(Teacher teacher : teachers){
|
||||
// 将在名单的教师记录
|
||||
for(TeacherCourse teacherCourse : teacherCourses){
|
||||
if(teacher.getId().equals(teacherCourse.getTeacherId())){
|
||||
if(teacher.getTeacherId().equals(teacherCourse.getTeacherId())){
|
||||
teacherIds.add(teacherCourse.getTeacherId());
|
||||
}
|
||||
}
|
||||
|
|
@ -257,7 +261,7 @@ public class TeachingTaskServiceImpl implements ITeachingTaskService {
|
|||
}
|
||||
List<Integer> teacherIds = new ArrayList<>();
|
||||
for (Teacher teacher : teachers) {
|
||||
teacherIds.add(teacher.getId());
|
||||
teacherIds.add(teacher.getTeacherId());
|
||||
}
|
||||
return AjaxResult.success(teacherIds);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,4 +50,10 @@ public class StudentInfoSearchValidate implements Serializable {
|
|||
@ApiModelProperty(value = "认证人ID")
|
||||
private Integer verifiedBy;
|
||||
|
||||
@ApiModelProperty(value = "招生老师ID")
|
||||
private Integer recruitmentTeacherId;
|
||||
|
||||
@ApiModelProperty(value = "接待老师ID")
|
||||
private Integer receptionTeacherId;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@ public class TeacherCreateValidate implements Serializable {
|
|||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@NotEmpty(message = "账号不能为空")
|
||||
@ApiModelProperty(value = "教师工号", required = true)
|
||||
@ApiModelProperty(value = "教师工号(系统自动生成)")
|
||||
private String teacherCode;
|
||||
|
||||
@NotEmpty(message = "姓名不能为空")
|
||||
|
|
@ -31,4 +30,7 @@ public class TeacherCreateValidate implements Serializable {
|
|||
|
||||
@ApiModelProperty(value = "联系邮箱")
|
||||
private String contactEmail;
|
||||
|
||||
@ApiModelProperty(value = "邀请码(二维码地址标识)")
|
||||
private String invitationCode;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,9 +14,6 @@ public class TeacherSearchValidate implements Serializable {
|
|||
@ApiModelProperty(value = "姓名")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "关联管理员ID")
|
||||
private Integer adminId;
|
||||
|
||||
@ApiModelProperty(value = "教师工号")
|
||||
private String teacherCode;
|
||||
|
||||
|
|
@ -26,4 +23,7 @@ public class TeacherSearchValidate implements Serializable {
|
|||
@ApiModelProperty(value = "教师状态:1-在职,2-休假,3-离职")
|
||||
private Integer teacherStatus;
|
||||
|
||||
@ApiModelProperty(value = "邀请码(二维码地址标识)")
|
||||
private String invitationCode;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@ public class TeacherUpdateValidate implements Serializable {
|
|||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@IDMust(message = "id参数必传且需大于0")
|
||||
@ApiModelProperty(value = "")
|
||||
private Integer id;
|
||||
@IDMust(message = "teacherId参数必传且需大于0")
|
||||
@ApiModelProperty(value = "教师ID")
|
||||
private Integer teacherId;
|
||||
|
||||
@ApiModelProperty(value = "关联管理员ID")
|
||||
private Integer adminId;
|
||||
@ApiModelProperty(value = "姓名")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "教师工号")
|
||||
private String teacherCode;
|
||||
|
|
@ -42,4 +42,7 @@ public class TeacherUpdateValidate implements Serializable {
|
|||
@ApiModelProperty(value = "教师状态:1-在职,2-休假,3-离职")
|
||||
private Integer teacherStatus;
|
||||
|
||||
@ApiModelProperty(value = "邀请码(二维码地址标识)")
|
||||
private String invitationCode;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import lombok.Data;
|
|||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@ApiModel("学生信息列表Vo")
|
||||
|
|
@ -71,6 +72,18 @@ public class StudentInfoListedVo implements Serializable {
|
|||
@ApiModelProperty(value = "学业预警: [0=无, 1=一级预警, 2=二级预警, 3=三级预警]")
|
||||
private Integer academicWarnings;
|
||||
|
||||
@ApiModelProperty(value = "中考成绩")
|
||||
private BigDecimal highSchoolScore;
|
||||
|
||||
@ApiModelProperty(value = "预报名金额")
|
||||
private BigDecimal preRegistrationAmount;
|
||||
|
||||
@ApiModelProperty(value = "招生老师ID")
|
||||
private Integer recruitmentTeacherId;
|
||||
|
||||
@ApiModelProperty(value = "接待老师ID")
|
||||
private Integer receptionTeacherId;
|
||||
|
||||
@ApiModelProperty(value = "是否认证: [0=未认证, 1=已认证]")
|
||||
private Integer isVerified;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,15 +12,12 @@ public class TeacherDetailVo implements Serializable {
|
|||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty(value = "")
|
||||
private Integer id;
|
||||
@ApiModelProperty(value = "教师ID")
|
||||
private Integer teacherId;
|
||||
|
||||
@ApiModelProperty(value = "姓名")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "关联管理员ID")
|
||||
private Integer adminId;
|
||||
|
||||
@ApiModelProperty(value = "教师工号")
|
||||
private String teacherCode;
|
||||
|
||||
|
|
@ -42,5 +39,10 @@ public class TeacherDetailVo implements Serializable {
|
|||
@ApiModelProperty(value = "教师状态:1-在职,2-休假,3-离职")
|
||||
private Integer teacherStatus;
|
||||
|
||||
@ApiModelProperty(value = "邀请码(二维码地址标识)")
|
||||
private String invitationCode;
|
||||
|
||||
@ApiModelProperty(value = "二维码图片地址")
|
||||
private String qrcodeUrl;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,15 +12,12 @@ public class TeacherListedVo implements Serializable {
|
|||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty(value = "")
|
||||
private Integer id;
|
||||
@ApiModelProperty(value = "教师ID")
|
||||
private Integer teacherId;
|
||||
|
||||
@ApiModelProperty(value = "姓名")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "关联管理员ID")
|
||||
private Integer adminId;
|
||||
|
||||
@ApiModelProperty(value = "学院名")
|
||||
private String collegeName;
|
||||
|
||||
|
|
@ -42,6 +39,12 @@ public class TeacherListedVo implements Serializable {
|
|||
@ApiModelProperty(value = "教师状态:1-在职,2-休假,3-离职")
|
||||
private Integer teacherStatus;
|
||||
|
||||
@ApiModelProperty(value = "邀请码(二维码地址标识)")
|
||||
private String invitationCode;
|
||||
|
||||
@ApiModelProperty(value = "二维码图片地址")
|
||||
private String qrcodeUrl;
|
||||
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
private String createTime;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,13 +15,17 @@ public class Teacher implements Serializable {
|
|||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value="id", type= IdType.AUTO)
|
||||
@ApiModelProperty(value = "")
|
||||
private Integer id;
|
||||
@TableId(value="teacher_id", type= IdType.AUTO)
|
||||
@ApiModelProperty(value = "教师ID")
|
||||
private Integer teacherId;
|
||||
|
||||
@TableField("admin_id")
|
||||
@ApiModelProperty(value = "关联管理员ID")
|
||||
private Integer adminId;
|
||||
@TableField("teacher_name")
|
||||
@ApiModelProperty(value = "教师姓名")
|
||||
private String teacherName;
|
||||
|
||||
@TableField("teacher_code")
|
||||
@ApiModelProperty(value = "教师工号")
|
||||
private String teacherCode;
|
||||
|
||||
@ApiModelProperty(value = "所属院系ID")
|
||||
private Integer collegeId;
|
||||
|
|
@ -35,6 +39,14 @@ public class Teacher implements Serializable {
|
|||
@ApiModelProperty(value = "教师状态:1-在职,2-休假,3-离职")
|
||||
private Integer teacherStatus;
|
||||
|
||||
@TableField("invitation_code")
|
||||
@ApiModelProperty(value = "邀请码(二维码地址标识)")
|
||||
private String invitationCode;
|
||||
|
||||
@TableField("qrcode_url")
|
||||
@ApiModelProperty(value = "二维码图片地址")
|
||||
private String qrcodeUrl;
|
||||
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
private Long createTime;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
package com.mdd.common.util;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.QRCodeWriter;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 二维码生成工具类
|
||||
*/
|
||||
public class QrCodeUtil {
|
||||
|
||||
/**
|
||||
* 生成二维码图片并保存到文件
|
||||
*
|
||||
* @param content 二维码内容
|
||||
* @param width 图片宽度
|
||||
* @param height 图片高度
|
||||
* @param filePath 保存文件路径
|
||||
* @throws WriterException 写入异常
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static void generateQrCodeToFile(String content, int width, int height, String filePath) throws WriterException, IOException {
|
||||
BufferedImage image = generateQrCodeImage(content, width, height);
|
||||
File file = new File(filePath);
|
||||
// 确保父目录存在
|
||||
File parentDir = file.getParentFile();
|
||||
if (parentDir != null && !parentDir.exists()) {
|
||||
parentDir.mkdirs();
|
||||
}
|
||||
ImageIO.write(image, "png", file);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成二维码图片(BufferedImage)
|
||||
*
|
||||
* @param content 二维码内容
|
||||
* @param width 图片宽度
|
||||
* @param height 图片高度
|
||||
* @return BufferedImage
|
||||
* @throws WriterException 写入异常
|
||||
*/
|
||||
public static BufferedImage generateQrCodeImage(String content, int width, int height) throws WriterException {
|
||||
Map<EncodeHintType, Object> hints = new HashMap<>();
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
|
||||
hints.put(EncodeHintType.MARGIN, 1);
|
||||
|
||||
QRCodeWriter qrCodeWriter = new QRCodeWriter();
|
||||
BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
|
||||
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D graphics = image.createGraphics();
|
||||
graphics.setColor(Color.WHITE);
|
||||
graphics.fillRect(0, 0, width, height);
|
||||
graphics.setColor(Color.BLACK);
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (bitMatrix.get(x, y)) {
|
||||
graphics.fillRect(x, y, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
graphics.dispose();
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成二维码图片字节数组
|
||||
*
|
||||
* @param content 二维码内容
|
||||
* @param width 图片宽度
|
||||
* @param height 图片高度
|
||||
* @return 图片字节数组
|
||||
* @throws WriterException 写入异常
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static byte[] generateQrCodeBytes(String content, int width, int height) throws WriterException, IOException {
|
||||
BufferedImage image = generateQrCodeImage(content, width, height);
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
ImageIO.write(image, "png", outputStream);
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue