From a8b0206ccefd457e80308e2ee1f378c6e36eb983 Mon Sep 17 00:00:00 2001 From: JR <3573153686@qq.com> Date: Wed, 22 Oct 2025 22:36:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(oa):=20=E6=B7=BB=E5=8A=A0=E7=9F=A5?= =?UTF-8?q?=E8=AF=86=E7=AE=A1=E7=90=86=E5=92=8C=E9=82=AE=E4=BB=B6=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增知识分类和知识文章的完整CRUD接口- 实现知识文章预览组件,支持富文本和附件展示 - 添加动态邮件配置功能,支持多种邮箱类型自动识别 - 实现邮件模板管理功能,提供多种商务邮件模板- 添加邮件发送功能,支持批量发送和附件上传 - 完善邮件工具类,支持富文本、附件和内嵌图片发送- 新增发件人邮箱账号管理功能 - 添加家具信息管理相关接口- 配置默认邮件服务参数 --- gear-admin/src/main/resources/application.yml | 13 + gear-oa/pom.xml | 23 + .../com/gear/oa/config/DynamicMailConfig.java | 201 +++ .../controller/OaEmailAccountController.java | 111 ++ .../controller/OaEmailTemplateController.java | 100 ++ .../OaFurnitureTableController.java | 100 ++ .../oa/controller/SysOaArticleController.java | 118 ++ .../controller/SysOaCategoryController.java | 106 ++ .../com/gear/oa/domain/OaEmailAccount.java | 66 + .../com/gear/oa/domain/OaEmailTemplate.java | 54 + .../com/gear/oa/domain/OaFurnitureTable.java | 96 ++ .../java/com/gear/oa/domain/SysOaArticle.java | 62 + .../com/gear/oa/domain/SysOaCategory.java | 40 + .../gear/oa/domain/bo/OaEmailAccountBo.java | 64 + .../gear/oa/domain/bo/OaEmailTemplateBo.java | 49 + .../gear/oa/domain/bo/OaFurnitureTableBo.java | 106 ++ .../com/gear/oa/domain/bo/SysOaArticleBo.java | 75 ++ .../gear/oa/domain/bo/SysOaCategoryBo.java | 47 + .../oa/domain/request/EmailSendRequest.java | 26 + .../gear/oa/domain/vo/OaEmailAccountVo.java | 81 ++ .../gear/oa/domain/vo/OaEmailTemplateVo.java | 61 + .../gear/oa/domain/vo/OaFurnitureTableVo.java | 119 ++ .../com/gear/oa/domain/vo/SysOaArticleVo.java | 81 ++ .../gear/oa/domain/vo/SysOaCategoryVo.java | 65 + .../gear/oa/mapper/OaEmailAccountMapper.java | 15 + .../gear/oa/mapper/OaEmailTemplateMapper.java | 15 + .../oa/mapper/OaFurnitureTableMapper.java | 26 + .../gear/oa/mapper/SysOaArticleMapper.java | 32 + .../gear/oa/mapper/SysOaCategoryMapper.java | 15 + .../oa/service/IOaEmailAccountService.java | 54 + .../oa/service/IOaEmailTemplateService.java | 48 + .../oa/service/IOaFurnitureTableService.java | 48 + .../gear/oa/service/ISysOaArticleService.java | 52 + .../oa/service/ISysOaCategoryService.java | 42 + .../impl/OaEmailAccountServiceImpl.java | 331 +++++ .../impl/OaEmailTemplateServiceImpl.java | 112 ++ .../impl/OaFurnitureTableServiceImpl.java | 131 ++ .../service/impl/SysOaArticleServiceImpl.java | 134 ++ .../impl/SysOaCategoryServiceImpl.java | 99 ++ .../java/com/gear/oa/utils/EmailUtil.java | 382 ++++++ .../mapper/oa/OaEmailAccountMapper.xml | 25 + .../mapper/oa/OaEmailTemplateMapper.xml | 22 + .../mapper/oa/OaFurnitureTableMapper.xml | 48 + .../mapper/oa/SysOaArticleMapper.xml | 61 + .../mapper/oa/SysOaCategoryMapper.xml | 20 + gear-ui3/package.json | 1 + gear-ui3/src/api/oa/article.js | 44 + gear-ui3/src/api/oa/category.js | 44 + gear-ui3/src/api/oa/contact.js | 44 + gear-ui3/src/api/oa/emailAccount.js | 53 + gear-ui3/src/api/oa/emailTemplate.js | 44 + .../article/components/ArticlePreview.vue | 347 +++++ gear-ui3/src/views/sale/article/index.vue | 519 ++++++++ gear-ui3/src/views/sale/contact/index.vue | 1139 +++++++++++++++++ .../views/sale/contact/templates/business.js | 32 + .../src/views/sale/contact/templates/index.js | 32 + .../views/sale/contact/templates/marketing.js | 103 ++ .../sale/contact/templates/notification.js | 82 ++ .../views/sale/contact/templates/product.js | 94 ++ gear-ui3/src/views/sale/email/index.vue | 483 +++++++ gear-ui3/src/views/sale/template/index.vue | 418 ++++++ 61 files changed, 7055 insertions(+) create mode 100644 gear-oa/src/main/java/com/gear/oa/config/DynamicMailConfig.java create mode 100644 gear-oa/src/main/java/com/gear/oa/controller/OaEmailAccountController.java create mode 100644 gear-oa/src/main/java/com/gear/oa/controller/OaEmailTemplateController.java create mode 100644 gear-oa/src/main/java/com/gear/oa/controller/OaFurnitureTableController.java create mode 100644 gear-oa/src/main/java/com/gear/oa/controller/SysOaArticleController.java create mode 100644 gear-oa/src/main/java/com/gear/oa/controller/SysOaCategoryController.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/OaEmailAccount.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/OaEmailTemplate.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/OaFurnitureTable.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/SysOaArticle.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/SysOaCategory.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/bo/OaEmailAccountBo.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/bo/OaEmailTemplateBo.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/bo/OaFurnitureTableBo.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/bo/SysOaArticleBo.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/bo/SysOaCategoryBo.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/request/EmailSendRequest.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/vo/OaEmailAccountVo.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/vo/OaEmailTemplateVo.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/vo/OaFurnitureTableVo.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/vo/SysOaArticleVo.java create mode 100644 gear-oa/src/main/java/com/gear/oa/domain/vo/SysOaCategoryVo.java create mode 100644 gear-oa/src/main/java/com/gear/oa/mapper/OaEmailAccountMapper.java create mode 100644 gear-oa/src/main/java/com/gear/oa/mapper/OaEmailTemplateMapper.java create mode 100644 gear-oa/src/main/java/com/gear/oa/mapper/OaFurnitureTableMapper.java create mode 100644 gear-oa/src/main/java/com/gear/oa/mapper/SysOaArticleMapper.java create mode 100644 gear-oa/src/main/java/com/gear/oa/mapper/SysOaCategoryMapper.java create mode 100644 gear-oa/src/main/java/com/gear/oa/service/IOaEmailAccountService.java create mode 100644 gear-oa/src/main/java/com/gear/oa/service/IOaEmailTemplateService.java create mode 100644 gear-oa/src/main/java/com/gear/oa/service/IOaFurnitureTableService.java create mode 100644 gear-oa/src/main/java/com/gear/oa/service/ISysOaArticleService.java create mode 100644 gear-oa/src/main/java/com/gear/oa/service/ISysOaCategoryService.java create mode 100644 gear-oa/src/main/java/com/gear/oa/service/impl/OaEmailAccountServiceImpl.java create mode 100644 gear-oa/src/main/java/com/gear/oa/service/impl/OaEmailTemplateServiceImpl.java create mode 100644 gear-oa/src/main/java/com/gear/oa/service/impl/OaFurnitureTableServiceImpl.java create mode 100644 gear-oa/src/main/java/com/gear/oa/service/impl/SysOaArticleServiceImpl.java create mode 100644 gear-oa/src/main/java/com/gear/oa/service/impl/SysOaCategoryServiceImpl.java create mode 100644 gear-oa/src/main/java/com/gear/oa/utils/EmailUtil.java create mode 100644 gear-oa/src/main/resources/mapper/oa/OaEmailAccountMapper.xml create mode 100644 gear-oa/src/main/resources/mapper/oa/OaEmailTemplateMapper.xml create mode 100644 gear-oa/src/main/resources/mapper/oa/OaFurnitureTableMapper.xml create mode 100644 gear-oa/src/main/resources/mapper/oa/SysOaArticleMapper.xml create mode 100644 gear-oa/src/main/resources/mapper/oa/SysOaCategoryMapper.xml create mode 100644 gear-ui3/src/api/oa/article.js create mode 100644 gear-ui3/src/api/oa/category.js create mode 100644 gear-ui3/src/api/oa/contact.js create mode 100644 gear-ui3/src/api/oa/emailAccount.js create mode 100644 gear-ui3/src/api/oa/emailTemplate.js create mode 100644 gear-ui3/src/views/sale/article/components/ArticlePreview.vue create mode 100644 gear-ui3/src/views/sale/article/index.vue create mode 100644 gear-ui3/src/views/sale/contact/index.vue create mode 100644 gear-ui3/src/views/sale/contact/templates/business.js create mode 100644 gear-ui3/src/views/sale/contact/templates/index.js create mode 100644 gear-ui3/src/views/sale/contact/templates/marketing.js create mode 100644 gear-ui3/src/views/sale/contact/templates/notification.js create mode 100644 gear-ui3/src/views/sale/contact/templates/product.js create mode 100644 gear-ui3/src/views/sale/email/index.vue create mode 100644 gear-ui3/src/views/sale/template/index.vue diff --git a/gear-admin/src/main/resources/application.yml b/gear-admin/src/main/resources/application.yml index b2bc05c..7d69357 100644 --- a/gear-admin/src/main/resources/application.yml +++ b/gear-admin/src/main/resources/application.yml @@ -97,6 +97,19 @@ spring: deserialization: # 允许对象忽略json中不存在的属性 fail_on_unknown_properties: false + mail: + host: smtp.163.com + port: 465 + username: dummy@dummy.com # 占位用,随便写 + password: dummy # 占位用,随便写 + properties: + mail: + smtp: + auth: true + ssl: + enable: true + starttls: + enable: true # Sa-Token配置 sa-token: diff --git a/gear-oa/pom.xml b/gear-oa/pom.xml index da5c3ab..d7d0cd8 100644 --- a/gear-oa/pom.xml +++ b/gear-oa/pom.xml @@ -21,6 +21,29 @@ com.gear gear-common + + + org.springframework.boot + spring-boot-starter-mail + + + com.aliyun + aliyun-java-sdk-core + 4.5.20 + compile + + + com.aliyun + aliyun-java-sdk-dm + 3.3.1 + compile + + + com.larksuite.oapi + oapi-sdk + 2.4.19 + compile + com.alibaba.fastjson2 diff --git a/gear-oa/src/main/java/com/gear/oa/config/DynamicMailConfig.java b/gear-oa/src/main/java/com/gear/oa/config/DynamicMailConfig.java new file mode 100644 index 0000000..cf0a20d --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/config/DynamicMailConfig.java @@ -0,0 +1,201 @@ +package com.gear.oa.config; + +import com.gear.oa.domain.OaEmailAccount; +import org.springframework.context.annotation.Configuration; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.JavaMailSenderImpl; + +import java.util.Properties; + +/** + * 动态邮件配置类 + * 支持根据不同的邮箱账号动态配置邮件发送器 + * + * @author ruoyi + */ +@Configuration +public class DynamicMailConfig { + + /** + * 根据邮箱账号创建JavaMailSender + * + * @param account 邮箱账号信息 + * @return JavaMailSender + */ + public JavaMailSender createMailSender(OaEmailAccount account) { + JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); + + // 设置SMTP服务器 - 根据邮箱域名自动识别企业邮箱 + String email = account.getEmail(); + String smtpHost = getSmtpHostByEmail(email, account.getSmtpHost()); + + mailSender.setHost(smtpHost); + mailSender.setPort(account.getSmtpPort() == null ? 465 : account.getSmtpPort().intValue()); + mailSender.setUsername(account.getEmail()); + mailSender.setPassword(account.getPassword()); + + // 设置邮件属性 + Properties props = mailSender.getJavaMailProperties(); + props.put("mail.transport.protocol", "smtp"); + props.put("mail.smtp.auth", "true"); + props.put("mail.smtp.starttls.enable", "true"); + props.put("mail.smtp.ssl.enable", "true"); + props.put("mail.smtp.connectiontimeout", "10000"); + props.put("mail.smtp.timeout", "10000"); + props.put("mail.smtp.writetimeout", "10000"); + props.put("mail.debug", "false"); + + return mailSender; + } + + /** + * 根据邮箱类型获取默认配置 + * + * @param type 邮箱类型 0=网易 1=QQ 2=阿里云 3=飞书 + * @return 默认配置 + */ + public OaEmailAccount getDefaultConfig(int type) { + OaEmailAccount config = new OaEmailAccount(); + + switch (type) { + case 0: // 网易邮箱 + config.setSmtpHost("smtp.163.com"); + config.setSmtpPort(465L); + break; + case 1: // QQ邮箱 + config.setSmtpHost("smtp.qq.com"); + config.setSmtpPort(465L); + break; + case 2: // 阿里云邮箱 + config.setSmtpHost("smtp.aliyun.com"); + config.setSmtpPort(465L); + break; + case 3: // 飞书邮箱 + config.setSmtpHost("smtp.feishu.cn"); + config.setSmtpPort(465L); + break; + default: + config.setSmtpHost("smtp.163.com"); + config.setSmtpPort(465L); + break; + } + + return config; + } + + // 测试方法 + public static void main(String[] args) { + DynamicMailConfig config = new DynamicMailConfig(); + + // 测试各种邮箱类型 + String[] testEmails = { + "test@freeqiye.com", // 网易企业邮箱 + "test@qiye.163.com", // 网易企业邮箱 + "test@163.com", // 网易个人邮箱 + "test@126.com", // 网易126邮箱 + "test@qq.com", // QQ邮箱 + "test@exmail.qq.com", // QQ企业邮箱 + "test@aliyun.com", // 阿里云邮箱 + "test@sina.com", // 新浪邮箱 + "test@vip.sina.com", // 新浪VIP邮箱 + "test@sohu.com", // 搜狐邮箱 + "test@139.com", // 139邮箱 + "test@189.cn", // 189邮箱 + "test@feishu.cn", // 飞书邮箱 + "test@gmail.com", // Gmail邮箱 + "test@outlook.com", // Outlook邮箱 + "test@hotmail.com", // Hotmail邮箱 + "test@company.com" // 自定义企业邮箱 + }; + + System.out.println("邮箱SMTP服务器识别测试:"); + System.out.println("=========================================="); + + for (String email : testEmails) { + String smtpHost = config.getSmtpHostByEmail(email, null); + System.out.printf("%-20s -> %s%n", email, smtpHost); + } + + System.out.println("=========================================="); + } + + /** + * 根据邮箱地址自动识别SMTP服务器 + * + * @param email 邮箱地址 + * @param defaultSmtpHost 默认SMTP服务器 + * @return SMTP服务器地址 + */ + public String getSmtpHostByEmail(String email, String defaultSmtpHost) { + if (email == null) { + return defaultSmtpHost != null ? defaultSmtpHost : "smtp.163.com"; + } + + String domain = email.toLowerCase(); + + // 网易企业邮箱 + if (domain.contains("@freeqiye.com") || domain.contains("@qiye.163.com")) { + return "smtp.qiye.163.com"; + } + // 网易个人邮箱 + else if (domain.contains("@163.com")) { + return "smtp.163.com"; + } + // 网易126邮箱 + else if (domain.contains("@126.com")) { + return "smtp.126.com"; + } + // QQ邮箱 + else if (domain.contains("@qq.com")) { + return "smtp.qq.com"; + } + // QQ企业邮箱 + else if (domain.contains("@exmail.qq.com")) { + return "smtp.exmail.qq.com"; + } + // 阿里云邮箱 + else if (domain.contains("@aliyun.com")) { + return "smtp.aliyun.com"; + } + // 新浪邮箱 + else if (domain.contains("@sina.com")) { + return "smtp.sina.com"; + } + // 新浪VIP邮箱 + else if (domain.contains("@vip.sina.com")) { + return "smtp.vip.sina.com"; + } + // 搜狐邮箱 + else if (domain.contains("@sohu.com")) { + return "smtp.sohu.com"; + } + // 139邮箱 + else if (domain.contains("@139.com")) { + return "smtp.139.com"; + } + // 189邮箱 + else if (domain.contains("@189.cn")) { + return "smtp.189.cn"; + } + // 飞书邮箱 + else if (domain.contains("@feishu.cn")) { + return "smtp.feishu.cn"; + } + // Gmail邮箱 + else if (domain.contains("@gmail.com")) { + return "smtp.gmail.com"; + } + // Outlook邮箱 + else if (domain.contains("@outlook.com") || domain.contains("@hotmail.com")) { + return "smtp-mail.outlook.com"; + } + // 企业邮箱通用域名识别(可以根据需要添加更多) + else if (domain.contains("@qiye.") || domain.contains("@corp.") || domain.contains("@enterprise.")) { + // 对于企业邮箱,优先使用配置的SMTP服务器,如果没有配置则使用通用企业邮箱SMTP + return defaultSmtpHost != null ? defaultSmtpHost : "smtp." + domain.split("@")[1]; + } + + // 如果都不匹配,使用配置的SMTP服务器或默认服务器 + return defaultSmtpHost != null ? defaultSmtpHost : "smtp.163.com"; + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/controller/OaEmailAccountController.java b/gear-oa/src/main/java/com/gear/oa/controller/OaEmailAccountController.java new file mode 100644 index 0000000..0bd9bb5 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/controller/OaEmailAccountController.java @@ -0,0 +1,111 @@ +package com.gear.oa.controller; + +import com.gear.common.annotation.Log; +import com.gear.common.annotation.RepeatSubmit; +import com.gear.common.core.controller.BaseController; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.domain.R; +import com.gear.common.core.page.TableDataInfo; +import com.gear.common.core.validate.AddGroup; +import com.gear.common.core.validate.EditGroup; +import com.gear.common.enums.BusinessType; +import com.gear.common.utils.poi.ExcelUtil; +import com.gear.oa.domain.bo.OaEmailAccountBo; +import com.gear.oa.domain.request.EmailSendRequest; +import com.gear.oa.domain.vo.OaEmailAccountVo; +import com.gear.oa.service.IOaEmailAccountService; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Arrays; +import java.util.List; + +/** + * 发件人邮箱账号管理 + * + * @author Joshi + * @date 2025-07-10 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/oa/emailAccount") +public class OaEmailAccountController extends BaseController { + + private final IOaEmailAccountService iOaEmailAccountService; + + /** + * 查询发件人邮箱账号管理列表 + */ + @GetMapping("/list") + public TableDataInfo list(OaEmailAccountBo bo, PageQuery pageQuery) { + return iOaEmailAccountService.queryPageList(bo, pageQuery); + } + + /** + * 导出发件人邮箱账号管理列表 + */ + @Log(title = "发件人邮箱账号管理", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(OaEmailAccountBo bo, HttpServletResponse response) { + List list = iOaEmailAccountService.queryList(bo); + ExcelUtil.exportExcel(list, "发件人邮箱账号管理", OaEmailAccountVo.class, response); + } + + /** + * 获取发件人邮箱账号管理详细信息 + * + * @param emailId 主键 + */ + @GetMapping("/{emailId}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long emailId) { + return R.ok(iOaEmailAccountService.queryById(emailId)); + } + + /** + * 新增发件人邮箱账号管理 + */ + @Log(title = "发件人邮箱账号管理", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody OaEmailAccountBo bo) { + return toAjax(iOaEmailAccountService.insertByBo(bo)); + } + + /** + * 修改发件人邮箱账号管理 + */ + @Log(title = "发件人邮箱账号管理", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody OaEmailAccountBo bo) { + return toAjax(iOaEmailAccountService.updateByBo(bo)); + } + + /** + * 删除发件人邮箱账号管理 + * + * @param emailIds 主键串 + */ + @Log(title = "发件人邮箱账号管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{emailIds}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] emailIds) { + return toAjax(iOaEmailAccountService.deleteWithValidByIds(Arrays.asList(emailIds), true)); + } + + /** + * 批量发送邮件(支持网易企业邮箱、飞书SMTP) + */ + @PostMapping("/sendBatchEmail") + public R sendBatchEmail(@RequestBody EmailSendRequest request) { + // 调用Service批量发送邮件 + String result = iOaEmailAccountService.sendBatchEmail(request); + return R.ok(result); + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/controller/OaEmailTemplateController.java b/gear-oa/src/main/java/com/gear/oa/controller/OaEmailTemplateController.java new file mode 100644 index 0000000..030a64e --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/controller/OaEmailTemplateController.java @@ -0,0 +1,100 @@ +package com.gear.oa.controller; + +import com.gear.common.annotation.Log; +import com.gear.common.annotation.RepeatSubmit; +import com.gear.common.core.controller.BaseController; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.domain.R; +import com.gear.common.core.page.TableDataInfo; +import com.gear.common.core.validate.AddGroup; +import com.gear.common.core.validate.EditGroup; +import com.gear.common.enums.BusinessType; +import com.gear.common.utils.poi.ExcelUtil; +import com.gear.oa.domain.bo.OaEmailTemplateBo; +import com.gear.oa.domain.vo.OaEmailTemplateVo; +import com.gear.oa.service.IOaEmailTemplateService; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Arrays; +import java.util.List; + +/** + * 邮件模板 + * + * @author ruoyi + * @date 2025-07-16 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/oa/emailTemplate") +public class OaEmailTemplateController extends BaseController { + + private final IOaEmailTemplateService iOaEmailTemplateService; + + /** + * 查询邮件模板列表 + */ + @GetMapping("/list") + public TableDataInfo list(OaEmailTemplateBo bo, PageQuery pageQuery) { + return iOaEmailTemplateService.queryPageList(bo, pageQuery); + } + + /** + * 导出邮件模板列表 + */ + @Log(title = "邮件模板", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(OaEmailTemplateBo bo, HttpServletResponse response) { + List list = iOaEmailTemplateService.queryList(bo); + ExcelUtil.exportExcel(list, "邮件模板", OaEmailTemplateVo.class, response); + } + + /** + * 获取邮件模板详细信息 + * + * @param id 主键 + */ + @GetMapping("/{id}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long id) { + return R.ok(iOaEmailTemplateService.queryById(id)); + } + + /** + * 新增邮件模板 + */ + @Log(title = "邮件模板", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody OaEmailTemplateBo bo) { + return toAjax(iOaEmailTemplateService.insertByBo(bo)); + } + + /** + * 修改邮件模板 + */ + @Log(title = "邮件模板", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody OaEmailTemplateBo bo) { + return toAjax(iOaEmailTemplateService.updateByBo(bo)); + } + + /** + * 删除邮件模板 + * + * @param ids 主键串 + */ + @Log(title = "邮件模板", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ids) { + return toAjax(iOaEmailTemplateService.deleteWithValidByIds(Arrays.asList(ids), true)); + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/controller/OaFurnitureTableController.java b/gear-oa/src/main/java/com/gear/oa/controller/OaFurnitureTableController.java new file mode 100644 index 0000000..7bb7c49 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/controller/OaFurnitureTableController.java @@ -0,0 +1,100 @@ +package com.gear.oa.controller; + +import com.gear.common.annotation.Log; +import com.gear.common.annotation.RepeatSubmit; +import com.gear.common.core.controller.BaseController; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.domain.R; +import com.gear.common.core.page.TableDataInfo; +import com.gear.common.core.validate.AddGroup; +import com.gear.common.core.validate.EditGroup; +import com.gear.common.enums.BusinessType; +import com.gear.common.utils.poi.ExcelUtil; +import com.gear.oa.domain.bo.OaFurnitureTableBo; +import com.gear.oa.domain.vo.OaFurnitureTableVo; +import com.gear.oa.service.IOaFurnitureTableService; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Arrays; +import java.util.List; + +/** + * 家具 + * + * @author liujingchao + * @date 2025-07-08 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/oa/furnitureTable") +public class OaFurnitureTableController extends BaseController { + + private final IOaFurnitureTableService iOaFurnitureTableService; + + /** + * 查询家具列表 + */ + @GetMapping("/list") + public TableDataInfo list(OaFurnitureTableBo bo, PageQuery pageQuery) { + return iOaFurnitureTableService.queryPageList(bo, pageQuery); + } + + /** + * 导出家具列表 + */ + @Log(title = "家具", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(OaFurnitureTableBo bo, HttpServletResponse response) { + List list = iOaFurnitureTableService.queryList(bo); + ExcelUtil.exportExcel(list, "家具", OaFurnitureTableVo.class, response); + } + + /** + * 获取家具详细信息 + * + * @param furnitureId 主键 + */ + @GetMapping("/{furnitureId}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long furnitureId) { + return R.ok(iOaFurnitureTableService.queryById(furnitureId)); + } + + /** + * 新增家具 + */ + @Log(title = "家具", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody OaFurnitureTableBo bo) { + return toAjax(iOaFurnitureTableService.insertByBo(bo)); + } + + /** + * 修改家具 + */ + @Log(title = "家具", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody OaFurnitureTableBo bo) { + return toAjax(iOaFurnitureTableService.updateByBo(bo)); + } + + /** + * 删除家具 + * + * @param furnitureIds 主键串 + */ + @Log(title = "家具", businessType = BusinessType.DELETE) + @DeleteMapping("/{furnitureIds}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] furnitureIds) { + return toAjax(iOaFurnitureTableService.deleteWithValidByIds(Arrays.asList(furnitureIds), true)); + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/controller/SysOaArticleController.java b/gear-oa/src/main/java/com/gear/oa/controller/SysOaArticleController.java new file mode 100644 index 0000000..7cecbc1 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/controller/SysOaArticleController.java @@ -0,0 +1,118 @@ +package com.gear.oa.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.gear.common.annotation.Log; +import com.gear.common.annotation.RepeatSubmit; +import com.gear.common.core.controller.BaseController; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.domain.R; +import com.gear.common.core.page.TableDataInfo; +import com.gear.common.core.validate.AddGroup; +import com.gear.common.core.validate.EditGroup; +import com.gear.common.enums.BusinessType; +import com.gear.common.utils.poi.ExcelUtil; +import com.gear.oa.domain.SysOaArticle; +import com.gear.oa.domain.bo.SysOaArticleBo; +import com.gear.oa.domain.vo.SysOaArticleVo; +import com.gear.oa.service.ISysOaArticleService; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Arrays; +import java.util.List; + +/** + * 知识管理 + * + * @author huangxing + * @date 2024-01-17 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/oa/article") +public class SysOaArticleController extends BaseController { + + private final ISysOaArticleService iSysOaArticleService; + + /** + * 查询知识管理列表 + */ + @SaCheckPermission("oa:article:list") + @GetMapping("/list") + public TableDataInfo list(SysOaArticleBo bo, PageQuery pageQuery) { + return iSysOaArticleService.queryPageList(bo, pageQuery); + } + + /** + * 自定义查询知识管理列表 + */ + @SaCheckPermission("oa:article:list") + @GetMapping("/listArticle") + public TableDataInfo listArticle(SysOaArticleBo bo, PageQuery pageQuery) { + return iSysOaArticleService.selectArticlePageList(bo, pageQuery); + } + + /** + * 导出知识管理列表 + */ + @SaCheckPermission("oa:article:export") + @Log(title = "知识管理", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(SysOaArticleBo bo, HttpServletResponse response) { + List list = iSysOaArticleService.queryList(bo); + ExcelUtil.exportExcel(list, "知识管理", SysOaArticleVo.class, response); + } + + /** + * 获取知识管理详细信息 + * + * @param articleId 主键 + */ + @SaCheckPermission("oa:article:query") + @GetMapping("/{articleId}") + public R getInfo(@NotNull(message = "主键不能为空") @PathVariable Long articleId) { + SysOaArticle sysOaArticle = iSysOaArticleService.selectArticleById(articleId); + + return R.ok(sysOaArticle); + } + + /** + * 新增知识管理 + */ + @SaCheckPermission("oa:article:add") + @Log(title = "知识管理", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody SysOaArticleBo bo) { + return toAjax(iSysOaArticleService.insertByBo(bo)); + } + + /** + * 修改知识管理 + */ + @SaCheckPermission("oa:article:edit") + @Log(title = "知识管理", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody SysOaArticleBo bo) { + return toAjax(iSysOaArticleService.updateByBo(bo)); + } + + /** + * 删除知识管理 + * + * @param articleIds 主键串 + */ + @SaCheckPermission("oa:article:remove") + @Log(title = "知识管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{articleIds}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] articleIds) { + return toAjax(iSysOaArticleService.deleteWithValidByIds(Arrays.asList(articleIds), true)); + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/controller/SysOaCategoryController.java b/gear-oa/src/main/java/com/gear/oa/controller/SysOaCategoryController.java new file mode 100644 index 0000000..a207fb9 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/controller/SysOaCategoryController.java @@ -0,0 +1,106 @@ +package com.gear.oa.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.gear.common.annotation.Log; +import com.gear.common.annotation.RepeatSubmit; +import com.gear.common.core.controller.BaseController; +import com.gear.common.core.domain.R; +import com.gear.common.core.validate.AddGroup; +import com.gear.common.core.validate.EditGroup; +import com.gear.common.enums.BusinessType; +import com.gear.common.utils.poi.ExcelUtil; +import com.gear.oa.domain.bo.SysOaCategoryBo; +import com.gear.oa.domain.vo.SysOaCategoryVo; +import com.gear.oa.service.ISysOaCategoryService; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Arrays; +import java.util.List; + +/** + * 知识分类 + * + * @author huangxing + * @date 2024-01-17 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/oa/category") +public class SysOaCategoryController extends BaseController { + + private final ISysOaCategoryService iSysOaCategoryService; + + /** + * 查询知识分类列表 + */ + @SaCheckPermission("oa:category:list") + @GetMapping("/list") + public R> list(SysOaCategoryBo bo) { + List list = iSysOaCategoryService.queryList(bo); + return R.ok(list); + } + + /** + * 导出知识分类列表 + */ + @SaCheckPermission("oa:category:export") + @Log(title = "知识分类", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(SysOaCategoryBo bo, HttpServletResponse response) { + List list = iSysOaCategoryService.queryList(bo); + ExcelUtil.exportExcel(list, "知识分类", SysOaCategoryVo.class, response); + } + + /** + * 获取知识分类详细信息 + * + * @param categoryId 主键 + */ + @SaCheckPermission("oa:category:query") + @GetMapping("/{categoryId}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long categoryId) { + return R.ok(iSysOaCategoryService.queryById(categoryId)); + } + + /** + * 新增知识分类 + */ + @SaCheckPermission("oa:category:add") + @Log(title = "知识分类", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody SysOaCategoryBo bo) { + return toAjax(iSysOaCategoryService.insertByBo(bo)); + } + + /** + * 修改知识分类 + */ + @SaCheckPermission("oa:category:edit") + @Log(title = "知识分类", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody SysOaCategoryBo bo) { + return toAjax(iSysOaCategoryService.updateByBo(bo)); + } + + /** + * 删除知识分类 + * + * @param categoryIds 主键串 + */ + @SaCheckPermission("oa:category:remove") + @Log(title = "知识分类", businessType = BusinessType.DELETE) + @DeleteMapping("/{categoryIds}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] categoryIds) { + return toAjax(iSysOaCategoryService.deleteWithValidByIds(Arrays.asList(categoryIds), true)); + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/OaEmailAccount.java b/gear-oa/src/main/java/com/gear/oa/domain/OaEmailAccount.java new file mode 100644 index 0000000..5b054bb --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/OaEmailAccount.java @@ -0,0 +1,66 @@ +package com.gear.oa.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.gear.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 发件人邮箱账号管理对象 oa_email_account + * + * @author Joshi + * @date 2025-07-10 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("oa_email_account") +public class OaEmailAccount extends BaseEntity { + + private static final long serialVersionUID=1L; + + /** + * + */ + @TableId(value = "email_id") + private Long emailId; + /** + * 邮箱账号 + */ + private String email; + /** + * 邮箱授权码/密码(SMTP方式用) + */ + private String password; + /** + * SMTP服务器地址(SMTP方式用) + */ + private String smtpHost; + /** + * SMTP端口(SMTP方式用) + */ + private Long smtpPort; + /** + * API方式用accessKey + */ + private String accessKey; + /** + * API方式用secretKey + */ + private String secretKey; + /** + * 邮箱类型(0网易 1QQ 2阿里云API 3SendGridAPI等) + */ + private Long type; + /** + * 备注 + */ + private String remark; + /** + * 删除标志:0正常;1已删除 + */ + @TableLogic + private Integer delFlag; + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/OaEmailTemplate.java b/gear-oa/src/main/java/com/gear/oa/domain/OaEmailTemplate.java new file mode 100644 index 0000000..89d5228 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/OaEmailTemplate.java @@ -0,0 +1,54 @@ +package com.gear.oa.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.gear.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 邮件模板对象 oa_email_template + * + * @author ruoyi + * @date 2025-07-16 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("oa_email_template") +public class OaEmailTemplate extends BaseEntity { + + private static final long serialVersionUID=1L; + + /** + * 主键 + */ + @TableId(value = "id") + private Long id; + /** + * 模板名称 + */ + private String templateName; + /** + * 模板分类 + */ + private String category; + /** + * 模板内容(富文本HTML) + */ + private String content; + /** + * 附件信息(逗号分隔或JSON) + */ + private String attachments; + /** + * 删除标志:0正常;1已删除 + */ + @TableLogic + private Long delFlag; + /** + * 备注 + */ + private String remark; + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/OaFurnitureTable.java b/gear-oa/src/main/java/com/gear/oa/domain/OaFurnitureTable.java new file mode 100644 index 0000000..4367875 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/OaFurnitureTable.java @@ -0,0 +1,96 @@ +package com.gear.oa.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.gear.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 家具对象 oa_furniture_table + * + * @author liujingchao + * @date 2025-07-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("oa_furniture_table") +public class OaFurnitureTable extends BaseEntity { + + private static final long serialVersionUID=1L; + + /** + * + */ + @TableId(value = "furniture_id") + private Long furnitureId; + /** + * + */ + private String companyName; + /** + * + */ + private String state; + /** + * + */ + private String procurementOfProducts; + /** + * + */ + private String contactGroup; + /** + * + */ + private String phone; + /** + * + */ + private String fax; + /** + * + */ + private String address; + /** + * + */ + private String zip; + /** + * + */ + private String email; + /** + * + */ + private String website; + /** + * 发送邮件次数 + */ + private Long emailSendCount; + /** + * 上次发邮件时间 + */ + private Date lastEmailSendTime; + /** + * 跟单人 + */ + private String contactPerson; + /** + * 接收次数 + */ + private Long receiveCount; + /** + * 删除标志:0正常;1已删除 + */ + @TableLogic + private Integer delFlag; + /** + * 备注 + */ + private String remark; + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/SysOaArticle.java b/gear-oa/src/main/java/com/gear/oa/domain/SysOaArticle.java new file mode 100644 index 0000000..f8d94e1 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/SysOaArticle.java @@ -0,0 +1,62 @@ +package com.gear.oa.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.gear.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 知识管理对象 sys_oa_article + * + * @author huangxing + * @date 2024-01-17 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("sys_oa_article") +public class SysOaArticle extends BaseEntity { + + private static final long serialVersionUID=1L; + + /** + * 文章id + */ + @TableId(value = "article_id") + private Long articleId; + /** + * 文章分类 + */ + private Long categoryId; + /** + * 文章标题 + */ + private String articleTitle; + /** + * 副标题 + */ + private String subhead; + /** + * 来源 + */ + private String source; + /** + * 内容 + */ + private String content; + /** + * 查看数 + */ + private Integer checkNum; + /** + * 附件 + */ + private String accessory; + /** + * 备注 + */ + private String remark; + + private SysOaCategory category; + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/SysOaCategory.java b/gear-oa/src/main/java/com/gear/oa/domain/SysOaCategory.java new file mode 100644 index 0000000..670c7fb --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/SysOaCategory.java @@ -0,0 +1,40 @@ +package com.gear.oa.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.gear.common.core.domain.TreeEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 知识分类对象 sys_oa_category + * + * @author huangxing + * @date 2024-01-17 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("sys_oa_category") +public class SysOaCategory extends TreeEntity { + + private static final long serialVersionUID=1L; + + /** + * 产品id + */ + @TableId(value = "category_id") + private Long categoryId; + /** + * 分类名称 + */ + private String categoryName; + /** + * 状态 + */ + private String status; + /** + * 备注 + */ + private String remark; + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/bo/OaEmailAccountBo.java b/gear-oa/src/main/java/com/gear/oa/domain/bo/OaEmailAccountBo.java new file mode 100644 index 0000000..5e3f78a --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/bo/OaEmailAccountBo.java @@ -0,0 +1,64 @@ +package com.gear.oa.domain.bo; + +import com.gear.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 发件人邮箱账号管理业务对象 oa_email_account + * + * @author Joshi + * @date 2025-07-10 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +public class OaEmailAccountBo extends BaseEntity { + + /** + * + */ + private Long emailId; + + /** + * 邮箱账号 + */ + private String email; + + /** + * 邮箱授权码/密码(SMTP方式用) + */ + private String password; + + /** + * SMTP服务器地址(SMTP方式用) + */ + private String smtpHost; + + /** + * SMTP端口(SMTP方式用) + */ + private Long smtpPort; + + /** + * API方式用accessKey + */ + private String accessKey; + + /** + * API方式用secretKey + */ + private String secretKey; + + /** + * 邮箱类型(0网易 1QQ 2阿里云API 3SendGridAPI等) + */ + private Long type; + + /** + * 备注 + */ + private String remark; + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/bo/OaEmailTemplateBo.java b/gear-oa/src/main/java/com/gear/oa/domain/bo/OaEmailTemplateBo.java new file mode 100644 index 0000000..6889f6a --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/bo/OaEmailTemplateBo.java @@ -0,0 +1,49 @@ +package com.gear.oa.domain.bo; + +import com.gear.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 邮件模板业务对象 oa_email_template + * + * @author ruoyi + * @date 2025-07-16 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +public class OaEmailTemplateBo extends BaseEntity { + + /** + * 主键 + */ + private Long id; + + /** + * 模板名称 + */ + private String templateName; + + /** + * 模板分类 + */ + private String category; + + /** + * 模板内容(富文本HTML) + */ + private String content; + + /** + * 附件信息(逗号分隔或JSON) + */ + private String attachments; + + /** + * 备注 + */ + private String remark; + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/bo/OaFurnitureTableBo.java b/gear-oa/src/main/java/com/gear/oa/domain/bo/OaFurnitureTableBo.java new file mode 100644 index 0000000..d0a4423 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/bo/OaFurnitureTableBo.java @@ -0,0 +1,106 @@ +package com.gear.oa.domain.bo; + +import com.gear.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 家具业务对象 oa_furniture_table + * + * @author liujingchao + * @date 2025-07-08 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +public class OaFurnitureTableBo extends BaseEntity { + + /** + * + */ + private Long furnitureId; + + /** + * + */ + private String companyName; + + /** + * + */ + private String state; + + /** + * + */ + private String procurementOfProducts; + + /** + * + */ + private String contactGroup; + + /** + * + */ + private String phone; + + /** + * + */ + private String fax; + + /** + * + */ + private String address; + + /** + * + */ + private String zip; + + /** + * + */ + private String email; + + /** + * + */ + private String website; + + /** + * 发送邮件次数 + */ + private Long emailSendCount; + + /** + * 上次发邮件时间 + */ + private Date lastEmailSendTime; + + /** + * 跟单人 + */ + private String contactPerson; + + /** + * 接收次数 + */ + private Long receiveCount; + + /** + * 备注 + */ + private String remark; + + /** + * 优质筛选:true表示只查询邮箱不为空的记录 + */ + private Boolean qualityFilter; + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/bo/SysOaArticleBo.java b/gear-oa/src/main/java/com/gear/oa/domain/bo/SysOaArticleBo.java new file mode 100644 index 0000000..a0cbd8f --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/bo/SysOaArticleBo.java @@ -0,0 +1,75 @@ +package com.gear.oa.domain.bo; + +import com.gear.common.core.domain.BaseEntity; +import com.gear.common.core.validate.AddGroup; +import com.gear.common.core.validate.EditGroup; +import com.gear.oa.domain.SysOaCategory; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * 知识管理业务对象 sys_oa_article + * + * @author huangxing + * @date 2024-01-17 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +public class SysOaArticleBo extends BaseEntity { + + /** + * 文章id + */ + @NotNull(message = "文章id不能为空", groups = { EditGroup.class }) + private Long articleId; + + /** + * 文章分类 + */ + @NotNull(message = "文章分类不能为空", groups = { AddGroup.class, EditGroup.class }) + private Long categoryId; + + /** + * 文章标题 + */ + @NotBlank(message = "文章标题不能为空", groups = { AddGroup.class, EditGroup.class }) + private String articleTitle; + + /** + * 副标题 + */ + private String subhead; + + /** + * 来源 + */ + private String source; + + /** + * 内容 + */ + private String content; + + /** + * 查看数 + */ + private Integer checkNum; + + /** + * 附件 + */ + private String accessory; + + /** + * 备注 + */ + private String remark; + + private SysOaCategory category; + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/bo/SysOaCategoryBo.java b/gear-oa/src/main/java/com/gear/oa/domain/bo/SysOaCategoryBo.java new file mode 100644 index 0000000..0c30a60 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/bo/SysOaCategoryBo.java @@ -0,0 +1,47 @@ +package com.gear.oa.domain.bo; + +import com.gear.common.core.domain.TreeEntity; +import com.gear.common.core.validate.AddGroup; +import com.gear.common.core.validate.EditGroup; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * 知识分类业务对象 sys_oa_category + * + * @author huangxing + * @date 2024-01-17 + */ + +@Data +@EqualsAndHashCode(callSuper = true) +public class SysOaCategoryBo extends TreeEntity { + + /** + * 产品id + */ + @NotNull(message = "产品id不能为空", groups = { EditGroup.class }) + private Long categoryId; + + /** + * 分类名称 + */ + @NotBlank(message = "分类名称不能为空", groups = { AddGroup.class, EditGroup.class }) + private String categoryName; + + /** + * 状态 + */ + @NotBlank(message = "状态不能为空", groups = { AddGroup.class, EditGroup.class }) + private String status; + + /** + * 备注 + */ + private String remark; + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/request/EmailSendRequest.java b/gear-oa/src/main/java/com/gear/oa/domain/request/EmailSendRequest.java new file mode 100644 index 0000000..158b271 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/request/EmailSendRequest.java @@ -0,0 +1,26 @@ +package com.gear.oa.domain.request; + +import lombok.Data; + +import java.util.List; + +/** + * 邮件批量发送请求参数 + */ +@Data +public class EmailSendRequest { + /** 发件人邮箱账号ID */ + private Long emailAccountId; + /** 收件人邮箱列表 */ + private List toList; + /** 邮件主题 */ + private String subject; + /** 邮件正文 */ + private String content; + /** 附件文件路径列表 */ + private List attachmentPaths; + /** 内嵌图片路径列表 */ + private List inlineImagePaths; + /** 家具ID列表(发送邮件时关联的多个家具) */ + private List furnitureIds; +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/OaEmailAccountVo.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/OaEmailAccountVo.java new file mode 100644 index 0000000..e2dc49c --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/OaEmailAccountVo.java @@ -0,0 +1,81 @@ +package com.gear.oa.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import com.gear.common.annotation.ExcelDictFormat; +import com.gear.common.convert.ExcelDictConvert; +import lombok.Data; + + +/** + * 发件人邮箱账号管理视图对象 oa_email_account + * + * @author Joshi + * @date 2025-07-10 + */ +@Data +@ExcelIgnoreUnannotated +public class OaEmailAccountVo { + + private static final long serialVersionUID = 1L; + + /** + * + */ + @ExcelProperty(value = "") + private Long emailId; + + /** + * 邮箱账号 + */ + @ExcelProperty(value = "邮箱账号") + private String email; + + /** + * 邮箱授权码/密码(SMTP方式用) + */ + @ExcelProperty(value = "邮箱授权码/密码", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "S=MTP方式用") + private String password; + + /** + * SMTP服务器地址(SMTP方式用) + */ + @ExcelProperty(value = "SMTP服务器地址", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "S=MTP方式用") + private String smtpHost; + + /** + * SMTP端口(SMTP方式用) + */ + @ExcelProperty(value = "SMTP端口", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "S=MTP方式用") + private Long smtpPort; + + /** + * API方式用accessKey + */ + @ExcelProperty(value = "API方式用accessKey") + private String accessKey; + + /** + * API方式用secretKey + */ + @ExcelProperty(value = "API方式用secretKey") + private String secretKey; + + /** + * 邮箱类型(0网易 1QQ 2阿里云API 3SendGridAPI等) + */ + @ExcelProperty(value = "邮箱类型", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "0=网易,1=QQ,2=阿里云API,3=SendGridAPI等") + private Long type; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/OaEmailTemplateVo.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/OaEmailTemplateVo.java new file mode 100644 index 0000000..9582abe --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/OaEmailTemplateVo.java @@ -0,0 +1,61 @@ +package com.gear.oa.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import com.gear.common.annotation.ExcelDictFormat; +import com.gear.common.convert.ExcelDictConvert; +import lombok.Data; + + +/** + * 邮件模板视图对象 oa_email_template + * + * @author ruoyi + * @date 2025-07-16 + */ +@Data +@ExcelIgnoreUnannotated +public class OaEmailTemplateVo { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @ExcelProperty(value = "主键") + private Long id; + + /** + * 模板名称 + */ + @ExcelProperty(value = "模板名称") + private String templateName; + + /** + * 模板分类 + */ + @ExcelProperty(value = "模板分类") + private String category; + + /** + * 模板内容(富文本HTML) + */ + @ExcelProperty(value = "模板内容", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "富=文本HTML") + private String content; + + /** + * 附件信息(逗号分隔或JSON) + */ + @ExcelProperty(value = "附件信息", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "逗=号分隔或JSON") + private String attachments; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/OaFurnitureTableVo.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/OaFurnitureTableVo.java new file mode 100644 index 0000000..5b4b5a6 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/OaFurnitureTableVo.java @@ -0,0 +1,119 @@ +package com.gear.oa.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.util.Date; + + +/** + * 家具视图对象 oa_furniture_table + * + * @author liujingchao + * @date 2025-07-08 + */ +@Data +@ExcelIgnoreUnannotated +public class OaFurnitureTableVo { + + private static final long serialVersionUID = 1L; + + /** + * + */ + @ExcelProperty(value = "") + private Long furnitureId; + + /** + * + */ + @ExcelProperty(value = "") + private String companyName; + + /** + * + */ + @ExcelProperty(value = "") + private String state; + + /** + * + */ + @ExcelProperty(value = "") + private String procurementOfProducts; + + /** + * + */ + @ExcelProperty(value = "") + private String contactGroup; + + /** + * + */ + @ExcelProperty(value = "") + private String phone; + + /** + * + */ + @ExcelProperty(value = "") + private String fax; + + /** + * + */ + @ExcelProperty(value = "") + private String address; + + /** + * + */ + @ExcelProperty(value = "") + private String zip; + + /** + * + */ + @ExcelProperty(value = "") + private String email; + + /** + * + */ + @ExcelProperty(value = "") + private String website; + + /** + * 发送邮件次数 + */ + @ExcelProperty(value = "发送邮件次数") + private Long emailSendCount; + + /** + * 上次发邮件时间 + */ + @ExcelProperty(value = "上次发邮件时间") + private Date lastEmailSendTime; + + /** + * 跟单人 + */ + @ExcelProperty(value = "跟单人") + private String contactPerson; + + /** + * 接收次数 + */ + @ExcelProperty(value = "接收次数") + private Long receiveCount; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/SysOaArticleVo.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/SysOaArticleVo.java new file mode 100644 index 0000000..3f829a3 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/SysOaArticleVo.java @@ -0,0 +1,81 @@ +package com.gear.oa.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import com.gear.oa.domain.SysOaCategory; +import lombok.Data; + +import java.util.Date; + + +/** + * 知识管理视图对象 sys_oa_article + * + * @author huangxing + * @date 2024-01-17 + */ +@Data +@ExcelIgnoreUnannotated +public class SysOaArticleVo { + + private static final long serialVersionUID = 1L; + + /** + * 文章id + */ + @ExcelProperty(value = "文章id") + private Long articleId; + + /** + * 文章分类 + */ + @ExcelProperty(value = "文章分类") + private Long categoryId; + + /** + * 文章标题 + */ + @ExcelProperty(value = "文章标题") + private String articleTitle; + + /** + * 文章标题 + */ + @ExcelProperty(value = "文章副标题") + private String subhead; + + /** + * 来源 + */ + @ExcelProperty(value = "来源") + private String source; + + /** + * 备注 + */ + @ExcelProperty(value = "描述") + private String remark; + + /** + * 查看数 + */ + @ExcelProperty(value = "查看数") + private Integer checkNum; + + /** + * 创建者 + */ + @ExcelProperty(value = "创建者") + private String createBy; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + private Date createTime; + + @ExcelProperty(value = "分类实体") + private SysOaCategory category; + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/SysOaCategoryVo.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/SysOaCategoryVo.java new file mode 100644 index 0000000..0941c12 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/SysOaCategoryVo.java @@ -0,0 +1,65 @@ +package com.gear.oa.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.util.Date; + + +/** + * 知识分类视图对象 sys_oa_category + * + * @author huangxing + * @date 2024-01-17 + */ +@Data +@ExcelIgnoreUnannotated +public class SysOaCategoryVo { + + private static final long serialVersionUID = 1L; + + /** + * 产品id + */ + @ExcelProperty(value = "产品id") + private Long categoryId; + + /** + * 父级分类id + */ + @ExcelProperty(value = "父级分类id") + private Long parentId; + + /** + * 分类名称 + */ + @ExcelProperty(value = "分类名称") + private String categoryName; + + /** + * 状态 + */ + @ExcelProperty(value = "状态") + private String status; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + /** + * 创建者 + */ + @ExcelProperty(value = "创建者") + private String createBy; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + private Date createTime; + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/mapper/OaEmailAccountMapper.java b/gear-oa/src/main/java/com/gear/oa/mapper/OaEmailAccountMapper.java new file mode 100644 index 0000000..aab1b6d --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/mapper/OaEmailAccountMapper.java @@ -0,0 +1,15 @@ +package com.gear.oa.mapper; + +import com.gear.common.core.mapper.BaseMapperPlus; +import com.gear.oa.domain.OaEmailAccount; +import com.gear.oa.domain.vo.OaEmailAccountVo; + +/** + * 发件人邮箱账号管理Mapper接口 + * + * @author Joshi + * @date 2025-07-10 + */ +public interface OaEmailAccountMapper extends BaseMapperPlus { + +} diff --git a/gear-oa/src/main/java/com/gear/oa/mapper/OaEmailTemplateMapper.java b/gear-oa/src/main/java/com/gear/oa/mapper/OaEmailTemplateMapper.java new file mode 100644 index 0000000..a0adbfb --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/mapper/OaEmailTemplateMapper.java @@ -0,0 +1,15 @@ +package com.gear.oa.mapper; + +import com.gear.common.core.mapper.BaseMapperPlus; +import com.gear.oa.domain.OaEmailTemplate; +import com.gear.oa.domain.vo.OaEmailTemplateVo; + +/** + * 邮件模板Mapper接口 + * + * @author ruoyi + * @date 2025-07-16 + */ +public interface OaEmailTemplateMapper extends BaseMapperPlus { + +} diff --git a/gear-oa/src/main/java/com/gear/oa/mapper/OaFurnitureTableMapper.java b/gear-oa/src/main/java/com/gear/oa/mapper/OaFurnitureTableMapper.java new file mode 100644 index 0000000..f29adc5 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/mapper/OaFurnitureTableMapper.java @@ -0,0 +1,26 @@ +package com.gear.oa.mapper; + +import com.gear.common.core.mapper.BaseMapperPlus; +import com.gear.oa.domain.OaFurnitureTable; +import com.gear.oa.domain.vo.OaFurnitureTableVo; + +import java.util.List; + +/** + * 家具Mapper接口 + * + * @author liujingchao + * @date 2025-07-08 + */ +public interface OaFurnitureTableMapper extends BaseMapperPlus { + + /** + * 邮件发送成功后,更新发送次数和上次发送时间 + */ + int updateEmailSendInfo(Long furnitureId); + + /** + * 根据家具ID列表批量查询邮箱地址 + */ + List selectEmailsByFurnitureIds(List furnitureIds); +} diff --git a/gear-oa/src/main/java/com/gear/oa/mapper/SysOaArticleMapper.java b/gear-oa/src/main/java/com/gear/oa/mapper/SysOaArticleMapper.java new file mode 100644 index 0000000..d4a00d8 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/mapper/SysOaArticleMapper.java @@ -0,0 +1,32 @@ +package com.gear.oa.mapper; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gear.common.annotation.DataColumn; +import com.gear.common.annotation.DataPermission; +import com.gear.common.core.mapper.BaseMapperPlus; +import com.gear.oa.domain.SysOaArticle; +import com.gear.oa.domain.vo.SysOaArticleVo; +import org.apache.ibatis.annotations.Param; + +/** + * 知识管理Mapper接口 + * + * @author huangxing + * @date 2024-01-17 + */ +public interface SysOaArticleMapper extends BaseMapperPlus { + + + @DataPermission({ + @DataColumn(key = "categoryName", value = "c.category_id"), + @DataColumn(key = "articleTitle", value = "a.article_id") + }) + Page selectArticlePageList(@Param("page") Page page, @Param(Constants.WRAPPER)Wrapper queryWrapper); + + SysOaArticle selectArticleById(Long articleId); + + + +} diff --git a/gear-oa/src/main/java/com/gear/oa/mapper/SysOaCategoryMapper.java b/gear-oa/src/main/java/com/gear/oa/mapper/SysOaCategoryMapper.java new file mode 100644 index 0000000..6668008 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/mapper/SysOaCategoryMapper.java @@ -0,0 +1,15 @@ +package com.gear.oa.mapper; + +import com.gear.common.core.mapper.BaseMapperPlus; +import com.gear.oa.domain.SysOaCategory; +import com.gear.oa.domain.vo.SysOaCategoryVo; + +/** + * 知识分类Mapper接口 + * + * @author huangxing + * @date 2024-01-17 + */ +public interface SysOaCategoryMapper extends BaseMapperPlus { + +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/IOaEmailAccountService.java b/gear-oa/src/main/java/com/gear/oa/service/IOaEmailAccountService.java new file mode 100644 index 0000000..726e5bd --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/IOaEmailAccountService.java @@ -0,0 +1,54 @@ +package com.gear.oa.service; + +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.oa.domain.bo.OaEmailAccountBo; +import com.gear.oa.domain.request.EmailSendRequest; +import com.gear.oa.domain.vo.OaEmailAccountVo; + +import java.util.Collection; +import java.util.List; + +/** + * 发件人邮箱账号管理Service接口 + * + * @author Joshi + * @date 2025-07-10 + */ +public interface IOaEmailAccountService { + + /** + * 查询发件人邮箱账号管理 + */ + OaEmailAccountVo queryById(Long emailId); + + /** + * 查询发件人邮箱账号管理列表 + */ + TableDataInfo queryPageList(OaEmailAccountBo bo, PageQuery pageQuery); + + /** + * 查询发件人邮箱账号管理列表 + */ + List queryList(OaEmailAccountBo bo); + + /** + * 新增发件人邮箱账号管理 + */ + Boolean insertByBo(OaEmailAccountBo bo); + + /** + * 修改发件人邮箱账号管理 + */ + Boolean updateByBo(OaEmailAccountBo bo); + + /** + * 校验并批量删除发件人邮箱账号管理信息 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + /** + * 批量发送邮件(支持网易企业邮箱、飞书SMTP) + */ + String sendBatchEmail(EmailSendRequest request); +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/IOaEmailTemplateService.java b/gear-oa/src/main/java/com/gear/oa/service/IOaEmailTemplateService.java new file mode 100644 index 0000000..cc4a1e7 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/IOaEmailTemplateService.java @@ -0,0 +1,48 @@ +package com.gear.oa.service; + +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.oa.domain.bo.OaEmailTemplateBo; +import com.gear.oa.domain.vo.OaEmailTemplateVo; + +import java.util.Collection; +import java.util.List; + +/** + * 邮件模板Service接口 + * + * @author ruoyi + * @date 2025-07-16 + */ +public interface IOaEmailTemplateService { + + /** + * 查询邮件模板 + */ + OaEmailTemplateVo queryById(Long id); + + /** + * 查询邮件模板列表 + */ + TableDataInfo queryPageList(OaEmailTemplateBo bo, PageQuery pageQuery); + + /** + * 查询邮件模板列表 + */ + List queryList(OaEmailTemplateBo bo); + + /** + * 新增邮件模板 + */ + Boolean insertByBo(OaEmailTemplateBo bo); + + /** + * 修改邮件模板 + */ + Boolean updateByBo(OaEmailTemplateBo bo); + + /** + * 校验并批量删除邮件模板信息 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/IOaFurnitureTableService.java b/gear-oa/src/main/java/com/gear/oa/service/IOaFurnitureTableService.java new file mode 100644 index 0000000..46f245b --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/IOaFurnitureTableService.java @@ -0,0 +1,48 @@ +package com.gear.oa.service; + +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.oa.domain.bo.OaFurnitureTableBo; +import com.gear.oa.domain.vo.OaFurnitureTableVo; + +import java.util.Collection; +import java.util.List; + +/** + * 家具Service接口 + * + * @author liujingchao + * @date 2025-07-08 + */ +public interface IOaFurnitureTableService { + + /** + * 查询家具 + */ + OaFurnitureTableVo queryById(Long furnitureId); + + /** + * 查询家具列表 + */ + TableDataInfo queryPageList(OaFurnitureTableBo bo, PageQuery pageQuery); + + /** + * 查询家具列表 + */ + List queryList(OaFurnitureTableBo bo); + + /** + * 新增家具 + */ + Boolean insertByBo(OaFurnitureTableBo bo); + + /** + * 修改家具 + */ + Boolean updateByBo(OaFurnitureTableBo bo); + + /** + * 校验并批量删除家具信息 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/ISysOaArticleService.java b/gear-oa/src/main/java/com/gear/oa/service/ISysOaArticleService.java new file mode 100644 index 0000000..68bba6a --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/ISysOaArticleService.java @@ -0,0 +1,52 @@ +package com.gear.oa.service; + +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.oa.domain.SysOaArticle; +import com.gear.oa.domain.bo.SysOaArticleBo; +import com.gear.oa.domain.vo.SysOaArticleVo; + +import java.util.Collection; +import java.util.List; + +/** + * 知识管理Service接口 + * + * @author huangxing + * @date 2024-01-17 + */ +public interface ISysOaArticleService { + + /** + * 查询知识管理 + */ + SysOaArticle selectArticleById(Long articleId); + + /** + * 查询知识管理列表 + */ + TableDataInfo queryPageList(SysOaArticleBo bo, PageQuery pageQuery); + + /** + * 查询知识管理列表 + */ + List queryList(SysOaArticleBo bo); + + + TableDataInfo selectArticlePageList(SysOaArticleBo bo, PageQuery pageQuery); + + /** + * 新增知识管理 + */ + Boolean insertByBo(SysOaArticleBo bo); + + /** + * 修改知识管理 + */ + Boolean updateByBo(SysOaArticleBo bo); + + /** + * 校验并批量删除知识管理信息 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/ISysOaCategoryService.java b/gear-oa/src/main/java/com/gear/oa/service/ISysOaCategoryService.java new file mode 100644 index 0000000..da34e67 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/ISysOaCategoryService.java @@ -0,0 +1,42 @@ +package com.gear.oa.service; + +import com.gear.oa.domain.bo.SysOaCategoryBo; +import com.gear.oa.domain.vo.SysOaCategoryVo; + +import java.util.Collection; +import java.util.List; + +/** + * 知识分类Service接口 + * + * @author huangxing + * @date 2024-01-17 + */ +public interface ISysOaCategoryService { + + /** + * 查询知识分类 + */ + SysOaCategoryVo queryById(Long categoryId); + + + /** + * 查询知识分类列表 + */ + List queryList(SysOaCategoryBo bo); + + /** + * 新增知识分类 + */ + Boolean insertByBo(SysOaCategoryBo bo); + + /** + * 修改知识分类 + */ + Boolean updateByBo(SysOaCategoryBo bo); + + /** + * 校验并批量删除知识分类信息 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/impl/OaEmailAccountServiceImpl.java b/gear-oa/src/main/java/com/gear/oa/service/impl/OaEmailAccountServiceImpl.java new file mode 100644 index 0000000..6d71a32 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/impl/OaEmailAccountServiceImpl.java @@ -0,0 +1,331 @@ +package com.gear.oa.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.aliyuncs.DefaultAcsClient; +import com.aliyuncs.IAcsClient; +import com.aliyuncs.dm.model.v20151123.SingleSendMailRequest; +import com.aliyuncs.dm.model.v20151123.SingleSendMailResponse; +import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.profile.DefaultProfile; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.lark.oapi.Client; +import com.lark.oapi.service.mail.v1.model.MailAddress; +import com.lark.oapi.service.mail.v1.model.Message; +import com.lark.oapi.service.mail.v1.model.SendUserMailboxMessageReq; +import com.lark.oapi.service.mail.v1.model.SendUserMailboxMessageResp; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.common.utils.StringUtils; +import com.gear.oa.config.DynamicMailConfig; +import com.gear.oa.domain.OaEmailAccount; +import com.gear.oa.domain.bo.OaEmailAccountBo; +import com.gear.oa.domain.request.EmailSendRequest; +import com.gear.oa.domain.vo.OaEmailAccountVo; +import com.gear.oa.mapper.OaEmailAccountMapper; +import com.gear.oa.mapper.OaFurnitureTableMapper; +import com.gear.oa.service.IOaEmailAccountService; +import com.gear.oa.utils.EmailUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * 发件人邮箱账号管理Service业务层处理 + * + * @author Joshi + * @date 2025-07-10 + */ +@RequiredArgsConstructor +@Service +public class OaEmailAccountServiceImpl implements IOaEmailAccountService { + + private final OaEmailAccountMapper baseMapper; + + @Autowired + private EmailUtil emailUtil; + + @Autowired + private OaFurnitureTableMapper oaFurnitureTableMapper; + + @Autowired + private DynamicMailConfig dynamicMailConfig; + + /** + * 查询发件人邮箱账号管理 + */ + @Override + public OaEmailAccountVo queryById(Long emailId){ + return baseMapper.selectVoById(emailId); + } + + /** + * 查询发件人邮箱账号管理列表 + */ + @Override + public TableDataInfo queryPageList(OaEmailAccountBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询发件人邮箱账号管理列表 + */ + @Override + public List queryList(OaEmailAccountBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(OaEmailAccountBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(StringUtils.isNotBlank(bo.getEmail()), OaEmailAccount::getEmail, bo.getEmail()); + lqw.eq(StringUtils.isNotBlank(bo.getPassword()), OaEmailAccount::getPassword, bo.getPassword()); + lqw.eq(StringUtils.isNotBlank(bo.getSmtpHost()), OaEmailAccount::getSmtpHost, bo.getSmtpHost()); + lqw.eq(bo.getSmtpPort() != null, OaEmailAccount::getSmtpPort, bo.getSmtpPort()); + lqw.eq(StringUtils.isNotBlank(bo.getAccessKey()), OaEmailAccount::getAccessKey, bo.getAccessKey()); + lqw.eq(StringUtils.isNotBlank(bo.getSecretKey()), OaEmailAccount::getSecretKey, bo.getSecretKey()); + lqw.eq(bo.getType() != null, OaEmailAccount::getType, bo.getType()); + return lqw; + } + + /** + * 新增发件人邮箱账号管理 + */ + @Override + public Boolean insertByBo(OaEmailAccountBo bo) { + OaEmailAccount add = BeanUtil.toBean(bo, OaEmailAccount.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setEmailId(add.getEmailId()); + } + return flag; + } + + /** + * 修改发件人邮箱账号管理 + */ + @Override + public Boolean updateByBo(OaEmailAccountBo bo) { + OaEmailAccount update = BeanUtil.toBean(bo, OaEmailAccount.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(OaEmailAccount entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 批量删除发件人邮箱账号管理 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteBatchIds(ids) > 0; + } + + @Override + public String sendBatchEmail(EmailSendRequest request) { + OaEmailAccount account = baseMapper.selectById(request.getEmailAccountId()); + if (account == null) { + return "发件人邮箱账号不存在"; + } + + // 输出SMTP服务器信息 + String smtpHost = dynamicMailConfig.getSmtpHostByEmail(account.getEmail(), account.getSmtpHost()); + System.out.println("使用邮箱: " + account.getEmail() + ", SMTP服务器: " + smtpHost); + + List emailList = oaFurnitureTableMapper.selectEmailsByFurnitureIds(request.getFurnitureIds()); + int type = account.getType() == null ? -1 : account.getType().intValue(); + int success = 0, fail = 0; + StringBuilder failList = new StringBuilder(); + // 处理附件:如果是http/https链接,先下载 + List attachmentFiles = new ArrayList<>(); + try { + if (request.getAttachmentPaths() != null && !request.getAttachmentPaths().isEmpty()) { + for (String path : request.getAttachmentPaths()) { + if (path.startsWith("http://") || path.startsWith("https://")) { + attachmentFiles.add(EmailUtil.downloadUrlToTempFile(path)); + } else { + attachmentFiles.add(new File(path)); + } + } + } + if (type == 0 || type == 1) { + for (String to : emailList) { + try { + boolean isHtml = request.getContent() != null && + (request.getContent().contains("")); + boolean hasAttachments = !attachmentFiles.isEmpty(); + boolean hasInlineImages = request.getInlineImagePaths() != null && !request.getInlineImagePaths().isEmpty(); + if (hasAttachments && hasInlineImages) { + if (isHtml) { + String processedContent = emailUtil.processHtmlWithInlineImages(request.getContent(), request.getInlineImagePaths()); + emailUtil.sendHtmlMailWithAttachmentsAndDynamicConfig(account, to, request.getSubject(), processedContent, toPathList(attachmentFiles)); + } else { + emailUtil.sendMailWithAttachmentAndDynamicConfig(account, to, request.getSubject(), request.getContent(), attachmentFiles.get(0).getAbsolutePath()); + } + } else if (hasAttachments) { + if (isHtml) { + emailUtil.sendHtmlMailWithAttachmentsAndDynamicConfig(account, to, request.getSubject(), request.getContent(), toPathList(attachmentFiles)); + } else { + emailUtil.sendMailWithAttachmentAndDynamicConfig(account, to, request.getSubject(), request.getContent(), attachmentFiles.get(0).getAbsolutePath()); + } + } else if (hasInlineImages) { + if (isHtml) { + emailUtil.sendHtmlMailWithInlineImagesAndDynamicConfig(account, to, request.getSubject(), request.getContent(), request.getInlineImagePaths()); + } else { + emailUtil.sendMailWithDynamicConfig(account, to, request.getSubject(), request.getContent()); + } + } else { + if (isHtml) { + emailUtil.sendHtmlMailWithDynamicConfig(account, to, request.getSubject(), request.getContent()); + } else { + emailUtil.sendMailWithDynamicConfig(account, to, request.getSubject(), request.getContent()); + } + } + success++; + } catch (Exception e) { + fail++; + failList.append(to).append(", "); + } + } + } else if (type == 2) { + for (String to : emailList) { + try { + boolean result = sendAliyunMail(account, to, request.getSubject(), request.getContent()); + if (result) { + success++; + } else { + fail++; + failList.append(to).append(", "); + } + } catch (Exception e) { + fail++; + failList.append(to).append(", "); + } + } + } else if (type == 3) { + for (String to : emailList) { + try { + boolean result = sendFeishuMail(account, to, request.getSubject(), request.getContent()); + if (result) { + success++; + } else { + fail++; + failList.append(to).append(", "); + } + } catch (Exception e) { + fail++; + failList.append(to).append(", "); + } + } + } else { + return "不支持的邮箱类型"; + } + } catch (Exception e) { + return "附件处理失败:" + e.getMessage(); + } finally { + // 删除所有临时文件 + for (File file : attachmentFiles) { + if (file != null && file.exists() && file.getName().startsWith("mail_attach_")) { + file.delete(); + } + } + } + if (success > 0 && request.getFurnitureIds() != null) { + for (Long furnitureId : request.getFurnitureIds()) { + oaFurnitureTableMapper.updateEmailSendInfo(furnitureId); + } + } + return "发送成功" + success + "封,失败" + fail + "封" + (fail > 0 ? (",失败邮箱:" + failList) : ""); + } + + // 辅助方法:File列表转路径列表 + private List toPathList(List files) { + List paths = new ArrayList<>(); + for (File f : files) { + if (f != null) paths.add(f.getAbsolutePath()); + } + return paths; + } + private boolean sendAliyunMail(OaEmailAccount account, String to, String subject, String content) { + try { + DefaultProfile profile = DefaultProfile.getProfile( + "cn-hangzhou", + account.getAccessKey(), + account.getSecretKey() + ); + IAcsClient client = new DefaultAcsClient(profile); + + SingleSendMailRequest request = new SingleSendMailRequest(); + request.setAccountName(account.getEmail()); + request.setFromAlias("发件人昵称"); + request.setAddressType(1); + request.setReplyToAddress(true); + request.setToAddress(to); + request.setSubject(subject); + request.setHtmlBody(content); + + SingleSendMailResponse response = client.getAcsResponse(request); + //打印这个响应 + System.out.println(response.getRequestId()); + return true; + } catch (ClientException e) { + // 打印日志 e.getErrCode() + e.getErrMsg() + return false; + } + } + private boolean sendFeishuMail(OaEmailAccount account, String to, String subject, String content) { + try { + // 1. 构建飞书Client + Client client = Client.newBuilder(account.getAccessKey(), account.getSecretKey()).build(); + + // 2. 构建收件人 + MailAddress[] toList = new MailAddress[]{ + MailAddress.newBuilder().mailAddress(to).name(to).build() + }; + + // 3. 构建请求 + SendUserMailboxMessageReq req = SendUserMailboxMessageReq.newBuilder() + .userMailboxId("me") // 推荐用 "me" + .message(Message.newBuilder() + .subject(subject) + .to(toList) + .bodyHtml(content) + .build()) + .build(); + + // 4. 发送请求 + SendUserMailboxMessageResp resp = client.mail().v1().userMailboxMessage().send(req); + + // 5. 判断结果 + if (!resp.success()) { + // 可加日志 resp.getCode(), resp.getMsg() + return false; + } + return true; + } catch (Exception e) { + // 可加日志 e.getMessage() + return false; + } + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/impl/OaEmailTemplateServiceImpl.java b/gear-oa/src/main/java/com/gear/oa/service/impl/OaEmailTemplateServiceImpl.java new file mode 100644 index 0000000..d092aa8 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/impl/OaEmailTemplateServiceImpl.java @@ -0,0 +1,112 @@ +package com.gear.oa.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.common.utils.StringUtils; +import com.gear.oa.domain.OaEmailTemplate; +import com.gear.oa.domain.bo.OaEmailTemplateBo; +import com.gear.oa.domain.vo.OaEmailTemplateVo; +import com.gear.oa.mapper.OaEmailTemplateMapper; +import com.gear.oa.service.IOaEmailTemplateService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * 邮件模板Service业务层处理 + * + * @author ruoyi + * @date 2025-07-16 + */ +@RequiredArgsConstructor +@Service +public class OaEmailTemplateServiceImpl implements IOaEmailTemplateService { + + private final OaEmailTemplateMapper baseMapper; + + /** + * 查询邮件模板 + */ + @Override + public OaEmailTemplateVo queryById(Long id){ + return baseMapper.selectVoById(id); + } + + /** + * 查询邮件模板列表 + */ + @Override + public TableDataInfo queryPageList(OaEmailTemplateBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询邮件模板列表 + */ + @Override + public List queryList(OaEmailTemplateBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(OaEmailTemplateBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.like(StringUtils.isNotBlank(bo.getTemplateName()), OaEmailTemplate::getTemplateName, bo.getTemplateName()); + lqw.eq(StringUtils.isNotBlank(bo.getCategory()), OaEmailTemplate::getCategory, bo.getCategory()); + lqw.eq(StringUtils.isNotBlank(bo.getContent()), OaEmailTemplate::getContent, bo.getContent()); + lqw.eq(StringUtils.isNotBlank(bo.getAttachments()), OaEmailTemplate::getAttachments, bo.getAttachments()); + return lqw; + } + + /** + * 新增邮件模板 + */ + @Override + public Boolean insertByBo(OaEmailTemplateBo bo) { + OaEmailTemplate add = BeanUtil.toBean(bo, OaEmailTemplate.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setId(add.getId()); + } + return flag; + } + + /** + * 修改邮件模板 + */ + @Override + public Boolean updateByBo(OaEmailTemplateBo bo) { + OaEmailTemplate update = BeanUtil.toBean(bo, OaEmailTemplate.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(OaEmailTemplate entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 批量删除邮件模板 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteBatchIds(ids) > 0; + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/impl/OaFurnitureTableServiceImpl.java b/gear-oa/src/main/java/com/gear/oa/service/impl/OaFurnitureTableServiceImpl.java new file mode 100644 index 0000000..d61bad3 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/impl/OaFurnitureTableServiceImpl.java @@ -0,0 +1,131 @@ +package com.gear.oa.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.common.utils.StringUtils; +import com.gear.oa.domain.OaFurnitureTable; +import com.gear.oa.domain.bo.OaFurnitureTableBo; +import com.gear.oa.domain.vo.OaFurnitureTableVo; +import com.gear.oa.mapper.OaFurnitureTableMapper; +import com.gear.oa.service.IOaFurnitureTableService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * 家具Service业务层处理 + * + * @author liujingchao + * @date 2025-07-08 + */ +@RequiredArgsConstructor +@Service +public class OaFurnitureTableServiceImpl implements IOaFurnitureTableService { + + private final OaFurnitureTableMapper baseMapper; + + /** + * 查询家具 + */ + @Override + public OaFurnitureTableVo queryById(Long furnitureId){ + return baseMapper.selectVoById(furnitureId); + } + + /** + * 查询家具列表 + */ + @Override + public TableDataInfo queryPageList(OaFurnitureTableBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询家具列表 + */ + @Override + public List queryList(OaFurnitureTableBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(OaFurnitureTableBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.like(StringUtils.isNotBlank(bo.getCompanyName()), OaFurnitureTable::getCompanyName, bo.getCompanyName()); + lqw.eq(StringUtils.isNotBlank(bo.getState()), OaFurnitureTable::getState, bo.getState()); + lqw.eq(StringUtils.isNotBlank(bo.getProcurementOfProducts()), OaFurnitureTable::getProcurementOfProducts, bo.getProcurementOfProducts()); + lqw.eq(StringUtils.isNotBlank(bo.getContactGroup()), OaFurnitureTable::getContactGroup, bo.getContactGroup()); + lqw.eq(StringUtils.isNotBlank(bo.getPhone()), OaFurnitureTable::getPhone, bo.getPhone()); + lqw.eq(StringUtils.isNotBlank(bo.getFax()), OaFurnitureTable::getFax, bo.getFax()); + lqw.eq(StringUtils.isNotBlank(bo.getAddress()), OaFurnitureTable::getAddress, bo.getAddress()); + lqw.eq(StringUtils.isNotBlank(bo.getZip()), OaFurnitureTable::getZip, bo.getZip()); + lqw.eq(StringUtils.isNotBlank(bo.getEmail()), OaFurnitureTable::getEmail, bo.getEmail()); + lqw.eq(StringUtils.isNotBlank(bo.getWebsite()), OaFurnitureTable::getWebsite, bo.getWebsite()); + lqw.eq(bo.getEmailSendCount() != null, OaFurnitureTable::getEmailSendCount, bo.getEmailSendCount()); + lqw.eq(bo.getLastEmailSendTime() != null, OaFurnitureTable::getLastEmailSendTime, bo.getLastEmailSendTime()); + lqw.eq(StringUtils.isNotBlank(bo.getContactPerson()), OaFurnitureTable::getContactPerson, bo.getContactPerson()); + lqw.eq(bo.getReceiveCount() != null, OaFurnitureTable::getReceiveCount, bo.getReceiveCount()); + + // 优质筛选:只查询邮箱不为空的记录 + if (Boolean.TRUE.equals(bo.getQualityFilter())) { + lqw.isNotNull(OaFurnitureTable::getEmail); + lqw.ne(OaFurnitureTable::getEmail, ""); + } + + // 按邮件发送次数升序排序,发送次数少的靠前显示 + lqw.orderByAsc(OaFurnitureTable::getEmailSendCount); + return lqw; + } + + /** + * 新增家具 + */ + @Override + public Boolean insertByBo(OaFurnitureTableBo bo) { + OaFurnitureTable add = BeanUtil.toBean(bo, OaFurnitureTable.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setFurnitureId(add.getFurnitureId()); + } + return flag; + } + + /** + * 修改家具 + */ + @Override + public Boolean updateByBo(OaFurnitureTableBo bo) { + OaFurnitureTable update = BeanUtil.toBean(bo, OaFurnitureTable.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(OaFurnitureTable entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 批量删除家具 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteBatchIds(ids) > 0; + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/impl/SysOaArticleServiceImpl.java b/gear-oa/src/main/java/com/gear/oa/service/impl/SysOaArticleServiceImpl.java new file mode 100644 index 0000000..b9721bb --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/impl/SysOaArticleServiceImpl.java @@ -0,0 +1,134 @@ +package com.gear.oa.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gear.common.core.domain.PageQuery; +import com.gear.common.core.page.TableDataInfo; +import com.gear.common.utils.StringUtils; +import com.gear.oa.domain.SysOaArticle; +import com.gear.oa.domain.bo.SysOaArticleBo; +import com.gear.oa.domain.vo.SysOaArticleVo; +import com.gear.oa.mapper.SysOaArticleMapper; +import com.gear.oa.service.ISysOaArticleService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * 知识管理Service业务层处理 + * + * @author huangxing + * @date 2024-01-17 + */ +@RequiredArgsConstructor +@Service +public class SysOaArticleServiceImpl implements ISysOaArticleService { + + private final SysOaArticleMapper baseMapper; + + /** + * 查询知识管理 + */ + @Override + public SysOaArticle selectArticleById(Long articleId){ + SysOaArticle sysOaArticleInfo = baseMapper.selectArticleById(articleId); + //更新阅读数量 + SysOaArticleBo sysOaArticleBo = new SysOaArticleBo(); + sysOaArticleBo.setArticleId(articleId); + sysOaArticleBo.setCheckNum(sysOaArticleInfo.getCheckNum() + 1); + this.updateByBo(sysOaArticleBo); + + return sysOaArticleInfo; + } + + /** + * 查询知识管理列表 + */ + @Override + public TableDataInfo queryPageList(SysOaArticleBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + + /** + * 自定义-查询知识管理列表 + * @param bo + * @param pageQuery + * @return + */ + @Override + public TableDataInfo selectArticlePageList(SysOaArticleBo bo, PageQuery pageQuery){ + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page articlePageList = baseMapper.selectArticlePageList(pageQuery.build(), lqw); + return TableDataInfo.build(articlePageList); + + } + + + /** + * 查询知识管理列表 + */ + @Override + public List queryList(SysOaArticleBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(SysOaArticleBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(bo.getCategoryId() != null, SysOaArticle::getCategoryId, bo.getCategoryId()); + lqw.eq(StringUtils.isNotBlank(bo.getArticleTitle()), SysOaArticle::getArticleTitle, bo.getArticleTitle()); + lqw.orderByDesc(SysOaArticle::getCreateTime); + return lqw; + } + + /** + * 新增知识管理 + */ + @Override + public Boolean insertByBo(SysOaArticleBo bo) { + SysOaArticle add = BeanUtil.toBean(bo, SysOaArticle.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setArticleId(add.getArticleId()); + } + return flag; + } + + /** + * 修改知识管理 + */ + @Override + public Boolean updateByBo(SysOaArticleBo bo) { + SysOaArticle update = BeanUtil.toBean(bo, SysOaArticle.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(SysOaArticle entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 批量删除知识管理 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteBatchIds(ids) > 0; + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/service/impl/SysOaCategoryServiceImpl.java b/gear-oa/src/main/java/com/gear/oa/service/impl/SysOaCategoryServiceImpl.java new file mode 100644 index 0000000..14465b0 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/impl/SysOaCategoryServiceImpl.java @@ -0,0 +1,99 @@ +package com.gear.oa.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.gear.common.utils.StringUtils; +import com.gear.oa.domain.SysOaCategory; +import com.gear.oa.domain.bo.SysOaCategoryBo; +import com.gear.oa.domain.vo.SysOaCategoryVo; +import com.gear.oa.mapper.SysOaCategoryMapper; +import com.gear.oa.service.ISysOaCategoryService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * 知识分类Service业务层处理 + * + * @author huangxing + * @date 2024-01-17 + */ +@RequiredArgsConstructor +@Service +public class SysOaCategoryServiceImpl implements ISysOaCategoryService { + + private final SysOaCategoryMapper baseMapper; + + /** + * 查询知识分类 + */ + @Override + public SysOaCategoryVo queryById(Long categoryId){ + return baseMapper.selectVoById(categoryId); + } + + + /** + * 查询知识分类列表 + */ + @Override + public List queryList(SysOaCategoryBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(SysOaCategoryBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.like(StringUtils.isNotBlank(bo.getCategoryName()), SysOaCategory::getCategoryName, bo.getCategoryName()); + lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysOaCategory::getStatus, bo.getStatus()); + lqw.orderByDesc(SysOaCategory::getCreateTime); + return lqw; + } + + /** + * 新增知识分类 + */ + @Override + public Boolean insertByBo(SysOaCategoryBo bo) { + SysOaCategory add = BeanUtil.toBean(bo, SysOaCategory.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setCategoryId(add.getCategoryId()); + } + return flag; + } + + /** + * 修改知识分类 + */ + @Override + public Boolean updateByBo(SysOaCategoryBo bo) { + SysOaCategory update = BeanUtil.toBean(bo, SysOaCategory.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(SysOaCategory entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 批量删除知识分类 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteBatchIds(ids) > 0; + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/utils/EmailUtil.java b/gear-oa/src/main/java/com/gear/oa/utils/EmailUtil.java new file mode 100644 index 0000000..4426219 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/utils/EmailUtil.java @@ -0,0 +1,382 @@ +package com.gear.oa.utils; + +import com.gear.oa.config.DynamicMailConfig; +import com.gear.oa.domain.OaEmailAccount; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Component; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import java.io.File; +import java.util.List; + +/** + * 邮件发送工具类 + * + * @author ruoyi + */ +@Component +public class EmailUtil { + + @Autowired + private JavaMailSender javaMailSender; + + @Autowired + private DynamicMailConfig dynamicMailConfig; + + /** + * 发送纯文本邮件 + * + * @param from 发件人邮箱 + * @param to 收件人邮箱 + * @param subject 邮件主题 + * @param text 纯文本内容 + */ + public void sendMail(String from, String to, String subject, String text) { + SimpleMailMessage message = new SimpleMailMessage(); + message.setFrom(from); + message.setTo(to); + message.setSubject(subject); + message.setText(text); + javaMailSender.send(message); + } + + /** + * 使用动态配置发送纯文本邮件 + * + * @param account 邮箱账号信息 + * @param to 收件人邮箱 + * @param subject 邮件主题 + * @param text 纯文本内容 + */ + public void sendMailWithDynamicConfig(OaEmailAccount account, String to, String subject, String text) { + JavaMailSender dynamicMailSender = dynamicMailConfig.createMailSender(account); + SimpleMailMessage message = new SimpleMailMessage(); + message.setFrom(account.getEmail()); + message.setTo(to); + message.setSubject(subject); + message.setText(text); + dynamicMailSender.send(message); + } + + /** + * 发送纯文本邮件(批量) + * + * @param from 发件人邮箱 + * @param toList 收件人邮箱列表 + * @param subject 邮件主题 + * @param text 纯文本内容 + */ + public void sendMailBatch(String from, List toList, String subject, String text) { + SimpleMailMessage message = new SimpleMailMessage(); + message.setFrom(from); + message.setTo(toList.toArray(new String[0])); + message.setSubject(subject); + message.setText(text); + javaMailSender.send(message); + } + + /** + * 发送富文本邮件 + * + * @param from 发件人邮箱 + * @param to 收件人邮箱 + * @param subject 邮件主题 + * @param htmlContent HTML内容 + */ + public void sendHtmlMail(String from, String to, String subject, String htmlContent) throws MessagingException { + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(htmlContent, true); // 第二个参数true表示这是HTML内容 + javaMailSender.send(mimeMessage); + } + + /** + * 使用动态配置发送富文本邮件 + * + * @param account 邮箱账号信息 + * @param to 收件人邮箱 + * @param subject 邮件主题 + * @param htmlContent HTML内容 + */ + public void sendHtmlMailWithDynamicConfig(OaEmailAccount account, String to, String subject, String htmlContent) throws MessagingException { + JavaMailSender dynamicMailSender = dynamicMailConfig.createMailSender(account); + MimeMessage mimeMessage = dynamicMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); + helper.setFrom(account.getEmail()); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(htmlContent, true); + dynamicMailSender.send(mimeMessage); + } + + /** + * 发送富文本邮件(批量) + * + * @param from 发件人邮箱 + * @param toList 收件人邮箱列表 + * @param subject 邮件主题 + * @param htmlContent HTML内容 + */ + public void sendHtmlMailBatch(String from, List toList, String subject, String htmlContent) throws MessagingException { + for (String to : toList) { + sendHtmlMail(from, to, subject, htmlContent); + } + } + + /** + * 发送带附件的邮件 + * + * @param from 发件人邮箱 + * @param to 收件人邮箱 + * @param subject 邮件主题 + * @param text 邮件内容 + * @param filePath 附件文件路径 + */ + public void sendMailWithAttachment(String from, String to, String subject, String text, String filePath) throws MessagingException { + File attachment = new File(filePath); + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(text); + helper.addAttachment(attachment.getName(), attachment); + javaMailSender.send(mimeMessage); + } + + /** + * 使用动态配置发送带附件的邮件 + * + * @param account 邮箱账号信息 + * @param to 收件人邮箱 + * @param subject 邮件主题 + * @param text 邮件内容 + * @param filePath 附件文件路径 + */ + public void sendMailWithAttachmentAndDynamicConfig(OaEmailAccount account, String to, String subject, String text, String filePath) throws MessagingException { + JavaMailSender dynamicMailSender = dynamicMailConfig.createMailSender(account); + File attachment = new File(filePath); + MimeMessage mimeMessage = dynamicMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); + helper.setFrom(account.getEmail()); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(text); + helper.addAttachment(attachment.getName(), attachment); + dynamicMailSender.send(mimeMessage); + } + + /** + * 发送带附件的富文本邮件 + * + * @param from 发件人邮箱 + * @param to 收件人邮箱 + * @param subject 邮件主题 + * @param htmlContent HTML内容 + * @param filePath 附件文件路径 + */ + public void sendHtmlMailWithAttachment(String from, String to, String subject, String htmlContent, String filePath) throws MessagingException { + File attachment = new File(filePath); + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(htmlContent, true); + helper.addAttachment(attachment.getName(), attachment); + javaMailSender.send(mimeMessage); + } + + /** + * 使用动态配置发送带附件的富文本邮件 + * + * @param account 邮箱账号信息 + * @param to 收件人邮箱 + * @param subject 邮件主题 + * @param htmlContent HTML内容 + * @param filePath 附件文件路径 + */ + public void sendHtmlMailWithAttachmentAndDynamicConfig(OaEmailAccount account, String to, String subject, String htmlContent, String filePath) throws MessagingException { + JavaMailSender dynamicMailSender = dynamicMailConfig.createMailSender(account); + File attachment = new File(filePath); + MimeMessage mimeMessage = dynamicMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); + helper.setFrom(account.getEmail()); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(htmlContent, true); + helper.addAttachment(attachment.getName(), attachment); + dynamicMailSender.send(mimeMessage); + } + + /** + * 发送带多个附件的邮件 + * + * @param from 发件人邮箱 + * @param to 收件人邮箱 + * @param subject 邮件主题 + * @param htmlContent HTML内容 + * @param filePaths 附件文件路径列表 + */ + public void sendHtmlMailWithAttachments(String from, String to, String subject, String htmlContent, List filePaths) throws MessagingException { + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(htmlContent, true); + + for (String filePath : filePaths) { + File attachment = new File(filePath); + if (attachment.exists()) { + helper.addAttachment(attachment.getName(), attachment); + } + } + + javaMailSender.send(mimeMessage); + } + + /** + * 使用动态配置发送带多个附件的邮件 + * + * @param account 邮箱账号信息 + * @param to 收件人邮箱 + * @param subject 邮件主题 + * @param htmlContent HTML内容 + * @param filePaths 附件文件路径列表 + */ + public void sendHtmlMailWithAttachmentsAndDynamicConfig(OaEmailAccount account, String to, String subject, String htmlContent, List filePaths) throws MessagingException { + JavaMailSender dynamicMailSender = dynamicMailConfig.createMailSender(account); + MimeMessage mimeMessage = dynamicMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); + helper.setFrom(account.getEmail()); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(htmlContent, true); + + for (String filePath : filePaths) { + File attachment = new File(filePath); + if (attachment.exists()) { + helper.addAttachment(attachment.getName(), attachment); + } + } + + dynamicMailSender.send(mimeMessage); + } + + /** + * 发送带内嵌图片的邮件 + * + * @param from 发件人邮箱 + * @param to 收件人邮箱 + * @param subject 邮件主题 + * @param htmlContent HTML内容(包含cid:xxx的图片引用) + * @param imagePaths 内嵌图片路径列表 + */ + public void sendHtmlMailWithInlineImages(String from, String to, String subject, String htmlContent, List imagePaths) throws MessagingException { + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(htmlContent, true); + + for (int i = 0; i < imagePaths.size(); i++) { + String imagePath = imagePaths.get(i); + File imageFile = new File(imagePath); + if (imageFile.exists()) { + String cid = "image" + i; + helper.addInline(cid, imageFile); + } + } + + javaMailSender.send(mimeMessage); + } + + /** + * 使用动态配置发送带内嵌图片的邮件 + * + * @param account 邮箱账号信息 + * @param to 收件人邮箱 + * @param subject 邮件主题 + * @param htmlContent HTML内容(包含cid:xxx的图片引用) + * @param imagePaths 内嵌图片路径列表 + */ + public void sendHtmlMailWithInlineImagesAndDynamicConfig(OaEmailAccount account, String to, String subject, String htmlContent, List imagePaths) throws MessagingException { + JavaMailSender dynamicMailSender = dynamicMailConfig.createMailSender(account); + MimeMessage mimeMessage = dynamicMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); + helper.setFrom(account.getEmail()); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(htmlContent, true); + + for (int i = 0; i < imagePaths.size(); i++) { + String imagePath = imagePaths.get(i); + File imageFile = new File(imagePath); + if (imageFile.exists()) { + String cid = "image" + i; + helper.addInline(cid, imageFile); + } + } + + dynamicMailSender.send(mimeMessage); + } + + /** + * 处理HTML内容中的图片,将外链图片转为内嵌 + * + * @param htmlContent 原始HTML内容 + * @param imagePaths 图片路径列表 + * @return 处理后的HTML内容 + */ + public String processHtmlWithInlineImages(String htmlContent, List imagePaths) { + if (imagePaths == null || imagePaths.isEmpty()) { + return htmlContent; + } + + String processedHtml = htmlContent; + for (int i = 0; i < imagePaths.size(); i++) { + String imagePath = imagePaths.get(i); + String cid = "image" + i; + // 这里可以根据需要替换图片URL为cid引用 + // 例如:将 替换为 + processedHtml = processedHtml.replace("image" + i + ".jpg", "cid:" + cid); + processedHtml = processedHtml.replace("image" + i + ".png", "cid:" + cid); + } + + return processedHtml; + } + + /** + * 下载网络文件到本地临时文件,保留原始文件后缀 + * @param url 文件的http/https链接 + * @return 本地临时文件 + */ + public static File downloadUrlToTempFile(String url) throws Exception { + // 提取文件名和后缀 + String fileName = url.substring(url.lastIndexOf('/') + 1); + String suffix = ""; + int dotIdx = fileName.lastIndexOf('.'); + if (dotIdx != -1) { + suffix = fileName.substring(dotIdx); + } + File tempFile = File.createTempFile("mail_attach_", suffix); + try (java.io.InputStream in = new java.net.URL(url).openStream(); + java.io.OutputStream out = new java.io.FileOutputStream(tempFile)) { + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = in.read(buffer)) != -1) { + out.write(buffer, 0, bytesRead); + } + } + return tempFile; + } +} diff --git a/gear-oa/src/main/resources/mapper/oa/OaEmailAccountMapper.xml b/gear-oa/src/main/resources/mapper/oa/OaEmailAccountMapper.xml new file mode 100644 index 0000000..08f23a7 --- /dev/null +++ b/gear-oa/src/main/resources/mapper/oa/OaEmailAccountMapper.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gear-oa/src/main/resources/mapper/oa/OaEmailTemplateMapper.xml b/gear-oa/src/main/resources/mapper/oa/OaEmailTemplateMapper.xml new file mode 100644 index 0000000..3774229 --- /dev/null +++ b/gear-oa/src/main/resources/mapper/oa/OaEmailTemplateMapper.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/gear-oa/src/main/resources/mapper/oa/OaFurnitureTableMapper.xml b/gear-oa/src/main/resources/mapper/oa/OaFurnitureTableMapper.xml new file mode 100644 index 0000000..fd9f50a --- /dev/null +++ b/gear-oa/src/main/resources/mapper/oa/OaFurnitureTableMapper.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + UPDATE oa_furniture_table + SET email_send_count = IFNULL(email_send_count,0) + 1, + last_email_send_time = NOW() + WHERE furniture_id = #{furnitureId} + + + + + diff --git a/gear-oa/src/main/resources/mapper/oa/SysOaArticleMapper.xml b/gear-oa/src/main/resources/mapper/oa/SysOaArticleMapper.xml new file mode 100644 index 0000000..1a73a59 --- /dev/null +++ b/gear-oa/src/main/resources/mapper/oa/SysOaArticleMapper.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select a.article_id, + a.category_id, + a.article_title, + a.subhead, + a.source, + a.content, + a.check_num, + a.accessory, + a.remark, + a.create_by, + a.create_time, + a.update_by, + a.update_time, + c.category_id, + c.category_name + from sys_oa_article a + left join sys_oa_category c on a.category_id = c.category_id + + + + + + + + diff --git a/gear-oa/src/main/resources/mapper/oa/SysOaCategoryMapper.xml b/gear-oa/src/main/resources/mapper/oa/SysOaCategoryMapper.xml new file mode 100644 index 0000000..625e4a6 --- /dev/null +++ b/gear-oa/src/main/resources/mapper/oa/SysOaCategoryMapper.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/gear-ui3/package.json b/gear-ui3/package.json index 2981a92..78f99d1 100644 --- a/gear-ui3/package.json +++ b/gear-ui3/package.json @@ -37,6 +37,7 @@ "vue": "3.5.16", "vue-cropper": "1.1.1", "vue-router": "4.5.1", + "vue3-treeselect": "^0.1.10", "vuedraggable": "4.1.0" }, "devDependencies": { diff --git a/gear-ui3/src/api/oa/article.js b/gear-ui3/src/api/oa/article.js new file mode 100644 index 0000000..3ca63c6 --- /dev/null +++ b/gear-ui3/src/api/oa/article.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询知识管理列表 +export function listArticle(query) { + return request({ + url: '/oa/article/listArticle', + method: 'get', + params: query + }) +} + +// 查询知识管理详细 +export function getArticle(articleId) { + return request({ + url: '/oa/article/' + articleId, + method: 'get' + }) +} + +// 新增知识管理 +export function addArticle(data) { + return request({ + url: '/oa/article', + method: 'post', + data: data + }) +} + +// 修改知识管理 +export function updateArticle(data) { + return request({ + url: '/oa/article', + method: 'put', + data: data + }) +} + +// 删除知识管理 +export function delArticle(articleId) { + return request({ + url: '/oa/article/' + articleId, + method: 'delete' + }) +} diff --git a/gear-ui3/src/api/oa/category.js b/gear-ui3/src/api/oa/category.js new file mode 100644 index 0000000..9d39be2 --- /dev/null +++ b/gear-ui3/src/api/oa/category.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询知识分类列表 +export function listCategory(query) { + return request({ + url: '/oa/category/list', + method: 'get', + params: query + }) +} + +// 查询知识分类详细 +export function getCategory(categoryId) { + return request({ + url: '/oa/category/' + categoryId, + method: 'get' + }) +} + +// 新增知识分类 +export function addCategory(data) { + return request({ + url: '/oa/category', + method: 'post', + data: data + }) +} + +// 修改知识分类 +export function updateCategory(data) { + return request({ + url: '/oa/category', + method: 'put', + data: data + }) +} + +// 删除知识分类 +export function delCategory(categoryId) { + return request({ + url: '/oa/category/' + categoryId, + method: 'delete' + }) +} diff --git a/gear-ui3/src/api/oa/contact.js b/gear-ui3/src/api/oa/contact.js new file mode 100644 index 0000000..c2e4498 --- /dev/null +++ b/gear-ui3/src/api/oa/contact.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询家具列表 +export function listFurnitureTable(query) { + return request({ + url: '/oa/furnitureTable/list', + method: 'get', + params: query + }) +} + +// 查询家具详细 +export function getFurnitureTable(furnitureId) { + return request({ + url: '/oa/furnitureTable/' + furnitureId, + method: 'get' + }) +} + +// 新增家具 +export function addFurnitureTable(data) { + return request({ + url: '/oa/furnitureTable', + method: 'post', + data: data + }) +} + +// 修改家具 +export function updateFurnitureTable(data) { + return request({ + url: '/oa/furnitureTable', + method: 'put', + data: data + }) +} + +// 删除家具 +export function delFurnitureTable(furnitureId) { + return request({ + url: '/oa/furnitureTable/' + furnitureId, + method: 'delete' + }) +} diff --git a/gear-ui3/src/api/oa/emailAccount.js b/gear-ui3/src/api/oa/emailAccount.js new file mode 100644 index 0000000..04a7712 --- /dev/null +++ b/gear-ui3/src/api/oa/emailAccount.js @@ -0,0 +1,53 @@ +import request from '@/utils/request' + +// 查询发件人邮箱账号管理列表 +export function listEmailAccount(query) { + return request({ + url: '/oa/emailAccount/list', + method: 'get', + params: query + }) +} + +// 查询发件人邮箱账号管理详细 +export function getEmailAccount(emailId) { + return request({ + url: '/oa/emailAccount/' + emailId, + method: 'get' + }) +} + +// 新增发件人邮箱账号管理 +export function addEmailAccount(data) { + return request({ + url: '/oa/emailAccount', + method: 'post', + data: data + }) +} + +// 修改发件人邮箱账号管理 +export function updateEmailAccount(data) { + return request({ + url: '/oa/emailAccount', + method: 'put', + data: data + }) +} + +// 删除发件人邮箱账号管理 +export function delEmailAccount(emailId) { + return request({ + url: '/oa/emailAccount/' + emailId, + method: 'delete' + }) +} + +// 发送邮件(单条和批量共用) +export function sendEmail(data) { + return request({ + url: '/oa/emailAccount/sendBatchEmail', + method: 'post', + data + }) +} diff --git a/gear-ui3/src/api/oa/emailTemplate.js b/gear-ui3/src/api/oa/emailTemplate.js new file mode 100644 index 0000000..fbd53e4 --- /dev/null +++ b/gear-ui3/src/api/oa/emailTemplate.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询邮件模板列表 +export function listEmailTemplate(query) { + return request({ + url: '/oa/emailTemplate/list', + method: 'get', + params: query + }) +} + +// 查询邮件模板详细 +export function getEmailTemplate(id) { + return request({ + url: '/oa/emailTemplate/' + id, + method: 'get' + }) +} + +// 新增邮件模板 +export function addEmailTemplate(data) { + return request({ + url: '/oa/emailTemplate', + method: 'post', + data: data + }) +} + +// 修改邮件模板 +export function updateEmailTemplate(data) { + return request({ + url: '/oa/emailTemplate', + method: 'put', + data: data + }) +} + +// 删除邮件模板 +export function delEmailTemplate(id) { + return request({ + url: '/oa/emailTemplate/' + id, + method: 'delete' + }) +} diff --git a/gear-ui3/src/views/sale/article/components/ArticlePreview.vue b/gear-ui3/src/views/sale/article/components/ArticlePreview.vue new file mode 100644 index 0000000..c27428d --- /dev/null +++ b/gear-ui3/src/views/sale/article/components/ArticlePreview.vue @@ -0,0 +1,347 @@ + + + + + diff --git a/gear-ui3/src/views/sale/article/index.vue b/gear-ui3/src/views/sale/article/index.vue new file mode 100644 index 0000000..950fa23 --- /dev/null +++ b/gear-ui3/src/views/sale/article/index.vue @@ -0,0 +1,519 @@ + + + + + diff --git a/gear-ui3/src/views/sale/contact/index.vue b/gear-ui3/src/views/sale/contact/index.vue new file mode 100644 index 0000000..76c270b --- /dev/null +++ b/gear-ui3/src/views/sale/contact/index.vue @@ -0,0 +1,1139 @@ + + + + + + diff --git a/gear-ui3/src/views/sale/contact/templates/business.js b/gear-ui3/src/views/sale/contact/templates/business.js new file mode 100644 index 0000000..433edaf --- /dev/null +++ b/gear-ui3/src/views/sale/contact/templates/business.js @@ -0,0 +1,32 @@ +/** + * 商务邮件模板 + * 适用于商务合作、客户沟通等场景 + */ +export const businessTemplate = { + name: "商务模板", + description: "专业的商务合作邮件模板,适合客户沟通和商务洽谈", + category: "business", + html: ` + + + + + + + +
+

商务合作

+

Professional Business Communication

+
+
+

+ 尊敬的客户 +

+
+
+
+
+ ` +}; + +export default businessTemplate; \ No newline at end of file diff --git a/gear-ui3/src/views/sale/contact/templates/index.js b/gear-ui3/src/views/sale/contact/templates/index.js new file mode 100644 index 0000000..c9ec006 --- /dev/null +++ b/gear-ui3/src/views/sale/contact/templates/index.js @@ -0,0 +1,32 @@ +/** + * 邮件模板索引文件 + * 统一管理所有邮件模板 + */ +import { businessTemplate } from './business.js'; +import { marketingTemplate } from './marketing.js'; +import { notificationTemplate } from './notification.js'; +import { productTemplate } from './product.js'; + +// 所有模板集合 +export const emailTemplates = { + business: businessTemplate, + product: productTemplate, + marketing: marketingTemplate, + notification: notificationTemplate +}; + +// 根据模板键获取模板 +export function getTemplate(templateKey) { + return emailTemplates[templateKey] || null; +} + +// 获取所有模板 +export function getAllTemplates() { + return emailTemplates; +} + +export default { + emailTemplates, + getTemplate, + getAllTemplates +}; \ No newline at end of file diff --git a/gear-ui3/src/views/sale/contact/templates/marketing.js b/gear-ui3/src/views/sale/contact/templates/marketing.js new file mode 100644 index 0000000..a561e2c --- /dev/null +++ b/gear-ui3/src/views/sale/contact/templates/marketing.js @@ -0,0 +1,103 @@ +/** + * 营销邮件模板 + * 适用于产品推广、活动宣传等营销场景 + */ +export const marketingTemplate = { + name: "营销推广模板", + description: "专业的营销推广邮件模板,适合产品推广和活动宣传", + category: "marketing", + html: ` + + + + + + + + + + +
+

限时优惠

+

Special Offer

+
+ +
+

+ 🎉 特别优惠活动 +

+ + + + +
+

限时折扣

+

全场商品 8折优惠

+

活动时间:2024年1月1日 - 2024年1月31日

+
+
+ + +
+

🔥 热门推荐

+ + + + + +
+ + + + +
+
🏠
+

精品家具

+

现代简约风格,品质保证

+
+ 原价 ¥2999 现价 ¥2399 +
+
+
+ + + + +
+
🛋️
+

办公用品

+

专业办公环境解决方案

+
+ 原价 ¥1999 现价 ¥1599 +
+
+
+
+ + +
+ + + + +
+ + 🛒 立即购买 + +
+
+ + + + + + +
+

📧 详细信息

+
+ +
+
+
+ ` +}; \ No newline at end of file diff --git a/gear-ui3/src/views/sale/contact/templates/notification.js b/gear-ui3/src/views/sale/contact/templates/notification.js new file mode 100644 index 0000000..89a247c --- /dev/null +++ b/gear-ui3/src/views/sale/contact/templates/notification.js @@ -0,0 +1,82 @@ +/** + * 通知邮件模板 + * 适用于系统通知、状态更新等场景 + */ +export const notificationTemplate = { + name: "系统通知模板", + description: "简洁专业的系统通知邮件模板,适合状态更新和重要通知", + category: "notification", + html: ` + + + + + + + + + + +
+

系统通知

+

System Notification

+
+ +
+
📢
+
+ + +
+

+ 重要通知 +

+

+ 请仔细阅读以下内容 +

+
+ + + + + + +
+
+

+ 📋 通知详情 +

+
+ +
+
+
+ + + + + + +
+

⚠️ 重要提醒

+
    +
  • 请及时处理相关事项
  • +
  • 如有疑问请联系客服
  • +
  • 感谢您的配合与支持
  • +
+
+ + + + + + +
+

📞 联系我们

+

+ 客服电话:400-123-4567 | 邮箱:support@company.com +

+
+
+ ` +}; \ No newline at end of file diff --git a/gear-ui3/src/views/sale/contact/templates/product.js b/gear-ui3/src/views/sale/contact/templates/product.js new file mode 100644 index 0000000..89c7df2 --- /dev/null +++ b/gear-ui3/src/views/sale/contact/templates/product.js @@ -0,0 +1,94 @@ +/** + * 产品介绍邮件模板 + * 适用于产品展示、新品发布等场景 + */ +export const productTemplate = { + name: "产品介绍模板", + description: "现代化的产品展示邮件模板,适合产品介绍和新品发布", + category: "product", + html: ` + + + + + + + + + + +
+

产品展示

+

Product Showcase

+
+ +
+

+ 🚀 产品特色 +

+ + + + +
+

✨ 核心优势

+
    +
  • 高质量材料,确保产品耐用性
  • +
  • 创新设计,满足现代审美需求
  • +
  • 环保认证,符合国际标准
  • +
  • 专业服务,全程技术支持
  • +
+
+ + + + + + +
+

📧 详细信息

+
+ +
+
+
+ + + + + + +
+

📸 产品展示

+ + + + + +
+ + + + +
+
🏠
+

家居系列

+

现代简约风格

+
+
+ + + + +
+
🛋️
+

办公系列

+

专业办公环境

+
+
+
+
+ ` +}; + +export default productTemplate; \ No newline at end of file diff --git a/gear-ui3/src/views/sale/email/index.vue b/gear-ui3/src/views/sale/email/index.vue new file mode 100644 index 0000000..b485d55 --- /dev/null +++ b/gear-ui3/src/views/sale/email/index.vue @@ -0,0 +1,483 @@ + + + diff --git a/gear-ui3/src/views/sale/template/index.vue b/gear-ui3/src/views/sale/template/index.vue new file mode 100644 index 0000000..ac982fa --- /dev/null +++ b/gear-ui3/src/views/sale/template/index.vue @@ -0,0 +1,418 @@ + + + + +