Compare commits

...

381 Commits

Author SHA1 Message Date
zhuoda
63ef235b95 v3.28.0 【优化】优化 Long、BigInteger、BigDecimal 的 JSON 序列化【优化】个人中心样式【优化】Spin加载 2025-08-24 23:05:00 +08:00
1024创新实验室
3ceea05ba1
!90 perf(json): 优化 Long、BigInteger、BigDecimal 的 JSON 序列化
Merge pull request !90 from CoderKK/feat-json
2025-08-24 12:47:54 +00:00
CoderKK
9fda0a7bd6 perf(json): 优化 Long、BigInteger、BigDecimal 的 JSON 序列化
- 为 Long、BigInteger 和 BigDecimal 类型添加自定义序列化器
- 超出 JavaScript 安全整数范围的 Long 值将被序列化为字符串
- BigInteger 和 BigDecimal值将始终被序列化为字符串
2025-08-20 16:04:18 +08:00
zhuoda
9361097097 v3.27.0 【优化】员工缓存;【优化】代码生成;【优化】redis缓存失效时间 2025-08-18 21:07:32 +08:00
zhuoda
942c628cc6 v3.27.0 【优化】员工缓存;【优化】代码生成;【优化】redis缓存失效时间 2025-08-18 20:49:07 +08:00
zhuoda
521b98746f v3.27.0 【优化】员工缓存;【优化】代码生成;【优化】redis缓存失效时间 2025-08-18 20:22:44 +08:00
zhuoda
4229ec80b0 v3.27.0 【优化】员工缓存;【优化】代码生成;【优化】redis缓存失效时间 2025-08-18 20:21:02 +08:00
zhuoda
4582656e27 v3.27.0 【优化】员工缓存;【优化】代码生成;【优化】redis缓存失效时间 2025-08-18 20:18:23 +08:00
zhuoda
fff0120058 v3.27.0 【优化】员工缓存;【优化】代码生成;【优化】redis缓存失效时间 2025-08-18 20:15:03 +08:00
1024创新实验室
b8f2200af6
!88 update smart-admin-web-javascript/src/views/system/home/index.vue.
Merge pull request !88 from 192890/N/A
2025-08-18 11:43:33 +00:00
1024创新实验室
0a56497b51
!89 feat(cache): 实现自定义 Spring Cache 缓存管理器支持 TTL- 新增 CustomRedisCacheManage…
Merge pull request !89 from CoderKK/feat-cache
2025-08-18 11:43:25 +00:00
CoderKK
2eb3742063 feat(cache): 实现自定义 Spring Cache 缓存管理器支持 TTL- 新增 CustomRedisCacheManager 类,用于解析 cacheName 中的 TTL 设置
- 修改 CacheConfig,使用新的自定义缓存管理器
- 更新 RedisCacheServiceImpl,使用 StandardCharsets.UTF_8 替代 魔法值"utf-8"
2025-08-15 13:45:36 +08:00
192890
74aa2da89b
update smart-admin-web-javascript/src/views/system/home/index.vue.
修改内容:订正“待办”、“更新日志”的位置

Signed-off-by: 192890 <zhang4342@163.com>
2025-08-12 06:31:49 +00:00
1024创新实验室
3dcad0b78a
!87 refactor(sql): 修改 smart_admin_v3.sql 中 response 字段的注释
Merge pull request !87 from CoderKK/fix
2025-08-11 10:59:53 +00:00
CoderKK
6ba6b18849 refactor(sql): 修改 smart_admin_v3.sql 中 response 字段的注释
- 将 `response` 字段的注释从 "请求参数" 修改为 "返回值"
2025-08-11 09:48:10 +08:00
zhuoda
d2c55e35ff v3.26.0 【优化】分页请求2次;【优化】菜单展开单个代码优化;【优化】操作记录返回结果;【优化】json viewer升级;【优化】S3协议优化;【优化】代码生成字典优化; 2025-08-10 13:02:01 +08:00
zhuoda
8135e0ec10 v3.25.0【优化】密码加密随机盐;【优化】java依赖版本;【优化】后端依赖库;【优化】单号生成器;【优化】防重复提交;【优化】sa-base.yaml健康检查邮箱;【新增】前端夜间模式;【优化】标签页issue;【优化】字典int回显bug 2025-08-05 21:00:12 +08:00
zhuoda
2a545117fa v3.25.0【优化】密码加密随机盐;【优化】java依赖版本;【优化】后端依赖库;【优化】单号生成器;【优化】防重复提交;【优化】sa-base.yaml健康检查邮箱;【新增】前端夜间模式;【优化】标签页issue;【优化】字典int回显bug 2025-08-05 20:46:21 +08:00
zhuoda
d8baf9dba7 v3.25.0【优化】密码加密随机盐;【优化】java依赖版本;【优化】后端依赖库;【优化】单号生成器;【优化】防重复提交;【优化】sa-base.yaml健康检查邮箱;【新增】前端夜间模式;【优化】标签页issue;【优化】字典int回显bug 2025-08-05 20:44:51 +08:00
zhuoda
2f8a0b6153 v3.25.0【优化】密码加密随机盐;【优化】java依赖版本;【优化】后端依赖库;【优化】单号生成器;【优化】防重复提交;【优化】sa-base.yaml健康检查邮箱;【新增】前端夜间模式;【优化】标签页issue;【优化】字典int回显bug 2025-08-05 20:15:40 +08:00
zhuoda
a97afd4683 v3.25.0【优化】密码加密随机盐;【优化】java依赖版本;【优化】后端依赖库;【优化】单号生成器;【优化】防重复提交;【优化】sa-base.yaml健康检查邮箱;【新增】前端夜间模式;【优化】标签页issue;【优化】字典int回显bug 2025-08-05 20:12:40 +08:00
zhuoda
075e7ad134 v3.25.0【优化】密码加密随机盐;【优化】java依赖版本;【优化】后端依赖库;【优化】单号生成器;【优化】防重复提交;【优化】sa-base.yaml健康检查邮箱;【新增】前端夜间模式;【优化】标签页issue;【优化】字典int回显bug 2025-08-05 20:10:13 +08:00
Turbolisten
acecebf4b3
!84 style(sa-base): 删除 SecurityLoginService 类中多余的分号,修正错别字“登陆”->;“登录”
Merge pull request !84 from CoderKK/master
2025-08-01 09:46:59 +00:00
CoderKK
73cd7f196c refactor(sa-base): 将 Java原生的 UUID 生成方式替换为性能更好 Hutool 库的 IdUtil.fastSimpleUUID() 2025-08-01 17:38:28 +08:00
CoderKK
d3ef935859 style(sa-base): 删除 SecurityLoginService 类中多余的分号,修正错别字“登陆”->“登录” 2025-08-01 16:04:28 +08:00
zhuoda
97df843072 v3.24.0【优化】SM4依赖优化;【优化】前端样式 2025-07-10 23:30:00 +08:00
1024创新实验室
12bd821770
!83 fix:修复代码生成功能中非空字段取值问题(取值取反了)
Merge pull request !83 from hchvhg/dev
2025-07-10 15:05:51 +00:00
hchvhg
2b6ead23bd fix:修复代码生成功能中非空字段取值问题(取值取反了) 2025-06-23 16:16:06 +08:00
hchvhg
b2aa70ce9e 暂时恢复代码 2025-06-23 16:14:02 +08:00
hchvhg
143a500c44 fix:修复代码生成功能非空字段取值问题(取值取反了) 2025-06-23 16:04:53 +08:00
hchvhg
8302ba4c2c 处理DictDataVO类报错问题 2025-06-23 15:42:48 +08:00
zhuoda
7ae4e898ad v3.23.0 【新增】TS代码生成和优化;【优化】log日志格式;【优化】数据字典缓存;【优化】职位表结构 2025-06-19 20:36:30 +08:00
1024创新实验室
245f8c7856
!77 处理商品管理导出功能:导出失败报错问题
Merge pull request !77 from hchvhg/master
2025-06-19 12:07:56 +00:00
1024创新实验室
43a9f53c0a
!78 FIX:#ICBNYK 点击代码配置,会发送多次获取字典请求
Merge pull request !78 from 一点点/master
2025-06-19 12:07:46 +00:00
1024创新实验室
551c9c9086
!79 feat(sa-admin): 优化日志格式及颜色
Merge pull request !79 from CoderKK/master
2025-06-19 12:07:36 +00:00
1024创新实验室
28d188251b
!81 优化通知公告表单 选择部门 部门名称不显示
Merge pull request !81 from Cool7Smile/N/A
2025-06-19 12:07:26 +00:00
1024创新实验室
87210fad28
!80 优化通知公告表单 选择员工部门名称不显示
Merge pull request !80 from Cool7Smile/N/A
2025-06-19 12:07:16 +00:00
Cool7Smile
4f0296ce23
优化通知公告表单 选择部门 部门名称不显示
Signed-off-by: Cool7Smile <331636030@qq.com>
2025-06-13 07:55:43 +00:00
Cool7Smile
563b20206b
优化通知公告表单 选择员工部门名称不显示
Signed-off-by: Cool7Smile <331636030@qq.com>
2025-06-13 07:51:43 +00:00
CoderKK
c1373ed21d feat(sa-admin): 优化日志格式及颜色
- 在 Console Appender 中添加了新的 PatternLayout 设置
- 使用蓝色显示时间戳,高亮显示日志级别,青色显示类名
- 保留 ANSI 颜色代码,提高日志可读性
2025-06-11 18:29:44 +08:00
一点点
8f6852673a FIX:#ICBNYK 点击代码配置,会发送多次获取字典请求
bug: 点击代码配置,会发送多次获取字典请求
https://gitee.com/lab1024/smart-admin/issues/ICBNYK
2025-05-30 17:45:26 +08:00
hchvhg
336bdc4895 处理商品管理导出功能:导出失败报错问题
报错信息:org.springframework.data.redis.serializer.SerializationException: Cannot deserialize
处理方式:DictDataVO实现了Serializable接口
2025-05-30 17:20:59 +08:00
zhuoda
922e49b27e v3.22.0 【新增】优化代码生成;【新增】优化角色列宽 2025-05-27 20:00:22 +08:00
1024创新实验室
3adb7376dd
!75 角色列表名字过长
Merge pull request !75 from wdy/master
2025-05-23 08:22:00 +00:00
1024创新实验室
40880b87c1
!76 build: 移除未使用的依赖项
Merge pull request !76 from CoderKK/master
2025-05-23 08:21:51 +00:00
CoderKK
a260368d0c build: 移除未使用的依赖项
- 从 sa-base/pom.xml 中移除了 commons-pool2、jjwt 和 jwks-rsa 依赖
- 从根 pom.xml 中移除了 jjwt 和 jwks-rsa 的版本定义
2025-05-20 11:33:00 +08:00
wdy
e7d29c68ae
!1 角色列表名字过长
Merge pull request !1 from wdy/N/A
2025-05-20 02:08:20 +00:00
wdy
c0dea0c3c6
角色列表名字过长,导致右边页面换行显示
Signed-off-by: wdy <350456985@163.com>
2025-05-20 02:07:48 +00:00
zhuoda
4d2be37e0e v3.21.0 【新增】修改部门名称字段;【新增】修改系统版本version字段;【新增】优化代码生成前端代码;【优化】SQL 2025-05-13 20:06:41 +08:00
zhuoda
d5abf42014 Merge branch 'master' of https://gitee.com/lab1024/smart-admin 2025-05-13 20:04:29 +08:00
zhuoda
8d2d8f2846 v3.21.0 【新增】修改部门名称字段;【新增】修改系统版本version字段;【新增】优化代码生成前端代码;【优化】SQL 2025-05-13 20:04:12 +08:00
1024创新实验室
0e06f36787
!74 【修复】数据变更记录getChangeContent解析列表返回空
Merge pull request !74 from 憨涛子/master
2025-05-10 15:28:19 +00:00
SillyBoy
012096a3ee 【修复】数据变更记录getChangeContent解析列表返回空 2025-05-10 10:43:33 +08:00
zhuoda
3fb4dfad09 v3.20.0 【新增】优化登录使用spring cache;【新增】优化部门cache;【新增】代码生成枚举;【优化】三级等保Label显示宽度 2025-05-03 21:31:28 +08:00
1024创新实验室
f198a949c9
!71 Fix: 修复三级等保配置页面部分Label被遮盖问题,优化 OA 模块代码结构
Merge pull request !71 from Engineer/master
2025-05-01 15:30:37 +00:00
钟家兴
41fad5b831 feat(sa-base): 实现主从数据源动态切换
- 新增 DataSource 注解用于切换数据源
- 实现 DynamicDataSourceHandler 动态数据源处理器
- 添加 DruidConfig 配置多数据源
- 更新 sa-base.yaml 配置文件,支持主从数据源
2025-05-01 23:26:22 +08:00
钟家兴
696db3835a fix(smart-admin-web-typescript): 三级等保配置页面部分Label被遮盖问题 2025-05-01 01:18:19 +08:00
钟家兴
40edf452ac fix(smart-admin-web-javascript): 三级等保配置页面部分Label被遮盖问题 2025-05-01 01:15:03 +08:00
钟家兴
c93616bec2 refactor(oa): 优化 OA 模块代码结构 Java8版本
- 银行相关代码:将 BankController、BankDao、BankService移至合适的包结构
- 数据范围控制器:将 DataScopeController移至 controller 包
- 企业相关代码:将 EnterpriseController、EnterpriseEmployeeManager、EnterpriseService 移至合适的包结构
- 发票相关代码:将 InvoiceController、InvoiceDao、InvoiceService 移至合适的包结构
- 更新相关 XML映射文件的命名空间
2025-05-01 00:20:05 +08:00
钟家兴
61c49b5798 refactor(oa): 优化 OA 模块代码结构
- 银行管理:将 BankController、BankDao、BankService 移至各自独立的包中
- 数据范围:将 DataScopeController移至独立包中
- 企业信息:将 EnterpriseController、EnterpriseEmployeeManager、EnterpriseService 移至各自独立的包中
- 发票管理:将 InvoiceController、InvoiceDao、InvoiceService 移至各自独立的包中
- 更新相关 XML 文件中的命名空间
2025-05-01 00:17:08 +08:00
1024创新实验室
54ad0e5893
!68 refactor(sa-base): 修正邮件服务类中的注释
Merge pull request !68 from Engineer/master
2025-04-27 07:29:55 +00:00
1024创新实验室
fa5b5c7def
!67 优化代码生成模块的前端枚举
Merge pull request !67 from 大熊/code-generator
2025-04-27 07:29:28 +00:00
1024创新实验室
57270a7130
!66 在goods-list.vue页面销毁时移除 resize 事件监听器
Merge pull request !66 from luoyangxin/master
2025-04-27 07:29:12 +00:00
zhuoda
6c4cf9cc34 v3.19.1 ts引入错误 2025-04-27 15:13:20 +08:00
钟家兴
c49c1bbbfe refactor(sa-base): 修正邮件服务类中的注释
- 将"发生邮件"修改为"发送邮件",纠正了拼写错误
- 优化了代码注释的准确性,提高了代码可读性
2025-04-26 23:54:49 +08:00
钟家兴
47d41f0379 refactor(sa-base): 修正邮件服务类文档错别字
- 将"发生邮件"修改为"发送邮件",纠正了文档中的错别字
- 优化了代码注释,提高了代码可读性
2025-04-26 23:53:19 +08:00
zhoumingfa
3c3e3b4e32 优化代码生成模块的前端枚举 2025-04-18 16:49:14 +08:00
luoyangxin
7bad13fc23
在goods-list.vue页面销毁时移除 resize 事件监听器
Signed-off-by: luoyangxin <835168276@qq.com>
2025-04-14 02:23:17 +00:00
zhuoda
51caeb1ad1 v3.19.0 【新增】启动时邮箱测试连接关闭;【新增】默认菜单打开互斥;【新增】默认不显示帮助文档 2025-04-14 09:45:09 +08:00
zhuoda
f127f02c96 v3.18.0 【新增】新增消息管理;【新增】完善企业demo;【新增】完善相关数据权限;【新增】菜单管理下级功能 2025-04-10 21:30:13 +08:00
zhuoda
6583f5f90d v3.18.0 【新增】新增消息管理;【新增】完善企业demo;【新增】完善相关数据权限;【新增】菜单管理下级功能 2025-04-10 21:27:09 +08:00
1024创新实验室
d6a53f03b7
v3.18.0 【新增】新增消息管理;【新增】完善企业demo;【新增】完善相关数据权限;【新增】菜单管理下级功能 2025-04-10 13:22:28 +00:00
zhuoda
caf8e3aa25 v3.18.0 【新增】新增消息管理;【新增】完善企业demo;【新增】完善相关数据权限;【新增】菜单管理下级功能 2025-04-10 21:21:37 +08:00
zhoumingfa
97cfdf1f57 完善企业管理demo 2025-04-08 22:00:30 +08:00
zhoumingfa
8bb9f173eb 完善数据字典管理,更新相应的权限字符串 2025-04-08 20:28:59 +08:00
zhuoda
7ea97f8433 v3.17.0 【新增】新增菜单展开1个配置;【新增】移除表格固定高度;【新增】App登录token模式 2025-04-08 20:19:41 +08:00
zhoumingfa
e7927bb948 更正前端权限插件的判断 2025-04-08 19:52:47 +08:00
zhoumingfa
79fc04d8cb 菜单管理新增添加下级功能 2025-04-08 19:52:07 +08:00
zhoumingfa
393cb325c7 解决代码生成的查询条件列表拖拽报错问题 2025-04-08 17:30:20 +08:00
1024创新实验室
33c93ae365
v3.16.0 【新增】优化代码生成 字典和文件预览;【新增】代码生成 菜单SQL;【新增】登录页面GIF炫酷图片;
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2025-04-06 14:15:37 +00:00
1024创新实验室
3c2c3cf81b
v3.16.0 【新增】优化代码生成 字典和文件预览;【新增】代码生成 菜单SQL;【新增】登录页面GIF炫酷图片;
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2025-04-06 13:01:35 +00:00
zhuoda
ec8fb1d69d v3.16.0 【新增】优化代码生成 字典和文件预览;【新增】代码生成 菜单SQL;【新增】登录页面GIF炫酷图片 2025-04-06 20:59:16 +08:00
zhuoda
d4f1806491 v3.16.0 【新增】优化代码生成 字典和文件预览;【新增】代码生成 菜单SQL;【新增】登录页面GIF炫酷图片; 2025-04-06 20:28:10 +08:00
zhuoda
ce0551696a v3.16.0 【新增】优化代码生成 字典和文件预览;【新增】代码生成 菜单SQL;【新增】登录页面GIF炫酷图片; 2025-04-06 20:25:06 +08:00
1024创新实验室
1abe2ee05e
!64 优化代码生成模块,使其适配当前版本
Merge pull request !64 from 大熊/master
2025-04-05 08:41:51 +00:00
zhuoda
cead60b406 v3.15.0【新增】升级SaToken到最新版本;【新增】重磅优化 数据字典;【新增】升级wangEditor-next;【新增】优化缓存 2025-04-03 22:30:18 +08:00
1024创新实验室
9445ad3cf6
v3.15.0【新增】升级SaToken到最新版本;【新增】重磅优化 数据字典;【新增】升级wangEditor-next;
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2025-04-03 14:19:45 +00:00
1024创新实验室
dd31f3e8a5
v3.15.0【新增】升级SaToken到最新版本;【新增】重磅优化 数据字典;【新增】升级wangEditor-next;
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2025-04-03 14:19:17 +00:00
zhoumingfa
486aa13cfd 更新代码生成的菜单SQL模板 2025-04-03 18:29:30 +08:00
zhoumingfa
ade82f8aa2 修改前端页面部分细节 2025-04-01 20:08:10 +08:00
zhoumingfa
66aac47a43 优化代码生成模块,使其适配当前版本 2025-04-01 17:44:29 +08:00
zhoumingfa
23c4889723 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	smart-admin-web-javascript/src/views/business/erp/goods/goods-list.vue
#	smart-admin-web-typescript/src/views/business/erp/goods/goods-list.vue
2025-03-31 23:37:57 +08:00
zhoumingfa
4062d5a4bb 优化代码生成,添加字典预览与文件预览,使其适配当前版本 2025-03-31 23:29:58 +08:00
zhuoda
fc2f3f2e23 v3.15.0【新增】升级SaToken到最新版本;【新增】重磅优化 数据字典;【新增】升级wangEditor-next;【新增】优化缓存实现redis与caffeine 2025-03-31 23:24:07 +08:00
zhuoda
4683e31290 v3.15.0【新增】升级SaToken到最新版本;【新增】重磅优化 数据字典;【新增】升级wangEditor-next;【新增】优化缓存实现redis与caffeine 2025-03-31 23:19:41 +08:00
zhoumingfa
5136148ce1 解决:java.util.concurrent.ExecutionException: net.sf.jsqlparser.parser.ParseException: Encountered unexpected token: "tables" "TABLES" 2025-03-31 23:15:16 +08:00
1024创新实验室
558d5c86ff
!62 Bug修复及细节优化
Merge pull request !62 from 大熊/master
2025-03-29 15:49:56 +00:00
zhoumingfa
45b5ba6795 优化前端字典预览组件 2025-03-28 21:21:02 +08:00
zhoumingfa
b72f58a0bb 1、若干个细节修改;2、更新SQL脚本,t_dict_key 的 key_code 值错误 2025-03-28 21:19:27 +08:00
zhoumingfa
5fb1456080 接口解密中的 fastjson 解析对象统一改为使用 jackson 2025-03-28 21:12:59 +08:00
zhoumingfa
a6607c063b 修复缓存实现配置为 redis 时抛异常的问题 2025-03-28 20:57:48 +08:00
1024创新实验室
580a783d25
!61 refactor(smart-admin): 统一使用“登录”替代“登陆”,确保术语准确性
Merge pull request !61 from CoderKK/master
2025-03-24 11:56:37 +00:00
1024创新实验室
a66d97a408
update README.md.
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2025-03-24 11:54:02 +00:00
CoderKK
684cb3f71c refactor(smart-admin): 统一使用“登录”替代“登陆”,确保术语准确性 2025-03-20 11:42:23 +08:00
1024创新实验室
109689be69
update README.md.
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2025-03-19 06:18:36 +00:00
1024创新实验室
30901ed00f
!60 refactor(smart-admin-api-java17-springboot3): 移除 Dao 接口中的冗余注解
Merge pull request !60 from CoderKK/master
2025-03-15 02:11:05 +00:00
1024创新实验室
e5edc82beb
v3.14.0 更新;【新增】EasyExcel重磅升级为FastExcel;【新增】使用最强Argon2算法作为密码存储;【新增】大家吐槽的数据字典改为可重复;【新增】前端布局再增加多种样式;
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2025-03-12 13:06:22 +00:00
1024创新实验室
ff868d1b2e
v3.14.0 更新;【新增】EasyExcel重磅升级为FastExcel;【新增】使用最强Argon2算法作为密码存储;【新增】大家吐槽的数据字典改为可重复;【新增】前端布局再增加多种样式;
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2025-03-12 13:05:46 +00:00
zhuoda
7ef9000c62 v3.14.0 更新;【新增】EasyExcel重磅升级为FastExcel;【新增】使用最强Argon2算法作为密码存储;【新增】大家吐槽的数据字典改为可重复;【新增】前端布局再增加多种样式;【优化】升级SaToken到最新版本;【优化】token使用Sa-Token的Bearer类型;【优化】优化其他 2025-03-12 20:18:45 +08:00
zhuoda
c295073037 v3.14.0 更新;【新增】EasyExcel重磅升级为FastExcel;【新增】使用最强Argon2算法作为密码存储;【新增】大家吐槽的数据字典改为可重复;【新增】前端布局再增加多种样式;【优化】升级SaToken到最新版本;【优化】token使用Sa-Token的Bearer类型;【优化】优化其他 2025-03-12 20:18:10 +08:00
zhuoda
eeb9c569de v3.14.0 更新;【新增】EasyExcel重磅升级为FastExcel;【新增】使用最强Argon2算法作为密码存储;【新增】大家吐槽的数据字典改为可重复;【新增】前端布局再增加多种样式;【优化】升级SaToken到最新版本;【优化】token使用Sa-Token的Bearer类型;【优化】优化其他 2025-03-12 20:17:39 +08:00
1024创新实验室
5553aac514
update README.md.
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2025-03-11 13:04:53 +00:00
1024创新实验室
30787815c8
通知
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2025-03-11 13:04:21 +00:00
CoderKK
92fd908619 refactor(smart-admin-api-java17-springboot3): 移除 Dao 接口中的冗余注解
- 删除了 Dao.java.vm 文件中的 @Component 注解- 优化了代码结构,减少了不必要的导入
2025-03-11 16:37:15 +08:00
1024创新实验室
b1cbad8362
!59 Bug修复与功能优化
Merge pull request !59 from 大熊/master
2025-03-11 07:26:56 +00:00
1024创新实验室
ad7ad667c8
!58 修复:登录失败锁定不生效 、账号删除后依然能登录、用户名枚举漏洞
Merge pull request !58 from 憨涛子/master
2025-03-11 07:26:43 +00:00
1024创新实验室
8b40637e98
!57 优化响应工具类 SmartResponseUtil 替换魔法值和移除不必要的异常捕获
Merge pull request !57 from CoderKK/master
2025-03-11 07:26:34 +00:00
1024创新实验室
5da35dfe85
!56 通过props-multiple设置单文件/多文件上传
Merge pull request !56 from 总督/master
2025-03-11 07:26:25 +00:00
SillyBoy
55fc58da3d 更新:文件类型检测白名单 2025-03-09 18:05:38 +08:00
SillyBoy
bb68f050bf 修复:java8 spring-security-crypto 需要低版本 2025-03-09 15:51:02 +08:00
SillyBoy
2dd72e404a 优化:添加编辑部门允许负责人为空 2025-03-01 19:38:33 +08:00
SillyBoy
34fdf59432 优化:使用更加安全的编码保存用户密码 2025-03-01 18:44:30 +08:00
zhoumingfa
66147e47da 修改DictSelect组件onChange事件 2025-02-23 23:20:49 +08:00
zhoumingfa
3ac76495ae 修改DictSelect组件onChange事件 2025-02-23 23:09:10 +08:00
zhoumingfa
0c156e23b2 更新SQL脚本 2025-02-23 22:26:20 +08:00
zhoumingfa
d0e9eef9c2 格式与细节修改 2025-02-23 22:25:47 +08:00
zhoumingfa
e44b116184 优化枚举与字典相关组件,增加禁用与隐藏选项属性 2025-02-23 22:23:18 +08:00
SillyBoy
57747d9082 修复:用户名枚举漏洞 2025-02-22 19:15:05 +08:00
zhoumingfa
81b7b2a3a4 1、优化与完善个人中心的资料更新;2、修改员工DAO层的方法参数 2025-02-21 16:17:44 +08:00
zhoumingfa
a100b1ab12 优化公告管理,修改创建人查询的错误等等其他显示问题 2025-02-21 16:00:54 +08:00
zhoumingfa
2c70db1498 更正前端权限插件的判断 2025-02-20 23:00:34 +08:00
zhoumingfa
9a6d758fc7 优化数据范围组件,解决了以部门in的情况下数据权限为本人时最终查看的数据还是部门全部数据的问题 2025-02-20 22:59:30 +08:00
SillyBoy
c4b95654fe 修复:账号删除后依然能登录 2025-02-19 10:44:13 +08:00
zhoumingfa
ac0f1ae2b9 Merge branch 'master' of https://gitee.com/DxrHelloWorld/smart-admin
 Conflicts:
	smart-admin-api-java17-springboot3/sa-base/src/main/resources/code-generator-template/java/dao/Dao.java.vm
	smart-admin-web-typescript/src/api/system/employee-api.ts
2025-02-16 00:07:11 +08:00
SillyBoy
8d635bb80b 修复:登录失败锁定不生效 2025-02-13 15:59:04 +08:00
zhuoda
cdbb854e6c 更新V3.13.0版本:【新增】顶部菜单模式;【优化】因kaptcha有漏洞,弃用;【优化】三级等保默认值 2025-01-19 18:05:34 +08:00
CoderKK
ae753844c7 refactor(sa-base): 优化响应工具类 SmartResponseUtil
- 使用常量 MediaType.APPLICATION_JSON_VALUE 替代硬编码的 "application/json"- 使用 UTF_8 常量替代 "utf-8" 字符串
- 移除不必要的异常捕获
- 优化文件下载头信息设置方法
2025-01-15 10:47:55 +08:00
knight322
e988867b17 通过props-multiple设置单文件/多文件上传,原先未启用 2025-01-14 15:42:45 +08:00
zhuoda
db5e0062a0 v3.12【新增】标签页Chome模式;【优化】优化很多细节 2025-01-08 20:12:46 +08:00
1024创新实验室
29064c176f
!48 修复代码生成缺少SaCheckPermission引入问题
Merge pull request !48 from 檀淮南/N/A
2025-01-05 08:48:09 +00:00
1024创新实验室
b7c71189e1
!47 修复二级菜单展开后,菜单长度样式超长的问题
Merge pull request !47 from 檀淮南/N/A
2025-01-05 08:47:51 +00:00
1024创新实验室
55fb01174f
!51 修复初始化无法获取到 urls 问题
Merge pull request !51 from 丶老实人/N/A
2025-01-05 08:47:11 +00:00
1024创新实验室
1943431df0
!52 fix(system): 修复菜单模态框中显示状态和禁用状态字段、功能点状态名称错误以及点击名称切换错误的问题
Merge pull request !52 from Smile/master
2025-01-05 08:46:51 +00:00
1024创新实验室
bbc382bc38
!54 Fix bug:unexpected token
Merge pull request !54 from RabbitQ/N/A
2025-01-05 08:46:29 +00:00
Turbolisten
31f0041f74
update java17-TokenConfig.java
Signed-off-by: Turbolisten <188029906@qq.com>
2024-12-24 01:43:26 +00:00
RabbitQ
36ebb16574
Fix bug:unexpected token
java.util.concurrent.ExecutionException: net.sf.jsqlparser.parser.ParseException: Encountered unexpected token: "tables" "TABLES"
    at line 7, column 40.


Signed-off-by: RabbitQ <15024835320@163.com>
2024-12-16 03:41:43 +00:00
mijunl
23b75137bb fix(system): 修复菜单模态框中显示状态和禁用状态字段、功能点状态名称错误以及点击名称切换错误的问题 2024-12-04 11:07:56 +08:00
丶老实人
e3888cef9b
修复初始化无法获取到 urls 问题
Signed-off-by: 丶老实人 <120765338@qq.com>
2024-12-03 15:01:15 +00:00
1024Lab-佩弦
7b681e44a8 【功能优化】:新增标签页样式Naive 2024-12-01 19:48:55 +08:00
1024Lab-佩弦
83d970095b 【功能优化】:新增标签页样式Naive 2024-12-01 19:33:25 +08:00
lipeng
a3a7cf63a8 【功能优化】:新增标签页样式Naive 2024-11-28 16:30:17 +08:00
檀淮南
fff3ec203f
修复代码生成缺少SaCheckPermission引入问题
Signed-off-by: 檀淮南 <coder_nai@163.com>
2024-11-27 12:16:58 +00:00
檀淮南
a53acc504e
修复二级菜单展开后,菜单长度样式超长的问题
Signed-off-by: 檀淮南 <coder_nai@163.com>
2024-11-27 01:19:14 +00:00
zhuoda
64ebe2bfdb v3.11.0 【优化】SaTokenConfig与三级等保配置关联;【优化】smart-app去掉无用请求; 2024-11-24 20:03:04 +08:00
zhuoda
69ea81b020 v3.11.0 【优化】SaTokenConfig与三级等保配置关联;【优化】smart-app去掉无用请求; 2024-11-24 20:02:24 +08:00
zhuoda
cb39dedfd5 v3.11.0 【优化】SaTokenConfig与三级等保配置关联;【优化】smart-app去掉无用请求; 2024-11-24 20:02:08 +08:00
1024创新实验室
b27b004edc
!44 修复bug:三级等保配置初始化后最低活跃频率会被全局配置覆盖
Merge pull request !44 from 憨涛子/master
2024-11-24 08:14:30 +00:00
zhuoda
b3b20bc029 v3.10.1 【紧急优化】smart-app 查询用户消息相关业务 2024-11-21 18:57:39 +08:00
zhuoda
b350918501 v3.10.0【新增】全屏模式Modal等终极解决方案;【新增】生成环境去掉跨域;【优化】其他一些小细节 2024-11-18 20:31:47 +08:00
zhoumingfa
145895703d 更改前端的根据部门id查询员工接口地址与后端一致 2024-11-14 17:15:18 +08:00
zhoumingfa
7b712bae71 修改员工SQL 2024-11-13 00:34:42 +08:00
zhoumingfa
69ff0a9631 解决代码生成配置中的插入和更新表单配置显示有误 2024-11-12 22:59:21 +08:00
zhoumingfa
364ca94973 优化表格列设置 2024-11-12 22:55:11 +08:00
zhuoda
69fa9088f5 v3.9.0【优化】typescript版本;【优化】App端消息;【优化】弹出层z-index; 2024-11-04 20:15:49 +08:00
zhoumingfa
33a8ab3280 1、代码生成器模块的菜单SQL改为不缓存;2、格式修改 2024-10-25 14:44:50 +08:00
SillyBoy
dab0afdb59 修复bug:三级等保配置初始化后最低活跃频率会被全局配置覆盖 2024-10-22 18:10:01 +08:00
zhuoda
17a3e1fd86 v3.8.0【优化】简介明了的数据范围说明文档;【优化】Long序列化;【优化】标签页右键关闭;【优化】表格排序Demo 2024-10-17 21:56:11 +08:00
zhuoda
053d562157 v3.8.0【优化】简介明了的数据范围说明文档;【优化】Long序列化;【优化】标签页右键关闭;【优化】表格排序Demo 2024-10-17 21:55:56 +08:00
卓大
3940dcb245
update README.md.
Signed-off-by: 卓大 <zhuoluodada@qq.com>
2024-10-08 14:16:28 +00:00
卓大
2fe5a0796e
update README.md.
Signed-off-by: 卓大 <zhuoluodada@qq.com>
2024-10-08 14:05:44 +00:00
1024创新实验室
7669139d7a
!39 【轻量级 PR】修改重置密码使用Long类型接收员工id
Merge pull request !39 from ly-liuxia/master
2024-10-07 07:17:24 +00:00
zhuoda
753283191a v3.7.0 (2024-09-28) Java17+SpringBoot3重磅更新,【新增】支持Java17;【新增】支持SpringBoot3;【优化】优化AES和SM4加密;【优化】优化三级等保文档; 2024-09-28 21:55:51 +08:00
zhuoda
0f719aee10 v3.7.0 (2024-09-28) Java17+SpringBoot3重磅更新,【新增】支持Java17;【新增】支持SpringBoot3;【优化】优化AES和SM4加密;【优化】优化三级等保文档; 2024-09-28 21:54:38 +08:00
liutao-lx
7486d3bc58 【轻量级 PR】修改重置密码使用Long类型接收员工id 2024-09-09 22:05:36 +08:00
zhuoda
4362e8df8b v3.6.0 三级等保重磅更新:1、【新增】双因子方式登录;2、【新增】定期修改密码;3、【新增】最大活跃时间;4、【新增】敏感数据脱敏;5、【新增】登录锁定配置;6、【新增】密码复杂度配置;7、【新增】三级等保可配置 2024-09-03 22:35:00 +08:00
zhuoda
6855b8b088 Merge branch 'master' of https://gitee.com/lab1024/smart-admin
# Conflicts:
#	smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/manager/EmployeeManager.java
#	smart-admin-web/javascript-ant-design-vue3/.env.development
#	smart-admin-web/javascript-ant-design-vue3/src/router/index.js
2024-09-02 22:23:55 +08:00
zhuoda
92dddd507b v3.6.0 三级等保重磅更新:1、【新增】双因子方式登录;2、【新增】定期修改密码;3、【新增】最大活跃时间;4、【新增】敏感数据脱敏;5、【新增】登录锁定配置;6、【新增】密码复杂度配置;7、【新增】三级等保可配置 2024-09-02 22:20:29 +08:00
1024创新实验室
013d1c237b
!35 功能优化与部分Bug修复
Merge pull request !35 from 大熊/master
2024-09-02 13:57:34 +00:00
1024创新实验室
8920b35945
!37 修复删除部门的碧油鸡
Merge pull request !37 from LiZongLiang/master
2024-09-02 13:46:09 +00:00
1024创新实验室
d702e6cca4
!36 解决deparement中返回树形列表SelfAndAllChildrenIdList只返回本节点id的问题
Merge pull request !36 from C-ccc/N/A
2024-09-02 13:45:07 +00:00
zhoumingfa
3fcb764078 修改代码生成 form 模板的 width 2024-08-16 17:53:06 +08:00
1024创新实验室
f4923487b4
update smart-admin-web/javascript-ant-design-vue3/.env.development.
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2024-08-14 15:09:36 +00:00
zhoumingfa
6bcb9b296f Merge branch 'code-generator'
# Conflicts:
#	smart-admin-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/CodeGeneratorTemplateService.java
#	smart-admin-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/MapperVariableService.java
#	smart-admin-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/core/SmartJobExecutor.java
#	smart-admin-api/sa-base/src/main/resources/code-generator-template/js/form.vue.vm
#	smart-admin-api/sa-base/src/main/resources/code-generator-template/js/list.vue.vm
#	smart-admin-web/javascript-ant-design-vue3/src/views/support/code-generator/components/form/code-generator-table-config-form-delete.vue
#	smart-admin-web/javascript-ant-design-vue3/src/views/support/code-generator/components/preview/code-generator-preview-modal.vue
2024-08-14 15:11:15 +08:00
zhoumingfa
be56a0b505 增强:1、代码生成器模块支持生成菜单SQL;2、Controller 代码模板添加权限注解 2024-08-14 15:09:14 +08:00
zhoumingfa
b16d8a6128 细节优化 2024-08-14 14:58:10 +08:00
zhoumingfa
66cd067fa1 优化代码生成器模块:1、代码生成器配置页支持刷新字典;2、修改 Mapper.xml 中字典的查询方式;3、其它细节优化 2024-08-14 14:54:56 +08:00
zhoumingfa
ff03f07b3f 优化:字典选择组件支持多选 2024-08-14 14:22:23 +08:00
zhoumingfa
6c28721b38 bug修复:1、解决代码生成配置中的查询条件拖拽后不能删除的问题;2、解决删除条件并再次新增条件后点击【保存】按钮无反应问题。 2024-08-04 22:00:01 +08:00
zhoumingfa
dc9f4b7953 优化代码生成模块:1、字典与文件字段添加序列化注解;2、新增 bit-Boolean 类型的映射;新增在create_time与update_time字段上添加自动填充注解。 2024-08-04 22:00:01 +08:00
zhoumingfa
594c847523 bug修复:1、解决代码生成配置中的查询条件拖拽后不能删除的问题;2、解决删除条件并再次新增条件后点击【保存】按钮无反应问题。 2024-08-04 21:58:39 +08:00
zhoumingfa
a1043083dc 优化代码生成模块:1、字典与文件字段添加序列化注解;2、新增 bit-Boolean 类型的映射;新增在create_time与update_time字段上添加自动填充注解。 2024-08-04 21:51:40 +08:00
zhoumingfa
a5a7fdf61a Field 'execute_end_time' doesn't have a default value 2024-08-04 20:24:50 +08:00
zhoumingfa
6f183c3366 Merge branch 'master' of https://gitee.com/DxrHelloWorld/smart-admin 2024-08-04 15:57:33 +08:00
zhoumingfa
84b5d338b6 优化:1、查询员工通知时更新浏览量;2、删除多余的 NoticeMapper.xml 文件 2024-08-04 15:37:44 +08:00
大熊
f8039df1bf 添加角色员工中不应该存在删除操作,而是过滤出需要添加的员工再进行保存操作。
Signed-off-by: 大熊 <daxiongren@foxmail.com>
2024-08-04 06:54:13 +00:00
zhoumingfa
8fd02fc519 优化:1、角色员工列表的添加员工弹窗中禁止添加选择已存在该角色的员工;2、禁止删除已存在员工的角色 2024-08-04 14:32:23 +08:00
zhoumingfa
949f7a209c 首页 card 插槽去除白色背景色 2024-08-04 11:47:40 +08:00
zhoumingfa
15cc4a9003 优化首页的待办工作添加与标记star的移动位置 2024-08-04 11:46:47 +08:00
zhoumingfa
ecd671682e 优化页面头部的消息气泡卡片 2024-08-04 11:38:16 +08:00
zhoumingfa
bf64f525fb 去除首页卡片的直角 2024-08-03 23:38:54 +08:00
zhoumingfa
694aa18452 前端首页的待办卡片中新增基于localStorage的待办添加与删除功能,并优化页面顶部的消息卡片 2024-08-03 23:38:05 +08:00
zhoumingfa
7d8879abcb 转换为查询参数中添加是否查询总条数 2024-08-03 22:40:53 +08:00
LiZongLiang
2f5683ac9d 修复删除部门的bug 2024-08-03 16:13:21 +08:00
C-ccc
6f3d7dc3a2
update system/department/manager/DepartmentCacheManager.java.
修改 recursiveBuildTree方法,使返回值中的setSelfAndAllChildrenIdList是以当前节点为根节点的层序遍历结果

Signed-off-by: C-ccc <2170639886@qq.com>
2024-07-25 08:36:58 +00:00
zhoumingfa
36e554d8ed 解决前端文件下载报文件不存在的错误 2024-07-24 20:42:33 +08:00
zhuoda
ac7c9940bf 【V3.5.0】1、【新增】轻量级定时任务 SmartJob;2、【新增】站内信;3、【新增】个人中心;4、【新增】岗位管理;5、【优化】部门员工管理 2024-07-17 20:19:59 +08:00
zhuoda
fed72d0c34 【V3.5.0】1、【新增】轻量级定时任务 SmartJob;2、【新增】站内信;3、【新增】个人中心;4、【新增】岗位管理;5、【优化】部门员工管理 2024-07-17 20:16:12 +08:00
zhuoda
cbdac440d3 【V3.5.0】1、【新增】轻量级定时任务 SmartJob;2、【新增】站内信;3、【新增】个人中心;4、【新增】岗位管理;5、【优化】部门员工管理 2024-07-16 23:44:15 +08:00
zhuoda
4a4d7115ef 【V3.5.0】1、【新增】轻量级定时任务 SmartJob;2、【新增】站内信;3、【新增】个人中心;4、【新增】岗位管理;5、【优化】部门员工管理 2024-07-16 23:41:50 +08:00
zhuoda
201b6a5018 【V3.5.0】1、【新增】轻量级定时任务 SmartJob;2、【新增】站内信;3、【新增】个人中心;4、【新增】岗位管理;5、【优化】部门员工管理 2024-07-16 00:20:17 +08:00
zhuoda
716b6303e3 【V3.5.0】1、【新增】轻量级定时任务 SmartJob;2、【新增】站内信;3、【新增】个人中心;4、【新增】岗位管理;5、【优化】部门员工管理 2024-07-16 00:20:02 +08:00
1024创新实验室
3bfd00a416
!33 【BUG】角色添加员工,数据会全覆盖
Merge pull request !33 from lzy6666666/master
2024-07-15 16:18:30 +00:00
1024创新实验室
23e8ea55e1
update README.md.
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2024-06-13 04:06:46 +00:00
1024创新实验室
3678687114
update README.md.
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2024-06-13 04:05:51 +00:00
1024创新实验室
32f45a6651
update README.md.
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2024-06-13 04:05:30 +00:00
Tim
42b6689b80 【BUG】角色添加员工,数据会全覆盖 2024-05-21 10:58:13 +08:00
zhuoda
3c4e683ff0 【v3.4.0】 1、【新增】页面全局圆角可配置化;2、【优化】首页心灵鸡汤语录;3、【优化】底部公司信息写法; 2024-05-05 20:52:34 +08:00
zhuoda
2b41357c8c 【v3.4.0】 1、【新增】页面全局圆角可配置化;2、【优化】首页心灵鸡汤语录;3、【优化】底部公司信息写法; 2024-05-05 20:43:05 +08:00
zhuoda
a4e0855f0a 【v3.4.0】 1、【新增】页面全局圆角可配置化;2、【优化】首页心灵鸡汤语录;3、【优化】底部公司信息写法; 2024-05-05 20:42:49 +08:00
卓大
babf575fc6
update README.md.
Signed-off-by: 卓大 <zhuoluodada@qq.com>
2024-04-28 14:25:00 +00:00
卓大
0a37427a84
update README.md.
Signed-off-by: 卓大 <zhuoluodada@qq.com>
2024-04-28 14:24:30 +00:00
zhuoda
9ad5a5a5b5 【v3.3.0】 1、uniapp 首页菜单功能区多平台适配;2、菜单组件路径说明;3、长时间不在线自动返回登录页;4、标签页 tab 为圆角;5、升级 sa token 到 1.37.0;6、代码生成表单弹窗 关闭事件;7、接口操作日志@OperateLogAspect 对文件的处理; 2024-04-28 21:59:11 +08:00
1024创新实验室
5075fc6030
!32 【轻量级 PR】:修改代码生成 form.vue.vm 模板中取消事件
Merge pull request !32 from 大熊/master
2024-04-28 13:06:26 +00:00
1024创新实验室
cfba870006
!30 update smart-admin-api/pom.xml.
Merge pull request !30 from npc6/N/A
2024-04-28 13:02:07 +00:00
Zhou Mingfa
9a991b2e27 修改代码生成 form.vue.vm 模板,drawer 类型的取消事件为 @close,modal 类型的取消事件为 @cancel 2024-04-25 16:08:59 +08:00
npc6
f97079ac1b
update smart-admin-api/pom.xml.
sa-token.version 升级到1.37.0

修复:修复路由拦截鉴权可被绕过的问题。 [漏洞修复]
重构:未登录时调用鉴权 API 抛出未登录异常而不再是无权限异常。
优化:优化 SaTokenDao 组件更换时的逻辑。
文档:提供 SpringBoot3.x 路由匹配出错的解决方案。

Signed-off-by: npc6 <jjwsoft@qq.com>
2024-04-24 02:38:42 +00:00
zhuoda
e75c1ec34d 【V3.2.0】1、左侧菜单Logo和标题固定;2、Excel导出添加水印;3、长时间不在线自动返回登录页;4、移除sa-token的 token-prefix 配置;5、升级 ant deign vue到最新版4.2;6、登录页面引入登录类型图标方式;7、文件预览组件的文件下载方式为接口方式下载; 2024-04-22 23:27:30 +08:00
1024创新实验室
51aa2e08ba
!29 为导出Excel导出添加水印
Merge pull request !29 from BOOM/master
2024-04-22 14:41:20 +00:00
刘哲贤
18cd04c33a 封装excel导出类,简化Controller中代码 2024-04-16 22:46:13 +08:00
刘哲贤
48d108d4e6 实现easyexcel中的SheetWriteHandler,在afterSheetCreate中添加水印 2024-04-16 22:43:43 +08:00
刘哲贤
ce8db0389e 新增水印配置类 2024-04-16 22:42:57 +08:00
刘哲贤
44938b34a5 添加导出是否带水印配置,默认为带水印 2024-04-16 22:42:20 +08:00
刘哲贤
c761a94c43 添加ooxml-schemas依赖,实现导出带水印 2024-04-16 22:41:51 +08:00
1024创新实验室
ad8ae5bb0f
!28 部分细节优化
Merge pull request !28 from 大熊/master
2024-04-16 13:39:23 +00:00
Zhou Mingfa
52a7a5f839 解决登录页面的登录类型图标不显示问题与背景图片不显示问题 2024-04-11 20:32:14 +08:00
Zhou Mingfa
a90b8d114a 代码格式化与部分细节优化 2024-04-11 20:26:00 +08:00
Zhou Mingfa
9100dc1225 修改文件预览组件的文件下载方式为接口方式下载,解决了下载时整个页面闪烁的问题;优化相册样式。 2024-04-11 20:24:59 +08:00
Zhou Mingfa
2e0cb6a96d 在获取通知公告详情更新表单中添加分类名称,用于前端通知公告详情页面中显示分类名称 2024-04-11 16:40:38 +08:00
Zhou Mingfa
af4c470e93 删除发票信息的接口路径错误 2024-04-11 15:59:55 +08:00
1024创新实验室
71521d1d41
!26 后端员工通知公告查询Bug修复以及前端文件上传组件优化
Merge pull request !26 from 大熊/master
2024-04-10 11:40:13 +00:00
1024创新实验室
8558fd307b
!27 前端代码:为help-doc的详情页面 提供好看的html样式
Merge pull request !27 from tsukimojo/master
2024-04-10 11:37:23 +00:00
good
d155e8e2cd 前端代码:为help-doc的详情页面 提供好看的html样式(标题、表格等) 2024-04-10 13:35:38 +08:00
卓大
abcbc7fda6
update README.md.
Signed-off-by: 卓大 <zhuoluodada@qq.com>
2024-04-06 14:18:28 +00:00
zhuoda
2713ecac0b v3.1.0 1、【新增】9种登录背景图和样式; 2、【新增】全局字体大小切换; 3、【新增】主题颜色切换; 4、【新增】移除cookie保存token,改为使用localStorage; 5、【优化】升级 ant design vue 到最新版本; 2024-04-06 21:02:51 +08:00
zhuoda
6a2c86d9f2 v3.1.0 1、【新增】9种登录背景图和样式; 2、【新增】全局字体大小切换; 3、【新增】主题颜色切换; 4、【新增】移除cookie保存token,改为使用localStorage; 5、【优化】升级 ant design vue 到最新版本; 2024-04-06 21:01:43 +08:00
大熊
d4ae31cad0 Merge branch 'master' of gitee.com:lab1024/smart-admin into master
Signed-off-by: 大熊 <daxiongren@foxmail.com>
2024-03-20 07:51:46 +00:00
卓大
994b3954ed
update README.md.
Signed-off-by: 卓大 <zhuoluodada@qq.com>
2024-03-18 15:20:08 +00:00
卓大
cb9f1f22e6
update README.md.
Signed-off-by: 卓大 <zhuoluodada@qq.com>
2024-03-18 15:17:58 +00:00
zhuoda
1723f2514f 【v3.0.1】1、【新增】tomcat访问日志accessslog 最大保存天数;2、【新增】获取登录结果信息接口返回 Token;3、【新增】员工列表、表单 新增超级管理员标识;4、【优化】移除dev环境swagger用户名和密码;5、【优化】成功返回消息内容改为"操作成功";6、【优化】代码下载zip文件名改为 下划线,eg:t_apply_code.zip;7、【优化】Service代码生成自动Import;8、【优化】AdminInterpter 拦截器中对超级管理员放行;9、【优化】优化重复提交RepeatSubmitAspect;10、【优化】修改其他bug 2024-03-18 22:36:36 +08:00
zhuoda
27dffd9919 【smart-app更新】1、意见反馈;2、我的;3、退出登录;4、等等其他 2024-03-17 22:53:19 +08:00
zhuoda
83d316a2d1 【smart-app更新】1、意见反馈;2、我的;3、退出登录;4、等等其他 2024-03-17 22:52:00 +08:00
zhuoda
4b36de6de5 【smart-app更新】1、版本更新记录;2、复杂表单‘3、引入tabs组件 2024-03-15 22:43:39 +08:00
zhuoda
d170a9d189 【smart-app更新】1、版本更新记录;2、复杂表单‘3、引入tabs组件 2024-03-13 21:05:28 +08:00
zhuoda
3b31558adb Merge branch 'master' of https://gitee.com/lab1024/smart-admin 2024-03-10 22:26:57 +08:00
zhuoda
728ddb9a7e smart-app alpha 版本 2024-03-10 22:26:32 +08:00
Zhou Mingfa
e1f5b5ca12 解决查看更新日志的 modal 对话框点击右上角的叉不能关闭的问题 2024-02-23 09:55:28 +08:00
Zhou Mingfa
47dd346f14 变量命名错别字 2024-02-23 09:51:17 +08:00
Zhou Mingfa
1812cb3d6b 文件上传组件:解决不能点击下载文件的问题、支持多选文件上传、新增超出文件最大数量与超出单文件大小相应的错误提示。 2024-02-22 17:26:19 +08:00
Zhou Mingfa
18c1ac5a5b 修复 防止重复提交注解 不生效的问题 2024-02-22 15:54:51 +08:00
Zhou Mingfa
28834e2515 解决员工查询不到未读通知公告的问题 2024-02-22 11:28:18 +08:00
Zhou Mingfa
caab0040ff 解决员工通知公告按关键字查询时的SQL报错 2024-02-22 11:20:03 +08:00
kkaiyun
2c72327c8e 删除参数保持一致 2024-01-29 09:15:01 +08:00
zhuoda
d64b769d40 v3.0.1, 修改代码生成的注解引入 2024-01-21 22:31:09 +08:00
zhuoda
851d913ab6 v3.0.0 【优化】登录日志回显、版本号改为3.0、文件下载 2024-01-15 21:49:04 +08:00
zhuoda
4142295ee1 v3.0.0 2024-01-10 22:31:20 +08:00
1024创新实验室
2861f6e8e0
v3.0.0
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2024-01-08 12:46:51 +00:00
1024创新实验室
b0f8dc30e6
v3.0.0
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2024-01-08 12:07:31 +00:00
1024创新实验室
7ea308817a
v3.0.0
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2024-01-08 12:06:52 +00:00
zhuoda
192e959d14 v3.0.0 2024-01-08 19:52:39 +08:00
zhuoda
8dc663d885 【优化】代码格式优化 2023-07-26 21:23:41 +08:00
zhuoda
018bbf0993 恢复 2023-07-26 21:18:58 +08:00
zhuoda
25aad6ba5f Revert "!22 sa-token"
This reverts commit e465fdbf0a, reversing
changes made to c6d7ae9f46.
2023-07-26 21:18:39 +08:00
1024创新实验室
e465fdbf0a
!22 sa-token
Merge pull request !22 from Turbolisten/master
2023-07-26 12:11:31 +00:00
lixiaodong
1b6d8ac270 remove SaCheckPermission 2023-07-25 20:07:55 +08:00
lixiaodong
c9d4f12c64 sa-token update 2023-07-25 19:55:55 +08:00
lixiaodong
de3269b233 sa-token update 2023-07-25 19:54:52 +08:00
lixiaodong
0733919efc sa-token update 2023-07-25 19:42:47 +08:00
lixiaodong
8a113bb7f8 sa-token update 2023-07-25 19:36:42 +08:00
lixiaodong
7de2627fee sa-token update 2023-07-21 08:32:56 +08:00
lixiaodong
ac6921a278 sa-token 2023-07-13 20:15:41 +08:00
lixiaodong
54d8d9489a sa-token 2023-07-13 18:54:48 +08:00
lixiaodong
0d17270b11 update system env 2023-07-12 22:58:04 +08:00
lixiaodong
1ad96b81e9 sa-token add login 2023-07-12 22:33:33 +08:00
lixiaodong
c894c3d934 add sa-token 2023-07-12 20:13:22 +08:00
zhuoda
c6d7ae9f46 Merge branch 'master' of https://gitee.com/lab1024/smart-admin 2023-06-13 20:34:15 +08:00
zhuoda
793115e2e7 update 2023-06-13 20:33:33 +08:00
kkaiyun
5a7cccbd26 update 2023-05-22 22:45:56 +08:00
卓大
08ded5b3fc
!21 update smart_admin_v2.sql.
Merge pull request !21 from 桃花仙/N/A
2023-05-22 14:21:38 +00:00
卓大
c51d3a6181
!20 修改40X页面提示代码与错误提示内容不匹配
Merge pull request !20 from 霜叶/master
2023-05-22 14:21:09 +00:00
卓大
8683a1bcd6
!19 调整 请求监控>请求详情 请求内容的 列宽
Merge pull request !19 from dd/vue-modify
2023-05-22 14:20:16 +00:00
卓大
40de7c1e32
!18 fix disableFlag 判断逻辑导致token 未移除
Merge pull request !18 from dd/master
2023-05-22 14:19:37 +00:00
桃花仙
05804c64f5
update smart_admin_v2.sql.
订正字段描述错误

Signed-off-by: 桃花仙 <36101995@qq.com>
2023-05-18 07:09:29 +00:00
霜叶
fdea2dd169
修改40X错误提示页面的错误,正确代码应为404对应页面未找到,403对应被禁止
Signed-off-by: 霜叶 <only_passerby@163.com>
2023-05-17 12:41:52 +00:00
peter zhang
f0f317ab53
调整 请求监控>请求详情 请求内容的 列宽 2023-05-12 15:19:57 +08:00
peter zhang
29a67c6340
fix disableFlag 判断逻辑导致token 未移除 2023-05-12 14:58:14 +08:00
kkaiyun
3693856a05 Merge remote-tracking branch 'origin/master' 2023-05-10 20:09:42 +08:00
kkaiyun
05e91f7786 删除多余字符串 2023-05-10 20:09:36 +08:00
zhuoda
c7501c7f36 Merge branch 'master' of https://gitee.com/lab1024/smart-admin 2023-05-09 19:53:25 +08:00
zhuoda
6469ec4d4f fix issus 2023-05-09 19:52:10 +08:00
kkaiyun
361b1fd60f Merge branch 'master' of gitee.com:lab1024/smart-admin 2023-05-09 17:50:10 +08:00
kkaiyun
60757af3d7 更新代码生成参数 2023-05-09 17:49:55 +08:00
zhuoda
6665da07b7 优化一些问题和代码 2023-04-06 22:50:50 +08:00
zhuoda
28f4962e32 优化一些问题和代码 2023-04-06 22:50:18 +08:00
zhuoda
e2c6a83125 优化一些问题和代码 2023-04-06 22:48:07 +08:00
kkaiyun
f2d098d5d1 菜单树检索不生效 2023-03-04 14:27:02 +08:00
kkaiyun
fbd60b5881 菜单树检索不生效 2023-03-04 14:25:29 +08:00
1024创新实验室
5f16ab91d5
update README.md.
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2023-02-17 00:50:35 +00:00
1024创新实验室
5673df549b
update smart-admin-web/javascript-ant-design-vue3/src/main.js.
Signed-off-by: 1024创新实验室 <1024lab@sina.com>
2023-02-16 13:45:42 +00:00
卓大
d0885616b7
update README.md.
优化

Signed-off-by: 卓大 <zhuoluodada@qq.com>
2023-02-16 13:05:22 +00:00
zhuoda
588e055fc3 优化下文档 2023-02-16 21:00:01 +08:00
zhuoda
a5b40fabc9 优化下文档 2023-02-16 20:55:11 +08:00
zhuoda
613c033967 优化下文档 2023-02-16 20:53:57 +08:00
zhuoda
86b8c6849e 修复几个显示问题 2023-02-16 20:13:34 +08:00
zhuoda
521c89119f 修复几个显示问题 2023-02-16 20:11:43 +08:00
kkaiyun
f6651b8efe 天气显示不全 2023-02-09 22:06:20 +08:00
yandy_java
3e97448fd9 本地问题 下载预览需要在系统参数里面配置访问路径 我这边涉及文件的都是这个问题。
默认路径:
http://[ip:端口号]/preview/[文件key]
参考:net.lab1024.sa.common.config.MvcConfig#addResourceHandlers 这里配置。
2023-02-08 23:22:22 +08:00
yandy_java
77fac6149d 数据字典报错 2023-02-08 23:11:43 +08:00
zhuoda
3161675d40 修复字典第二页查询bug 2023-01-12 19:04:55 +08:00
zhuoda
4389441c2d 更新文档地址 2023-01-03 19:39:57 +08:00
zhuoda
2d6499b42d 修改标签页多次点击的问题 2022-12-16 18:37:42 +08:00
zhuoda
4d634887ba 添加代码规范 2022-12-09 18:48:01 +08:00
zhuoda
340dc1950c v2.0 修改下登录提示语 2022-12-09 18:45:26 +08:00
zhuoda
cc590abc9e Merge branch 'master' of https://gitee.com/lab1024/smart-admin 2022-12-09 18:39:41 +08:00
zhuoda
851f30a3b1 1、添加默认用户名和密码提示 2、打包prod环境添加依赖 2022-12-09 18:39:36 +08:00
yandy
6149ef9f0c 1.解决不需要security的项目是通过拦截器判断是否存在用户,此时common会自动引入security包
2.解决本地文件上传,图片找不到问题
3.添加UrlMatcherUtil,用于判断是否包含特定的URL
2022-11-25 09:46:16 +08:00
zhuoda
945e31290e v2.0 更新vite3.2.3,速度非常快 2022-11-13 21:21:16 +08:00
zhuoda
5bd36cb42e v2.0 2022-11-07 23:28:10 +08:00
zhuoda
01b7f93a9b v2.0 优化下代码生成的提示 2022-11-07 23:27:02 +08:00
zhuoda
9631dbe008 v2.0 2022-11-06 22:10:44 +08:00
zhuoda
b811d79b34 时间范围选择增加默认选项 2022-11-06 22:09:46 +08:00
zhuoda
cd10a2d1b8 v2.0 2022-11-05 22:31:31 +08:00
zhuoda
2a2ccb4386 v2.0 2022-11-05 22:29:27 +08:00
zhuoda
06591c5a33 v2.0 2022-11-05 22:27:16 +08:00
zhuoda
a5e3271f56 v2.0 2022-11-05 22:03:50 +08:00
zhuoda
ff88bbcb6a v2.0 2022-11-05 11:40:51 +08:00
zhuoda
188843517d v2.0 2022-11-05 11:39:44 +08:00
卓大
79fb81ca38
update README.md.
Signed-off-by: 卓大 <zhuoluodada@qq.com>
2022-11-05 03:38:54 +00:00
卓大
70747bf1de
update README.md.
Signed-off-by: 卓大 <zhuoluodada@qq.com>
2022-11-05 03:37:27 +00:00
zhuoda
9ee69b7889 v2.0 2022-11-05 11:36:25 +08:00
zhuoda
45f0a50344 v2.0 2022-11-05 11:33:49 +08:00
zhuoda
c54716808d v2.0 2022-10-29 08:59:31 +08:00
zhuoda
0fefed6da1 v2.0 2022-10-28 21:43:48 +08:00
zhuoda
f6971fa7c0 v2.0 代码提交 2022-10-27 22:38:31 +08:00
zhuoda
c42e24ccf8 v2.0 代码提交 2022-10-27 22:36:43 +08:00
zhuoda
98df0f5e6a v2.0 代码提交 2022-10-27 22:33:46 +08:00
zhuoda
7f2099d507 v2.0 代码提交 2022-10-27 22:31:26 +08:00
zhuoda
fe58e61814 v2.0 代码提交 2022-10-27 22:28:52 +08:00
zhuoda
8d42c5730d Merge branch 'master' of https://gitee.com/lab1024/smart-admin 2022-10-27 22:15:20 +08:00
zhuoda
f7e5f6d539 v2.0 代码提交 2022-10-27 22:14:48 +08:00
zhuoda
a8cefcc310
update smart-admin-api/sa-parent/pom.xml.
Signed-off-by: user_5589720 <zhuoluodada@qq.com>
2022-10-24 12:32:30 +00:00
zhuoda
207b949484 vue3的js和ts代码上传 2022-10-24 20:11:58 +08:00
zhuoda
0996e90df0 修改下目录结构 2022-10-24 20:10:37 +08:00
zhuoda
692ab99e0c Merge branch 'master' of https://gitee.com/lab1024/smart-admin 2022-10-24 19:47:54 +08:00
zhuoda
51ce05b761 上传 v2.0.0 的typescript代码 2022-10-24 19:46:34 +08:00
zhuoda
f0c5369e36 v2.0.0 2022-10-24 19:42:11 +08:00
zhuoda
58ad4f12b8 上传typescript版本代码,但是ts很多警告还没解决 2022-10-24 19:39:27 +08:00
zhuoda
2621703f1f 2.0的js版本和后端 完成 2022-10-22 20:49:25 +08:00
zhuoda
b782b953a5
update README.md. 2022-04-26 05:38:58 +00:00
zhuoda
4fc2976624 update 2021-09-13 14:36:17 +00:00
lipeng
c692d0e6d3 增加缺失依赖 2021-08-10 13:13:17 +08:00
zhuoda
1204787cf3 update 代码规范/api接口规范.md. 2021-05-19 10:48:01 +08:00
zhuoda
2d61c21398 update 代码规范/api接口规范.md. 2021-05-19 10:47:44 +08:00
zhuoda
fe6ab3798a update 代码规范/api接口规范.md. 2021-05-19 10:47:36 +08:00
zhuoda
0c0da77ecd 更新api接口规范 2021-05-19 10:46:37 +08:00
zhuoda
c530d8db15 add 代码规范/api接口规范.md. 2021-05-19 10:39:04 +08:00
zhuoda
a1357155b9 去掉引导和修改默认登录账号 2021-05-02 10:15:25 +08:00
zhuoda
b072b9e758 update README.md. 2021-04-16 22:48:51 +08:00
zhuoda
355643ce86 update README.md. 2021-04-15 22:33:50 +08:00
1024-lab
5e43679c3c update README.md. 2021-03-05 21:03:14 +08:00
1024-lab
5249c2fdf5 update README.md. 2021-03-05 21:02:18 +08:00
1024-lab
8fc8338bfa update README.md. 2021-03-05 08:56:10 +08:00
yandy_java
111d930f98 !6 修复同电话员工校验
Merge pull request !6 from Anonym/master
2021-01-18 21:55:43 +08:00
yandy_java
835076c301 !7 bug修复及优化
Merge pull request !7 from Turbolisten/master
2021-01-18 21:54:47 +08:00
zhuoda
02560ea621 package lock 2021-01-11 21:24:50 +08:00
zhuoda
606e763126 优化h5项目 2021-01-10 20:21:30 +08:00
Turbolisten
21cd668943 修改数据库字符编码统一为utf8mb4_unicode_ci 2021-01-09 10:22:21 +08:00
Turbolisten
ea0159ddb4 优化枚举类校验;优化Swagger配置,添加默认参数;fix删除部门;优化ResponseDTO; 2021-01-09 10:13:15 +08:00
Turbolisten
f7155ac4c2 Merge remote-tracking branch 'origin/master' 2021-01-09 09:05:03 +08:00
Turbolisten
063190c314 update .gitignore 2021-01-08 22:01:36 +08:00
李宗亮
46645e5696 修复同电话员工校验 2020-12-09 11:20:01 +08:00
Turbolisten
701d95653e 优化枚举类校验;Decimal工具类增加max,min 2020-10-24 09:59:13 +08:00
3038 changed files with 225532 additions and 65592 deletions

23
.gitignore vendored
View File

@ -1,6 +1,25 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**
### STS ###
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
**/target/
### front ###
**/dist
**/node_modules
**/.vscode
**/node_modules/

181
README.md
View File

@ -1,130 +1,83 @@
#### 简介
SmartAdmin由河南·洛阳 [1024创新实验室](https://www.1024lab.net/)团队研发的一套互联网企业级的通用型中后台解决方案使用最前沿的前后台技术栈SpringBoot和Vue前后端分离<font color="#DC143C">**我们开源一套漂亮的代码和一套整洁的代码规范**</font>让大家在这浮躁的代码世界里感受到一股把代码写好的清流同时又让开发者节省大量的时间减少加班快乐工作热爱生活。SmartAdmin 让你从认识到忘不了,绝对是你最想要的!
### **SmartAdmin**
#### 开源地址 (*欢迎 Star ~ ~ ╰( ̄▽ ̄)╭*)
github: [https://github.com/1024-lab/smart-admin](https://github.com/1024-lab/smart-admin)
gitee: [https://gitee.com/lab1024/smart-admin](https://gitee.com/lab1024/smart-admin)
在线预览: [http://preview.smartadmin.1024lab.net](http://preview.smartadmin.1024lab.net)
部署文档:[http://smartadmin.1024lab.net/doc/2/168](http://smartadmin.1024lab.net/doc/2/168)
平滑升级:[http://smartadmin.1024lab.net/doc/2/173](http://smartadmin.1024lab.net/doc/2/173)
**SmartAdmin** 由 **中国·洛阳** [1024创新实验室](https://www.1024lab.net/) 基于SpringBoot2/3+Sa-Token+Mybatis-Plus 和 Vue3+Ant Design Vue+Uni-App+Uni-UI并以 <font color="#DC143C">**「高质量代码」为核心,「简洁、高效、安全」**</font>的快速开发平台。
#### 疑惑
有人问:又是个“轮子”? 轮子靠谱吗?为什么要选择你这个轮子?
<font color="#DC143C">**1024Lab**回答:
它不是“轮子”,目的不是为了重复造轮子! 我们开源的是一套 “漂亮的代码” 和 “代码规范”。
</font>
**<font color="#DC143C">国内首个满足《网络安全-三级等保》、《数据安全》</font>** 功能要求,支持登录限制、接口国产加解密、数据脱敏等一系列安全要求。
#### 理念与思想
- 我们分享的不是代码不是徒劳无功的堆砌功能而是你必须的基础功能比如Vue前端权限、心跳、动态Reload、Keepalived标签页等等可能还有一些正是你当前项目中缺失的功能。
- 我们分享的不仅有代码,还有一套经过几十人验证过的前、后端代码。细节决定成败,好的规范能让我们敲下的每行代码更铿锵有力!
- 我们推崇高质量的代码,身为开发,代码即利剑,键盘上一套行云流水,宛如侠客,事了拂衣去,深藏身与名。
- 我们推崇团队的高度配合默契、互相帮助从不加班而不是一看到别人的代码就头皮发麻留其996.ICU
- 我们热爱编程,热爱代码,保持谦逊,不断学习,快乐工作,热爱生活。
- **请相信并认真阅读下面的每一个点,让你感受不一样的编码体验**
**<font color="#DC143C">支持国产数据库【达梦、金仓、南大通用、OceanBase、GaussDB 高斯、阿里PolarDB、GoldenDB】等主流数据库【Mysql, PostgreSQL】等</font>**
#### 演示图
<table>
<tr>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180453_252f5e9f_5469596.png"/></td>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180630_ee5b4f46_5469596.png"/></td>
</tr>
<tr>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180737_9363e283_5469596.png"/></td>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180802_aefb78f4_5469596.png"/></td>
</tr>
<tr>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180821_30fc7aaf_5469596.png")"/></td>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180844_01ebd7d2_5469596.png")"/></td>
</tr>
<tr>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180902_02c8d838_5469596.png"/></td>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180918_ff1f7ff5_5469596.png"/></td>
</tr>
<tr>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180938_86b39645_5469596.png"/></td>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180956_69e25a9c_5469596.png"/></td>
</tr>
<tr>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/181013_791d92f0_5469596.png"/></td>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/181032_9f0dbbee_5469596.png"/></td>
</tr>
<tr>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/181049_099d0169_5469596.png"/></td>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/181104_914c457a_5469596.png"/></td>
</tr>
</table>
**<font color="#DC143C">前端提供JavaScript和TypeScript双版本后端提供Java8+SpringBoot2.X和Java17+SpringBoot3.X 双版本</font>**。
同时 **<font color="#DC143C">重磅开源</font>** 开源六年来 **<font color="#DC143C">千余家企业验证过且正在使用</font>** 的代码规范: **<font color="#DC143C">《高质量代码思想》、《Vue3规范》、《Java规范》</font>** ,让大家在这浮躁的世界里感受到一股把代码写好的清流!同时又能节省大量时间,减少加班,快乐工作,保持谦逊,保持学习,**<font color="#DC143C">热爱代码,更热爱生活</font>**
### **技术体系**
#### 技术体系
- 前端Vue + Vue-Router + Vuex + ViewUI + vue-enum
- 后端SpringBoot2 + Mybatis-plus + jwt + druid + mysql
- 前端代码规范smart-front-standard -guide大力推荐
- 基于阿里规范之上的后端规范smart-backend-standard-guide大力推荐
- 前端JavaScript/TypeScript + Vue3 + Vite5 + Pinia + Ant Design Vue 4.X
- 移动端uniapp (vue3版本) + uni-ui + 同时支持APP、小程序、H5
- 后端Java8/17 + SpringBoot2/3 + Sa Token + Mybatis-plus + 主流数据库/国产数据库
- 官方文档:[https://smartadmin.vip](https://smartadmin.vip)
- 电脑在线预览:[https://preview.smartadmin.vip](https://preview.smartadmin.vip)
- 移动端在线预览:[https://app.smartadmin.vip](https://app.smartadmin.vip/#/pages/login/login)
### **理念与思想**
#### 前端特点
- 高质量的代码、代码结构、和代码注释
- 漂亮的UI菜单栏、标签页体验、交互更好用的员工、部门、角色、菜单管理等等
- 优化基于Keepalive的标签页做到标签页该缓存的时候缓存比如左右切换等不该缓存的时候不缓存比如新建表单提交结束等
- 前端常量维护: vue-enum拒绝出现魔法数字代码不可维护的现象
- 全新的基于前端的权限设计(忘掉传统的权限设计吧,已经不适合这个前端时代)
- 基于websocket的在线人数
- 支持一级、二级、三级菜单,四级菜单以及搜索功能
- 其他功能:邮件、富文本、消息、系统配置等等
- 写不完了,太多好的细节需要你的发现......
- 我们分享的不是徒劳无功的各种功能,而是必须有的功能,如:数据变动记录、系统说明文档、版本更新记录、意见反馈、日志、心跳、单号生成器等等。
- 我们分享的还有经过上百家公司验证过的前端、后端、vue3等代码规范好的规范能让我敲下的每行代码更铿锵有力
- **我们推崇高质量的代码,身为开发,代码即利剑,键盘上一套行云流水,宛如侠客,事了拂衣去,深藏身与名。**
- **我们推崇团队的高度配合默契、互相帮助,从不加班,而不是一看到别人的代码就头皮发麻,留其 [996.ICU](https://baike.baidu.com/item/996.ICU) 加班。**
- **我们主动思考,保持谦逊,保持学习,热爱代码,更热爱生活。**
- **<font color="#DC143C">我们希望你希望你能花费3分钟认真阅读下面的每一个点让你感受从未有过的技术体验</font>**
#### 后端特点
- 高质量的Java代码、分包结构、和代码注释
- 业内独创的请求返回码维护,非常值得一看
- 基于一个注解和controller的权限设计放弃更复杂的shiro以及一套数据权限支持
- 四层架构controller, service, manager, dao
- 代码阅读性强、扩展性极高的员工、部门、角色、菜单管理
- 基于LRU策略的内存级权限缓存
- 配合前端vue-enum的swagger文档注解
- 心跳服务让你发现有哪些机器再跑哪些人在偷偷的跑你的Job
- 自定义的quartz job添加和修改方便测试人员测试
- smart-reload为系统预留钩子动态加载在不重启程序前提下执行一些代码你懂的
- 以上只是一些举例,更多灿若繁星的惊喜和细节,等待着你的发现!
#### 前端代码规范
- 文件、文件夹、目录结构、组建、变量等等怎么命名
- html、css、less等如何规范
- vue项目目录结构如何划分
- router和store该怎么划分扩展性更好
- vue组件规范该选择哪些
- 以及更多,数不胜数让你觉得实用,同时身心愉悦的规范
#### 后端代码规范
- 四层架构controller, service, manager, dao 是什么,为什么要有四层
- 各个层的代码该怎么写才能让团队配合默契,高度一致
- vo, bo, dto, entity 各种javabean 怎么区分和使用
- spring的 @Transactional 你用对了吗
- 方法参数个数、注释、todo这些也要有规范你遵守过吗
- 以上举例,只是沧海一粟,更多的细节等待你的发现!
ps以上规范基础都是以团队出发让团队开心快乐的写代码而不是为了代码规范而规范不喜勿喷谢谢。
#### 联系我们
[1024创新实验室](https://www.1024lab.net/)
SmartAdmin微信群**加我微信拉你入群!**
### **功能亮点图**
<table>
<tr>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/181125_2ab89aa9_5469596.jpeg"/></td>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/login/login-bg.png"/></td>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/cut/home.png"/></td>
</tr>
</table>
#### 捐赠
开源不易,感谢捐赠
>*佛祖保佑捐赠这些人写程序永无bug工资翻倍迎娶白富美走上人生巅峰*
<table>
<tr>
<td><img src="https://images.gitee.com/uploads/images/2020/1208/181143_b6804a87_5469596.jpeg"/></td>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/login/login-fail-log.png"/></td>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/cut/doc.png"/></td>
</tr>
<tr>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/cut/code.png"/></td>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/cut/git-diff.png"/></td>
</tr>
<tr>
<td><img src="https://img.smartadmin.1024lab.net/smart-app/app1.png"/></td>
<td><img src="https://img.smartadmin.1024lab.net/smart-app/app2.png"/></td>
</tr>
<tr>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/cut/front.png"/></td>
<td><img src="https://img.smartadmin.1024lab.net/smart-admin-v3/cut/back.png"/></td>
</tr>
</table>
---
作者简介:
[卓大](https://zhuoluodada.cn) 1024创新实验室主任混迹于各个技术圈研究过计算机熟悉点java略懂点前端。
### **功能亮点**
- **<font color="#DC143C">安全体系</font>**:满足国家三级等保要求,如双因子登录、密码加密、密码复杂度要求、登录错误次数锁定、登录超时退出、数据脱敏等网络安全和数据安全功能
- **<font color="#DC143C">接口加解密</font>**:支持请求参数和返回内容进行加解密操作,支持国产加密算法和其他国外加密算法
- **表格自定义列**:支持用户自定义列,并能将用户自定义列持久化到数据库
- **数据变更记录**支持基于git diff插件的数据变更记录查看数据变化更直观方便
- **在线文档**:支持右侧帮助文档(类似阿里云控制台右侧帮助文档效果)、支持意见反馈、版本记录 等功能
- **OA办公**:公司信息(发票、银行、员工等)、通知公告(阅读记录、次数等)
- **日志、监控**服务器心跳日志、登录日志、操作日志IP、浏览器、操作系统等设备信息
- **系统功能**:员工、部门、角色、权限、菜单、水印、文件管理、系统参数、数据字典、单号生成 等
- **代码生成** 基于每个表的配置、在线预览代码、下载 等
- **以上只是一些举例,更多灿若繁星的惊喜和细节,等待着你的发现!**[SmartAdmin 业内独有功能亮点](https://smartadmin.vip)
### **代码亮点**
- **【前端-双版本】:** 提供 js 和 ts 双版本,目录结构及其清晰
- **【前端-常量维护】:** vue-enum拒绝出现魔法数字常量枚举不可维护的现象
- **【前端-命名】:** 业内最好的api、常量等命名和写法
- **【前端-多环境支持】:** 独有的本地、开发、测试、预发布、生产 5个env环境配置文件
- **【前端-layout代码】** 业内代码最清晰的layout布局写法小白都能看懂
- **【前端-main.js】** 业内可能只有我们把main.js中的router加载方式写对了
- ----华丽前后端分割线----
- **【后端-独有目录结构】:** 业内独有的高质量的 Java代码分包结构适合大、中、小型项目结构非常清晰
- **【后端-公共配置文件】:** 业内独有的共用配置文件维护,简化共同配置
- **【后端-返回码维护】:** 业内独创的请求返回码维护,非常值得一看
- **【后端-四层架构】:** 四层架构controller, service, manager, dao为什么要有四层
- **【后端-多环境】:** maven多环境开发、测试、预发布、生产 环境配置
- **【后端-系统钩子】:** smart-reload为系统预留钩子动态加载在不重启程序前提下执行一些代码
- 以上只是沧海一粟,更多的细节等待你的发现![去查看](https://smartadmin.vip)

View File

@ -0,0 +1,420 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.lab1024</groupId>
<artifactId>sa-parent</artifactId>
<version>3.0.0</version>
<packaging>pom</packaging>
<name>sa-parent</name>
<description>SmartAdmin project</description>
<modules>
<module>sa-base</module>
<module>sa-admin</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>17</java.version>
<springboot.version>3.5.4</springboot.version>
<spring-security-crypto.version>6.5.1</spring-security-crypto.version>
<mybatis-plus.version>3.5.12</mybatis-plus.version>
<p6spy.version>3.9.1</p6spy.version>
<springdoc-openapi.version>2.8.9</springdoc-openapi.version>
<knife4j.version>4.6.0</knife4j.version>
<fastjson.version>2.0.57</fastjson.version>
<druid.version>1.2.25</druid.version>
<google-linkedhashmap.version>1.4.2</google-linkedhashmap.version>
<google-guava.version>20.0</google-guava.version>
<reflections.version>0.10.2</reflections.version>
<commons-io.version>2.19.0</commons-io.version>
<commons-lang3.version>3.18.0</commons-lang3.version>
<commons-collections4.version>4.5.0</commons-collections4.version>
<commons-compress.version>1.27.1</commons-compress.version>
<commons-codec.version>1.18.0</commons-codec.version>
<commons-text.version>1.13.1</commons-text.version>
<fast-excel.version>1.2.0</fast-excel.version>
<poi.version>5.4.1</poi.version>
<awssdk-s3.version>2.31.78</awssdk-s3.version>
<mysql-connector-j.version>9.3.0</mysql-connector-j.version>
<hutool.version>5.8.39</hutool.version>
<velocity-engine-core.version>2.4.1</velocity-engine-core.version>
<velocity-tools.version>3.1</velocity-tools.version>
<sa-token.version>1.44.0</sa-token.version>
<ip2region.version>2.7.0</ip2region.version>
<bcprov.version>1.80</bcprov.version>
<smartdb.version>1.2.0</smartdb.version>
<redisson.version>3.50.0</redisson.version>
<snakeyaml.version>2.4</snakeyaml.version>
<freemarker.version>2.3.34</freemarker.version>
<jsoup.version>1.21.1</jsoup.version>
<tika.version>3.1.0</tika.version>
<httpcomponents.version>5.5</httpcomponents.version>
</properties>
<dependencyManagement>
<dependencies>
<!--SpringBoot BOM begin-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--SpringBoot BOM end-->
<!--mybatis-plus BOM begin-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-bom</artifactId>
<version>${mybatis-plus.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--mybatis-plus BOM end-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>${spring-security-crypto.version}</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>${mysql-connector-j.version}</version>
</dependency>
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>${p6spy.version}</version>
</dependency>
<dependency>
<groupId>com.github.xingfudeshi</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>com.googlecode.concurrentlinkedhashmap</groupId>
<artifactId>concurrentlinkedhashmap-lru</artifactId>
<version>${google-linkedhashmap.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${google-guava.version}</version>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>${reflections.version}</version>
<exclusions>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>${commons-collections4.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>${commons-compress.version}</version>
</dependency>
<dependency>
<artifactId>commons-codec</artifactId>
<groupId>commons-codec</groupId>
<version>${commons-codec.version}</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>${awssdk-s3.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>${commons-text.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<!--velocity begin-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>${velocity-engine-core.version}</version>
</dependency>
<dependency>
<groupId>org.apache.velocity.tools</groupId>
<artifactId>velocity-tools-generic</artifactId>
<version>${velocity-tools.version}</version>
</dependency>
<!--velocity end-->
<!-- Sa-Token 权限认证在线文档https://sa-token.cc -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot3-starter</artifactId>
<version>${sa-token.version}</version>
</dependency>
<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-redis-jackson</artifactId>
<version>${sa-token.version}</version>
</dependency>
<!-- sa-token end -->
<!--ip 地址-->
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>${ip2region.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>${bcprov.version}</version>
</dependency>
<dependency>
<groupId>cn.idev.excel</groupId>
<artifactId>fastexcel</artifactId>
<version>${fast-excel.version}</version>
<exclusions>
<exclusion>
<artifactId>logback-classic</artifactId>
<groupId>ch.qos.logback</groupId>
</exclusion>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-full</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>net.1024lab</groupId>
<artifactId>smartdb</artifactId>
<version>${smartdb.version}</version>
</dependency>
<!-- redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>${redisson.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</exclusion>
<exclusion>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-32</artifactId>
</exclusion>
<exclusion>
<artifactId>objenesis</artifactId>
<groupId>org.objenesis</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-27</artifactId>
<version>${redisson.version}</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>${snakeyaml.version}</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>${tika.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>${httpcomponents.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>${project.name}-${profiles.active}-${project.version}</finalName>
<resources>
<resource>
<filtering>false</filtering>
<directory>src/main/resources</directory>
<excludes>
<exclude>dev/*</exclude>
<exclude>test/*</exclude>
<exclude>pre/*</exclude>
<exclude>prod/*</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources/${profiles.active}</directory>
<filtering>true</filtering>
<includes>
<include>*.yaml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources/${profiles.active}</directory>
<filtering>false</filtering>
<includes>
<include>*.*</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<compilerArgument>-parameters</compilerArgument>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${springboot.version}</version>
</plugin>
</plugins>
</build>
<profiles>
<!--开发环境-->
<profile>
<id>dev</id>
<properties>
<profiles.active>dev</profiles.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!--测试环境-->
<profile>
<id>test</id>
<properties>
<profiles.active>test</profiles.active>
</properties>
</profile>
<!--预发布环境-->
<profile>
<id>pre</id>
<properties>
<profiles.active>pre</profiles.active>
</properties>
</profile>
<!--生产环境-->
<profile>
<id>prod</id>
<properties>
<profiles.active>prod</profiles.active>
</properties>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,47 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.lab1024</groupId>
<artifactId>sa-parent</artifactId>
<version>3.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>sa-admin</artifactId>
<version>3.0.0</version>
<packaging>jar</packaging>
<name>sa-admin</name>
<description>sa-admin project</description>
<dependencies>
<dependency>
<groupId>net.lab1024</groupId>
<artifactId>sa-base</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>net.lab1024.sa.admin.AdminApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,40 @@
package net.lab1024.sa.admin;
import net.lab1024.sa.base.listener.Ip2RegionListener;
import net.lab1024.sa.base.listener.LogVariableListener;
import org.apache.ibatis.annotations.Mapper;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* SmartAdmin 项目启动类
*
* @Author 1024创新实验室-主任:卓大
* @Date 2022-08-29 21:00:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@EnableCaching
@EnableScheduling
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
@ComponentScan(AdminApplication.COMPONENT_SCAN)
@MapperScan(value = AdminApplication.COMPONENT_SCAN, annotationClass = Mapper.class)
@SpringBootApplication(exclude = {UserDetailsServiceAutoConfiguration.class})
public class AdminApplication {
public static final String COMPONENT_SCAN = "net.lab1024.sa";
public static void main(String[] args) {
SpringApplication application = new SpringApplication(AdminApplication.class);
// 添加 日志监听器使 log4j2-spring.xml 可以间接读取到配置文件的属性
application.addListeners(new LogVariableListener(), new Ip2RegionListener());
application.run(args);
}
}

View File

@ -0,0 +1,41 @@
package net.lab1024.sa.admin.config;
import jakarta.annotation.Resource;
import net.lab1024.sa.admin.interceptor.AdminInterceptor;
import net.lab1024.sa.base.config.SwaggerConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* web相关配置
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2021-09-02 20:21:10
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Resource
private AdminInterceptor adminInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(adminInterceptor)
.excludePathPatterns(SwaggerConfig.SWAGGER_WHITELIST)
.addPathPatterns("/**");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}

View File

@ -0,0 +1,28 @@
package net.lab1024.sa.admin.config;
import net.lab1024.sa.base.module.support.operatelog.core.OperateLogAspect;
import net.lab1024.sa.base.module.support.operatelog.core.OperateLogConfig;
import org.springframework.context.annotation.Configuration;
/**
* 操作日志切面 配置
*
* @Author 1024创新实验室: 罗伊
* @Date 2022-05-30 21:22:12
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Configuration
public class OperateLogAspectConfig extends OperateLogAspect{
/**
* 配置信息
*/
@Override
public OperateLogConfig getOperateLogConfig() {
return OperateLogConfig.builder().corePoolSize(1).queueCapacity(10000).build();
}
}

View File

@ -0,0 +1,68 @@
package net.lab1024.sa.admin.constant;
import net.lab1024.sa.base.constant.CacheKeyConst;
/**
* 缓存 key
*
* @Author 1024创新实验室-主任:卓大
* @Date 2022-01-07 18:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
public class AdminCacheConst extends CacheKeyConst {
public static class Department {
/**
* 部门列表
*/
public static final String DEPARTMENT_LIST_CACHE = "department_list_cache";
/**
* 部门树
*/
public static final String DEPARTMENT_TREE_CACHE = "department_tree_cache";
/**
* 某个部门以及下级的id列表
*/
public static final String DEPARTMENT_SELF_CHILDREN_CACHE = "department_self_children_cache";
/**
* 部门路径 缓存
*/
public static final String DEPARTMENT_PATH_CACHE = "department_path_cache";
}
/**
* 分类相关缓存
*/
public static class Category {
public static final String CATEGORY_ENTITY = "category_cache";
public static final String CATEGORY_SUB = "category_sub_cache";
public static final String CATEGORY_TREE = "category_tree_cache";
}
/**
* 登录相关
*/
public static class Login {
/**
* 请求用户信息
*/
public static final String REQUEST_EMPLOYEE = "login_request_employee";
/**
* 请求用户信息权限
*/
public static final String USER_PERMISSION = "login_user_permission";
}
}

View File

@ -0,0 +1,17 @@
package net.lab1024.sa.admin.constant;
import net.lab1024.sa.base.constant.RedisKeyConst;
/**
* redis key 常量类
*
* @Author 1024创新实验室-主任:卓大
* @Date 2022-01-07 18:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
public class AdminRedisKeyConst extends RedisKeyConst {
}

View File

@ -0,0 +1,59 @@
package net.lab1024.sa.admin.constant;
import net.lab1024.sa.base.constant.SwaggerTagConst;
/**
* swagger
*
* @Author 1024创新实验室:罗伊
* @Date 2022-01-07 18:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
public class AdminSwaggerTagConst extends SwaggerTagConst {
public static class Business {
public static final String MANAGER_CATEGORY = "ERP进销存-分类管理";
public static final String MANAGER_GOODS = "ERP进销存-商品管理";
public static final String OA_BANK = "OA办公-银行卡信息";
public static final String OA_ENTERPRISE = "OA办公-企业";
public static final String OA_INVOICE = "OA办公-发票信息";
public static final String OA_NOTICE = "OA办公-通知公告";
}
public static class System {
public static final String SYSTEM_LOGIN = "系统-员工登录";
public static final String SYSTEM_EMPLOYEE = "系统-员工管理";
public static final String SYSTEM_DEPARTMENT = "系统-部门管理";
public static final String SYSTEM_MENU = "系统-菜单";
public static final String SYSTEM_DATA_SCOPE = "系统-系统-数据范围";
public static final String SYSTEM_ROLE = "系统-角色";
public static final String SYSTEM_ROLE_DATA_SCOPE = "系统-角色-数据范围";
public static final String SYSTEM_ROLE_EMPLOYEE = "系统-角色-员工";
public static final String SYSTEM_ROLE_MENU = "系统-角色-菜单";
public static final String SYSTEM_POSITION = "系统-职务管理";
public static final String SYSTEM_MESSAGE = "系统-消息";
}
}

View File

@ -0,0 +1,141 @@
package net.lab1024.sa.admin.interceptor;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.strategy.SaAnnotationStrategy;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.module.system.login.domain.RequestEmployee;
import net.lab1024.sa.admin.module.system.login.service.LoginService;
import net.lab1024.sa.base.common.annoation.NoNeedLogin;
import net.lab1024.sa.base.common.code.SystemErrorCode;
import net.lab1024.sa.base.common.code.UserErrorCode;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartRequestUtil;
import net.lab1024.sa.base.common.util.SmartResponseUtil;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import java.lang.reflect.Method;
/**
* admin 拦截器
*
* @Author 1024创新实验室-主任:卓大
* @Date 2023/7/26 20:20:33
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>Since 2012
*/
@Component
@Slf4j
public class AdminInterceptor implements HandlerInterceptor {
@Resource
private LoginService loginService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// OPTIONS请求直接return
if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
response.setStatus(HttpStatus.NO_CONTENT.value());
return false;
}
boolean isHandler = handler instanceof HandlerMethod;
if (!isHandler) {
return true;
}
try {
// --------------- 第一步 根据token 获取用户 ---------------
String tokenValue = StpUtil.getTokenValue();
String loginId = (String) StpUtil.getLoginIdByToken(tokenValue);
RequestEmployee requestEmployee = loginService.getLoginEmployee(loginId, request);
// --------------- 第二步 校验 登录 ---------------
Method method = ((HandlerMethod) handler).getMethod();
NoNeedLogin noNeedLogin = ((HandlerMethod) handler).getMethodAnnotation(NoNeedLogin.class);
if (noNeedLogin != null) {
updateActiveTimeout(requestEmployee);
SmartRequestUtil.setRequestUser(requestEmployee);
return true;
}
if (requestEmployee == null) {
SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID));
return false;
}
// 更新活跃
updateActiveTimeout(requestEmployee);
// --------------- 第三步 校验 权限 ---------------
SmartRequestUtil.setRequestUser(requestEmployee);
if (SaAnnotationStrategy.instance.isAnnotationPresent.apply(method, SaIgnore.class)) {
return true;
}
// 如果是超级管理员的话不需要校验权限
if (requestEmployee.getAdministratorFlag()) {
return true;
}
SaAnnotationStrategy.instance.checkMethodAnnotation.accept(method);
} catch (SaTokenException e) {
/*
* sa-token 异常状态码
* 具体请看 https://sa-token.cc/doc.html#/fun/exception-code
*/
int code = e.getCode();
if (code == 11041 || code == 11051) {
SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.NO_PERMISSION));
} else if (code == 11016) {
SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.LOGIN_ACTIVE_TIMEOUT));
} else if (code >= 11011 && code <= 11015) {
SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID));
} else {
SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.PARAM_ERROR));
}
return false;
} catch (Throwable e) {
SmartResponseUtil.write(response, ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR));
log.error(e.getMessage(), e);
return false;
}
// 通过验证
return true;
}
/**
* 更新活跃时间
*/
private void updateActiveTimeout(RequestEmployee requestEmployee) {
if (requestEmployee == null) {
return;
}
StpUtil.updateLastActiveToNow();
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 清除上下文
SmartRequestUtil.remove();
}
}

View File

@ -0,0 +1,36 @@
package net.lab1024.sa.admin.module.business.category.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.lab1024.sa.base.common.enumeration.BaseEnum;
/**
* 分类类型 枚举
*
* @Author 1024创新实验室: 胡克
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@AllArgsConstructor
@Getter
public enum CategoryTypeEnum implements BaseEnum {
/**
* 1 商品
*/
GOODS(1, "商品"),
/**
* 2 自定义
*/
CUSTOM(2, "自定义"),
;
private final Integer value;
private final String desc;
}

View File

@ -0,0 +1,69 @@
package net.lab1024.sa.admin.module.business.category.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
import net.lab1024.sa.admin.module.business.category.domain.form.CategoryAddForm;
import net.lab1024.sa.admin.module.business.category.domain.form.CategoryTreeQueryForm;
import net.lab1024.sa.admin.module.business.category.domain.form.CategoryUpdateForm;
import net.lab1024.sa.admin.module.business.category.domain.vo.CategoryTreeVO;
import net.lab1024.sa.admin.module.business.category.domain.vo.CategoryVO;
import net.lab1024.sa.admin.module.business.category.service.CategoryService;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 类目
*
* @Author 1024创新实验室: 胡克
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@RestController
@Tag(name = AdminSwaggerTagConst.Business.MANAGER_CATEGORY)
public class CategoryController {
@Resource
private CategoryService categoryService;
@Operation(summary = "添加类目 @author 胡克")
@PostMapping("/category/add")
@SaCheckPermission("category:add")
public ResponseDTO<String> add(@RequestBody @Valid CategoryAddForm addForm) {
return categoryService.add(addForm);
}
@Operation(summary = "更新类目 @author 胡克")
@PostMapping("/category/update")
@SaCheckPermission("category:update")
public ResponseDTO<String> update(@RequestBody @Valid CategoryUpdateForm updateForm) {
return categoryService.update(updateForm);
}
@Operation(summary = "查询类目详情 @author 胡克")
@GetMapping("/category/{categoryId}")
public ResponseDTO<CategoryVO> queryDetail(@PathVariable Long categoryId) {
return categoryService.queryDetail(categoryId);
}
@Operation(summary = "查询类目层级树 @author 胡克")
@PostMapping("/category/tree")
@SaCheckPermission("category:tree")
public ResponseDTO<List<CategoryTreeVO>> queryTree(@RequestBody @Valid CategoryTreeQueryForm queryForm) {
return categoryService.queryTree(queryForm);
}
@Operation(summary = "删除类目 @author 胡克")
@GetMapping("/category/delete/{categoryId}")
@SaCheckPermission("category:delete")
public ResponseDTO<String> delete(@PathVariable Long categoryId) {
return categoryService.delete(categoryId);
}
}

View File

@ -0,0 +1,62 @@
package net.lab1024.sa.admin.module.business.category.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum;
import net.lab1024.sa.admin.module.business.category.domain.entity.CategoryEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 类目 dao
*
* @Author 1024创新实验室: 胡克
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Mapper
public interface CategoryDao extends BaseMapper<CategoryEntity> {
/**
* 根据父级id 类型 查询子类
*
* @param parentIdList 父级id集合
* @param deletedFlag 删除标识
* @return 列表
*/
List<CategoryEntity> queryByParentId(@Param("parentIdList") List<Long> parentIdList,
@Param("deletedFlag") Boolean deletedFlag);
/**
* 根据父级id 类型 查询子类
*
* @param parentIdList 父级id集合
* @param categoryType {@link CategoryTypeEnum}
* @param deletedFlag 删除标识
* @return 列表
*/
List<CategoryEntity> queryByParentIdAndType(@Param("parentIdList") List<Long> parentIdList,
@Param("categoryType") Integer categoryType,
@Param("deletedFlag") Boolean deletedFlag);
/**
* 某个类型的所有
*/
List<CategoryEntity> queryByType(@Param("categoryType") Integer categoryType,
@Param("deletedFlag") Boolean deletedFlag);
/**
* 根据类型和id查询
*/
CategoryEntity selectByTypeAndId(@Param("categoryType") Integer categoryType, @Param("categoryId") Long categoryId);
/**
* 查看类目 具体条件 看sql
*/
CategoryEntity selectOne(CategoryEntity entity);
}

View File

@ -0,0 +1,43 @@
package net.lab1024.sa.admin.module.business.category.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum;
import net.lab1024.sa.base.common.swagger.SchemaEnum;
import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;
import org.hibernate.validator.constraints.Length;
/**
* 类目 基础属性 DTO
*
* @author 胡克
* @date 2021/1/20 16:17
*/
@Data
public class CategoryBaseDTO {
@Schema(description = "类目名称", required = true)
@NotBlank(message = "类目名称不能为空")
@Length(max = 20, message = "类目名称最多20字符")
private String categoryName;
@SchemaEnum(desc = "分类类型", value = CategoryTypeEnum.class)
@CheckEnum(value = CategoryTypeEnum.class, required = true, message = "分类错误")
private Integer categoryType;
@Schema(description = "父级类目id|可选")
private Long parentId;
@Schema(description = "排序|可选")
private Integer sort;
@Schema(description = "备注|可选")
@Length(max = 200, message = "备注最多200字符")
private String remark;
@Schema(description = "禁用状态")
@NotNull(message = "禁用状态不能为空")
private Boolean disabledFlag;
}

View File

@ -0,0 +1,26 @@
package net.lab1024.sa.admin.module.business.category.domain.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 类目 基础属性 DTO
*
* @author 胡克
* @date 2021/1/20 16:17
*/
@Data
public class CategorySimpleDTO {
@Schema(description = "类目id")
private Long categoryId;
@Schema(description = "类目名称")
private String categoryName;
@Schema(description = "类目层级全称")
private String categoryFullName;
@Schema(description = "父级id")
private Long parentId;
}

View File

@ -0,0 +1,70 @@
package net.lab1024.sa.admin.module.business.category.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 类目 实体类
*
* @Author 1024创新实验室: 胡克
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
@TableName("t_category")
public class CategoryEntity implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(type = IdType.AUTO)
private Long categoryId;
/**
* 类目名称
*/
private String categoryName;
/**
* 类目 类型
*
* @see CategoryTypeEnum
*/
private Integer categoryType;
/**
* 父级类目id
*/
private Long parentId;
/**
* 是否禁用
*/
private Boolean disabledFlag;
/**
* 排序
*/
private Integer sort;
/**
* 删除状态
*/
private Boolean deletedFlag;
/**
* 备注
*/
private String remark;
private LocalDateTime updateTime;
private LocalDateTime createTime;
}

View File

@ -0,0 +1,47 @@
package net.lab1024.sa.admin.module.business.category.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum;
import net.lab1024.sa.base.common.swagger.SchemaEnum;
import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;
import org.hibernate.validator.constraints.Length;
/**
* 类目 添加
*
* @Author 1024创新实验室: 胡克
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class CategoryAddForm {
@Schema(description = "类目名称", required = true)
@NotBlank(message = "类目名称不能为空")
@Length(max = 20, message = "类目名称最多20字符")
private String categoryName;
@SchemaEnum(desc = "分类类型", value = CategoryTypeEnum.class)
@CheckEnum(value = CategoryTypeEnum.class, required = true, message = "分类错误")
private Integer categoryType;
@Schema(description = "父级类目id|可选")
private Long parentId;
@Schema(description = "排序|可选")
private Integer sort;
@Schema(description = "备注|可选")
@Length(max = 200, message = "备注最多200字符")
private String remark;
@Schema(description = "禁用状态")
@NotNull(message = "禁用状态不能为空")
private Boolean disabledFlag;
}

View File

@ -0,0 +1,25 @@
package net.lab1024.sa.admin.module.business.category.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum;
import net.lab1024.sa.base.common.swagger.SchemaEnum;
/**
* 类目 层级树查询
*
* @Author 1024创新实验室: 胡克
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class CategoryTreeQueryForm {
@SchemaEnum(desc = "分类类型|可选", value = CategoryTypeEnum.class)
private Integer categoryType;
@Schema(description = "父级类目id|可选")
private Long parentId;
}

View File

@ -0,0 +1,22 @@
package net.lab1024.sa.admin.module.business.category.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* 类目 更新
*
* @Author 1024创新实验室: 胡克
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class CategoryUpdateForm extends CategoryAddForm {
@Schema(description = "类目id")
@NotNull(message = "类目id不能为空")
private Long categoryId;
}

View File

@ -0,0 +1,43 @@
package net.lab1024.sa.admin.module.business.category.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 类目 层级树 vo
*
* @Author 1024创新实验室: 胡克
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class CategoryTreeVO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "类目id")
private Long categoryId;
@Schema(description = "类目名称")
private String categoryName;
@Schema(description = "类目层级全称")
private String categoryFullName;
@Schema(description = "父级id")
private Long parentId;
@Schema(description = "类目id")
private Long value;
@Schema(description = "类目名称")
private String label;
@Schema(description = "子类")
private List<CategoryTreeVO> children;
}

View File

@ -0,0 +1,46 @@
package net.lab1024.sa.admin.module.business.category.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum;
import net.lab1024.sa.base.common.swagger.SchemaEnum;
import java.time.LocalDateTime;
/**
* 类目
*
* @Author 1024创新实验室: 胡克
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class CategoryVO {
@Schema(description = "类目名称", required = true)
private String categoryName;
@SchemaEnum(desc = "分类类型", value = CategoryTypeEnum.class)
private Integer categoryType;
@Schema(description = "父级类目id|可选")
private Long parentId;
@Schema(description = "排序|可选")
private Integer sort;
@Schema(description = "备注|可选")
private String remark;
@Schema(description = "禁用状态")
private Boolean disabledFlag;
@Schema(description = "类目id")
private Long categoryId;
private LocalDateTime updateTime;
private LocalDateTime createTime;
}

View File

@ -0,0 +1,113 @@
package net.lab1024.sa.admin.module.business.category.manager;
import com.google.common.collect.Lists;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.constant.AdminCacheConst;
import net.lab1024.sa.admin.module.business.category.dao.CategoryDao;
import net.lab1024.sa.admin.module.business.category.domain.entity.CategoryEntity;
import net.lab1024.sa.admin.module.business.category.domain.vo.CategoryTreeVO;
import net.lab1024.sa.base.common.constant.StringConst;
import net.lab1024.sa.base.common.util.SmartBeanUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 类目 查询 缓存
*
* @Author 1024创新实验室: 胡克
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Service
@Slf4j
public class CategoryCacheManager {
@Resource
private CategoryDao categoryDao;
/**
* 根据类目id 移除缓存
*/
@CacheEvict(value = {AdminCacheConst.Category.CATEGORY_ENTITY, AdminCacheConst.Category.CATEGORY_SUB, AdminCacheConst.Category.CATEGORY_TREE}, allEntries = true)
public void removeCache() {
log.info("clear CATEGORY ,CATEGORY_SUB ,CATEGORY_TREE");
}
/**
* 查詢类目
*
*/
@Cacheable(AdminCacheConst.Category.CATEGORY_ENTITY)
public CategoryEntity queryCategory(Long categoryId) {
return categoryDao.selectById(categoryId);
}
/**
* 查询类目 子级
*
*/
@Cacheable(AdminCacheConst.Category.CATEGORY_SUB)
public List<CategoryEntity> querySubCategory(Long categoryId) {
return categoryDao.queryByParentId(Lists.newArrayList(categoryId), false);
}
/**
* 查询类目 层级树
* 优先查询缓存
*/
@Cacheable(AdminCacheConst.Category.CATEGORY_TREE)
public List<CategoryTreeVO> queryCategoryTree(Long parentId, Integer categoryType) {
List<CategoryEntity> allCategoryEntityList = categoryDao.queryByType(categoryType, false);
List<CategoryEntity> categoryEntityList = allCategoryEntityList.stream().filter(e -> e.getParentId().equals(parentId)).collect(Collectors.toList());
List<CategoryTreeVO> treeList = SmartBeanUtil.copyList(categoryEntityList, CategoryTreeVO.class);
treeList.forEach(e -> {
e.setLabel(e.getCategoryName());
e.setValue(e.getCategoryId());
e.setCategoryFullName(e.getCategoryName());
});
// 递归设置子类
this.queryAndSetSubCategory(treeList, allCategoryEntityList);
return treeList;
}
/**
* 递归查询设置类目子类
* 从缓存查询子类
*
*/
private void queryAndSetSubCategory(List<CategoryTreeVO> treeList, List<CategoryEntity> allCategoryEntityList) {
if (CollectionUtils.isEmpty(treeList)) {
return;
}
List<Long> parentIdList = treeList.stream().map(CategoryTreeVO::getValue).collect(Collectors.toList());
List<CategoryEntity> categoryEntityList = allCategoryEntityList.stream().filter(e -> parentIdList.contains(e.getParentId())).collect(Collectors.toList());
Map<Long, List<CategoryEntity>> categorySubMap = categoryEntityList.stream().collect(Collectors.groupingBy(CategoryEntity::getParentId));
treeList.forEach(e -> {
List<CategoryEntity> childrenEntityList = categorySubMap.getOrDefault(e.getValue(), Lists.newArrayList());
List<CategoryTreeVO> childrenVOList = SmartBeanUtil.copyList(childrenEntityList, CategoryTreeVO.class);
childrenVOList.forEach(item -> {
item.setLabel(item.getCategoryName());
item.setValue(item.getCategoryId());
item.setCategoryFullName(e.getCategoryFullName() + StringConst.SEPARATOR_SLASH + item.getCategoryName());
});
// 递归查询
this.queryAndSetSubCategory(childrenVOList, allCategoryEntityList);
e.setChildren(childrenVOList);
});
}
}

View File

@ -0,0 +1,188 @@
package net.lab1024.sa.admin.module.business.category.service;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.module.business.category.domain.dto.CategorySimpleDTO;
import net.lab1024.sa.admin.module.business.category.domain.entity.CategoryEntity;
import net.lab1024.sa.admin.module.business.category.manager.CategoryCacheManager;
import net.lab1024.sa.base.common.constant.StringConst;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 类目 查询 业务类
*
* @Author 1024创新实验室: 胡克
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Service
@Slf4j
public class CategoryQueryService {
private static final Long DEFAULT_CATEGORY_PARENT_ID = 0L;
@Resource
private CategoryCacheManager categoryCacheManager;
/**
* 根据 id 查询未删除的类目
*
* @param categoryId
* @return 可能 null
*/
public Optional<CategoryEntity> queryCategory(Long categoryId) {
if (null == categoryId) {
return Optional.empty();
}
CategoryEntity entity = categoryCacheManager.queryCategory(categoryId);
if (null == entity || entity.getDeletedFlag()) {
return Optional.empty();
}
return Optional.of(entity);
}
/**
* 根据 类目id集合 查询未删除的类目集合
*/
public Map<Long, CategoryEntity> queryCategoryList(List<Long> categoryIdList) {
if (CollectionUtils.isEmpty(categoryIdList)) {
return Collections.emptyMap();
}
categoryIdList = categoryIdList.stream().distinct().collect(Collectors.toList());
Map<Long, CategoryEntity> categoryEntityMap = Maps.newHashMap();
for (Long categoryId : categoryIdList) {
CategoryEntity categoryEntity = categoryCacheManager.queryCategory(categoryId);
if (categoryEntity != null) {
categoryEntityMap.put(categoryId, categoryEntity);
}
}
return categoryEntityMap;
}
/**
* 根据类目id 递归查询该id的所有子类id 递归查询
* 同时存入缓存
* 注意查询出来的集合 不包含传递的父类参数
*/
public List<Long> queryCategorySubId(List<Long> categoryIdList) {
if (CollectionUtils.isEmpty(categoryIdList)) {
return Collections.emptyList();
}
//所有子类
List<CategoryEntity> categoryEntityList = Lists.newArrayList();
categoryIdList.forEach(e -> {
categoryEntityList.addAll(categoryCacheManager.querySubCategory(e));
});
Map<Long, List<CategoryEntity>> subTypeMap = categoryEntityList.stream().collect(Collectors.groupingBy(CategoryEntity::getCategoryId));
// 递归查询子类
categoryIdList = subTypeMap.values().stream().flatMap(Collection::stream).map(CategoryEntity::getCategoryId).distinct().collect(Collectors.toList());
if (CollectionUtils.isEmpty(categoryIdList)) {
return Lists.newArrayList();
}
categoryIdList.addAll(this.queryCategorySubId(categoryIdList));
return categoryIdList;
}
/**
* 处理类目名称
*/
public List<String> queryCategoryName(List<Long> categoryIdList) {
if (CollectionUtils.isEmpty(categoryIdList)) {
return null;
}
Map<Long, CategoryEntity> categoryMap = this.queryCategoryList(categoryIdList);
List<String> categoryNameList = Lists.newArrayList();
categoryIdList.forEach(e -> {
CategoryEntity categoryEntity = categoryMap.get(e);
if (categoryEntity != null) {
categoryNameList.add(categoryMap.get(e).getCategoryName());
}
});
return categoryNameList;
}
/**
* 根据类目id 查询类目名称
*/
public String queryCategoryName(Long categoryId) {
CategoryEntity categoryEntity = categoryCacheManager.queryCategory(categoryId);
if (null == categoryEntity || categoryEntity.getDeletedFlag()) {
return null;
}
return categoryEntity.getCategoryName();
}
/**
* 根据类目id 查询类目详情 包含类目全称 医考/医师资格/临床执业
*/
public CategorySimpleDTO queryCategoryInfo(Long categoryId) {
CategoryEntity categoryEntity = categoryCacheManager.queryCategory(categoryId);
if (null == categoryEntity || categoryEntity.getDeletedFlag()) {
return null;
}
String fullName = this.queryFullName(categoryId);
// 返回DTO
CategorySimpleDTO categoryDTO = new CategorySimpleDTO();
categoryDTO.setCategoryId(categoryId);
categoryDTO.setCategoryName(categoryEntity.getCategoryName());
categoryDTO.setCategoryFullName(fullName);
categoryDTO.setParentId(categoryEntity.getParentId());
return categoryDTO;
}
/**
* 递归查询分类和所有父级类目
* ps:特别注意返回的集合中 包含自己
*/
public List<CategoryEntity> queryCategoryAndParent(Long categoryId) {
List<CategoryEntity> parentCategoryList = Lists.newArrayList();
CategoryEntity categoryEntity = categoryCacheManager.queryCategory(categoryId);
if (null == categoryEntity || categoryEntity.getDeletedFlag()) {
return parentCategoryList;
}
// 父级始终放在第一位
parentCategoryList.add(0, categoryEntity);
Long parentId = categoryEntity.getParentId();
if (Objects.equals(DEFAULT_CATEGORY_PARENT_ID, parentId)) {
return parentCategoryList;
}
parentCategoryList.addAll(0, this.queryCategoryAndParent(parentId));
return parentCategoryList;
}
/**
* 查询 分类全称 医考/医师资格/临床执业
*/
public String queryFullName(Long categoryId) {
List<CategoryEntity> parentCategoryList = this.queryCategoryAndParent(categoryId);
// 拼接父级类目名称 斜杠分隔返回
List<String> nameList = parentCategoryList.stream().map(CategoryEntity::getCategoryName).collect(Collectors.toList());
return StrUtil.join(StringConst.SEPARATOR_SLASH, nameList);
}
/**
* 查询 分类全称 医考/医师资格/临床执业
*/
public Map<Long, String> queryFullName(List<Long> categoryIdList) {
if (CollectionUtils.isEmpty(categoryIdList)) {
return Maps.newHashMap();
}
// 循环内查询的缓存 还ok
return categoryIdList.stream().collect(Collectors.toMap(Function.identity(), this::queryFullName));
}
}

View File

@ -0,0 +1,206 @@
package net.lab1024.sa.admin.module.business.category.service;
import com.google.common.collect.Lists;
import jakarta.annotation.Resource;
import net.lab1024.sa.admin.module.business.category.dao.CategoryDao;
import net.lab1024.sa.admin.module.business.category.domain.entity.CategoryEntity;
import net.lab1024.sa.admin.module.business.category.domain.form.CategoryAddForm;
import net.lab1024.sa.admin.module.business.category.domain.form.CategoryTreeQueryForm;
import net.lab1024.sa.admin.module.business.category.domain.form.CategoryUpdateForm;
import net.lab1024.sa.admin.module.business.category.domain.vo.CategoryTreeVO;
import net.lab1024.sa.admin.module.business.category.domain.vo.CategoryVO;
import net.lab1024.sa.admin.module.business.category.manager.CategoryCacheManager;
import net.lab1024.sa.base.common.code.UserErrorCode;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartBeanUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
* 类目
*
* @Author 1024创新实验室: 胡克
* @Date 2021/08/05 21:26:58
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Service
public class CategoryService {
@Resource
private CategoryDao categoryDao;
@Resource
private CategoryQueryService categoryQueryService;
@Resource
private CategoryCacheManager categoryCacheManager;
/**
* 添加类目
*/
public ResponseDTO<String> add(CategoryAddForm addForm) {
// 校验类目
CategoryEntity categoryEntity = SmartBeanUtil.copy(addForm, CategoryEntity.class);
ResponseDTO<String> res = this.checkCategory(categoryEntity, false);
if (!res.getOk()) {
return res;
}
// 没有父类则使用默认父类
Long parentId = null == addForm.getParentId() ? NumberUtils.LONG_ZERO : addForm.getParentId();
categoryEntity.setParentId(parentId);
categoryEntity.setSort(null == addForm.getSort() ? 0 : addForm.getSort());
categoryEntity.setDeletedFlag(false);
// 保存数据
categoryDao.insert(categoryEntity);
// 更新缓存
categoryCacheManager.removeCache();
return ResponseDTO.ok();
}
/**
* 更新类目
* 不能更新父级类目
*
*/
public ResponseDTO<String> update(CategoryUpdateForm updateForm) {
// 校验类目
Long categoryId = updateForm.getCategoryId();
Optional<CategoryEntity> optional = categoryQueryService.queryCategory(categoryId);
if (!optional.isPresent()) {
return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
}
CategoryEntity categoryEntity = SmartBeanUtil.copy(updateForm, CategoryEntity.class);
/*
不更新类目类型
不更新父类id
*/
Integer categoryType = optional.get().getCategoryType();
categoryEntity.setCategoryType(categoryType);
categoryEntity.setParentId(optional.get().getParentId());
ResponseDTO<String> responseDTO = this.checkCategory(categoryEntity, true);
if (!responseDTO.getOk()) {
return responseDTO;
}
categoryDao.updateById(categoryEntity);
// 更新缓存
categoryCacheManager.removeCache();
return ResponseDTO.ok();
}
/**
* 新增/更新 类目时的 校验
*
*/
private ResponseDTO<String> checkCategory(CategoryEntity categoryEntity, boolean isUpdate) {
// 校验父级是否存在
Long parentId = categoryEntity.getParentId();
Integer categoryType = categoryEntity.getCategoryType();
if (null != parentId) {
if (Objects.equals(categoryEntity.getCategoryId(), parentId)) {
return ResponseDTO.userErrorParam("父级类目怎么和自己相同了");
}
if (!Objects.equals(parentId, NumberUtils.LONG_ZERO)) {
Optional<CategoryEntity> optional = categoryQueryService.queryCategory(parentId);
if (!optional.isPresent()) {
return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST, "父级类目不存在~");
}
CategoryEntity parent = optional.get();
if (!Objects.equals(categoryType, parent.getCategoryType())) {
return ResponseDTO.userErrorParam("与父级类目类型不一致");
}
}
} else {
// 如果没有父类 使用默认父类
parentId = NumberUtils.LONG_ZERO;
}
// 校验同父类下 名称是否重复
CategoryEntity queryEntity = new CategoryEntity();
queryEntity.setParentId(parentId);
queryEntity.setCategoryType(categoryType);
queryEntity.setCategoryName(categoryEntity.getCategoryName());
queryEntity.setDeletedFlag(false);
queryEntity = categoryDao.selectOne(queryEntity);
if (null != queryEntity) {
if (isUpdate) {
if (!Objects.equals(queryEntity.getCategoryId(), categoryEntity.getCategoryId())) {
return ResponseDTO.userErrorParam("同级下已存在相同类目~");
}
} else {
return ResponseDTO.userErrorParam("同级下已存在相同类目~");
}
}
return ResponseDTO.ok();
}
/**
* 查询 类目详情
*
*/
public ResponseDTO<CategoryVO> queryDetail(Long categoryId) {
Optional<CategoryEntity> optional = categoryQueryService.queryCategory(categoryId);
if (!optional.isPresent()) {
return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
}
CategoryVO adminVO = SmartBeanUtil.copy(optional.get(), CategoryVO.class);
return ResponseDTO.ok(adminVO);
}
/**
* 根据父级id 查询所有子类 返回层级树
* 如果父类id 为空 返回所有类目层级
*
*/
public ResponseDTO<List<CategoryTreeVO>> queryTree(CategoryTreeQueryForm queryForm) {
if (null == queryForm.getParentId()) {
if (null == queryForm.getCategoryType()) {
return ResponseDTO.userErrorParam("类目类型不能为空");
}
queryForm.setParentId(NumberUtils.LONG_ZERO);
}
List<CategoryTreeVO> treeList = categoryCacheManager.queryCategoryTree(queryForm.getParentId(), queryForm.getCategoryType());
return ResponseDTO.ok(treeList);
}
/**
* 删除类目
* 如果有未删除的子类 则无法删除
*
*/
public ResponseDTO<String> delete(Long categoryId) {
Optional<CategoryEntity> optional = categoryQueryService.queryCategory(categoryId);
if (!optional.isPresent()) {
return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
}
List<Long> categorySubId = categoryQueryService.queryCategorySubId(Lists.newArrayList(categoryId));
if (CollectionUtils.isNotEmpty(categorySubId)) {
return ResponseDTO.userErrorParam("请先删除子级类目");
}
// 更新数据
CategoryEntity categoryEntity = new CategoryEntity();
categoryEntity.setCategoryId(categoryId);
categoryEntity.setDeletedFlag(true);
categoryDao.updateById(categoryEntity);
// 更新缓存
categoryCacheManager.removeCache();
return ResponseDTO.ok();
}
}

View File

@ -0,0 +1,42 @@
package net.lab1024.sa.admin.module.business.goods.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.lab1024.sa.base.common.enumeration.BaseEnum;
/**
* 商品状态
*
* @Author 1024创新实验室: 胡克
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@AllArgsConstructor
@Getter
public enum GoodsStatusEnum implements BaseEnum {
/**
* 1 预约中
*/
APPOINTMENT(1, "预约中"),
/**
* 2 售卖
*/
SELL(2, "售卖中"),
/**
* 3 售罄
*/
SELL_OUT(3, "售罄"),
;
private final Integer value;
private final String desc;
}

View File

@ -0,0 +1,94 @@
package net.lab1024.sa.admin.module.business.goods.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsAddForm;
import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsQueryForm;
import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsUpdateForm;
import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsExcelVO;
import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsVO;
import net.lab1024.sa.admin.module.business.goods.service.GoodsService;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.domain.ValidateList;
import net.lab1024.sa.base.common.util.SmartExcelUtil;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
/**
* 商品业务
*
* @Author 1024创新实验室: 胡克
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@RestController
@Tag(name = AdminSwaggerTagConst.Business.MANAGER_GOODS)
public class GoodsController {
@Resource
private GoodsService goodsService;
@Operation(summary = "分页查询 @author 胡克")
@PostMapping("/goods/query")
@SaCheckPermission("goods:query")
public ResponseDTO<PageResult<GoodsVO>> query(@RequestBody @Valid GoodsQueryForm queryForm) {
return goodsService.query(queryForm);
}
@Operation(summary = "添加商品 @author 胡克")
@PostMapping("/goods/add")
@SaCheckPermission("goods:add")
public ResponseDTO<String> add(@RequestBody @Valid GoodsAddForm addForm) {
return goodsService.add(addForm);
}
@Operation(summary = "更新商品 @author 胡克")
@PostMapping("/goods/update")
@SaCheckPermission("goods:update")
public ResponseDTO<String> update(@RequestBody @Valid GoodsUpdateForm updateForm) {
return goodsService.update(updateForm);
}
@Operation(summary = "删除 @author 卓大")
@GetMapping("/goods/delete/{goodsId}")
@SaCheckPermission("goods:delete")
public ResponseDTO<String> delete(@PathVariable Long goodsId) {
return goodsService.delete(goodsId);
}
@Operation(summary = "批量 @author 卓大")
@PostMapping("/goods/batchDelete")
@SaCheckPermission("goods:batchDelete")
public ResponseDTO<String> batchDelete(@RequestBody @Valid ValidateList<Long> idList) {
return goodsService.batchDelete(idList);
}
// --------------- 导出和导入 -------------------
@Operation(summary = "导入 @author 卓大")
@PostMapping("/goods/importGoods")
@SaCheckPermission("goods:importGoods")
public ResponseDTO<String> importGoods(@RequestParam MultipartFile file) {
return goodsService.importGoods(file);
}
@Operation(summary = "导出 @author 卓大")
@GetMapping("/goods/exportGoods")
@SaCheckPermission("goods:exportGoods")
public void exportGoods(HttpServletResponse response) throws IOException {
List<GoodsExcelVO> goodsList = goodsService.getAllGoods();
SmartExcelUtil.exportExcel(response,"商品列表.xlsx","商品",GoodsExcelVO.class, goodsList);
}
}

View File

@ -0,0 +1,37 @@
package net.lab1024.sa.admin.module.business.goods.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.lab1024.sa.admin.module.business.goods.domain.entity.GoodsEntity;
import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsQueryForm;
import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 商品
*
* @Author 1024创新实验室: 胡克
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Mapper
public interface GoodsDao extends BaseMapper<GoodsEntity> {
/**
* 分页 查询商品
*
*/
List<GoodsVO> query(Page page, @Param("query") GoodsQueryForm query);
/**
* 批量更新删除状态
*/
void batchUpdateDeleted(@Param("goodsIdList")List<Long> goodsIdList,@Param("deletedFlag")Boolean deletedFlag);
}

View File

@ -0,0 +1,71 @@
package net.lab1024.sa.admin.module.business.goods.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 商品 实体类
*
* @Author 1024创新实验室: 胡克
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
@TableName("t_goods")
public class GoodsEntity {
@TableId(type = IdType.AUTO)
private Long goodsId;
/**
* 商品状态:[1:预约中,2:售卖中,3:售罄]
*/
private Integer goodsStatus;
/**
* 商品分类
*/
private Long categoryId;
/**
* 商品名称
*/
private String goodsName;
/**
* 产地
*/
private String place;
/**
* 商品价格
*/
private BigDecimal price;
/**
* 上架状态
*/
private Boolean shelvesFlag;
/**
* 删除状态
*/
private Boolean deletedFlag;
/**
* 备注
*/
private String remark;
private LocalDateTime updateTime;
private LocalDateTime createTime;
}

View File

@ -0,0 +1,56 @@
package net.lab1024.sa.admin.module.business.goods.domain.form;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import net.lab1024.sa.admin.module.business.goods.constant.GoodsStatusEnum;
import net.lab1024.sa.base.common.json.deserializer.DictDataDeserializer;
import net.lab1024.sa.base.common.swagger.SchemaEnum;
import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;
import java.math.BigDecimal;
/**
* 商品 添加表单
*
* @Author 1024创新实验室: 胡克
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class GoodsAddForm {
@Schema(description = "商品分类")
@NotNull(message = "商品分类不能为空")
private Long categoryId;
@Schema(description = "商品名称")
@NotBlank(message = "商品名称不能为空")
private String goodsName;
@SchemaEnum(GoodsStatusEnum.class)
@CheckEnum(message = "商品状态错误", value = GoodsStatusEnum.class, required = true)
private Integer goodsStatus;
@Schema(description = "产地")
@NotBlank(message = "产地 不能为空 ")
@JsonDeserialize(using = DictDataDeserializer.class)
private String place;
@Schema(description = "商品价格")
@NotNull(message = "商品价格不能为空")
@DecimalMin(value = "0", message = "商品价格最低0")
private BigDecimal price;
@Schema(description = "上架状态")
@NotNull(message = "上架状态不能为空")
private Boolean shelvesFlag;
@Schema(description = "备注|可选")
private String remark;
}

View File

@ -0,0 +1,37 @@
package net.lab1024.sa.admin.module.business.goods.domain.form;
import cn.idev.excel.annotation.ExcelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
* 商品 导入表单
*
* @Author 1024创新实验室: 胡克
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class GoodsImportForm {
@ExcelProperty("商品分类")
private String categoryName;
@ExcelProperty("商品名称")
private String goodsName;
@ExcelProperty("商品状态错误")
private String goodsStatus;
@ExcelProperty("产地")
private String place;
@ExcelProperty("商品价格")
private BigDecimal price;
@ExcelProperty("备注")
private String remark;
}

View File

@ -0,0 +1,45 @@
package net.lab1024.sa.admin.module.business.goods.domain.form;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import net.lab1024.sa.admin.module.business.goods.constant.GoodsStatusEnum;
import net.lab1024.sa.base.common.domain.PageParam;
import net.lab1024.sa.base.common.json.deserializer.DictDataDeserializer;
import net.lab1024.sa.base.common.swagger.SchemaEnum;
import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;
import org.hibernate.validator.constraints.Length;
/**
* 商品 分页查询
*
* @Author 1024创新实验室: 胡克
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class GoodsQueryForm extends PageParam {
@Schema(description = "商品分类")
private Integer categoryId;
@Schema(description = "搜索词")
@Length(max = 30, message = "搜索词最多30字符")
private String searchWord;
@SchemaEnum(GoodsStatusEnum.class)
@CheckEnum(message = "商品状态错误", value = GoodsStatusEnum.class, required = false)
private Integer goodsStatus;
@Schema(description = "产地")
@JsonDeserialize(using = DictDataDeserializer.class)
private String place;
@Schema(description = "上架状态")
private Boolean shelvesFlag;
@Schema(hidden = true)
private Boolean deletedFlag;
}

View File

@ -0,0 +1,22 @@
package net.lab1024.sa.admin.module.business.goods.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* 商品 更新表单
*
* @Author 1024创新实验室: 胡克
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class GoodsUpdateForm extends GoodsAddForm {
@Schema(description = "商品id")
@NotNull(message = "商品id不能为空")
private Long goodsId;
}

View File

@ -0,0 +1,44 @@
package net.lab1024.sa.admin.module.business.goods.domain.vo;
import cn.idev.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* excel商品
*
* @Author 1024创新实验室: 胡克
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class GoodsExcelVO {
@ExcelProperty("商品分类")
private String categoryName;
@ExcelProperty("商品名称")
private String goodsName;
@ExcelProperty("商品状态错误")
private String goodsStatus;
@ExcelProperty("产地")
private String place;
@ExcelProperty("商品价格")
private BigDecimal price;
@ExcelProperty("备注")
private String remark;
}

View File

@ -0,0 +1,53 @@
package net.lab1024.sa.admin.module.business.goods.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import net.lab1024.sa.admin.module.business.goods.constant.GoodsStatusEnum;
import net.lab1024.sa.base.common.swagger.SchemaEnum;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 商品
*
* @Author 1024创新实验室: 胡克
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class GoodsVO {
@Schema(description = "商品分类")
private Long categoryId;
@Schema(description = "商品名称")
private String goodsName;
@SchemaEnum(GoodsStatusEnum.class)
private Integer goodsStatus;
@Schema(description = "产地")
private String place;
@Schema(description = "商品价格")
private BigDecimal price;
@Schema(description = "上架状态")
private Boolean shelvesFlag;
@Schema(description = "备注|可选")
private String remark;
@Schema(description = "商品id")
private Long goodsId;
@Schema(description = "商品分类")
private String categoryName;
private LocalDateTime updateTime;
private LocalDateTime createTime;
}

View File

@ -0,0 +1,211 @@
package net.lab1024.sa.admin.module.business.goods.service;
import cn.idev.excel.FastExcel;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum;
import net.lab1024.sa.admin.module.business.category.domain.entity.CategoryEntity;
import net.lab1024.sa.admin.module.business.category.service.CategoryQueryService;
import net.lab1024.sa.admin.module.business.goods.constant.GoodsStatusEnum;
import net.lab1024.sa.admin.module.business.goods.dao.GoodsDao;
import net.lab1024.sa.admin.module.business.goods.domain.entity.GoodsEntity;
import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsAddForm;
import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsImportForm;
import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsQueryForm;
import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsUpdateForm;
import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsExcelVO;
import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsVO;
import net.lab1024.sa.base.common.code.UserErrorCode;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.exception.BusinessException;
import net.lab1024.sa.base.common.util.SmartBeanUtil;
import net.lab1024.sa.base.common.util.SmartEnumUtil;
import net.lab1024.sa.base.common.util.SmartPageUtil;
import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum;
import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService;
import net.lab1024.sa.base.module.support.dict.service.DictService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
/**
* 商品
*
* @Author 1024创新实验室: 胡克
* @Date 2021-10-25 20:26:54
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Service
@Slf4j
public class GoodsService {
@Resource
private GoodsDao goodsDao;
@Resource
private CategoryQueryService categoryQueryService;
@Resource
private DataTracerService dataTracerService;
@Resource
private DictService dictService;
/**
* 添加商品
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> add(GoodsAddForm addForm) {
// 商品校验
ResponseDTO<String> res = this.checkGoods(addForm);
if (!res.getOk()) {
return res;
}
GoodsEntity goodsEntity = SmartBeanUtil.copy(addForm, GoodsEntity.class);
goodsEntity.setDeletedFlag(Boolean.FALSE);
goodsDao.insert(goodsEntity);
dataTracerService.insert(goodsEntity.getGoodsId(), DataTracerTypeEnum.GOODS);
return ResponseDTO.ok();
}
/**
* 更新商品
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> update(GoodsUpdateForm updateForm) {
// 商品校验
ResponseDTO<String> res = this.checkGoods(updateForm);
if (!res.getOk()) {
return res;
}
GoodsEntity originEntity = goodsDao.selectById(updateForm.getGoodsId());
GoodsEntity goodsEntity = SmartBeanUtil.copy(updateForm, GoodsEntity.class);
goodsDao.updateById(goodsEntity);
dataTracerService.update(updateForm.getGoodsId(), DataTracerTypeEnum.GOODS, originEntity, goodsEntity);
return ResponseDTO.ok();
}
/**
* 添加/更新 商品校验
*/
private ResponseDTO<String> checkGoods(GoodsAddForm addForm) {
// 校验类目id
Long categoryId = addForm.getCategoryId();
Optional<CategoryEntity> optional = categoryQueryService.queryCategory(categoryId);
if (!optional.isPresent() || !CategoryTypeEnum.GOODS.equalsValue(optional.get().getCategoryType())) {
return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST, "商品类目不存在~");
}
return ResponseDTO.ok();
}
/**
* 删除
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> delete(Long goodsId) {
GoodsEntity goodsEntity = goodsDao.selectById(goodsId);
if (goodsEntity == null) {
return ResponseDTO.userErrorParam("商品不存在");
}
if (!goodsEntity.getGoodsStatus().equals(GoodsStatusEnum.SELL_OUT.getValue())) {
return ResponseDTO.userErrorParam("只有售罄的商品才可以删除");
}
batchDelete(Collections.singletonList(goodsId));
dataTracerService.batchDelete(Collections.singletonList(goodsId), DataTracerTypeEnum.GOODS);
return ResponseDTO.ok();
}
/**
* 批量删除
*/
public ResponseDTO<String> batchDelete(List<Long> goodsIdList) {
if (CollectionUtils.isEmpty(goodsIdList)) {
return ResponseDTO.ok();
}
goodsDao.batchUpdateDeleted(goodsIdList, Boolean.TRUE);
return ResponseDTO.ok();
}
/**
* 分页查询
*/
public ResponseDTO<PageResult<GoodsVO>> query(GoodsQueryForm queryForm) {
queryForm.setDeletedFlag(false);
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
List<GoodsVO> list = goodsDao.query(page, queryForm);
PageResult<GoodsVO> pageResult = SmartPageUtil.convert2PageResult(page, list);
if (pageResult.getEmptyFlag()) {
return ResponseDTO.ok(pageResult);
}
// 查询分类名称
List<Long> categoryIdList = list.stream().map(GoodsVO::getCategoryId).distinct().collect(Collectors.toList());
Map<Long, CategoryEntity> categoryMap = categoryQueryService.queryCategoryList(categoryIdList);
list.forEach(e -> {
CategoryEntity categoryEntity = categoryMap.get(e.getCategoryId());
if (categoryEntity != null) {
e.setCategoryName(categoryEntity.getCategoryName());
}
});
return ResponseDTO.ok(pageResult);
}
/**
* 商品导入
*
* @param file 上传文件
* @return 结果
*/
public ResponseDTO<String> importGoods(MultipartFile file) {
List<GoodsImportForm> dataList;
try {
dataList = FastExcel.read(file.getInputStream()).head(GoodsImportForm.class)
.sheet()
.doReadSync();
} catch (IOException e) {
log.error(e.getMessage(), e);
throw new BusinessException("数据格式存在问题,无法读取");
}
if (CollectionUtils.isEmpty(dataList)) {
return ResponseDTO.userErrorParam("数据为空");
}
return ResponseDTO.okMsg("成功导入" + dataList.size() + "条,具体数据为:" + JSON.toJSONString(dataList));
}
/**
* 商品导出
*/
public List<GoodsExcelVO> getAllGoods() {
List<GoodsEntity> goodsEntityList = goodsDao.selectList(null);
String dictCode = "GOODS_PLACE";
return goodsEntityList.stream()
.map(e ->
GoodsExcelVO.builder()
.goodsStatus(SmartEnumUtil.getEnumDescByValue(e.getGoodsStatus(), GoodsStatusEnum.class))
.categoryName(categoryQueryService.queryCategoryName(e.getCategoryId()))
.place(Arrays.stream(e.getPlace().split(",")).map(code -> dictService.getDictDataLabel(dictCode, code)).collect(Collectors.joining(",")))
.price(e.getPrice())
.goodsName(e.getGoodsName())
.remark(e.getRemark())
.build()
)
.collect(Collectors.toList());
}
}

View File

@ -0,0 +1,82 @@
package net.lab1024.sa.admin.module.business.oa.bank.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
import net.lab1024.sa.admin.module.business.oa.bank.service.BankService;
import net.lab1024.sa.admin.module.business.oa.bank.domain.BankCreateForm;
import net.lab1024.sa.admin.module.business.oa.bank.domain.BankQueryForm;
import net.lab1024.sa.admin.module.business.oa.bank.domain.BankUpdateForm;
import net.lab1024.sa.admin.module.business.oa.bank.domain.BankVO;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.domain.RequestUser;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartRequestUtil;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* OA办公-OA银行信息
*
* @Author 1024创新实验室:善逸
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@RestController
@Tag(name = AdminSwaggerTagConst.Business.OA_BANK)
public class BankController {
@Resource
private BankService bankService;
@Operation(summary = "分页查询银行信息 @author 善逸")
@PostMapping("/oa/bank/page/query")
@SaCheckPermission("oa:bank:query")
public ResponseDTO<PageResult<BankVO>> queryByPage(@RequestBody @Valid BankQueryForm queryForm) {
return bankService.queryByPage(queryForm);
}
@Operation(summary = "根据企业ID查询银行信息列表 @author 善逸")
@GetMapping("/oa/bank/query/list/{enterpriseId}")
@SaCheckPermission("oa:bank:query")
public ResponseDTO<List<BankVO>> queryList(@PathVariable Long enterpriseId) {
return bankService.queryList(enterpriseId);
}
@Operation(summary = "查询银行信息详情 @author 善逸")
@GetMapping("/oa/bank/get/{bankId}")
@SaCheckPermission("oa:bank:query")
public ResponseDTO<BankVO> getDetail(@PathVariable Long bankId) {
return bankService.getDetail(bankId);
}
@Operation(summary = "新建银行信息 @author 善逸")
@PostMapping("/oa/bank/create")
@SaCheckPermission("oa:bank:add")
public ResponseDTO<String> createBank(@RequestBody @Valid BankCreateForm createVO) {
RequestUser requestUser = SmartRequestUtil.getRequestUser();
createVO.setCreateUserId(requestUser.getUserId());
createVO.setCreateUserName(requestUser.getUserName());
return bankService.createBank(createVO);
}
@Operation(summary = "编辑银行信息 @author 善逸")
@PostMapping("/oa/bank/update")
@SaCheckPermission("oa:bank:update")
public ResponseDTO<String> updateBank(@RequestBody @Valid BankUpdateForm updateVO) {
return bankService.updateBank(updateVO);
}
@Operation(summary = "删除银行信息 @author 善逸")
@GetMapping("/oa/bank/delete/{bankId}")
@SaCheckPermission("oa:bank:delete")
public ResponseDTO<String> deleteBank(@PathVariable Long bankId) {
return bankService.deleteBank(bankId);
}
}

View File

@ -0,0 +1,46 @@
package net.lab1024.sa.admin.module.business.oa.bank.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.lab1024.sa.admin.module.business.oa.bank.domain.BankEntity;
import net.lab1024.sa.admin.module.business.oa.bank.domain.BankQueryForm;
import net.lab1024.sa.admin.module.business.oa.bank.domain.BankVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* OA办公-OA银行信息
*
* @Author 1024创新实验室:善逸
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Mapper
public interface BankDao extends BaseMapper<BankEntity> {
/**
* 根据账号查询
*/
BankEntity queryByAccountNumber(@Param("enterpriseId") Long enterpriseId, @Param("accountNumber") String accountNumber, @Param("excludeBankId") Long excludeBankId, @Param("deletedFlag") Boolean deletedFlag);
/**
* 删除银行信息
*
*/
void deleteBank(@Param("bankId") Long bankId, @Param("deletedFlag") Boolean deletedFlag);
/**
* 银行信息分页查询
*
*/
List<BankVO> queryPage(Page page, @Param("queryForm") BankQueryForm queryForm);
/**
* 查询银行信息详情
*/
BankVO getDetail(@Param("bankId") Long bankId, @Param("deletedFlag") Boolean deletedFlag);
}

View File

@ -0,0 +1,57 @@
package net.lab1024.sa.admin.module.business.oa.bank.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
/**
* OA办公-银行信息新建
*
* @Author 1024创新实验室:善逸
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class BankCreateForm {
@Schema(description = "开户银行")
@NotBlank(message = "开户银行不能为空")
@Length(max = 200, message = "开户银行最多200字符")
private String bankName;
@Schema(description = "账户名称")
@NotBlank(message = "账户名称不能为空")
@Length(max = 200, message = "账户名称最多200字符")
private String accountName;
@Schema(description = "账号")
@NotBlank(message = "账号不能为空")
@Length(max = 200, message = "账号最多200字符")
private String accountNumber;
@Schema(description = "备注")
@Length(max = 500, message = "备注最多500字符")
private String remark;
@Schema(description = "是否对公")
@NotNull(message = "是否对公不能为空")
private Boolean businessFlag;
@Schema(description = "企业")
@NotNull(message = "企业不能为空")
private Long enterpriseId;
@Schema(description = "禁用状态")
@NotNull(message = "禁用状态不能为空")
private Boolean disabledFlag;
@Schema(hidden = true)
private Long createUserId;
@Schema(hidden = true)
private String createUserName;
}

View File

@ -0,0 +1,95 @@
package net.lab1024.sa.admin.module.business.oa.bank.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import net.lab1024.sa.base.module.support.datatracer.annoation.DataTracerFieldLabel;
import java.time.LocalDateTime;
/**
* OA办公-OA银行信息
*
* @Author 1024创新实验室:善逸
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
@TableName("t_oa_bank")
public class BankEntity {
/**
* 银行信息ID
*/
@TableId(type = IdType.AUTO)
@DataTracerFieldLabel("银行信息ID")
private Long bankId;
/**
* 开户银行
*/
@DataTracerFieldLabel("开户银行")
private String bankName;
/**
* 账户名称
*/
@DataTracerFieldLabel("账户名称")
private String accountName;
/**
* 账号
*/
@DataTracerFieldLabel("账号")
private String accountNumber;
/**
* 备注
*/
@DataTracerFieldLabel("备注")
private String remark;
/**
* 是否对公
*/
@DataTracerFieldLabel("是否对公")
private Boolean businessFlag;
/**
* 企业ID
*/
private Long enterpriseId;
/**
* 禁用状态
*/
@DataTracerFieldLabel("禁用状态")
private Boolean disabledFlag;
/**
* 删除状态
*/
private Boolean deletedFlag;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人ID
*/
private String createUserName;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,40 @@
package net.lab1024.sa.admin.module.business.oa.bank.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import net.lab1024.sa.base.common.domain.PageParam;
import org.hibernate.validator.constraints.Length;
import java.time.LocalDate;
/**
* OA办公-OA银行信息查询
*
* @Author 1024创新实验室:善逸
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class BankQueryForm extends PageParam {
@Schema(description = "企业ID")
private Long enterpriseId;
@Schema(description = "关键字")
@Length(max = 200, message = "关键字最多200字符")
private String keywords;
@Schema(description = "开始时间")
private LocalDate startTime;
@Schema(description = "结束时间")
private LocalDate endTime;
@Schema(description = "禁用状态")
private Boolean disabledFlag;
@Schema(description = "删除状态", hidden = true)
private Boolean deletedFlag;
}

View File

@ -0,0 +1,22 @@
package net.lab1024.sa.admin.module.business.oa.bank.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* OA办公-银行信息更新
*
* @Author 1024创新实验室:善逸
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class BankUpdateForm extends BankCreateForm {
@Schema(description = "银行信息ID")
@NotNull(message = "银行信息ID不能为空")
private Long bankId;
}

View File

@ -0,0 +1,58 @@
package net.lab1024.sa.admin.module.business.oa.bank.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* OA办公-OA银行信息
*
* @Author 1024创新实验室:善逸
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class BankVO {
@Schema(description = "银行信息ID")
private Long bankId;
@Schema(description = "开户银行")
private String bankName;
@Schema(description = "账户名称")
private String accountName;
@Schema(description = "账号")
private String accountNumber;
@Schema(description = "备注")
private String remark;
@Schema(description = "是否对公")
private Boolean businessFlag;
@Schema(description = "企业ID")
private Long enterpriseId;
@Schema(description = "企业名称")
private String enterpriseName;
@Schema(description = "禁用状态")
private Boolean disabledFlag;
@Schema(description = "创建人ID")
private Long createUserId;
@Schema(description = "创建人名称")
private String createUserName;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "更新时间")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,146 @@
package net.lab1024.sa.admin.module.business.oa.bank.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.module.business.oa.bank.dao.BankDao;
import net.lab1024.sa.admin.module.business.oa.bank.domain.*;
import net.lab1024.sa.admin.module.business.oa.enterprise.dao.EnterpriseDao;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity.EnterpriseEntity;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartBeanUtil;
import net.lab1024.sa.base.common.util.SmartPageUtil;
import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerConst;
import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum;
import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Objects;
/**
* OA办公-OA银行信息
*
* @Author 1024创新实验室:善逸
* @Date 2022/6/23 21:59:22
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Service
@Slf4j
public class BankService {
@Resource
private BankDao bankDao;
@Resource
private EnterpriseDao enterpriseDao;
@Resource
private DataTracerService dataTracerService;
/**
* 分页查询银行信息
*/
public ResponseDTO<PageResult<BankVO>> queryByPage(BankQueryForm queryForm) {
queryForm.setDeletedFlag(Boolean.FALSE);
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
List<BankVO> bankList = bankDao.queryPage(page, queryForm);
PageResult<BankVO> pageResult = SmartPageUtil.convert2PageResult(page, bankList);
return ResponseDTO.ok(pageResult);
}
/**
* 根据企业ID查询不分页的银行列表
*/
public ResponseDTO<List<BankVO>> queryList(Long enterpriseId) {
BankQueryForm queryForm = new BankQueryForm();
queryForm.setEnterpriseId(enterpriseId);
queryForm.setDeletedFlag(Boolean.FALSE);
List<BankVO> bankList = bankDao.queryPage(null, queryForm);
return ResponseDTO.ok(bankList);
}
/**
* 查询银行信息详情
*/
public ResponseDTO<BankVO> getDetail(Long bankId) {
// 校验银行信息是否存在
BankVO bankVO = bankDao.getDetail(bankId, Boolean.FALSE);
if (Objects.isNull(bankVO)) {
return ResponseDTO.userErrorParam("银行信息不存在");
}
return ResponseDTO.ok(bankVO);
}
/**
* 新建银行信息
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> createBank(BankCreateForm createVO) {
Long enterpriseId = createVO.getEnterpriseId();
// 校验企业是否存在
EnterpriseEntity enterpriseDetail = enterpriseDao.selectById(enterpriseId);
if (Objects.isNull(enterpriseDetail) || enterpriseDetail.getDeletedFlag()) {
return ResponseDTO.userErrorParam("企业不存在");
}
// 验证银行信息账号是否重复
BankEntity validateBank = bankDao.queryByAccountNumber(enterpriseId, createVO.getAccountNumber(), null, Boolean.FALSE);
if (Objects.nonNull(validateBank)) {
return ResponseDTO.userErrorParam("银行信息账号重复");
}
// 数据插入
BankEntity insertBank = SmartBeanUtil.copy(createVO, BankEntity.class);
bankDao.insert(insertBank);
dataTracerService.addTrace(enterpriseId, DataTracerTypeEnum.OA_ENTERPRISE, "新增银行:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(insertBank));
return ResponseDTO.ok();
}
/**
* 编辑银行信息
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> updateBank(BankUpdateForm updateVO) {
Long enterpriseId = updateVO.getEnterpriseId();
// 校验企业是否存在
EnterpriseEntity enterpriseDetail = enterpriseDao.selectById(enterpriseId);
if (Objects.isNull(enterpriseDetail) || enterpriseDetail.getDeletedFlag()) {
return ResponseDTO.userErrorParam("企业不存在");
}
Long bankId = updateVO.getBankId();
// 校验银行信息是否存在
BankEntity bankDetail = bankDao.selectById(bankId);
if (Objects.isNull(bankDetail) || bankDetail.getDeletedFlag()) {
return ResponseDTO.userErrorParam("银行信息不存在");
}
// 验证银行信息账号是否重复
BankEntity validateBank = bankDao.queryByAccountNumber(updateVO.getEnterpriseId(), updateVO.getAccountNumber(), bankId, Boolean.FALSE);
if (Objects.nonNull(validateBank)) {
return ResponseDTO.userErrorParam("银行信息账号重复");
}
// 数据编辑
BankEntity updateBank = SmartBeanUtil.copy(updateVO, BankEntity.class);
bankDao.updateById(updateBank);
dataTracerService.addTrace(enterpriseId, DataTracerTypeEnum.OA_ENTERPRISE, "更新银行:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(bankDetail, updateBank));
return ResponseDTO.ok();
}
/**
* 删除银行信息
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> deleteBank(Long bankId) {
// 校验银行信息是否存在
BankEntity bankDetail = bankDao.selectById(bankId);
if (Objects.isNull(bankDetail) || bankDetail.getDeletedFlag()) {
return ResponseDTO.userErrorParam("银行信息不存在");
}
bankDao.deleteBank(bankId, Boolean.TRUE);
dataTracerService.addTrace(bankDetail.getEnterpriseId(), DataTracerTypeEnum.OA_ENTERPRISE, "删除银行:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(bankDetail));
return ResponseDTO.ok();
}
}

View File

@ -0,0 +1,46 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.constant;
import net.lab1024.sa.base.common.enumeration.BaseEnum;
/**
* 企业类型
*
* @Author 1024创新实验室: 开云
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
public enum EnterpriseTypeEnum implements BaseEnum {
/**
* 有限企业
*/
NORMAL(1, "有限企业"),
/**
* 外资企业
*/
FOREIGN(2, "外资企业"),
;
private Integer value;
private String desc;
EnterpriseTypeEnum(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
@Override
public Integer getValue() {
return value;
}
@Override
public String getDesc() {
return desc;
}
}

View File

@ -0,0 +1,138 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
import net.lab1024.sa.admin.module.business.oa.enterprise.service.EnterpriseService;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.form.*;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseEmployeeVO;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseExcelVO;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseListVO;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO;
import net.lab1024.sa.admin.util.AdminRequestUtil;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.domain.RequestUser;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.*;
import net.lab1024.sa.base.module.support.operatelog.annotation.OperateLog;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
/**
* 企业
*
* @Author 1024创新实验室: 开云
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Slf4j
@RestController
@Tag(name = AdminSwaggerTagConst.Business.OA_ENTERPRISE)
@OperateLog
public class EnterpriseController {
@Resource
private EnterpriseService enterpriseService;
@Operation(summary = "分页查询企业模块 @author 开云")
@PostMapping("/oa/enterprise/page/query")
@SaCheckPermission("oa:enterprise:query")
public ResponseDTO<PageResult<EnterpriseVO>> queryByPage(@RequestBody @Valid EnterpriseQueryForm queryForm) {
return enterpriseService.queryByPage(queryForm);
}
@Operation(summary = "导出企业信息 @author 卓大")
@PostMapping("/oa/enterprise/exportExcel")
public void exportExcel(@RequestBody @Valid EnterpriseQueryForm queryForm, HttpServletResponse response) throws IOException {
List<EnterpriseExcelVO> data = enterpriseService.getExcelExportData(queryForm);
if (CollectionUtils.isEmpty(data)) {
SmartResponseUtil.write(response, ResponseDTO.userErrorParam("暂无数据"));
return;
}
String watermark = AdminRequestUtil.getRequestUser().getActualName();
watermark += SmartLocalDateUtil.format(LocalDateTime.now(), SmartDateFormatterEnum.YMD_HMS);
SmartExcelUtil.exportExcelWithWatermark(response,"企业基本信息.xlsx","企业信息",EnterpriseExcelVO.class,data,watermark);
}
@Operation(summary = "查询企业详情 @author 开云")
@GetMapping("/oa/enterprise/get/{enterpriseId}")
@SaCheckPermission("oa:enterprise:detail")
public ResponseDTO<EnterpriseVO> getDetail(@PathVariable Long enterpriseId) {
return ResponseDTO.ok(enterpriseService.getDetail(enterpriseId));
}
@Operation(summary = "新建企业 @author 开云")
@PostMapping("/oa/enterprise/create")
@SaCheckPermission("oa:enterprise:add")
public ResponseDTO<String> createEnterprise(@RequestBody @Valid EnterpriseCreateForm createVO) {
RequestUser requestUser = SmartRequestUtil.getRequestUser();
createVO.setCreateUserId(requestUser.getUserId());
createVO.setCreateUserName(requestUser.getUserName());
return enterpriseService.createEnterprise(createVO);
}
@Operation(summary = "编辑企业 @author 开云")
@PostMapping("/oa/enterprise/update")
@SaCheckPermission("oa:enterprise:update")
public ResponseDTO<String> updateEnterprise(@RequestBody @Valid EnterpriseUpdateForm updateVO) {
return enterpriseService.updateEnterprise(updateVO);
}
@Operation(summary = "删除企业 @author 开云")
@GetMapping("/oa/enterprise/delete/{enterpriseId}")
@SaCheckPermission("oa:enterprise:delete")
public ResponseDTO<String> deleteEnterprise(@PathVariable Long enterpriseId) {
return enterpriseService.deleteEnterprise(enterpriseId);
}
@Operation(summary = "按照类型查询企业 @author 开云")
@GetMapping("/oa/enterprise/query/list")
@SaCheckPermission("oa:enterprise:query")
public ResponseDTO<List<EnterpriseListVO>> queryList(@RequestParam(value = "type", required = false) Integer type) {
return enterpriseService.queryList(type);
}
@Operation(summary = "企业添加员工 @author 罗伊")
@PostMapping("/oa/enterprise/employee/add")
@SaCheckPermission("oa:enterprise:addEmployee")
public ResponseDTO<String> addEmployee(@RequestBody @Valid EnterpriseEmployeeForm enterpriseEmployeeForm) {
return enterpriseService.addEmployee(enterpriseEmployeeForm);
}
@Operation(summary = "查询企业全部员工 @author 罗伊")
@PostMapping("/oa/enterprise/employee/list")
@SaCheckPermission("oa:enterprise:queryEmployee")
public ResponseDTO<List<EnterpriseEmployeeVO>> employeeList(@RequestBody @Valid List<Long> enterpriseIdList) {
return ResponseDTO.ok(enterpriseService.employeeList(enterpriseIdList));
}
@Operation(summary = "分页查询企业员工 @author 卓大")
@PostMapping("/oa/enterprise/employee/queryPage")
@SaCheckPermission("oa:enterprise:queryEmployee")
public ResponseDTO<PageResult<EnterpriseEmployeeVO>> queryPageEmployeeList(@RequestBody @Valid EnterpriseEmployeeQueryForm queryForm) {
return ResponseDTO.ok(enterpriseService.queryPageEmployeeList(queryForm));
}
@Operation(summary = "企业删除员工 @author 罗伊")
@PostMapping("/oa/enterprise/employee/delete")
@SaCheckPermission("oa:enterprise:deleteEmployee")
public ResponseDTO<String> deleteEmployee(@RequestBody @Valid EnterpriseEmployeeForm enterpriseEmployeeForm) {
return enterpriseService.deleteEmployee(enterpriseEmployeeForm);
}
}

View File

@ -0,0 +1,64 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity.EnterpriseEntity;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.form.EnterpriseQueryForm;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseExcelVO;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseListVO;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 企业
*
* @Author 1024创新实验室: 开云
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Mapper
public interface EnterpriseDao extends BaseMapper<EnterpriseEntity> {
/**
* 根据企业名称查询
*
*/
EnterpriseEntity queryByEnterpriseName(@Param("enterpriseName") String enterpriseName, @Param("excludeEnterpriseId") Long excludeEnterpriseId, @Param("deletedFlag") Boolean deletedFlag);
/**
* 删除企业
*/
void deleteEnterprise(@Param("enterpriseId") Long enterpriseId, @Param("deletedFlag") Boolean deletedFlag);
/**
* 企业分页查询
*
*/
List<EnterpriseVO> queryPage(Page page, @Param("queryForm") EnterpriseQueryForm queryForm);
/**
* 查询导出的数据
*
*/
List<EnterpriseExcelVO> selectExcelExportData(@Param("queryForm") EnterpriseQueryForm queryForm);
/**
* 查询企业详情
*
*/
EnterpriseVO getDetail(@Param("enterpriseId") Long enterpriseId, @Param("deletedFlag") Boolean deletedFlag);
/**
* 查询列表
*
*/
List<EnterpriseListVO> queryList(@Param("type") Integer type, @Param("disabledFlag") Boolean disabledFlag, @Param("deletedFlag") Boolean deletedFlag);
}

View File

@ -0,0 +1,69 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity.EnterpriseEmployeeEntity;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.form.EnterpriseEmployeeQueryForm;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseEmployeeVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.List;
/**
* 企业员工
*
* @Author 1024创新实验室: 罗伊
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Mapper
public interface EnterpriseEmployeeDao extends BaseMapper<EnterpriseEmployeeEntity> {
/**
* 根据员工查询
*/
List<EnterpriseEmployeeVO> selectByEmployeeIdList(@Param("employeeIdList")Collection<Long> employeeIdList);
/**
* 查询员工关联的企业
*/
List<Long> selectEnterpriseIdByEmployeeId(@Param("employeeId")Long employeeId);
/**
* 根据企业查询
*/
List<EnterpriseEmployeeVO> selectByEnterpriseIdList(@Param("enterpriseIdList")Collection<Long> enterpriseIdList);
/**
* 根据企业查询
*/
List<EnterpriseEmployeeEntity> selectByEnterpriseId(@Param("enterpriseId")Long enterpriseId);
/**
* 查询企业下的所有员工id
*/
List<Long> selectEmployeeIdByEnterpriseIdList(@Param("enterpriseIdList")Collection<Long> enterpriseIdList);
/**
* 根据员工删除
*/
void deleteByEnterpriseAndEmployeeIdList(@Param("enterpriseId")Long enterpriseId, @Param("employeeIdList")Collection<Long> employeeIdList);
/**
* 根据员工查询
*/
List<EnterpriseEmployeeEntity> selectByEnterpriseAndEmployeeIdList(@Param("enterpriseId")Long enterpriseId, @Param("employeeIdList")Collection<Long> employeeIdList);
/**
* 删除某员工关联的所有企业
*/
void deleteByEmployeeId(@Param("employeeId")Long employeeId);
/**
* 分页查询企业员工
*/
List<EnterpriseEmployeeVO> queryPageEmployeeList(Page<?> page,@Param("queryForm") EnterpriseEmployeeQueryForm queryForm);
}

View File

@ -0,0 +1,51 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 企业员工
*
* @Author 1024创新实验室: 罗伊
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
@TableName("t_oa_enterprise_employee")
@NoArgsConstructor
public class EnterpriseEmployeeEntity {
@TableId(type = IdType.AUTO)
private Long enterpriseEmployeeId;
/**
* 企业ID
*/
private Long enterpriseId;
/**
* 员工
*/
private Long employeeId;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
public EnterpriseEmployeeEntity(Long enterpriseId, Long employeeId) {
this.enterpriseId = enterpriseId;
this.employeeId = employeeId;
}
}

View File

@ -0,0 +1,153 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import net.lab1024.sa.admin.module.business.oa.enterprise.constant.EnterpriseTypeEnum;
import net.lab1024.sa.base.module.support.datatracer.annoation.DataTracerFieldEnum;
import net.lab1024.sa.base.module.support.datatracer.annoation.DataTracerFieldLabel;
import java.time.LocalDateTime;
/**
* 企业
*
* @Author 1024创新实验室: 开云
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
@TableName("t_oa_enterprise")
public class EnterpriseEntity {
/**
* 企业ID
*/
@TableId(type = IdType.AUTO)
private Long enterpriseId;
/**
* 企业名称
*/
@DataTracerFieldLabel("企业名称")
private String enterpriseName;
/**
* 企业logo
*/
@DataTracerFieldLabel("企业logo")
private String enterpriseLogo;
/**
* 统一社会信用代码
*/
@DataTracerFieldLabel("统一社会信用代码")
private String unifiedSocialCreditCode;
/**
* 类型
*
* @see EnterpriseTypeEnum
*/
@DataTracerFieldLabel("类型")
@DataTracerFieldEnum(enumClass = EnterpriseTypeEnum.class)
private Integer type;
/**
* 联系人
*/
@DataTracerFieldLabel("联系人")
private String contact;
/**
* 联系人电话
*/
@DataTracerFieldLabel("联系人电话")
private String contactPhone;
/**
* 邮箱
*/
@DataTracerFieldLabel("邮箱")
private String email;
/**
* 省份
*/
private Integer province;
/**
* 省份名称
*/
@DataTracerFieldLabel("省份名称")
private String provinceName;
/**
* 城市
*/
private Integer city;
/**
* 城市名称
*/
@DataTracerFieldLabel("城市名称")
private String cityName;
/**
* 区县
*/
private Integer district;
/**
* 区县名称
*/
@DataTracerFieldLabel("区县名称")
private String districtName;
/**
* 详细地址
*/
@DataTracerFieldLabel("详细地址")
private String address;
/**
* 营业执照
*/
@DataTracerFieldLabel("营业执照")
private String businessLicense;
/**
* 禁用状态
*/
@DataTracerFieldLabel("禁用状态")
private Boolean disabledFlag;
/**
* 删除状态
*/
@DataTracerFieldLabel("删除状态")
private Boolean deletedFlag;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人ID
*/
private String createUserName;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,100 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.domain.form;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
import net.lab1024.sa.admin.module.business.oa.enterprise.constant.EnterpriseTypeEnum;
import net.lab1024.sa.base.common.json.deserializer.FileKeyVoDeserializer;
import net.lab1024.sa.base.common.json.serializer.FileKeyVoSerializer;
import net.lab1024.sa.base.common.swagger.SchemaEnum;
import net.lab1024.sa.base.common.util.SmartVerificationUtil;
import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;
import org.hibernate.validator.constraints.Length;
/**
* OA企业模块创建
*
* @Author 1024创新实验室: 开云
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class EnterpriseCreateForm {
@Schema(description = "企业名称")
@NotBlank(message = "企业名称不能为空")
@Length(max = 200, message = "企业名称最多200字符")
private String enterpriseName;
@Schema(description = "企业logo")
@JsonSerialize(using = FileKeyVoSerializer.class)
@JsonDeserialize(using = FileKeyVoDeserializer.class)
private String enterpriseLogo;
@Schema(description = "统一社会信用代码")
@NotBlank(message = "统一社会信用代码不能为空")
@Length(max = 200, message = "统一社会信用代码最多200字符")
private String unifiedSocialCreditCode;
@Schema(description = "联系人")
@NotBlank(message = "联系人不能为空")
@Length(max = 100, message = "联系人最多100字符")
private String contact;
@Schema(description = "联系人电话")
@NotBlank(message = "联系人电话不能为空")
@Pattern(regexp = SmartVerificationUtil.PHONE_REGEXP, message = "手机号格式不正确")
private String contactPhone;
@SchemaEnum(desc = "类型", value = EnterpriseTypeEnum.class)
@CheckEnum(message = "类型不正确", value = EnterpriseTypeEnum.class)
private Integer type;
@Schema(description = "邮箱")
@Pattern(regexp = SmartVerificationUtil.EMAIL, message = "邮箱格式不正确")
private String email;
@Schema(description = "省份")
private Integer province;
@Schema(description = "省份名称")
private String provinceName;
@Schema(description = "城市")
private Integer city;
@Schema(description = "城市名称")
private String cityName;
@Schema(description = "区县")
private Integer district;
@Schema(description = "区县名称")
private String districtName;
@Schema(description = "详细地址")
@Length(max = 500, message = "详细地址最多500字符")
private String address;
@Schema(description = "营业执照")
@JsonSerialize(using = FileKeyVoSerializer.class)
@JsonDeserialize(using = FileKeyVoDeserializer.class)
private String businessLicense;
@Schema(description = "禁用状态")
@NotNull(message = "禁用状态不能为空")
private Boolean disabledFlag;
@Schema(description = "创建人", hidden = true)
private Long createUserId;
@Schema(description = "创建人", hidden = true)
private String createUserName;
}

View File

@ -0,0 +1,29 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
/**
* 企业员工
*
* @Author 1024创新实验室: 罗伊
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class EnterpriseEmployeeForm {
@Schema(description = "企业id")
@NotNull(message = "企业id不能为空")
private Long enterpriseId;
@Schema(description = "员工信息id")
@NotEmpty(message = "员工信息id不能为空")
private List<Long> employeeIdList;
}

View File

@ -0,0 +1,32 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import net.lab1024.sa.base.common.domain.PageParam;
import org.hibernate.validator.constraints.Length;
/**
* 查询企业员工
*
* @Author 1024创新实验室: 开云
* @Date 2021-12-20 21:06:49
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class EnterpriseEmployeeQueryForm extends PageParam {
@Schema(description = "搜索词")
@Length(max = 20, message = "搜索词最多20字符")
private String keyword;
@Schema(description = "公司Id")
@NotNull(message = "公司id 不能为空")
private Long enterpriseId;
@Schema(description = "删除标识", hidden = true)
private Boolean deletedFlag;
}

View File

@ -0,0 +1,38 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import net.lab1024.sa.base.common.domain.PageParam;
import org.hibernate.validator.constraints.Length;
import java.time.LocalDate;
/**
* OA企业模块分页查询
*
* @Author 1024创新实验室: 开云
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class EnterpriseQueryForm extends PageParam {
@Schema(description = "关键字")
@Length(max = 200, message = "关键字最多200字符")
private String keywords;
@Schema(description = "开始时间")
private LocalDate startTime;
@Schema(description = "结束时间")
private LocalDate endTime;
@Schema(description = "禁用状态")
private Boolean disabledFlag;
@Schema(description = "删除状态", hidden = true)
private Boolean deletedFlag;
}

View File

@ -0,0 +1,22 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* OA企业模块编辑
*
* @Author 1024创新实验室: 开云
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class EnterpriseUpdateForm extends EnterpriseCreateForm {
@Schema(description = "企业ID")
@NotNull(message = "企业ID不能为空")
private Long enterpriseId;
}

View File

@ -0,0 +1,47 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 企业员工信息
*
* @Author 1024创新实验室: 罗伊
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class EnterpriseEmployeeVO {
private Long enterpriseEmployeeId;
@Schema(description = "企业ID")
private Long enterpriseId;
@Schema(description = "企业名称")
private String enterpriseName;
@Schema(description = "员工")
private Long employeeId;
@Schema(description = "登录账号")
private String loginName;
@Schema(description = "员工名称")
private String actualName;
@Schema(description = "手机号码")
private String phone;
@Schema(description = "部门id")
private Long departmentId;
@Schema(description = "是否被禁用")
private Boolean disabledFlag;
@Schema(description = "部门名称")
private String departmentName;
}

View File

@ -0,0 +1,48 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo;
import cn.idev.excel.annotation.ExcelProperty;
import lombok.Data;
/**
* 企业信息
*
* @Author 1024创新实验室: 开云
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class EnterpriseExcelVO {
@ExcelProperty("企业名称")
private String enterpriseName;
@ExcelProperty("统一社会信用代码")
private String unifiedSocialCreditCode;
@ExcelProperty("企业类型")
private String typeName;
@ExcelProperty("联系人")
private String contact;
@ExcelProperty("联系人电话")
private String contactPhone;
@ExcelProperty("邮箱")
private String email;
@ExcelProperty("省份名称")
private String provinceName;
@ExcelProperty("城市名称")
private String cityName;
@ExcelProperty("区县名称")
private String districtName;
@ExcelProperty("详细地址")
private String address;
}

View File

@ -0,0 +1,20 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* OA企业模块列表
*
* @author lihaifan
* @date 2022/6/23 14:31
*/
@Data
public class EnterpriseListVO {
@Schema(description = "企业ID")
private Long enterpriseId;
@Schema(description = "企业名称")
private String enterpriseName;
}

View File

@ -0,0 +1,89 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import net.lab1024.sa.admin.module.business.oa.enterprise.constant.EnterpriseTypeEnum;
import net.lab1024.sa.base.common.json.serializer.FileKeyVoSerializer;
import net.lab1024.sa.base.common.swagger.SchemaEnum;
import java.time.LocalDateTime;
/**
* 企业信息
*
* @Author 1024创新实验室: 开云
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class EnterpriseVO {
@Schema(description = "企业ID")
private Long enterpriseId;
@Schema(description = "企业名称")
private String enterpriseName;
@Schema(description = "企业logo")
@JsonSerialize(using = FileKeyVoSerializer.class)
private String enterpriseLogo;
@Schema(description = "统一社会信用代码")
private String unifiedSocialCreditCode;
@SchemaEnum(desc = "类型", value = EnterpriseTypeEnum.class)
private Integer type;
@Schema(description = "联系人")
private String contact;
@Schema(description = "联系人电话")
private String contactPhone;
@Schema(description = "邮箱")
private String email;
@Schema(description = "省份")
private Integer province;
@Schema(description = "省份名称")
private String provinceName;
@Schema(description = "城市")
private Integer city;
@Schema(description = "城市名称")
private String cityName;
@Schema(description = "区县")
private Integer district;
@Schema(description = "区县名称")
private String districtName;
@Schema(description = "详细地址")
private String address;
@Schema(description = "营业执照")
@JsonSerialize(using = FileKeyVoSerializer.class)
private String businessLicense;
@Schema(description = "禁用状态")
private Boolean disabledFlag;
@Schema(description = "创建人ID")
private Long createUserId;
@Schema(description = "创建人名称")
private String createUserName;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "更新时间")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,19 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.manager;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.lab1024.sa.admin.module.business.oa.enterprise.dao.EnterpriseEmployeeDao;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity.EnterpriseEmployeeEntity;
import org.springframework.stereotype.Service;
/**
* 企业员工关系 manager
*
* @Author 1024创新实验室: 罗伊
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Service
public class EnterpriseEmployeeManager extends ServiceImpl<EnterpriseEmployeeDao, EnterpriseEmployeeEntity> {
}

View File

@ -0,0 +1,239 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.module.business.oa.enterprise.dao.EnterpriseDao;
import net.lab1024.sa.admin.module.business.oa.enterprise.dao.EnterpriseEmployeeDao;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity.EnterpriseEmployeeEntity;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity.EnterpriseEntity;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.form.*;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseEmployeeVO;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseExcelVO;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseListVO;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO;
import net.lab1024.sa.admin.module.business.oa.enterprise.manager.EnterpriseEmployeeManager;
import net.lab1024.sa.admin.module.system.department.service.DepartmentService;
import net.lab1024.sa.base.common.code.UserErrorCode;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartBeanUtil;
import net.lab1024.sa.base.common.util.SmartPageUtil;
import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum;
import net.lab1024.sa.base.module.support.datatracer.domain.form.DataTracerForm;
import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 企业
*
* @Author 1024创新实验室: 开云
* @Date 2022/7/28 20:37:15
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Service
@Slf4j
public class EnterpriseService {
@Resource
private EnterpriseDao enterpriseDao;
@Resource
private EnterpriseEmployeeDao enterpriseEmployeeDao;
@Resource
private EnterpriseEmployeeManager enterpriseEmployeeManager;
@Resource
private DataTracerService dataTracerService;
@Resource
private DepartmentService departmentService;
/**
* 分页查询企业模块
*
*/
public ResponseDTO<PageResult<EnterpriseVO>> queryByPage(EnterpriseQueryForm queryForm) {
queryForm.setDeletedFlag(Boolean.FALSE);
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
List<EnterpriseVO> enterpriseList = enterpriseDao.queryPage(page, queryForm);
PageResult<EnterpriseVO> pageResult = SmartPageUtil.convert2PageResult(page, enterpriseList);
return ResponseDTO.ok(pageResult);
}
/**
* 获取导出数据
*/
public List<EnterpriseExcelVO> getExcelExportData(EnterpriseQueryForm queryForm) {
queryForm.setDeletedFlag(false);
return enterpriseDao.selectExcelExportData(queryForm);
}
/**
* 查询企业详情
*
*/
public EnterpriseVO getDetail(Long enterpriseId) {
return enterpriseDao.getDetail(enterpriseId, Boolean.FALSE);
}
/**
* 新建企业
*
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> createEnterprise(EnterpriseCreateForm createVO) {
// 验证企业名称是否重复
EnterpriseEntity validateEnterprise = enterpriseDao.queryByEnterpriseName(createVO.getEnterpriseName(), null, Boolean.FALSE);
if (Objects.nonNull(validateEnterprise)) {
return ResponseDTO.userErrorParam("企业名称重复");
}
// 数据插入
EnterpriseEntity insertEnterprise = SmartBeanUtil.copy(createVO, EnterpriseEntity.class);
enterpriseDao.insert(insertEnterprise);
dataTracerService.insert(insertEnterprise.getEnterpriseId(), DataTracerTypeEnum.OA_ENTERPRISE);
return ResponseDTO.ok();
}
/**
* 编辑企业
*
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> updateEnterprise(EnterpriseUpdateForm updateVO) {
Long enterpriseId = updateVO.getEnterpriseId();
// 校验企业是否存在
EnterpriseEntity enterpriseDetail = enterpriseDao.selectById(enterpriseId);
if (Objects.isNull(enterpriseDetail) || enterpriseDetail.getDeletedFlag()) {
return ResponseDTO.userErrorParam("企业不存在");
}
// 验证企业名称是否重复
EnterpriseEntity validateEnterprise = enterpriseDao.queryByEnterpriseName(updateVO.getEnterpriseName(), enterpriseId, Boolean.FALSE);
if (Objects.nonNull(validateEnterprise)) {
return ResponseDTO.userErrorParam("企业名称重复");
}
// 数据编辑
EnterpriseEntity updateEntity = SmartBeanUtil.copy(enterpriseDetail, EnterpriseEntity.class);
SmartBeanUtil.copyProperties(updateVO, updateEntity);
enterpriseDao.updateById(updateEntity);
//变更记录
DataTracerForm dataTracerForm = DataTracerForm.builder()
.dataId(updateVO.getEnterpriseId())
.type(DataTracerTypeEnum.OA_ENTERPRISE)
.content("修改企业信息")
.diffOld(dataTracerService.getChangeContent(enterpriseDetail))
.diffNew(dataTracerService.getChangeContent(updateEntity))
.build();
dataTracerService.addTrace(dataTracerForm);
return ResponseDTO.ok();
}
/**
* 删除企业
*
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> deleteEnterprise(Long enterpriseId) {
// 校验企业是否存在
EnterpriseEntity enterpriseDetail = enterpriseDao.selectById(enterpriseId);
if (Objects.isNull(enterpriseDetail) || enterpriseDetail.getDeletedFlag()) {
return ResponseDTO.userErrorParam("企业不存在");
}
enterpriseDao.deleteEnterprise(enterpriseId, Boolean.TRUE);
dataTracerService.delete(enterpriseId, DataTracerTypeEnum.OA_ENTERPRISE);
return ResponseDTO.ok();
}
/**
* 企业列表查询
*/
public ResponseDTO<List<EnterpriseListVO>> queryList(Integer type) {
List<EnterpriseListVO> enterpriseList = enterpriseDao.queryList(type, Boolean.FALSE, Boolean.FALSE);
return ResponseDTO.ok(enterpriseList);
}
//----------------------------------------- 以下为员工相关--------------------------------------------
/**
* 企业添加员工
*
*/
public synchronized ResponseDTO<String> addEmployee(EnterpriseEmployeeForm enterpriseEmployeeForm) {
Long enterpriseId = enterpriseEmployeeForm.getEnterpriseId();
EnterpriseEntity enterpriseEntity = enterpriseDao.selectById(enterpriseId);
if (enterpriseEntity == null || enterpriseEntity.getDeletedFlag()) {
return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
}
//过滤掉已存在的员工
List<Long> waitAddEmployeeIdList = enterpriseEmployeeForm.getEmployeeIdList();
List<EnterpriseEmployeeEntity> enterpriseEmployeeEntityList = enterpriseEmployeeDao.selectByEnterpriseAndEmployeeIdList(enterpriseId, waitAddEmployeeIdList);
if (CollectionUtils.isNotEmpty(enterpriseEmployeeEntityList)) {
List<Long> existEmployeeIdList = enterpriseEmployeeEntityList.stream().map(EnterpriseEmployeeEntity::getEmployeeId).collect(Collectors.toList());
waitAddEmployeeIdList = waitAddEmployeeIdList.stream().filter(e -> !existEmployeeIdList.contains(e)).collect(Collectors.toList());
}
if (CollectionUtils.isEmpty(waitAddEmployeeIdList)) {
return ResponseDTO.ok();
}
List<EnterpriseEmployeeEntity> batchAddList = Lists.newArrayList();
for (Long employeeId : waitAddEmployeeIdList) {
EnterpriseEmployeeEntity enterpriseEmployeeEntity = new EnterpriseEmployeeEntity();
enterpriseEmployeeEntity.setEnterpriseId(enterpriseId);
enterpriseEmployeeEntity.setEmployeeId(employeeId);
batchAddList.add(enterpriseEmployeeEntity);
}
enterpriseEmployeeManager.saveBatch(batchAddList);
return ResponseDTO.ok();
}
/**
* 企业删除员工
*
*/
public synchronized ResponseDTO<String> deleteEmployee(EnterpriseEmployeeForm enterpriseEmployeeForm) {
Long enterpriseId = enterpriseEmployeeForm.getEnterpriseId();
EnterpriseEntity enterpriseEntity = enterpriseDao.selectById(enterpriseId);
if (enterpriseEntity == null || enterpriseEntity.getDeletedFlag()) {
return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
}
List<Long> waitDeleteEmployeeIdList = enterpriseEmployeeForm.getEmployeeIdList();
enterpriseEmployeeDao.deleteByEnterpriseAndEmployeeIdList(enterpriseId, waitDeleteEmployeeIdList);
return ResponseDTO.ok();
}
/**
* 企业下员工列表
*
*/
public List<EnterpriseEmployeeVO> employeeList(List<Long> enterpriseIdList) {
if (CollectionUtils.isEmpty(enterpriseIdList)) {
return Lists.newArrayList();
}
return enterpriseEmployeeDao.selectByEnterpriseIdList(enterpriseIdList);
}
/**
* 分页查询企业员工
*
*/
public PageResult<EnterpriseEmployeeVO> queryPageEmployeeList(EnterpriseEmployeeQueryForm queryForm) {
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
List<EnterpriseEmployeeVO> enterpriseEmployeeVOList = enterpriseEmployeeDao.queryPageEmployeeList(page, queryForm);
for (EnterpriseEmployeeVO enterpriseEmployeeVO : enterpriseEmployeeVOList) {
enterpriseEmployeeVO.setDepartmentName(departmentService.getDepartmentPath(enterpriseEmployeeVO.getDepartmentId()));
}
return SmartPageUtil.convert2PageResult(page, enterpriseEmployeeVOList);
}
}

View File

@ -0,0 +1,88 @@
package net.lab1024.sa.admin.module.business.oa.invoice.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
import net.lab1024.sa.admin.module.business.oa.invoice.service.InvoiceService;
import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceAddForm;
import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceQueryForm;
import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceUpdateForm;
import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceVO;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.domain.RequestUser;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartRequestUtil;
import net.lab1024.sa.base.module.support.operatelog.annotation.OperateLog;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* OA发票信息
*
* @Author 1024创新实验室: 善逸
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Slf4j
@RestController
@Tag(name = AdminSwaggerTagConst.Business.OA_INVOICE)
public class InvoiceController {
@Resource
private InvoiceService invoiceService;
@Operation(summary = "分页查询发票信息 @author 善逸")
@PostMapping("/oa/invoice/page/query")
@SaCheckPermission("oa:invoice:query")
public ResponseDTO<PageResult<InvoiceVO>> queryByPage(@RequestBody @Valid InvoiceQueryForm queryForm) {
return invoiceService.queryByPage(queryForm);
}
@Operation(summary = "查询发票信息详情 @author 善逸")
@GetMapping("/oa/invoice/get/{invoiceId}")
@SaCheckPermission("oa:invoice:query")
public ResponseDTO<InvoiceVO> getDetail(@PathVariable Long invoiceId) {
return invoiceService.getDetail(invoiceId);
}
@Operation(summary = "新建发票信息 @author 善逸")
@PostMapping("/oa/invoice/create")
@SaCheckPermission("oa:invoice:add")
public ResponseDTO<String> createInvoice(@RequestBody @Valid InvoiceAddForm createVO) {
RequestUser requestUser = SmartRequestUtil.getRequestUser();
createVO.setCreateUserId(requestUser.getUserId());
createVO.setCreateUserName(requestUser.getUserName());
return invoiceService.createInvoice(createVO);
}
@OperateLog
@Operation(summary = "编辑发票信息 @author 善逸")
@PostMapping("/oa/invoice/update")
@SaCheckPermission("oa:invoice:update")
public ResponseDTO<String> updateInvoice(@RequestBody @Valid InvoiceUpdateForm updateVO) {
return invoiceService.updateInvoice(updateVO);
}
@Operation(summary = "删除发票信息 @author 善逸")
@GetMapping("/invoice/delete/{invoiceId}")
@SaCheckPermission("oa:invoice:delete")
public ResponseDTO<String> deleteInvoice(@PathVariable Long invoiceId) {
return invoiceService.deleteInvoice(invoiceId);
}
@Operation(summary = "查询列表 @author lidoudou")
@GetMapping("/oa/invoice/query/list/{enterpriseId}")
@SaCheckPermission("oa:invoice:query")
public ResponseDTO<List<InvoiceVO>> queryList(@PathVariable Long enterpriseId) {
return invoiceService.queryList(enterpriseId);
}
}

View File

@ -0,0 +1,59 @@
package net.lab1024.sa.admin.module.business.oa.invoice.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceEntity;
import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceQueryForm;
import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* OA发票信息
*
* @Author 1024创新实验室: 善逸
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Mapper
public interface InvoiceDao extends BaseMapper<InvoiceEntity> {
/**
* 根据账号查询
* @param enterpriseId
* @param accountNumber
* @param excludeInvoiceId
* @param deletedFlag
* @return
*/
InvoiceEntity queryByAccountNumber(@Param("enterpriseId") Long enterpriseId, @Param("accountNumber") String accountNumber, @Param("excludeInvoiceId") Long excludeInvoiceId, @Param("deletedFlag") Boolean deletedFlag);
/**
* 删除发票信息
*
* @param invoiceId
* @param deletedFlag
*/
void deleteInvoice(@Param("invoiceId") Long invoiceId, @Param("deletedFlag") Boolean deletedFlag);
/**
* 发票信息分页查询
*
* @param page
* @param queryForm
* @return
*/
List<InvoiceVO> queryPage(Page page, @Param("queryForm") InvoiceQueryForm queryForm);
/**
* 查询发票信息详情
* @param invoiceId
* @param deletedFlag
* @return
*/
InvoiceVO getDetail(@Param("invoiceId") Long invoiceId, @Param("deletedFlag") Boolean deletedFlag);
}

View File

@ -0,0 +1,58 @@
package net.lab1024.sa.admin.module.business.oa.invoice.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
/**
* OA发票信息新建
*
* @Author 1024创新实验室: 善逸
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class InvoiceAddForm {
@Schema(description = "开票抬头")
@NotBlank(message = "开票抬头不能为空")
@Length(max = 200, message = "开票抬头最多200字符")
private String invoiceHeads;
@Schema(description = "纳税人识别号")
@NotBlank(message = "纳税人识别号不能为空")
@Length(max = 200, message = "纳税人识别号最多200字符")
private String taxpayerIdentificationNumber;
@Schema(description = "银行账户")
@NotBlank(message = "银行账户不能为空")
@Length(max = 200, message = "银行账户最多200字符")
private String accountNumber;
@Schema(description = "开户行")
@NotBlank(message = "开户行不能为空")
@Length(max = 200, message = "开户行最多200字符")
private String bankName;
@Schema(description = "启用状态")
@NotNull(message = "启用状态不能为空")
private Boolean disabledFlag;
@Schema(description = "备注")
@Length(max = 500, message = "备注最多500字符")
private String remark;
@Schema(description = "企业")
@NotNull(message = "企业不能为空")
private Long enterpriseId;
@Schema(description = "创建人", hidden = true)
private Long createUserId;
@Schema(description = "创建人名称", hidden = true)
private String createUserName;
}

View File

@ -0,0 +1,98 @@
package net.lab1024.sa.admin.module.business.oa.invoice.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import net.lab1024.sa.base.module.support.datatracer.annoation.DataTracerFieldLabel;
import java.time.LocalDateTime;
/**
* OA发票信息
*
* @Author 1024创新实验室: 善逸
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
@TableName("t_oa_invoice")
public class InvoiceEntity {
/**
* 发票信息ID
*/
@TableId(type = IdType.AUTO)
private Long invoiceId;
/**
* 开票抬头
*/
@DataTracerFieldLabel("开票抬头")
private String invoiceHeads;
/**
* 纳税人识别号
*/
@DataTracerFieldLabel("纳税人识别号")
private String taxpayerIdentificationNumber;
/**
* 银行账户
*/
@DataTracerFieldLabel("银行账户")
private String accountNumber;
/**
* 开户行
*/
@DataTracerFieldLabel("开户行")
private String bankName;
/**
* 备注
*/
@DataTracerFieldLabel("备注")
private String remark;
/**
* 企业ID
*/
private Long enterpriseId;
/**
* 禁用状态
*/
@DataTracerFieldLabel("禁用状态")
private Boolean disabledFlag;
/**
* 删除状态
*/
@DataTracerFieldLabel("删除状态")
private Boolean deletedFlag;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人ID
*/
private String createUserName;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,40 @@
package net.lab1024.sa.admin.module.business.oa.invoice.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import net.lab1024.sa.base.common.domain.PageParam;
import org.hibernate.validator.constraints.Length;
import java.time.LocalDate;
/**
* OA发票信息查询
*
* @Author 1024创新实验室: 善逸
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class InvoiceQueryForm extends PageParam {
@Schema(description = "企业ID")
private Long enterpriseId;
@Schema(description = "关键字")
@Length(max = 200, message = "关键字最多200字符")
private String keywords;
@Schema(description = "开始时间")
private LocalDate startTime;
@Schema(description = "结束时间")
private LocalDate endTime;
@Schema(description = "禁用状态")
private Boolean disabledFlag;
@Schema(description = "删除状态", hidden = true)
private Boolean deletedFlag;
}

View File

@ -0,0 +1,22 @@
package net.lab1024.sa.admin.module.business.oa.invoice.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* OA发票信息编辑
*
* @Author 1024创新实验室: 善逸
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class InvoiceUpdateForm extends InvoiceAddForm {
@Schema(description = "发票信息ID")
@NotNull(message = "发票信息ID不能为空")
private Long invoiceId;
}

View File

@ -0,0 +1,58 @@
package net.lab1024.sa.admin.module.business.oa.invoice.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* OA发票信息
*
* @Author 1024创新实验室: 善逸
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class InvoiceVO {
@Schema(description = "发票信息ID")
private Long invoiceId;
@Schema(description = "开票抬头")
private String invoiceHeads;
@Schema(description = "纳税人识别号")
private String taxpayerIdentificationNumber;
@Schema(description = "银行账户")
private String accountNumber;
@Schema(description = "开户行")
private String bankName;
@Schema(description = "备注")
private String remark;
@Schema(description = "企业")
private Long enterpriseId;
@Schema(description = "企业名称")
private String enterpriseName;
@Schema(description = "禁用状态")
private Boolean disabledFlag;
@Schema(description = "创建人ID")
private Long createUserId;
@Schema(description = "创建人名称")
private String createUserName;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "更新时间")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,144 @@
package net.lab1024.sa.admin.module.business.oa.invoice.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.module.business.oa.enterprise.service.EnterpriseService;
import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO;
import net.lab1024.sa.admin.module.business.oa.invoice.dao.InvoiceDao;
import net.lab1024.sa.admin.module.business.oa.invoice.domain.*;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartBeanUtil;
import net.lab1024.sa.base.common.util.SmartPageUtil;
import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerConst;
import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum;
import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Objects;
/**
* OA发票信息
*
* @Author 1024创新实验室: 善逸
* @Date 2022-06-23 19:32:59
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Service
@Slf4j
public class InvoiceService {
@Resource
private InvoiceDao invoiceDao;
@Resource
private EnterpriseService enterpriseService;
@Resource
private DataTracerService dataTracerService;
/**
* 分页查询发票信息
*/
public ResponseDTO<PageResult<InvoiceVO>> queryByPage(InvoiceQueryForm queryForm) {
queryForm.setDeletedFlag(Boolean.FALSE);
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
List<InvoiceVO> invoiceList = invoiceDao.queryPage(page, queryForm);
PageResult<InvoiceVO> pageResult = SmartPageUtil.convert2PageResult(page, invoiceList);
return ResponseDTO.ok(pageResult);
}
public ResponseDTO<List<InvoiceVO>> queryList(Long enterpriseId) {
InvoiceQueryForm queryForm = new InvoiceQueryForm();
queryForm.setDeletedFlag(Boolean.FALSE);
queryForm.setDisabledFlag(Boolean.FALSE);
queryForm.setEnterpriseId(enterpriseId);
List<InvoiceVO> invoiceList = invoiceDao.queryPage(null, queryForm);
return ResponseDTO.ok(invoiceList);
}
/**
* 查询发票信息详情
*/
public ResponseDTO<InvoiceVO> getDetail(Long invoiceId) {
// 校验发票信息是否存在
InvoiceVO invoiceVO = invoiceDao.getDetail(invoiceId, Boolean.FALSE);
if (Objects.isNull(invoiceVO)) {
return ResponseDTO.userErrorParam("发票信息不存在");
}
return ResponseDTO.ok(invoiceVO);
}
/**
* 新建发票信息
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> createInvoice(InvoiceAddForm createVO) {
Long enterpriseId = createVO.getEnterpriseId();
// 校验企业是否存在
EnterpriseVO enterpriseVO = enterpriseService.getDetail(enterpriseId);
if (Objects.isNull(enterpriseVO)) {
return ResponseDTO.userErrorParam("企业不存在");
}
// 验证发票信息账号是否重复
InvoiceEntity validateInvoice = invoiceDao.queryByAccountNumber(enterpriseId, createVO.getAccountNumber(), null, Boolean.FALSE);
if (Objects.nonNull(validateInvoice)) {
return ResponseDTO.userErrorParam("发票信息账号重复");
}
// 数据插入
InvoiceEntity insertInvoice = SmartBeanUtil.copy(createVO, InvoiceEntity.class);
invoiceDao.insert(insertInvoice);
dataTracerService.addTrace(enterpriseId, DataTracerTypeEnum.OA_ENTERPRISE, "新增发票:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(insertInvoice));
return ResponseDTO.ok();
}
/**
* 编辑发票信息
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> updateInvoice(InvoiceUpdateForm updateVO) {
Long enterpriseId = updateVO.getEnterpriseId();
// 校验企业是否存在
EnterpriseVO enterpriseVO = enterpriseService.getDetail(enterpriseId);
if (Objects.isNull(enterpriseVO)) {
return ResponseDTO.userErrorParam("企业不存在");
}
Long invoiceId = updateVO.getInvoiceId();
// 校验发票信息是否存在
InvoiceEntity invoiceDetail = invoiceDao.selectById(invoiceId);
if (Objects.isNull(invoiceDetail) || invoiceDetail.getDeletedFlag()) {
return ResponseDTO.userErrorParam("发票信息不存在");
}
// 验证发票信息账号是否重复
InvoiceEntity validateInvoice = invoiceDao.queryByAccountNumber(updateVO.getEnterpriseId(), updateVO.getAccountNumber(), invoiceId, Boolean.FALSE);
if (Objects.nonNull(validateInvoice)) {
return ResponseDTO.userErrorParam("发票信息账号重复");
}
// 数据编辑
InvoiceEntity updateInvoice = SmartBeanUtil.copy(updateVO, InvoiceEntity.class);
invoiceDao.updateById(updateInvoice);
dataTracerService.addTrace(enterpriseId, DataTracerTypeEnum.OA_ENTERPRISE, "更新发票:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(invoiceDetail, updateInvoice));
return ResponseDTO.ok();
}
/**
* 删除发票信息
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> deleteInvoice(Long invoiceId) {
// 校验发票信息是否存在
InvoiceEntity invoiceDetail = invoiceDao.selectById(invoiceId);
if (Objects.isNull(invoiceDetail) || invoiceDetail.getDeletedFlag()) {
return ResponseDTO.userErrorParam("发票信息不存在");
}
invoiceDao.deleteInvoice(invoiceId, Boolean.TRUE);
dataTracerService.addTrace(invoiceDetail.getEnterpriseId(), DataTracerTypeEnum.OA_ENTERPRISE, "删除发票:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(invoiceDetail));
return ResponseDTO.ok();
}
}

View File

@ -0,0 +1,36 @@
package net.lab1024.sa.admin.module.business.oa.notice.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.lab1024.sa.base.common.enumeration.BaseEnum;
/**
* 公告通知 可见范围类型
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Getter
@AllArgsConstructor
public enum NoticeVisibleRangeDataTypeEnum implements BaseEnum {
/**
* 员工
*/
EMPLOYEE(1, "员工"),
/**
* 部门
*/
DEPARTMENT(2, "部门"),
;
private final Integer value;
private final String desc;
}

View File

@ -0,0 +1,140 @@
package net.lab1024.sa.admin.module.business.oa.notice.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.extra.servlet.JakartaServletUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
import net.lab1024.sa.admin.module.business.oa.notice.domain.form.*;
import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.*;
import net.lab1024.sa.admin.module.business.oa.notice.service.NoticeEmployeeService;
import net.lab1024.sa.admin.module.business.oa.notice.service.NoticeService;
import net.lab1024.sa.admin.module.business.oa.notice.service.NoticeTypeService;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartRequestUtil;
import net.lab1024.sa.base.module.support.operatelog.annotation.OperateLog;
import net.lab1024.sa.base.module.support.repeatsubmit.annoation.RepeatSubmit;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 公告通知新闻等等
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat 卓大1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Tag(name = AdminSwaggerTagConst.Business.OA_NOTICE)
@RestController
@OperateLog
public class NoticeController {
@Resource
private NoticeService noticeService;
@Resource
private NoticeTypeService noticeTypeService;
@Resource
private NoticeEmployeeService noticeEmployeeService;
// --------------------- 通知公告类型 -------------------------
@Operation(summary = "通知公告类型-获取全部 @author 卓大")
@GetMapping("/oa/noticeType/getAll")
public ResponseDTO<List<NoticeTypeVO>> getAll() {
return ResponseDTO.ok(noticeTypeService.getAll());
}
@Operation(summary = "通知公告类型-添加 @author 卓大")
@GetMapping("/oa/noticeType/add/{name}")
public ResponseDTO<String> add(@PathVariable String name) {
return noticeTypeService.add(name);
}
@Operation(summary = "通知公告类型-修改 @author 卓大")
@GetMapping("/oa/noticeType/update/{noticeTypeId}/{name}")
public ResponseDTO<String> update(@PathVariable Long noticeTypeId, @PathVariable String name) {
return noticeTypeService.update(noticeTypeId, name);
}
@Operation(summary = "通知公告类型-删除 @author 卓大")
@GetMapping("/oa/noticeType/delete/{noticeTypeId}")
public ResponseDTO<String> deleteNoticeType(@PathVariable Long noticeTypeId) {
return noticeTypeService.delete(noticeTypeId);
}
// --------------------- 管理通知公告-------------------------
@Operation(summary = "【管理】通知公告-分页查询 @author 卓大")
@PostMapping("/oa/notice/query")
@SaCheckPermission("oa:notice:query")
public ResponseDTO<PageResult<NoticeVO>> query(@RequestBody @Valid NoticeQueryForm queryForm) {
return ResponseDTO.ok(noticeService.query(queryForm));
}
@Operation(summary = "【管理】通知公告-添加 @author 卓大")
@PostMapping("/oa/notice/add")
@RepeatSubmit
@SaCheckPermission("oa:notice:add")
public ResponseDTO<String> add(@RequestBody @Valid NoticeAddForm addForm) {
addForm.setCreateUserId(SmartRequestUtil.getRequestUserId());
return noticeService.add(addForm);
}
@Operation(summary = "【管理】通知公告-更新 @author 卓大")
@PostMapping("/oa/notice/update")
@RepeatSubmit
@SaCheckPermission("oa:notice:update")
public ResponseDTO<String> update(@RequestBody @Valid NoticeUpdateForm updateForm) {
return noticeService.update(updateForm);
}
@Operation(summary = "【管理】通知公告-更新详情 @author 卓大")
@GetMapping("/oa/notice/getUpdateVO/{noticeId}")
@SaCheckPermission("oa:notice:update")
public ResponseDTO<NoticeUpdateFormVO> getUpdateFormVO(@PathVariable Long noticeId) {
return ResponseDTO.ok(noticeService.getUpdateFormVO(noticeId));
}
@Operation(summary = "【管理】通知公告-删除 @author 卓大")
@GetMapping("/oa/notice/delete/{noticeId}")
@SaCheckPermission("oa:notice:delete")
public ResponseDTO<String> delete(@PathVariable Long noticeId) {
return noticeService.delete(noticeId);
}
// --------------------- 员工查看 通知公告 -------------------------
@Operation(summary = "【员工】通知公告-查看详情 @author 卓大")
@GetMapping("/oa/notice/employee/view/{noticeId}")
public ResponseDTO<NoticeDetailVO> view(@PathVariable Long noticeId, HttpServletRequest request) {
return noticeEmployeeService.view(
SmartRequestUtil.getRequestUserId(),
noticeId,
JakartaServletUtil.getClientIP(request),
request.getHeader("User-Agent")
);
}
@Operation(summary = "【员工】通知公告-查询全部 @author 卓大")
@PostMapping("/oa/notice/employee/query")
public ResponseDTO<PageResult<NoticeEmployeeVO>> queryEmployeeNotice(@RequestBody @Valid NoticeEmployeeQueryForm noticeEmployeeQueryForm) {
return noticeEmployeeService.queryList(SmartRequestUtil.getRequestUserId(), noticeEmployeeQueryForm);
}
@Operation(summary = "【员工】通知公告-查询 查看记录 @author 卓大")
@PostMapping("/oa/notice/employee/queryViewRecord")
public ResponseDTO<PageResult<NoticeViewRecordVO>> queryViewRecord(@RequestBody @Valid NoticeViewRecordQueryForm noticeViewRecordQueryForm) {
return ResponseDTO.ok(noticeEmployeeService.queryViewRecord(noticeViewRecordQueryForm));
}
}

View File

@ -0,0 +1,126 @@
package net.lab1024.sa.admin.module.business.oa.notice.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.lab1024.sa.admin.module.business.oa.notice.domain.entity.NoticeEntity;
import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeEmployeeQueryForm;
import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeQueryForm;
import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeViewRecordQueryForm;
import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeVisibleRangeForm;
import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeEmployeeVO;
import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVO;
import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeViewRecordVO;
import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVisibleRangeVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 公告通知新闻等等
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Mapper
public interface NoticeDao extends BaseMapper<NoticeEntity> {
// ================================= 数据范围相关 子表 =================================
/**
* 保存可见范围
*
*/
void insertVisibleRange(@Param("noticeId") Long noticeId, @Param("visibleRangeFormList") List<NoticeVisibleRangeForm> visibleRangeFormList);
/**
* 删除可见范围
*
*/
void deleteVisibleRange(@Param("noticeId") Long noticeId);
/**
* 相关可见范围
*
*/
List<NoticeVisibleRangeVO> queryVisibleRange(@Param("noticeId") Long noticeId);
// ================================= 通知公告主表 相关 =================================
/**
* 后管分页查询资讯
*
*/
List<NoticeVO> query(Page<?> page, @Param("query") NoticeQueryForm queryForm);
/**
* 更新删除状态
*
*/
void updateDeletedFlag(@Param("noticeId") Long noticeId);
// ================================= 通知公告员工查看 相关 =================================
/**
* 查询 员工 查看到的通知公告
*
*/
List<NoticeEmployeeVO> queryEmployeeNotice(Page<?> page,
@Param("requestEmployeeId") Long requestEmployeeId,
@Param("query") NoticeEmployeeQueryForm noticeEmployeeQueryForm,
@Param("requestEmployeeDepartmentIdList") List<Long> requestEmployeeDepartmentIdList,
@Param("deletedFlag") boolean deletedFlag,
@Param("administratorFlag") boolean administratorFlag,
@Param("departmentDataType") Integer departmentDataType,
@Param("employeeDataType") Integer employeeDataType
);
/**
* 查询 员工 未读的通知公告
*
*/
List<NoticeEmployeeVO> queryEmployeeNotViewNotice(Page<?> page,
@Param("requestEmployeeId") Long requestEmployeeId,
@Param("query") NoticeEmployeeQueryForm noticeEmployeeQueryForm,
@Param("requestEmployeeDepartmentIdList") List<Long> requestEmployeeDepartmentIdList,
@Param("deletedFlag") boolean deletedFlag,
@Param("administratorFlag") boolean administratorFlag,
@Param("departmentDataType") Integer departmentDataType,
@Param("employeeDataType") Integer employeeDataType
);
long viewRecordCount(@Param("noticeId")Long noticeId, @Param("employeeId")Long employeeId);
/**
* 查询通知公告的 查看记录
*/
List<NoticeViewRecordVO> queryNoticeViewRecordList(Page page,@Param("queryForm") NoticeViewRecordQueryForm noticeViewRecordQueryForm);
/**
* 保存查看记录
*/
void insertViewRecord(@Param("noticeId") Long noticeId, @Param("employeeId") Long employeeId, @Param("ip") String ip, @Param("userAgent") String userAgent,@Param("pageViewCount") Integer pageViewCount);
/**
* 更新查看记录
*/
void updateViewRecord(@Param("noticeId")Long noticeId, @Param("employeeId")Long requestEmployeeId,@Param("ip") String ip, @Param("userAgent")String userAgent);
/**
* 更新 浏览量
*
* @param noticeId 通知 id
* @param pageViewCountIncrement 页面浏览量的增量
* @param userViewCountIncrement 用户浏览量的增量
*/
void updateViewCount(@Param("noticeId")Long noticeId,@Param("pageViewCountIncrement") Integer pageViewCountIncrement, @Param("userViewCountIncrement")Integer userViewCountIncrement);
}

View File

@ -0,0 +1,20 @@
package net.lab1024.sa.admin.module.business.oa.notice.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.lab1024.sa.admin.module.business.oa.notice.domain.entity.NoticeTypeEntity;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;
/**
* 通知公告类型
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Mapper
public interface NoticeTypeDao extends BaseMapper<NoticeTypeEntity> {
}

View File

@ -0,0 +1,99 @@
package net.lab1024.sa.admin.module.business.oa.notice.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 通知公告
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
@TableName("t_notice")
public class NoticeEntity {
@TableId(type = IdType.AUTO)
private Long noticeId;
/**
* 类型
*/
private Long noticeTypeId;
/**
* 标题
*/
private String title;
/**
* 是否全部可见
*/
private Boolean allVisibleFlag;
/**
* 是否定时发布
*/
private Boolean scheduledPublishFlag;
/**
* 发布时间
*/
private LocalDateTime publishTime;
/**
* 内容 纯文本
*/
private String contentText;
/**
* 内容 html
*/
private String contentHtml;
/**
* 附件
* 多个英文逗号分隔
*/
private String attachment;
/**
* 页面浏览量
*/
private Integer pageViewCount;
/**
* 用户浏览量
*/
private Integer userViewCount;
/**
* 来源
*/
private String source;
/**
* 作者
*/
private String author;
/**
* 文号
*/
private String documentNumber;
private Boolean deletedFlag;
private Long createUserId;
private LocalDateTime updateTime;
private LocalDateTime createTime;
}

View File

@ -0,0 +1,41 @@
package net.lab1024.sa.admin.module.business.oa.notice.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 通知公告类型
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
@TableName("t_notice_type")
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class NoticeTypeEntity {
@TableId(type = IdType.AUTO)
private Long noticeTypeId;
/**
* 名称
*/
private String noticeTypeName;
private LocalDateTime updateTime;
private LocalDateTime createTime;
}

View File

@ -0,0 +1,78 @@
package net.lab1024.sa.admin.module.business.oa.notice.domain.form;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import net.lab1024.sa.base.common.json.deserializer.FileKeyVoDeserializer;
import org.hibernate.validator.constraints.Length;
import java.time.LocalDateTime;
import java.util.List;
/**
* 通知公告 添加表单
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class NoticeAddForm {
@Schema(description = "标题")
@NotBlank(message = "标题不能为空")
@Length(max = 200, message = "标题最多200字符")
private String title;
@Schema(description = "分类")
@NotNull(message = "分类不能为空")
private Long noticeTypeId;
@Schema(description = "是否全部可见")
@NotNull(message = "是否全部可见不能为空")
private Boolean allVisibleFlag;
@Schema(description = "是否定时发布")
@NotNull(message = "是否定时发布不能为空")
private Boolean scheduledPublishFlag;
@Schema(description = "发布时间")
@NotNull(message = "发布时间不能为空")
private LocalDateTime publishTime;
@Schema(description = "纯文本内容")
@NotNull(message = "文本内容不能为空")
private String contentText;
@Schema(description = "html内容")
@NotNull(message = "html内容不能为空")
private String contentHtml;
@Schema(description = "附件,多个英文逗号分隔|可选")
@Length(max = 1000, message = "最多1000字符")
@JsonDeserialize(using = FileKeyVoDeserializer.class)
private String attachment;
@Schema(description = "作者")
@NotBlank(message = "作者不能为空")
private String author;
@Schema(description = "来源")
@NotBlank(message = "标题不能为空")
private String source;
@Schema(description = "文号")
private String documentNumber;
@Schema(hidden = true)
private Long createUserId;
@Schema(description = "可见范围设置|可选")
@Valid
private List<NoticeVisibleRangeForm> visibleRangeList;
}

View File

@ -0,0 +1,35 @@
package net.lab1024.sa.admin.module.business.oa.notice.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import net.lab1024.sa.base.common.domain.PageParam;
import java.time.LocalDate;
/**
* 通知公告 员工查询表单
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class NoticeEmployeeQueryForm extends PageParam {
@Schema(description = "标题、作者、来源、文号")
private String keywords;
@Schema(description = "分类")
private Long noticeTypeId;
@Schema(description = "发布-开始时间")
private LocalDate publishTimeBegin;
@Schema(description = "未读标识")
private Boolean notViewFlag;
@Schema(description = "发布-截止时间")
private LocalDate publishTimeEnd;
}

View File

@ -0,0 +1,48 @@
package net.lab1024.sa.admin.module.business.oa.notice.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import net.lab1024.sa.base.common.domain.PageParam;
import java.time.LocalDate;
/**
* 通知公告 管理查询表单
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class NoticeQueryForm extends PageParam {
@Schema(description = "分类")
private Long noticeTypeId;
@Schema(description = "标题、作者、来源")
private String keywords;
@Schema(description = "文号")
private String documentNumber;
@Schema(description = "创建人")
private String createUserName;
@Schema(description = "删除标识")
private Boolean deletedFlag;
@Schema(description = "创建-开始时间")
private LocalDate createTimeBegin;
@Schema(description = "创建-截止时间")
private LocalDate createTimeEnd;
@Schema(description = "发布-开始时间")
private LocalDate publishTimeBegin;
@Schema(description = "发布-截止时间")
private LocalDate publishTimeEnd;
}

View File

@ -0,0 +1,23 @@
package net.lab1024.sa.admin.module.business.oa.notice.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* 通知公告 更新表单
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class NoticeUpdateForm extends NoticeAddForm {
@Schema(description = "id")
@NotNull(message = "通知id不能为空")
private Long noticeId;
}

View File

@ -0,0 +1,31 @@
package net.lab1024.sa.admin.module.business.oa.notice.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import net.lab1024.sa.base.common.domain.PageParam;
/**
* 通知公告 阅读记录查询
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class NoticeViewRecordQueryForm extends PageParam {
@Schema(description = "通知公告id")
@NotNull(message = "通知公告id不能为空")
private Long noticeId;
@Schema(description = "部门id")
private Long departmentId;
@Schema(description = "关键字")
private String keywords;
}

View File

@ -0,0 +1,33 @@
package net.lab1024.sa.admin.module.business.oa.notice.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import net.lab1024.sa.admin.module.business.oa.notice.constant.NoticeVisibleRangeDataTypeEnum;
import net.lab1024.sa.base.common.swagger.SchemaEnum;
import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;
/**
* 通知公告 可见范围数据
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class NoticeVisibleRangeForm {
@SchemaEnum(NoticeVisibleRangeDataTypeEnum.class)
@CheckEnum(value = NoticeVisibleRangeDataTypeEnum.class, required = true, message = "数据类型错误")
private Integer dataType;
@Schema(description = "员工/部门id")
@NotNull(message = "员工/部门id不能为空")
private Long dataId;
}

View File

@ -0,0 +1,84 @@
package net.lab1024.sa.admin.module.business.oa.notice.domain.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import net.lab1024.sa.base.common.json.serializer.FileKeyVoSerializer;
import java.time.LocalDateTime;
/**
* 通知公告 详情
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class NoticeDetailVO {
@Schema(description = "id")
private Long noticeId;
@Schema(description = "标题")
private String title;
@Schema(description = "分类")
private Long noticeTypeId;
@Schema(description = "分类名称")
private Long noticeTypeName;
@Schema(description = "是否全部可见")
@NotNull(message = "是否全部可见不能为空")
private Boolean allVisibleFlag;
@Schema(description = "是否定时发布")
@NotNull(message = "是否定时发布不能为空")
private Boolean scheduledPublishFlag;
@Schema(description = "纯文本内容")
private String contentText;
@Schema(description = "html内容")
private String contentHtml;
@Schema(description = "附件")
@JsonSerialize(using = FileKeyVoSerializer.class)
private String attachment;
@Schema(description = "发布时间")
@NotNull(message = "发布时间不能为空")
private LocalDateTime publishTime;
@Schema(description = "作者")
@NotBlank(message = "作者不能为空")
private String author;
@Schema(description = "来源")
@NotBlank(message = "标题不能为空")
private String source;
@Schema(description = "文号")
private String documentNumber;
@Schema(description = "页面浏览量")
private Integer pageViewCount;
@Schema(description = "用户浏览量")
private Integer userViewCount;
@Schema(description = "创建人名称")
private Long createUserName;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "更新时间")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,26 @@
package net.lab1024.sa.admin.module.business.oa.notice.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDate;
/**
* 通知公告 员工查看
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class NoticeEmployeeVO extends NoticeVO {
@Schema(description = "是否查看")
private Boolean viewFlag;
@Schema(description = "发布日期")
private LocalDate publishDate;
}

View File

@ -0,0 +1,24 @@
package net.lab1024.sa.admin.module.business.oa.notice.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 通知公告 类型
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class NoticeTypeVO {
@Schema(description = "通知类型id")
private Long noticeTypeId;
@Schema(description = "通知类型-名称")
private String noticeTypeName;
}

View File

@ -0,0 +1,35 @@
package net.lab1024.sa.admin.module.business.oa.notice.domain.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import net.lab1024.sa.base.common.json.serializer.FileKeyVoSerializer;
import java.util.List;
/**
* 用于更新 通知公告 VO 对象
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class NoticeUpdateFormVO extends NoticeVO {
@Schema(description = "纯文本内容")
private String contentText;
@Schema(description = "html内容")
private String contentHtml;
@Schema(description = "附件")
@JsonSerialize(using = FileKeyVoSerializer.class)
private String attachment;
@Schema(description = "可见范围")
private List<NoticeVisibleRangeVO> visibleRangeList;
}

View File

@ -0,0 +1,72 @@
package net.lab1024.sa.admin.module.business.oa.notice.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 新闻公告 VO
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class NoticeVO {
@Schema(description = "id")
private Long noticeId;
@Schema(description = "标题")
private String title;
@Schema(description = "分类")
private Long noticeTypeId;
@Schema(description = "分类名称")
private String noticeTypeName;
@Schema(description = "是否全部可见")
private Boolean allVisibleFlag;
@Schema(description = "是否定时发布")
private Boolean scheduledPublishFlag;
@Schema(description = "发布状态")
private Boolean publishFlag;
@Schema(description = "发布时间")
private LocalDateTime publishTime;
@Schema(description = "作者")
private String author;
@Schema(description = "来源")
private String source;
@Schema(description = "文号")
private String documentNumber;
@Schema(description = "页面浏览量")
private Integer pageViewCount;
@Schema(description = "用户浏览量")
private Integer userViewCount;
@Schema(description = "删除标识")
private Boolean deletedFlag;
@Schema(description = "创建人名称")
private String createUserName;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "更新时间")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,49 @@
package net.lab1024.sa.admin.module.business.oa.notice.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 浏览记录 VO
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class NoticeViewRecordVO {
@Schema(description = "员工ID")
private Long employeeId;
@Schema(description = "员工姓名")
private String employeeName;
@Schema(description = "员工部门名称")
private String departmentName;
@Schema(description = "查看次数")
private Integer pageViewCount;
@Schema(description = "首次ip")
private String firstIp;
@Schema(description = "首次用户设备等标识")
private String firstUserAgent;
@Schema(description = "首次查看时间")
private LocalDateTime createTime;
@Schema(description = "最后一次 ip")
private String lastIp;
@Schema(description = "最后一次 用户设备等标识")
private String lastUserAgent;
@Schema(description = "最后一次查看时间")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,29 @@
package net.lab1024.sa.admin.module.business.oa.notice.domain.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import net.lab1024.sa.admin.module.business.oa.notice.constant.NoticeVisibleRangeDataTypeEnum;
import net.lab1024.sa.base.common.swagger.SchemaEnum;
/**
* 新闻公告 可见范围数据 VO
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class NoticeVisibleRangeVO {
@SchemaEnum(NoticeVisibleRangeDataTypeEnum.class)
private Integer dataType;
@Schema(description = "员工/部门id")
private Long dataId;
@Schema(description = "员工/部门 名称")
private String dataName;
}

View File

@ -0,0 +1,62 @@
package net.lab1024.sa.admin.module.business.oa.notice.manager;
import jakarta.annotation.Resource;
import net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeDao;
import net.lab1024.sa.admin.module.business.oa.notice.domain.entity.NoticeEntity;
import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeVisibleRangeForm;
import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum;
import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* 通知公告 manager
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Service
public class NoticeManager {
@Resource
private NoticeDao noticeDao;
@Resource
private DataTracerService dataTracerService;
/**
* 保存
*/
@Transactional(rollbackFor = Throwable.class)
public void save(NoticeEntity noticeEntity, List<NoticeVisibleRangeForm> visibleRangeFormList) {
noticeDao.insert(noticeEntity);
Long noticeId = noticeEntity.getNoticeId();
// 保存可见范围
if (CollectionUtils.isNotEmpty(visibleRangeFormList)) {
noticeDao.insertVisibleRange(noticeId, visibleRangeFormList);
}
dataTracerService.insert(noticeId, DataTracerTypeEnum.OA_NOTICE);
}
/**
* 更新
*
*/
@Transactional(rollbackFor = Throwable.class)
public void update(NoticeEntity old, NoticeEntity noticeEntity, List<NoticeVisibleRangeForm> visibleRangeList) {
noticeDao.updateById(noticeEntity);
Long noticeId = noticeEntity.getNoticeId();
// 保存可见范围
if (CollectionUtils.isNotEmpty(visibleRangeList)) {
noticeDao.deleteVisibleRange(noticeId);
noticeDao.insertVisibleRange(noticeId, visibleRangeList);
}
dataTracerService.update(noticeId, DataTracerTypeEnum.OA_NOTICE, old, noticeEntity);
}
}

View File

@ -0,0 +1,155 @@
package net.lab1024.sa.admin.module.business.oa.notice.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import jakarta.annotation.Resource;
import net.lab1024.sa.admin.module.business.oa.notice.constant.NoticeVisibleRangeDataTypeEnum;
import net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeDao;
import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeEmployeeQueryForm;
import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeViewRecordQueryForm;
import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.*;
import net.lab1024.sa.admin.module.system.department.service.DepartmentService;
import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity;
import net.lab1024.sa.admin.module.system.employee.service.EmployeeService;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartBeanUtil;
import net.lab1024.sa.base.common.util.SmartPageUtil;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 员工查看 通知公告
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Service
public class NoticeEmployeeService {
@Resource
private NoticeDao noticeDao;
@Resource
private NoticeService noticeService;
@Resource
private DepartmentService departmentService;
@Resource
private EmployeeService employeeService;
/**
* 查询我的 通知公告清单
*/
public ResponseDTO<PageResult<NoticeEmployeeVO>> queryList(Long requestEmployeeId, NoticeEmployeeQueryForm noticeEmployeeQueryForm) {
Page<?> page = SmartPageUtil.convert2PageQuery(noticeEmployeeQueryForm);
List<Long> employeeDepartmentIdList = Lists.newArrayList();
EmployeeEntity employeeEntity = employeeService.getById(requestEmployeeId);
// 如果不是管理员 则获取请求人的 部门及其子部门
if (!employeeEntity.getAdministratorFlag() && employeeEntity.getDepartmentId() != null) {
employeeDepartmentIdList = departmentService.selfAndChildrenIdList(employeeEntity.getDepartmentId());
}
List<NoticeEmployeeVO> noticeList = null;
//只查询未读的
if (noticeEmployeeQueryForm.getNotViewFlag() != null && noticeEmployeeQueryForm.getNotViewFlag()) {
noticeList = noticeDao.queryEmployeeNotViewNotice(page,
requestEmployeeId,
noticeEmployeeQueryForm,
employeeDepartmentIdList,
false,
employeeEntity.getAdministratorFlag(),
NoticeVisibleRangeDataTypeEnum.DEPARTMENT.getValue(),
NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue());
} else {
// 查询全部
noticeList = noticeDao.queryEmployeeNotice(page,
requestEmployeeId,
noticeEmployeeQueryForm,
employeeDepartmentIdList,
false,
employeeEntity.getAdministratorFlag(),
NoticeVisibleRangeDataTypeEnum.DEPARTMENT.getValue(),
NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue());
}
// 设置发布日期
noticeList.forEach(notice -> notice.setPublishDate(notice.getPublishTime().toLocalDate()));
return ResponseDTO.ok(SmartPageUtil.convert2PageResult(page, noticeList));
}
/**
* 查询我的 待查看的 通知公告清单
*/
public ResponseDTO<NoticeDetailVO> view(Long requestEmployeeId, Long noticeId, String ip, String userAgent) {
NoticeUpdateFormVO updateFormVO = noticeService.getUpdateFormVO(noticeId);
if (updateFormVO == null || Boolean.TRUE.equals(updateFormVO.getDeletedFlag())) {
return ResponseDTO.userErrorParam("通知公告不存在");
}
EmployeeEntity employeeEntity = employeeService.getById(requestEmployeeId);
if (!updateFormVO.getAllVisibleFlag() && !checkVisibleRange(updateFormVO.getVisibleRangeList(), requestEmployeeId, employeeEntity.getDepartmentId())) {
return ResponseDTO.userErrorParam("对不起,您没有权限查看内容");
}
NoticeDetailVO noticeDetailVO = SmartBeanUtil.copy(updateFormVO, NoticeDetailVO.class);
long viewCount = noticeDao.viewRecordCount(noticeId, requestEmployeeId);
if (viewCount == 0) {
noticeDao.insertViewRecord(noticeId, requestEmployeeId, ip, userAgent, 1);
// 该员工对于这个通知是第一次查看 页面浏览量+1 用户浏览量+1
noticeDao.updateViewCount(noticeId, 1, 1);
noticeDetailVO.setPageViewCount(noticeDetailVO.getPageViewCount() + 1);
noticeDetailVO.setUserViewCount(noticeDetailVO.getUserViewCount() + 1);
} else {
noticeDao.updateViewRecord(noticeId, requestEmployeeId, ip, userAgent);
// 该员工对于这个通知不是第一次查看 页面浏览量+1 用户浏览量+0
noticeDao.updateViewCount(noticeId, 1, 0);
noticeDetailVO.setPageViewCount(noticeDetailVO.getPageViewCount() + 1);
}
return ResponseDTO.ok(noticeDetailVO);
}
/**
* 校验是否有查看权限的范围
*
*/
public boolean checkVisibleRange(List<NoticeVisibleRangeVO> visibleRangeList, Long employeeId, Long departmentId) {
// 员工范围
boolean anyMatch = visibleRangeList.stream().anyMatch(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.equalsValue(e.getDataType()) && Objects.equals(e.getDataId(), employeeId));
if (anyMatch) {
return true;
}
//部门范围
List<Long> visibleDepartmentIdList = visibleRangeList.stream().filter(e -> NoticeVisibleRangeDataTypeEnum.DEPARTMENT.equalsValue(e.getDataType()))
.map(NoticeVisibleRangeVO::getDataId).collect(Collectors.toList());
for (Long visibleDepartmentId : visibleDepartmentIdList) {
List<Long> departmentIdList = departmentService.selfAndChildrenIdList(visibleDepartmentId);
if (departmentIdList.contains(departmentId)) {
return true;
}
}
return false;
}
/**
* 分页查询 查看记录
*/
public PageResult<NoticeViewRecordVO> queryViewRecord(NoticeViewRecordQueryForm noticeViewRecordQueryForm) {
Page<?> page = SmartPageUtil.convert2PageQuery(noticeViewRecordQueryForm);
List<NoticeViewRecordVO> noticeViewRecordList = noticeDao.queryNoticeViewRecordList(page, noticeViewRecordQueryForm);
return SmartPageUtil.convert2PageResult(page, noticeViewRecordList);
}
}

View File

@ -0,0 +1,240 @@
package net.lab1024.sa.admin.module.business.oa.notice.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import net.lab1024.sa.admin.module.business.oa.notice.constant.NoticeVisibleRangeDataTypeEnum;
import net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeDao;
import net.lab1024.sa.admin.module.business.oa.notice.domain.entity.NoticeEntity;
import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeAddForm;
import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeQueryForm;
import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeUpdateForm;
import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeVisibleRangeForm;
import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeTypeVO;
import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeUpdateFormVO;
import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVO;
import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVisibleRangeVO;
import net.lab1024.sa.admin.module.business.oa.notice.manager.NoticeManager;
import net.lab1024.sa.admin.module.system.department.dao.DepartmentDao;
import net.lab1024.sa.admin.module.system.department.domain.entity.DepartmentEntity;
import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO;
import net.lab1024.sa.admin.module.system.department.service.DepartmentService;
import net.lab1024.sa.admin.module.system.employee.dao.EmployeeDao;
import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity;
import net.lab1024.sa.base.common.constant.StringConst;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartBeanUtil;
import net.lab1024.sa.base.common.util.SmartPageUtil;
import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum;
import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 通知公告 后台管理业务
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Service
public class NoticeService {
@Resource
private NoticeDao noticeDao;
@Resource
private NoticeManager noticeManager;
@Resource
private EmployeeDao employeeDao;
@Resource
private DepartmentDao departmentDao;
@Resource
private DepartmentService departmentService;
@Resource
private NoticeTypeService noticeTypeService;
@Resource
private DataTracerService dataTracerService;
/**
* 查询 通知公告
*
*/
public PageResult<NoticeVO> query(NoticeQueryForm queryForm) {
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
List<NoticeVO> list = noticeDao.query(page, queryForm);
LocalDateTime now = LocalDateTime.now();
list.forEach(e -> e.setPublishFlag(e.getPublishTime().isBefore(now)));
return SmartPageUtil.convert2PageResult(page, list);
}
/**
* 添加
*/
public ResponseDTO<String> add(NoticeAddForm addForm) {
// 校验并获取可见范围
ResponseDTO<String> validate = this.checkAndBuildVisibleRange(addForm);
if (!validate.getOk()) {
return ResponseDTO.error(validate);
}
// build 资讯
NoticeEntity noticeEntity = SmartBeanUtil.copy(addForm, NoticeEntity.class);
// 发布时间不是定时发布时 默认为 当前
if (!addForm.getScheduledPublishFlag()) {
noticeEntity.setPublishTime(LocalDateTime.now());
}
// 保存数据
noticeManager.save(noticeEntity, addForm.getVisibleRangeList());
return ResponseDTO.ok();
}
/**
* 校验并返回可见范围
*
*/
private ResponseDTO<String> checkAndBuildVisibleRange(NoticeAddForm form) {
// 校验资讯分类
NoticeTypeVO noticeType = noticeTypeService.getByNoticeTypeId(form.getNoticeTypeId());
if (noticeType == null) {
return ResponseDTO.userErrorParam("分类不存在");
}
if (form.getAllVisibleFlag()) {
return ResponseDTO.ok();
}
/*
* 校验可见范围
* 非全部可见时 校验选择的员工|部门
*/
List<NoticeVisibleRangeForm> visibleRangeUpdateList = form.getVisibleRangeList();
if (CollectionUtils.isEmpty(visibleRangeUpdateList)) {
return ResponseDTO.userErrorParam("未设置可见范围");
}
// 校验可见范围-> 员工
List<Long> employeeIdList = visibleRangeUpdateList.stream()
.filter(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.equalsValue(e.getDataType()))
.map(NoticeVisibleRangeForm::getDataId)
.distinct().collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(employeeIdList)) {
employeeIdList = employeeIdList.stream().distinct().collect(Collectors.toList());
List<Long> dbEmployeeIdList = employeeDao.selectBatchIds(employeeIdList).stream().map(EmployeeEntity::getEmployeeId).collect(Collectors.toList());
Collection<Long> subtract = CollectionUtils.subtract(employeeIdList, dbEmployeeIdList);
if (!subtract.isEmpty()) {
return ResponseDTO.userErrorParam("员工id不存在" + subtract);
}
}
// 校验可见范围-> 部门
List<Long> deptIdList = visibleRangeUpdateList.stream()
.filter(e -> NoticeVisibleRangeDataTypeEnum.DEPARTMENT.equalsValue(e.getDataType()))
.map(NoticeVisibleRangeForm::getDataId)
.distinct().collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(deptIdList)) {
deptIdList = deptIdList.stream().distinct().collect(Collectors.toList());
List<Long> dbDeptIdList = departmentDao.selectBatchIds(deptIdList).stream().map(DepartmentEntity::getDepartmentId).collect(Collectors.toList());
Collection<Long> subtract = CollectionUtils.subtract(deptIdList, dbDeptIdList);
if (!subtract.isEmpty()) {
return ResponseDTO.userErrorParam("部门id不存在" + subtract);
}
}
return ResponseDTO.ok();
}
/**
* 更新
*
*/
public ResponseDTO<String> update(NoticeUpdateForm updateForm) {
NoticeEntity oldNoticeEntity = noticeDao.selectById(updateForm.getNoticeId());
if (oldNoticeEntity == null) {
return ResponseDTO.userErrorParam("通知不存在");
}
// 校验并获取可见范围
ResponseDTO<String> res = this.checkAndBuildVisibleRange(updateForm);
if (!res.getOk()) {
return ResponseDTO.error(res);
}
// 更新
NoticeEntity noticeEntity = SmartBeanUtil.copy(updateForm, NoticeEntity.class);
noticeManager.update(oldNoticeEntity, noticeEntity, updateForm.getVisibleRangeList());
return ResponseDTO.ok();
}
/**
* 删除
*
*/
public ResponseDTO<String> delete(Long noticeId) {
NoticeEntity noticeEntity = noticeDao.selectById(noticeId);
if (null == noticeEntity || noticeEntity.getDeletedFlag()) {
return ResponseDTO.userErrorParam("通知公告不存在");
}
// 更新删除状态
noticeDao.updateDeletedFlag(noticeId);
dataTracerService.delete(noticeId, DataTracerTypeEnum.OA_NOTICE);
return ResponseDTO.ok();
}
/**
* 获取更新表单用的详情
*/
public NoticeUpdateFormVO getUpdateFormVO(Long noticeId) {
NoticeEntity noticeEntity = noticeDao.selectById(noticeId);
if (null == noticeEntity) {
return null;
}
NoticeUpdateFormVO updateFormVO = SmartBeanUtil.copy(noticeEntity, NoticeUpdateFormVO.class);
NoticeTypeVO noticeType = noticeTypeService.getByNoticeTypeId(noticeEntity.getNoticeTypeId());
updateFormVO.setNoticeTypeName(noticeType.getNoticeTypeName());
updateFormVO.setPublishFlag(updateFormVO.getPublishTime() != null && updateFormVO.getPublishTime().isBefore(LocalDateTime.now()));
if (!updateFormVO.getAllVisibleFlag()) {
List<NoticeVisibleRangeVO> noticeVisibleRangeList = noticeDao.queryVisibleRange(noticeId);
List<Long> employeeIdList = noticeVisibleRangeList.stream().filter(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue().equals(e.getDataType()))
.map(NoticeVisibleRangeVO::getDataId)
.collect(Collectors.toList());
Map<Long, EmployeeEntity> employeeMap = null;
if (CollectionUtils.isNotEmpty(employeeIdList)) {
employeeMap = employeeDao.selectBatchIds(employeeIdList).stream().collect(Collectors.toMap(EmployeeEntity::getEmployeeId, Function.identity()));
} else {
employeeMap = Maps.newHashMap();
}
for (NoticeVisibleRangeVO noticeVisibleRange : noticeVisibleRangeList) {
if (noticeVisibleRange.getDataType().equals(NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue())) {
EmployeeEntity employeeEntity = employeeMap.get(noticeVisibleRange.getDataId());
noticeVisibleRange.setDataName(employeeEntity == null ? StringConst.EMPTY : employeeEntity.getActualName());
} else {
DepartmentVO departmentVO = departmentService.getDepartmentById(noticeVisibleRange.getDataId());
noticeVisibleRange.setDataName(departmentVO == null ? StringConst.EMPTY : departmentVO.getDepartmentName());
}
}
updateFormVO.setVisibleRangeList(noticeVisibleRangeList);
}
return updateFormVO;
}
}

View File

@ -0,0 +1,87 @@
package net.lab1024.sa.admin.module.business.oa.notice.service;
import cn.hutool.core.util.StrUtil;
import jakarta.annotation.Resource;
import net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeTypeDao;
import net.lab1024.sa.admin.module.business.oa.notice.domain.entity.NoticeTypeEntity;
import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeTypeVO;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartBeanUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 通知公告 类型
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2022-08-12 21:40:39
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Service
public class NoticeTypeService {
@Resource
private NoticeTypeDao noticeTypeDao;
/**
* 查询全部
* @return
*/
public List<NoticeTypeVO> getAll() {
return SmartBeanUtil.copyList(noticeTypeDao.selectList(null), NoticeTypeVO.class);
}
public NoticeTypeVO getByNoticeTypeId(Long noticceTypeId) {
return SmartBeanUtil.copy(noticeTypeDao.selectById(noticceTypeId), NoticeTypeVO.class);
}
public synchronized ResponseDTO<String> add(String name) {
if (StrUtil.isBlank(name)) {
return ResponseDTO.userErrorParam("类型名称不能为空");
}
List<NoticeTypeEntity> noticeTypeEntityList = noticeTypeDao.selectList(null);
if (!CollectionUtils.isEmpty(noticeTypeEntityList)) {
boolean exist = noticeTypeEntityList.stream().map(NoticeTypeEntity::getNoticeTypeName).collect(Collectors.toSet()).contains(name);
if (exist) {
return ResponseDTO.userErrorParam("类型名称已经存在");
}
}
noticeTypeDao.insert(NoticeTypeEntity.builder().noticeTypeName(name).build());
return ResponseDTO.ok();
}
public synchronized ResponseDTO<String> update(Long noticeTypeId, String name) {
if (StrUtil.isBlank(name)) {
return ResponseDTO.userErrorParam("类型名称不能为空");
}
NoticeTypeEntity noticeTypeEntity = noticeTypeDao.selectById(noticeTypeId);
if (noticeTypeEntity == null) {
return ResponseDTO.userErrorParam("类型名称不存在");
}
List<NoticeTypeEntity> noticeTypeEntityList = noticeTypeDao.selectList(null);
if (!CollectionUtils.isEmpty(noticeTypeEntityList)) {
Optional<NoticeTypeEntity> optionalNoticeTypeEntity = noticeTypeEntityList.stream().filter(e -> e.getNoticeTypeName().equals(name)).findFirst();
if (optionalNoticeTypeEntity.isPresent() && !optionalNoticeTypeEntity.get().getNoticeTypeId().equals(noticeTypeId)) {
return ResponseDTO.userErrorParam("类型名称已经存在");
}
}
noticeTypeEntity.setNoticeTypeName(name);
noticeTypeDao.updateById(noticeTypeEntity);
return ResponseDTO.ok();
}
public synchronized ResponseDTO<String> delete(Long noticeTypeId) {
noticeTypeDao.deleteById(noticeTypeId);
return ResponseDTO.ok();
}
}

View File

@ -0,0 +1,50 @@
package net.lab1024.sa.admin.module.system.datascope;
import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeTypeEnum;
import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeWhereInTypeEnum;
import net.lab1024.sa.admin.module.system.datascope.strategy.AbstractDataScopeStrategy;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 数据范围
*
* @Author 1024创新实验室: 罗伊
* @Date 2022-03-18 20:59:17
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataScope {
DataScopeTypeEnum dataScopeType() ;
DataScopeWhereInTypeEnum whereInType() default DataScopeWhereInTypeEnum.EMPLOYEE;
/**
* DataScopeWhereInTypeEnum.CUSTOM_STRATEGY类型 才可使用joinSqlImplClazz属性
*/
Class<? extends AbstractDataScopeStrategy> joinSqlImplClazz() default AbstractDataScopeStrategy.class;
/**
* 多个参数已逗号分隔本属性主要用于joinSqlImplClazz 实现类跟进参数进行不同的范围控制如不使用CUSTOM_STRATEGY可不做配置
*/
String paramName() default "";
/**
*
* 第几个where 条件 从0开始
*/
int whereIndex() default 0;
/**
* DataScopeWhereInTypeEnum为CUSTOM_STRATEGY类型时此属性无效
*/
String joinSql() default "";
}

View File

@ -0,0 +1,38 @@
package net.lab1024.sa.admin.module.system.datascope;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
import net.lab1024.sa.admin.module.system.datascope.domain.DataScopeAndViewTypeVO;
import net.lab1024.sa.admin.module.system.datascope.service.DataScopeService;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 查询支持的数据范围类型
*
* @Author 1024创新实验室: 罗伊
* @Date 2022-03-18 20:59:17
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@RestController
@Tag(name = AdminSwaggerTagConst.System.SYSTEM_DATA_SCOPE)
public class DataScopeController {
@Resource
private DataScopeService dataScopeService;
@Operation(summary = "获取当前系统所配置的所有数据范围 @author 罗伊")
@GetMapping("/dataScope/list")
public ResponseDTO<List<DataScopeAndViewTypeVO>> dataScopeList() {
return dataScopeService.dataScopeList();
}
}

View File

@ -0,0 +1,186 @@
package net.lab1024.sa.admin.module.system.datascope;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import net.lab1024.sa.admin.module.system.datascope.domain.DataScopeSqlConfig;
import net.lab1024.sa.admin.module.system.datascope.service.DataScopeSqlConfigService;
import net.lab1024.sa.base.common.domain.DataScopePlugin;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* mybaits sql 拦截
*
* @Author 1024创新实验室: 罗伊
* @Date 2022-03-18 20:59:17
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Intercepts({@Signature(type = org.apache.ibatis.executor.Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
@Component
public class MyBatisPlugin extends DataScopePlugin {
@Resource
private ApplicationContext applicationContext;
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
Object parameter = invocation.getArgs()[1];
BoundSql boundSql = mappedStatement.getBoundSql(parameter);
String originalSql = boundSql.getSql().trim();
String id = mappedStatement.getId();
List<String> methodStrList = StrUtil.split(id, ".");
String path = methodStrList.get(methodStrList.size() - 2) + "." + methodStrList.get(methodStrList.size() - 1);
DataScopeSqlConfigService dataScopeSqlConfigService = this.dataScopeSqlConfigService();
if (dataScopeSqlConfigService == null) {
return invocation.proceed();
}
DataScopeSqlConfig sqlConfigDTO = dataScopeSqlConfigService.getSqlConfig(path);
if (sqlConfigDTO != null) {
Map<String, Object> paramMap = this.getParamList(sqlConfigDTO.getParamName(), parameter);
BoundSql newBoundSql = copyFromBoundSql(mappedStatement, boundSql, this.joinSql(originalSql, paramMap, sqlConfigDTO));
ParameterMap map = mappedStatement.getParameterMap();
MappedStatement newMs = copyFromMappedStatement(mappedStatement, new BoundSqlSqlSource(newBoundSql), map);
invocation.getArgs()[0] = newMs;
}
Object obj = invocation.proceed();
return obj;
}
private Map<String, Object> getParamList(String paramName, Object parameter) {
Map<String, Object> paramMap = Maps.newHashMap();
if (StringUtils.isEmpty(paramName)) {
return paramMap;
}
if (parameter == null) {
return paramMap;
}
if (parameter instanceof Map) {
String[] paramNameArray = paramName.split(",");
Map<?, ?> parameterMap = (Map) parameter;
for (String param : paramNameArray) {
if(parameterMap.containsKey(param)){
paramMap.put(param, parameterMap.get(param));
}
}
}
return paramMap;
}
private String joinSql(String sql, Map<String, Object> paramMap, DataScopeSqlConfig sqlConfigDTO) {
if (null == sqlConfigDTO) {
return sql;
}
String appendSql = this.dataScopeSqlConfigService().getJoinSql(paramMap, sqlConfigDTO);
if (StringUtils.isEmpty(appendSql)) {
return sql;
}
Integer appendSqlWhereIndex = sqlConfigDTO.getWhereIndex();
String where = "where";
String order = "order by";
String group = "group by";
int whereIndex = StringUtils.ordinalIndexOf(sql.toLowerCase(), where, appendSqlWhereIndex + 1);
int orderIndex = sql.toLowerCase().indexOf(order);
int groupIndex = sql.toLowerCase().indexOf(group);
if (whereIndex > -1) {
String subSql = sql.substring(0, whereIndex + where.length() + 1);
subSql = subSql + " " + appendSql + " AND " + sql.substring(whereIndex + where.length() + 1);
return subSql;
}
if (groupIndex > -1) {
String subSql = sql.substring(0, groupIndex);
subSql = subSql + " where " + appendSql + " " + sql.substring(groupIndex);
return subSql;
}
if (orderIndex > -1) {
String subSql = sql.substring(0, orderIndex);
subSql = subSql + " where " + appendSql + " " + sql.substring(orderIndex);
return subSql;
}
sql += " where " + appendSql;
return sql;
}
public DataScopeSqlConfigService dataScopeSqlConfigService() {
return (DataScopeSqlConfigService) applicationContext.getBean("dataScopeSqlConfigService");
}
public class BoundSqlSqlSource implements SqlSource {
BoundSql boundSql;
public BoundSqlSqlSource(BoundSql boundSql) {
this.boundSql = boundSql;
}
@Override
public BoundSql getBoundSql(Object parameterObject) {
return boundSql;
}
}
/**
* 复制MappedStatement对象
*/
private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource, ParameterMap parameterMap) {
MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType());
builder.resource(ms.getResource());
builder.fetchSize(ms.getFetchSize());
builder.statementType(ms.getStatementType());
builder.keyGenerator(ms.getKeyGenerator());
builder.timeout(ms.getTimeout());
builder.parameterMap(parameterMap);
builder.resultMaps(ms.getResultMaps());
builder.resultSetType(ms.getResultSetType());
builder.cache(ms.getCache());
builder.flushCacheRequired(ms.isFlushCacheRequired());
builder.useCache(ms.isUseCache());
return builder.build();
}
/**
* 复制BoundSql对象
*/
private BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, String sql) {
BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), sql, boundSql.getParameterMappings(), boundSql.getParameterObject());
for (ParameterMapping mapping : boundSql.getParameterMappings()) {
String prop = mapping.getProperty();
if (boundSql.hasAdditionalParameter(prop)) {
newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));
}
}
return newBoundSql;
}
@Override
public Object plugin(Object arg0) {
return Plugin.wrap(arg0, this);
}
@Override
public void setProperties(Properties arg0) {
}
}

View File

@ -0,0 +1,56 @@
package net.lab1024.sa.admin.module.system.datascope.constant;
import net.lab1024.sa.base.common.enumeration.BaseEnum;
/**
* 数据范围 类型
*
* @Author 1024创新实验室: 罗伊
* @Date 2020/11/28 20:59:17
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
public enum DataScopeTypeEnum implements BaseEnum {
/**
* 系统通知
*/
NOTICE(1, 20, "系统通知", "系统通知数据范围"),
;
private final Integer value;
private final Integer sort;
private final String name;
private final String desc;
DataScopeTypeEnum(Integer value, Integer sort, String name, String desc) {
this.value = value;
this.sort = sort;
this.name = name;
this.desc = desc;
}
@Override
public Integer getValue() {
return value;
}
public Integer getSort() {
return sort;
}
@Override
public String getDesc() {
return desc;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,65 @@
package net.lab1024.sa.admin.module.system.datascope.constant;
import net.lab1024.sa.base.common.enumeration.BaseEnum;
/**
* 数据可见范围类型
*
* @Author 1024创新实验室: 罗伊
* @Date 2020/11/28 20:59:17
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
public enum DataScopeViewTypeEnum implements BaseEnum {
/**
* 本人
*/
ME(0, 0, "本人"),
/**
* 部门
*/
DEPARTMENT(1, 5, "本部门"),
/**
* 本部门及下属子部门
*/
DEPARTMENT_AND_SUB(2, 10, "本部门及下属子部门"),
/**
* 全部
*/
ALL(10, 100, "全部");
private final Integer value;
private final Integer level;
private final String desc;
DataScopeViewTypeEnum(Integer value, Integer level, String desc) {
this.value = value;
this.level = level;
this.desc = desc;
}
@Override
public Integer getValue() {
return value;
}
public Integer getLevel() {
return level;
}
@Override
public String getDesc() {
return desc;
}
}

View File

@ -0,0 +1,51 @@
package net.lab1024.sa.admin.module.system.datascope.constant;
import net.lab1024.sa.base.common.enumeration.BaseEnum;
/**
* 数据范围 sql where
*
* @Author 1024创新实验室: 罗伊
* @Date 2020/11/28 20:59:17
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
public enum DataScopeWhereInTypeEnum implements BaseEnum {
/**
* 以员工IN
*/
EMPLOYEE(0, "以员工IN"),
/**
* 以部门IN
*/
DEPARTMENT(1, "以部门IN"),
/**
* 自定义策略
*/
CUSTOM_STRATEGY(2, "自定义策略");
private final Integer value;
private final String desc;
DataScopeWhereInTypeEnum(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
@Override
public Integer getValue() {
return value;
}
@Override
public String getDesc() {
return desc;
}
}

View File

@ -0,0 +1,35 @@
package net.lab1024.sa.admin.module.system.datascope.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* 数据范围
*
* @Author 1024创新实验室: 罗伊
* @Date 2020/11/28 20:59:17
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class DataScopeAndViewTypeVO {
@Schema(description = "数据范围类型")
private Integer dataScopeType;
@Schema(description = "数据范围名称")
private String dataScopeTypeName;
@Schema(description = "描述")
private String dataScopeTypeDesc;
@Schema(description = "顺序")
private Integer dataScopeTypeSort;
@Schema(description = "可见范围列表")
private List<DataScopeViewTypeVO> viewTypeList;
}

View File

@ -0,0 +1,32 @@
package net.lab1024.sa.admin.module.system.datascope.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
/**
* 数据范围
*
* @Author 1024创新实验室: 罗伊
* @Date 2020/11/28 20:59:17
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
@Builder
public class DataScopeDTO {
@Schema(description = "数据范围类型")
private Integer dataScopeType;
@Schema(description = "数据范围名称")
private String dataScopeTypeName;
@Schema(description = "描述")
private String dataScopeTypeDesc;
@Schema(description = "顺序")
private Integer dataScopeTypeSort;
}

Some files were not shown because too many files have changed in this diff Show More