14 changed files with 840 additions and 71 deletions
@ -0,0 +1,109 @@ |
|||||||
|
package apelet.association.controller; |
||||||
|
|
||||||
|
import apelet.association.utils.DataTransformationUtil; |
||||||
|
import apelet.common.core.object.ObjectCollection; |
||||||
|
import apelet.common.core.object.ObjectValue; |
||||||
|
import apelet.common.core.object.ResponseResult; |
||||||
|
import apelet.common.generator.utils.OrmGenDataSourceUtil; |
||||||
|
import apelet.common.orm.impl.Filter; |
||||||
|
import apelet.common.orm.impl.FilterItem; |
||||||
|
import apelet.common.orm.impl.Selector; |
||||||
|
import cn.hutool.core.util.ObjectUtil; |
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.web.bind.annotation.*; |
||||||
|
|
||||||
|
import java.util.*; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
@RestController |
||||||
|
@RequestMapping("/tenantadmin/activity") |
||||||
|
public class AssociationActivitiesController { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private OrmGenDataSourceUtil ormGenDataSourceUtil; |
||||||
|
|
||||||
|
/** |
||||||
|
* 签到/签退 |
||||||
|
* |
||||||
|
* @param jsonObject |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@PostMapping("/checkInOut") |
||||||
|
public ResponseResult<?> activityCheckIn(@RequestBody JSONObject jsonObject) throws Exception { |
||||||
|
String activityId = jsonObject.getString("activityId"); |
||||||
|
String activityName = jsonObject.getString("activityName"); |
||||||
|
if (StringUtils.isEmpty(activityId) || StringUtils.isEmpty(activityName)) { |
||||||
|
return ResponseResult.error("500", "活动信息为空!!!"); |
||||||
|
} |
||||||
|
String signInPerson = jsonObject.getString("signInPerson"); |
||||||
|
if (StringUtils.isEmpty(signInPerson)) { |
||||||
|
return ResponseResult.error("500", "签到人为空!!!"); |
||||||
|
} |
||||||
|
String phoneNumber = jsonObject.getString("phoneNumber"); |
||||||
|
if (StringUtils.isEmpty(phoneNumber)) { |
||||||
|
return ResponseResult.error("500", "用户手机号为空!!!"); |
||||||
|
} |
||||||
|
|
||||||
|
String signInUnit = jsonObject.getString("signInUnit"); |
||||||
|
if (StringUtils.isEmpty(signInUnit)) { |
||||||
|
return ResponseResult.error("500", "签到单位为空!!!"); |
||||||
|
} |
||||||
|
Integer type = jsonObject.getInteger("type"); |
||||||
|
|
||||||
|
Filter filter = new Filter(); |
||||||
|
filter.add(new FilterItem("unit_name", FilterItem.equals, signInUnit)); |
||||||
|
ObjectCollection collection = ormGenDataSourceUtil.query("membership_apply", filter, new Selector()); |
||||||
|
|
||||||
|
if (collection == null || collection.isEmpty()) { |
||||||
|
return ResponseResult.error("500", "签到单位不存在, 请检查签到单位!!!"); |
||||||
|
} |
||||||
|
|
||||||
|
ObjectCollection managerCollection = ormGenDataSourceUtil.query("membership_manager", new Filter(), new Selector()); |
||||||
|
List<Map<String, Object>> managerList = DataTransformationUtil.objectCollectionToList(managerCollection); |
||||||
|
Map<String, Map<String, Object>> mapMap = managerList.stream().collect(Collectors.toMap(map -> String.valueOf(map.get("id")), map -> map, (oldValue, newValue) -> oldValue)); |
||||||
|
|
||||||
|
ObjectValue member = null; |
||||||
|
for (int i = 0; i < collection.size(); i++) { |
||||||
|
ObjectValue object = collection.getObject(i); |
||||||
|
ObjectValue manger = object.getObjectValue("membership_manger_id"); |
||||||
|
Map<String, Object> map = mapMap.get(manger != null && manger.get("id") != null ? manger.get("id") : ""); |
||||||
|
Object phone = map.get("phone"); |
||||||
|
if (ObjectUtil.equal(phone, phoneNumber)) { |
||||||
|
member = object; |
||||||
|
} |
||||||
|
} |
||||||
|
if (member == null) { |
||||||
|
return ResponseResult.error("500", signInUnit + " 签到单位下签到人不存在!!!"); |
||||||
|
} |
||||||
|
if (type == 1) { |
||||||
|
//签到
|
||||||
|
ObjectValue value = new ObjectValue("check_in_out"); |
||||||
|
value.put("name", signInPerson); |
||||||
|
value.put("phone", phoneNumber); |
||||||
|
value.put("membership_id", member); |
||||||
|
value.put("create_time", new Date()); |
||||||
|
value.put("create_time", new Date()); |
||||||
|
value.put("parent_id", activityId); |
||||||
|
value.put("check_in", 1); |
||||||
|
ormGenDataSourceUtil.addNew(value.getTableName(), value); |
||||||
|
} |
||||||
|
if (type == 2) { |
||||||
|
//签退
|
||||||
|
filter = new Filter(); |
||||||
|
filter.add(new FilterItem("membership_id", FilterItem.equals, member.get("id"))); |
||||||
|
filter.add(new FilterItem("parent_id", FilterItem.equals, activityId)); |
||||||
|
filter.add(new FilterItem("check_in", FilterItem.equals, 1)); |
||||||
|
collection = ormGenDataSourceUtil.query("check_in_out", filter, new Selector()); |
||||||
|
if (collection != null && !collection.isEmpty()) { |
||||||
|
ObjectValue object = collection.getObject(0); |
||||||
|
object.put("check_out", 1); |
||||||
|
ormGenDataSourceUtil.update("check_in_out", object, new Selector()); |
||||||
|
} |
||||||
|
} |
||||||
|
return ResponseResult.success("签到成功!!!"); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,49 @@ |
|||||||
|
package apelet.association.plugin.active; |
||||||
|
|
||||||
|
import apelet.common.core.exception.MyRuntimeException; |
||||||
|
import apelet.common.core.object.ObjectValue; |
||||||
|
import apelet.common.core.util.ApplicationContextHolder; |
||||||
|
import apelet.common.generator.utils.OrmGenDataSourceUtil; |
||||||
|
import apelet.common.online.abstractplugin.ListPlugin; |
||||||
|
import apelet.common.online.dto.OnlineEventPluginExecuteDto; |
||||||
|
import apelet.common.online.model.constant.AttributeEnum; |
||||||
|
import apelet.common.orm.impl.Selector; |
||||||
|
|
||||||
|
/** |
||||||
|
* 活动日程插件 |
||||||
|
*/ |
||||||
|
public class ActivitySchedulePlugin extends ListPlugin { |
||||||
|
|
||||||
|
private OrmGenDataSourceUtil ormGenDataSourceUtil; |
||||||
|
|
||||||
|
public ActivitySchedulePlugin() { |
||||||
|
ormGenDataSourceUtil = ApplicationContextHolder.getBean(OrmGenDataSourceUtil.class); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void formCreated(String widgetVariableName, ObjectValue objectValue) { |
||||||
|
OnlineEventPluginExecuteDto dto = getDto(); |
||||||
|
this.setWidgetAttribute("id", AttributeEnum.SHOW, false); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void change(String widgetVariableName, ObjectValue objectValue) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void buttonTriggered(String widgetVariableName, ObjectValue objectValue) { |
||||||
|
if ("保存".equals(widgetVariableName)) { |
||||||
|
try { |
||||||
|
ObjectValue value = ormGenDataSourceUtil.queryOne("association_activity", objectValue.get("id")); |
||||||
|
value.put("activity_schedule", objectValue.getObjectCollection("activity_schedule")); |
||||||
|
ormGenDataSourceUtil.update("association_activity", value, new Selector()); |
||||||
|
} catch (Exception e) { |
||||||
|
throw new MyRuntimeException(e.getMessage()); |
||||||
|
} |
||||||
|
this.cancelOperate(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,153 @@ |
|||||||
|
package apelet.association.plugin.active; |
||||||
|
|
||||||
|
import apelet.association.utils.MyFileUtil; |
||||||
|
import apelet.association.utils.QRCodeUtil; |
||||||
|
import apelet.common.core.exception.MyRuntimeException; |
||||||
|
import apelet.common.core.object.*; |
||||||
|
import apelet.common.core.upload.*; |
||||||
|
import apelet.common.core.util.ApplicationContextHolder; |
||||||
|
import apelet.common.generator.utils.OrmGenDataSourceUtil; |
||||||
|
import apelet.common.online.abstractplugin.ListPlugin; |
||||||
|
import apelet.common.online.dto.OnlineEventPluginExecuteDto; |
||||||
|
import apelet.common.online.model.OnlineDatasource; |
||||||
|
import apelet.common.online.model.OnlineTable; |
||||||
|
import apelet.common.online.model.constant.AttributeEnum; |
||||||
|
import apelet.common.online.service.OnlineColumnService; |
||||||
|
import apelet.common.online.service.OnlineDatasourceService; |
||||||
|
import apelet.common.online.service.OnlineTableService; |
||||||
|
import apelet.common.orm.impl.*; |
||||||
|
import com.alibaba.fastjson.JSON; |
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.apache.commons.io.FileUtils; |
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
import org.springframework.web.multipart.MultipartFile; |
||||||
|
|
||||||
|
import java.io.*; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* 活动签到配置插件 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
public class ActivitySignConfigPlugin extends ListPlugin { |
||||||
|
|
||||||
|
private MyFileUtil myFileUtil; |
||||||
|
private QRCodeUtil qrCodeUtil; |
||||||
|
|
||||||
|
private OnlineTableService onlineTableService; |
||||||
|
private OnlineColumnService onlineColumnService; |
||||||
|
private OrmGenDataSourceUtil ormGenDataSourceUtil; |
||||||
|
|
||||||
|
|
||||||
|
private OnlineDatasourceService onlineDatasourceService; |
||||||
|
|
||||||
|
|
||||||
|
public ActivitySignConfigPlugin() { |
||||||
|
myFileUtil = ApplicationContextHolder.getBean(MyFileUtil.class); |
||||||
|
qrCodeUtil = ApplicationContextHolder.getBean(QRCodeUtil.class); |
||||||
|
onlineTableService = ApplicationContextHolder.getBean(OnlineTableService.class); |
||||||
|
onlineColumnService = ApplicationContextHolder.getBean(OnlineColumnService.class); |
||||||
|
ormGenDataSourceUtil = ApplicationContextHolder.getBean(OrmGenDataSourceUtil.class); |
||||||
|
onlineDatasourceService = ApplicationContextHolder.getBean(OnlineDatasourceService.class); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void formCreated(String widgetVariableName, ObjectValue objectValue) { |
||||||
|
OnlineEventPluginExecuteDto dto = getDto(); |
||||||
|
Map parentParams = dto.getParentParams(); |
||||||
|
Object activityId = parentParams.get("id"); |
||||||
|
this.setWidgetAttribute("activityId", AttributeEnum.VALUE_CHANGE, parentParams); |
||||||
|
Filter filter = new Filter(); |
||||||
|
filter.add(new FilterItem("activity_id", FilterItem.equals, activityId)); |
||||||
|
Object data = ormGenDataSourceUtil.queryData("orm", "activity_sign_config", filter, new Selector(), new Sorter(), new HashMap<>()); |
||||||
|
if (data instanceof ObjectCollection) { |
||||||
|
ObjectCollection collection = (ObjectCollection) data; |
||||||
|
ObjectValue object = collection.getObject(0); |
||||||
|
this.setWidgetAttribute("id", AttributeEnum.VALUE_CHANGE, object.get("id")); |
||||||
|
|
||||||
|
this.setWidgetAttribute("checkAction", AttributeEnum.VALUE_CHANGE, object.get("check_action")); |
||||||
|
|
||||||
|
this.setWidgetAttribute("scanCheck", AttributeEnum.VALUE_CHANGE, object.getInt("scan_check")); |
||||||
|
this.setWidgetAttribute("positionLimit", AttributeEnum.VALUE_CHANGE, object.getInt("position_limit")); |
||||||
|
this.setWidgetAttribute("duplicateCheck", AttributeEnum.VALUE_CHANGE, object.getInt("duplicate_check")); |
||||||
|
this.setWidgetAttribute("scanCodeReview", AttributeEnum.VALUE_CHANGE, object.getInt("scan_code_review")); |
||||||
|
this.setWidgetAttribute("checkCertificate", AttributeEnum.VALUE_CHANGE, object.getInt("id")); |
||||||
|
|
||||||
|
try { |
||||||
|
JSONObject signInCode = JSON.parseObject(object.getString("sign_in_code")); |
||||||
|
this.setWidgetAttribute("signInCode", AttributeEnum.VALUE_CHANGE, signInCode); |
||||||
|
|
||||||
|
JSONObject signOutCode = JSON.parseObject(object.getString("sign_out_code")); |
||||||
|
this.setWidgetAttribute("signOutCode", AttributeEnum.VALUE_CHANGE, signOutCode); |
||||||
|
} catch (Exception ee) { |
||||||
|
log.error("二维码数据转换失败!!!"); |
||||||
|
ee.printStackTrace(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
this.setWidgetAttribute("id", AttributeEnum.SHOW, false); |
||||||
|
this.setWidgetAttribute("activityId", AttributeEnum.SHOW, false); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void buttonTriggered(String widgetVariableName, ObjectValue objectValue) { |
||||||
|
OnlineEventPluginExecuteDto dto = getDto(); |
||||||
|
Model model = dto.getModel(); |
||||||
|
if ("button1778742711763".equals(widgetVariableName)) { |
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(objectValue.getString("sign_in_code")) && |
||||||
|
StringUtils.isNotBlank(objectValue.getString("sign_out_code"))) { |
||||||
|
showWarningMessage("当前已存在二维码, 请勿重复生产!!!"); |
||||||
|
return; |
||||||
|
} |
||||||
|
// 生成二维码
|
||||||
|
String savePath = System.getProperty("user.dir") + "\\zz-resource\\qrcode"; |
||||||
|
|
||||||
|
File checkOutFile; |
||||||
|
File checkInFile; |
||||||
|
try { |
||||||
|
Object activityId = objectValue.get("id"); |
||||||
|
Object activityName = objectValue.get("name"); |
||||||
|
|
||||||
|
OnlineDatasource onlineDatasource = onlineDatasourceService.getById(model.getDatasourceId()); |
||||||
|
OnlineTable table = onlineTableService.getOnlineTableFromCache(onlineDatasource.getMasterTableId()); |
||||||
|
|
||||||
|
String checkIn = "https://localhost:8080/#/pages/login/routerHdView?activityId=" + activityId + "&activityName=" + activityName + "&type=" + 1; |
||||||
|
byte[] checkInQr = qrCodeUtil.generateQrCode(checkIn, 350, 350); |
||||||
|
checkInFile = MyFileUtil.writeToFile(checkInQr, savePath, "qrcode-" + System.currentTimeMillis() + ".png"); |
||||||
|
MultipartFile checkInMultipart = MyFileUtil.readFileAsMultipartFile(checkInFile, "image/png"); |
||||||
|
UploadResponseInfo checkInUpload = myFileUtil.uploadMyFile(table, "sign_in_code", true, checkInMultipart); |
||||||
|
this.setWidgetAttribute("signInCode", AttributeEnum.VALUE_CHANGE, checkInUpload); |
||||||
|
|
||||||
|
String checkOut = "https://localhost:8080/#/pages/login/routerHdView?activityId=" + activityId + "&activityName=" + activityName + "&type=" + 2; |
||||||
|
byte[] checkOutQr = qrCodeUtil.generateQrCode(checkOut, 300, 300); |
||||||
|
checkOutFile = MyFileUtil.writeToFile(checkOutQr, savePath, "qrcode-" + System.currentTimeMillis() + ".png"); |
||||||
|
MultipartFile checkOutMultipart = MyFileUtil.readFileAsMultipartFile(checkOutFile, "image/png"); |
||||||
|
UploadResponseInfo checkOutUpload = myFileUtil.uploadMyFile(table, "sign_out_code", true, checkOutMultipart); |
||||||
|
this.setWidgetAttribute("signOutCode", AttributeEnum.VALUE_CHANGE, checkOutUpload); |
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
throw new MyRuntimeException("二维码生成失败, 请联系管理员!!!"); |
||||||
|
} finally { |
||||||
|
try { |
||||||
|
FileUtils.cleanDirectory(new File(savePath)); |
||||||
|
} catch (IOException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
System.err.println("文件刪除失敗!!!"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void change(String widgetVariableName, ObjectValue objectValue) { |
||||||
|
super.formCreated(widgetVariableName, objectValue); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,73 @@ |
|||||||
|
package apelet.association.task; |
||||||
|
|
||||||
|
|
||||||
|
import apelet.common.core.object.ObjectCollection; |
||||||
|
import apelet.common.core.object.ObjectValue; |
||||||
|
import apelet.common.generator.utils.OrmGenDataSourceUtil; |
||||||
|
import apelet.common.orm.impl.Filter; |
||||||
|
import apelet.common.orm.impl.Selector; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.scheduling.annotation.Scheduled; |
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
import java.time.LocalDate; |
||||||
|
import java.time.ZoneId; |
||||||
|
import java.time.temporal.ChronoUnit; |
||||||
|
import java.util.Date; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class UserRenewalReminderTask { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
OrmGenDataSourceUtil ormGenDataSourceUtil; |
||||||
|
|
||||||
|
// 提前 30 天提醒
|
||||||
|
private static final int REMIND_BEFORE_DAYS = 30; |
||||||
|
// 会员年度天数(固定 365)
|
||||||
|
private static final int YEAR_DAYS = 365; |
||||||
|
|
||||||
|
@Scheduled(cron = "0 0 1 * * ?") |
||||||
|
public void sendRemind(){ |
||||||
|
ObjectCollection collection = ormGenDataSourceUtil.query("membership_apply", new Filter(), new Selector()); |
||||||
|
if(collection == null){ |
||||||
|
return; |
||||||
|
} |
||||||
|
for (int i = 0; i < collection.size(); i++) { |
||||||
|
ObjectValue objectValue = collection.getObject(i); |
||||||
|
Date registTime = objectValue.getDate("regist_time"); |
||||||
|
if (needRemind(registTime)) { |
||||||
|
// TODO 发送消息提示续费
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public boolean needRemind(Date date) { |
||||||
|
LocalDate today = LocalDate.now(); |
||||||
|
LocalDate join = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); |
||||||
|
|
||||||
|
if (today.isBefore(join)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
// 入会到今天总天数
|
||||||
|
long totalDays = ChronoUnit.DAYS.between(join, today); |
||||||
|
|
||||||
|
// 第几个年度(从 1 开始)
|
||||||
|
int yearIndex = (int) (totalDays / YEAR_DAYS) + 1; |
||||||
|
|
||||||
|
// 该年度到期日
|
||||||
|
LocalDate expireDate = join.plusDays((long) YEAR_DAYS * yearIndex); |
||||||
|
|
||||||
|
// 提醒开始日:到期前 30 天
|
||||||
|
LocalDate remindStart = expireDate.minusDays(REMIND_BEFORE_DAYS); |
||||||
|
|
||||||
|
// 今天在 [remindStart, expireDate] 区间内,则提醒
|
||||||
|
return !today.isBefore(remindStart) && !today.isAfter(expireDate); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,27 @@ |
|||||||
|
package apelet.association.utils; |
||||||
|
|
||||||
|
import apelet.common.core.object.ObjectCollection; |
||||||
|
import apelet.common.core.object.ObjectValue; |
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
public class DataTransformationUtil { |
||||||
|
|
||||||
|
public static List<Map<String, Object>> objectCollectionToList(ObjectCollection oc) { |
||||||
|
|
||||||
|
List<Map<String, Object>> list = new ArrayList<>(); |
||||||
|
if(oc == null || oc.isEmpty()){ |
||||||
|
return list; |
||||||
|
} |
||||||
|
for (int i = 0; i < oc.size(); i++) { |
||||||
|
ObjectValue object = oc.getObject(i); |
||||||
|
JSONObject jsonObject = new JSONObject(object.getValues()); |
||||||
|
list.add(jsonObject); |
||||||
|
} |
||||||
|
return list; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,211 @@ |
|||||||
|
package apelet.association.utils; |
||||||
|
|
||||||
|
import apelet.common.core.constant.ErrorCodeEnum; |
||||||
|
import apelet.common.core.object.ResponseResult; |
||||||
|
import apelet.common.core.upload.*; |
||||||
|
import apelet.common.online.config.OnlineProperties; |
||||||
|
import apelet.common.online.model.OnlineColumn; |
||||||
|
import apelet.common.online.model.OnlineTable; |
||||||
|
import apelet.common.online.model.constant.FieldKind; |
||||||
|
|
||||||
|
import liquibase.util.BooleanUtil; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.http.MediaType; |
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
import org.springframework.web.multipart.MultipartFile; |
||||||
|
|
||||||
|
import java.io.*; |
||||||
|
import java.nio.file.*; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class MyFileUtil { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private UpDownloaderFactory upDownloaderFactory; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private OnlineProperties onlineProperties; |
||||||
|
|
||||||
|
|
||||||
|
public UploadResponseInfo uploadMyFile(OnlineTable table, String fieldName, Boolean asImg, MultipartFile multipartFile) throws IOException { |
||||||
|
ResponseResult<OnlineColumn> verifyResult = this.doVerifyUpDownloadFileColumn(table, fieldName, asImg); |
||||||
|
OnlineColumn uploadColumn = verifyResult.getData(); |
||||||
|
UploadStoreTypeEnum uploadStoreType = UploadStoreTypeEnum.values()[uploadColumn.getUploadFileSystemType()]; |
||||||
|
BaseUpDownloader upDownloader = upDownloaderFactory.get(uploadStoreType); |
||||||
|
return upDownloader.doUpload(null, onlineProperties.getUploadFileBaseDir(), table.getModelName(), fieldName, asImg, multipartFile); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public static MultipartFile createMultipartFile(String filePath, String fileName) { |
||||||
|
Path path = Paths.get(filePath); |
||||||
|
return new MultipartFile() { |
||||||
|
@Override |
||||||
|
public String getName() { |
||||||
|
return fileName; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getOriginalFilename() { |
||||||
|
return fileName; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getContentType() { |
||||||
|
try { |
||||||
|
return Files.probeContentType(path); |
||||||
|
} catch (IOException e) { |
||||||
|
return MediaType.APPLICATION_OCTET_STREAM_VALUE; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isEmpty() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public long getSize() { |
||||||
|
try { |
||||||
|
return Files.size(path); |
||||||
|
} catch (IOException e) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public byte[] getBytes() throws IOException { |
||||||
|
return Files.readAllBytes(path); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public InputStream getInputStream() throws IOException { |
||||||
|
return Files.newInputStream(path); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void transferTo(File dest) throws IOException { |
||||||
|
Files.copy(path, dest.toPath(), StandardCopyOption.REPLACE_EXISTING); |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public static void saveFileToLocal(byte[] qrCodeByte, String savePath, String fileName) throws IOException { |
||||||
|
// 1. 创建文件夹
|
||||||
|
File folder = new File(savePath); |
||||||
|
if (!folder.exists()) { |
||||||
|
folder.mkdirs(); |
||||||
|
} |
||||||
|
// 2. 最终文件
|
||||||
|
File file = new File(folder, fileName); |
||||||
|
// 3. 写入文件(try-with-resources 会自动关闭流,最安全)
|
||||||
|
try (FileOutputStream fos = new FileOutputStream(file); |
||||||
|
ByteArrayInputStream bais = new ByteArrayInputStream(qrCodeByte)) { |
||||||
|
byte[] buffer = new byte[1024]; |
||||||
|
int len; |
||||||
|
while ((len = bais.read(buffer)) != -1) { |
||||||
|
fos.write(buffer, 0, len); |
||||||
|
} |
||||||
|
fos.flush(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private ResponseResult<OnlineColumn> doVerifyUpDownloadFileColumn( |
||||||
|
OnlineTable table, String fieldName, Boolean asImage) { |
||||||
|
OnlineColumn column = null; |
||||||
|
for (OnlineColumn c : table.getColumnMap().values()) { |
||||||
|
if (c.getColumnName().equals(fieldName)) { |
||||||
|
column = c; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
if (column == null) { |
||||||
|
return ResponseResult.error(ErrorCodeEnum.INVALID_DATA_FIELD); |
||||||
|
} |
||||||
|
if (BooleanUtil.isTrue(asImage)) { |
||||||
|
if (column.getFieldKind() != FieldKind.UPLOAD_IMAGE) { |
||||||
|
return ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FIELD); |
||||||
|
} |
||||||
|
} else { |
||||||
|
if (column.getFieldKind() != FieldKind.UPLOAD) { |
||||||
|
return ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FIELD); |
||||||
|
} |
||||||
|
} |
||||||
|
return ResponseResult.success(column); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public static File writeToFile(byte[] qrBytes, String dirPath, String fileName) throws IOException { |
||||||
|
Path dir = Paths.get(dirPath); |
||||||
|
if (!Files.exists(dir)) { |
||||||
|
Files.createDirectories(dir); |
||||||
|
} |
||||||
|
Path filePath = dir.resolve(fileName); |
||||||
|
try (FileOutputStream fos = new FileOutputStream(filePath.toFile())) { |
||||||
|
fos.write(qrBytes); |
||||||
|
} |
||||||
|
return filePath.toFile(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public static MultipartFile readFileAsMultipartFile(File file, String contentType) throws IOException { |
||||||
|
return new CustomMultipartFile(file, contentType); |
||||||
|
} |
||||||
|
|
||||||
|
// ==================== 步骤3:获取 InputStream ====================
|
||||||
|
public static InputStream getInputStream(MultipartFile multipartFile) throws IOException { |
||||||
|
return multipartFile.getInputStream(); |
||||||
|
} |
||||||
|
|
||||||
|
// ==================== 自定义 MultipartFile 实现 ====================
|
||||||
|
public static class CustomMultipartFile implements MultipartFile { |
||||||
|
|
||||||
|
private final File file; |
||||||
|
private final String contentType; |
||||||
|
|
||||||
|
public CustomMultipartFile(File file, String contentType) { |
||||||
|
this.file = file; |
||||||
|
this.contentType = contentType; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getName() { |
||||||
|
return file.getName(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getOriginalFilename() { |
||||||
|
return file.getName(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getContentType() { |
||||||
|
return contentType; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isEmpty() { |
||||||
|
return file.length() == 0; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public long getSize() { |
||||||
|
return file.length(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public byte[] getBytes() throws IOException { |
||||||
|
return Files.readAllBytes(file.toPath()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public InputStream getInputStream() throws IOException { |
||||||
|
return new FileInputStream(file); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void transferTo(File dest) throws IOException { |
||||||
|
Files.copy(file.toPath(), dest.toPath()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,78 @@ |
|||||||
|
package apelet.association.utils; |
||||||
|
|
||||||
|
import com.google.zxing.BarcodeFormat; |
||||||
|
import com.google.zxing.EncodeHintType; |
||||||
|
import com.google.zxing.MultiFormatWriter; |
||||||
|
import com.google.zxing.client.j2se.MatrixToImageWriter; |
||||||
|
import com.google.zxing.common.BitMatrix; |
||||||
|
import com.google.zxing.qrcode.QRCodeWriter; |
||||||
|
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; |
||||||
|
import lombok.var; |
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
import javax.imageio.ImageIO; |
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
import java.awt.image.BufferedImage; |
||||||
|
import java.io.ByteArrayOutputStream; |
||||||
|
import java.io.File; |
||||||
|
import java.io.OutputStream; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class QRCodeUtil { |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 生成二维码并直接输出到响应流中 |
||||||
|
* |
||||||
|
* @param url 扫码后要跳转的网址 |
||||||
|
* @param response HTTP响应 |
||||||
|
*/ |
||||||
|
public void generateQRCode(String url, HttpServletResponse response) { |
||||||
|
try { |
||||||
|
// 设置响应类型为图片
|
||||||
|
response.setContentType("image/png"); |
||||||
|
OutputStream os = response.getOutputStream(); |
||||||
|
|
||||||
|
// 二维码参数配置
|
||||||
|
Map<EncodeHintType, Object> hints = new HashMap<>(); |
||||||
|
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 防止中文乱码
|
||||||
|
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 高容错率(30%)
|
||||||
|
hints.put(EncodeHintType.MARGIN, 1); // 白边宽度
|
||||||
|
|
||||||
|
// 生成二维码矩阵 (宽350,高350)
|
||||||
|
BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, 350, 350, hints); |
||||||
|
|
||||||
|
// 将矩阵转换成图片并输出
|
||||||
|
MatrixToImageWriter.writeToStream(bitMatrix, "PNG", os); |
||||||
|
|
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
throw new RuntimeException("生成二维码失败"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 生成二维码字节流(可直接返回给前端) |
||||||
|
* @param content 二维码内容:即你的网页 URL |
||||||
|
* @param width 宽度 |
||||||
|
* @param height 高度 |
||||||
|
* @return 图片字节数组 |
||||||
|
*/ |
||||||
|
public byte[] generateQrCode(String content, int width, int height) throws Exception { |
||||||
|
Map<EncodeHintType, Object> hints = new HashMap<>(); |
||||||
|
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); |
||||||
|
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); |
||||||
|
// 缩小白边(可选)
|
||||||
|
hints.put(EncodeHintType.MARGIN, 1); |
||||||
|
QRCodeWriter writer = new QRCodeWriter(); |
||||||
|
var bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints); |
||||||
|
BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix); |
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
||||||
|
ImageIO.write(image, "PNG", baos); |
||||||
|
return baos.toByteArray(); |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue