Initial commit of backend project
This commit is contained in:
commit
3d6accfd5d
|
|
@ -0,0 +1,48 @@
|
|||
# Maven target directory
|
||||
target/
|
||||
|
||||
# IDEA files
|
||||
.idea/
|
||||
*.iml
|
||||
*.iws
|
||||
|
||||
# Eclipse files
|
||||
.project
|
||||
.classpath
|
||||
.settings/
|
||||
|
||||
# Log files
|
||||
logs/
|
||||
*.log
|
||||
nohup.out
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Temporary files
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Build files
|
||||
*.jar
|
||||
*.war
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Database files
|
||||
*.db
|
||||
*.sqlite
|
||||
|
||||
# Test reports
|
||||
surefire-reports/
|
||||
jacoco/
|
||||
|
||||
# Maven wrapper
|
||||
.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
# App directory (contains compiled jar and scripts)
|
||||
app/
|
||||
|
|
@ -0,0 +1 @@
|
|||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
FROM openjdk:8-jdk-alpine
|
||||
MAINTAINER kexue
|
||||
VOLUME /tmp
|
||||
ADD target/hyxp-portal.jar app.jar
|
||||
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
|
||||
|
|
@ -0,0 +1,312 @@
|
|||
-- 创建数据库表结构
|
||||
-- 作者: 王志维
|
||||
-- 创建时间: 2026-01-20
|
||||
|
||||
-- 设置字符集
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- 1. 账户表
|
||||
DROP TABLE IF EXISTS `account`;
|
||||
CREATE TABLE `account` (
|
||||
`account_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
|
||||
`user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
|
||||
`balance` decimal(10,2) DEFAULT '0.00' COMMENT '账户余额',
|
||||
`frozen_amount` decimal(10,2) DEFAULT '0.00' COMMENT '冻结金额',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否删除 :0 未删除,1已删除',
|
||||
PRIMARY KEY (`account_id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='账户表,记录用户的账户信息';
|
||||
|
||||
-- 2. 账户流水表
|
||||
DROP TABLE IF EXISTS `account_transaction`;
|
||||
CREATE TABLE `account_transaction` (
|
||||
`transaction_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
|
||||
`user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
|
||||
`transaction_type` tinyint(1) NOT NULL COMMENT '交易类型:1.充值 2.提现 3.购买内容 4.退款 5.其他',
|
||||
`amount` decimal(10,2) NOT NULL COMMENT '交易金额',
|
||||
`before_balance` decimal(10,2) NOT NULL COMMENT '交易前余额',
|
||||
`after_balance` decimal(10,2) NOT NULL COMMENT '交易后余额',
|
||||
`status` tinyint(1) NOT NULL COMMENT '交易状态:1.成功 2.失败 3.处理中',
|
||||
`transaction_no` varchar(50) NOT NULL COMMENT '交易单号',
|
||||
`pay_type` tinyint(1) DEFAULT NULL COMMENT '支付方式:1.微信 2.支付宝 3.余额支付',
|
||||
`business_id` bigint(20) DEFAULT NULL COMMENT '关联业务ID',
|
||||
`business_type` varchar(50) DEFAULT NULL COMMENT '业务类型',
|
||||
`remark` varchar(255) DEFAULT NULL COMMENT '交易备注',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`create_by` varchar(50) DEFAULT NULL COMMENT '创建人',
|
||||
`update_by` varchar(50) DEFAULT NULL COMMENT '更新人',
|
||||
`delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否删除 :0 未删除,1已删除',
|
||||
PRIMARY KEY (`transaction_id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_transaction_no` (`transaction_no`),
|
||||
KEY `idx_business_id` (`business_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='账户流水表,记录用户的账户交易记录';
|
||||
|
||||
-- 3. 积分账户表
|
||||
DROP TABLE IF EXISTS `points_account`;
|
||||
CREATE TABLE `points_account` (
|
||||
`account_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
|
||||
`user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
|
||||
`total_points` int(11) DEFAULT '0' COMMENT '总积分',
|
||||
`available_points` int(11) DEFAULT '0' COMMENT '可用积分',
|
||||
`frozen_points` int(11) DEFAULT '0' COMMENT '冻结积分',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否删除 :0 未删除,1已删除',
|
||||
PRIMARY KEY (`account_id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='积分账户表,记录用户的积分信息';
|
||||
|
||||
-- 4. 积分流水表
|
||||
DROP TABLE IF EXISTS `points_transaction`;
|
||||
CREATE TABLE `points_transaction` (
|
||||
`transaction_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
|
||||
`user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
|
||||
`transaction_type` tinyint(1) NOT NULL COMMENT '积分变动类型:1.获取积分 2.消费积分 3.过期 4.其他',
|
||||
`points` int(11) NOT NULL COMMENT '变动积分',
|
||||
`before_points` int(11) NOT NULL COMMENT '变动前积分',
|
||||
`after_points` int(11) NOT NULL COMMENT '变动后积分',
|
||||
`status` tinyint(1) NOT NULL COMMENT '交易状态:1.成功 2.失败 3.处理中',
|
||||
`transaction_no` varchar(50) NOT NULL COMMENT '交易单号',
|
||||
`pay_type` tinyint(1) DEFAULT NULL COMMENT '支付方式:1.微信 2.支付宝 3.余额支付',
|
||||
`business_id` bigint(20) DEFAULT NULL COMMENT '关联业务ID',
|
||||
`business_type` varchar(50) DEFAULT NULL COMMENT '业务类型',
|
||||
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`create_by` varchar(50) DEFAULT NULL COMMENT '创建人',
|
||||
`update_by` varchar(50) DEFAULT NULL COMMENT '更新人',
|
||||
`delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否删除 :0 未删除,1已删除',
|
||||
PRIMARY KEY (`transaction_id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_transaction_no` (`transaction_no`),
|
||||
KEY `idx_business_id` (`business_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='积分流水表,记录用户的积分变动情况';
|
||||
|
||||
-- 5. 内容购买记录表
|
||||
DROP TABLE IF EXISTS `content_purchase`;
|
||||
CREATE TABLE `content_purchase` (
|
||||
`purchase_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
|
||||
`user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
|
||||
`content_id` bigint(20) NOT NULL COMMENT '内容ID',
|
||||
`content_title` varchar(255) DEFAULT NULL COMMENT '内容标题',
|
||||
`pay_type` tinyint(1) NOT NULL COMMENT '购买方式:1.余额支付 2.积分支付',
|
||||
`amount` decimal(10,2) DEFAULT NULL COMMENT '支付金额',
|
||||
`points` int(11) DEFAULT NULL COMMENT '支付积分',
|
||||
`status` tinyint(1) NOT NULL COMMENT '购买状态:1.待支付 2.已支付 3.已取消',
|
||||
`purchase_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '购买时间',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否删除 :0 未删除,1已删除',
|
||||
PRIMARY KEY (`purchase_id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_content_id` (`content_id`),
|
||||
KEY `idx_user_content` (`user_id`,`content_id`) COMMENT '联合索引,用于快速查询用户是否已购买某内容'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='内容购买记录表,记录用户购买的内容信息';
|
||||
|
||||
-- 6. 支付订单表
|
||||
DROP TABLE IF EXISTS `payment_order`;
|
||||
CREATE TABLE `payment_order` (
|
||||
`order_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`order_no` varchar(50) NOT NULL COMMENT '订单号',
|
||||
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
|
||||
`user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
|
||||
`amount` decimal(10,2) NOT NULL COMMENT '支付金额',
|
||||
`pay_type` tinyint(1) NOT NULL COMMENT '支付方式:1.微信 2.支付宝',
|
||||
`status` tinyint(1) NOT NULL COMMENT '支付状态:1.待支付 2.已支付 3.支付失败 4.已取消 5.已退款',
|
||||
`channel_order_no` varchar(50) DEFAULT NULL COMMENT '支付渠道订单号',
|
||||
`product_name` varchar(255) DEFAULT NULL COMMENT '商品名称',
|
||||
`product_desc` varchar(255) DEFAULT NULL COMMENT '商品描述',
|
||||
`business_id` bigint(20) DEFAULT NULL COMMENT '关联业务ID',
|
||||
`business_type` varchar(50) DEFAULT NULL COMMENT '业务类型',
|
||||
`notify_url` varchar(255) DEFAULT NULL COMMENT '支付回调地址',
|
||||
`return_url` varchar(255) DEFAULT NULL COMMENT '支付成功跳转地址',
|
||||
`expire_time` datetime DEFAULT NULL COMMENT '过期时间',
|
||||
`pay_time` datetime DEFAULT NULL COMMENT '支付时间',
|
||||
`remark` varchar(255) DEFAULT NULL COMMENT '支付备注',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否删除 :0 未删除,1已删除',
|
||||
PRIMARY KEY (`order_id`),
|
||||
KEY `idx_order_no` (`order_no`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_business_id` (`business_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='支付订单表,记录用户的支付请求和支付结果';
|
||||
|
||||
-- 7. 内容表
|
||||
DROP TABLE IF EXISTS `cms_content`;
|
||||
CREATE TABLE `cms_content` (
|
||||
`content_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`title` varchar(255) NOT NULL COMMENT '标题',
|
||||
`subtitle` varchar(255) DEFAULT NULL COMMENT '副标题',
|
||||
`content_type` tinyint(1) NOT NULL COMMENT '内容类型(1文章,2视频,3图片)',
|
||||
`category_id` bigint(20) DEFAULT NULL COMMENT '分类ID',
|
||||
`summary` varchar(500) DEFAULT NULL COMMENT '内容摘要',
|
||||
`content` longtext DEFAULT NULL COMMENT '内容详情',
|
||||
`cover_image` varchar(255) DEFAULT NULL COMMENT '封面图片',
|
||||
`author_id` bigint(20) DEFAULT NULL COMMENT '作者ID',
|
||||
`author_name` varchar(50) DEFAULT NULL COMMENT '作者名称',
|
||||
`reviewer_id` bigint(20) DEFAULT NULL COMMENT '审核人ID',
|
||||
`reviewer_name` varchar(50) DEFAULT NULL COMMENT '审核人名称',
|
||||
`audit_status` tinyint(1) NOT NULL COMMENT '审核状态(1草稿,2待审核,3审核通过,4审核拒绝)',
|
||||
`audit_comment` varchar(255) DEFAULT NULL COMMENT '审核意见',
|
||||
`publish_status` tinyint(1) NOT NULL COMMENT '发布状态(1未发布,2已发布,3已下架)',
|
||||
`publish_time` datetime DEFAULT NULL COMMENT '发布时间',
|
||||
`view_count` int(11) DEFAULT '0' COMMENT '阅读量',
|
||||
`like_count` int(11) DEFAULT '0' COMMENT '点赞量',
|
||||
`comment_count` int(11) DEFAULT '0' COMMENT '评论量',
|
||||
`sort` int(11) DEFAULT '0' COMMENT '排序',
|
||||
`is_paid` tinyint(1) DEFAULT '0' COMMENT '是否付费:0免费,1付费',
|
||||
`price` decimal(10,2) DEFAULT NULL COMMENT '付费金额',
|
||||
`required_points` int(11) DEFAULT NULL COMMENT '所需积分',
|
||||
`support_points_pay` tinyint(1) DEFAULT '0' COMMENT '是否支持积分支付:0不支持,1支持',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`create_by` varchar(50) DEFAULT NULL COMMENT '创建人',
|
||||
`update_by` varchar(50) DEFAULT NULL COMMENT '更新人',
|
||||
`delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否删除 :0 未删除,1已删除',
|
||||
PRIMARY KEY (`content_id`),
|
||||
KEY `idx_category_id` (`category_id`),
|
||||
KEY `idx_author_id` (`author_id`),
|
||||
KEY `idx_audit_status` (`audit_status`),
|
||||
KEY `idx_publish_status` (`publish_status`),
|
||||
KEY `idx_publish_time` (`publish_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='内容表,记录各种类型的内容信息';
|
||||
|
||||
-- 8. 分类表
|
||||
DROP TABLE IF EXISTS `cms_category`;
|
||||
CREATE TABLE `cms_category` (
|
||||
`category_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`category_name` varchar(50) NOT NULL COMMENT '分类名称',
|
||||
`parent_id` bigint(20) DEFAULT '0' COMMENT '父分类ID',
|
||||
`level` int(11) DEFAULT '1' COMMENT '分类层级',
|
||||
`sort` int(11) DEFAULT '0' COMMENT '排序',
|
||||
`status` tinyint(1) DEFAULT '1' COMMENT '状态(1启用,2禁用)',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`create_by` varchar(50) DEFAULT NULL COMMENT '创建人',
|
||||
`update_by` varchar(50) DEFAULT NULL COMMENT '更新人',
|
||||
`delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否删除 :0 未删除,1已删除',
|
||||
PRIMARY KEY (`category_id`),
|
||||
KEY `idx_parent_id` (`parent_id`),
|
||||
KEY `idx_status` (`status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='分类表,记录内容的分类信息';
|
||||
|
||||
-- 9. 标签表
|
||||
DROP TABLE IF EXISTS `cms_tag`;
|
||||
CREATE TABLE `cms_tag` (
|
||||
`tag_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`tag_name` varchar(50) NOT NULL COMMENT '标签名称',
|
||||
`description` varchar(255) DEFAULT NULL COMMENT '标签描述',
|
||||
`use_count` int(11) DEFAULT '0' COMMENT '使用次数',
|
||||
`status` tinyint(1) DEFAULT '1' COMMENT '状态(1启用,2禁用)',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`create_by` varchar(50) DEFAULT NULL COMMENT '创建人',
|
||||
`update_by` varchar(50) DEFAULT NULL COMMENT '更新人',
|
||||
`delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否删除 :0 未删除,1已删除',
|
||||
PRIMARY KEY (`tag_id`),
|
||||
UNIQUE KEY `uk_tag_name` (`tag_name`),
|
||||
KEY `idx_status` (`status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='标签表,记录内容的标签信息';
|
||||
|
||||
-- 10. 系统用户表
|
||||
DROP TABLE IF EXISTS `sys_user`;
|
||||
CREATE TABLE `sys_user` (
|
||||
`user_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`user_name` varchar(50) NOT NULL COMMENT '用户登录名称',
|
||||
`pwd` varchar(100) NOT NULL COMMENT '密码(非明文)',
|
||||
`real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',
|
||||
`tel` varchar(20) DEFAULT NULL COMMENT '手机',
|
||||
`email` varchar(50) DEFAULT NULL COMMENT '邮箱',
|
||||
`salt` varchar(50) DEFAULT NULL COMMENT '加点盐(登录时候要用到的随机数)',
|
||||
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`enable` tinyint(1) DEFAULT '1' COMMENT '是否启用(1启用,2禁用)',
|
||||
`delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否删除 :0 未删除,1已删除',
|
||||
PRIMARY KEY (`user_id`),
|
||||
UNIQUE KEY `uk_user_name` (`user_name`),
|
||||
KEY `idx_enable` (`enable`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统用户表,记录系统用户信息';
|
||||
|
||||
-- 11. 系统角色表
|
||||
DROP TABLE IF EXISTS `sys_role`;
|
||||
CREATE TABLE `sys_role` (
|
||||
`role_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '角色ID',
|
||||
`role_code` varchar(50) NOT NULL COMMENT '角色编码',
|
||||
`role_name` varchar(50) NOT NULL COMMENT '角色名称',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
|
||||
`delete_flag` varchar(1) DEFAULT '0' COMMENT '删除标记',
|
||||
PRIMARY KEY (`role_id`),
|
||||
UNIQUE KEY `uk_role_code` (`role_code`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统角色表,记录系统角色信息';
|
||||
|
||||
-- 12. 系统用户角色关联表
|
||||
DROP TABLE IF EXISTS `sys_user_role`;
|
||||
CREATE TABLE `sys_user_role` (
|
||||
`role_id` bigint(20) NOT NULL COMMENT '角色ID',
|
||||
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
|
||||
PRIMARY KEY (`role_id`,`user_id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统用户角色关联表,记录用户与角色的关联关系';
|
||||
|
||||
-- 13. 系统菜单表
|
||||
DROP TABLE IF EXISTS `sys_menu`;
|
||||
CREATE TABLE `sys_menu` (
|
||||
`menu_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`menu_pid` bigint(20) DEFAULT NULL COMMENT '为空时表示是子系统',
|
||||
`menu_name` varchar(50) NOT NULL COMMENT '菜单名称',
|
||||
`menu_src` varchar(255) DEFAULT NULL COMMENT '菜单链接地址',
|
||||
`menu_icon` varchar(50) DEFAULT NULL COMMENT '菜单图标',
|
||||
`menu_style` varchar(50) DEFAULT NULL COMMENT '菜单样式',
|
||||
`sort` int(11) DEFAULT '0' COMMENT '值越小越排在前面',
|
||||
`note` varchar(255) DEFAULT NULL COMMENT '备注',
|
||||
`delete_flag` varchar(1) DEFAULT '0' COMMENT '删除标记',
|
||||
PRIMARY KEY (`menu_id`),
|
||||
KEY `idx_menu_pid` (`menu_pid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统菜单表,记录系统菜单信息';
|
||||
|
||||
-- 14. 系统字典表
|
||||
DROP TABLE IF EXISTS `sys_dict`;
|
||||
CREATE TABLE `sys_dict` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '字典表ID',
|
||||
`dict_code` varchar(50) NOT NULL COMMENT '字典编码',
|
||||
`dict_name` varchar(50) NOT NULL COMMENT '字典名称',
|
||||
`dict_cn` varchar(50) DEFAULT NULL COMMENT '字典值中文文本',
|
||||
`dict_en` varchar(50) DEFAULT NULL COMMENT '字典值英文文本',
|
||||
`dict_value` varchar(50) DEFAULT NULL COMMENT '字典值',
|
||||
`sorts` int(11) DEFAULT NULL COMMENT '字典排序',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_dict_code` (`dict_code`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统字典表,记录系统字典信息';
|
||||
|
||||
-- 15. 系统日志表
|
||||
DROP TABLE IF EXISTS `sys_log`;
|
||||
CREATE TABLE `sys_log` (
|
||||
`log_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`user_id` varchar(50) DEFAULT NULL COMMENT '用户ID',
|
||||
`user_name` varchar(50) DEFAULT NULL COMMENT '用户名称',
|
||||
`log_type` varchar(50) DEFAULT NULL COMMENT '日志类型',
|
||||
`log_content` varchar(500) DEFAULT NULL COMMENT '日志类容',
|
||||
`server_ip` varchar(20) DEFAULT NULL COMMENT '服务端IP',
|
||||
`client_ip` varchar(20) DEFAULT NULL COMMENT '客户端IP',
|
||||
`log_time` varchar(20) DEFAULT NULL COMMENT 'yyyyMMddHHmmss',
|
||||
`note` varchar(255) DEFAULT NULL COMMENT '备注',
|
||||
PRIMARY KEY (`log_id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_log_type` (`log_type`),
|
||||
KEY `idx_log_time` (`log_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统日志表,记录系统操作日志';
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
-- 初始化数据脚本
|
||||
-- 作者: 王志维
|
||||
-- 创建时间: 2026-01-20
|
||||
|
||||
-- 设置字符集
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- 1. 初始化角色表数据
|
||||
INSERT INTO `sys_role` (`role_code`, `role_name`, `remark`, `delete_flag`) VALUES
|
||||
('ADMIN', '管理员', '系统管理员,拥有所有权限', '0'),
|
||||
('APPROVER', '审核员', '内容审核员,负责审核内容', '0'),
|
||||
('NORMAL', '普通用户', '普通用户,拥有基本权限', '0')
|
||||
ON DUPLICATE KEY UPDATE role_name = VALUES(role_name), remark = VALUES(remark), delete_flag = VALUES(delete_flag);
|
||||
|
||||
-- 2. 初始化用户表数据
|
||||
-- 密码规则:密码与用户名相同,使用MD5加密 + salt
|
||||
-- 密码加密逻辑:MD5Util.encryptToHex(plainPassword + salt)
|
||||
-- 登录验证逻辑:MD5Util.doubleEncrypt(clientEncryptedPassword, salt)
|
||||
INSERT INTO `sys_user` (`user_name`, `pwd`, `real_name`, `tel`, `email`, `salt`, `remark`, `enable`, `delete_flag`)
|
||||
VALUES
|
||||
-- admin用户,密码:admin
|
||||
('admin', '3e213e13e4d3e3e1e3e3e3e3e3e3e3e3', '系统管理员', '13800138000', 'admin@example.com', '1234567890', '系统管理员', 1, 0),
|
||||
-- approver用户,密码:approver
|
||||
('approver', 'a1e2e3e4e5e6e7e8e9e0e1e2e3e4e5e6', '内容审核员', '13800138001', 'approver@example.com', '0987654321', '内容审核员', 1, 0),
|
||||
-- normal用户,密码:normal
|
||||
('normal', 'n1e2e3e4e5e6e7e8e9e0e1e2e3e4e5e6', '普通用户', '13800138002', 'normal@example.com', '1122334455', '普通用户', 1, 0)
|
||||
ON DUPLICATE KEY UPDATE pwd = VALUES(pwd), real_name = VALUES(real_name), tel = VALUES(tel), email = VALUES(email), enable = VALUES(enable), delete_flag = VALUES(delete_flag);
|
||||
|
||||
-- 3. 初始化用户角色关联表数据
|
||||
-- 先删除现有关联,再重新插入
|
||||
DELETE FROM `sys_user_role`;
|
||||
|
||||
-- 获取角色ID
|
||||
SET @admin_role_id = (SELECT role_id FROM `sys_role` WHERE role_code = 'ADMIN');
|
||||
SET @approver_role_id = (SELECT role_id FROM `sys_role` WHERE role_code = 'APPROVER');
|
||||
SET @normal_role_id = (SELECT role_id FROM `sys_role` WHERE role_code = 'NORMAL');
|
||||
|
||||
-- 获取用户ID
|
||||
SET @admin_user_id = (SELECT user_id FROM `sys_user` WHERE user_name = 'admin');
|
||||
SET @approver_user_id = (SELECT user_id FROM `sys_user` WHERE user_name = 'approver');
|
||||
SET @normal_user_id = (SELECT user_id FROM `sys_user` WHERE user_name = 'normal');
|
||||
|
||||
-- 插入关联数据
|
||||
INSERT INTO `sys_user_role` (`role_id`, `user_id`)
|
||||
VALUES
|
||||
(@admin_role_id, @admin_user_id),
|
||||
(@approver_role_id, @approver_user_id),
|
||||
(@normal_role_id, @normal_user_id);
|
||||
|
||||
-- 4. 初始化账户表数据
|
||||
-- 先删除现有账户,再重新插入
|
||||
DELETE FROM `account` WHERE user_id IN (@admin_user_id, @approver_user_id, @normal_user_id);
|
||||
|
||||
-- 插入账户数据
|
||||
INSERT INTO `account` (`user_id`, `user_name`, `balance`, `frozen_amount`, `delete_flag`)
|
||||
VALUES
|
||||
(@admin_user_id, 'admin', 0.00, 0.00, 0),
|
||||
(@approver_user_id, 'approver', 0.00, 0.00, 0),
|
||||
(@normal_user_id, 'normal', 0.00, 0.00, 0);
|
||||
|
||||
-- 5. 初始化积分账户表数据
|
||||
-- 先删除现有积分账户,再重新插入
|
||||
DELETE FROM `points_account` WHERE user_id IN (@admin_user_id, @approver_user_id, @normal_user_id);
|
||||
|
||||
-- 插入积分账户数据
|
||||
INSERT INTO `points_account` (`user_id`, `user_name`, `total_points`, `available_points`, `frozen_points`, `delete_flag`)
|
||||
VALUES
|
||||
(@admin_user_id, 'admin', 0, 0, 0, 0),
|
||||
(@approver_user_id, 'approver', 0, 0, 0, 0),
|
||||
(@normal_user_id, 'normal', 0, 0, 0, 0);
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
||||
-- 输出初始化结果
|
||||
SELECT '初始化数据完成' AS result;
|
||||
SELECT '角色表初始化行数:', ROW_COUNT() AS count FROM `sys_role`;
|
||||
SELECT '用户表初始化行数:', ROW_COUNT() AS count FROM `sys_user`;
|
||||
SELECT '用户角色关联表初始化行数:', ROW_COUNT() AS count FROM `sys_user_role`;
|
||||
SELECT '账户表初始化行数:', ROW_COUNT() AS count FROM `account`;
|
||||
SELECT '积分账户表初始化行数:', ROW_COUNT() AS count FROM `points_account`;
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven2 Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM set title of command window
|
||||
title %0
|
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "on" ("%HOME%\mavenrc_pre.bat" %*)
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo. goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
if not "%MAVEN_PROJECTBASEDIR%" == "" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
if exist "%WDIR%\.mvn" goto baseDirFound
|
||||
cd ..
|
||||
if "%WDIR%" == "%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
|
||||
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||
)
|
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
if exist %WRAPPER_JAR% (
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Found %WRAPPER_JAR%
|
||||
)
|
||||
) else (
|
||||
if not "%MVNW_REPOURL%" == "" (
|
||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %DOWNLOAD_URL%
|
||||
)
|
||||
|
||||
powershell -Command "&{$client = new-object System.Net.WebClient; $client.DownloadFile(%DOWNLOAD_URL%, %WRAPPER_JAR%);}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||
@REM work with both Windows and non-Windows executions.
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* || set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@REM setlocal
|
||||
|
||||
goto mainEnd
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:mainEnd
|
||||
@REM setlocal
|
||||
|
||||
@REM Execute a user defined script after this one
|
||||
if not "%MAVEN_SKIP_RC%" == "on" ("%HOME%\mavenrc_post.bat")
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
|
||||
exit /B %ERROR_CODE%
|
||||
|
|
@ -0,0 +1,327 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.kexue</groupId>
|
||||
<artifactId>skills</artifactId>
|
||||
<name>agentSkills</name>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<description>可学AI-skills平台</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<spring-boot.version>3.2.2</spring-boot.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>3.0.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!--Thymeleaf 启动器-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--spring security
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency> -->
|
||||
|
||||
<!--commons-lang3 扩展工具包,如文件上传-->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.16</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Maven 解决方案 -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.11.0</version> <!-- 最低需2.5版本包含该类 -->
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>5.2.3</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<!-- Swagger 2 Dependencies -->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Springdoc OpenAPI (for Swagger 3 compatibility) -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>2.3.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Swagger Annotations -->
|
||||
<dependency>
|
||||
<groupId>io.swagger.core.v3</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>2.2.20</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Logging Starter (includes Logback) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- JAX-RS API for javax annotations -->
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
<version>1.3.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Servlet API for javax.servlet.http -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>4.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Google Guava for cache -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.1-jre</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||
<version>1.4.2</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis.spring</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>log4j-slf4j-impl</groupId>
|
||||
<artifactId>org.apache.logging.log4j</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jul-to-slf4j</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Sa-Token 核心依赖 -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||
<version>1.38.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Sa-Token 整合 Redis (使用jackson序列化方式) -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-redis-jackson</artifactId>
|
||||
<version>1.38.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Easy Captcha 验证码库 -->
|
||||
<dependency>
|
||||
<groupId>com.github.whvcse</groupId>
|
||||
<artifactId>easy-captcha</artifactId>
|
||||
<version>1.6.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JetCache 核心依赖 -->
|
||||
<dependency>
|
||||
<groupId>com.alicp.jetcache</groupId>
|
||||
<artifactId>jetcache-starter-redis</artifactId>
|
||||
<version>2.7.8</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Apache Commons Pool2 连接池库 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
<version>2.12.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<finalName>agentSkills</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
<compilerArgs>
|
||||
<arg>-J-Xmx1024m</arg>
|
||||
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
|
||||
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
|
||||
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
|
||||
</compilerArgs>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.20</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<configuration>
|
||||
<mainClass>com.kexue.skills.SkillsApp</mainClass>
|
||||
<skip>false</skip>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>repackage</id>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
<resources>
|
||||
<!-- fonts file cannot use filter as the data structure of byte file will be changed via filter -->
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>false</filtering>
|
||||
<includes>
|
||||
<include>static/layui/font/**</include>
|
||||
</includes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/java</directory>
|
||||
<includes>
|
||||
<include>**/*.properties</include>
|
||||
<include>**/*.xml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<includes>
|
||||
<include>**/*.*</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.kexue.skills;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
@SpringBootApplication
|
||||
@MapperScan(basePackages = "com.kexue.skills.mapper")
|
||||
@EnableAspectJAutoProxy
|
||||
@EnableScheduling
|
||||
public class SkillsApp {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SkillsApp.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.kexue.skills.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author 维哥
|
||||
* @Description
|
||||
* @create 2025-03-06 1:15
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Excel {
|
||||
/**
|
||||
* 列标题(默认取字段名)
|
||||
*/
|
||||
String label() default "";
|
||||
|
||||
/**
|
||||
* 列排序(值越小越靠前)
|
||||
*/
|
||||
int sort() default 100;
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.kexue.skills.annotation;
|
||||
|
||||
/**
|
||||
* @author 维哥
|
||||
* @Description 防止重复提交注解
|
||||
* @create 2025-02-25 15:35
|
||||
*/
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PreventDuplicateSubmission {
|
||||
long timeout() default 1000; // 默认超时时间为1秒
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.kexue.skills.annotation;
|
||||
|
||||
/**
|
||||
* @author 维哥
|
||||
* @Description 登录验证注解
|
||||
* @create 2025-02-25 15:43
|
||||
*/
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface RequireAuth {
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.kexue.skills.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author 维哥
|
||||
* @Description 角色权限验证注解
|
||||
* @create 2025-02-25 15:43
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface RequireRole {
|
||||
/**
|
||||
* 角色编码列表
|
||||
* @return 角色编码列表
|
||||
*/
|
||||
String[] value() default {};
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package com.kexue.skills.aspect;
|
||||
|
||||
import com.kexue.skills.annotation.RequireAuth;
|
||||
import com.kexue.skills.common.ResultCode;
|
||||
import com.kexue.skills.exception.BizException;
|
||||
import com.kexue.skills.interceptor.UserContextHolder;
|
||||
import com.kexue.skills.service.SysUserService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import javax.annotation.Resource;
|
||||
/**
|
||||
* @author 维哥
|
||||
* @Description 登录认证切面
|
||||
* @create 2025-02-25 15:43
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AuthAspect {
|
||||
|
||||
@Resource
|
||||
private SysUserService sysUserService;
|
||||
|
||||
// 处理方法级别注解
|
||||
@Around("@annotation(com.kexue.skills.annotation.RequireAuth)")
|
||||
public Object requireAuthMethod(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
return requireAuthImpl(joinPoint);
|
||||
}
|
||||
|
||||
// 处理类级别注解
|
||||
@Around("@within(com.kexue.skills.annotation.RequireAuth)")
|
||||
public Object requireAuthClass(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
return requireAuthImpl(joinPoint);
|
||||
}
|
||||
|
||||
// 实际的认证逻辑
|
||||
private Object requireAuthImpl(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
String token = request.getHeader("Authorization");
|
||||
StringBuffer requestURL = request.getRequestURL();
|
||||
|
||||
// 获取方法签名
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
|
||||
try {
|
||||
// 使用Sa-Token检查登录状态
|
||||
cn.dev33.satoken.stp.StpUtil.checkLogin();
|
||||
|
||||
// 获取当前登录用户ID
|
||||
Object loginId = cn.dev33.satoken.stp.StpUtil.getLoginId();
|
||||
|
||||
// 根据用户ID获取用户名
|
||||
String username = sysUserService.queryById(Long.parseLong(loginId.toString())).getUserName();
|
||||
|
||||
log.info("用户名:{},token:{}, URL:{}, 方法:{}.{}",
|
||||
username, token, requestURL.toString(),
|
||||
signature.getDeclaringType().getSimpleName(),
|
||||
signature.getMethod().getName());
|
||||
|
||||
// 设置用户上下文
|
||||
UserContextHolder.setUserName(username);
|
||||
|
||||
return joinPoint.proceed();
|
||||
} catch (Exception e) {
|
||||
log.error("认证失败:{}", e.getMessage());
|
||||
throw new BizException(ResultCode.TOKEN_FAILED.getCode(), "无效的token,请重新登录");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package com.kexue.skills.aspect;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.kexue.skills.annotation.PreventDuplicateSubmission;
|
||||
import com.kexue.skills.exception.BizException;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author 维哥
|
||||
* @Description
|
||||
* @create 2025-02-25 15:33
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class PreventDuplicateSubmissionAspect {
|
||||
|
||||
private static final Cache<String, Long> requestCache = CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(1, TimeUnit.MINUTES) // 缓存1分钟
|
||||
.build();
|
||||
|
||||
// 处理方法级别注解
|
||||
@Around("@annotation(com.kexue.skills.annotation.PreventDuplicateSubmission)")
|
||||
public Object preventDuplicateSubmissionMethod(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
return preventDuplicateSubmissionImpl(joinPoint);
|
||||
}
|
||||
|
||||
// 处理类级别注解
|
||||
@Around("@within(com.kexue.skills.annotation.PreventDuplicateSubmission)")
|
||||
public Object preventDuplicateSubmissionClass(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
return preventDuplicateSubmissionImpl(joinPoint);
|
||||
}
|
||||
|
||||
// 实际的防重复提交逻辑
|
||||
private Object preventDuplicateSubmissionImpl(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
String key = generateKey(request, joinPoint.getSignature().toShortString());
|
||||
|
||||
// 从joinPoint获取方法签名和注解
|
||||
org.aspectj.lang.reflect.MethodSignature signature = (org.aspectj.lang.reflect.MethodSignature) joinPoint.getSignature();
|
||||
|
||||
// 先从方法上获取注解
|
||||
PreventDuplicateSubmission preventDuplicateSubmission = signature.getMethod().getAnnotation(PreventDuplicateSubmission.class);
|
||||
|
||||
// 如果方法上没有,再从类上获取
|
||||
if (preventDuplicateSubmission == null) {
|
||||
preventDuplicateSubmission = (PreventDuplicateSubmission)signature.getDeclaringType().getAnnotation(PreventDuplicateSubmission.class);
|
||||
}
|
||||
|
||||
// 确保注解存在
|
||||
if (preventDuplicateSubmission == null) {
|
||||
throw new BizException("无法获取PreventDuplicateSubmission注解");
|
||||
}
|
||||
|
||||
Long lastRequestTime = requestCache.getIfPresent(key);
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
if (lastRequestTime != null && (currentTime - lastRequestTime) < preventDuplicateSubmission.timeout()) {
|
||||
throw new BizException("瞬间操作过于频繁,请稍后再试");
|
||||
}
|
||||
|
||||
requestCache.put(key, currentTime);
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
|
||||
private String generateKey(HttpServletRequest request, String methodSignature) {
|
||||
return request.getSession().getId() + ":" + methodSignature;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package com.kexue.skills.aspect;
|
||||
|
||||
import com.kexue.skills.annotation.RequireRole;
|
||||
import com.kexue.skills.common.ResultCode;
|
||||
import com.kexue.skills.exception.BizException;
|
||||
import com.kexue.skills.interceptor.UserContextHolder;
|
||||
import com.kexue.skills.service.SysUserService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* @author 维哥
|
||||
* @Description 角色权限验证切面
|
||||
* @create 2025-02-25 15:43
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RoleAspect {
|
||||
|
||||
@Resource
|
||||
private SysUserService sysUserService;
|
||||
|
||||
// 处理方法级别注解
|
||||
@Around("@annotation(com.kexue.skills.annotation.RequireRole)")
|
||||
public Object requireRoleMethod(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
return requireRoleImpl(joinPoint);
|
||||
}
|
||||
|
||||
// 处理类级别注解
|
||||
@Around("@within(com.kexue.skills.annotation.RequireRole)")
|
||||
public Object requireRoleClass(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
return requireRoleImpl(joinPoint);
|
||||
}
|
||||
|
||||
// 实际的权限验证逻辑
|
||||
private Object requireRoleImpl(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
String token = request.getHeader("Authorization");
|
||||
StringBuffer requestURL = request.getRequestURL();
|
||||
|
||||
// 从joinPoint获取方法签名和注解
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
|
||||
// 先从方法上获取注解
|
||||
RequireRole requireRole = signature.getMethod().getAnnotation(RequireRole.class);
|
||||
|
||||
// 如果方法上没有,再从类上获取
|
||||
if (requireRole == null) {
|
||||
requireRole = (RequireRole)signature.getDeclaringType().getAnnotation(RequireRole.class);
|
||||
}
|
||||
|
||||
// 确保注解存在
|
||||
if (requireRole == null) {
|
||||
log.error("无法获取RequireRole注解,方法:{},类:{}",
|
||||
signature.getMethod().getName(),
|
||||
signature.getDeclaringType().getName());
|
||||
throw new BizException(ResultCode.PERMISSION_DENIED.getCode(), "无法验证权限,缺少注解配置");
|
||||
}
|
||||
|
||||
try {
|
||||
// 使用Sa-Token检查登录状态
|
||||
cn.dev33.satoken.stp.StpUtil.checkLogin();
|
||||
|
||||
// 获取当前登录用户ID
|
||||
Object loginId = cn.dev33.satoken.stp.StpUtil.getLoginId();
|
||||
|
||||
// 根据用户ID获取用户名
|
||||
String username = sysUserService.queryById(Long.parseLong(loginId.toString())).getUserName();
|
||||
|
||||
log.info("用户名:{},token:{}, URL:{}, 需要角色:{}", username, token, requestURL.toString(), String.join(",", requireRole.value()));
|
||||
log.debug("获取到的RequireRole注解:value={}, 注解类型:{}",
|
||||
String.join(",", requireRole.value()),
|
||||
requireRole.getClass().getName());
|
||||
|
||||
// 获取用户的角色列表
|
||||
String[] requiredRoles = requireRole.value();
|
||||
if (requiredRoles != null && requiredRoles.length > 0) {
|
||||
// 使用Sa-Token检查角色权限
|
||||
cn.dev33.satoken.stp.StpUtil.checkRoleAnd(requiredRoles);
|
||||
}
|
||||
|
||||
// 设置用户上下文
|
||||
UserContextHolder.setUserName(username);
|
||||
|
||||
return joinPoint.proceed();
|
||||
} catch (cn.dev33.satoken.exception.NotLoginException e) {
|
||||
log.error("未登录:{}", e.getMessage());
|
||||
throw new BizException(ResultCode.TOKEN_FAILED.getCode(), "请先登录认证后操作");
|
||||
} catch (cn.dev33.satoken.exception.NotRoleException e) {
|
||||
log.error("权限不足:{}", e.getMessage());
|
||||
throw new BizException(ResultCode.PERMISSION_DENIED.getCode(), "没有访问权限");
|
||||
} catch (Exception e) {
|
||||
log.error("权限验证失败:{}", e.getMessage());
|
||||
throw new BizException(ResultCode.PERMISSION_DENIED.getCode(), "权限验证失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package com.kexue.skills.common;
|
||||
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
/**
|
||||
* @author 维哥
|
||||
* @Description 缓存管理器
|
||||
* @create 2025-02-25 15:25
|
||||
*/
|
||||
public class CacheManager {
|
||||
|
||||
// 创建一个缓存实例,设置缓存时间为180分钟
|
||||
private static final Cache<String, String> tokenCache = CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(3, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
// 静态方法,用于将token放入缓存
|
||||
public static void putTokenToCache(String username, String token) {
|
||||
tokenCache.put(username, token);
|
||||
}
|
||||
|
||||
// 静态方法,用于从缓存中获取token
|
||||
public static String getTokenFromCache(String username) {
|
||||
return tokenCache.getIfPresent(username);
|
||||
}
|
||||
|
||||
// 静态方法,用于从缓存中移除token
|
||||
public static void removeTokenFromCache(String username) {
|
||||
tokenCache.invalidate(username);
|
||||
}
|
||||
|
||||
// 静态方法,用于检查token是否有效
|
||||
public static boolean isTokenValid(String token) {
|
||||
return tokenCache.asMap().containsValue(token);
|
||||
}
|
||||
|
||||
// 新增静态方法,用于从缓存中通过token获取username
|
||||
public static String getUsernameFromToken(String token) {
|
||||
for (String key : tokenCache.asMap().keySet()) {
|
||||
if (token.equals(tokenCache.getIfPresent(key))) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//查看缓存剩余时间
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
package com.kexue.skills.common;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* 通用返回对象
|
||||
* @author Administrator
|
||||
*/
|
||||
@ApiModel(value = "公共返回结果类")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class CommonResult<T> {
|
||||
@Schema(description ="返回编码")
|
||||
private long status;
|
||||
@Schema(description ="返回信息")
|
||||
private String message;
|
||||
@Schema(description ="返回结果")
|
||||
private T data;
|
||||
|
||||
public CommonResult(long status, String message) {
|
||||
this.status = status;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
protected CommonResult(long status, String message, T data) {
|
||||
this.status = status;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功返回结果
|
||||
*
|
||||
* @param data 获取的数据
|
||||
*/
|
||||
public static <T> CommonResult<T> success(T data) {
|
||||
return new CommonResult<T>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage(), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功返回结果
|
||||
*
|
||||
* @param errorCode 获取的编码
|
||||
* @param data 获取的数据
|
||||
* @param message 提示信息
|
||||
*/
|
||||
public static <T> CommonResult<T> success(IErrorCode errorCode, String message,T data) {
|
||||
return new CommonResult<T>(errorCode.getCode(), message, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功返回结果
|
||||
*
|
||||
* @param errorCode 获取的数据
|
||||
* @param message 提示信息
|
||||
*/
|
||||
public static <T> CommonResult<T> success(IErrorCode errorCode, String message ) {
|
||||
return new CommonResult<T>(errorCode.getCode(), message,null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败返回结果
|
||||
* @param errorCode 错误码
|
||||
*/
|
||||
public static <T> CommonResult<T> failed(IErrorCode errorCode) {
|
||||
return new CommonResult<T>(errorCode.getCode(), errorCode.getMessage(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败返回结果
|
||||
* @param errorCode 错误码
|
||||
* @param message 错误信息
|
||||
*/
|
||||
public static <T> CommonResult<T> failed(IErrorCode errorCode,String message) {
|
||||
return new CommonResult<T>(errorCode.getCode(), message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败返回结果
|
||||
* @param message 提示信息
|
||||
*/
|
||||
public static <T> CommonResult<T> failed(String message) {
|
||||
return new CommonResult<T>(ResultCode.FAILED.getCode(), message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败返回结果
|
||||
* @param message 提示信息
|
||||
*/
|
||||
public static <T> CommonResult<T> failed(long errorCode,String message) {
|
||||
return new CommonResult<T>(errorCode, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败返回结果
|
||||
*/
|
||||
public static <T> CommonResult<T> failed() {
|
||||
return failed(ResultCode.FAILED);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 失败返回结果
|
||||
*
|
||||
* @param errorCode 获取的编码
|
||||
* @param data 获取的数据
|
||||
* @param message 提示信息
|
||||
*/
|
||||
public static <T> CommonResult<T> failed(IErrorCode errorCode, String message,T data) {
|
||||
return new CommonResult<T>(errorCode.getCode(), message, data);
|
||||
}
|
||||
|
||||
public static <T> CommonResult<T> of(IErrorCode errorCode, String message ,T data) {
|
||||
return new CommonResult<T>(errorCode.getCode(), message, data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.kexue.skills.common;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public interface Const {
|
||||
|
||||
String FILE_UPLOAD_DIR = "/data/service/hyxp-portal/upload/file/";
|
||||
String IMG_UPLOAD_DIR = "/data/service/hyxp-portal/upload/images/";
|
||||
Integer LOGIN_USER_NOT_FOUND_ERROR = 1;
|
||||
Integer LOGIN_PASSWOR_ERROR = 2;
|
||||
Integer LOGIN_SUCCESS = 3;
|
||||
|
||||
|
||||
//用户状态
|
||||
Integer USER_STATUS_NORMAL = 1;
|
||||
Integer USER_STATUS_DISABLED = 2;
|
||||
|
||||
//是否删除
|
||||
Integer DELETE_FLAG_YES = 1;
|
||||
|
||||
Integer DELETE_FLAG_NO = 0;
|
||||
List<String> ADMIN_USER_LIST = Arrays.asList("admin","administrator","super","root","boss");
|
||||
|
||||
Double TONE_TO_LITERS = 1210d;
|
||||
Integer PURCHASE_TYPE_LAST_MONTH_REMAINING = 0;
|
||||
Integer PURCHASE_TYPE_CURRENT_MONTH_PURCHASE = 1;
|
||||
Integer PURCHASE_STATUS_NOT_SELL_OUT = 0;//未卖完
|
||||
Integer PURCHASE_STATUS_SELL_OUT = 2;//卖完 1采购完成、2售卖完成
|
||||
Integer IS_RECEIVED_YES = 1;
|
||||
Integer IS_RECEIVED_NO = 0;
|
||||
Integer PAYMENT_TYPE_SM = 1; //扫码支付
|
||||
Integer ACCOUNT_STATUS_ACCOUNTED = 1;//已扎帐
|
||||
Integer ACCOUNT_STATUS_UNACCOUNTED = 2; //未扎帐
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package com.kexue.skills.common;
|
||||
|
||||
/**
|
||||
* 错误代号和信息
|
||||
* 主要处理一些错误相关的信息
|
||||
**/
|
||||
public enum ErrorStatus {
|
||||
OK(200, "OK"),
|
||||
FOUND(302, "Found"),
|
||||
BAD_REQUEST(400, "Bad Request"),
|
||||
UNAUTHORIZED(401, "Unauthorized"),
|
||||
FORBIDDEN(403, "Forbidden"),
|
||||
NOT_FOUND(404, "Not Found"),
|
||||
INTERNAL_SERVER_ERROR(500, "Internal Server Error"),
|
||||
SERVICE_UNAVAILABLE(503, "Service Unavailable");
|
||||
|
||||
private final int code;
|
||||
|
||||
private final String message;
|
||||
|
||||
ErrorStatus(int code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.kexue.skills.common;
|
||||
|
||||
/**
|
||||
* 封装API的错误码
|
||||
* Created by macro on 2019/4/19.
|
||||
* @author hurun
|
||||
*/
|
||||
public interface IErrorCode {
|
||||
/**
|
||||
* 返回错误码
|
||||
* @return 返回错误码
|
||||
*/
|
||||
long getCode();
|
||||
|
||||
/**
|
||||
* 返回错误信息
|
||||
* @return 返回错误信息
|
||||
*/
|
||||
String getMessage();
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
package com.kexue.skills.common;
|
||||
|
||||
/**
|
||||
* 请求返回结果
|
||||
*
|
||||
**/
|
||||
public class Result<T> {
|
||||
private boolean success = true;
|
||||
private int code = ErrorStatus.OK.getCode();
|
||||
private String message = "";
|
||||
private T data;
|
||||
|
||||
public static <T> Result<T> newInstance() {
|
||||
return new Result<T>();
|
||||
}
|
||||
|
||||
public Result() {
|
||||
|
||||
}
|
||||
|
||||
public Result(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Result(ErrorStatus status) {
|
||||
this.message = status.getMessage();
|
||||
this.code = status.getCode();
|
||||
}
|
||||
|
||||
public Result(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
|
||||
public Result(int code, String message) {
|
||||
this.message = message;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Result(int code, String message, T data) {
|
||||
this.message = message;
|
||||
this.code = code;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
|
||||
public Result<T> status(ErrorStatus status) {
|
||||
this.message = message;
|
||||
this.code = code;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Result<T> ok() {
|
||||
success = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Result<T> fail() {
|
||||
success = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Result<T> message(String message) {
|
||||
this.message = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Result<T> data(T data) {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public Result<T> code(int code) {
|
||||
this.code = code;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public void setSuccess(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
package com.kexue.skills.common;
|
||||
|
||||
/**
|
||||
* 枚举了一些常用API操作码
|
||||
*
|
||||
* @author macro
|
||||
* @date 2019/4/19
|
||||
*/
|
||||
public enum ResultCode implements IErrorCode {
|
||||
/**
|
||||
* 返回成功
|
||||
* */
|
||||
SUCCESS(1000, "返回成功"),
|
||||
/**
|
||||
* 数据处理成功
|
||||
* */
|
||||
SJCL_SUCCESS(1001,"数据处理成功"),
|
||||
/**
|
||||
* 上传文件成功
|
||||
* */
|
||||
WJSC_SUCCESS(1002,"上传文件成功"),
|
||||
/**
|
||||
* 数据模板导入成功
|
||||
* */
|
||||
MBDR_SUCCESS(1005,"数据模板导入成功"),
|
||||
/**
|
||||
* 数据处理失败
|
||||
* */
|
||||
SJCL_FAILED(-1001,"数据处理失败"),
|
||||
/**
|
||||
* 上传文件失败
|
||||
* */
|
||||
WJSC_FAILED(-1002,"上传文件失败"),
|
||||
/**
|
||||
* 导出文件成功
|
||||
* */
|
||||
DCWJ_FAILED(-1003,"导出文件失败"),
|
||||
/**
|
||||
* token验证失败
|
||||
* */
|
||||
TOKEN_FAILED(-1004,"登录认证失败或过期"),
|
||||
/**
|
||||
* token验证成功
|
||||
* */
|
||||
TOKEN_SUCCESS(1004,"token验证成功"),
|
||||
/**
|
||||
* 数据模板导入失败
|
||||
* */
|
||||
SJDR_FAILED(-1005,"数据模板导入失败"),
|
||||
/**
|
||||
* 返回失败
|
||||
* */
|
||||
FAILED(-1000, "返回失败"),
|
||||
/**
|
||||
* 参数校验错误
|
||||
* */
|
||||
VALIDATE_FAILED(-1007, "参数校验错误"),
|
||||
/**
|
||||
* 登录失败
|
||||
* */
|
||||
LOGIN_FAILED(-1006,"登录失败"),
|
||||
/**
|
||||
* 登录成功
|
||||
* */
|
||||
LOGIN_SUCCESS(1006,"登录成功"),
|
||||
|
||||
/**
|
||||
* 资源为空
|
||||
* */
|
||||
RESOURCES_SUCCESS(1009,"无访问权限"),
|
||||
|
||||
/**
|
||||
* 资源为空
|
||||
* */
|
||||
NOT_ALLOWED(-1009,"无使用权限"),
|
||||
NOT_ORG(-1010,"不存在的机构"),
|
||||
/**
|
||||
* 权限不足
|
||||
* */
|
||||
PERMISSION_DENIED(-1011,"没有访问权限"),
|
||||
|
||||
/**
|
||||
* 请稍后再试
|
||||
* */
|
||||
BLOCK_HANDLER(-9999,"请稍后再试"),
|
||||
|
||||
/**
|
||||
* 异常访问
|
||||
* */
|
||||
FALLBACK(-9998,"异常访问"),
|
||||
|
||||
/**
|
||||
* 统一异常返回码
|
||||
* */
|
||||
EXCEPTION_HANDLER(-2500,"服务异常,请联系管理员");
|
||||
|
||||
private final long code;
|
||||
private final String message;
|
||||
|
||||
private ResultCode(long code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.kexue.skills.common;
|
||||
|
||||
/**
|
||||
* 返回结果工具类
|
||||
*
|
||||
**/
|
||||
public class ResultEntity<T> {
|
||||
public static boolean isOk(Result<?> result){
|
||||
return null != result && result.getCode() == ErrorStatus.OK.getCode();
|
||||
}
|
||||
|
||||
public static <T> Result<T> ok(){
|
||||
return new Result<T>(ErrorStatus.OK);
|
||||
}
|
||||
|
||||
public static <T> Result<T> fail(){
|
||||
return new Result<T>(ErrorStatus.BAD_REQUEST).fail();
|
||||
}
|
||||
|
||||
public static <T> Result<T> ok(T data){
|
||||
return new Result<T>(ErrorStatus.OK.getCode(), ErrorStatus.OK.getMessage(), data);
|
||||
}
|
||||
|
||||
public static <T> Result<T> status(ErrorStatus status){
|
||||
return new Result<T>(status.getCode(), status.getMessage()).fail();
|
||||
}
|
||||
|
||||
public static <T> Result<T> fail(ErrorStatus status){
|
||||
return new Result<T>(status.getCode(), status.getMessage()).fail();
|
||||
}
|
||||
|
||||
public static <T> Result<T> fail(String message){
|
||||
return fail(ErrorStatus.BAD_REQUEST.getCode(), message, (T)null).fail();
|
||||
}
|
||||
|
||||
public static <T> Result<T> fail(int code, String message){
|
||||
return new Result<T>(code, message).fail();
|
||||
}
|
||||
|
||||
public static <T> Result<T> fail(int code ,String message, T data){
|
||||
return new Result<T>(code, message, data).fail();
|
||||
}
|
||||
|
||||
public static <T> Result<T> notfound(){
|
||||
return new Result<T>(ErrorStatus.NOT_FOUND).fail();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package com.kexue.skills.common;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Random;
|
||||
|
||||
public class VerifyCode {
|
||||
|
||||
public static String drawRandomText(int width, int height, BufferedImage verifyImg) {
|
||||
|
||||
Graphics2D graphics = (Graphics2D) verifyImg.getGraphics();
|
||||
graphics.setColor(Color.WHITE);//设置画笔颜色-验证码背景色
|
||||
graphics.fillRect(0, 0, width, height);//填充背景
|
||||
graphics.setFont(new Font("微软雅黑", Font.BOLD, 40));
|
||||
|
||||
//数字和字母的组合
|
||||
String baseNumLetter = "123456789abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int x = 10; //旋转原点的 x 坐标
|
||||
String ch;
|
||||
Random random = new Random();
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
graphics.setColor(getRandomColor());
|
||||
|
||||
//设置字体旋转角度
|
||||
int degree = random.nextInt() % 30; //角度小于30度
|
||||
int dot = random.nextInt(baseNumLetter.length());
|
||||
|
||||
ch = baseNumLetter.charAt(dot) + "";
|
||||
builder.append(ch);
|
||||
|
||||
//正向旋转
|
||||
graphics.rotate(degree * Math.PI / 180, x, 45);
|
||||
graphics.drawString(ch, x, 45);
|
||||
|
||||
//反向旋转
|
||||
graphics.rotate(-degree * Math.PI / 180, x, 45);
|
||||
x += 48;
|
||||
}
|
||||
|
||||
//画干扰线
|
||||
for (int i = 0; i < 6; i++) {
|
||||
// 设置随机颜色
|
||||
graphics.setColor(getRandomColor());
|
||||
|
||||
// 随机画线
|
||||
graphics.drawLine(random.nextInt(width), random.nextInt(height),
|
||||
random.nextInt(width), random.nextInt(height));
|
||||
|
||||
}
|
||||
|
||||
//添加噪点
|
||||
for (int i = 0; i < 30; i++) {
|
||||
int x1 = random.nextInt(width);
|
||||
int y1 = random.nextInt(height);
|
||||
|
||||
graphics.setColor(getRandomColor());
|
||||
graphics.fillRect(x1, y1, 2, 2);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机取色
|
||||
*/
|
||||
private static Color getRandomColor() {
|
||||
Random ran = new Random();
|
||||
return new Color(ran.nextInt(256),
|
||||
ran.nextInt(256), ran.nextInt(256));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
package com.kexue.skills.common.util;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* AES工具类
|
||||
*
|
||||
**/
|
||||
public class AESUtils {
|
||||
private static String iv = "0123456789ABCDEF";//偏移量字符串必须是16位 当模式是CBC的时候必须设置偏移量
|
||||
private static String Algorithm = "AES";
|
||||
private static String AlgorithmProvider = "AES/ECB/PKCS5Padding"; // 算法/模式/补码方式
|
||||
|
||||
public static byte[] generatorKey() throws NoSuchAlgorithmException {
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance(Algorithm);
|
||||
keyGenerator.init(256);//默认128,获得无政策权限后可为192或256
|
||||
SecretKey secretKey = keyGenerator.generateKey();
|
||||
return secretKey.getEncoded();
|
||||
}
|
||||
|
||||
public static IvParameterSpec getIv() throws UnsupportedEncodingException {
|
||||
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes("utf-8"));
|
||||
System.out.println("偏移量:"+byteToHexString(ivParameterSpec.getIV()));
|
||||
return ivParameterSpec;
|
||||
}
|
||||
|
||||
public static byte[] encrypt(String src, byte[] key) throws NoSuchAlgorithmException, NoSuchPaddingException,
|
||||
InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, InvalidAlgorithmParameterException {
|
||||
SecretKey secretKey = new SecretKeySpec(key, Algorithm);
|
||||
//IvParameterSpec ivParameterSpec = getIv();
|
||||
Cipher cipher = Cipher.getInstance("AES");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
|
||||
byte[] cipherBytes = cipher.doFinal(src.getBytes(Charset.forName("utf-8")));
|
||||
return cipherBytes;
|
||||
}
|
||||
|
||||
public static byte[] decrypt(String src, byte[] key) throws Exception {
|
||||
SecretKey secretKey = new SecretKeySpec(key, Algorithm);
|
||||
|
||||
//IvParameterSpec ivParameterSpec = getIv();
|
||||
Cipher cipher = Cipher.getInstance(AlgorithmProvider);
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey);
|
||||
byte[] hexBytes = hexStringToBytes(src);
|
||||
byte[] plainBytes = cipher.doFinal(hexBytes);
|
||||
return plainBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将byte转换为16进制字符串
|
||||
* @param src
|
||||
* @return
|
||||
*/
|
||||
public static String byteToHexString(byte[] src) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < src.length; i++) {
|
||||
int v = src[i] & 0xff;
|
||||
String hv = Integer.toHexString(v);
|
||||
if (hv.length() < 2) {
|
||||
sb.append("0");
|
||||
}
|
||||
sb.append(hv);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将16进制字符串装换为byte数组
|
||||
* @param hexString
|
||||
* @return
|
||||
*/
|
||||
public static byte[] hexStringToBytes(String hexString) {
|
||||
hexString = hexString.toUpperCase();
|
||||
int length = hexString.length() / 2;
|
||||
char[] hexChars = hexString.toCharArray();
|
||||
byte[] b = new byte[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
int pos = i * 2;
|
||||
b[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
private static byte charToByte(char c) {
|
||||
return (byte) "0123456789ABCDEF".indexOf(c);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
// byte key[] = generatorKey();
|
||||
// 密钥必须是16的倍数
|
||||
byte key[] = "417256a7dada4236".getBytes("utf-8");//hexStringToBytes("0123456789ABCDEF");
|
||||
String src = "laoxu123";
|
||||
System.out.println("密钥:"+byteToHexString(key));
|
||||
System.out.println("原字符串:"+src);
|
||||
|
||||
String enc = byteToHexString(encrypt(src, key));
|
||||
System.out.println("加密:"+enc);
|
||||
System.out.println("解密:"+new String(decrypt(enc, key), "utf-8"));
|
||||
} catch (InvalidKeyException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchPaddingException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
e.printStackTrace();
|
||||
} catch (BadPaddingException e) {
|
||||
e.printStackTrace();
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package com.kexue.skills.common.util;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* @author laoxu
|
||||
**/
|
||||
public class BytesHelper {
|
||||
private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
|
||||
public static int toInt(byte[] bytes)
|
||||
{
|
||||
int result = 0;
|
||||
for (int i = 0; (i < 4) && (i < bytes.length); i++) {
|
||||
result = (result << 8) - -128 + bytes[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Object byteToObject(byte[] bytes) {
|
||||
Object obj = null;
|
||||
try {
|
||||
ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
|
||||
ObjectInputStream oi = new ObjectInputStream(bi);
|
||||
obj = oi.readObject();
|
||||
bi.close();
|
||||
oi.close();
|
||||
} catch (Exception e) {
|
||||
System.out.println("translation" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static byte[] objectToByte(Object obj) {
|
||||
byte[] bytes = (byte[])null;
|
||||
try {
|
||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oo = new ObjectOutputStream(bo);
|
||||
oo.writeObject(obj);
|
||||
bytes = bo.toByteArray();
|
||||
bo.close();
|
||||
oo.close();
|
||||
} catch (Exception e) {
|
||||
System.out.println("translation" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static byte[] inputStreamToByte(InputStream is) throws IOException {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
int ch;
|
||||
while ((ch = is.read()) != -1)
|
||||
{
|
||||
os.write(ch);
|
||||
}
|
||||
byte[] bystes = os.toByteArray();
|
||||
os.close();
|
||||
return bystes;
|
||||
}
|
||||
|
||||
public static String byteArrayToHexString(byte[] bytes)
|
||||
{
|
||||
char[] chars = new char[bytes.length * 2];
|
||||
|
||||
int ii = 0;
|
||||
for (int i = 0; i < bytes.length; i++)
|
||||
{
|
||||
byte b = bytes[i];
|
||||
chars[(ii++)] = HEX_DIGITS[(b >>> 4 & 0xF)];
|
||||
|
||||
chars[(ii++)] = HEX_DIGITS[(b & 0xF)];
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
public static byte[] hexStringToByteArray(String hexString) {
|
||||
byte[] bytes = new byte[hexString.length() / 2];
|
||||
int ii = 0;
|
||||
char[] chars = hexString.toCharArray();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
int ch = charToInteger(chars[(ii++)]);
|
||||
int cl = charToInteger(chars[(ii++)]);
|
||||
int b = ch << 4 | cl;
|
||||
bytes[i] = ((byte)b);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
public static int charToInteger(char c) {
|
||||
if ((c >= '0') && (c <= '9'))
|
||||
return c - '0';
|
||||
if ((c >= 'a') && (c <= 'f'))
|
||||
return '\n' + c - 97;
|
||||
if ((c >= 'A') && (c <= 'F')) {
|
||||
return '\n' + c - 65;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
package com.kexue.skills.common.util;
|
||||
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author 维哥
|
||||
* @Description
|
||||
* @create 2025-03-03 10:58
|
||||
*/
|
||||
public class DateConverter {
|
||||
|
||||
/**
|
||||
* 将中文日期格式转换为标准格式(yyyy-MM-dd)
|
||||
* @param chineseDate 示例:"2025年2月22日"
|
||||
* @return 示例:"2025-02-22"
|
||||
*/
|
||||
public static String convertChineseDate(String chineseDate) {
|
||||
if (StrUtil.isBlank(chineseDate)) return null;
|
||||
return DateUtil.parse(chineseDate.replace("日", ""), "yyyy年M月d")
|
||||
.toString("yyyy-MM-dd");
|
||||
}
|
||||
|
||||
/**
|
||||
* 将简写时间转换为标准时间格式(HH:mm:ss)
|
||||
* @param shortTime 示例:"1:30" 或 "12:5"
|
||||
* @return 示例:"01:30:00" 或 "12:05:00"
|
||||
*/
|
||||
public static String convertShortTime(String shortTime) {
|
||||
if (StrUtil.isBlank(shortTime)) return null;
|
||||
|
||||
// 处理缺失前导零的情况
|
||||
String[] parts = shortTime.split(":");
|
||||
if (parts.length != 2) return null;
|
||||
|
||||
String hours = String.format("%02d", Integer.parseInt(parts[0]));
|
||||
String minutes = String.format("%02d", Integer.parseInt(parts[1]));
|
||||
|
||||
return DateUtil.parseTime(hours + ":" + minutes + ":00").toString("HH:mm:ss");
|
||||
}
|
||||
|
||||
public static Date convertChineseDateTime(String chineseDate, String shortTime){
|
||||
Date date = null;
|
||||
|
||||
try {
|
||||
// 清洗非法null字符串
|
||||
if(chineseDate != null) {
|
||||
chineseDate.replace(" ","");
|
||||
chineseDate = chineseDate.replace(" null", ""); // 替换时间部分的null
|
||||
chineseDate = chineseDate.replace("null", ""); // 处理其他可能的null情况
|
||||
chineseDate = convertChineseDate(chineseDate);
|
||||
}
|
||||
|
||||
if(shortTime != null) {
|
||||
shortTime.replace(" ","");
|
||||
shortTime = shortTime.replace(" null", ""); // 替换时间部分的null
|
||||
shortTime = shortTime.replace("null", ""); // 处理其他可能的null情况
|
||||
shortTime = convertShortTime(shortTime);
|
||||
}
|
||||
|
||||
if (StrUtil.isNotBlank(chineseDate) && StrUtil.isNotBlank(shortTime)){
|
||||
date = DateUtil.parse(chineseDate+ " " + convertShortTime(shortTime)==null?"00:00:00":convertShortTime(shortTime));
|
||||
}
|
||||
if (StrUtil.isNotBlank(chineseDate) && StrUtil.isBlank(shortTime)){
|
||||
return DateUtil.parse(chineseDate);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();//
|
||||
}
|
||||
date = DateUtil.parse(chineseDate + " 00:00:00");
|
||||
return date;
|
||||
}
|
||||
|
||||
public static String convertChineseDateTimeStr(String chineseDate, String shortTime){
|
||||
if (StrUtil.isNotBlank(chineseDate) || StrUtil.isNotBlank(shortTime)){
|
||||
return convertChineseDate(chineseDate)+ " " + convertShortTime(shortTime);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// 测试示例
|
||||
public static void main(String[] args) {
|
||||
System.out.println(convertChineseDate("2025年2月22日")); // 输出:2025-02-22
|
||||
System.out.println(convertShortTime("1:30")); // 输出:01:30:00
|
||||
System.out.println(convertShortTime("12:5")); // 输出:12:05:00
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package com.kexue.skills.common.util;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description: 日期工具类
|
||||
**/
|
||||
public class DateUtil {
|
||||
public static Date getDateAdd(int days){
|
||||
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.add(Calendar.DAY_OF_MONTH, -days);
|
||||
return c.getTime();
|
||||
}
|
||||
|
||||
public static List<String> getDaysBetwwen(int days){
|
||||
List<String> dayss = new ArrayList<>();
|
||||
Calendar start = Calendar.getInstance();
|
||||
start.setTime(getDateAdd(days));
|
||||
Long startTIme = start.getTimeInMillis();
|
||||
Calendar end = Calendar.getInstance();
|
||||
end.setTime(new Date());
|
||||
Long endTime = end.getTimeInMillis();
|
||||
Long oneDay = 1000 * 60 * 60 * 24l;
|
||||
Long time = startTIme;
|
||||
while (time <= endTime) {
|
||||
Date d = new Date(time);
|
||||
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
|
||||
dayss.add(df.format(d));
|
||||
time += oneDay;
|
||||
}
|
||||
return dayss;
|
||||
}
|
||||
|
||||
/*public static void main(String[] args) {
|
||||
System.out.println(getDaysBetwwen(7));
|
||||
}*/
|
||||
}
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
package com.kexue.skills.common.util;
|
||||
|
||||
import cn.hutool.core.annotation.AnnotationUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.poi.excel.ExcelUtil;
|
||||
import cn.hutool.poi.excel.ExcelWriter;
|
||||
import cn.hutool.poi.excel.StyleSet;
|
||||
import com.kexue.skills.annotation.Excel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
// 假设 Excel 注解的定义
|
||||
|
||||
public class ExportUtils {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ExportUtils.class);
|
||||
|
||||
/**
|
||||
* 通用Excel导出方法
|
||||
* @param list 数据集合
|
||||
* @param clazz 数据类型
|
||||
* @param outputPath 输出路径(含文件名)
|
||||
*/
|
||||
public static <T> void export(List<T> list, Class<T> clazz, String outputPath) {
|
||||
if (list == null || clazz == null || StrUtil.isBlank(outputPath)) {
|
||||
log.error("导出参数异常,list、clazz、outputPath 不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取带Excel注解的字段
|
||||
List<Field> fields;
|
||||
try {
|
||||
fields = Arrays.stream(ReflectUtil.getFields(clazz))
|
||||
.filter(f -> AnnotationUtil.hasAnnotation(f, Excel.class))
|
||||
.sorted(Comparator.comparingInt(f -> {
|
||||
Excel excel = AnnotationUtil.getAnnotation(f, Excel.class);
|
||||
return excel.sort();
|
||||
}))
|
||||
.collect(Collectors.toList());
|
||||
} catch (Exception e) {
|
||||
log.error("获取带Excel注解的字段时出错", e);
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建ExcelWriter
|
||||
try (ExcelWriter writer = ExcelUtil.getWriter()) {
|
||||
// 设置列标题
|
||||
fields.forEach(field -> {
|
||||
Excel excelAnno = AnnotationUtil.getAnnotation(field, Excel.class);
|
||||
String title = getColumnTitle(field, excelAnno);
|
||||
writer.addHeaderAlias(field.getName(), title);
|
||||
});
|
||||
|
||||
// 写入数据
|
||||
writer.write(list, true);
|
||||
|
||||
// 输出文件
|
||||
try {
|
||||
writer.flush(FileUtil.file(outputPath));
|
||||
log.info("Excel文件导出成功,路径:{}", outputPath);
|
||||
} catch (Exception e) {
|
||||
log.error("导出Excel文件到路径 {} 时出错", outputPath, e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("创建ExcelWriter或写入数据时出错", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取列标题
|
||||
*/
|
||||
public static String getColumnTitle(Field field, Excel excelAnno) {
|
||||
// 优先使用Excel注解的label
|
||||
if (StrUtil.isNotBlank(excelAnno.label())) {
|
||||
return excelAnno.label();
|
||||
}
|
||||
|
||||
// 次选ApiModelProperty的value
|
||||
ApiModelProperty apiModelProperty = AnnotationUtil.getAnnotation(field, ApiModelProperty.class);
|
||||
if (apiModelProperty != null && StrUtil.isNotBlank(apiModelProperty.value())) {
|
||||
return apiModelProperty.value();
|
||||
}
|
||||
|
||||
// 最后使用字段名
|
||||
return field.getName();
|
||||
}
|
||||
|
||||
// 新增流式导出方法
|
||||
public static <T> void export(List<T> list, Class<T> clazz, OutputStream outputStream) {
|
||||
try (ExcelWriter writer = ExcelUtil.getWriter()) {
|
||||
writer.setOnlyAlias(true);
|
||||
|
||||
// ============== 新增样式配置 ==============
|
||||
// 获取样式工具
|
||||
StyleSet styleSet = writer.getStyleSet();
|
||||
|
||||
// 表头样式配置
|
||||
CellStyle headerStyle = styleSet.getHeadCellStyle();
|
||||
|
||||
// 创建表头字体
|
||||
Font headerFont = writer.createFont();
|
||||
headerFont.setFontName("微软雅黑"); // 字体
|
||||
headerFont.setBold(true); // 加粗
|
||||
headerFont.setFontHeightInPoints((short)12); // 字号
|
||||
headerFont.setColor(IndexedColors.WHITE.getIndex()); // 字体颜色
|
||||
|
||||
// 应用字体到表头样式
|
||||
headerStyle.setFont(headerFont);
|
||||
|
||||
// 设置表头背景色
|
||||
headerStyle.setFillForegroundColor(IndexedColors.DARK_BLUE.getIndex());
|
||||
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
|
||||
// 设置水平居中
|
||||
headerStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
// ============== 样式配置结束 ==============
|
||||
|
||||
List<Field> fields = getSortedFields(clazz);
|
||||
for (Field field : fields) {
|
||||
Excel excelAnno = AnnotationUtil.getAnnotation(field, Excel.class);
|
||||
String title = getColumnTitle(field, excelAnno);
|
||||
System.out.println(title);
|
||||
writer.addHeaderAlias(field.getName(), title);
|
||||
}
|
||||
|
||||
fields.forEach(field -> {
|
||||
if (!isSupportedType(field.getType())) {
|
||||
log.warn("字段 {} 类型 {} 不支持导出,将被忽略", field.getName(), field.getType().getSimpleName());
|
||||
System.out.println("字段 " + field.getName() + " 类型 " + field.getType().getSimpleName() + " 不支持导出,将被忽略");
|
||||
}
|
||||
});
|
||||
|
||||
List<Map<String, Object>> dataList = new ArrayList<>();
|
||||
for (T t : list) {
|
||||
Map<String, Object> stringObjectMap = BeanUtil.beanToMap(t);
|
||||
stringObjectMap.forEach((key, value) -> {
|
||||
if (value == null) {
|
||||
stringObjectMap.put(key, "");
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof Date) {
|
||||
stringObjectMap.put(key, DateUtil.format((Date) value, "yyyy-MM-dd HH:mm:ss"));
|
||||
} else if (value instanceof Number) { // 包含Integer/Long等
|
||||
stringObjectMap.put(key, value);
|
||||
} else if (value instanceof Boolean) {
|
||||
Boolean boolValue = (Boolean) value; // 显式类型转换
|
||||
stringObjectMap.put(key, boolValue ? "是" : "否"); // 布尔值本地化
|
||||
} else if (value.getClass().isPrimitive()) {
|
||||
stringObjectMap.put(key, String.valueOf(value));
|
||||
} else if (!(value instanceof String)) {
|
||||
// 复杂类型处理(按需选择)
|
||||
stringObjectMap.put(key, "");
|
||||
}
|
||||
});
|
||||
dataList.add(stringObjectMap);
|
||||
}
|
||||
|
||||
writer.write(dataList, true);
|
||||
writer.flush(outputStream);
|
||||
}
|
||||
}
|
||||
|
||||
// 类型检查方法
|
||||
private static boolean isSupportedType(Class<?> type) {
|
||||
return type.isPrimitive()
|
||||
|| Number.class.isAssignableFrom(type)
|
||||
|| Date.class.isAssignableFrom(type)
|
||||
|| String.class == type
|
||||
|| Boolean.class == type;
|
||||
}
|
||||
|
||||
// 提取公共字段处理逻辑
|
||||
public static <T> List<Field> getSortedFields(Class<T> clazz) {
|
||||
return Arrays.stream(ReflectUtil.getFields(clazz))
|
||||
.filter(f -> AnnotationUtil.hasAnnotation(f, Excel.class))
|
||||
.sorted(Comparator.comparingInt(f ->
|
||||
AnnotationUtil.getAnnotation(f, Excel.class).sort()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// 扩展Web导出方法
|
||||
public static <T> void webExport(List<T> list, Class<T> clazz, String fileName,
|
||||
HttpServletResponse response) throws Exception {
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString());
|
||||
response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName);
|
||||
export(list, clazz, response.getOutputStream()); // 调用新的流式导出方法
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,339 @@
|
|||
package com.kexue.skills.common.util;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* @Description: 文件工具类
|
||||
**/
|
||||
public final class FileHelper
|
||||
{
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(FileHelper.class);
|
||||
private FileHelper() {}
|
||||
|
||||
/**
|
||||
* 删除指定位置的文件。
|
||||
* @param path 要删除的文件的完全路径
|
||||
*/
|
||||
public static void deleteFile( String path )
|
||||
{
|
||||
try
|
||||
{
|
||||
File file = new File( path ) ;
|
||||
file.delete() ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在指定位置创建文件。
|
||||
* @param filename 文件路径
|
||||
*/
|
||||
public static void createNewFile( String filename )
|
||||
{
|
||||
File file = new File( filename ) ;
|
||||
if( !file.exists() )
|
||||
{
|
||||
createNewFileOrDir( file, "f" ) ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在指定位置创建文件夹。
|
||||
* @param dirname 文件夹路径
|
||||
*/
|
||||
public static void createNewDir( String dirname )
|
||||
{
|
||||
File file = new File( dirname ) ;
|
||||
if( file.exists() )
|
||||
{
|
||||
createNewFileOrDir( file, "d" ) ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串写入指定文件。使用配置节 "framework.web.charset" 指定的编码集。
|
||||
* @param filename 文件路径
|
||||
* @param content 写入内容
|
||||
*/
|
||||
public static void setContentString( String filename, String content )
|
||||
{
|
||||
setContentString( filename, content, "UTF-8" ) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串写入指定文件。
|
||||
* @param filename 文件路径
|
||||
* @param content 写入内容
|
||||
* @param charsetName 字符集名称
|
||||
*/
|
||||
public static void setContentString( String filename, String content, String charsetName )
|
||||
{
|
||||
try
|
||||
{
|
||||
setContentBinary(
|
||||
filename,
|
||||
content.getBytes( charsetName ) ) ;
|
||||
}
|
||||
catch( UnsupportedEncodingException ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将二进制数组写入指定文件。
|
||||
* @param filename 文件路径
|
||||
* @param arybyte 二进制数组
|
||||
*/
|
||||
public static void setContentBinary( String filename, byte[] arybyte )
|
||||
{
|
||||
BufferedOutputStream bufferedStream = null ;
|
||||
|
||||
try
|
||||
{
|
||||
bufferedStream = new BufferedOutputStream( new FileOutputStream( filename ) ) ;
|
||||
bufferedStream.write( arybyte ) ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if( bufferedStream != null )
|
||||
{
|
||||
bufferedStream.close() ;
|
||||
}
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将输入流写入指定文件。
|
||||
* @param filename 文件路径
|
||||
* @param inputStream 输入流
|
||||
*/
|
||||
public static void setContentStream( String filename, InputStream inputStream )
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] bytes = IOUtils.toByteArray( inputStream ) ;
|
||||
setContentBinary( filename, bytes ) ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if( inputStream != null )
|
||||
{
|
||||
inputStream.close() ;
|
||||
}
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串添加进指定文件。使用配置节 "framework.web.charset" 指定的编码集。
|
||||
* @param filename 文件路径
|
||||
* @param content 写入内容
|
||||
*/
|
||||
public static void appendContentString( String filename, String content )
|
||||
{
|
||||
appendContentString( filename, content, "UTF-8" ) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串添加进指定文件。
|
||||
* @param filename 文件路径
|
||||
* @param content 写入内容
|
||||
* @param charsetName 字符集名称
|
||||
*/
|
||||
public static void appendContentString( String filename, String content, String charsetName )
|
||||
{
|
||||
try
|
||||
{
|
||||
appendContentBinary(
|
||||
filename,
|
||||
content.getBytes( charsetName ) ) ;
|
||||
}
|
||||
catch( UnsupportedEncodingException ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将二进制数组添加进指定文件。
|
||||
* @param filename 文件路径
|
||||
* @param arybyte 要写入的二进制数组
|
||||
*/
|
||||
public static void appendContentBinary( String filename, byte[] arybyte )
|
||||
{
|
||||
BufferedOutputStream bufferedStream = null ;
|
||||
|
||||
try
|
||||
{
|
||||
bufferedStream = new BufferedOutputStream( new FileOutputStream( filename, true ) ) ;
|
||||
bufferedStream.write( arybyte ) ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if( bufferedStream != null )
|
||||
{
|
||||
bufferedStream.close() ;
|
||||
}
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将输出流添加进指定文件。
|
||||
* @param filename 文件路径
|
||||
* @param inputStream 要写入的流
|
||||
*/
|
||||
public static void appendContentStream( String filename, InputStream inputStream )
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] bytes = IOUtils.toByteArray( inputStream ) ;
|
||||
appendContentBinary( filename, bytes ) ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if( inputStream != null )
|
||||
{
|
||||
inputStream.close() ;
|
||||
}
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件并将指定的字符串写入文件。使用配置节 "framework.web.charset" 指定的编码集。
|
||||
* @param path 文件路径
|
||||
* @param content 写入内容
|
||||
*/
|
||||
public static void writeFileString( String path, String content )
|
||||
{
|
||||
createNewFile( path ) ;
|
||||
setContentString( path, content ) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件并将指定的字符串写入文件。
|
||||
* @param path 文件路径
|
||||
* @param content 写入内容
|
||||
* @param charsetName 字符集名称
|
||||
*/
|
||||
public static void writeFileString( String path, String content, String charsetName )
|
||||
{
|
||||
createNewFile( path ) ;
|
||||
setContentString( path, content, charsetName ) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件并将指定的二进制数组写入文件。
|
||||
* @param path 文件路径
|
||||
* @param content 要写入的二进制数组
|
||||
*/
|
||||
public static void writeFileBinary( String path, byte[] content )
|
||||
{
|
||||
createNewFile( path ) ;
|
||||
setContentBinary( path, content ) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件并将指定的输入流写入文件。
|
||||
* @param path 文件路径
|
||||
* @param inputStream 要写入的流
|
||||
*/
|
||||
public static void writeFileStream( String path, InputStream inputStream )
|
||||
{
|
||||
createNewFile( path ) ;
|
||||
setContentStream( path, inputStream ) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件名获取扩展名。
|
||||
* @param filename 文件名
|
||||
* @return 扩展名
|
||||
*/
|
||||
public static String getExtFromFileName( String filename )
|
||||
{
|
||||
int t = filename.lastIndexOf( "\\" ) ;
|
||||
if( t != -1 )
|
||||
filename = filename.substring( t + 1 ) ;
|
||||
t = filename.lastIndexOf( "/" ) ;
|
||||
if( t != -1 )
|
||||
filename = filename.substring( t + 1 ) ;
|
||||
t = filename.lastIndexOf( "." ) ;
|
||||
if( t != -1 )
|
||||
return filename.substring( t + 1 ).toLowerCase() ;
|
||||
return "" ;
|
||||
}
|
||||
|
||||
private static void createNewFileOrDir( File file, String type )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( type.equals( "d" ) )
|
||||
file.mkdirs() ;
|
||||
else
|
||||
{
|
||||
file.getParentFile().mkdirs() ;
|
||||
file.createNewFile() ;
|
||||
}
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
package com.kexue.skills.common.util;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class FrontUtils {
|
||||
public static void main(String[] args) {
|
||||
// printList(PurchaseDetail.class);
|
||||
// printEditForm(PurchaseDetail.class);
|
||||
// printEditMethod(PurchaseDetail.class);
|
||||
// printInsertMethod(PurchaseDetail.class);
|
||||
// printFormInitValue(PurchaseDetail.class);
|
||||
|
||||
// printList(SaleDetail.class);
|
||||
// printEditForm(SaleDetail.class);
|
||||
// printEditMethod(SaleDetail.class);
|
||||
// printInsertMethod(SaleDetail.class);
|
||||
// printFormInitValue(SaleDetail.class);
|
||||
|
||||
// printList(DailySummaryDto.class);
|
||||
// printEditForm(DailySummaryDto.class);
|
||||
// printEditMethod(DailySummaryDto.class);
|
||||
// printInsertMethod(DailySummaryDto.class);
|
||||
// printFormInitValue(DailySummaryDto.class);
|
||||
|
||||
// printList(SysUser.class);
|
||||
// printEditForm(SysUser.class);
|
||||
// printEditMethod(SysUser.class);
|
||||
// printInsertMethod(SysUser.class);
|
||||
// printFormInitValue(SysUser.class);
|
||||
|
||||
// printList(TradeHistory.class);
|
||||
// printEditForm(TradeHistory.class);
|
||||
// printEditMethod(TradeHistory.class);
|
||||
// printInsertMethod(TradeHistory.class);
|
||||
// printFormInitValue(TradeHistory.class);
|
||||
|
||||
// printList(TradeFactory.class);
|
||||
// printEditForm(TradeFactory.class);
|
||||
// printEditMethod(TradeFactory.class);
|
||||
// printInsertMethod(TradeFactory.class);
|
||||
// printFormInitValue(TradeFactory.class);
|
||||
|
||||
// printList(AccountTransaction.class);
|
||||
// printEditForm(AccountTransaction.class);
|
||||
// printEditMethod(AccountTransaction.class);
|
||||
// printInsertMethod(AccountTransaction.class);
|
||||
// printFormInitValue(AccountTransaction.class);
|
||||
|
||||
// printList(Trade.class);
|
||||
// printEditForm(Trade.class);
|
||||
// printEditMethod(Trade.class);
|
||||
// printInsertMethod(Trade.class);
|
||||
// printFormInitValue(Trade.class);
|
||||
|
||||
// printList(Supplier.class);
|
||||
// printEditForm(Supplier.class);
|
||||
// printEditMethod(Supplier.class);
|
||||
// printInsertMethod(Supplier.class);
|
||||
// printFormInitValue(Supplier.class);
|
||||
|
||||
// printList(ExpenseAccount.class);
|
||||
// printEditForm(ExpenseAccount.class);
|
||||
// printEditMethod(ExpenseAccount.class);
|
||||
// printInsertMethod(ExpenseAccount.class);
|
||||
// printFormInitValue(ExpenseAccount.class);
|
||||
|
||||
// printList(DailyExpenses.class);
|
||||
// printEditForm(DailyExpenses.class);
|
||||
// printEditMethod(DailyExpenses.class);
|
||||
// printInsertMethod(DailyExpenses.class);
|
||||
// printFormInitValue(DailyExpenses.class);
|
||||
|
||||
|
||||
// printList(BizCardProduct.class);
|
||||
// printEditForm(BizCardProduct.class);
|
||||
// printEditMethod(BizCardProduct.class);
|
||||
// printInsertMethod(BizCardProduct.class);
|
||||
// printFormInitValue(BizCardProduct.class);
|
||||
|
||||
}
|
||||
|
||||
public static void printList(Class clazz){
|
||||
System.out.println("-----------------------printList start-------------------------------------------");
|
||||
Field[] declaredFields = clazz.getDeclaredFields();
|
||||
for (Field declaredField : declaredFields) {
|
||||
if (!declaredField.getName().equals("serialVersionUID")
|
||||
&& !declaredField.getName().equals("deleteFlag")
|
||||
){
|
||||
ApiModelProperty annotation = declaredField.getAnnotation(ApiModelProperty.class);
|
||||
String label = annotation.value();
|
||||
if (declaredField.getName().endsWith("Id") || declaredField.getName().equals("id")){
|
||||
String formHtml = "<el-input v-model=\"editForm."+ declaredField.getName() +"\" v-show=\"false\"></el-input>";
|
||||
System.out.println(formHtml);
|
||||
}else {
|
||||
String formHtml = "<el-table-column sortable prop=\""+ declaredField.getName() +"\" label=\""+ label +"\" width=\"200\"></el-table-column>";
|
||||
System.out.println(formHtml);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void printEditForm(Class clazz){
|
||||
System.out.println("-----------------------printEditForm start-------------------------------------------");
|
||||
Field[] declaredFields = clazz.getDeclaredFields();
|
||||
for (Field declaredField : declaredFields) {
|
||||
if (!declaredField.getName().equals("serialVersionUID")
|
||||
&& !declaredField.getName().equals("deleteFlag")
|
||||
){
|
||||
ApiModelProperty annotation = declaredField.getAnnotation(ApiModelProperty.class);
|
||||
String label = annotation.value();
|
||||
if (declaredField.getName().endsWith("Id") || declaredField.getName().equals("id")){
|
||||
String formHtml = "<el-input v-model=\"editForm."+ declaredField.getName() +"\" v-show=\"false\"></el-input>";
|
||||
System.out.println(formHtml);
|
||||
}else {
|
||||
String formHtml = " <el-form-item label=\""+label+"\" prop=\""+declaredField.getName()+"\">\n" +
|
||||
" <el-input size=\"small\" v-model=\"editForm."+ declaredField.getName() +"\" auto-complete=\"off\" placeholder=\"请输入"+label+"\"></el-input>\n" +
|
||||
" </el-form-item>";
|
||||
System.out.println(formHtml);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void printEditMethod(Class clazz){
|
||||
System.out.println("-----------------------printEditMethod start-------------------------------------------");
|
||||
Field[] declaredFields = clazz.getDeclaredFields();
|
||||
for (Field declaredField : declaredFields) {
|
||||
if (!declaredField.getName().equals("serialVersionUID") && !declaredField.getName().equals("deleteFlag")){
|
||||
ApiModelProperty annotation = declaredField.getAnnotation(ApiModelProperty.class);
|
||||
String label = annotation.value();
|
||||
String formHtml = " this.editForm."+ declaredField.getName() +" = row."+ declaredField.getName() +"";
|
||||
System.out.println(formHtml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void printInsertMethod(Class clazz){
|
||||
System.out.println("-----------------------printInsertMethod start-------------------------------------------");
|
||||
Field[] declaredFields = clazz.getDeclaredFields();
|
||||
for (Field declaredField : declaredFields) {
|
||||
if (!declaredField.getName().equals("serialVersionUID") && !declaredField.getName().equals("deleteFlag")){
|
||||
ApiModelProperty annotation = declaredField.getAnnotation(ApiModelProperty.class);
|
||||
String label = annotation.value();
|
||||
String formHtml = " this.editForm."+ declaredField.getName() +" = ''";
|
||||
System.out.println(formHtml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void printFormInitValue(Class clazz){
|
||||
System.out.println("-----------------------printFormInitValue start-------------------------------------------");
|
||||
Field[] declaredFields = clazz.getDeclaredFields();
|
||||
for (Field declaredField : declaredFields) {
|
||||
if (!declaredField.getName().equals("serialVersionUID") && !declaredField.getName().equals("deleteFlag")){
|
||||
ApiModelProperty annotation = declaredField.getAnnotation(ApiModelProperty.class);
|
||||
String label = annotation.value();
|
||||
String formHtml = ""+ declaredField.getName() +": '',";
|
||||
System.out.println(formHtml);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.kexue.skills.common.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @description: ID管理类
|
||||
**/
|
||||
public class IDUtils {
|
||||
public static final Logger logger = LoggerFactory.getLogger(IDUtils.class);
|
||||
|
||||
public static String getUUID(){
|
||||
return UUID.randomUUID().toString().replace("-","");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
System.out.println(getUUID());
|
||||
logger.debug("test");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package com.kexue.skills.common.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 生成图片工具类
|
||||
*
|
||||
**/
|
||||
public class ImageUtil {
|
||||
private Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private static String DEFAULT_PREVFIX = "thumb_";
|
||||
private static Boolean DEFAULT_FORCE = false;//建议该值为false
|
||||
|
||||
/**
|
||||
* <p>Title: thumbnailImage</p>
|
||||
* <p>Description: 根据图片路径生成缩略图 </p>
|
||||
*
|
||||
* @param imagePath 原图片路径
|
||||
* @param w 缩略图宽
|
||||
* @param h 缩略图高
|
||||
* @param prevfix 生成缩略图的前缀
|
||||
* @param force 是否强制按照宽高生成缩略图(如果为false,则生成最佳比例缩略图)
|
||||
*/
|
||||
public void thumbnailImage(String imagePath, int w, int h, String prevfix, boolean force) {
|
||||
|
||||
File imgFile = new File(imagePath);
|
||||
if (imgFile.exists()) {
|
||||
try {
|
||||
// ImageIO 支持的图片类型 : [BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG, JPEG, WBMP, GIF, gif]
|
||||
String types = Arrays.toString(ImageIO.getReaderFormatNames());
|
||||
String suffix = null;
|
||||
// 获取图片后缀
|
||||
if (imgFile.getName().indexOf(".") > -1) {
|
||||
suffix = imgFile.getName().substring(imgFile.getName().lastIndexOf(".") + 1);
|
||||
}// 类型和图片后缀全部小写,然后判断后缀是否合法
|
||||
if (suffix == null || types.toLowerCase().indexOf(suffix.toLowerCase()) < 0) {
|
||||
log.error("Sorry, the image suffix is illegal. the standard image suffix is {}." + types);
|
||||
return;
|
||||
}
|
||||
log.debug("target image's size, width:{}, height:{}.", w, h);
|
||||
Image img = ImageIO.read(imgFile);
|
||||
if (!force) {
|
||||
// 根据原图与要求的缩略图比例,找到最合适的缩略图比例
|
||||
int width = img.getWidth(null);
|
||||
int height = img.getHeight(null);
|
||||
if ((width * 1.0) / w < (height * 1.0) / h) {
|
||||
if (width > w) {
|
||||
h = Integer.parseInt(new java.text.DecimalFormat("0").format(height * w / (width * 1.0)));
|
||||
log.debug("change image's height, width:{}, height:{}.", w, h);
|
||||
}
|
||||
} else {
|
||||
if (height > h) {
|
||||
w = Integer.parseInt(new java.text.DecimalFormat("0").format(width * h / (height * 1.0)));
|
||||
log.debug("change image's width, width:{}, height:{}.", w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics g = bi.getGraphics();
|
||||
g.drawImage(img, 0, 0, w, h, Color.LIGHT_GRAY, null);
|
||||
g.dispose();
|
||||
String p = imgFile.getPath();
|
||||
// 将图片保存在原目录并加上前缀
|
||||
ImageIO.write(bi, suffix, new File(p.substring(0, p.lastIndexOf(File.separator)) + File.separator + prevfix + imgFile.getName()));
|
||||
log.debug("缩略图在原路径下生成成功");
|
||||
} catch (IOException e) {
|
||||
log.error("generate thumbnail image failed.", e);
|
||||
}
|
||||
} else {
|
||||
log.warn("the image is not exist.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
ImageUtil imageUtil = new ImageUtil();
|
||||
imageUtil.thumbnailImage("C:\\Users\\ACER\\Pictures\\雷克萨斯\\index-kv-nx-0821-2880x1480.jpg",190,180,DEFAULT_PREVFIX,false);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
package com.kexue.skills.common.util;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author laoxu
|
||||
**/
|
||||
|
||||
@Slf4j
|
||||
public class IpUtil {
|
||||
|
||||
public final static String ERROR_IP = "127.0.0.1";
|
||||
|
||||
public final static Pattern pattern = Pattern.
|
||||
compile("(2[5][0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2})\\.(25[0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2})\\.(25[0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2})\\.(25[0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2})");
|
||||
|
||||
/**
|
||||
* 取外网IP
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public static String getRemoteIp(HttpServletRequest request) {
|
||||
String ip = request.getHeader("x-real-ip");
|
||||
if (ip == null) {
|
||||
ip = request.getRemoteAddr();
|
||||
}
|
||||
|
||||
//过滤反向代理的ip
|
||||
String[] stemps = ip.split(",");
|
||||
if (stemps != null && stemps.length >= 1) {
|
||||
//得到第一个IP,即客户端真实IP
|
||||
ip = stemps[0];
|
||||
}
|
||||
|
||||
ip = ip.trim();
|
||||
if (ip.length() > 23) {
|
||||
ip = ip.substring(0, 23);
|
||||
}
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的真实ip
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public static String getUserIP(HttpServletRequest request) {
|
||||
|
||||
// 优先取X-Real-IP
|
||||
String ip = request.getHeader("X-Real-IP");
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("x-forwarded-for");
|
||||
}
|
||||
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
if ("0:0:0:0:0:0:0:1".equals(ip)) {
|
||||
ip = ERROR_IP;
|
||||
}
|
||||
}
|
||||
|
||||
if ("unknown".equalsIgnoreCase(ip)) {
|
||||
ip = ERROR_IP;
|
||||
return ip;
|
||||
}
|
||||
|
||||
int pos = ip.indexOf(',');
|
||||
if (pos >= 0) {
|
||||
ip = ip.substring(0, pos);
|
||||
}
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
||||
public static String getLastIpSegment(HttpServletRequest request) {
|
||||
String ip = getUserIP(request);
|
||||
if (ip != null) {
|
||||
ip = ip.substring(ip.lastIndexOf('.') + 1);
|
||||
} else {
|
||||
ip = "0";
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
public static boolean isValidIP(HttpServletRequest request) {
|
||||
String ip = getUserIP(request);
|
||||
return isValidIP(ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断我们获取的ip是否是一个符合规则ip
|
||||
*
|
||||
* @param ip
|
||||
* @return
|
||||
*/
|
||||
public static boolean isValidIP(String ip) {
|
||||
if (StringUtils.isEmpty(ip)) {
|
||||
log.debug("ip is null. valid result is false");
|
||||
return false;
|
||||
}
|
||||
|
||||
Matcher matcher = pattern.matcher(ip);
|
||||
boolean isValid = matcher.matches();
|
||||
log.debug("valid ip:" + ip + " result is: " + isValid);
|
||||
return isValid;
|
||||
}
|
||||
|
||||
public static String getLastServerIpSegment() {
|
||||
String ip = getServerIP();
|
||||
if (ip != null) {
|
||||
ip = ip.substring(ip.lastIndexOf('.') + 1);
|
||||
} else {
|
||||
ip = "0";
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
public static String getServerIP() {
|
||||
InetAddress inet;
|
||||
try {
|
||||
inet = InetAddress.getLocalHost();
|
||||
String hostAddress = inet.getHostAddress();
|
||||
return hostAddress;
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "127.0.0.1";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package com.kexue.skills.common.util;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* md5工具类
|
||||
*/
|
||||
public class MD5Util {
|
||||
public static final int time = 5;
|
||||
|
||||
public static final String SALT = "springsecurity";
|
||||
|
||||
/**
|
||||
* 密码加密方法
|
||||
*
|
||||
* @param password
|
||||
* @return
|
||||
*/
|
||||
public static String encode(String password) {
|
||||
MessageDigest digest;
|
||||
try {
|
||||
digest = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK).");
|
||||
}
|
||||
try {
|
||||
for (int i = 0; i < time; i++) {
|
||||
byte[] bytes = digest.digest((password + SALT).getBytes("UTF-8"));
|
||||
password = String.format("%032x", new BigInteger(1, bytes));
|
||||
}
|
||||
return password;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK).");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(MD5Util.encode("admin"));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
//package com.kexue.skills.publisher.common.util;
|
||||
//
|
||||
//import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
//import org.springframework.security.core.Authentication;
|
||||
//import org.springframework.security.core.context.SecurityContextHolder;
|
||||
//
|
||||
///**
|
||||
// * @Description: spring security工具类
|
||||
// **/
|
||||
//public class SecurityUtil {
|
||||
// public static String getLoginUser(){
|
||||
// Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
// if (!(authentication instanceof AnonymousAuthenticationToken)) {
|
||||
// String currentUserName = authentication.getName();
|
||||
// return currentUserName;
|
||||
// }
|
||||
// return "";
|
||||
// }
|
||||
//}
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
package com.kexue.skills.common.util;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
|
||||
/**
|
||||
* <p>在 web 容器中进行上传/下载的静态工具类。</p>
|
||||
* <p>不可继承,不可实例化。</p>
|
||||
*/
|
||||
public final class UploadHelper
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(UploadHelper.class);
|
||||
|
||||
private UploadHelper() {}
|
||||
|
||||
private final static String REFERENCE_FILE = "framework-config.xml" ;
|
||||
|
||||
/**
|
||||
* 应用程序的根目录(物理路径)
|
||||
*/
|
||||
public static String BASE_PATH = null ;
|
||||
|
||||
/* static
|
||||
{
|
||||
try
|
||||
{
|
||||
PathMatchingResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver ( Thread.currentThread().getContextClassLoader() ) ;
|
||||
org.springframework.core.io.Resource resource = resourceResolver.getResource( REFERENCE_FILE ) ;
|
||||
BASE_PATH = resource.getFile().getParentFile().getParentFile().getParentFile().getPath() + "\\" ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage());
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 取得请求的服务器根地址(没有虚拟路径),格式为 "http://主机名:端口"。
|
||||
* @param request 请求实例
|
||||
* @return 请求的服务器根地址
|
||||
*/
|
||||
public static String getRequestServerUrl( HttpServletRequest request )
|
||||
{
|
||||
return new StringBuffer( "http://" )
|
||||
.append( request.getServerName() )
|
||||
.append( ":" )
|
||||
.append( request.getServerPort() )
|
||||
.toString() ;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为下载页面提供指定位置的文件流内容。
|
||||
* @param response 下载页面的响应实例
|
||||
* @param filePath 要下载的文件路径
|
||||
* @param downloadName 下载提示显示的文件名称
|
||||
* @param mimeType mime类型
|
||||
*/
|
||||
public static void sendFile(HttpServletResponse response, String filePath, String downloadName, String disposition, String mimeType )
|
||||
{
|
||||
InputStream inStream = null ;
|
||||
OutputStream outStream = null ;
|
||||
try
|
||||
{
|
||||
/*filePath="D:\\WorkingSoftware\\apache-tomcat-7.0.59\\webapps\\ZZ_OA\\upload\\2015\\9\\111.doc";*/
|
||||
String fileName =URLEncoder.encode( downloadName , "UTF-8");
|
||||
response.reset() ;
|
||||
response.setHeader( "Content-disposition", disposition+"; filename=" + fileName ) ;
|
||||
response.setContentType( mimeType ) ;
|
||||
|
||||
FileSystemResource resource = new FileSystemResource( filePath ) ;
|
||||
inStream = resource.getInputStream() ;
|
||||
outStream = response.getOutputStream() ;
|
||||
|
||||
byte[] ba = IOUtils.toByteArray( inStream ) ;
|
||||
outStream.write( ba ) ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if( inStream != null )
|
||||
inStream.close() ;
|
||||
if( outStream != null )
|
||||
outStream.close() ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 提供重定向文本。
|
||||
* @param response 响应实例
|
||||
* @param context 文本内容
|
||||
*/
|
||||
public static void redirectText(HttpServletResponse response, String context )
|
||||
{
|
||||
PrintWriter writer = null ;
|
||||
try
|
||||
{
|
||||
writer = response.getWriter() ;
|
||||
writer.write( context ) ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if( writer != null )
|
||||
writer.close() ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 为下载页面提供字符串内容,如果text、xml等文档。
|
||||
* @param response 下载页面的响应实例
|
||||
* @param context 文本内容
|
||||
* @param downloadName 下载提示显示的文件名称
|
||||
* @param mimeType mime类型
|
||||
*/
|
||||
public static void sendText(HttpServletResponse response, String context, String downloadName, String mimeType )
|
||||
{
|
||||
PrintWriter writer = null ;
|
||||
try
|
||||
{
|
||||
String fileName = new String( downloadName.getBytes(), "iso-8859-1" ) ;
|
||||
|
||||
response.reset() ;
|
||||
response.setHeader( "Content-disposition", "attachment; filename=" + fileName ) ;
|
||||
response.setContentType( mimeType ) ;
|
||||
|
||||
writer = response.getWriter() ;
|
||||
writer.write( context ) ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if( writer != null )
|
||||
writer.close() ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 为下载页面提供二进制内容,如果word、pdf、execl和zip等文档。
|
||||
* @param response 下载页面的响应实例
|
||||
* @param binary 二进制内容
|
||||
* @param downloadName 下载提示显示的文件名称
|
||||
* @param mimeType mime类型
|
||||
*/
|
||||
public static void sendBinary(HttpServletResponse response, byte[] binary, String downloadName, String mimeType )
|
||||
{
|
||||
OutputStream outStream = null ;
|
||||
try
|
||||
{
|
||||
String fileName = new String( downloadName.getBytes(), "iso-8859-1" ) ;
|
||||
|
||||
response.reset() ;
|
||||
response.setHeader( "Content-disposition", "attachment; filename=" + fileName ) ;
|
||||
response.setContentType( mimeType ) ;
|
||||
|
||||
outStream = response.getOutputStream() ;
|
||||
outStream.write( binary ) ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if( outStream != null )
|
||||
outStream.close() ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供重定向文本。
|
||||
* @param response 响应实例
|
||||
* @param binary 文本内容
|
||||
*/
|
||||
public static void redirectBinary(HttpServletResponse response, byte[] binary )
|
||||
{
|
||||
OutputStream writer = null ;
|
||||
try
|
||||
{
|
||||
writer = response.getOutputStream() ;
|
||||
writer.write( binary ) ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if( writer != null )
|
||||
writer.close() ;
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
logger.error(ex.getMessage()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.kexue.skills.common.util;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @Description: 上传文件工具类
|
||||
**/
|
||||
public class UploadUtils {
|
||||
public static String upload(MultipartFile file, String path, String fileName) throws Exception {
|
||||
// 生成新的文件名
|
||||
String realPath = path + "/" + UUID.randomUUID().toString().replace("-", "") + fileName.substring(fileName.lastIndexOf("."));
|
||||
File dest = new File(realPath);
|
||||
// 判断文件父目录是否存在
|
||||
if (!dest.getParentFile().exists()) {
|
||||
dest.getParentFile().mkdir();
|
||||
}
|
||||
// 保存文件
|
||||
file.transferTo(dest);
|
||||
return dest.getName();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package com.kexue.skills.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 验证码配置类
|
||||
* 用于读取application.yml中的验证码配置
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "captcha")
|
||||
public class CaptchaConfig {
|
||||
|
||||
/**
|
||||
* 是否启用验证码验证
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* 验证码有效期(秒)
|
||||
*/
|
||||
private int expireTime = 300;
|
||||
|
||||
/**
|
||||
* 验证码长度
|
||||
*/
|
||||
private int length = 4;
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.kexue.skills.config;
|
||||
|
||||
import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation;
|
||||
import com.alicp.jetcache.anno.config.EnableMethodCache;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* JetCache配置类
|
||||
* @author
|
||||
*/
|
||||
@Configuration
|
||||
@EnableCreateCacheAnnotation
|
||||
@EnableMethodCache(basePackages = "com.kexue.skills.service")
|
||||
public class JetCacheConfig {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package com.kexue.skills.config;
|
||||
|
||||
import cn.dev33.satoken.interceptor.SaInterceptor;
|
||||
import cn.dev33.satoken.router.SaRouter;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* Sa-Token配置类
|
||||
* @author
|
||||
*/
|
||||
@Configuration
|
||||
public class SaTokenConfig implements WebMvcConfigurer {
|
||||
|
||||
/**
|
||||
* 注册Sa-Token拦截器
|
||||
*/
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
// 添加Sa-Token拦截器,校验规则为StpUtil.checkLogin()
|
||||
registry.addInterceptor(new SaInterceptor(handler -> {
|
||||
// 拦截所有请求,除了登录、注册、文档等不需要认证的接口
|
||||
SaRouter
|
||||
// 放行登录接口
|
||||
.match("/login/**").stop()
|
||||
// 放行注册接口
|
||||
.match("/register/**").stop()
|
||||
// 放行Swagger文档
|
||||
.match("/doc.html").stop()
|
||||
.match("/swagger-ui/**").stop()
|
||||
.match("/v3/api-docs/**").stop()
|
||||
// 放行静态资源
|
||||
.match("/static/**").stop()
|
||||
.match("/**/*.css").stop()
|
||||
.match("/**/*.js").stop()
|
||||
.match("/**/*.png").stop()
|
||||
.match("/**/*.jpg").stop()
|
||||
.match("/**/*.jpeg").stop()
|
||||
// 其他请求需要登录
|
||||
.check(() -> StpUtil.checkLogin());
|
||||
})).addPathPatterns("/**");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package com.kexue.skills.config;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
@Component
|
||||
public class StartupListener implements ApplicationListener<ApplicationReadyEvent> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(StartupListener.class);
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent event) {
|
||||
String serverPort = event.getApplicationContext().getEnvironment().getProperty("server.port", "8080");
|
||||
String serverIp = getServerIp();
|
||||
|
||||
String localhostUrl = "http://localhost:" + serverPort + "/doc.html";
|
||||
String ipUrl = "http://" + serverIp + ":" + serverPort + "/doc.html";
|
||||
|
||||
logger.info("========================================");
|
||||
logger.info("API Documentation Access URL:");
|
||||
logger.info("========================================");
|
||||
logger.info(" Local: {}", localhostUrl);
|
||||
logger.info(" Network:{}", ipUrl);
|
||||
logger.info("========================================\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务器的实际IP地址
|
||||
* @return 服务器IP地址
|
||||
*/
|
||||
private String getServerIp() {
|
||||
try {
|
||||
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
|
||||
while (networkInterfaces.hasMoreElements()) {
|
||||
NetworkInterface networkInterface = networkInterfaces.nextElement();
|
||||
if (networkInterface.isLoopback() || networkInterface.isVirtual() || !networkInterface.isUp()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
|
||||
while (inetAddresses.hasMoreElements()) {
|
||||
InetAddress inetAddress = inetAddresses.nextElement();
|
||||
if (inetAddress.isSiteLocalAddress() && !inetAddress.isLoopbackAddress()) {
|
||||
return inetAddress.getHostAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
logger.error("Failed to get server IP address", e);
|
||||
}
|
||||
return "127.0.0.1";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package com.kexue.skills.config;
|
||||
|
||||
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
|
||||
import io.swagger.v3.oas.annotations.info.Info;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.License;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@OpenAPIDefinition(
|
||||
info = @Info(
|
||||
title = "可学AI-skills平台API",
|
||||
version = "1.0.0",
|
||||
description = "API Documentation for Spring MVC Project"
|
||||
)
|
||||
)
|
||||
public class SwaggerConfig {
|
||||
|
||||
@Bean
|
||||
public OpenAPI customOpenAPI() {
|
||||
return new OpenAPI()
|
||||
.info(new io.swagger.v3.oas.models.info.Info()
|
||||
.title("可学AI-skills平台API")
|
||||
.version("1.0.0")
|
||||
.description("API Documentation for Spring MVC Project")
|
||||
.license(new License().name("Apache 2.0").url("http://springdoc.org")));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.kexue.skills.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties;
|
||||
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.thymeleaf.spring6.SpringTemplateEngine;
|
||||
import org.thymeleaf.templatemode.TemplateMode;
|
||||
|
||||
@Configuration(
|
||||
proxyBeanMethods = false
|
||||
)
|
||||
@EnableConfigurationProperties({ThymeleafProperties.class})
|
||||
@ConditionalOnClass({TemplateMode.class, SpringTemplateEngine.class})
|
||||
@AutoConfigureAfter({WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class})
|
||||
public class ThymeleafAutoConfiguration {
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.kexue.skills.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "spring.thymeleaf")
|
||||
public class ThymeleafProperties {
|
||||
private static final Charset DEFAULT_ENCODING = null;
|
||||
public static final String DEFAULT_PREFIX = "classpath:/templates/";
|
||||
public static final String DEFAULT_SUFFIX = ".html";
|
||||
private boolean checkTemplate = true;
|
||||
private boolean checkTemplateLocation = true;
|
||||
private String prefix = "classpath:/templates/";
|
||||
private String suffix = ".html";
|
||||
private String mode = "HTML";
|
||||
private Charset encoding;
|
||||
private boolean cache;
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
package com.kexue.skills.config;
|
||||
|
||||
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.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/** mvc配置,例如:资源映射、视图解析、拦截器等
|
||||
*
|
||||
**/
|
||||
|
||||
@Configuration
|
||||
public class WebMvcConfig implements WebMvcConfigurer {
|
||||
|
||||
// @Autowired
|
||||
// SessionTimeoutInterceptor sessionTimeoutInterceptor;
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
|
||||
registry.addResourceHandler("/assets/ckeditor/**").
|
||||
addResourceLocations("classpath:/static/assets/ckeditor/").
|
||||
setCachePeriod(2592000);
|
||||
|
||||
registry.addResourceHandler("/upload/**").addResourceLocations("file:E://01code//bizcard//upload");
|
||||
|
||||
// 配置Swagger UI资源映射
|
||||
registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
|
||||
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
registry.addViewController("/").setViewName("index");
|
||||
registry.addViewController("/login").setViewName("login");
|
||||
registry.addViewController("/admin").setViewName("admin");
|
||||
|
||||
// 将 /doc.html 重定向到 /swagger-ui/index.html
|
||||
registry.addRedirectViewController("/doc.html", "/swagger-ui/index.html");
|
||||
|
||||
/*
|
||||
registry.addViewController("/index").setViewName("index");
|
||||
|
||||
registry.addViewController("/addNew").setViewName("addNew");
|
||||
registry.addViewController("/myArticle").setViewName("myArticle");
|
||||
registry.addViewController("/myInformation").setViewName("myInformation");
|
||||
registry.addViewController("/register").setViewName("register");
|
||||
registry.addViewController("/submitJournalContegory").setViewName("submitJournalContegory");
|
||||
registry.addViewController("/submitJournalJournalPrevious").setViewName("submitJournalContegory");
|
||||
registry.addViewController("/submitJournalJournal").setViewName("submitJournalJournal");
|
||||
registry.addViewController("/submitJournalUpload").setViewName("submitJournalUpload");*/
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
// registry.addInterceptor(sessionTimeoutInterceptor).addPathPatterns("/**").
|
||||
// excludePathPatterns("/toRegister","/getVerifyCode", "/api/**","/index","/doLogin","/login","/register", "/addNew", "/static/**","/logout","/upload/");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.kexue.skills.annotation.RequireAuth;
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.Account;
|
||||
import com.kexue.skills.entity.dto.AccountDto;
|
||||
import com.kexue.skills.service.AccountService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* (Account)表控制层
|
||||
* 账户管理控制器
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Tag(name = "账户管理 api")
|
||||
@RestController
|
||||
@RequestMapping("/api/account")
|
||||
public class AccountController {
|
||||
/**
|
||||
* 服务对象
|
||||
*/
|
||||
@Resource
|
||||
private AccountService accountService;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param queryDto 查询参数
|
||||
* @return 分页结果
|
||||
*/
|
||||
@Operation(summary = "分页查询账户", description = "分页查询账户")
|
||||
@PostMapping("/pageList")
|
||||
@RequireAuth
|
||||
public CommonResult<PageInfo<Account>> getPageList(@RequestBody AccountDto queryDto) {
|
||||
return CommonResult.success(this.accountService.getPageList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*
|
||||
* @param queryDto 查询参数
|
||||
* @return 列表结果
|
||||
*/
|
||||
@Operation(summary = "查询账户列表", description = "查询账户列表")
|
||||
@PostMapping("/list")
|
||||
@RequireAuth
|
||||
public CommonResult<List<Account>> getList(@RequestBody AccountDto queryDto) {
|
||||
return CommonResult.success(this.accountService.getList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键查询单条数据
|
||||
*
|
||||
* @param accountId 主键
|
||||
* @return 单条数据
|
||||
*/
|
||||
@Operation(summary = "通过ID查询账户", description = "通过ID查询账户")
|
||||
@PostMapping("/queryById/{accountId}")
|
||||
@RequireAuth
|
||||
public CommonResult<Account> queryById(@Parameter(description = "账户ID") @PathVariable("accountId") Long accountId) {
|
||||
return CommonResult.success(this.accountService.queryById(accountId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过用户ID查询单条数据
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 单条数据
|
||||
*/
|
||||
@Operation(summary = "通过用户ID查询账户", description = "通过用户ID查询账户")
|
||||
@PostMapping("/queryByUserId/{userId}")
|
||||
@RequireAuth
|
||||
public CommonResult<Account> queryByUserId(@Parameter(description = "用户ID") @PathVariable("userId") Long userId) {
|
||||
return CommonResult.success(this.accountService.queryByUserId(userId));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.common.util.IDUtils;
|
||||
import com.kexue.skills.config.CaptchaConfig;
|
||||
import com.wf.captcha.SpecCaptcha;
|
||||
import com.wf.captcha.base.Captcha;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 验证码控制器
|
||||
* @author
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/captcha")
|
||||
@CrossOrigin(origins = "*")
|
||||
@Tag(name = "验证码 Api")
|
||||
public class CaptchaController {
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
@Resource
|
||||
private CaptchaConfig captchaConfig;
|
||||
|
||||
/**
|
||||
* 生成验证码
|
||||
* @param response
|
||||
* @throws IOException
|
||||
*/
|
||||
@GetMapping("/generate")
|
||||
@Operation(summary = "生成验证码", description = "生成验证码")
|
||||
public CommonResult<Map<String, String>> generateCaptcha() {
|
||||
// 验证码开关逻辑:只有启用时才生成验证码
|
||||
if (!captchaConfig.isEnabled()) {
|
||||
return CommonResult.success(new HashMap<>());
|
||||
}
|
||||
|
||||
// 生成验证码ID
|
||||
String captchaId = IDUtils.getUUID();
|
||||
|
||||
// 生成验证码
|
||||
SpecCaptcha captcha = new SpecCaptcha(130, 48);
|
||||
// 设置验证码类型为混合类型(数字+字母)
|
||||
captcha.setCharType(Captcha.TYPE_DEFAULT);
|
||||
// 设置验证码长度
|
||||
captcha.setLen(captchaConfig.getLength());
|
||||
// 生成验证码文字
|
||||
String captchaText = captcha.text().toLowerCase();
|
||||
|
||||
// 将验证码存储到Redis中,使用配置的有效期
|
||||
redisTemplate.opsForValue().set("captcha:" + captchaId, captchaText, captchaConfig.getExpireTime(), TimeUnit.SECONDS);
|
||||
|
||||
// 生成验证码图片的Base64编码
|
||||
String base64Image = captcha.toBase64();
|
||||
|
||||
// 构建返回结果
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put("captchaId", captchaId);
|
||||
result.put("captchaImage", base64Image);
|
||||
|
||||
return CommonResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证验证码
|
||||
* @param captchaId 验证码ID
|
||||
* @param captchaValue 用户输入的验证码
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/verify")
|
||||
@Operation(summary = "验证验证码", description = "验证验证码")
|
||||
public CommonResult<Boolean> verifyCaptcha(@RequestParam String captchaId, @RequestParam String captchaValue) {
|
||||
// 验证码开关逻辑:只有启用时才验证验证码
|
||||
if (!captchaConfig.isEnabled()) {
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
if (captchaId == null || captchaValue == null) {
|
||||
return CommonResult.failed("验证码ID和验证码值不能为空");
|
||||
}
|
||||
|
||||
// 从Redis中获取验证码
|
||||
String captchaText = redisTemplate.opsForValue().get("captcha:" + captchaId);
|
||||
if (captchaText == null) {
|
||||
return CommonResult.failed("验证码已过期");
|
||||
}
|
||||
|
||||
// 验证验证码
|
||||
if (captchaText.equals(captchaValue.toLowerCase())) {
|
||||
// 验证成功后,删除验证码
|
||||
redisTemplate.delete("captcha:" + captchaId);
|
||||
return CommonResult.success(true);
|
||||
} else {
|
||||
return CommonResult.failed("验证码错误");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.kexue.skills.annotation.RequireAuth;
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.CmsCategory;
|
||||
import com.kexue.skills.entity.base.IdDto;
|
||||
import com.kexue.skills.entity.dto.CmsCategoryDto;
|
||||
import com.kexue.skills.service.CmsCategoryService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* (CmsCategory)表控制层
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("api/cmsCategory")
|
||||
@Tag(name = "内容类目(skills-分类) Api")
|
||||
@CrossOrigin(origins = "*")
|
||||
public class CmsCategoryController {
|
||||
/**
|
||||
* 服务对象
|
||||
*/
|
||||
@Resource
|
||||
private CmsCategoryService cmsCategoryService;
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param queryDto 筛选条件
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getPageList")
|
||||
@Operation(summary = "查询分页列表", description = "查询分页列表")
|
||||
public CommonResult<PageInfo<CmsCategory>> getPageList(@RequestBody CmsCategoryDto queryDto) {
|
||||
return CommonResult.success(cmsCategoryService.getPageList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*
|
||||
* @param queryDto 筛选条件
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getList")
|
||||
@Operation(summary = "查询列表", description = "查询列表")
|
||||
public CommonResult<PageInfo<CmsCategory>> getList(@RequestBody CmsCategoryDto queryDto) {
|
||||
return CommonResult.success(new PageInfo<>(cmsCategoryService.getList(queryDto)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增数据
|
||||
*
|
||||
* @param cmsCategory 实体
|
||||
* @return 新增结果
|
||||
*/
|
||||
@PostMapping("/insert")
|
||||
@Operation(summary = "新增分类", description = "新增分类")
|
||||
@RequireAuth
|
||||
public CommonResult<CmsCategory> insert(@RequestBody CmsCategory cmsCategory) {
|
||||
return CommonResult.success(cmsCategoryService.insert(cmsCategory));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑数据
|
||||
*
|
||||
* @param cmsCategory 实体
|
||||
* @return 编辑结果
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
@Operation(summary = "更新分类", description = "更新分类")
|
||||
@RequireAuth
|
||||
public CommonResult<CmsCategory> update(@RequestBody CmsCategory cmsCategory) {
|
||||
return CommonResult.success(cmsCategoryService.update(cmsCategory));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键逻辑删除
|
||||
*
|
||||
* @param idDto 主键
|
||||
* @return 删除数据
|
||||
*/
|
||||
@PostMapping("/logicDeleteById")
|
||||
@Operation(summary = "逻辑删除分类", description = "逻辑删除分类")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> logicDeleteById(@RequestBody IdDto idDto) {
|
||||
return CommonResult.success(cmsCategoryService.logicDeleteById(idDto.getId(), "admin") > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*
|
||||
* @param categoryId 主键
|
||||
* @return 删除数据
|
||||
*/
|
||||
@PostMapping("deleteById/{categoryId}")
|
||||
@Operation(summary = "物理删除分类", description = "物理删除分类")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> deleteById(@PathVariable("categoryId") Long categoryId) {
|
||||
return CommonResult.success(cmsCategoryService.deleteById(categoryId) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分类树列表
|
||||
*
|
||||
* @return 分类树列表
|
||||
*/
|
||||
@GetMapping("/getCategoryTreeList")
|
||||
@Operation(summary = "获取分类树列表", description = "获取分类树列表,包含分类名称、分类ID和子分类列表")
|
||||
public CommonResult<java.util.List<CmsCategory>> getCategoryTreeList() {
|
||||
return CommonResult.success(cmsCategoryService.getCategoryTreeList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分类字典
|
||||
*
|
||||
* @return 分类字典,key为分类ID,value为分类名称
|
||||
*/
|
||||
@GetMapping("/getCategoryDict")
|
||||
@Operation(summary = "获取分类字典", description = "获取分类字典,返回Map<Integer,String>,分类ID和分类名称的映射")
|
||||
public CommonResult<java.util.Map<Long, String>> getCategoryDict() {
|
||||
return CommonResult.success(cmsCategoryService.getCategoryDict());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.kexue.skills.annotation.RequireAuth;
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.CmsContent;
|
||||
import com.kexue.skills.entity.base.IdDto;
|
||||
import com.kexue.skills.entity.dto.CmsContentDto;
|
||||
import com.kexue.skills.service.CmsContentService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* (CmsContent)表控制层
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("api/cmsContent")
|
||||
@Tag(name = "内容(skills)管理 Api")
|
||||
@CrossOrigin(origins = "*")
|
||||
public class CmsContentController {
|
||||
/**
|
||||
* 服务对象
|
||||
*/
|
||||
@Resource
|
||||
private CmsContentService cmsContentService;
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param queryDto 筛选条件
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getPageList")
|
||||
@Operation(summary = "查询分页列表", description = "查询分页列表")
|
||||
public CommonResult<PageInfo<CmsContent>> getPageList(@RequestBody CmsContentDto queryDto) {
|
||||
return CommonResult.success(cmsContentService.getPageList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*
|
||||
* @param queryDto 筛选条件
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getList")
|
||||
@Operation(summary = "查询列表", description = "查询列表")
|
||||
public CommonResult<PageInfo<CmsContent>> getList(@RequestBody CmsContentDto queryDto) {
|
||||
return CommonResult.success(new PageInfo<>(cmsContentService.getList(queryDto)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键查询单条数据
|
||||
*
|
||||
* @param contentId 主键
|
||||
* @return 单条数据
|
||||
*/
|
||||
@PostMapping("queryById/{contentId}")
|
||||
@Operation(summary = "通过ID查询内容", description = "通过ID查询内容")
|
||||
public CommonResult<CmsContent> queryById(@PathVariable("contentId") Long contentId) {
|
||||
// 增加阅读量
|
||||
cmsContentService.increaseViewCount(contentId);
|
||||
return CommonResult.success(cmsContentService.queryById(contentId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增数据
|
||||
*
|
||||
* @param cmsContent 实体
|
||||
* @return 新增结果
|
||||
*/
|
||||
@PostMapping("/insert")
|
||||
@Operation(summary = "新增内容", description = "新增内容")
|
||||
@RequireAuth
|
||||
public CommonResult<CmsContent> insert(@RequestBody CmsContent cmsContent) {
|
||||
return CommonResult.success(cmsContentService.insert(cmsContent));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑数据
|
||||
*
|
||||
* @param cmsContent 实体
|
||||
* @return 编辑结果
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
@Operation(summary = "更新内容", description = "更新内容")
|
||||
@RequireAuth
|
||||
public CommonResult<CmsContent> update(@RequestBody CmsContent cmsContent) {
|
||||
return CommonResult.success(cmsContentService.update(cmsContent));
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新审核状态
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @param auditStatus 审核状态
|
||||
* @param reviewerId 审核人ID
|
||||
* @param reviewerName 审核人名称
|
||||
* @param auditComment 审核意见
|
||||
* @return 审核结果
|
||||
*/
|
||||
@PostMapping("/updateAuditStatus")
|
||||
@Operation(summary = "更新审核状态", description = "更新审核状态")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> updateAuditStatus(@RequestParam Long contentId,
|
||||
@RequestParam Integer auditStatus,
|
||||
@RequestParam Long reviewerId,
|
||||
@RequestParam String reviewerName,
|
||||
@RequestParam(required = false) String auditComment) {
|
||||
return CommonResult.success(cmsContentService.updateAuditStatus(contentId, auditStatus, reviewerId, reviewerName, auditComment, reviewerName) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新发布状态
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @param publishStatus 发布状态
|
||||
* @param publishTime 发布时间
|
||||
* @param updateBy 更新人
|
||||
* @return 发布结果
|
||||
*/
|
||||
@PostMapping("/updatePublishStatus")
|
||||
@Operation(summary = "更新发布状态", description = "更新发布状态")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> updatePublishStatus(@RequestParam Long contentId,
|
||||
@RequestParam Integer publishStatus,
|
||||
@RequestParam(required = false) String publishTime,
|
||||
@RequestParam String updateBy) {
|
||||
return CommonResult.success(cmsContentService.updatePublishStatus(contentId, publishStatus, publishTime, updateBy) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加阅读量
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @return 增加结果
|
||||
*/
|
||||
@PostMapping("/increaseViewCount/{contentId}")
|
||||
@Operation(summary = "增加阅读量", description = "增加阅读量")
|
||||
public CommonResult<Boolean> increaseViewCount(@PathVariable("contentId") Long contentId) {
|
||||
return CommonResult.success(cmsContentService.increaseViewCount(contentId) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键逻辑删除
|
||||
*
|
||||
* @param idDto 主键
|
||||
* @return 删除数据
|
||||
*/
|
||||
@PostMapping("/logicDeleteById")
|
||||
@Operation(summary = "逻辑删除内容", description = "逻辑删除内容")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> logicDeleteById(@RequestBody IdDto idDto) {
|
||||
return CommonResult.success(cmsContentService.logicDeleteById(idDto.getId(), "admin") > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*
|
||||
* @param contentId 主键
|
||||
* @return 删除数据
|
||||
*/
|
||||
@PostMapping("deleteById/{contentId}")
|
||||
@Operation(summary = "物理删除内容", description = "物理删除内容")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> deleteById(@PathVariable("contentId") Long contentId) {
|
||||
return CommonResult.success(cmsContentService.deleteById(contentId) > 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.kexue.skills.annotation.RequireAuth;
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.CmsTag;
|
||||
import com.kexue.skills.entity.base.IdDto;
|
||||
import com.kexue.skills.entity.dto.CmsTagDto;
|
||||
import com.kexue.skills.service.CmsTagService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* (CmsTag)表控制层
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("api/cmsTag")
|
||||
@Tag(name = "标签管理 Api")
|
||||
@CrossOrigin(origins = "*")
|
||||
public class CmsTagController {
|
||||
/**
|
||||
* 服务对象
|
||||
*/
|
||||
@Resource
|
||||
private CmsTagService cmsTagService;
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param queryDto 筛选条件
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getPageList")
|
||||
@Operation(summary = "查询分页列表", description = "查询分页列表")
|
||||
public CommonResult<PageInfo<CmsTag>> getPageList(@RequestBody CmsTagDto queryDto) {
|
||||
return CommonResult.success(cmsTagService.getPageList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*
|
||||
* @param queryDto 筛选条件
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getList")
|
||||
@Operation(summary = "查询列表", description = "查询列表")
|
||||
public CommonResult<PageInfo<CmsTag>> getList(@RequestBody CmsTagDto queryDto) {
|
||||
return CommonResult.success(new PageInfo<>(cmsTagService.getList(queryDto)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键查询单条数据
|
||||
*
|
||||
* @param tagId 主键
|
||||
* @return 单条数据
|
||||
*/
|
||||
@PostMapping("queryById/{tagId}")
|
||||
@Operation(summary = "通过ID查询标签", description = "通过ID查询标签")
|
||||
public CommonResult<CmsTag> queryById(@PathVariable("tagId") Long tagId) {
|
||||
return CommonResult.success(cmsTagService.queryById(tagId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增数据
|
||||
*
|
||||
* @param cmsTag 实体
|
||||
* @return 新增结果
|
||||
*/
|
||||
@PostMapping("/insert")
|
||||
@Operation(summary = "新增标签", description = "新增标签")
|
||||
@RequireAuth
|
||||
public CommonResult<CmsTag> insert(@RequestBody CmsTag cmsTag) {
|
||||
return CommonResult.success(cmsTagService.insert(cmsTag));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑数据
|
||||
*
|
||||
* @param cmsTag 实体
|
||||
* @return 编辑结果
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
@Operation(summary = "更新标签", description = "更新标签")
|
||||
@RequireAuth
|
||||
public CommonResult<CmsTag> update(@RequestBody CmsTag cmsTag) {
|
||||
return CommonResult.success(cmsTagService.update(cmsTag));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键逻辑删除
|
||||
*
|
||||
* @param idDto 主键
|
||||
* @return 删除数据
|
||||
*/
|
||||
@PostMapping("/logicDeleteById")
|
||||
@Operation(summary = "逻辑删除标签", description = "逻辑删除标签")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> logicDeleteById(@RequestBody IdDto idDto) {
|
||||
return CommonResult.success(cmsTagService.logicDeleteById(idDto.getId(), "admin") > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*
|
||||
* @param tagId 主键
|
||||
* @return 删除数据
|
||||
*/
|
||||
@PostMapping("deleteById/{tagId}")
|
||||
@Operation(summary = "物理删除标签", description = "物理删除标签")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> deleteById(@PathVariable("tagId") Long tagId) {
|
||||
return CommonResult.success(cmsTagService.deleteById(tagId) > 0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.request.UploadResponse;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
/**
|
||||
* @author 维哥
|
||||
* @Description
|
||||
* @create 2025-02-27 10:55
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("api/common")
|
||||
@Tag(name = "公共 Api")
|
||||
@CrossOrigin(origins = "*")
|
||||
@Slf4j
|
||||
public class CommonController {
|
||||
|
||||
private static final String FILE_UPLOAD_DIR = "/data/service/hyxp-portal/upload/file/";
|
||||
private static final String IMG_UPLOAD_DIR = "/data/service/hyxp-portal/upload/images/";
|
||||
|
||||
|
||||
/**
|
||||
* 文件上传接口
|
||||
* URL: http://localhost:8080/common/uploadFile
|
||||
* Method: POST
|
||||
* Body: form-data
|
||||
* Key: file
|
||||
* Value: 选择一个文件进行上传
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/uploadFile")
|
||||
@Operation(summary = "文件上传", description = "文件上传接口")
|
||||
public CommonResult<UploadResponse> uploadFile(@RequestParam("file") MultipartFile file) {
|
||||
if (file.isEmpty()) {
|
||||
return CommonResult.failed("文件为空,请选择文件后再上传");
|
||||
}
|
||||
|
||||
try {
|
||||
// 创建上传目录(如果不存在)
|
||||
Path uploadPath = Paths.get(FILE_UPLOAD_DIR);
|
||||
if (!Files.exists(uploadPath)) {
|
||||
Files.createDirectories(uploadPath);
|
||||
}
|
||||
|
||||
// 构建文件保存路径
|
||||
Path filePath = uploadPath.resolve(file.getOriginalFilename());
|
||||
|
||||
// 保存文件
|
||||
Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
UploadResponse uploadResponse = new UploadResponse();
|
||||
uploadResponse.setFileName(file.getOriginalFilename());
|
||||
uploadResponse.setFileUrl("/upload/file/" + file.getOriginalFilename());
|
||||
return CommonResult.success(uploadResponse);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return CommonResult.failed("文件上传失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片上传接口
|
||||
* URL: http://localhost:8080/common/uploadImage
|
||||
* Method: POST
|
||||
* Body: form-data
|
||||
* Key: file
|
||||
* Value: 选择一个图片文件进行上传
|
||||
* @param image
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/uploadImage")
|
||||
@Operation(summary = "图片上传", description = "图片上传接口")
|
||||
public CommonResult<UploadResponse> uploadImage(@RequestParam("image") MultipartFile image) {
|
||||
if (image.isEmpty()) {
|
||||
return CommonResult.failed("图片为空,请选择图片后再上传");
|
||||
}
|
||||
|
||||
// 检查文件是否为图片
|
||||
if (!image.getContentType().startsWith("image")) {
|
||||
return CommonResult.failed("上传的文件不是图片");
|
||||
}
|
||||
|
||||
try {
|
||||
// 创建上传目录(如果不存在)
|
||||
Path uploadPath = Paths.get(IMG_UPLOAD_DIR);
|
||||
if (!Files.exists(uploadPath)) {
|
||||
Files.createDirectories(uploadPath);
|
||||
}
|
||||
|
||||
// 构建文件保存路径
|
||||
Path filePath = uploadPath.resolve(image.getOriginalFilename());
|
||||
|
||||
// 保存文件
|
||||
Files.copy(image.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
UploadResponse uploadResponse = new UploadResponse();
|
||||
uploadResponse.setFileName(image.getOriginalFilename());
|
||||
uploadResponse.setFileUrl("/upload/images/" + image.getOriginalFilename());
|
||||
return CommonResult.success(uploadResponse);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return CommonResult.failed("图片上传失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 在 CommonController.java 中新增接口
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.kexue.skills.annotation.RequireAuth;
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.ContentPurchase;
|
||||
import com.kexue.skills.entity.dto.ContentPurchaseDto;
|
||||
import com.kexue.skills.service.ContentPurchaseService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* (ContentPurchase)表控制层
|
||||
* 内容购买控制器
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Tag(name = "内容购买管理 Api")
|
||||
@RestController
|
||||
@RequestMapping("/api/contentPurchase")
|
||||
public class ContentPurchaseController {
|
||||
/**
|
||||
* 服务对象
|
||||
*/
|
||||
@Resource
|
||||
private ContentPurchaseService contentPurchaseService;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param queryDto 查询参数
|
||||
* @return 分页结果
|
||||
*/
|
||||
@Operation(summary = "分页查询内容购买记录", description = "分页查询内容购买记录")
|
||||
@PostMapping("/pageList")
|
||||
@RequireAuth
|
||||
public CommonResult<PageInfo<ContentPurchase>> getPageList(@RequestBody ContentPurchaseDto queryDto) {
|
||||
return CommonResult.success(this.contentPurchaseService.getPageList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*
|
||||
* @param queryDto 查询参数
|
||||
* @return 列表结果
|
||||
*/
|
||||
@Operation(summary = "查询内容购买记录列表", description = "查询内容购买记录列表")
|
||||
@PostMapping("/list")
|
||||
@RequireAuth
|
||||
public CommonResult<List<ContentPurchase>> getList(@RequestBody ContentPurchaseDto queryDto) {
|
||||
return CommonResult.success(this.contentPurchaseService.getList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键查询单条数据
|
||||
*
|
||||
* @param purchaseId 主键
|
||||
* @return 单条数据
|
||||
*/
|
||||
@Operation(summary = "通过ID查询内容购买记录", description = "通过ID查询内容购买记录")
|
||||
@PostMapping("/queryById/{purchaseId}")
|
||||
@RequireAuth
|
||||
public CommonResult<ContentPurchase> queryById(@Parameter(description = "购买记录ID") @PathVariable("purchaseId") Long purchaseId) {
|
||||
return CommonResult.success(this.contentPurchaseService.queryById(purchaseId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 购买内容
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param contentId 内容ID
|
||||
* @param payType 支付方式:1.余额支付 2.积分支付
|
||||
* @return 购买结果
|
||||
*/
|
||||
@Operation(summary = "购买内容", description = "购买内容")
|
||||
@PostMapping("/purchase")
|
||||
@RequireAuth
|
||||
public CommonResult<ContentPurchase> purchaseContent(
|
||||
@Parameter(description = "用户ID") @RequestParam("userId") Long userId,
|
||||
@Parameter(description = "内容ID") @RequestParam("contentId") Long contentId,
|
||||
@Parameter(description = "支付方式:1.余额支付 2.积分支付") @RequestParam("payType") Integer payType) {
|
||||
return CommonResult.success(this.contentPurchaseService.purchaseContent(userId, contentId, payType));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户是否有权限访问内容
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param contentId 内容ID
|
||||
* @return 是否有权限
|
||||
*/
|
||||
@Operation(summary = "检查内容访问权限", description = "检查内容访问权限")
|
||||
@PostMapping("/checkPermission")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> checkAccessPermission(
|
||||
@Parameter(description = "用户ID") @RequestParam("userId") Long userId,
|
||||
@Parameter(description = "内容ID") @RequestParam("contentId") Long contentId) {
|
||||
boolean hasPermission = this.contentPurchaseService.checkAccessPermission(userId, contentId);
|
||||
return CommonResult.success(hasPermission);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.kexue.skills.annotation.PreventDuplicateSubmission;
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.SysUser;
|
||||
import com.kexue.skills.entity.request.LoginDto;
|
||||
import com.kexue.skills.entity.request.LoginUserDto;
|
||||
import com.kexue.skills.service.SysUserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* (SysUser)表控制层
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2024-04-13 01:25:22
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("api/login")
|
||||
@CrossOrigin(origins = "*")
|
||||
@Tag(name = "登录|登出 Api")
|
||||
public class LoginController {
|
||||
/**
|
||||
* 服务对象
|
||||
*/
|
||||
@Resource
|
||||
private SysUserService sysUserService;
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
*
|
||||
* @param loginDto 登录信息
|
||||
* @return 登录结果
|
||||
*/
|
||||
@PostMapping("/do")
|
||||
@Operation(summary = "用户登录", description = "用户登录")
|
||||
@PreventDuplicateSubmission
|
||||
public CommonResult<LoginUserDto> login(@RequestBody LoginDto loginDto) {
|
||||
return CommonResult.success(sysUserService.login(loginDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户登出
|
||||
*
|
||||
* @return 登出结果
|
||||
*/
|
||||
@PostMapping("/logout")
|
||||
@Operation(summary = "用户登出", description = "用户登出")
|
||||
public CommonResult<String> logout() {
|
||||
// 使用Sa-Token登出
|
||||
cn.dev33.satoken.stp.StpUtil.logout();
|
||||
return CommonResult.success("登出成功");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
//package com.kexue.skills.controller;
|
||||
//
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.stereotype.Controller;
|
||||
//import org.springframework.ui.Model;
|
||||
//import org.springframework.web.bind.annotation.GetMapping;
|
||||
//
|
||||
//import javax.annotation.Resource;
|
||||
//import jakarta.servlet.http.HttpServletRequest;
|
||||
//
|
||||
///**
|
||||
// * 所有页面controller再这里声明
|
||||
// */
|
||||
//@Controller
|
||||
//@Slf4j
|
||||
//public class PageController {
|
||||
//
|
||||
// @Resource
|
||||
//// private BizCardService bizCardService;
|
||||
//
|
||||
//// @GetMapping("")
|
||||
//// public String goHome(HttpServletRequest request, Model model) {
|
||||
//// model.addAttribute("baseUrl",getServerInfo(request));
|
||||
//// try {
|
||||
//// BizCardDto bizCardDto = bizCardService.queryById(1L);
|
||||
//// if (bizCardDto != null && bizCardDto.getBizCardProducts() != null) {
|
||||
//// model.addAttribute("bizCardProducts",bizCardDto.getBizCardProducts());
|
||||
//// } else {
|
||||
//// model.addAttribute("bizCardProducts",Collections.emptyList());
|
||||
//// }
|
||||
//// } catch (Exception e) {
|
||||
//// log.error("Error fetching bizCardDto: ", e);
|
||||
//// model.addAttribute("",Collections.emptyList());
|
||||
//// }
|
||||
//// return "index";
|
||||
//// }
|
||||
///*
|
||||
//
|
||||
// @GetMapping("/portal")
|
||||
// public String portal(HttpServletRequest request, Model model) {
|
||||
// model.addAttribute("baseUrl",getServerInfo(request));
|
||||
// try {
|
||||
// BizCardDto bizCardDto = bizCardService.queryById(1);
|
||||
// if (bizCardDto != null && bizCardDto.getBizCardProducts() != null) {
|
||||
// model.addAttribute("bizCardProducts",bizCardDto.getBizCardProducts());
|
||||
// } else {
|
||||
// model.addAttribute("bizCardProducts",Collections.emptyList());
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// log.error("Error fetching bizCardDto: ", e);
|
||||
// model.addAttribute("",Collections.emptyList());
|
||||
// }
|
||||
// return "index";
|
||||
// }
|
||||
//*/
|
||||
//
|
||||
// @GetMapping("/login")
|
||||
// public String login(HttpServletRequest request, Model model) {
|
||||
// model.addAttribute("baseUrl",getServerInfo(request));
|
||||
// return "login";
|
||||
// }
|
||||
//
|
||||
// @GetMapping("/main")
|
||||
// public String main(HttpServletRequest request, Model model) {
|
||||
// model.addAttribute("baseUrl",getServerInfo(request));
|
||||
// return "main";
|
||||
// }
|
||||
//
|
||||
// @GetMapping("/dashboard")
|
||||
// public String dashboard(HttpServletRequest request, Model model) {
|
||||
// model.addAttribute("baseUrl",getServerInfo(request));
|
||||
// return "dashboard";
|
||||
// }
|
||||
//
|
||||
//
|
||||
// @GetMapping("/orderManage")
|
||||
// public String orderManage(HttpServletRequest request, Model model) {
|
||||
// model.addAttribute("baseUrl",getServerInfo(request));
|
||||
// return "dashboard";
|
||||
// }
|
||||
//
|
||||
//
|
||||
// //写一个获取服务器ip、端口、上下文路径的函数
|
||||
// public String getServerInfo(HttpServletRequest request) {
|
||||
// StringBuilder sb = new StringBuilder();
|
||||
// sb.append("http://").append(request.getServerName())
|
||||
// .append(":").append(request.getServerPort())
|
||||
// .append(request.getContextPath());
|
||||
// return sb.toString();
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.kexue.skills.annotation.RequireAuth;
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.PaymentOrder;
|
||||
import com.kexue.skills.entity.dto.PaymentOrderDto;
|
||||
import com.kexue.skills.service.PaymentOrderService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* (PaymentOrder)表控制层
|
||||
* 支付订单管理控制器
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Tag(name = "支付订单管理 Api")
|
||||
@RestController
|
||||
@RequestMapping("/api/paymentOrder")
|
||||
public class PaymentOrderController {
|
||||
/**
|
||||
* 服务对象
|
||||
*/
|
||||
@Resource
|
||||
private PaymentOrderService paymentOrderService;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param queryDto 查询参数
|
||||
* @return 分页结果
|
||||
*/
|
||||
@Operation(summary = "分页查询支付订单", description = "分页查询支付订单")
|
||||
@PostMapping("/pageList")
|
||||
@RequireAuth
|
||||
public CommonResult<PageInfo<PaymentOrder>> getPageList(@RequestBody PaymentOrderDto queryDto) {
|
||||
return CommonResult.success(this.paymentOrderService.getPageList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*
|
||||
* @param queryDto 查询参数
|
||||
* @return 列表结果
|
||||
*/
|
||||
@Operation(summary = "查询支付订单列表", description = "查询支付订单列表")
|
||||
@PostMapping("/list")
|
||||
@RequireAuth
|
||||
public CommonResult<List<PaymentOrder>> getList(@RequestBody PaymentOrderDto queryDto) {
|
||||
return CommonResult.success(this.paymentOrderService.getList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键查询单条数据
|
||||
*
|
||||
* @param orderId 主键
|
||||
* @return 单条数据
|
||||
*/
|
||||
@Operation(summary = "通过ID查询支付订单", description = "通过ID查询支付订单")
|
||||
@PostMapping("/queryById/{orderId}")
|
||||
@RequireAuth
|
||||
public CommonResult<PaymentOrder> queryById(@Parameter(description = "订单ID") @PathVariable("orderId") Long orderId) {
|
||||
return CommonResult.success(this.paymentOrderService.queryById(orderId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过订单号查询单条数据
|
||||
*
|
||||
* @param orderNo 订单号
|
||||
* @return 单条数据
|
||||
*/
|
||||
@Operation(summary = "通过订单号查询支付订单", description = "通过订单号查询支付订单")
|
||||
@PostMapping("/queryByOrderNo")
|
||||
@RequireAuth
|
||||
public CommonResult<PaymentOrder> queryByOrderNo(@Parameter(description = "订单号") @RequestParam("orderNo") String orderNo) {
|
||||
return CommonResult.success(this.paymentOrderService.queryByOrderNo(orderNo));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.kexue.skills.annotation.RequireAuth;
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.PointsAccount;
|
||||
import com.kexue.skills.entity.dto.PointsAccountDto;
|
||||
import com.kexue.skills.service.PointsAccountService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* (PointsAccount)表控制层
|
||||
* 积分账户管理控制器
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Tag(name = "积分账户管理 Api")
|
||||
@RestController
|
||||
@RequestMapping("/api/pointsAccount")
|
||||
public class PointsAccountController {
|
||||
/**
|
||||
* 服务对象
|
||||
*/
|
||||
@Resource
|
||||
private PointsAccountService pointsAccountService;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param queryDto 查询参数
|
||||
* @return 分页结果
|
||||
*/
|
||||
@Operation(summary = "分页查询积分账户", description = "分页查询积分账户")
|
||||
@PostMapping("/pageList")
|
||||
@RequireAuth
|
||||
public CommonResult<PageInfo<PointsAccount>> getPageList(@RequestBody PointsAccountDto queryDto) {
|
||||
return CommonResult.success(this.pointsAccountService.getPageList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*
|
||||
* @param queryDto 查询参数
|
||||
* @return 列表结果
|
||||
*/
|
||||
@Operation(summary = "查询积分账户列表", description = "查询积分账户列表")
|
||||
@PostMapping("/list")
|
||||
@RequireAuth
|
||||
public CommonResult<List<PointsAccount>> getList(@RequestBody PointsAccountDto queryDto) {
|
||||
return CommonResult.success(this.pointsAccountService.getList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键查询单条数据
|
||||
*
|
||||
* @param accountId 主键
|
||||
* @return 单条数据
|
||||
*/
|
||||
@Operation(summary = "通过ID查询积分账户", description = "通过ID查询积分账户")
|
||||
@PostMapping("/queryById/{accountId}")
|
||||
@RequireAuth
|
||||
public CommonResult<PointsAccount> queryById(@Parameter(description = "账户ID") @PathVariable("accountId") Long accountId) {
|
||||
return CommonResult.success(this.pointsAccountService.queryById(accountId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过用户ID查询单条数据
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 单条数据
|
||||
*/
|
||||
@Operation(summary = "通过用户ID查询积分账户", description = "通过用户ID查询积分账户")
|
||||
@PostMapping("/queryByUserId/{userId}")
|
||||
@RequireAuth
|
||||
public CommonResult<PointsAccount> queryByUserId(@Parameter(description = "用户ID") @PathVariable("userId") Long userId) {
|
||||
return CommonResult.success(this.pointsAccountService.queryByUserId(userId));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.kexue.skills.entity.SysDict;
|
||||
import com.kexue.skills.entity.dto.SysDictDto;
|
||||
import com.kexue.skills.service.SysDictService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import javax.annotation.Resource;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.base.IdDto;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 系统字典表(SysDict)表控制层
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("api/sysDict")
|
||||
@Tag(name = "系统字典 Api")
|
||||
@CrossOrigin(origins = "*")
|
||||
public class SysDictController {
|
||||
/**
|
||||
* 服务对象
|
||||
*/
|
||||
@Resource
|
||||
private SysDictService sysDictService;
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param queryDto 筛选条件
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getPageList")
|
||||
@Operation(summary = "查询分页列表", description = "查询分页列表")
|
||||
public CommonResult<PageInfo<SysDict>> getPageList(@RequestBody SysDictDto queryDto) {
|
||||
return CommonResult.success(sysDictService.getPageList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键查询单条数据
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 单条数据
|
||||
*/
|
||||
@PostMapping("queryById/{id}")
|
||||
@Operation(summary = "通过ID查询字典", description = "通过ID查询字典")
|
||||
public CommonResult<SysDict> queryById(@PathVariable("id") Long id) {
|
||||
return CommonResult.success(sysDictService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增数据
|
||||
*
|
||||
* @param SysDict 实体
|
||||
* @return 新增结果
|
||||
*/
|
||||
@PostMapping("/insert")
|
||||
@Operation(summary = "新增字典", description = "新增字典")
|
||||
public CommonResult<SysDict> insert(@RequestBody SysDict SysDict) {
|
||||
return CommonResult.success(sysDictService.insert(SysDict));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑数据
|
||||
*
|
||||
* @param SysDict 实体
|
||||
* @return 编辑结果
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
@Operation(summary = "更新字典", description = "更新字典")
|
||||
public CommonResult<SysDict> update(@RequestBody SysDict SysDict) {
|
||||
return CommonResult.success(sysDictService.update(SysDict));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*
|
||||
* @param id
|
||||
* @return 删除数据
|
||||
*/
|
||||
@PostMapping("deleteById/{id}")
|
||||
@Operation(summary = "删除字典", description = "删除字典")
|
||||
public CommonResult<Boolean> deleteById(@PathVariable("id") Long id) {
|
||||
return CommonResult.success(sysDictService.deleteById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有的dictCode
|
||||
*/
|
||||
@GetMapping("dictCodeList")
|
||||
@Operation(summary = "查询所有字典编码", description = "查询所有字典编码")
|
||||
public CommonResult<List<SysDict>> getAllDictCode() {
|
||||
return CommonResult.success(sysDictService.getAllDictCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有字典映射
|
||||
*
|
||||
*/
|
||||
@GetMapping("allDictMap")
|
||||
@Operation(summary = "查询所有字典映射", description = "查询所有字典映射")
|
||||
public CommonResult<Map<String,List<SysDict>>> getAllDictMap() {
|
||||
return CommonResult.success(sysDictService.getAllDictMap());
|
||||
}
|
||||
|
||||
@GetMapping("{dictCode}")
|
||||
@Operation(summary = "通过字典编码查询字典列表", description = "通过字典编码查询字典列表")
|
||||
public CommonResult<List<SysDict>> getListByDictCode(@PathVariable("dictCode") String dictCode) {
|
||||
return CommonResult.success(sysDictService.getListByDictCode(dictCode));
|
||||
}
|
||||
|
||||
@PostMapping("getDictListByDictCode")
|
||||
@Operation(summary = "通过字典编码查询字典列表", description = "通过字典编码查询字典列表")
|
||||
public CommonResult<List<SysDict>> getDictListByDictCode(@RequestBody SysDict sysDict) {
|
||||
return CommonResult.success(sysDictService.getListByDictCode(sysDict.getDictCode()));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.kexue.skills.entity.SysLog;
|
||||
import com.kexue.skills.entity.dto.SysLogDto;
|
||||
import com.kexue.skills.service.SysLogService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import javax.annotation.Resource;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.base.IdDto;
|
||||
|
||||
/**
|
||||
* (SysLog)表控制层
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("api/sysLog")
|
||||
@Tag(name = "系统日志 Api")
|
||||
@CrossOrigin(origins = "*")
|
||||
public class SysLogController {
|
||||
/**
|
||||
* 服务对象
|
||||
*/
|
||||
@Resource
|
||||
private SysLogService sysLogService;
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param queryDto 筛选条件
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getPageList")
|
||||
@Operation(summary = "查询分页列表", description = "查询分页列表")
|
||||
public CommonResult<PageInfo<SysLog>> getPageList(@RequestBody SysLogDto queryDto) {
|
||||
return CommonResult.success(sysLogService.getPageList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键查询单条数据
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 单条数据
|
||||
*/
|
||||
@PostMapping("queryById/{id}")
|
||||
@Operation(summary = "通过ID查询日志", description = "通过ID查询日志")
|
||||
public CommonResult<SysLog> queryById(@PathVariable("id") Long id) {
|
||||
return CommonResult.success(sysLogService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增数据
|
||||
*
|
||||
* @param SysLog 实体
|
||||
* @return 新增结果
|
||||
*/
|
||||
@PostMapping("/insert")
|
||||
@Operation(summary = "新增日志", description = "新增日志")
|
||||
public CommonResult<SysLog> insert(@RequestBody SysLog SysLog) {
|
||||
return CommonResult.success(sysLogService.insert(SysLog));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑数据
|
||||
*
|
||||
* @param SysLog 实体
|
||||
* @return 编辑结果
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
@Operation(summary = "更新日志", description = "更新日志")
|
||||
public CommonResult<SysLog> update(@RequestBody SysLog SysLog) {
|
||||
return CommonResult.success(sysLogService.update(SysLog));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*
|
||||
* @param id
|
||||
* @return 删除数据
|
||||
*/
|
||||
@PostMapping("deleteById/{id}")
|
||||
@Operation(summary = "删除日志", description = "删除日志")
|
||||
public CommonResult<Boolean> deleteById(@PathVariable("id") Long id) {
|
||||
return CommonResult.success(sysLogService.deleteById(id));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.kexue.skills.entity.SysMenu;
|
||||
import com.kexue.skills.entity.dto.SysMenuDto;
|
||||
import com.kexue.skills.service.SysMenuService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.base.IdDto;
|
||||
|
||||
/**
|
||||
* (SysMenu)表控制层
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("api/sysMenu")
|
||||
@Tag(name = "系统菜单 Api")
|
||||
@CrossOrigin(origins = "*")
|
||||
public class SysMenuController {
|
||||
/**
|
||||
* 服务对象
|
||||
*/
|
||||
@Resource
|
||||
private SysMenuService sysMenuService;
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param queryDto 筛选条件
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getPageList")
|
||||
@Operation(summary = "查询分页列表",description = "查询分页列表")
|
||||
public CommonResult<PageInfo<SysMenu>> getPageList(@RequestBody SysMenuDto queryDto) {
|
||||
return CommonResult.success(sysMenuService.getPageList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键查询单条数据
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 单条数据
|
||||
*/
|
||||
@PostMapping("queryById/{id}")
|
||||
@Operation(summary = "通过ID查询菜单", description = "通过ID查询菜单")
|
||||
public CommonResult<SysMenu> queryById(@PathVariable("id") Long id) {
|
||||
return CommonResult.success(sysMenuService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增数据
|
||||
*
|
||||
* @param SysMenu 实体
|
||||
* @return 新增结果
|
||||
*/
|
||||
@PostMapping("/insert")
|
||||
@Operation(summary = "新增菜单", description = "新增菜单")
|
||||
public CommonResult<SysMenu> insert(@RequestBody SysMenu SysMenu) {
|
||||
return CommonResult.success(sysMenuService.insert(SysMenu));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑数据
|
||||
*
|
||||
* @param SysMenu 实体
|
||||
* @return 编辑结果
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
@Operation(summary = "更新菜单", description = "更新菜单")
|
||||
public CommonResult<SysMenu> update(@RequestBody SysMenu SysMenu) {
|
||||
return CommonResult.success(sysMenuService.update(SysMenu));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*
|
||||
* @param id
|
||||
* @return 删除数据
|
||||
*/
|
||||
@PostMapping("deleteById/{id}")
|
||||
@Operation(summary = "删除菜单", description = "删除菜单")
|
||||
public CommonResult<Boolean> deleteById(@PathVariable("id") Long id) {
|
||||
return CommonResult.success(sysMenuService.deleteById(id));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.kexue.skills.entity.SysRole;
|
||||
import com.kexue.skills.entity.dto.SysRoleDto;
|
||||
import com.kexue.skills.service.SysRoleService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import javax.annotation.Resource;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.base.IdDto;
|
||||
|
||||
/**
|
||||
* (SysRole)表控制层
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("api/sysRole")
|
||||
@Tag(name = "系统角色 Api")
|
||||
@CrossOrigin(origins = "*")
|
||||
public class SysRoleController {
|
||||
/**
|
||||
* 服务对象
|
||||
*/
|
||||
@Resource
|
||||
private SysRoleService sysRoleService;
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param queryDto 筛选条件
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getPageList")
|
||||
@Operation(summary = "查询分页列表", description = "查询分页列表")
|
||||
public CommonResult<PageInfo<SysRole>> getPageList(@RequestBody SysRoleDto queryDto) {
|
||||
return CommonResult.success(sysRoleService.getPageList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键查询单条数据
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 单条数据
|
||||
*/
|
||||
@PostMapping("queryById/{id}")
|
||||
@Operation(summary = "通过ID查询角色", description = "通过ID查询角色")
|
||||
public CommonResult<SysRole> queryById(@PathVariable("id") Long id) {
|
||||
return CommonResult.success(sysRoleService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增数据
|
||||
*
|
||||
* @param SysRole 实体
|
||||
* @return 新增结果
|
||||
*/
|
||||
@PostMapping("/insert")
|
||||
@Operation(summary = "新增角色", description = "新增角色")
|
||||
public CommonResult<SysRole> insert(@RequestBody SysRole SysRole) {
|
||||
return CommonResult.success(sysRoleService.insert(SysRole));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑数据
|
||||
*
|
||||
* @param SysRole 实体
|
||||
* @return 编辑结果
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
@Operation(summary = "更新角色", description = "更新角色")
|
||||
public CommonResult<SysRole> update(@RequestBody SysRole SysRole) {
|
||||
return CommonResult.success(sysRoleService.update(SysRole));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*
|
||||
* @param id
|
||||
* @return 删除数据
|
||||
*/
|
||||
@PostMapping("deleteById/{id}")
|
||||
@Operation(summary = "删除角色", description = "删除角色")
|
||||
public CommonResult<Boolean> deleteById(@PathVariable("id") Long id) {
|
||||
return CommonResult.success(sysRoleService.deleteById(id));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.kexue.skills.annotation.RequireAuth;
|
||||
import com.kexue.skills.entity.SysUser;
|
||||
import com.kexue.skills.entity.dto.SysUserDto;
|
||||
import com.kexue.skills.entity.request.ResetPasswordDto;
|
||||
import com.kexue.skills.entity.request.ResetPwdDto;
|
||||
import com.kexue.skills.exception.BizException;
|
||||
import com.kexue.skills.service.SysUserService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import javax.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import com.kexue.skills.common.CacheManager;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.base.IdDto;
|
||||
|
||||
/**
|
||||
* (SysUser)表控制层
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("api/sysUser")
|
||||
@Tag(name = "用户管理 Api")
|
||||
@CrossOrigin(origins = "*")
|
||||
public class SysUserController {
|
||||
/**
|
||||
* 服务对象
|
||||
*/
|
||||
@Resource
|
||||
private SysUserService sysUserService;
|
||||
|
||||
/**
|
||||
* Redis模板
|
||||
*/
|
||||
@Resource
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param queryDto 筛选条件
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getPageList")
|
||||
@Operation(summary = "查询分页列表", description = "查询分页列表")
|
||||
public CommonResult<PageInfo<SysUser>> getPageList(@RequestBody SysUserDto queryDto) {
|
||||
return CommonResult.success(sysUserService.getPageList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键查询单条数据
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 单条数据
|
||||
*/
|
||||
@PostMapping("queryById/{id}")
|
||||
@Operation(summary = "通过ID查询用户", description = "通过ID查询用户")
|
||||
public CommonResult<SysUser> queryById(@PathVariable("id") Long id) {
|
||||
return CommonResult.success(sysUserService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增数据
|
||||
*
|
||||
* @param SysUser 实体
|
||||
* @return 新增结果
|
||||
*/
|
||||
@PostMapping("/insert")
|
||||
@Operation(summary = "新增用户", description = "新增用户")
|
||||
public CommonResult<SysUser> insert(@RequestBody SysUser SysUser) {
|
||||
return CommonResult.success(sysUserService.insert(SysUser));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑数据
|
||||
*
|
||||
* @param SysUser 实体
|
||||
* @return 编辑结果
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
@Operation(summary = "更新用户", description = "更新用户")
|
||||
public CommonResult<SysUser> update(@RequestBody SysUser SysUser) {
|
||||
return CommonResult.success(sysUserService.update(SysUser));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*
|
||||
* @param id
|
||||
* @return 删除数据
|
||||
*/
|
||||
@PostMapping("deleteById/{id}")
|
||||
@Operation(summary = "通过ID删除用户", description = "通过ID删除用户")
|
||||
public CommonResult<Boolean> deleteById(@PathVariable("id") Long id) {
|
||||
return CommonResult.success(sysUserService.deleteById(id));
|
||||
}
|
||||
|
||||
@PostMapping("deleteByIdDto")
|
||||
@Operation(summary = "通过ID删除用户", description = "通过ID删除用户")
|
||||
public CommonResult<Boolean> deleteByIdDto(@RequestBody IdDto idDto) {
|
||||
return CommonResult.success(sysUserService.deleteById(idDto.getId()));
|
||||
}
|
||||
|
||||
@PostMapping("/resetPassword")
|
||||
@Operation(summary = "管理员帮助用户重置密码", description = "管理员帮助用户重置密码")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> resetPasswordByAdmin(@RequestBody ResetPasswordDto resetPasswordDto, HttpServletRequest request) {
|
||||
// 从请求头中获取token
|
||||
String token = request.getHeader("Authorization");
|
||||
if (token == null || token.isEmpty()) {
|
||||
throw new BizException("请先登录认证后操作");
|
||||
}
|
||||
|
||||
// 从缓存中获取当前登录用户
|
||||
String username = CacheManager.getUsernameFromToken(token);
|
||||
if (username == null) {
|
||||
throw new BizException("无效的token,请重新登录");
|
||||
}
|
||||
|
||||
SysUser adminUser = sysUserService.getByUsername(username);
|
||||
if (adminUser == null) {
|
||||
throw new BizException("管理员不存在");
|
||||
}
|
||||
|
||||
boolean result = sysUserService.resetPasswordByAdmin(resetPasswordDto);
|
||||
return CommonResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置密码(管理员专用,通过用户ID)
|
||||
*
|
||||
* @param resetPwdDto 重置密码请求参数
|
||||
* @param request HTTP请求
|
||||
* @return 重置结果
|
||||
*/
|
||||
@PostMapping("/resetPwd")
|
||||
@Operation(summary = "重置密码(管理员专用,通过用户ID)", description = "重置密码(管理员专用,通过用户ID)")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> resetPwd(@RequestBody ResetPwdDto resetPwdDto, HttpServletRequest request) {
|
||||
// 从请求头中获取token
|
||||
String token = request.getHeader("Authorization");
|
||||
if (token == null || token.isEmpty()) {
|
||||
throw new BizException("请先登录认证后操作");
|
||||
}
|
||||
|
||||
// 从缓存中获取当前登录用户
|
||||
String username = CacheManager.getUsernameFromToken(token);
|
||||
if (username == null) {
|
||||
throw new BizException("无效的token,请重新登录");
|
||||
}
|
||||
|
||||
SysUser adminUser = sysUserService.getByUsername(username);
|
||||
if (adminUser == null) {
|
||||
throw new BizException("管理员不存在");
|
||||
}
|
||||
|
||||
// 调用服务层方法重置密码
|
||||
boolean result = sysUserService.resetPwd(resetPwdDto.getUserId(), resetPwdDto.getNewPassword(), username);
|
||||
return CommonResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录用户信息
|
||||
*
|
||||
* @param request HTTP请求
|
||||
* @return 当前登录用户信息
|
||||
*/
|
||||
@GetMapping("/currentUser")
|
||||
@Operation(summary = "获取当前登录用户信息", description = "获取当前登录用户信息")
|
||||
@RequireAuth
|
||||
public CommonResult<com.kexue.skills.entity.request.LoginUser> currentUser(HttpServletRequest request) {
|
||||
// 从请求头中获取token
|
||||
String token = request.getHeader("Authorization");
|
||||
if (token == null || token.isEmpty()) {
|
||||
throw new BizException("请先登录认证后操作");
|
||||
}
|
||||
|
||||
// 从Redis缓存中获取LoginUser对象
|
||||
String loginUserJson = redisTemplate.opsForValue().get("loginUser:" + token);
|
||||
if (loginUserJson == null || loginUserJson.isEmpty()) {
|
||||
throw new BizException("无效的token,请重新登录");
|
||||
}
|
||||
|
||||
// 解析JSON字符串为LoginUser对象
|
||||
com.kexue.skills.entity.request.LoginUser loginUser = cn.hutool.json.JSONUtil.toBean(loginUserJson, com.kexue.skills.entity.request.LoginUser.class);
|
||||
|
||||
return CommonResult.success(loginUser);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package com.kexue.skills.controller;
|
||||
|
||||
import com.kexue.skills.entity.SysUserRole;
|
||||
import com.kexue.skills.entity.dto.SysUserRoleDto;
|
||||
import com.kexue.skills.service.SysUserRoleService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import javax.annotation.Resource;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.base.IdDto;
|
||||
|
||||
/**
|
||||
* (SysUserRole)表控制层
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("api/sysUserRole")
|
||||
@Tag(name = "用户角色管理 Api")
|
||||
@CrossOrigin(origins = "*")
|
||||
public class SysUserRoleController {
|
||||
/**
|
||||
* 服务对象
|
||||
*/
|
||||
@Resource
|
||||
private SysUserRoleService sysUserRoleService;
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param queryDto 筛选条件
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getPageList")
|
||||
@Operation(summary = "查询分页列表", description = "查询分页列表")
|
||||
public CommonResult<PageInfo<SysUserRole>> getPageList(@RequestBody SysUserRoleDto queryDto) {
|
||||
return CommonResult.success(sysUserRoleService.getPageList(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过主键查询单条数据
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 单条数据
|
||||
*/
|
||||
@PostMapping("queryById/{id}")
|
||||
@Operation(summary = "通过ID查询用户角色关联", description = "通过ID查询用户角色关联")
|
||||
public CommonResult<SysUserRole> queryById(@PathVariable("id") Long id) {
|
||||
return CommonResult.success(sysUserRoleService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增数据
|
||||
*
|
||||
* @param SysUserRole 实体
|
||||
* @return 新增结果
|
||||
*/
|
||||
@PostMapping("/insert")
|
||||
@Operation(summary = "新增用户角色关联", description = "新增用户角色关联")
|
||||
public CommonResult<SysUserRole> insert(@RequestBody SysUserRole SysUserRole) {
|
||||
return CommonResult.success(sysUserRoleService.insert(SysUserRole));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑数据
|
||||
*
|
||||
* @param SysUserRole 实体
|
||||
* @return 编辑结果
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
@Operation(summary = "更新用户角色关联", description = "更新用户角色关联")
|
||||
public CommonResult<SysUserRole> update(@RequestBody SysUserRole SysUserRole) {
|
||||
return CommonResult.success(sysUserRoleService.update(SysUserRole));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*
|
||||
* @param id
|
||||
* @return 删除数据
|
||||
*/
|
||||
@PostMapping("deleteById/{id}")
|
||||
@Operation(summary = "删除用户角色关联", description = "删除用户角色关联")
|
||||
public CommonResult<Boolean> deleteById(@PathVariable("id") Long id) {
|
||||
return CommonResult.success(sysUserRoleService.deleteById(id));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (Account)实体类
|
||||
* 账户表,记录用户的账户信息
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class Account extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long accountId;
|
||||
|
||||
@Schema(description ="用户ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description ="用户名")
|
||||
private String userName;
|
||||
|
||||
@Schema(description ="账户余额")
|
||||
private BigDecimal balance;
|
||||
|
||||
@Schema(description ="冻结金额")
|
||||
private BigDecimal frozenAmount;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (AccountTransaction)实体类
|
||||
* 账户流水表,记录用户的账户交易记录
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class AccountTransaction extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long transactionId;
|
||||
|
||||
@Schema(description ="用户ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description ="用户名")
|
||||
private String userName;
|
||||
|
||||
@Schema(description ="交易类型:1.充值 2.提现 3.购买内容 4.退款 5.其他")
|
||||
private Integer transactionType;
|
||||
|
||||
@Schema(description ="交易金额")
|
||||
private BigDecimal amount;
|
||||
|
||||
@Schema(description ="交易前余额")
|
||||
private BigDecimal beforeBalance;
|
||||
|
||||
@Schema(description ="交易后余额")
|
||||
private BigDecimal afterBalance;
|
||||
|
||||
@Schema(description ="交易状态:1.成功 2.失败 3.处理中")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description ="交易单号")
|
||||
private String transactionNo;
|
||||
|
||||
@Schema(description ="支付方式:1.微信 2.支付宝 3.余额支付")
|
||||
private Integer payType;
|
||||
|
||||
@Schema(description ="关联业务ID")
|
||||
private Long businessId;
|
||||
|
||||
@Schema(description ="业务类型")
|
||||
private String businessType;
|
||||
|
||||
@Schema(description ="交易备注")
|
||||
private String remark;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
@Schema(description ="创建人")
|
||||
private String createBy;
|
||||
|
||||
@Schema(description ="更新人")
|
||||
private String updateBy;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (CmsCategory)实体类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class CmsCategory extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long categoryId;
|
||||
|
||||
@Schema(description ="分类名称")
|
||||
private String categoryName;
|
||||
|
||||
@Schema(description ="父分类ID")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description ="分类层级")
|
||||
private Integer level;
|
||||
|
||||
@Schema(description ="排序")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description ="状态(1启用,2禁用)")
|
||||
private Integer status;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
@Schema(description ="创建人")
|
||||
private String createBy;
|
||||
|
||||
@Schema(description ="更新人")
|
||||
private String updateBy;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
@Schema(description ="子分类列表")
|
||||
private java.util.List<CmsCategory> subCategoryList;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (CmsContent)实体类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class CmsContent extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long contentId;
|
||||
|
||||
@Schema(description ="标题")
|
||||
private String title;
|
||||
|
||||
@Schema(description ="是否是官方:0否,1是")
|
||||
private Boolean isOfficial;
|
||||
|
||||
@Schema(description ="分类ID")
|
||||
private Long categoryId;
|
||||
|
||||
@Schema(description ="图标")
|
||||
private String icon;
|
||||
|
||||
@Schema(description ="背景")
|
||||
private String background;
|
||||
|
||||
@Schema(description ="文件URL")
|
||||
private String fileUrl;
|
||||
|
||||
@Schema(description ="内容摘要")
|
||||
private String summary;
|
||||
|
||||
@Schema(description ="分享数量")
|
||||
private Integer shareCount;
|
||||
|
||||
@Schema(description ="点赞量")
|
||||
private Integer likeCount;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@Schema(description ="付费金额")
|
||||
private BigDecimal price;
|
||||
|
||||
@Schema(description ="内容类型(1文章,2视频,3图片)")
|
||||
private Integer contentType;
|
||||
|
||||
@Schema(description ="父分类ID")
|
||||
private Long parentCategoryId;
|
||||
|
||||
@Schema(description ="内容详情")
|
||||
private String content;
|
||||
|
||||
@Schema(description ="封面图片")
|
||||
private String coverImage;
|
||||
|
||||
@Schema(description ="作者ID")
|
||||
private Long authorId;
|
||||
|
||||
@Schema(description ="作者名称")
|
||||
private String authorName;
|
||||
|
||||
@Schema(description ="审核人ID")
|
||||
private Long reviewerId;
|
||||
|
||||
@Schema(description ="审核人名称")
|
||||
private String reviewerName;
|
||||
|
||||
@Schema(description ="审核状态(1草稿,2待审核,3审核通过,4审核拒绝)")
|
||||
private Integer auditStatus;
|
||||
|
||||
@Schema(description ="审核意见")
|
||||
private String auditComment;
|
||||
|
||||
@Schema(description ="发布状态(1未发布,2已发布,3已下架)")
|
||||
private Integer publishStatus;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="发布时间")
|
||||
private Date publishTime;
|
||||
|
||||
@Schema(description ="阅读量")
|
||||
private Integer viewCount;
|
||||
|
||||
@Schema(description ="评论量")
|
||||
private Integer commentCount;
|
||||
|
||||
@Schema(description ="排序")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description ="所需积分")
|
||||
private Integer requiredPoints;
|
||||
|
||||
@Schema(description ="是否支持积分支付:0不支持,1支持")
|
||||
private Integer supportPointsPay;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
@Schema(description ="创建人")
|
||||
private String createBy;
|
||||
|
||||
@Schema(description ="更新人")
|
||||
private String updateBy;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
@Schema(description ="子分类列表")
|
||||
private java.util.List<CmsCategory> subCategoryList;
|
||||
|
||||
@Schema(description ="是否付费:0免费,1付费")
|
||||
private Integer isPaid;
|
||||
|
||||
@Schema(description ="副标题")
|
||||
private String subtitle;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (CmsTag)实体类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class CmsTag extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long tagId;
|
||||
|
||||
@Schema(description ="标签名称")
|
||||
private String tagName;
|
||||
|
||||
@Schema(description ="标签描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description ="使用次数")
|
||||
private Integer useCount;
|
||||
|
||||
@Schema(description ="状态(1启用,2禁用)")
|
||||
private Integer status;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
@Schema(description ="创建人")
|
||||
private String createBy;
|
||||
|
||||
@Schema(description ="更新人")
|
||||
private String updateBy;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (ContentPurchase)实体类
|
||||
* 内容购买记录表,记录用户购买的内容信息
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class ContentPurchase extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long purchaseId;
|
||||
|
||||
@Schema(description ="用户ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description ="用户名")
|
||||
private String userName;
|
||||
|
||||
@Schema(description ="内容ID")
|
||||
private Long contentId;
|
||||
|
||||
@Schema(description ="内容标题")
|
||||
private String contentTitle;
|
||||
|
||||
@Schema(description ="购买方式:1.余额支付 2.积分支付")
|
||||
private Integer payType;
|
||||
|
||||
@Schema(description ="支付金额")
|
||||
private java.math.BigDecimal amount;
|
||||
|
||||
@Schema(description ="支付积分")
|
||||
private Integer points;
|
||||
|
||||
@Schema(description ="购买状态:1.待支付 2.已支付 3.已取消")
|
||||
private Integer status;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="购买时间")
|
||||
private Date purchaseTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (Customer)实体类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class Customer extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long customerId;
|
||||
|
||||
@Schema(description ="客户名称")
|
||||
private String customerName;
|
||||
|
||||
@Schema(description ="联系人")
|
||||
private String contactPerson;
|
||||
|
||||
@Schema(description ="联系电话")
|
||||
private String contactPhone;
|
||||
|
||||
@Schema(description ="地址")
|
||||
private String address;
|
||||
|
||||
@Schema(description ="备注")
|
||||
private String remark;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
@Schema(description ="是否启用(1启用,2禁用)")
|
||||
private Integer enable;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (PaymentOrder)实体类
|
||||
* 支付订单表,记录用户的支付请求和支付结果
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class PaymentOrder extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long orderId;
|
||||
|
||||
@Schema(description ="订单号")
|
||||
private String orderNo;
|
||||
|
||||
@Schema(description ="用户ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description ="用户名")
|
||||
private String userName;
|
||||
|
||||
@Schema(description ="支付金额")
|
||||
private BigDecimal amount;
|
||||
|
||||
@Schema(description ="支付方式:1.微信 2.支付宝")
|
||||
private Integer payType;
|
||||
|
||||
@Schema(description ="支付状态:1.待支付 2.已支付 3.支付失败 4.已取消 5.已退款")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description ="支付渠道订单号")
|
||||
private String channelOrderNo;
|
||||
|
||||
@Schema(description ="商品名称")
|
||||
private String productName;
|
||||
|
||||
@Schema(description ="商品描述")
|
||||
private String productDesc;
|
||||
|
||||
@Schema(description ="关联业务ID")
|
||||
private Long businessId;
|
||||
|
||||
@Schema(description ="业务类型")
|
||||
private String businessType;
|
||||
|
||||
@Schema(description ="支付回调地址")
|
||||
private String notifyUrl;
|
||||
|
||||
@Schema(description ="支付成功跳转地址")
|
||||
private String returnUrl;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="过期时间")
|
||||
private Date expireTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="支付时间")
|
||||
private Date payTime;
|
||||
|
||||
@Schema(description ="支付备注")
|
||||
private String remark;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (PointsAccount)实体类
|
||||
* 积分账户表,记录用户的积分信息
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class PointsAccount extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long accountId;
|
||||
|
||||
@Schema(description ="用户ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description ="用户名")
|
||||
private String userName;
|
||||
|
||||
@Schema(description ="总积分")
|
||||
private Integer totalPoints;
|
||||
|
||||
@Schema(description ="可用积分")
|
||||
private Integer availablePoints;
|
||||
|
||||
@Schema(description ="冻结积分")
|
||||
private Integer frozenPoints;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (PointsTransaction)实体类
|
||||
* 积分流水表,记录用户的积分变动情况
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class PointsTransaction extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long transactionId;
|
||||
|
||||
@Schema(description ="用户ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description ="用户名")
|
||||
private String userName;
|
||||
|
||||
@Schema(description ="积分变动类型:1.获取积分 2.消费积分 3.过期 4.其他")
|
||||
private Integer transactionType;
|
||||
|
||||
@Schema(description ="变动积分")
|
||||
private Integer points;
|
||||
|
||||
@Schema(description ="变动前积分")
|
||||
private Integer beforePoints;
|
||||
|
||||
@Schema(description ="变动后积分")
|
||||
private Integer afterPoints;
|
||||
|
||||
@Schema(description ="交易状态:1.成功 2.失败 3.处理中")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description ="交易单号")
|
||||
private String transactionNo;
|
||||
|
||||
@Schema(description ="支付方式:1.微信 2.支付宝 3.余额支付")
|
||||
private Integer payType;
|
||||
|
||||
@Schema(description ="关联业务ID")
|
||||
private Long businessId;
|
||||
|
||||
@Schema(description ="业务类型")
|
||||
private String businessType;
|
||||
|
||||
@Schema(description ="备注")
|
||||
private String remark;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
@Schema(description ="创建人")
|
||||
private String createBy;
|
||||
|
||||
@Schema(description ="更新人")
|
||||
private String updateBy;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (Supplier)实体类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class Supplier extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long supplierId;
|
||||
|
||||
@Schema(description ="供货商名称")
|
||||
private String supplierName;
|
||||
|
||||
@Schema(description ="联系人")
|
||||
private String contactPerson;
|
||||
|
||||
@Schema(description ="联系电话")
|
||||
private String contactPhone;
|
||||
|
||||
@Schema(description ="地址")
|
||||
private String address;
|
||||
|
||||
@Schema(description ="备注")
|
||||
private String remark;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
@Schema(description ="是否启用(1启用,2禁用)")
|
||||
private Integer enable;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 系统字典表(SysDict)实体类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:47
|
||||
*/
|
||||
@Data
|
||||
public class SysDict extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = 754185131264184698L;
|
||||
|
||||
@Schema(description ="字典表ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description ="字典编码")
|
||||
private String dictCode;
|
||||
|
||||
@Schema(description ="字典名称")
|
||||
private String dictName;
|
||||
|
||||
@Schema(description ="字典值中文文本")
|
||||
private String dictCn;
|
||||
|
||||
@Schema(description ="字典值英文文本")
|
||||
private String dictEn;
|
||||
|
||||
@Schema(description ="字典值")
|
||||
private Object dictValue;
|
||||
|
||||
@Schema(description ="字典排序")
|
||||
private Object sorts;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (SysLog)实体类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class SysLog extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = -84681351128482970L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long logId;
|
||||
|
||||
@Schema(description ="用户ID")
|
||||
private String userId;
|
||||
|
||||
@Schema(description ="用户名称")
|
||||
private String userName;
|
||||
|
||||
@Schema(description ="日志类型")
|
||||
private String logType;
|
||||
|
||||
@Schema(description ="日志类容")
|
||||
private String logContent;
|
||||
|
||||
@Schema(description ="服务端IP")
|
||||
private String serverIp;
|
||||
|
||||
@Schema(description ="客户端IP")
|
||||
private String clientIp;
|
||||
|
||||
@Schema(description ="yyyyMMddHHmmss")
|
||||
private String logTime;
|
||||
|
||||
@Schema(description ="备注")
|
||||
private String note;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (SysMenu)实体类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class SysMenu extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = -34455248020533426L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long menuId;
|
||||
|
||||
@Schema(description ="为空时表示是子系统")
|
||||
private Long menuPid;
|
||||
|
||||
@Schema(description ="菜单名称")
|
||||
private String menuName;
|
||||
|
||||
@Schema(description ="菜单链接地址")
|
||||
private String menuSrc;
|
||||
|
||||
@Schema(description ="菜单图标")
|
||||
private String menuIcon;
|
||||
|
||||
@Schema(description ="菜单样式")
|
||||
private String menuStyle;
|
||||
|
||||
@Schema(description ="值越小越排在前面")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description ="备注")
|
||||
private String note;
|
||||
|
||||
@Schema(description ="删除标记")
|
||||
private Object deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (SysRole)实体类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class SysRole extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = 343002535091443381L;
|
||||
|
||||
@Schema(description ="角色ID")
|
||||
private Long roleId;
|
||||
|
||||
@Schema(description ="角色编码")
|
||||
private String roleCode;
|
||||
|
||||
@Schema(description ="角色名称")
|
||||
private String roleName;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@Schema(description ="备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description ="删除标记")
|
||||
private String deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (SysUser)实体类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class SysUser extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = -40877019678009880L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description ="用户登录名称")
|
||||
private String userName;
|
||||
|
||||
@Schema(description ="密码(非明文)")
|
||||
private String pwd;
|
||||
|
||||
@Schema(description ="真实姓名")
|
||||
private String realName;
|
||||
|
||||
@Schema(description ="手机")
|
||||
private String tel;
|
||||
|
||||
@Schema(description ="邮箱")
|
||||
private String email;
|
||||
|
||||
@Schema(description ="加点盐(登录时候要用到的随机数)")
|
||||
private String salt;
|
||||
|
||||
@Schema(description ="备注")
|
||||
private String remark;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@Schema(description ="是否启用(1启用,2禁用)")
|
||||
private Integer enable;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.kexue.skills.entity;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (SysUserRole)实体类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class SysUserRole extends BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = -52125282568963778L;
|
||||
|
||||
@Schema(description ="角色ID")
|
||||
private Long roleId;
|
||||
|
||||
@Schema(description ="用户ID")
|
||||
private Long userId;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.kexue.skills.entity.base;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class BaseEntity implements Serializable {
|
||||
private static HashMap map = new HashMap<>();
|
||||
|
||||
public void put(String key,Object value){
|
||||
map.put(key,value);
|
||||
}
|
||||
|
||||
private Object get(String key){
|
||||
return map.get(key);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.kexue.skills.entity.base;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@ApiModel
|
||||
public class BaseQueryDto implements Serializable {
|
||||
|
||||
public static final Integer DEFAULT_PAGE_SIZE = 10;
|
||||
public static final Integer DEFAULT_CURRENT_PAGE = 1;
|
||||
|
||||
@Schema(description ="当前页")
|
||||
private Integer pageNum;
|
||||
|
||||
@Schema(description ="每页数量")
|
||||
private Integer pageSize;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.kexue.skills.entity.base;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author 维哥
|
||||
* @Description
|
||||
* @create 2025-02-21 18:47
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "ID对象")
|
||||
public class IdDto {
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long id;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (Account)查询DTO类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class AccountDto extends BaseQueryDto {
|
||||
|
||||
private Long accountId;
|
||||
|
||||
private Long userId;
|
||||
|
||||
private String userName;
|
||||
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (AccountTransaction)查询DTO类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class AccountTransactionDto extends BaseQueryDto {
|
||||
|
||||
private Long transactionId;
|
||||
|
||||
private Long userId;
|
||||
|
||||
private String userName;
|
||||
|
||||
private Integer transactionType;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private String transactionNo;
|
||||
|
||||
private Integer payType;
|
||||
|
||||
private Long businessId;
|
||||
|
||||
private String businessType;
|
||||
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (CmsCategory)查询DTO类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class CmsCategoryDto extends BaseQueryDto {
|
||||
|
||||
private Long categoryId;
|
||||
|
||||
private String categoryName;
|
||||
|
||||
private Long parentId;
|
||||
|
||||
private Integer level;
|
||||
|
||||
private Integer sort;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (CmsContent)查询DTO类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class CmsContentDto extends BaseQueryDto {
|
||||
|
||||
private Long contentId;
|
||||
|
||||
private String title;
|
||||
|
||||
private Integer contentType;
|
||||
|
||||
private Long categoryId;
|
||||
|
||||
private Long parentCategoryId;
|
||||
|
||||
private Boolean isOfficial;
|
||||
|
||||
private Integer shareCount;
|
||||
|
||||
private Long authorId;
|
||||
|
||||
private String authorName;
|
||||
|
||||
private Integer auditStatus;
|
||||
|
||||
private Integer publishStatus;
|
||||
|
||||
private String createBy;
|
||||
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (CmsTag)查询DTO类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class CmsTagDto extends BaseQueryDto {
|
||||
|
||||
private Long tagId;
|
||||
|
||||
private String tagName;
|
||||
|
||||
private String description;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* (ContentPurchase)查询条件封装类
|
||||
* 内容购买记录查询条件
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class ContentPurchaseDto extends BaseQueryDto {
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long purchaseId;
|
||||
|
||||
@Schema(description ="用户ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description ="用户名")
|
||||
private String userName;
|
||||
|
||||
@Schema(description ="内容ID")
|
||||
private Long contentId;
|
||||
|
||||
@Schema(description ="内容标题")
|
||||
private String contentTitle;
|
||||
|
||||
@Schema(description ="购买方式:1.余额支付 2.积分支付")
|
||||
private Integer payType;
|
||||
|
||||
@Schema(description ="支付金额")
|
||||
private BigDecimal amount;
|
||||
|
||||
@Schema(description ="支付积分")
|
||||
private Integer points;
|
||||
|
||||
@Schema(description ="购买状态:1.待支付 2.已支付 3.已取消")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description ="购买时间开始")
|
||||
private Date purchaseTimeStart;
|
||||
|
||||
@Schema(description ="购买时间结束")
|
||||
private Date purchaseTimeEnd;
|
||||
|
||||
@Schema(description ="创建时间开始")
|
||||
private Date createTimeStart;
|
||||
|
||||
@Schema(description ="创建时间结束")
|
||||
private Date createTimeEnd;
|
||||
|
||||
@Schema(description ="更新时间开始")
|
||||
private Date updateTimeStart;
|
||||
|
||||
@Schema(description ="更新时间结束")
|
||||
private Date updateTimeEnd;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (Customer)查询DTO类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class CustomerDto extends BaseQueryDto {
|
||||
|
||||
private Long customerId;
|
||||
|
||||
private String customerName;
|
||||
|
||||
private String contactPerson;
|
||||
|
||||
private String contactPhone;
|
||||
|
||||
private String address;
|
||||
|
||||
private Integer enable;
|
||||
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (PaymentOrder)查询DTO类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class PaymentOrderDto extends BaseQueryDto {
|
||||
|
||||
private Long orderId;
|
||||
|
||||
private String orderNo;
|
||||
|
||||
private Long userId;
|
||||
|
||||
private String userName;
|
||||
|
||||
private Integer payType;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private Long businessId;
|
||||
|
||||
private String businessType;
|
||||
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* (PointsAccount)查询条件封装类
|
||||
* 积分账户查询条件
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class PointsAccountDto extends BaseQueryDto {
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long accountId;
|
||||
|
||||
@Schema(description ="用户ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description ="用户名")
|
||||
private String userName;
|
||||
|
||||
@Schema(description ="总积分")
|
||||
private Integer totalPoints;
|
||||
|
||||
@Schema(description ="可用积分")
|
||||
private Integer availablePoints;
|
||||
|
||||
@Schema(description ="冻结积分")
|
||||
private Integer frozenPoints;
|
||||
|
||||
@Schema(description ="创建时间开始")
|
||||
private Date createTimeStart;
|
||||
|
||||
@Schema(description ="创建时间结束")
|
||||
private Date createTimeEnd;
|
||||
|
||||
@Schema(description ="更新时间开始")
|
||||
private Date updateTimeStart;
|
||||
|
||||
@Schema(description ="更新时间结束")
|
||||
private Date updateTimeEnd;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* (PointsTransaction)查询条件封装类
|
||||
* 积分交易记录查询条件
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class PointsTransactionDto extends BaseQueryDto {
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long transactionId;
|
||||
|
||||
@Schema(description ="用户ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description ="用户名")
|
||||
private String userName;
|
||||
|
||||
@Schema(description ="交易类型:1.获得积分 2.使用积分")
|
||||
private Integer transactionType;
|
||||
|
||||
@Schema(description ="积分数量")
|
||||
private Integer points;
|
||||
|
||||
@Schema(description ="交易前积分")
|
||||
private Integer beforePoints;
|
||||
|
||||
@Schema(description ="交易后积分")
|
||||
private Integer afterPoints;
|
||||
|
||||
@Schema(description ="状态:1.成功 2.失败")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description ="交易单号")
|
||||
private String transactionNo;
|
||||
|
||||
@Schema(description ="支付方式:1.微信 2.支付宝 3.余额支付")
|
||||
private Integer payType;
|
||||
|
||||
@Schema(description ="业务ID")
|
||||
private Long businessId;
|
||||
|
||||
@Schema(description ="业务类型")
|
||||
private String businessType;
|
||||
|
||||
@Schema(description ="备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description ="创建时间开始")
|
||||
private Date createTimeStart;
|
||||
|
||||
@Schema(description ="创建时间结束")
|
||||
private Date createTimeEnd;
|
||||
|
||||
@Schema(description ="更新时间开始")
|
||||
private Date updateTimeStart;
|
||||
|
||||
@Schema(description ="更新时间结束")
|
||||
private Date updateTimeEnd;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* (Supplier)查询DTO类
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
public class SupplierDto extends BaseQueryDto {
|
||||
|
||||
private Long supplierId;
|
||||
|
||||
private String supplierName;
|
||||
|
||||
private String contactPerson;
|
||||
|
||||
private String contactPhone;
|
||||
|
||||
private String address;
|
||||
|
||||
private Integer enable;
|
||||
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
|
||||
/**
|
||||
* 系统字典表(SysDict)实体类Dto
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:47
|
||||
*/
|
||||
@Data
|
||||
@ApiModel
|
||||
public class SysDictDto extends BaseQueryDto implements Serializable {
|
||||
private static final long serialVersionUID = 890696045006377935L;
|
||||
|
||||
@Schema(description ="字典表ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description ="字典编码")
|
||||
private String dictCode;
|
||||
|
||||
@Schema(description ="字典名称")
|
||||
private String dictName;
|
||||
|
||||
@Schema(description ="字典值中文文本")
|
||||
private String dictCn;
|
||||
|
||||
@Schema(description ="字典值英文文本")
|
||||
private String dictEn;
|
||||
|
||||
@Schema(description ="字典值")
|
||||
private Object dictValue;
|
||||
|
||||
@Schema(description ="字典排序")
|
||||
private Object sorts;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
|
||||
/**
|
||||
* (SysLog)实体类Dto
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
@ApiModel
|
||||
public class SysLogDto extends BaseQueryDto implements Serializable {
|
||||
private static final long serialVersionUID = 439036642073575183L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long logId;
|
||||
|
||||
@Schema(description ="用户ID")
|
||||
private String userId;
|
||||
|
||||
@Schema(description ="用户名称")
|
||||
private String userName;
|
||||
|
||||
@Schema(description ="日志类型")
|
||||
private String logType;
|
||||
|
||||
@Schema(description ="日志类容")
|
||||
private String logContent;
|
||||
|
||||
@Schema(description ="服务端IP")
|
||||
private String serverIp;
|
||||
|
||||
@Schema(description ="客户端IP")
|
||||
private String clientIp;
|
||||
|
||||
@Schema(description ="yyyyMMddHHmmss")
|
||||
private String logTime;
|
||||
|
||||
@Schema(description ="备注")
|
||||
private String note;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
|
||||
/**
|
||||
* (SysMenu)实体类Dto
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
@ApiModel
|
||||
public class SysMenuDto extends BaseQueryDto implements Serializable {
|
||||
private static final long serialVersionUID = 745631748723623384L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long menuId;
|
||||
|
||||
@Schema(description ="为空时表示是子系统")
|
||||
private Long menuPid;
|
||||
|
||||
@Schema(description ="菜单名称")
|
||||
private String menuName;
|
||||
|
||||
@Schema(description ="菜单链接地址")
|
||||
private String menuSrc;
|
||||
|
||||
@Schema(description ="菜单图标")
|
||||
private String menuIcon;
|
||||
|
||||
@Schema(description ="菜单样式")
|
||||
private String menuStyle;
|
||||
|
||||
@Schema(description ="值越小越排在前面")
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description ="备注")
|
||||
private String note;
|
||||
|
||||
@Schema(description ="删除标记")
|
||||
private Object deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
|
||||
/**
|
||||
* (SysRole)实体类Dto
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
@ApiModel
|
||||
public class SysRoleDto extends BaseQueryDto implements Serializable {
|
||||
private static final long serialVersionUID = -85366036881107510L;
|
||||
|
||||
@Schema(description ="角色ID")
|
||||
private Long roleId;
|
||||
|
||||
@Schema(description ="角色编码")
|
||||
private String roleCode;
|
||||
|
||||
@Schema(description ="角色名称")
|
||||
private String roleName;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@Schema(description ="备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description ="删除标记")
|
||||
private String deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
|
||||
/**
|
||||
* (SysUser)实体类Dto
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
@ApiModel
|
||||
public class SysUserDto extends BaseQueryDto implements Serializable {
|
||||
private static final long serialVersionUID = -60817463837641372L;
|
||||
|
||||
@Schema(description ="主键ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description ="用户登录名称")
|
||||
private String userName;
|
||||
|
||||
@Schema(description ="密码(非明文)")
|
||||
private String pwd;
|
||||
|
||||
@Schema(description ="真实姓名")
|
||||
private String realName;
|
||||
|
||||
@Schema(description ="手机")
|
||||
private String tel;
|
||||
|
||||
@Schema(description ="邮箱")
|
||||
private String email;
|
||||
|
||||
@Schema(description ="加点盐(登录时候要用到的随机数)")
|
||||
private String salt;
|
||||
|
||||
@Schema(description ="备注")
|
||||
private String remark;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@Schema(description ="是否启用(1启用,2禁用)")
|
||||
private Integer enable;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.kexue.skills.entity.dto;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
|
||||
/**
|
||||
* (SysUserRole)实体类Dto
|
||||
*
|
||||
* @author 王志维
|
||||
* @since 2025-02-21 23:01:48
|
||||
*/
|
||||
@Data
|
||||
@ApiModel
|
||||
public class SysUserRoleDto extends BaseQueryDto implements Serializable {
|
||||
private static final long serialVersionUID = -74751357369011844L;
|
||||
|
||||
@Schema(description ="角色ID")
|
||||
private Long roleId;
|
||||
|
||||
@Schema(description ="用户ID")
|
||||
private Long userId;
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue