diff --git a/.idea/.cache/.Apifox_Helper/.toolWindow.db b/.idea/.cache/.Apifox_Helper/.toolWindow.db
index 28a2e7c..837d4a2 100644
Binary files a/.idea/.cache/.Apifox_Helper/.toolWindow.db and b/.idea/.cache/.Apifox_Helper/.toolWindow.db differ
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..da2d57e
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/cdzy/activity/component/ImageConfig.java b/src/main/java/com/cdzy/activity/component/ImageConfig.java
new file mode 100644
index 0000000..6056ac2
--- /dev/null
+++ b/src/main/java/com/cdzy/activity/component/ImageConfig.java
@@ -0,0 +1,27 @@
+package com.cdzy.activity.component;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 微信配置类
+ *
+ * @author attiya
+ */
+@Getter
+@Setter
+@Configuration
+@ConfigurationProperties(prefix = "image")
+public class ImageConfig {
+ /**
+ * 活动封面地址
+ */
+ private String activityUrl;
+ /**
+ * 公告封面地址
+ */
+ private String bulletinUrl;
+
+}
diff --git a/src/main/java/com/cdzy/activity/component/MyBatisFlexConfiguration.java b/src/main/java/com/cdzy/activity/component/MyBatisFlexConfiguration.java
deleted file mode 100644
index 39e42d6..0000000
--- a/src/main/java/com/cdzy/activity/component/MyBatisFlexConfiguration.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.cdzy.activity.component;
-
-import com.mybatisflex.annotation.KeyType;
-import com.mybatisflex.core.FlexGlobalConfig;
-import com.mybatisflex.core.audit.AuditManager;
-import com.mybatisflex.core.dialect.DbType;
-import com.mybatisflex.core.keygen.KeyGenerators;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * @author attiya
- */
-@Configuration
-public class MyBatisFlexConfiguration {
-
- private static final Logger logger = LoggerFactory.getLogger("mybatis-flex-sql:");
-
- public MyBatisFlexConfiguration() {
- // 只保留审计功能配置(这部分可以留在构造函数)
- AuditManager.setAuditEnable(true);
- AuditManager.setMessageCollector(auditMessage ->
- logger.info("{},{}ms", auditMessage.getFullSql(), auditMessage.getElapsedTime())
- );
- }
-
- @Bean
- public FlexGlobalConfig flexGlobalConfig() {
- FlexGlobalConfig globalConfig = FlexGlobalConfig.getDefaultConfig();
-
-
- // 1. 数据库方言
- globalConfig.setDbType(DbType.MYSQL);
-
- // 2. 全局主键配置(从构造函数移到这里)
- FlexGlobalConfig.KeyConfig keyConfig = new FlexGlobalConfig.KeyConfig();
- keyConfig.setKeyType(KeyType.Generator);
- keyConfig.setValue(KeyGenerators.snowFlakeId);
- keyConfig.setBefore(true);
- globalConfig.setKeyConfig(keyConfig);
-
-
- logger.info("MyBatis-Flex 全局配置已完成,使用 MySQL 方言和雪花算法");
- return globalConfig;
- }
-}
\ No newline at end of file
diff --git a/src/main/java/com/cdzy/activity/component/SaTokenConfigure.java b/src/main/java/com/cdzy/activity/component/SaTokenConfigure.java
index a9ef58c..a7ed080 100644
--- a/src/main/java/com/cdzy/activity/component/SaTokenConfigure.java
+++ b/src/main/java/com/cdzy/activity/component/SaTokenConfigure.java
@@ -29,6 +29,7 @@ public class SaTokenConfigure implements WebMvcConfigurer {
.addInclude("/**")
// 开放地址
.addExclude("/user/**")
+ .addExclude("/api/**")
.setAuth(obj -> {
// 登录校验 -- 拦截所有路由,并排除/user/doLogin 用于开放登录
SaRouter.match("/**", "/staff/login", r -> StpUtil.checkLogin());
diff --git a/src/main/java/com/cdzy/activity/controller/ActivityController.java b/src/main/java/com/cdzy/activity/controller/ActivityController.java
index 2d6f5f9..109863a 100644
--- a/src/main/java/com/cdzy/activity/controller/ActivityController.java
+++ b/src/main/java/com/cdzy/activity/controller/ActivityController.java
@@ -11,7 +11,6 @@ import com.mybatisflex.core.util.StringUtil;
import jakarta.annotation.Resource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
@@ -42,18 +41,6 @@ public class ActivityController {
activityService.saveActivity(activity);
return JsonResult.success();
}
-//
-// /**
-// * 添加。
-// *
-// * @param file 封面文件
-// * @return {@code 200} 添加成功,{@code 500} 添加失败
-// */
-// @PostMapping("upload")
-// public JsonResult> upload(MultipartFile file) throws IOException {
-// activityService.saveActivity(activity);
-// return JsonResult.success();
-// }
/**
* 根据主键删除。
diff --git a/src/main/java/com/cdzy/activity/controller/BulletinController.java b/src/main/java/com/cdzy/activity/controller/BulletinController.java
new file mode 100644
index 0000000..21df8ee
--- /dev/null
+++ b/src/main/java/com/cdzy/activity/controller/BulletinController.java
@@ -0,0 +1,106 @@
+package com.cdzy.activity.controller;
+
+import com.cdzy.activity.model.Bulletin;
+import com.cdzy.activity.model.JsonResult;
+import com.cdzy.activity.model.PageParam;
+import com.cdzy.activity.model.vo.BulletinVo;
+import com.cdzy.activity.service.BulletinService;
+import com.mybatisflex.core.paginate.Page;
+import com.mybatisflex.core.query.QueryWrapper;
+import com.mybatisflex.core.util.StringUtil;
+import jakarta.annotation.Resource;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.List;
+
+import static com.cdzy.activity.model.table.BulletinTableDef.BULLETIN;
+
+/**
+ * 公告控制层。
+ *
+ * @author attiya
+ * @since 2025-09-18
+ */
+@RestController
+@RequestMapping("/bulletin")
+public class BulletinController {
+
+ @Resource
+ private BulletinService bulletinService;
+
+ /**
+ * 保存。
+ *
+ * @param bulletin 公告基础信息
+ * @return {@code true} 保存成功,{@code false} 保存失败
+ */
+ @PostMapping(value = "save",consumes = "multipart/*", headers = "content-type=multipart/form-data")
+ public JsonResult> save(BulletinVo bulletin) throws IOException {
+ bulletinService.saveBulletin(bulletin);
+ return JsonResult.success();
+ }
+
+ /**
+ * 根据主键删除。
+ *
+ * @param id 主键
+ * @return {@code true} 删除成功,{@code false} 删除失败
+ */
+ @DeleteMapping("remove/{id}")
+ public JsonResult> remove(@PathVariable Long id) {
+ bulletinService.removeById(id);
+ return JsonResult.success();
+ }
+
+ /**
+ * 根据主键更新。
+ *
+ * @param bulletin 基础信息
+ * @return {@code true} 更新成功,{@code false} 更新失败
+ */
+ @PutMapping(value = "update",consumes = "multipart/*", headers = "content-type=multipart/form-data")
+ public JsonResult> update(BulletinVo bulletin) throws IOException {
+ bulletinService.updateBulletind(bulletin);
+ return JsonResult.success();
+ }
+
+ /**
+ * 查询所有。
+ *
+ * @return 所有数据
+ */
+ @GetMapping("list")
+ public JsonResult> list() {
+ List list = bulletinService.list();
+ return JsonResult.success(list);
+ }
+
+ /**
+ * 根据主键获取。
+ *
+ * @param id 主键
+ * @return 详情
+ */
+ @GetMapping("getInfo/{id}")
+ public JsonResult> getInfo(@PathVariable Long id) {
+ Bulletin bulletin = bulletinService.getById(id);
+ return JsonResult.success(bulletin);
+
+ }
+
+ /**
+ * 分页查询
+ * @param pageParam 分页参数
+ * @param bulletinTitle 公告标题
+ * @return 分页结果
+ */
+ @GetMapping("page")
+ public JsonResult> page(PageParam pageParam, String bulletinTitle) {
+ QueryWrapper queryWrapper = QueryWrapper.create()
+ .where(BULLETIN.BULLETIN_TITLE.like(bulletinTitle, StringUtil.hasText(bulletinTitle)));
+ Page page = bulletinService.page(pageParam.getPage(), queryWrapper);
+ return JsonResult.success(page);
+ }
+
+}
diff --git a/src/main/java/com/cdzy/activity/controller/ImagePreviewController.java b/src/main/java/com/cdzy/activity/controller/ImagePreviewController.java
new file mode 100644
index 0000000..816775a
--- /dev/null
+++ b/src/main/java/com/cdzy/activity/controller/ImagePreviewController.java
@@ -0,0 +1,58 @@
+package com.cdzy.activity.controller;
+
+
+import com.cdzy.activity.component.ImageConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.UrlResource;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.net.MalformedURLException;
+import java.nio.file.Path;
+
+/**
+ * 图片预览控制层。
+ */
+@RestController
+@RequestMapping("/api/images")
+public class ImagePreviewController {
+
+ @Autowired
+ private ImageConfig imageConfig;
+
+ /**
+ * 活动封面预览
+ * @param filename 封面文件名称
+ * @return 图片
+ * @throws MalformedURLException 预览错误
+ */
+ @GetMapping(value = "/activity/{filename}", produces = {
+ MediaType.IMAGE_JPEG_VALUE,
+ MediaType.IMAGE_PNG_VALUE,
+ MediaType.IMAGE_GIF_VALUE
+ })
+ public Resource previewActivityImage(@PathVariable String filename) throws MalformedURLException {
+ Path filePath = Path.of(imageConfig.getActivityUrl(), filename);
+ return new UrlResource(filePath.toUri());
+ }
+
+ /**
+ * 公告封面预览
+ * @param filename 封面文件名称
+ * @return 图片
+ * @throws MalformedURLException 预览错误
+ */
+ @GetMapping(value = "/bulletin/{filename}", produces = {
+ MediaType.IMAGE_JPEG_VALUE,
+ MediaType.IMAGE_PNG_VALUE,
+ MediaType.IMAGE_GIF_VALUE
+ })
+ public Resource previewBulletinImage(@PathVariable String filename) throws MalformedURLException {
+ Path filePath = Path.of(imageConfig.getBulletinUrl(), filename);
+ return new UrlResource(filePath.toUri());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cdzy/activity/controller/TestController.java b/src/main/java/com/cdzy/activity/controller/TestController.java
deleted file mode 100644
index 79b4f00..0000000
--- a/src/main/java/com/cdzy/activity/controller/TestController.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.cdzy.activity.controller;
-
-
-import com.cdzy.activity.model.JsonResult;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.time.LocalDateTime;
-
-@RestController
-public class TestController {
- @GetMapping("/test")
- public JsonResult> test() {
- return JsonResult.success(LocalDateTime.now());
- }
-}
\ No newline at end of file
diff --git a/src/main/java/com/cdzy/activity/mapper/BulletinMapper.java b/src/main/java/com/cdzy/activity/mapper/BulletinMapper.java
new file mode 100644
index 0000000..faa2778
--- /dev/null
+++ b/src/main/java/com/cdzy/activity/mapper/BulletinMapper.java
@@ -0,0 +1,14 @@
+package com.cdzy.activity.mapper;
+
+import com.mybatisflex.core.BaseMapper;
+import com.cdzy.activity.model.Bulletin;
+
+/**
+ * 映射层。
+ *
+ * @author attiya
+ * @since 2025-09-18
+ */
+public interface BulletinMapper extends BaseMapper {
+
+}
diff --git a/src/main/java/com/cdzy/activity/model/Bulletin.java b/src/main/java/com/cdzy/activity/model/Bulletin.java
new file mode 100644
index 0000000..42f0700
--- /dev/null
+++ b/src/main/java/com/cdzy/activity/model/Bulletin.java
@@ -0,0 +1,50 @@
+package com.cdzy.activity.model;
+
+import com.mybatisflex.annotation.Id;
+import com.mybatisflex.annotation.KeyType;
+import com.mybatisflex.annotation.Table;
+import java.io.Serializable;
+
+import java.io.Serial;
+
+import com.mybatisflex.core.keygen.KeyGenerators;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 实体类。
+ *
+ * @author attiya
+ * @since 2025-09-18
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Table("bulletin")
+public class Bulletin implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ @Id(keyType = KeyType.Generator, value = KeyGenerators.snowFlakeId)
+ private Long bulletinId;
+
+ /**
+ * 公告标题
+ */
+ private String bulletinTitle;
+
+ /**
+ * 封面
+ */
+ private String bulletinCover;
+
+ /**
+ * 内容
+ */
+ private String bulletinDescription;
+
+}
diff --git a/src/main/java/com/cdzy/activity/model/vo/BulletinVo.java b/src/main/java/com/cdzy/activity/model/vo/BulletinVo.java
new file mode 100644
index 0000000..6ae7867
--- /dev/null
+++ b/src/main/java/com/cdzy/activity/model/vo/BulletinVo.java
@@ -0,0 +1,48 @@
+package com.cdzy.activity.model.vo;
+
+import com.mybatisflex.annotation.Id;
+import com.mybatisflex.annotation.KeyType;
+import com.mybatisflex.annotation.Table;
+import com.mybatisflex.core.keygen.KeyGenerators;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 实体类。
+ *
+ * @author attiya
+ * @since 2025-09-18
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BulletinVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ private Long bulletinId;
+
+ /**
+ * 公告标题
+ */
+ private String bulletinTitle;
+
+ /**
+ * 封面
+ */
+ private MultipartFile bulletinCover;
+
+ /**
+ * 内容
+ */
+ private String bulletinDescription;
+
+}
diff --git a/src/main/java/com/cdzy/activity/service/BulletinService.java b/src/main/java/com/cdzy/activity/service/BulletinService.java
new file mode 100644
index 0000000..5d25f7f
--- /dev/null
+++ b/src/main/java/com/cdzy/activity/service/BulletinService.java
@@ -0,0 +1,20 @@
+package com.cdzy.activity.service;
+
+import com.cdzy.activity.model.vo.BulletinVo;
+import com.mybatisflex.core.service.IService;
+import com.cdzy.activity.model.Bulletin;
+
+import java.io.IOException;
+
+/**
+ * 服务层。
+ *
+ * @author attiya
+ * @since 2025-09-18
+ */
+public interface BulletinService extends IService {
+
+ void saveBulletin(BulletinVo bulletin) throws IOException;
+
+ void updateBulletind(BulletinVo bulletin) throws IOException;
+}
diff --git a/src/main/java/com/cdzy/activity/service/impl/ActivityServiceImpl.java b/src/main/java/com/cdzy/activity/service/impl/ActivityServiceImpl.java
index d6eba33..3ffda78 100644
--- a/src/main/java/com/cdzy/activity/service/impl/ActivityServiceImpl.java
+++ b/src/main/java/com/cdzy/activity/service/impl/ActivityServiceImpl.java
@@ -1,16 +1,22 @@
package com.cdzy.activity.service.impl;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.lang.UUID;
+import com.cdzy.activity.component.ImageConfig;
import com.cdzy.activity.enums.ActivityStatus;
import com.cdzy.activity.mapper.ActivityMapper;
import com.cdzy.activity.model.Activity;
import com.cdzy.activity.model.vo.ActivityVo;
import com.cdzy.activity.service.ActivityService;
+import com.cdzy.activity.uitls.FileUtils;
import com.cdzy.activity.uitls.ImageToBase64Converter;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
@@ -29,9 +35,20 @@ public class ActivityServiceImpl extends ServiceImpl
@Resource
private ActivityMapper activityMapper;
+ @Resource
+ private ImageConfig imageConfig;
+
@Override
public void saveActivity(ActivityVo activity) throws IOException {
- String convert = ImageToBase64Converter.convertToBase64(activity.getActivityCover());
+ MultipartFile activityCover = activity.getActivityCover();
+ String convert = null;
+ if (activityCover != null){
+ String uuid = UUID.randomUUID().toString();
+ String fileExtension = FileUtils.getFileExtension(activityCover);
+ String destPath = imageConfig.getActivityUrl()+"/"+uuid+fileExtension;
+ FileUtils.copyMultipartFile(activityCover,destPath,true);
+ convert = uuid + fileExtension;
+ }
Activity entity = Activity.builder()
.activityName(activity.getActivityName())
.activityCover(convert)
@@ -44,6 +61,7 @@ public class ActivityServiceImpl extends ServiceImpl
.endTime(activity.getEndTime())
.maxNum(activity.getMaxNum())
.limitPeople(activity.getLimitPeople())
+ .limitRegister(activity.getLimitRegister())
.status(ActivityStatus.UN_START_REGISTERING)
.build();
activityMapper.insert(entity);
@@ -54,7 +72,16 @@ public class ActivityServiceImpl extends ServiceImpl
Activity entity = activityMapper.selectOneById(activity.getActivityId());
if (entity != null) {
entity.setActivityName(activity.getActivityName());
- String convert = ImageToBase64Converter.convertToBase64(activity.getActivityCover());
+ MultipartFile activityCover = activity.getActivityCover();
+ String convert = entity.getActivityCover();
+ if (activityCover != null){
+ String uuid = UUID.randomUUID().toString();
+ String fileExtension = FileUtils.getFileExtension(activityCover);
+ String destPath = imageConfig.getActivityUrl()+"/"+uuid+fileExtension;
+ FileUtils.copyMultipartFile(activityCover,destPath,true);
+ FileUtil.del(imageConfig.getActivityUrl()+"/"+convert);
+ convert = uuid + fileExtension;
+ }
entity.setActivityCover(convert);
entity.setActivitySponsor(activity.getActivitySponsor());
entity.setActivityDescription(activity.getActivityDescription());
@@ -65,6 +92,7 @@ public class ActivityServiceImpl extends ServiceImpl
entity.setEndTime(activity.getEndTime());
entity.setMaxNum(activity.getMaxNum());
entity.setLimitPeople(activity.getLimitPeople());
+ entity.setLimitRegister(activity.getLimitRegister());
activityMapper.update(entity);
}else {
throw new RuntimeException("该活动不存在");
diff --git a/src/main/java/com/cdzy/activity/service/impl/BulletinServiceImpl.java b/src/main/java/com/cdzy/activity/service/impl/BulletinServiceImpl.java
new file mode 100644
index 0000000..09ca5f8
--- /dev/null
+++ b/src/main/java/com/cdzy/activity/service/impl/BulletinServiceImpl.java
@@ -0,0 +1,75 @@
+package com.cdzy.activity.service.impl;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.lang.UUID;
+import com.cdzy.activity.component.ImageConfig;
+import com.cdzy.activity.model.vo.ActivityVo;
+import com.cdzy.activity.model.vo.BulletinVo;
+import com.cdzy.activity.uitls.FileUtils;
+import com.mybatisflex.spring.service.impl.ServiceImpl;
+import com.cdzy.activity.model.Bulletin;
+import com.cdzy.activity.mapper.BulletinMapper;
+import com.cdzy.activity.service.BulletinService;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+
+/**
+ * 服务层实现。
+ *
+ * @author attiya
+ * @since 2025-09-18
+ */
+@Service
+public class BulletinServiceImpl extends ServiceImpl implements BulletinService {
+
+ @Resource
+ private BulletinMapper bulletinMapper;
+
+ @Resource
+ private ImageConfig imageConfig;
+
+ @Override
+ public void saveBulletin(BulletinVo bulletin) throws IOException {
+ MultipartFile activityCover = bulletin.getBulletinCover();
+ String convert = null;
+ if (activityCover != null) {
+ String uuid = UUID.randomUUID().toString();
+ String fileExtension = FileUtils.getFileExtension(activityCover);
+ String destPath = imageConfig.getActivityUrl() + "/" + uuid + fileExtension;
+ FileUtils.copyMultipartFile(activityCover, destPath, true);
+ convert = uuid + fileExtension;
+ }
+ Bulletin entity = Bulletin.builder()
+ .bulletinCover(convert)
+ .bulletinTitle(bulletin.getBulletinTitle())
+ .bulletinDescription(bulletin.getBulletinDescription())
+ .build();
+ bulletinMapper.insert(entity);
+ }
+
+ @Override
+ public void updateBulletind(BulletinVo bulletin) throws IOException {
+ Bulletin entity = bulletinMapper.selectOneById(bulletin.getBulletinId());
+ if (entity != null) {
+ entity.setBulletinTitle(bulletin.getBulletinTitle());
+ MultipartFile activityCover = bulletin.getBulletinCover();
+ String convert = entity.getBulletinCover();
+ if (activityCover != null) {
+ String uuid = UUID.randomUUID().toString();
+ String fileExtension = FileUtils.getFileExtension(activityCover);
+ String destPath = imageConfig.getActivityUrl() + "/" + uuid + fileExtension;
+ FileUtils.copyMultipartFile(activityCover, destPath, true);
+ FileUtil.del(imageConfig.getActivityUrl() + "/" + convert);
+ convert = uuid + fileExtension;
+ }
+ entity.setBulletinCover(convert);
+ entity.setBulletinDescription(bulletin.getBulletinDescription());
+ bulletinMapper.update(entity);
+ } else {
+ throw new RuntimeException("该公告不存在");
+ }
+ }
+}
diff --git a/src/main/java/com/cdzy/activity/uitls/FileUtils.java b/src/main/java/com/cdzy/activity/uitls/FileUtils.java
new file mode 100644
index 0000000..20e108c
--- /dev/null
+++ b/src/main/java/com/cdzy/activity/uitls/FileUtils.java
@@ -0,0 +1,57 @@
+package com.cdzy.activity.uitls;
+
+import cn.hutool.core.io.FileUtil;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Optional;
+
+public class FileUtils {
+ /**
+ * 安全获取文件后缀(包含点符号)
+ * @param file MultipartFile对象
+ * @return 如 ".jpg" 或空字符串
+ */
+ public static String getFileExtension(MultipartFile file) {
+ return Optional.ofNullable(file.getOriginalFilename())
+ .filter(name -> name.contains("."))
+ .map(name -> name.substring(name.lastIndexOf(".")))
+ .orElse("");
+ }
+
+ /**
+ * 获取无点的纯后缀(小写形式)
+ * @param file MultipartFile对象
+ * @return 如 "jpg" 或空字符串
+ */
+ public static String getFileExtensionWithoutDot(MultipartFile file) {
+ return getFileExtension(file).replace(".", "").toLowerCase();
+ }
+
+ /**
+ * 复制MultipartFile到指定路径(自动创建目录)
+ *
+ * @param file 源文件(MultipartFile类型)
+ * @param destPath 目标绝对路径(包含文件名)
+ * @param override 是否覆盖已存在文件
+ * @throws IOException 文件操作异常
+ */
+ public static void copyMultipartFile(MultipartFile file, String destPath, boolean override) throws IOException {
+ // 校验目标路径
+ if (destPath == null || destPath.trim().isEmpty()) {
+ throw new IllegalArgumentException("Destination path cannot be empty");
+ }
+
+ // 创建父目录(如果不存在)
+ File destFile = new File(destPath);
+ FileUtil.mkParentDirs(destFile);
+
+ // 执行文件复制
+ if (override || !destFile.exists()) {
+ file.transferTo(destFile);
+ }
+
+ }
+
+}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index fefa6d4..ea2ce7c 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -67,4 +67,6 @@ wechat:
appid: wx327d788d7bd6eddf
app-secret: adf2539a6c26499c67b5a3829f2e05e3
-
+image:
+ activity-url: D:/file/activity
+ bulletin-url: D:/file/bulletin
diff --git a/target/classes/application-dev.yml b/target/classes/application-dev.yml
index fefa6d4..ea2ce7c 100644
--- a/target/classes/application-dev.yml
+++ b/target/classes/application-dev.yml
@@ -67,4 +67,6 @@ wechat:
appid: wx327d788d7bd6eddf
app-secret: adf2539a6c26499c67b5a3829f2e05e3
-
+image:
+ activity-url: D:/file/activity
+ bulletin-url: D:/file/bulletin
diff --git a/target/classes/com/cdzy/activity/component/ImageConfig.class b/target/classes/com/cdzy/activity/component/ImageConfig.class
new file mode 100644
index 0000000..183cc82
Binary files /dev/null and b/target/classes/com/cdzy/activity/component/ImageConfig.class differ
diff --git a/target/classes/com/cdzy/activity/component/MyBatisFlexConfiguration.class b/target/classes/com/cdzy/activity/component/MyBatisFlexConfiguration.class
deleted file mode 100644
index 529a1aa..0000000
Binary files a/target/classes/com/cdzy/activity/component/MyBatisFlexConfiguration.class and /dev/null differ
diff --git a/target/classes/com/cdzy/activity/component/SaTokenConfigure.class b/target/classes/com/cdzy/activity/component/SaTokenConfigure.class
index c596b6c..5d677b3 100644
Binary files a/target/classes/com/cdzy/activity/component/SaTokenConfigure.class and b/target/classes/com/cdzy/activity/component/SaTokenConfigure.class differ
diff --git a/target/classes/com/cdzy/activity/controller/ActivityController.class b/target/classes/com/cdzy/activity/controller/ActivityController.class
index 0e8a341..6eb3231 100644
Binary files a/target/classes/com/cdzy/activity/controller/ActivityController.class and b/target/classes/com/cdzy/activity/controller/ActivityController.class differ
diff --git a/target/classes/com/cdzy/activity/controller/BulletinController.class b/target/classes/com/cdzy/activity/controller/BulletinController.class
new file mode 100644
index 0000000..555a2fd
Binary files /dev/null and b/target/classes/com/cdzy/activity/controller/BulletinController.class differ
diff --git a/target/classes/com/cdzy/activity/controller/ImagePreviewController.class b/target/classes/com/cdzy/activity/controller/ImagePreviewController.class
new file mode 100644
index 0000000..3383c34
Binary files /dev/null and b/target/classes/com/cdzy/activity/controller/ImagePreviewController.class differ
diff --git a/target/classes/com/cdzy/activity/controller/TestController.class b/target/classes/com/cdzy/activity/controller/TestController.class
deleted file mode 100644
index a30fa67..0000000
Binary files a/target/classes/com/cdzy/activity/controller/TestController.class and /dev/null differ
diff --git a/target/classes/com/cdzy/activity/mapper/BulletinMapper.class b/target/classes/com/cdzy/activity/mapper/BulletinMapper.class
new file mode 100644
index 0000000..127f579
Binary files /dev/null and b/target/classes/com/cdzy/activity/mapper/BulletinMapper.class differ
diff --git a/target/classes/com/cdzy/activity/model/Bulletin$BulletinBuilder.class b/target/classes/com/cdzy/activity/model/Bulletin$BulletinBuilder.class
new file mode 100644
index 0000000..df5e881
Binary files /dev/null and b/target/classes/com/cdzy/activity/model/Bulletin$BulletinBuilder.class differ
diff --git a/target/classes/com/cdzy/activity/model/Bulletin.class b/target/classes/com/cdzy/activity/model/Bulletin.class
new file mode 100644
index 0000000..f1b6e8f
Binary files /dev/null and b/target/classes/com/cdzy/activity/model/Bulletin.class differ
diff --git a/target/classes/com/cdzy/activity/model/table/BulletinTableDef.class b/target/classes/com/cdzy/activity/model/table/BulletinTableDef.class
new file mode 100644
index 0000000..5d53264
Binary files /dev/null and b/target/classes/com/cdzy/activity/model/table/BulletinTableDef.class differ
diff --git a/target/classes/com/cdzy/activity/service/BulletinService.class b/target/classes/com/cdzy/activity/service/BulletinService.class
new file mode 100644
index 0000000..3f1f4c6
Binary files /dev/null and b/target/classes/com/cdzy/activity/service/BulletinService.class differ
diff --git a/target/classes/com/cdzy/activity/service/impl/ActivityServiceImpl.class b/target/classes/com/cdzy/activity/service/impl/ActivityServiceImpl.class
index 6025b19..f5bcbd7 100644
Binary files a/target/classes/com/cdzy/activity/service/impl/ActivityServiceImpl.class and b/target/classes/com/cdzy/activity/service/impl/ActivityServiceImpl.class differ
diff --git a/target/classes/com/cdzy/activity/service/impl/BulletinServiceImpl.class b/target/classes/com/cdzy/activity/service/impl/BulletinServiceImpl.class
new file mode 100644
index 0000000..43ed9e1
Binary files /dev/null and b/target/classes/com/cdzy/activity/service/impl/BulletinServiceImpl.class differ
diff --git a/target/classes/com/cdzy/activity/uitls/FileUtils.class b/target/classes/com/cdzy/activity/uitls/FileUtils.class
new file mode 100644
index 0000000..adce330
Binary files /dev/null and b/target/classes/com/cdzy/activity/uitls/FileUtils.class differ
diff --git a/target/generated-sources/annotations/com/cdzy/activity/model/table/BulletinTableDef.java b/target/generated-sources/annotations/com/cdzy/activity/model/table/BulletinTableDef.java
new file mode 100644
index 0000000..eccde20
--- /dev/null
+++ b/target/generated-sources/annotations/com/cdzy/activity/model/table/BulletinTableDef.java
@@ -0,0 +1,57 @@
+package com.cdzy.activity.model.table;
+
+import com.mybatisflex.core.query.QueryColumn;
+import com.mybatisflex.core.table.TableDef;
+
+// Auto generate by mybatis-flex, do not modify it.
+public class BulletinTableDef extends TableDef {
+
+ /**
+ * 实体类。
+
+ @author attiya
+ @since 2025-09-18
+ */
+ public static final BulletinTableDef BULLETIN = new BulletinTableDef();
+
+ public final QueryColumn BULLETIN_ID = new QueryColumn(this, "bulletin_id");
+
+ /**
+ * 封面
+ */
+ public final QueryColumn BULLETIN_COVER = new QueryColumn(this, "bulletin_cover");
+
+ /**
+ * 公告标题
+ */
+ public final QueryColumn BULLETIN_TITLE = new QueryColumn(this, "bulletin_title");
+
+ /**
+ * 内容
+ */
+ public final QueryColumn BULLETIN_DESCRIPTION = new QueryColumn(this, "bulletin_description");
+
+ /**
+ * 所有字段。
+ */
+ public final QueryColumn ALL_COLUMNS = new QueryColumn(this, "*");
+
+ /**
+ * 默认字段,不包含逻辑删除或者 large 等字段。
+ */
+ public final QueryColumn[] DEFAULT_COLUMNS = new QueryColumn[]{BULLETIN_ID, BULLETIN_COVER, BULLETIN_TITLE, BULLETIN_DESCRIPTION};
+
+ public BulletinTableDef() {
+ super("", "bulletin");
+ }
+
+ private BulletinTableDef(String schema, String name, String alisa) {
+ super(schema, name, alisa);
+ }
+
+ public BulletinTableDef as(String alias) {
+ String key = getNameWithSchema() + "." + alias;
+ return getCache(key, k -> new BulletinTableDef("", "bulletin", alias));
+ }
+
+}