diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2a24230
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+# Default ignored files
+/target/
+/log/
+/.idea/
+/*.iml
+/.fastRequest/
+/staticServer
+
+fastRequest/
+.fastRequest/
+/file_data/
+/old_webdav/
+/docker/
+
+
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..d154a15
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,4 @@
+FROM harbor.svnlan.com/library/office6_jdk8_ffmpeg6_libraw_skagent_centos7
+COPY target/disk-0.0.1-SNAPSHOT.jar /app.jar
+COPY src/main/resources/itest/agent.config /agent/config/agent.config
+RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..ddb6349
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc., [http://fsf.org/]
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ {description}
+ Copyright (C) 2017 小柒2012
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ {signature of Ty Coon}, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
\ No newline at end of file
diff --git a/db/ddl.sql b/db/ddl.sql
new file mode 100644
index 0000000..647fd84
--- /dev/null
+++ b/db/ddl.sql
@@ -0,0 +1,301 @@
+-- 2023-04-07
+create table `visit_count_record`
+(
+ id BIGINT UNSIGNED auto_increment comment '主键id',
+ visitCount BIGINT UNSIGNED not null comment '用户访问次数',
+ deviceType TINYINT default null comment '设备类型 1 pc , 2 h5, 3 安卓app, 4 ios-app, 5 小程序, 6 电脑app, 7 其他',
+ visitDay DATE DEFAULT NULL comment '访问的日期',
+ modifyTime BIGINT UNSIGNED not null comment '最后修改时间',
+ createTime BIGINT UNSIGNED not null comment '创建时间',
+ PRIMARY KEY (`id`)
+) ENGINE = InnoDB
+ DEFAULT CHARSET = utf8 COMMENT ='访问次数记录表';
+
+-- 2023-04-11 io_source 添加 文件类型 fileType
+ALTER TABLE io_source
+ ADD COLUMN `type` TINYINT(3) UNSIGNED default null comment '文档类型 1 文档 2 图片 3 音乐 4 视频 5 压缩包 6 其他' AFTER sourceHash;
+
+-- 2023-04-11 根据 fileType 设置文件类型 type
+UPDATE io_source
+SET `type` = (
+ CASE
+ WHEN find_in_set(fileType,
+ 'txt,md,pdf,ofd,doc,docx,xls,xlsx,ppt,pptx,xps,pps,ppsx,ods,odt,odp,docm,dot,dotm,xlsb,xlsm,mht,djvu,wps,dpt,csv,et,ett,pages,numbers,key,dotx,vsd,vsdx,mpp')
+ THEN 1
+ WHEN find_in_set(fileType, 'jpg,jpeg,png,gif,bmp,ico,svg,webp,tif,tiff,cdr,svgz,xbm,eps,pjepg,heic,raw,psd,ai')
+ THEN 2
+ WHEN find_in_set(fileType, 'mp3,wav,wma,m4a,ogg,omf,amr,aa3,flac,aac,cda,aif,aiff,mid,ra,ape,mpa') THEN 3
+ WHEN find_in_set(fileType,
+ 'mp4,flv,rm,rmvb,avi,mkv,mov,f4v,mpeg,mpg,vob,wmv,ogv,webm,3gp,mts,m2ts,m4v,mpe,3g2,asf,dat,asx,wvx')
+ THEN 4
+ WHEN find_in_set(fileType, 'zip,gz,rar,iso,tar,7z,ar,bz,bz2,xz,arj') THEN 5
+ ELSE 6
+ END
+ )
+WHERE isFolder = 0
+ AND `type` IS NULL;
+
+-- 2023-04-11 设置文件夹 type 类型为 NULL
+UPDATE io_source
+SET `type` = 0
+WHERE isFolder = 1;
+
+-- 2023-04-12
+ALTER TABLE `visit_count_record`
+ ADD COLUMN osName VARCHAR(20) DEFAULT NULL COMMENT '操作系统' AFTER deviceType;
+ALTER TABLE `visit_count_record`
+ ADD COLUMN `type` TINYINT(3) DEFAULT 1 COMMENT '1 客户端访问 2 用户访问 3 操作系统访问 4 各操作系统总访问' AFTER osName;
+
+-- 2023-04-20
+ALTER TABLE `user`
+ ADD COLUMN dingOpenId VARCHAR(64) DEFAULT NULL COMMENT '钉钉 openId' AFTER `status`;
+ALTER TABLE `user`
+ ADD COLUMN wechatOpenId VARCHAR(64) DEFAULT NULL COMMENT '微信 openId' AFTER wechatOpenId;
+ALTER TABLE `user`
+ ADD COLUMN alipayOpenId VARCHAR(64) DEFAULT NULL COMMENT '支付宝 openId' AFTER alipayOpenId;
+
+-- 2023-05-10
+ALTER TABLE `user`
+ ADD COLUMN enWechatOpenId VARCHAR(64) DEFAULT NULL COMMENT '企业微信 openId' AFTER wechatOpenId;
+
+-- 2023-05-16
+drop table if exists notice;
+create table notice
+(
+ id BIGINT UNSIGNED auto_increment comment '通知id' primary key,
+ title VARCHAR(128) not null comment '标题',
+ level TINYINT UNSIGNED default 0 comment '0 弱提示:左下角通知栏显示红点;1 强提示:用户登录后直接弹出通知。',
+ status TINYINT UNSIGNED default 0 comment '状态,0暂存,1已发送,2已删除',
+ enable TINYINT UNSIGNED default 0 comment '是否启用,0未启用,1启用',
+ send_time BIGINT UNSIGNED not null comment '通知发送时间',
+ sender_id BIGINT UNSIGNED not null comment '通知发送者id',
+ sender_ip VARCHAR(64) not null comment '发送通知的IP地址,json(222.22.22.22,杭州)',
+ notice_type TINYINT UNSIGNED default 1 comment '消息类型,1通知2消息3私信',
+ create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' NOT NULL,
+ modify_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' NULL
+);
+ALTER TABLE notice
+ COMMENT = '消息表';
+
+drop table if exists notice_detail_copy2;
+create table notice_detail
+(
+ id BIGINT UNSIGNED not null comment '主键id' primary key,
+ notice_id BIGINT UNSIGNED not null comment '通知id',
+ content TEXT not null comment '消息内容',
+ is_all TINYINT UNSIGNED default 1 comment '是否为所有用户 1 是 0 否',
+ target_ids JSON not null comment '接收者',
+ `status` TINYINT UNSIGNED default 0 comment '状态,0未读,1已读',
+ create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' NOT NULL,
+ modify_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' NULL
+);
+ALTER TABLE notice_detail
+ COMMENT = '消息详情表';
+
+CREATE TABLE notice_user
+(
+ id BIGINT UNSIGNED auto_increment comment '主键' primary key,
+ notice_id BIGINT UNSIGNED not null comment '通知id',
+ user_id BIGINT UNSIGNED not null comment '用户id',
+ is_read tinyint default 0 comment '是否已读 0 未读 1 已读',
+ `year` year not null comment '年份',
+ create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' NOT NULL,
+ modify_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' NULL
+);
+ALTER TABLE notice_detail
+ COMMENT = '消息用户表';
+
+-- target_ids
+-- {"u": [12312312,52345234,32342345],"g": [2341324,123123,345345],"r": [3252345,346134,132646345,6756354]}
+
+-- 2023-05-17
+ALTER TABLE notice_user
+ ADD COLUMN last_notice_time DATETIME DEFAULT NULL COMMENT '最后一条通知的时间' AFTER is_read;
+ALTER TABLE notice_user
+ DROP COLUMN notice_id;
+ALTER TABLE notice_user
+ ADD COLUMN notice_id JSON DEFAULT NULL COMMENT '通知id集合' AFTER user_id;
+ALTER TABLE notice
+ ADD COLUMN send_type TINYINT DEFAULT 1 COMMENT '推送方式 1 立即推送 2 计划推送' AFTER `enable`;
+ALTER TABLE notice
+ DROP COLUMN send_time;
+ALTER TABLE notice
+ ADD COLUMN send_time DATETIME DEFAULT NULL COMMENT '通知发送时间' AFTER send_type;
+ALTER TABLE notice
+ ADD COLUMN sort BIGINT DEFAULT 0 COMMENT '排序 越大越靠前' AFTER send_time;
+ALTER TABLE notice_detail
+ DROP COLUMN `status`;
+ALTER TABLE notice_detail
+ DROP COLUMN target_ids;
+ALTER TABLE notice_detail
+ ADD COLUMN target_user_ids JSON DEFAULT NULL COMMENT '目标用户id集合' AFTER is_all;
+ALTER TABLE notice_detail
+ ADD COLUMN target_dept_ids JSON DEFAULT NULL COMMENT '目标部门id集合' AFTER target_user_ids;
+ALTER TABLE notice_detail
+ ADD COLUMN target_role_ids JSON DEFAULT NULL COMMENT '目标角色id集合' AFTER target_dept_ids;
+ALTER TABLE notice_detail
+ ADD COLUMN notice_detail_id BIGINT DEFAULT NULL COMMENT '通知详情表id' AFTER target_role_ids;
+
+-- 2023-05-19
+alter table notice
+ modify sender_ip VARCHAR(64) null comment '发送通知的IP地址,json(222.22.22.22,杭州)';
+alter table notice
+ modify create_time DATETIME(19) default CURRENT_TIMESTAMP null comment '创建时间';
+alter table notice_detail
+ modify create_time DATETIME default CURRENT_TIMESTAMP null comment '创建时间';
+
+-- 2023-05-22
+ALTER TABLE notice_user
+ ADD COLUMN total BIGINT UNSIGNED DEFAULT 0 COMMENT '总数' AFTER is_read;
+
+-- 2023-05-23
+drop table if exists notice;
+drop table if exists notice_detail_copy;
+drop table if exists notice_detail;
+
+create table notice
+(
+ id BIGINT UNSIGNED auto_increment comment '通知id'
+ primary key,
+ title VARCHAR(128) not null comment '标题',
+ level TINYINT UNSIGNED default 0 comment '0 弱提示:左下角通知栏显示红点;1 强提示:用户登录后直接弹出通知。',
+ status TINYINT UNSIGNED default 0 comment '状态,0暂存,1已发送,2已删除',
+ enable TINYINT UNSIGNED default 0 comment '是否启用,0未启用,1启用',
+ send_type TINYINT default 1 comment '推送方式 1 立即推送 2 计划推送',
+ send_time DATETIME null comment '通知发送时间',
+ sort BIGINT default 0 comment '排序 越大越靠前',
+ sender_id BIGINT UNSIGNED not null comment '通知发送者id',
+ sender_ip VARCHAR(64) default null comment '发送通知的IP地址,json(222.22.22.22,杭州)',
+ notice_type TINYINT UNSIGNED default 1 comment '消息类型,1通知2消息3私信',
+ create_time DATETIME not null comment '创建时间',
+ modify_time DATETIME default null comment '更新时间'
+);
+
+create table notice_detail
+(
+ id BIGINT UNSIGNED auto_increment comment '主键id'
+ primary key,
+ notice_id BIGINT UNSIGNED not null comment '通知id',
+ content TEXT not null comment '消息内容',
+ is_all TINYINT UNSIGNED default 1 comment '是否为所有用户 1 是 0 否',
+ target_user_ids JSON null comment '目标用户id集合',
+ target_dept_ids JSON null comment '目标部门id集合',
+ target_role_ids JSON null comment '目标角色id集合',
+ notice_detail_id BIGINT null comment '通知详情表id',
+ create_time DATETIME not null comment '创建时间',
+ modify_time DATETIME default null comment '更新时间'
+);
+
+drop table if exists notice_user;
+create table notice_user
+(
+ id BIGINT UNSIGNED auto_increment comment '主键'
+ primary key,
+ user_id BIGINT UNSIGNED not null comment '用户id',
+ notice_id BIGINT UNSIGNED not null comment '通知id集合',
+ is_read TINYINT default 0 comment '是否已读 0 未读 1 已读',
+ create_time DATETIME not null comment '创建时间',
+ modify_time DATETIME default null comment '更新时间'
+);
+
+ALTER TABLE notice
+ COMMENT = '通知';
+ALTER TABLE notice_detail
+ COMMENT = '通知详情';
+ALTER TABLE notice_user
+ COMMENT = '通知用户关联';
+
+-- 2023-05-25
+ALTER TABLE notice_user
+ ADD UNIQUE INDEX user_notice_key (user_id, notice_id);
+ALTER TABLE notice_detail
+ ADD COLUMN dr TINYINT DEFAULT 0 COMMENT '逻辑删除 0 未删除 1 已删除' AFTER modify_time;
+
+-- 2023-05-26
+DROP TABLE IF EXISTS share_report;
+create table share_report_copy
+(
+ id BIGINT UNSIGNED auto_increment comment '自增id'
+ primary key,
+ share_id BIGINT UNSIGNED not null comment '分享id',
+ title VARCHAR(255) not null comment '分享标题',
+ source_id BIGINT UNSIGNED not null comment '举报资源id',
+ file_id BIGINT UNSIGNED not null comment '举报文件id,文件夹则该处为0',
+ user_id BIGINT UNSIGNED not null comment '举报用户id',
+ report_type TINYINT UNSIGNED not null comment '举报类型 (1-侵权,2-色情,3-暴力,4-政治,5-其他)',
+ reason VARCHAR(255) not null comment '举报原因(其他)描述',
+ status TINYINT UNSIGNED not null comment '处理状态(0-未处理,1-已处理,2-允许分享,3-禁止分享)',
+ create_time DATETIME not null comment '创建时间',
+ modify_time DATETIME DEFAULT null comment '最后修改时间'
+);
+ALTER TABLE share_report_copy
+ COMMENT = '分享链接举报';
+ALTER TABLE share_report
+ ADD INDEX create_time_index (user_id);
+
+-- 2023-05-30
+ALTER TABLE share
+ ADD COLUMN `status` TINYINT UNSIGNED DEFAULT 1 COMMENT '状态 1 正常 2 取消分享 3 禁止分享' AFTER isLink;
+ALTER TABLE io_source
+ ADD COLUMN canShare TINYINT UNSIGNED DEFAULT 1 COMMENT '是否可以分享 1 正常 0 禁止分享' AFTER `sort`;
+ALTER TABLE share_report
+ MODIFY status TINYINT UNSIGNED DEFAULT 0 COMMENT '处理状态(0-未处理,1-已处理)';
+-- 2023-05-31
+alter table share_report
+ modify reason VARCHAR(255) DEFAULT null comment '举报原因(其他)描述';
+alter table share
+ modify status TINYINT(3) UNSIGNED default 1 null comment '状态 1 正常 3 禁止分享 4 取消分享';
+
+-- 2023-06-08
+INSERT INTO system_option (`type`, `key`, `value`, createTime, modifyTime)
+values ('Storage', 'LOCAL', '{"name":"local1","size":"1024","location":"/uploads","storageKey":"LOCAL"}', 1682386870,
+ 1682386870);
+
+-- 2023-06-13
+ALTER TABLE common_info
+ ADD COLUMN likeCount INT(10) DEFAULT 0 COMMENT '点赞数' AFTER actualViewCount;
+ALTER TABLE common_info
+ ADD COLUMN isLogin TINYINT DEFAULT 0 COMMENT '是否需要登录 0 否 1 是' AFTER isHide;
+
+create table user_common_info
+(
+ id BIGINT UNSIGNED auto_increment
+ primary key,
+ user_id BIGINT UNSIGNED not null comment '用户id',
+ info_id BIGINT UNSIGNED not null comment '资讯id',
+ view_count INT UNSIGNED default 0 comment '阅读数',
+ is_like TINYINT UNSIGNED default 0 comment '是否点赞 0 否 1 是',
+ create_time DATETIME DEFAULT CURRENT_TIMESTAMP comment '创建时间',
+ modify_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP comment '最后修改时间',
+ constraint userId_infoId_unique
+ unique (user_id, info_id)
+)ENGINE = InnoDB CHARSET = utf8mb4 COLLATE = utf8mb4_bin COMMENT '用户资讯表';
+
+
+ALTER TABLE user_common_info DROP INDEX userId_infoId_unique;
+ALTER TABLE user_common_info ADD UNIQUE INDEX infoId_userId_unique(info_id, user_id);
+ALTER TABLE user_common_info ADD COLUMN ip VARCHAR(30) DEFAULT NULL COMMENT '用户ip' AFTER info_id;
+ALTER TABLE user_common_info ADD UNIQUE INDEX infoId_ip_unique(info_id, ip);
+ALTER TABLE user_common_info MODIFY user_id BIGINT UNSIGNED DEFAULT NULL comment '用户id';
+
+-- 2023-08-09
+create index file_name_index on io_file (fileName(8));
+drop index path on io_file;
+
+-- 2023-08-23
+create table t_tenant
+(
+ id BIGINT auto_increment primary key,
+ tenant_name VARCHAR(64) not null comment '名称',
+ second_level_domain VARCHAR(64) not null comment '二级域名',
+ user_id BIGINT not null comment '超级管理员,用户id',
+ status TINYINT(3) default 0 not null comment '状态,0停用,1启用,2删除',
+ start_time DATETIME not null comment '生效时间',
+ expire_time DATETIME not null comment '失效时间',
+ size_use BIGINT default 0 not null comment '已使用大小(byte)',
+ group_count BIGINT default 0 not null comment '组织数',
+ user_count BIGINT default 0 not null comment '用户数',
+ remark VARCHAR(255) null comment '备注',
+ create_time DATETIME not null comment '创建时间',
+ modify_time DATETIME not null comment '最后修改'
+) ENGINE = InnoDB CHARSET = utf8mb4 COLLATE = utf8mb4_bin COMMENT '用户租户表';
\ No newline at end of file
diff --git a/harbor b/harbor
new file mode 100644
index 0000000..dba86a5
--- /dev/null
+++ b/harbor
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import subprocess
+import os
+import sys
+
+site_name = "harbor.svnlan.com"
+app_name = "library/java/disk"
+dep_version = "latest"
+docker_login_name = "admin"
+docker_login_password = "Harbor12345"
+
+#执行shell命令
+def docker_cmd(cmd):
+ return_code = subprocess.call(cmd, shell=True)
+ if return_code != 0:
+ print "command === %s === error" % (cmd)
+ usage()
+ return return_code
+
+def main():
+ global dep_version
+ if len(sys.argv) >= 2:
+ dep_version = sys.argv[1]
+ docker_login = 'docker login -u %s -p %s https://%s' % (docker_login_name, docker_login_password, site_name )
+ docker_tag = 'docker build -t %s/%s:%s .' % ( site_name.lower(), app_name.lower(), dep_version)
+ docker_push = 'docker push %s/%s:%s' % ( site_name.lower(), app_name.lower(),dep_version)
+
+ for cmd in [docker_login, docker_tag, docker_push]:
+ docker_cmd(cmd)
+ print "docker cmd is run..."
+
+if __name__ =='__main__':
+ main()
diff --git a/java-disk-deployment.yaml b/java-disk-deployment.yaml
new file mode 100644
index 0000000..f6a58f3
--- /dev/null
+++ b/java-disk-deployment.yaml
@@ -0,0 +1,52 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: java-disk
+ namespace: default
+ labels:
+ app-name: java-disk
+spec:
+ replicas: 1
+ minReadySeconds: 30
+ strategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 0
+ selector:
+ matchLabels:
+ app-name: java-disk
+ template:
+ metadata:
+ labels:
+ app-name: java-disk
+ spec:
+ nodeSelector:
+ type: deployment
+ containers:
+ - name: java-disk
+ image: harbor.svnlan.com/library/java/disk:latest
+ imagePullPolicy: Always
+ securityContext:
+ privileged: true
+ ports:
+ - containerPort: 80
+ name: disk
+ protocol: TCP
+ volumeMounts:
+ - name: nfs-pvc-svnlan-cloud-disk
+ mountPath: "/uploads"
+ - name: nfs-pvc-svnlan-log30
+ mountPath: "/log"
+ - name: mem
+ mountPath: "/dev/mem"
+ volumes:
+ - name: nfs-pvc-svnlan-cloud-disk
+ persistentVolumeClaim:
+ claimName: svnlan-cloud-disk
+ - name: nfs-pvc-svnlan-log30
+ hostPath:
+ path: /data0/logs/app
+ - name: mem
+ hostPath:
+ path: /dev/mem
\ No newline at end of file
diff --git a/lib/aspose-pdf-23.4-crack.jar b/lib/aspose-pdf-23.4-crack.jar
new file mode 100644
index 0000000..c62ed44
Binary files /dev/null and b/lib/aspose-pdf-23.4-crack.jar differ
diff --git a/lib/webdav-server-6.2.9090-Beta.jar b/lib/webdav-server-6.2.9090-Beta.jar
new file mode 100644
index 0000000..b4c9f02
Binary files /dev/null and b/lib/webdav-server-6.2.9090-Beta.jar differ
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..98dcb3d
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,644 @@
+
+ 4.0.0
+ com.svnlan
+ disk
+ jar
+ 0.0.1-SNAPSHOT
+ disk
+ http://maven.apache.org
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.12.RELEASE
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ 1.2.0
+ 5.1.47
+ 1.3.2.RELEASE
+ 7.5.0
+ 1.28.5
+
+
+
+ org.apache.skywalking
+ apm-toolkit-trace
+ 8.6.0
+
+
+ org.apache.skywalking
+ apm-toolkit-logback-1.x
+ 8.6.0
+
+
+ org.apache.skywalking
+ apm-toolkit-logback-1.x-activation
+ 8.6.0
+
+
+ org.springframework.boot
+ spring-boot-starter
+ 2.2.12.RELEASE
+
+
+
+ org.springframework
+ spring-test
+ 5.0.9.RELEASE
+ test
+
+
+ org.apache.pdfbox
+ pdfbox
+ 2.0.26
+
+
+ org.apache.pdfbox
+ pdfbox-tools
+ 2.0.26
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ com.aspose
+ aspose-pdf
+ 23.4
+ system
+ ${project.basedir}/lib/aspose-pdf-23.4-crack.jar
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ org.redisson
+ redisson
+ 3.16.8
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+
+
+
+ junit
+ junit
+ 4.12
+
+
+ mysql
+ mysql-connector-java
+ ${mysql-connector}
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-mail
+
+
+
+
+ io.netty
+ netty-all
+ 4.1.48.Final
+
+
+ org.springframework
+ spring-test
+ 5.1.7.RELEASE
+
+
+
+ com.mpatric
+ mp3agic
+ 0.9.1
+
+
+
+
+ org.apache.commons
+ commons-compress
+ 1.9
+
+
+
+ com.github.junrar
+ junrar
+ 4.0.0
+
+
+
+ org.jsoup
+ jsoup
+ 1.12.1
+
+
+
+ com.auth0
+ java-jwt
+ 3.2.0
+
+
+ io.jsonwebtoken
+ jjwt
+ 0.9.0
+
+
+ commons-fileupload
+ commons-fileupload
+ 1.4
+
+
+
+ io.springfox
+ springfox-swagger2
+ 2.9.2
+
+
+
+ io.springfox
+ springfox-swagger-ui
+ 2.9.2
+
+
+ com.github.ulisesbocchio
+ jasypt-spring-boot-starter
+ 3.0.5
+
+
+ commons-io
+ commons-io
+ 2.5
+
+
+
+ com.aliyun.oss
+ aliyun-sdk-oss
+ 3.8.0
+
+
+
+ org.apache.ant
+ ant
+ 1.10.5
+
+
+
+ net.sf.sevenzipjbinding
+ sevenzipjbinding
+ 9.20-2.00beta
+
+
+ net.sf.sevenzipjbinding
+ sevenzipjbinding-all-platforms
+ 9.20-2.00beta
+
+
+
+ net.lingala.zip4j
+ zip4j
+ 2.11.5
+
+
+ net.coobird
+ thumbnailator
+ 0.4.13
+
+
+
+ org.apache.pdfbox
+ pdfbox
+ 2.0.12
+
+
+ org.apache.pdfbox
+ fontbox
+ 2.0.12
+
+
+
+ org.apache.poi
+ poi
+ 3.17
+
+
+
+ org.apache.poi
+ poi-ooxml
+ 3.17
+
+
+ com.github.eljah
+ xmindjbehaveplugin
+ 0.8
+
+
+
+
+ com.alibaba
+ druid
+ 1.1.10
+
+
+ com.alibaba
+ fastjson
+ 1.2.83
+
+
+
+
+
+
+
+
+
+ com.belerweb
+ pinyin4j
+ 2.5.0
+
+
+
+ com.github.pagehelper
+ pagehelper
+ 4.1.6
+
+
+
+ eu.bitwalker
+ UserAgentUtils
+ 1.21
+
+
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.5
+
+
+ org.apache.httpcomponents
+ httpmime
+ 4.5.6
+
+
+
+ org.projectlombok
+ lombok
+ 1.16.6
+
+
+
+ cn.jpush.api
+ jmessage-client
+ 1.1.8
+
+
+
+ com.google.code.gson
+ gson
+ 2.8.5
+
+
+
+ io.springfox
+ springfox-swagger2
+ 2.9.2
+
+
+
+ io.springfox
+ springfox-swagger-ui
+ 2.9.2
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+
+ org.mybatis
+ mybatis-typehandlers-jsr310
+ 1.0.2
+
+
+
+ cn.afterturn
+ easypoi-spring-boot-starter
+ 4.0.0
+
+
+ org.apache.poi
+ poi
+
+
+
+
+ org.apache.poi
+ poi
+ 3.17
+
+
+
+
+
+ com.github.ben-manes.caffeine
+ caffeine
+ 2.8.0
+
+
+
+ com.aliyun
+ dingtalk
+ 1.5.58
+
+
+ com.aliyun
+ alibaba-dingtalk-service-sdk
+ 2.0.0
+
+
+
+
+
+
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ 3.1.0
+
+
+
+ com.ithit.webdav
+ webdav-server
+ 6.2.9090-Beta
+ system
+ ${project.basedir}/lib/webdav-server-6.2.9090-Beta.jar
+
+
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+
+
+
+
+ net.java.dev.jna
+ jna-platform
+ 5.13.0
+
+
+ net.java.dev.jna
+ jna
+
+
+
+
+ net.java.dev.jna
+ jna
+ 5.13.0
+
+
+
+
+ org.apache.lucene
+ lucene-core
+ ${lucene-core.version}
+
+
+ org.apache.lucene
+ lucene-queryparser
+ ${lucene-core.version}
+
+
+ org.apache.lucene
+ lucene-highlighter
+ ${lucene-core.version}
+
+
+
+ org.apache.tika
+ tika-parsers
+ ${tika-core.version}
+
+
+ cxf-core
+ org.apache.cxf
+
+
+ cxf-rt-rs-client
+ org.apache.cxf
+
+
+ httpservices
+ edu.ucar
+
+
+ maven-scm-provider-svnexe
+ org.apache.maven.scm
+
+
+ maven-scm-api
+ org.apache.maven.scm
+
+
+ slf4j-log4j12
+ org.slf4j
+
+
+ c3p0
+ c3p0
+
+
+ httpclient
+ org.apache.httpcomponents
+
+
+ grib
+ edu.ucar
+
+
+ cdm
+ edu.ucar
+
+
+ unit-api
+ javax.measure
+
+
+ activation
+ javax.activation
+
+
+ org.apache.sis.storage
+ sis-netcdf
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+
+ org.mybatis.generator
+ mybatis-generator-maven-plugin
+ 1.3.2
+
+ ${basedir}/src/main/resources/generatorConfig.xml
+ false
+ true
+
+
+
+ mysql
+ mysql-connector-java
+ ${mysql.version}
+
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ 3.1.0
+
+
+ copy-resources
+ compile
+
+ copy-resources
+
+
+
+ true
+ ${project.build.outputDirectory}
+
+
+
+
+
+ src/main/resources/${package.environment}
+ false
+
+
+
+
+
+
+
+
+
+ src/main/resources
+ false
+
+
+ lib
+ WEB-INF/lib/
+
+ **/*.jar
+
+
+
+
+
+
+ pufay
+
+
+ env
+ pufay
+
+
+
+ pufay
+
+
+
+ dev
+
+
+ env
+ dev
+
+
+
+ dev
+
+
+
+ pre
+
+
+ env
+ pre
+
+
+
+ pre
+
+
+
+ itest
+
+
+ env
+ itest
+
+
+
+ itest
+
+
+
+ pro
+
+
+ env
+ pro
+
+
+
+ pro
+
+
+
+
+
diff --git a/src/main/java/com/svnlan/DiskApplication.java b/src/main/java/com/svnlan/DiskApplication.java
new file mode 100644
index 0000000..ccbce1d
--- /dev/null
+++ b/src/main/java/com/svnlan/DiskApplication.java
@@ -0,0 +1,122 @@
+package com.svnlan;
+
+import com.svnlan.annotation.EnableVisitRecord;
+import com.svnlan.utils.SpringUtil;
+import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
+import org.jasypt.encryption.StringEncryptor;
+import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
+import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.servlet.ServletComponentScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ThreadPoolExecutor;
+
+@SpringBootApplication
+// mapper 接口类扫描包配置
+@MapperScan("com.svnlan.**.dao")
+@EnableAsync
+@EnableVisitRecord
+@ServletComponentScan(basePackages = {"com.svnlan.interceptor", "com.svnlan.webdav"})
+@Import(value={SpringUtil.class})
+@EnableEncryptableProperties
+public class DiskApplication {
+ @Bean
+ RestTemplate restTemplate() {
+ RestTemplate restTemplate = new RestTemplate();
+ List> messageConverterList = new ArrayList<>();
+ for (HttpMessageConverter> mc : restTemplate.getMessageConverters()) {
+ if (!(mc instanceof MappingJackson2XmlHttpMessageConverter)) {
+ messageConverterList.add(mc);
+ }
+ }
+ restTemplate.setMessageConverters(messageConverterList);
+ return restTemplate;
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(DiskApplication.class, args);
+ }
+
+ /** 用做异步 */
+ @Bean(name = "asyncTaskExecutor")
+ public ThreadPoolTaskExecutor executor() {
+ ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
+ //核心线程数
+ taskExecutor.setCorePoolSize(3);
+ //线程池维护线程的最大数量,只有在缓冲队列满了之后才会申请超过核心线程数的线程
+ taskExecutor.setMaxPoolSize(20);
+ //缓存队列
+ taskExecutor.setQueueCapacity(15);
+ //许的空闲时间,当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
+ taskExecutor.setKeepAliveSeconds(200);
+ //异步方法内部线程名称
+ taskExecutor.setThreadNamePrefix("async-disk-");
+ /**
+ * 当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略
+ * 通常有以下四种策略:
+ * ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
+ * ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
+ * ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
+ * ThreadPoolExecutor.CallerRunsPolicy:重试添加当前的任务,自动重复调用 execute() 方法,直到成功
+ */
+ taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+ taskExecutor.initialize();
+ return taskExecutor;
+ }
+
+ /**
+ * 默认线程池线程池
+ *
+ * @return Executor
+ */
+ @Bean
+ public ThreadPoolTaskExecutor threadPoolDefault() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ //核心线程数目
+ executor.setCorePoolSize(24);
+ //指定最大线程数
+ executor.setMaxPoolSize(64);
+ //队列中最大的数目
+ executor.setQueueCapacity(24);
+ //线程名称前缀
+ executor.setThreadNamePrefix("diskThreadPool_");
+ //rejection-policy:当pool已经达到max size的时候,如何处理新任务
+ //CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
+ //对拒绝task的处理策略
+ executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+ //线程空闲后的最大存活时间
+ executor.setKeepAliveSeconds(120);
+ //加载
+ executor.initialize();
+ return executor;
+ }
+
+ @Bean(name="encryptorBean")
+ public StringEncryptor stringEncryptor() {
+ PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
+ SimpleStringPBEConfig config = new SimpleStringPBEConfig();
+ config.setPassword("WJHL2023");
+ config.setAlgorithm("PBEWithMD5AndDES");
+ config.setKeyObtentionIterations("1000");
+ config.setPoolSize("1");
+ config.setProviderName("SunJCE");
+ config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
+ config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
+ config.setStringOutputType("base64");
+ encryptor.setConfig(config);
+ return encryptor;
+ }
+
+
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/Common/CommonHandler.java b/src/main/java/com/svnlan/NettyWebchat/Common/CommonHandler.java
new file mode 100644
index 0000000..3c4a37c
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/Common/CommonHandler.java
@@ -0,0 +1,70 @@
+package com.svnlan.NettyWebchat.Common;
+
+import com.svnlan.NettyWebchat.Domain.ClientInfo;
+import com.svnlan.enums.BusinessTypeEnum;
+import com.svnlan.utils.*;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.util.AttributeKey;
+
+/**
+ * @Author:
+ * @Description:
+ */
+public class CommonHandler {
+ public static void setBaseClientInfo(ChannelHandlerContext ctx, FullHttpRequest req, String channelName, Boolean isCommon) {
+ //
+ setBaseClientInfo(ctx, req, channelName, isCommon, BusinessTypeEnum.COMMON.getCode());
+ }
+
+ public static void setBaseClientInfo(ChannelHandlerContext ctx, FullHttpRequest req, String channelName, Boolean isCommon,
+ String businessType) {
+ //记录roomName
+ AttributeKey attributeKey;
+ if (AttributeKey.exists("clientInfo")) {
+ attributeKey = AttributeKey.valueOf("clientInfo");
+ } else {
+ attributeKey = AttributeKey.newInstance("clientInfo");
+ }
+ //客户端信息写入
+ ClientInfo clientInfo = new ClientInfo();
+ clientInfo.setRoomName(channelName);
+ clientInfo.setUserAgent(req.headers().get("user-agent"));
+ clientInfo.setReferer(req.headers().get("referer"));
+ clientInfo.setIp(IpUtil.getIp(req, ctx));
+ clientInfo.setLoginTime(System.currentTimeMillis());
+ if (isCommon){
+ Long userId = getUserIdFromChannelName(channelName);
+ clientInfo.setUserId(userId);
+ }
+ clientInfo.setCommon(isCommon);
+ clientInfo.setBusinessType(businessType);
+
+ ctx.channel().attr(attributeKey).set(clientInfo);
+ }
+
+ private static Long getUserIdFromChannelName(String channelName) {
+ String hexUserId = channelName.split("_")[0];
+ return Long.valueOf(hexUserId, 16);
+ }
+
+ public static ClientInfo getClientInfo(Channel channel) {
+ ClientInfo clientInfo;
+ AttributeKey attributeKey = AttributeKey.valueOf("clientInfo");
+ try {
+ clientInfo = channel.attr(attributeKey).get();
+ } catch (Exception e){
+ LogUtil.error(e, "获取clientInfo 失败");
+ clientInfo = new ClientInfo();
+ }
+ if (clientInfo == null){
+ clientInfo = new ClientInfo();
+ }
+ return clientInfo;
+ }
+ public static ClientInfo getClientInfo(ChannelHandlerContext ctx) {
+ return getClientInfo(ctx.channel());
+ }
+
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/Common/SpringManager.java b/src/main/java/com/svnlan/NettyWebchat/Common/SpringManager.java
new file mode 100644
index 0000000..28b7919
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/Common/SpringManager.java
@@ -0,0 +1,58 @@
+package com.svnlan.NettyWebchat.Common;
+
+import com.svnlan.utils.BeanUtil;
+import com.svnlan.utils.SpringUtil;
+import org.springframework.context.ApplicationContext;
+import org.springframework.mock.web.MockServletConfig;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.servlet.DispatcherServlet;
+
+import javax.servlet.ServletContext;
+
+/**
+ * @Author:
+ * @Description:
+ */
+
+public class SpringManager {
+ //单例
+ private static SpringManager instance = new SpringManager();
+
+ private ApplicationContext ctx;
+ private WebApplicationContext mvcContext;
+ private DispatcherServlet dispatcherServlet;
+
+ private SpringManager() {
+// ctx = new ClassPathXmlApplicationContext("spring.xml");
+ ctx = SpringUtil.getApplicationContext();
+// mvcContext = new XmlWebApplicationContext();
+// mvcContext.setConfigLocation("classpath:spring-mvc.xml");
+// mvcContext.setParent(ctx);
+ BeanUtil beanUtil = SpringUtil.getBean(BeanUtil.class);
+ ServletContext servletContext = beanUtil.getServletContext();
+ mvcContext = beanUtil.getWebApplicationContext();
+ MockServletConfig servletConfig = new MockServletConfig(servletContext, "dispatcherServlet");
+ dispatcherServlet = new DispatcherServlet(mvcContext);
+ try {
+ dispatcherServlet.init(servletConfig);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static SpringManager getInstance(){
+ return instance;
+ }
+
+ public ApplicationContext getSpringContext(){
+ return ctx;
+ }
+
+ public WebApplicationContext getMvcContext(){
+ return mvcContext;
+ }
+
+ public DispatcherServlet getDispatcherServlet(){
+ return dispatcherServlet;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/svnlan/NettyWebchat/Domain/ChannelSupervise.java b/src/main/java/com/svnlan/NettyWebchat/Domain/ChannelSupervise.java
new file mode 100644
index 0000000..644c7e9
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/Domain/ChannelSupervise.java
@@ -0,0 +1,79 @@
+package com.svnlan.NettyWebchat.Domain;
+
+import com.svnlan.utils.JsonUtils;
+import com.svnlan.utils.LogUtil;
+import com.svnlan.utils.RandomUtil;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+
+/**
+ * @Author:
+ * @Description:
+ */
+public class ChannelSupervise {
+
+
+ //游客
+ public static ConcurrentHashMap> visitorRooms = new ConcurrentHashMap<>();
+ //通用业务
+ public static ConcurrentHashMap> commonRooms = new ConcurrentHashMap<>();
+ //扫码登录业务
+ public static ConcurrentHashMap> scanLoginRooms = new ConcurrentHashMap<>();
+ /** 聊天室内同步发送消息kafka */
+ public static final String SEND_ROOMMESSAGE_Netty = "sendRoomMessageNetty";
+
+ //服务标识 uuid
+ public static String uuid = RandomUtil.getuuid();
+
+ /**
+ * @Description: 发送通用返回结果
+ * @params: [ctx, code, type]
+ * @Return: void
+ * @Modified:
+ */
+ public static void sendCommonReturn(ChannelHandlerContext ctx, String code, String type) {
+ CommonReturnMessage commonReturnMessage = new CommonReturnMessage(code, type);
+ ChannelSupervise.sendToUser(ctx, JsonUtils.beanToJson(commonReturnMessage));
+ }
+
+ /**
+ * @description: 发送通用返回结果
+ * @param ctx
+ * @param type
+ * @param code
+ * @param message
+ * @return void
+ */
+ public static void sendCommonReturn(ChannelHandlerContext ctx, String type, String code, String message) {
+ CommonReturnMessage commonReturnMessage = new CommonReturnMessage(code, type, message);
+ ChannelSupervise.sendToUser(ctx, JsonUtils.beanToJson(commonReturnMessage));
+ }
+
+ public static String getRoomName(String uri) {
+ return uri.substring(uri.lastIndexOf("/") + 1);
+ }
+
+ public static void sendToUser(ChannelHandlerContext ctx, String s) {
+ sendToUser(ctx.channel(), s);
+ }
+ public static void sendToUser(Channel channel, String s){
+ if (channel == null){
+ return;
+ }
+
+ if (!channel.isWritable()){
+ LogUtil.error("无法写了,"
+ + (channel.id() == null ? "" : channel.id().asLongText()) );
+ return;
+ }
+ try {
+ channel.writeAndFlush(new TextWebSocketFrame(s));
+ } catch (Exception e){
+ LogUtil.error(e, "netty消息发送失败, " + s);
+ }
+ }
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/Domain/ClientInfo.java b/src/main/java/com/svnlan/NettyWebchat/Domain/ClientInfo.java
new file mode 100644
index 0000000..8bffa68
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/Domain/ClientInfo.java
@@ -0,0 +1,232 @@
+package com.svnlan.NettyWebchat.Domain;
+
+import com.svnlan.enums.BusinessTypeEnum;
+
+/**
+ * @Author:
+ * @Description:
+ */
+public class ClientInfo {
+ private String userAgent;
+ private String ip;
+ private String roomName;
+ private Long userId;
+ private Boolean platformManager;
+ private String groupId;
+ private String name;
+ private Boolean isCommon;
+ private String from;
+ private Boolean isLogin;
+ private String uuid;
+ private Long loginTime;
+ //大班分组序号
+ private Integer groupIndex;
+ private String groupName;
+
+ //游客ID
+ private String visitorId;
+
+ private Boolean isDevice;
+
+
+ //业务类型:common-通用;scanLogin-扫码登录
+ private String businessType = BusinessTypeEnum.COMMON.getCode();
+
+ private String referer;
+
+ //登录方式
+ private Integer CSLoginFrom;
+ //客服加密串
+ private String CServiceKey;
+ //上次发送消息的时间戳
+ private Long lastMsgTimestamp;
+ //是否客服人员
+ private Boolean isStaff;
+ //下线, 重复登录被踢
+ private Boolean offline;
+
+ public String getUserAgent() {
+ return userAgent;
+ }
+
+ public void setUserAgent(String userAgent) {
+ this.userAgent = userAgent;
+ }
+
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ public String getRoomName() {
+ return roomName;
+ }
+
+ public void setRoomName(String roomName) {
+ this.roomName = roomName;
+ }
+
+ public Long getUserId() {
+ return userId;
+ }
+
+ public void setUserId(Long userId) {
+ this.userId = userId;
+ }
+
+ public Boolean getPlatformManager() {
+ return platformManager;
+ }
+
+ public void setPlatformManager(Boolean platformManager) {
+ this.platformManager = platformManager;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Boolean getCommon() {
+ return isCommon;
+ }
+
+ public void setCommon(Boolean common) {
+ isCommon = common;
+ }
+
+ public String getFrom() {
+ return from;
+ }
+
+ public void setFrom(String from) {
+ this.from = from;
+ }
+
+ public Boolean getLogin() {
+ return isLogin;
+ }
+
+ public void setLogin(Boolean login) {
+ isLogin = login;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public Long getLoginTime() {
+ return loginTime;
+ }
+
+ public void setLoginTime(Long loginTime) {
+ this.loginTime = loginTime;
+ }
+
+ public Integer getGroupIndex() {
+ return groupIndex;
+ }
+
+ public void setGroupIndex(Integer groupIndex) {
+ this.groupIndex = groupIndex;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public void setGroupName(String groupName) {
+ this.groupName = groupName;
+ }
+
+ public String getBusinessType() {
+ return businessType;
+ }
+
+ public void setBusinessType(String businessType) {
+ this.businessType = businessType;
+ }
+
+ public String getVisitorId() {
+ return visitorId;
+ }
+
+ public void setVisitorId(String visitorId) {
+ this.visitorId = visitorId;
+ }
+
+ public Boolean getDevice() {
+ return isDevice;
+ }
+
+ public void setDevice(Boolean device) {
+ isDevice = device;
+ }
+
+ public String getReferer() {
+ return referer;
+ }
+
+ public void setReferer(String referer) {
+ this.referer = referer;
+ }
+
+
+ public Integer getCSLoginFrom() {
+ return CSLoginFrom;
+ }
+
+ public void setCSLoginFrom(Integer CSLoginFrom) {
+ this.CSLoginFrom = CSLoginFrom;
+ }
+
+ public String getCServiceKey() {
+ return CServiceKey;
+ }
+
+ public void setCServiceKey(String CServiceKey) {
+ this.CServiceKey = CServiceKey;
+ }
+
+ public Long getLastMsgTimestamp() {
+ return lastMsgTimestamp;
+ }
+
+ public void setLastMsgTimestamp(Long lastMsgTimestamp) {
+ this.lastMsgTimestamp = lastMsgTimestamp;
+ }
+
+ public Boolean getStaff() {
+ return isStaff;
+ }
+
+ public void setStaff(Boolean staff) {
+ isStaff = staff;
+ }
+
+ public Boolean getOffline() {
+ return offline;
+ }
+
+ public void setOffline(Boolean offline) {
+ this.offline = offline;
+ }
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/Domain/CommonReturnMessage.java b/src/main/java/com/svnlan/NettyWebchat/Domain/CommonReturnMessage.java
new file mode 100644
index 0000000..24f8f5b
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/Domain/CommonReturnMessage.java
@@ -0,0 +1,46 @@
+package com.svnlan.NettyWebchat.Domain;
+
+/**
+ * @Author:
+ * @Description:
+ */
+public class CommonReturnMessage {
+ private String type;
+ private String code;
+ private String message;
+
+ public CommonReturnMessage(String code, String type) {
+ this.type = type;
+ this.code = code;
+ }
+
+ public CommonReturnMessage(String type, String code, String message) {
+ this.type = type;
+ this.code = code;
+ this.message = message;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/Domain/RoomMsg.java b/src/main/java/com/svnlan/NettyWebchat/Domain/RoomMsg.java
new file mode 100644
index 0000000..c87d8a3
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/Domain/RoomMsg.java
@@ -0,0 +1,170 @@
+package com.svnlan.NettyWebchat.Domain;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @Author:
+ * @Description: 房间内广播
+ */
+public class RoomMsg {
+
+ /** 房间名 */
+ private String roomName;
+
+ /** 私聊 */
+ private Long uid;
+
+ /** 被屏蔽的session */
+ private String sessionId;
+
+ /** 被屏蔽的uid集合 */
+ private Set quarantineUid;
+
+ /** 消息体 */
+ private String message;
+
+ /** 发送给多个用户id */
+ private List userIdList;
+
+ /** 抽样发送比例 */
+ private Long sampleRate;
+
+ private Long sendToUid;
+
+ private String channelId;
+
+ private String groupNum;
+
+ private String groupName;
+
+ private Integer groupOnlineCount;
+
+ //是否公开课
+ private Integer isPublic;
+
+ //包含游客的抽样发送比例
+ private Long visitorSampleRate;
+
+ private String visitorId;
+
+ public String getRoomName() {
+ return roomName;
+ }
+
+ public void setRoomName(String roomName) {
+ this.roomName = roomName;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Long getUid() {
+ return uid;
+ }
+
+ public void setUid(Long uid) {
+ this.uid = uid;
+ }
+
+ public String getSessionId() {
+ return sessionId;
+ }
+
+ public void setSessionId(String sessionId) {
+ this.sessionId = sessionId;
+ }
+
+ public Set getQuarantineUid() {
+ return quarantineUid;
+ }
+
+ public void setQuarantineUid(Set quarantineUid) {
+ this.quarantineUid = quarantineUid;
+ }
+
+ public List getUserIdList() {
+ return userIdList;
+ }
+
+ public void setUserIdList(List userIdList) {
+ this.userIdList = userIdList;
+ }
+
+ public Long getSampleRate() {
+ return sampleRate;
+ }
+
+ public void setSampleRate(Long sampleRate) {
+ this.sampleRate = sampleRate;
+ }
+
+ public Long getSendToUid() {
+ return sendToUid;
+ }
+
+ public void setSendToUid(Long sendToUid) {
+ this.sendToUid = sendToUid;
+ }
+
+ public String getChannelId() {
+ return channelId;
+ }
+
+ public void setChannelId(String channelId) {
+ this.channelId = channelId;
+ }
+
+ public String getGroupNum() {
+ return groupNum;
+ }
+
+ public void setGroupNum(String groupNum) {
+ this.groupNum = groupNum;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public void setGroupName(String groupName) {
+ this.groupName = groupName;
+ }
+
+ public Integer getGroupOnlineCount() {
+ return groupOnlineCount;
+ }
+
+ public void setGroupOnlineCount(Integer groupOnlineCount) {
+ this.groupOnlineCount = groupOnlineCount;
+ }
+
+ public Integer getIsPublic() {
+ return isPublic;
+ }
+
+ public void setIsPublic(Integer isPublic) {
+ this.isPublic = isPublic;
+ }
+
+ public Long getVisitorSampleRate() {
+ return visitorSampleRate;
+ }
+
+ public void setVisitorSampleRate(Long visitorSampleRate) {
+ this.visitorSampleRate = visitorSampleRate;
+ }
+
+ public String getVisitorId() {
+ return visitorId;
+ }
+
+ public void setVisitorId(String visitorId) {
+ this.visitorId = visitorId;
+ }
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/NettyApplication.java b/src/main/java/com/svnlan/NettyWebchat/NettyApplication.java
new file mode 100644
index 0000000..a8f2857
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/NettyApplication.java
@@ -0,0 +1,28 @@
+package com.svnlan.NettyWebchat;
+
+import com.svnlan.NettyWebchat.initializer.NettyServer;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Profile;
+
+
+/**
+ * @Author:
+ * @Description:
+ * @Date:
+ */
+@Profile({"dev","test", "pre", "pro"})
+@SpringBootApplication
+//@EnableAsync
+public class NettyApplication implements CommandLineRunner {
+// public static void main(String[] args) {
+// SpringApplication.run(NettyApplication.class);
+// System.out.println("SpringBoot start");
+// }
+
+ @Override
+ public void run(String... args) {
+ new NettyServer().initNetty();
+// new NettyServer().start();
+ }
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/dto/ScanLoginMessage.java b/src/main/java/com/svnlan/NettyWebchat/dto/ScanLoginMessage.java
new file mode 100644
index 0000000..f8b95be
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/dto/ScanLoginMessage.java
@@ -0,0 +1,27 @@
+package com.svnlan.NettyWebchat.dto;
+
+import lombok.Data;
+
+/**
+ * @description: 扫码登录消息
+ */
+@Data
+public class ScanLoginMessage {
+
+ //消息类型:tvScanLogin-TV端;webScanLogin-web端;appScanLogin-APP端
+ private String msgType;
+ //动作
+ private String action;
+
+ //动作值
+ private String actionVal;
+
+ //登录token
+ private String token;
+ //临时登录授权码
+ private String tempAuth;
+
+ //登录token的网校域名,如:test.1x.cn
+ private String serverName;
+
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/dto/ScanLoginQRDTO.java b/src/main/java/com/svnlan/NettyWebchat/dto/ScanLoginQRDTO.java
new file mode 100644
index 0000000..6c3e61f
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/dto/ScanLoginQRDTO.java
@@ -0,0 +1,20 @@
+package com.svnlan.NettyWebchat.dto;
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @description: (扫码登录)二维码存储信息
+ */
+@Data
+public class ScanLoginQRDTO {
+
+ private String roomName;
+ //使用状态:0-未使用;1-已使用(登录)
+ private String state;
+ private Long userId;
+ //二维码生成时间
+ private Date gmtCreate;
+
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/dto/ScanLoginResult.java b/src/main/java/com/svnlan/NettyWebchat/dto/ScanLoginResult.java
new file mode 100644
index 0000000..83e385b
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/dto/ScanLoginResult.java
@@ -0,0 +1,21 @@
+package com.svnlan.NettyWebchat.dto;
+
+import lombok.Data;
+
+/**
+ * @description: 扫码登录结果信息
+ */
+@Data
+public class ScanLoginResult {
+
+ private String action;
+ private String code;
+ private String message;
+
+ //TV或WEB用于登录的临时授权码
+ private String tempAuth;
+
+ //TV或WEB用于登录的网校域名,如test.1x.cn
+ private String schoolDomain;
+
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/dto/TempAuthDTO.java b/src/main/java/com/svnlan/NettyWebchat/dto/TempAuthDTO.java
new file mode 100644
index 0000000..424bcf4
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/dto/TempAuthDTO.java
@@ -0,0 +1,16 @@
+package com.svnlan.NettyWebchat.dto;
+
+import lombok.Data;
+
+/**
+ * @description: 临时授权码对应的TOKEN信息
+ */
+@Data
+public class TempAuthDTO {
+
+ //登录TOKEN
+ private String token;
+ //
+ private String roomName;
+
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/initializer/NettyServer.java b/src/main/java/com/svnlan/NettyWebchat/initializer/NettyServer.java
new file mode 100644
index 0000000..ece29cb
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/initializer/NettyServer.java
@@ -0,0 +1,47 @@
+package com.svnlan.NettyWebchat.initializer;
+
+import com.svnlan.utils.LogUtil;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.WriteBufferWaterMark;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * @Author:
+ * @Description: 服务启动
+ * @Date:
+ */
+@Service
+public class NettyServer {
+ public void initNetty(){
+ new Thread(() -> new NettyServer().start()).start();
+ }
+ public void start(){
+ LogUtil.info("正在启动websocket服务器");
+ NioEventLoopGroup boss = new NioEventLoopGroup();
+ NioEventLoopGroup work = new NioEventLoopGroup();
+ try {
+ LogUtil.info("availableProcessors, " + Runtime.getRuntime().availableProcessors());
+ ServerBootstrap bootstrap = new ServerBootstrap();
+ bootstrap.group(boss,work);
+ bootstrap.channel(NioServerSocketChannel.class);
+ bootstrap.childHandler(new WebSocketChannelInitializer());
+ //设置高低水位
+ bootstrap.option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(32 * 1024,64 * 1024));
+ Channel channel = bootstrap.bind(81).sync().channel();
+ LogUtil.info("webSocket服务器启动成功:"+channel);
+ channel.closeFuture().sync();
+ } catch (InterruptedException e) {
+ LogUtil.error(e,"运行出错");
+ }finally {
+ boss.shutdownGracefully();
+ work.shutdownGracefully();
+ LogUtil.info("websocket服务器已关闭");
+ }
+ }
+
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/initializer/WebSocketChannelInitializer.java b/src/main/java/com/svnlan/NettyWebchat/initializer/WebSocketChannelInitializer.java
new file mode 100644
index 0000000..16e125a
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/initializer/WebSocketChannelInitializer.java
@@ -0,0 +1,49 @@
+package com.svnlan.NettyWebchat.initializer;
+
+import com.svnlan.NettyWebchat.service.WebSocketHandler;
+import com.svnlan.NettyWebchat.service.impl.HeartBeatServerHandler;
+import com.svnlan.NettyWebchat.service.impl.HttpHandler;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.handler.codec.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpServerCodec;
+import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler;
+import io.netty.handler.logging.LoggingHandler;
+import io.netty.handler.stream.ChunkedWriteHandler;
+import io.netty.handler.timeout.IdleStateHandler;
+import io.netty.util.NettyRuntime;
+import io.netty.util.concurrent.DefaultEventExecutorGroup;
+import io.netty.util.concurrent.EventExecutorGroup;
+import io.netty.util.internal.SystemPropertyUtil;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Author:
+ * @Description:
+ * @Date:
+ */
+public class WebSocketChannelInitializer extends ChannelInitializer {
+ private static final int DEFAULT_EVENT_LOOP_THREADS = Math.max(2, SystemPropertyUtil.getInt("io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
+ //主业务线程池
+ private static final EventExecutorGroup eventExecutorGroup = new DefaultEventExecutorGroup(DEFAULT_EVENT_LOOP_THREADS);
+ //耗时业务线程池
+ private static final EventExecutorGroup largeConsumptionExecutorGroup = new DefaultEventExecutorGroup(DEFAULT_EVENT_LOOP_THREADS);
+
+
+// private static final ChannelTrafficShapingHandler shapingHandler = new ChannelTrafficShapingHandler(2000);
+ @Override
+ protected void initChannel(SocketChannel ch) {
+ ch.pipeline().addLast("logging",new LoggingHandler("DEBUG"));//设置log监听器,并且日志级别为debug,方便观察运行流程
+ ch.pipeline().addLast("http-codec",new HttpServerCodec());//设置解码器
+ ch.pipeline().addLast("aggregator",new HttpObjectAggregator(1024 * 20));//聚合器,使用websocket会用到
+ ch.pipeline().addLast("http-chunked",new ChunkedWriteHandler());//用于大数据的分区传输
+ ch.pipeline().addLast("compress", new WebSocketServerCompressionHandler());
+ ch.pipeline().addLast("idleStateHandler", new IdleStateHandler(0, 0, 120, TimeUnit.SECONDS));
+ ch.pipeline().addLast(new HeartBeatServerHandler());
+// ch.pipeline().addLast(shapingHandler);
+// ch.pipeline().addLast("handler", new BaseEventHandler());
+ ch.pipeline().addLast(eventExecutorGroup, new WebSocketHandler());//自定义的业务handler
+ ch.pipeline().addLast(eventExecutorGroup, new HttpHandler());//自定义的业务handler
+ }
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/service/NettyBroadcastService.java b/src/main/java/com/svnlan/NettyWebchat/service/NettyBroadcastService.java
new file mode 100644
index 0000000..846a94e
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/service/NettyBroadcastService.java
@@ -0,0 +1,20 @@
+package com.svnlan.NettyWebchat.service;
+
+import com.svnlan.NettyWebchat.Domain.RoomMsg;
+
+/**
+ * @Author:
+ * @Description:
+ */
+public interface NettyBroadcastService {
+
+
+ /**
+ * @description: 发给某房间指定某channel消息
+ * @param roomMsg
+ * @return void
+ */
+ void sendScanLoginMessage(RoomMsg roomMsg);
+
+
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/service/NettyLoginService.java b/src/main/java/com/svnlan/NettyWebchat/service/NettyLoginService.java
new file mode 100644
index 0000000..8aa6408
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/service/NettyLoginService.java
@@ -0,0 +1,16 @@
+package com.svnlan.NettyWebchat.service;
+
+import io.netty.channel.ChannelHandlerContext;
+
+/**
+ * @description: 扫码登录
+ */
+public interface NettyLoginService {
+
+ void connect(ChannelHandlerContext ctx, String channelName);
+
+ void disconnect(ChannelHandlerContext ctx);
+
+ void receiveMessage(ChannelHandlerContext ctx, String message);
+
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/service/WebSocketHandler.java b/src/main/java/com/svnlan/NettyWebchat/service/WebSocketHandler.java
new file mode 100644
index 0000000..9698c49
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/service/WebSocketHandler.java
@@ -0,0 +1,200 @@
+package com.svnlan.NettyWebchat.service;
+
+import com.svnlan.NettyWebchat.Common.CommonHandler;
+import com.svnlan.NettyWebchat.Domain.ChannelSupervise;
+import com.svnlan.NettyWebchat.Domain.ClientInfo;
+import com.svnlan.enums.BusinessTypeEnum;
+import com.svnlan.utils.BeanUtil;
+import com.svnlan.utils.JsonUtils;
+import com.svnlan.utils.LogUtil;
+import com.svnlan.utils.SpringUtil;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.handler.codec.http.DefaultFullHttpResponse;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.websocketx.*;
+import io.netty.util.AttributeKey;
+import io.netty.util.CharsetUtil;
+
+import static io.netty.handler.codec.http.HttpUtil.isKeepAlive;
+
+/**
+ * @Author:
+ * @Description:
+ * @Date:
+ */
+public class WebSocketHandler extends SimpleChannelInboundHandler{
+ private WebSocketServerHandshaker handShaker;
+
+ //连接
+ @Override
+ public void channelActive(ChannelHandlerContext ctx) throws Exception {
+ //添加连接
+ LogUtil.info("客户端加入连接:" + ctx.channel().id().asLongText());
+// ChannelSupervise.addChannel(ctx.channel());
+ }
+ //读信息
+ @Override
+ protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
+ try {
+ if (msg instanceof FullHttpRequest){
+ //以http请求形式接入,但是走的是websocket
+ LogUtil.info("websocket WebSocketHandler FullHttpRequest");
+ handleHttpRequest(ctx, (FullHttpRequest) msg);
+ }else if (msg instanceof WebSocketFrame){
+ //处理websocket客户端的消息
+ LogUtil.info("websocket WebSocketHandler WebSocketFrame");
+ handlerWebSocketFrame(ctx, (WebSocketFrame) msg);
+ }else {
+ LogUtil.info("websocket WebSocketHandler other");
+// ReferenceCountUtil.release(msg)
+ };
+ } catch (Exception e){
+ LogUtil.error(e, "read0出错");
+ }
+ }
+
+ //断开
+ @Override
+ public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+ //断开连接
+// LogUtil.info("客户端断开连接:"+ctx.channel());
+ ClientInfo clientInfo = (ClientInfo) ctx.channel().attr(AttributeKey.valueOf("clientInfo")).get();
+ LogUtil.info("断开连接, " + JsonUtils.beanToJson(clientInfo));
+
+ try {
+ if (clientInfo == null){
+ return;
+ }
+ //扫码登录
+ if(BusinessTypeEnum.SCAN_LOGIN.getCode().equals(clientInfo.getBusinessType())) {
+ //
+ getLoginService().disconnect(ctx);
+ }
+ } catch (Exception e) {
+ LogUtil.error(e, "断开处理失败" + JsonUtils.beanToJson(clientInfo));
+ }
+ }
+
+ private NettyLoginService getLoginService() {
+ BeanUtil beanUtil = SpringUtil.getBean(BeanUtil.class);
+ return beanUtil.getNettyLoginService();
+ }
+
+ @Override
+ public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
+ ctx.flush();
+ }
+ /**
+ * 唯一的一次http请求,用于创建websocket
+ * */
+ private void handleHttpRequest(ChannelHandlerContext ctx,
+ FullHttpRequest req) {
+ //要求Upgrade为websocket,过滤掉get/Post
+ LogUtil.info("request info : " + req.decoderResult().isSuccess() + ", " + req.headers().get("Upgrade")
+ + ", " + req.headers().get("Connection")
+ );
+ if (!req.decoderResult().isSuccess()) {
+ //\\\\(不是)若不是websocket方式,则创建BAD_REQUEST的req,返回给客户端
+// sendHttpResponse(ctx, req, new DefaultFullHttpResponse(
+// HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
+ //处理http请求
+ ctx.fireChannelRead(req);
+ return;
+ }
+
+ WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
+ "ws://localhost:8081/websocket/webchat/xx", null, true, 2048);
+ handShaker = wsFactory.newHandshaker(req);
+ if (handShaker == null) {
+ WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
+ } else {
+ System.out.println("handleHttpRequest url....." + req.uri());
+ if (req.uri().indexOf("/websocket/webchat/scanLogin/") == 0){ //扫码登录
+ String channelName = ChannelSupervise.getRoomName(req.uri());
+ NettyLoginService nettyLoginService = getLoginService();
+ CommonHandler.setBaseClientInfo(ctx, req, channelName, false, BusinessTypeEnum.SCAN_LOGIN.getCode());
+ nettyLoginService.connect(ctx, channelName);
+ }
+
+ handShaker.handshake(ctx.channel(), req);
+ }
+ }
+
+
+
+ /**
+ * 拒绝不合法的请求,并返回错误信息
+ * */
+ private static void sendHttpResponse(ChannelHandlerContext ctx,
+ FullHttpRequest req, DefaultFullHttpResponse res) {
+ // 返回应答给客户端
+ if (res.status().code() != 200) {
+ ByteBuf buf = Unpooled.copiedBuffer(res.status().toString(),
+ CharsetUtil.UTF_8);
+ res.content().writeBytes(buf);
+ buf.release();
+ }
+ ChannelFuture f = ctx.channel().writeAndFlush(res);
+ // 如果是非Keep-Alive,关闭连接
+ if (!isKeepAlive(req) || res.status().code() != 200) {
+ f.addListener(ChannelFutureListener.CLOSE);
+ }
+ }
+
+ private void handlerWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame){
+ LogUtil.info("webSocketLog handlerWebSocketFrame");
+ // 判断是否关闭链路的指令
+ if (frame instanceof CloseWebSocketFrame) {
+ LogUtil.info("webSocketLog CloseWebSocketFrame");
+ handShaker.close(ctx.channel(), (CloseWebSocketFrame) frame.retain());
+ return;
+ }
+ // 判断是否ping消息
+ if (frame instanceof PingWebSocketFrame || frame instanceof PongWebSocketFrame) {
+ LogUtil.info("webSocketLog PingWebSocketFrame or PongWebSocketFrame");
+// ctx.channel().writeAndFlush(new PongWebSocketFrame(frame.content().retain()));
+ return;
+ }
+ // 其他格式帧
+ ClientInfo clientInfo;
+ try {
+ clientInfo = CommonHandler.getClientInfo(ctx.channel());
+ LogUtil.info("webSocketLog clientInfo=" + JsonUtils.beanToJson(clientInfo));
+ } catch (Exception e){
+ LogUtil.error(e.getMessage(), "非text消息, 客户端信息获取失败. ");
+ clientInfo = new ClientInfo();
+ }
+ if (!(frame instanceof TextWebSocketFrame)) {
+
+ try {
+ LogUtil.info(String.format(
+ "%s frame types not supported", frame.getClass().getName()) + ", " + JsonUtils.beanToJson(clientInfo));
+ } catch (Exception e){
+ LogUtil.error(e.getMessage(), "非text消息, ");
+ }
+ return;
+ }
+ if (clientInfo.getRoomName() == null){
+ return;
+ }
+ // 返回应答消息
+ String message = ((TextWebSocketFrame) frame).text();
+ LogUtil.info("服务端收到:" + message);
+ if (message.equals("1")){ //保活
+ ChannelSupervise.sendToUser(ctx, "2");
+ return;
+ }
+
+ String businessType = clientInfo.getBusinessType();
+ if(businessType.equals(BusinessTypeEnum.SCAN_LOGIN.getCode())) { //扫码登录
+ //
+ getLoginService().receiveMessage(ctx, message);
+ }
+
+ }
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/service/impl/HeartBeatServerHandler.java b/src/main/java/com/svnlan/NettyWebchat/service/impl/HeartBeatServerHandler.java
new file mode 100644
index 0000000..8576ca8
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/service/impl/HeartBeatServerHandler.java
@@ -0,0 +1,27 @@
+package com.svnlan.NettyWebchat.service.impl;
+
+import com.svnlan.utils.LogUtil;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.handler.timeout.IdleState;
+import io.netty.handler.timeout.IdleStateEvent;
+
+/**
+ * @Author:
+ * @Description: 心跳检测
+ * @Date:
+ */
+public class HeartBeatServerHandler extends ChannelInboundHandlerAdapter {
+ @Override
+ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+ if (evt instanceof IdleStateEvent){
+ IdleStateEvent event = (IdleStateEvent)evt;
+ if (event.state() == IdleState.READER_IDLE){
+ LogUtil.info("关闭这个不活跃通道!, " + ctx.channel().id().asLongText());
+ ctx.channel().close();
+ }
+ } else {
+ super.userEventTriggered(ctx,evt);
+ }
+ }
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/service/impl/HttpHandler.java b/src/main/java/com/svnlan/NettyWebchat/service/impl/HttpHandler.java
new file mode 100644
index 0000000..5fb6033
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/service/impl/HttpHandler.java
@@ -0,0 +1,36 @@
+package com.svnlan.NettyWebchat.service.impl;
+
+import com.svnlan.NettyWebchat.Common.SpringManager;
+import com.svnlan.NettyWebchat.utils.ResponseUtil;
+import com.svnlan.NettyWebchat.utils.RequestTransUtil;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.FullHttpResponse;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+/**
+ * @Author:
+ * @Description:
+ * @Date:
+ */
+public class HttpHandler extends SimpleChannelInboundHandler {
+ @Override
+ protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest) throws Exception {
+// boolean isKeepAlive = HttpUtil.isKeepAlive(req);
+// FullHttpRequest fullHttpRequest = (FullHttpRequest) req;
+ fullHttpRequest.retain();
+ MockHttpServletRequest servletRequest = RequestTransUtil.transRequest2Spring(fullHttpRequest);
+ MockHttpServletResponse servletResponse = new MockHttpServletResponse();
+ try {
+ SpringManager.getInstance().getDispatcherServlet().service(servletRequest, servletResponse);
+ FullHttpResponse nettyResponse = RequestTransUtil.transResponse2Netty(servletResponse);
+ ResponseUtil.sendHttpResponse(ctx, fullHttpRequest, nettyResponse);
+ } catch (Exception e) {
+ ResponseUtil.sendHttpResponse(ctx, fullHttpRequest, ResponseUtil.get500Response());
+ }
+// NettyWebchatService webchatService = SpringUtil.getBean(NettyWebchatService.class);
+// webchatService.aaa(ctx, fullHttpRequest);
+ }
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/service/impl/NettyBroadcastServiceImpl.java b/src/main/java/com/svnlan/NettyWebchat/service/impl/NettyBroadcastServiceImpl.java
new file mode 100644
index 0000000..9da3bf8
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/service/impl/NettyBroadcastServiceImpl.java
@@ -0,0 +1,38 @@
+package com.svnlan.NettyWebchat.service.impl;
+
+import com.svnlan.NettyWebchat.Domain.ChannelSupervise;
+import com.svnlan.NettyWebchat.Domain.RoomMsg;
+import com.svnlan.NettyWebchat.service.NettyBroadcastService;
+import com.svnlan.utils.*;
+import io.netty.channel.Channel;
+import org.springframework.stereotype.Service;
+
+/**
+ * @Author:
+ * @Description:
+ */
+@Service
+public class NettyBroadcastServiceImpl implements NettyBroadcastService {
+
+
+ @Override
+ public void sendScanLoginMessage(RoomMsg roomMsg) {
+ String roomMame = roomMsg.getRoomName();
+ if (StringUtil.isEmpty(roomMsg.getChannelId())) {
+ if (ChannelSupervise.scanLoginRooms.get(roomMame) != null) {
+ for (Channel channel : ChannelSupervise.scanLoginRooms.get(roomMame).keySet()) {
+ ChannelSupervise.sendToUser(channel, roomMsg.getMessage());
+ }
+ }
+ } else {
+ if (ChannelSupervise.scanLoginRooms.get(roomMame) != null) {
+ for (Channel channel : ChannelSupervise.scanLoginRooms.get(roomMame).keySet()) {
+ if (channel.id().asLongText().equals(roomMsg.getChannelId())) {
+ ChannelSupervise.sendToUser(channel, roomMsg.getMessage());
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/service/impl/NettyLoginServiceImpl.java b/src/main/java/com/svnlan/NettyWebchat/service/impl/NettyLoginServiceImpl.java
new file mode 100644
index 0000000..819bb82
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/service/impl/NettyLoginServiceImpl.java
@@ -0,0 +1,397 @@
+package com.svnlan.NettyWebchat.service.impl;
+
+import com.svnlan.NettyWebchat.Common.CommonHandler;
+import com.svnlan.NettyWebchat.Domain.ChannelSupervise;
+import com.svnlan.NettyWebchat.Domain.ClientInfo;
+import com.svnlan.NettyWebchat.Domain.CommonReturnMessage;
+import com.svnlan.NettyWebchat.Domain.RoomMsg;
+import com.svnlan.NettyWebchat.dto.ScanLoginMessage;
+import com.svnlan.NettyWebchat.dto.ScanLoginQRDTO;
+import com.svnlan.NettyWebchat.dto.ScanLoginResult;
+import com.svnlan.NettyWebchat.dto.TempAuthDTO;
+import com.svnlan.NettyWebchat.service.NettyBroadcastService;
+import com.svnlan.NettyWebchat.service.NettyLoginService;
+import com.svnlan.common.GlobalConfig;
+import com.svnlan.enums.BusinessTypeEnum;
+import com.svnlan.enums.ScanLoginActionEnum;
+import com.svnlan.enums.ScanLoginMsgTypeEnum;
+import com.svnlan.exception.CodeMessageEnum;
+import com.svnlan.jwt.domain.LoginUser;
+import com.svnlan.utils.*;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.util.AttributeKey;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.HashOperations;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @description: 扫码登录处理
+ * @author
+ */
+@Service
+public class NettyLoginServiceImpl implements NettyLoginService {
+
+ @Autowired
+ private LoginUserUtil loginUserUtil;
+ @Autowired
+ private StringRedisTemplate stringRedisTemplate;
+ @Value("${scan.login.code.expire}")
+ private Long scanLoginCodeExpire;
+ @Resource
+ private NettyBroadcastService newBroadcastService;
+
+ @Override
+ public void connect(ChannelHandlerContext ctx, String channelName) {
+ BeanUtil beanUtil = SpringUtil.getBean(BeanUtil.class);
+ StringRedisTemplate stringRedisTemplate = beanUtil.getStringRedisTemplate();
+ //查询key是否存在
+ String val = stringRedisTemplate.opsForValue().get(GlobalConfig.SCAN_LOGIN_CODE_REDIS_KEY + channelName);
+ //二维码已经失效,请重新扫描(或不存在)
+ if (StringUtil.isEmpty(val)){
+ LogUtil.error("[扫码登录]建立连接时检测二维码已经失效>>>channelName:" + channelName);
+ }
+ }
+
+ @Override
+ public void disconnect(ChannelHandlerContext ctx) {
+ ClientInfo clientInfo = CommonHandler.getClientInfo(ctx);
+ String roomName = clientInfo.getRoomName();
+ //
+ HashOperations hashOperations = this.stringRedisTemplate.opsForHash();
+ String channelId = ctx.channel().id().asLongText();
+
+ //删除内存值
+ if (ChannelSupervise.scanLoginRooms.get(roomName) != null) {
+ //
+ ChannelSupervise.scanLoginRooms.get(roomName).remove(ctx.channel());
+ }
+
+ //删除REDIS缓存
+ //扫码登录的 channelId与标识ID(loginId)的关联关系
+ String lcRelationRedisKey = String.format(GlobalConfig.ScanLoginIdChannelRelation, roomName);
+
+ //删除扫码登录的 APP token与 生成的临时授权码的关联关系的REDIS缓存
+ String tempAuthRelationRedisKey = String.format(GlobalConfig.ScanLoginTempAuthRelation, roomName);
+ Map lcMap = hashOperations.entries(lcRelationRedisKey);
+ Iterator iterator = lcMap.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ String tempChannelId = entry.getKey();
+ String loginId = entry.getValue();
+ if(tempChannelId.equals(channelId) && hashOperations.hasKey(tempAuthRelationRedisKey, loginId)) {
+ hashOperations.delete(tempAuthRelationRedisKey, loginId);
+ }
+ }
+
+ //删除channelId与标识ID(loginId)的关联关系的REDIS缓存
+ hashOperations.delete(lcRelationRedisKey, channelId);
+
+ ScanLoginResult scanLoginResult = new ScanLoginResult();
+ scanLoginResult.setAction("disconnect");
+ scanLoginResult.setCode("200");
+ scanLoginResult.setMessage("disconnect success");
+ RoomMsg roomMsg = new RoomMsg();
+ roomMsg.setRoomName(roomName);
+ roomMsg.setMessage(JsonUtils.beanToJson(scanLoginResult));
+ roomMsg.setChannelId(channelId);
+ newBroadcastService.sendScanLoginMessage(roomMsg);
+ }
+
+ @Override
+ public void receiveMessage(ChannelHandlerContext ctx, String message) {
+ String prefix = "[扫码登录]收到处理消息>>>";
+ ClientInfo clientInfo = CommonHandler.getClientInfo(ctx);
+ String roomName = clientInfo.getRoomName();
+ //校验房间号不能为空
+ if (StringUtil.isEmpty(roomName)){
+ ChannelSupervise.sendCommonReturn(ctx, "400", "rcv");
+ return;
+ }
+
+ String channelId = ctx.channel().id().asLongText();
+ String paramTip = String.format("<<<房间号:%s,内容:%s,channelId:%s", roomName, message, channelId);
+ LogUtil.info(prefix + " start" + paramTip);
+
+ //校验二维码(房间号)是否已失效
+ BeanUtil beanUtil = SpringUtil.getBean(BeanUtil.class);
+ StringRedisTemplate stringRedisTemplate = beanUtil.getStringRedisTemplate();
+ String redisKey = GlobalConfig.SCAN_LOGIN_CODE_REDIS_KEY + roomName;
+ //查询key是否存在
+ Object qrCodeObj = stringRedisTemplate.opsForValue().get(redisKey);
+ Date qrGmtCreate = null;
+ if(null == qrCodeObj) {
+ CommonReturnMessage commonReturnMessage = new CommonReturnMessage(BusinessTypeEnum.SCAN_LOGIN.getCode(),
+ CodeMessageEnum.QR_INVALID.getCode(), "二维码已失效");
+ LogUtil.error(prefix + "二维码已失效" + paramTip);
+ ChannelSupervise.sendToUser(ctx, JsonUtils.beanToJson(commonReturnMessage));
+ return;
+ } else {
+ ScanLoginQRDTO scanLoginQRDTO = JsonUtils.jsonToBean(StringUtil.changeNullToEmpty(qrCodeObj), ScanLoginQRDTO.class);
+ qrGmtCreate = scanLoginQRDTO.getGmtCreate();
+ }
+
+ if(StringUtil.isEmpty(message)) {
+ ChannelSupervise.sendCommonReturn(ctx, BusinessTypeEnum.SCAN_LOGIN.getCode(),
+ CodeMessageEnum.shareErrorParam.getCode(), "消息为空无效");
+ }
+ ScanLoginMessage scanLoginMessage = null;
+ try {
+ scanLoginMessage = JsonUtils.jsonToBean(message, ScanLoginMessage.class);
+ } catch (Exception e) {
+ LogUtil.error(e, prefix + "消息内容格式有误" + paramTip);
+ ChannelSupervise.sendCommonReturn(ctx, BusinessTypeEnum.SCAN_LOGIN.getCode(),
+ CodeMessageEnum.shareErrorParam.getCode(), "消息内容格式有误");
+ }
+
+ //处理接收到的消息
+ this.handleMessage(prefix, scanLoginMessage, roomName, ctx, qrGmtCreate);
+ }
+
+ /**
+ * @description: 处理接收到的消息
+ * @param prefix
+ * @param scanLoginMessage
+ * @param roomName
+ * @param ctx
+ * @param qrGmtCreate
+ * @return
+ */
+ private void handleMessage(String prefix, ScanLoginMessage scanLoginMessage, String roomName, ChannelHandlerContext ctx, Date qrGmtCreate) {
+ String msgType = StringUtil.trim(scanLoginMessage.getMsgType());
+ String action = StringUtil.trim(scanLoginMessage.getAction());
+ String actionVal = StringUtil.trim(scanLoginMessage.getActionVal());
+ String token = StringUtil.trim(scanLoginMessage.getToken());
+ String resultAction = action;
+ String serverName = StringUtil.trim(scanLoginMessage.getServerName());
+
+ String code = CodeMessageEnum.success.getCode();
+ String message = "";
+ String tempAuth = scanLoginMessage.getTempAuth();
+ String schoolDomain = null;
+
+ //是否原路回消息
+ Boolean isReturnMsg = Boolean.TRUE;
+
+ //是否转发消息
+ Boolean isTransfer = Boolean.FALSE;
+ //转发的接收人loginId标识
+ String transferReceiverId = "";
+ String transferAction = action;
+ String transferCode = "200";
+ String transferMessage = "";
+
+ //扫码登录的 channelId与标识ID(loginId)的关联关系
+ String lcRelationRedisKey = String.format(GlobalConfig.ScanLoginIdChannelRelation, roomName);
+ //扫码登录的 APP token与 生成的临时授权码的关联关系
+ String tempAuthRelationRedisKey = String.format(GlobalConfig.ScanLoginTempAuthRelation, roomName);
+
+ HashOperations hashOperations = this.stringRedisTemplate.opsForHash();
+ ValueOperations valueOperations = this.stringRedisTemplate.opsForValue();
+ try {
+ String channelId = ctx.channel().id().asLongText();
+ if(!ScanLoginMsgTypeEnum.contains(msgType)) {
+ code = CodeMessageEnum.shareErrorParam.getCode();
+ message = "msgType值非法";
+ }
+ LoginUser loginUser = null;
+ //若是TV、WEB端
+ if(!msgType.equals(ScanLoginMsgTypeEnum.APP_SCAN_LOGIN.getCode())) {
+ if(!ScanLoginActionEnum.containsTvWebAction(action)) {
+ code = CodeMessageEnum.success.getCode();
+ message = "action值非法";
+ } else {
+ //
+ if(action.equals(ScanLoginActionEnum.FEED_BACK.getCode())) {
+ if(!actionVal.equals("success") && !actionVal.equals("fail")) {
+ code = CodeMessageEnum.shareErrorParam.getCode();
+ message = "actionVal值非法";
+ }
+ }
+ }
+ } else { //若是APP端
+ if(!ScanLoginActionEnum.containsAppAction(action)) {
+ code = CodeMessageEnum.shareErrorParam.getCode();
+ message = "action值非法";
+ } else {
+ //校验TOKEN
+ if (StringUtil.isEmpty(token)) {
+ code = CodeMessageEnum.errorAdminAuth.getCode();
+ message = "token不能为空";
+ } else {
+ if (StringUtil.isEmpty(serverName)) {
+ code = CodeMessageEnum.shareErrorParam.getCode();
+ message = "serverName不能为空";
+ } else {
+ //
+ loginUser = this.loginUserUtil.getLoginUser(serverName, token);
+ if (loginUser == null || loginUser.getUserID() == null) {
+ code = CodeMessageEnum.errorAdminAuth.getCode();
+ message = CodeMessageEnum.errorAdminAuth.getMsg();
+ }
+ }
+ }
+ }
+ }
+
+ String loginId = roomName;
+ if("200".equals(code) || "common.success".equals(code)) {
+ //若是APP端
+ if (msgType.equals(ScanLoginMsgTypeEnum.APP_SCAN_LOGIN.getCode())) {
+ loginId = token;
+ }
+
+ //动作
+ //若是confirm-确认连接时
+ if(ScanLoginActionEnum.CONFIRM.getCode().equals(action)) {
+ //置房间、channel、标识的实例内存
+ ChannelSupervise.scanLoginRooms.putIfAbsent(roomName, new ConcurrentHashMap<>());
+ ChannelSupervise.scanLoginRooms.get(roomName).put(ctx.channel(), loginId);
+
+ //置redis缓存
+ hashOperations.put(lcRelationRedisKey, channelId, loginId);
+ this.stringRedisTemplate.expire(lcRelationRedisKey, this.scanLoginCodeExpire, TimeUnit.MINUTES);
+
+ ClientInfo clientInfo = CommonHandler.getClientInfo(ctx);
+ clientInfo.setLogin(true);
+ ctx.channel().attr(AttributeKey.valueOf("clientInfo")).set(clientInfo);
+
+ //若是APP端,则得转发消息通知下TV或WEB端:扫描成功
+ if(ScanLoginMsgTypeEnum.APP_SCAN_LOGIN.getCode().equals(msgType)) {
+ transferAction = ScanLoginActionEnum.SCAN.getCode();
+ transferMessage = "扫描成功";
+
+ isTransfer = Boolean.TRUE;
+ transferReceiverId = roomName;
+ }
+ }
+ //是auth-登录授权(APP端)
+ else if(ScanLoginActionEnum.AUTH.getCode().equals(action)) {
+ //若多次授权存在,则返回原有的
+ if(hashOperations.hasKey(tempAuthRelationRedisKey, token)) {
+ tempAuth = StringUtil.changeNullToEmpty(hashOperations.get(tempAuthRelationRedisKey, token));
+ }
+ //否则产生新的临时授权码给TV、WEB
+ else {
+ tempAuth = GlobalConfig.ScanLoginTempAuthRedisKeyPrefix + RandomUtil.getuuid();
+ //置APP token与生成的临时授权码的关联关系 redis缓存
+ hashOperations.put(tempAuthRelationRedisKey, token, tempAuth);
+ Long currentML = System.currentTimeMillis();
+ //剩余有效期
+ Long remainExpire = qrGmtCreate.getTime() + this.scanLoginCodeExpire*60*1000 - currentML;
+ this.stringRedisTemplate.expire(tempAuthRelationRedisKey, remainExpire, TimeUnit.MILLISECONDS);
+
+ TempAuthDTO tempAuthDTO = new TempAuthDTO();
+ tempAuthDTO.setToken(token);
+ tempAuthDTO.setRoomName(roomName);
+ //置 临时登录授权码与APP登录TOKEN的 REDIS缓存
+ valueOperations.set(tempAuth, JsonUtils.beanToJson(tempAuthDTO), this.scanLoginCodeExpire, TimeUnit.MINUTES);
+ }
+ //app扫码登录对应的网校域名
+ schoolDomain = serverName;
+
+ //暂不原路回消息给APP
+ isReturnMsg = Boolean.FALSE;
+
+ //转发消息给TV或WEB端
+ transferAction = ScanLoginActionEnum.AUTH.getCode();
+ transferMessage = "APP授权成功";
+ isTransfer = Boolean.TRUE;
+ transferReceiverId = roomName;
+ }
+ //是feedBack-反馈登录结果(TV或WEB端)
+ else if(ScanLoginActionEnum.FEED_BACK.getCode().equals(action)
+ && !msgType.equals(ScanLoginMsgTypeEnum.APP_SCAN_LOGIN.getCode())) {
+ //action为feedBack时则必填
+ //校验临时授权码
+ if (StringUtil.isEmpty(tempAuth)) {
+ code = CodeMessageEnum.errorAdminAuth.getCode();
+ message = "tempAuth不能为空";
+ } else {
+ Object appTokenObj = valueOperations.get(tempAuth);
+ if(ObjectUtils.isEmpty(appTokenObj)) {
+ code = CodeMessageEnum.TEMP_AUTH_INVALID.getCode();
+ message = CodeMessageEnum.TEMP_AUTH_INVALID.getMsg();
+ }
+ //转发给对应的APP通知下 TV或WEB登录结果
+ else {
+ TempAuthDTO tempAuthDTO = JsonUtils.jsonToBean(StringUtil.changeNullToEmpty(appTokenObj), TempAuthDTO.class);
+ String appToken = tempAuthDTO.getToken();
+ isTransfer = Boolean.TRUE;
+ transferReceiverId = appToken;
+
+ transferAction = ScanLoginActionEnum.AUTH.getCode();
+ //action为feedBack时,登录成功则放success,否则放fail;
+ if(!"success".equals(actionVal)) {
+ transferCode = CodeMessageEnum.QR_INVALID.getCode();
+ transferMessage = CodeMessageEnum.QR_INVALID.getMsg();
+ }
+ //若是成功,则
+ else {
+ //删除临时授权码的REDIS缓存
+ this.stringRedisTemplate.delete(tempAuth);
+ //删除二维码的缓存使失效
+ this.stringRedisTemplate.delete(GlobalConfig.SCAN_LOGIN_CODE_REDIS_KEY + roomName);
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ LogUtil.error(e, prefix + "未知异常");
+ code = CodeMessageEnum.shareErrorParam.getCode();
+ message = "未知异常,请重试";
+ }
+
+ //原路回消息
+ if(isReturnMsg) {
+ ScanLoginResult scanLoginResult = new ScanLoginResult();
+ scanLoginResult.setAction(resultAction);
+ scanLoginResult.setCode(code);
+ scanLoginResult.setMessage(message);
+ String resultJson = JsonUtils.beanToJson(scanLoginResult);
+ LogUtil.info(prefix + "原路回消息结果内容:" + resultJson);
+ //发送消息回去
+ ChannelSupervise.sendToUser(ctx, resultJson);
+ }
+
+ //转发消息
+ if(isTransfer) {
+ ScanLoginResult scanLoginResult = new ScanLoginResult();
+ scanLoginResult.setAction(transferAction);
+ scanLoginResult.setCode(transferCode);
+ scanLoginResult.setMessage(transferMessage);
+ scanLoginResult.setTempAuth(tempAuth);
+ scanLoginResult.setSchoolDomain(schoolDomain);
+
+ RoomMsg roomMsg = new RoomMsg();
+ roomMsg.setRoomName(roomName);
+ roomMsg.setMessage(JsonUtils.beanToJson(scanLoginResult));
+
+ Map lcMap = hashOperations.entries(lcRelationRedisKey);
+ Iterator iterator = lcMap.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ String channelId = entry.getKey();
+ String loginId = entry.getValue();
+ if(transferReceiverId.equals(loginId)) {
+ roomMsg.setChannelId(channelId);
+ String msg = JsonUtils.beanToJson(roomMsg);
+ LogUtil.info(prefix + "转发消息内容:" + msg);
+ newBroadcastService.sendScanLoginMessage(roomMsg);
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/utils/RequestTransUtil.java b/src/main/java/com/svnlan/NettyWebchat/utils/RequestTransUtil.java
new file mode 100644
index 0000000..dc3c06b
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/utils/RequestTransUtil.java
@@ -0,0 +1,99 @@
+package com.svnlan.NettyWebchat.utils;
+
+import com.svnlan.NettyWebchat.Common.SpringManager;
+import com.svnlan.utils.ParamUtil;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.handler.codec.http.*;
+import io.netty.handler.codec.http.websocketx.WebSocketFrame;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.util.UriComponents;
+import org.springframework.web.util.UriComponentsBuilder;
+import org.springframework.web.util.UriUtils;
+
+import javax.servlet.ServletContext;
+import java.util.Map;
+
+/**
+ * @Author:
+ * @Description:
+ */
+public class RequestTransUtil {
+ //Netty转Spring请求
+ public static MockHttpServletRequest transRequest2Spring(FullHttpRequest nettyRequest){
+ UriComponents uriComponents = UriComponentsBuilder.fromUriString(nettyRequest.uri()).build();
+ ServletContext servletContext = SpringManager.getInstance().getDispatcherServlet().getServletConfig().getServletContext();
+ MockHttpServletRequest servletRequest = new MockHttpServletRequest(servletContext);
+ servletRequest.setRequestURI(uriComponents.getPath());
+ servletRequest.setPathInfo(uriComponents.getPath());
+ servletRequest.setMethod(nettyRequest.method().name());
+
+ if (uriComponents.getScheme() != null) {
+ servletRequest.setScheme(uriComponents.getScheme());
+ }
+ if (uriComponents.getHost() != null) {
+ servletRequest.setServerName(uriComponents.getHost());
+ }
+ if (uriComponents.getPort() != -1) {
+ servletRequest.setServerPort(uriComponents.getPort());
+ }
+
+ for (String name : nettyRequest.headers().names()) {
+ servletRequest.addHeader(name, nettyRequest.headers().get(name));
+ }
+
+ ByteBuf content = nettyRequest.content();
+ content.readerIndex(0);
+ byte[] data = new byte[content.readableBytes()];
+ content.readBytes(data);
+ servletRequest.setContent(data);
+
+ if (uriComponents.getQuery() != null) {
+ String query = UriUtils.decode(uriComponents.getQuery(), "UTF-8");
+ servletRequest.setQueryString(query);
+ }
+
+ Map paramMap = ParamUtil.getRequestParams(nettyRequest);
+ if(! CollectionUtils.isEmpty(paramMap)){
+ for (Map.Entry entry : paramMap.entrySet()) {
+ servletRequest.addParameter(entry.getKey(), entry.getValue());
+ }
+ }
+ return servletRequest;
+ }
+
+ //WebSocket转Spring请求
+ public static MockHttpServletRequest transFrame2Spring(WebSocketFrame frame, String url){
+ ServletContext servletContext = SpringManager.getInstance().getDispatcherServlet().getServletConfig().getServletContext();
+ MockHttpServletRequest servletRequest = new MockHttpServletRequest(servletContext);
+ servletRequest.setRequestURI(url);
+ servletRequest.setPathInfo(url);
+ servletRequest.setMethod(HttpMethod.POST.name());
+ servletRequest.setContentType(HttpHeaderValues.TEXT_PLAIN.toString());
+
+ if(frame != null){
+ ByteBuf content = frame.content();
+ content.readerIndex(0);
+ byte[] data = new byte[content.readableBytes()];
+ content.readBytes(data);
+ servletRequest.setContent(data);
+ }
+ return servletRequest;
+ }
+
+
+ //Spring转Netty响应
+ public static FullHttpResponse transResponse2Netty(MockHttpServletResponse servletResponse){
+ HttpResponseStatus status = HttpResponseStatus.valueOf(servletResponse.getStatus());
+ FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, Unpooled.wrappedBuffer(servletResponse.getContentAsByteArray()));
+
+ for (String name : servletResponse.getHeaderNames()) {
+ for (Object value : servletResponse.getHeaderValues(name)) {
+ response.headers().add(name, value);
+ }
+ }
+ return response;
+ }
+}
diff --git a/src/main/java/com/svnlan/NettyWebchat/utils/ResponseUtil.java b/src/main/java/com/svnlan/NettyWebchat/utils/ResponseUtil.java
new file mode 100644
index 0000000..b39a578
--- /dev/null
+++ b/src/main/java/com/svnlan/NettyWebchat/utils/ResponseUtil.java
@@ -0,0 +1,70 @@
+package com.svnlan.NettyWebchat.utils;
+
+import io.netty.buffer.ByteBufUtil;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.*;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * @Author:
+ * @Description:
+ */
+public class ResponseUtil {
+
+ /**
+ * 获取400响应
+ */
+ public static FullHttpResponse get400Response(){
+ return new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST);
+ }
+
+ /**
+ * 获取200响应
+ */
+ public static FullHttpResponse get200Response(String content){
+ return new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(content.getBytes()));
+ }
+
+ /**
+ * 获取500响应
+ */
+ public static FullHttpResponse get500Response(){
+ return new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR, Unpooled.wrappedBuffer("服务器异常".getBytes()));
+ }
+
+ /**
+ * 发送HTTP响应
+ */
+ public static void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest request, FullHttpResponse response) {
+ // 返回应答给客户端
+ if (response.status().code() != 200) {
+ ByteBufUtil.writeUtf8(response.content(), response.status().toString());
+ }
+
+ //添加header描述length,避免客户端接收不到数据
+ if(StringUtils.isEmpty(response.headers().get(HttpHeaderNames.CONTENT_TYPE))){
+ response.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.TEXT_PLAIN);
+ }
+ if(StringUtils.isEmpty(response.headers().get(HttpHeaderNames.CONTENT_LENGTH))){
+ response.headers().add(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
+ }
+
+ //解决跨域的问题
+ response.headers().set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN,"*");
+ response.headers().set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_HEADERS,"*");//允许headers自定义
+ response.headers().set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_METHODS,"GET, POST, PUT,DELETE");
+ response.headers().set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_CREDENTIALS,"true");
+
+ // 如果是非Keep-Alive,关闭连接
+ if (! HttpUtil.isKeepAlive(request) || response.status().code() != 200) {
+ response.headers().add(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE);
+ ctx.channel().writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
+ }else{
+ response.headers().add(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
+ ctx.channel().writeAndFlush(response);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/svnlan/annotation/CreateGroup.java b/src/main/java/com/svnlan/annotation/CreateGroup.java
new file mode 100644
index 0000000..7eaae29
--- /dev/null
+++ b/src/main/java/com/svnlan/annotation/CreateGroup.java
@@ -0,0 +1,11 @@
+package com.svnlan.annotation;
+
+import javax.validation.groups.Default;
+
+/**
+ * 创建组
+ *
+ * @author lingxu 2023/05/16 16:46
+ */
+public interface CreateGroup extends Default {
+}
diff --git a/src/main/java/com/svnlan/annotation/EnableVisitRecord.java b/src/main/java/com/svnlan/annotation/EnableVisitRecord.java
new file mode 100644
index 0000000..a9be02f
--- /dev/null
+++ b/src/main/java/com/svnlan/annotation/EnableVisitRecord.java
@@ -0,0 +1,21 @@
+package com.svnlan.annotation;
+
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.context.annotation.Import;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+import java.lang.annotation.*;
+
+/**
+ * 开启访问数统计
+ *
+ * @author lingxu 2023/04/11 15:57
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Import(MyImportSelector.class)
+@EnableAspectJAutoProxy(exposeProxy = true,proxyTargetClass = true)
+@EnableScheduling
+public @interface EnableVisitRecord {
+}
diff --git a/src/main/java/com/svnlan/annotation/MyImportSelector.java b/src/main/java/com/svnlan/annotation/MyImportSelector.java
new file mode 100644
index 0000000..cc04914
--- /dev/null
+++ b/src/main/java/com/svnlan/annotation/MyImportSelector.java
@@ -0,0 +1,18 @@
+package com.svnlan.annotation;
+
+import com.svnlan.interceptor.VisitRecordAop;
+import com.svnlan.utils.timer.VisitRecordSchedule;
+import org.springframework.context.annotation.ImportSelector;
+import org.springframework.core.type.AnnotationMetadata;
+
+/**
+ * 自定义注入类
+ *
+ * @author lingxu 2023/04/11 16:02
+ */
+public class MyImportSelector implements ImportSelector {
+ @Override
+ public String[] selectImports(AnnotationMetadata importingClassMetadata) {
+ return new String[]{VisitRecordAop.class.getName(), VisitRecordSchedule.class.getName()};
+ }
+}
diff --git a/src/main/java/com/svnlan/annotation/SpecifiedValue.java b/src/main/java/com/svnlan/annotation/SpecifiedValue.java
new file mode 100644
index 0000000..fbabc64
--- /dev/null
+++ b/src/main/java/com/svnlan/annotation/SpecifiedValue.java
@@ -0,0 +1,14 @@
+package com.svnlan.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 指定值 注解
+ *
+ * @author lingxu 2023/06/13 10:48
+ */
+@Target({ElementType.PARAMETER,ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface SpecifiedValue {
+}
diff --git a/src/main/java/com/svnlan/annotation/UpdateGroup.java b/src/main/java/com/svnlan/annotation/UpdateGroup.java
new file mode 100644
index 0000000..3db3306
--- /dev/null
+++ b/src/main/java/com/svnlan/annotation/UpdateGroup.java
@@ -0,0 +1,11 @@
+package com.svnlan.annotation;
+
+import javax.validation.groups.Default;
+
+/**
+ * 修改组
+ *
+ * @author lingxu 2023/05/16 16:46
+ */
+public interface UpdateGroup extends Default {
+}
diff --git a/src/main/java/com/svnlan/annotation/VisitHandler.java b/src/main/java/com/svnlan/annotation/VisitHandler.java
new file mode 100644
index 0000000..502f4f1
--- /dev/null
+++ b/src/main/java/com/svnlan/annotation/VisitHandler.java
@@ -0,0 +1,11 @@
+package com.svnlan.annotation;
+
+/**
+ * 当访问时的处理器
+ *
+ * @author lingxu 2023/06/13 10:25
+ */
+public interface VisitHandler {
+
+ void handle(Object value);
+}
diff --git a/src/main/java/com/svnlan/annotation/VisitRecord.java b/src/main/java/com/svnlan/annotation/VisitRecord.java
new file mode 100644
index 0000000..775369b
--- /dev/null
+++ b/src/main/java/com/svnlan/annotation/VisitRecord.java
@@ -0,0 +1,92 @@
+package com.svnlan.annotation;
+
+import org.springframework.data.util.Pair;
+
+import java.lang.annotation.*;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Supplier;
+
+
+/**
+ * 访问记录
+ *
+ * @author lingxu 2023/04/06 16:53
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface VisitRecord {
+
+ /**
+ * 是否需要异步
+ */
+ boolean isAsync() default true;
+
+ /**
+ * 时间类型
+ */
+ TimeType[] timeType() default {TimeType.MILLI_SECOND, TimeType.DAY};
+
+ /**
+ * 记录哪种类型数据
+ */
+ RecordType[] recordType() default {RecordType.ALL};
+
+ /**
+ * 是否需要处理访问数
+ */
+ boolean handle() default false;
+
+ enum RecordType {
+ // 设备类型
+ CLIENT_TYPE,
+ // 操作系统类型
+ OS_NAME,
+ // 所有类型
+ ALL;
+ }
+
+ enum TimeType {
+ // 按天记录
+ DAY,
+ // 按小时记录
+ HOUR,
+ // 按分钟记录
+ MINUTE,
+ // 按秒记录
+ SECOND,
+ // 按毫秒记录
+ MILLI_SECOND;
+
+ /**
+ * 判断是否在给定的数组中
+ */
+ public static boolean isContains(TimeType[] timeTypes, TimeType timeType) {
+ for (TimeType item : timeTypes) {
+ if (item == timeType) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 获取时间类型及对应的时间戳
+ *
+ * @param now 当前时间
+ * @return 时间类型及对应时间戳集合
+ */
+ public static List>> getTimeList(LocalDateTime now) {
+ List>> list = new ArrayList<>();
+ list.add(Pair.of(VisitRecord.TimeType.MILLI_SECOND, () -> now.toInstant(ZoneOffset.of("+8")).toEpochMilli()));
+ list.add(Pair.of(VisitRecord.TimeType.SECOND, () -> now.toInstant(ZoneOffset.of("+8")).getEpochSecond()));
+ list.add(Pair.of(VisitRecord.TimeType.MINUTE, () -> now.withSecond(0).withNano(0).toEpochSecond(ZoneOffset.of("+8"))));
+ list.add(Pair.of(VisitRecord.TimeType.HOUR, () -> now.withSecond(0).withNano(0).withMinute(0).toEpochSecond(ZoneOffset.of("+8"))));
+ list.add(Pair.of(VisitRecord.TimeType.DAY, () -> now.withSecond(0).withNano(0).withMinute(0).withHour(0).toEpochSecond(ZoneOffset.of("+8"))));
+ return list;
+ }
+ }
+}
diff --git a/src/main/java/com/svnlan/common/CheckResult.java b/src/main/java/com/svnlan/common/CheckResult.java
new file mode 100644
index 0000000..3b38944
--- /dev/null
+++ b/src/main/java/com/svnlan/common/CheckResult.java
@@ -0,0 +1,38 @@
+package com.svnlan.common;
+
+import io.jsonwebtoken.Claims;
+
+/**
+ * @Author: @Description:验证信息
+ */
+public class CheckResult {
+ private int errCode;
+
+ private boolean success;
+
+ private Claims claims;
+
+ public int getErrCode() {
+ return errCode;
+ }
+
+ public void setErrCode(int errCode) {
+ this.errCode = errCode;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public Claims getClaims() {
+ return claims;
+ }
+
+ public void setClaims(Claims claims) {
+ this.claims = claims;
+ }
+}
diff --git a/src/main/java/com/svnlan/common/GlobalConfig.java b/src/main/java/com/svnlan/common/GlobalConfig.java
new file mode 100644
index 0000000..0d288d1
--- /dev/null
+++ b/src/main/java/com/svnlan/common/GlobalConfig.java
@@ -0,0 +1,254 @@
+package com.svnlan.common;
+
+import java.time.format.DateTimeFormatter;
+
+/**
+ * @Author:
+ * @Description: 常量
+ */
+public class GlobalConfig {
+ public static final String COMMA_DELIMITER = ",";
+ public static final String PWD_SALT = "PJEA4DR2WS8DF651DGT";
+
+ public static final String JWT_REDIS_PREFIX = "jwt";
+ public static final String JWT_TOKEN_HASH_PRE = "jwt_token_hash_";
+
+
+ public static final String HOST_REDIS_PREFIX = "host";
+ public static final String default_disk_path_pre = "/uploads";
+
+ public static final String UPCONFIG = "upconfig.properties";
+
+ public static final String LOGIN_PASSWORD_AES_KEY = "njsdearr8h239ay3";
+ public static final String OPEN_LOGIN_PASSWORD_AES_KEY = "oi2qpe2dnwufa982";
+ //记录,判断短时间内多次登录使用
+ public static final String JWT_FAST_LOGIN_KEY_PRE = "jwt_fast_login_key_";
+ //第三方登录, 临时权限redis key前缀
+ public static final String THIRD_LOGIN_TEMP_AUTH_PRE = "thirdLoginTempAuth_";
+
+ public static final String SEVEN_DAY_CLIENT_COUNT = "seven_day_client_count_";
+ public static final String RIGHTS_API_KEY = "rights_api_hash";
+ // api token redis key
+ public static final String JWT_API_REDIS_PREFIX = "api_jwt_";
+
+
+ /** copy验证码的cookie键名 **/
+ public static final String CAPTCHA_CODE_COOKIE_KEY = "captchaCode";
+ public static final int CAPTCHA_CODE_TTL = 180; // 验证码的有效时间,秒
+ // 生成验证码图片方法 outCaptcha(),返回map中,对应的客户端的cookie的值的key
+ public static final String CAPTCHA_CODE_COOKIE_VALUE_RETURNKEY="codeCookieValue";
+ // 生成验证码图片方法 outCaptcha(),返回map中,对应的图片验证码内容的key
+ public static final String CAPTCHA_CODE_CODE_VALUE_RETURNKEY = "captchaCodeValue";
+
+
+ /** resources目录下验证码图片子目录名称 **/
+ public static final String RESOURCES_CAPTCHA_DIRECTORY = "captcha";
+ /** 验证码的cookie键名 **/
+ public static final String CAPTCHA_COOKIE_KEY = "captcha";
+ public static final int CAPTCHA_TTL = 180; // 验证码的有效时间,秒
+ // 生成验证码图片方法 outCaptcha(),返回map中,对应的客户端的cookie的值的key
+ public static final String CAPTCHA_COOKIE_VALUE_RETURNKEY="cookieValue";
+ // 生成验证码图片方法 outCaptcha(),返回map中,对应的图片验证码内容的key
+ public static final String CAPTCHA_CODE_VALUE_RETURNKEY = "captchaValue";
+
+
+ /** copy验证码的cookie键名 图形滑动验证码 **/
+ public static final String IMAGE_CAPTCHA_CODE_COOKIE_KEY = "captchaImageCode";
+ public static final int IMAGE_CAPTCHA_CODE_TTL = 180; // 验证码的有效时间,秒
+ // 生成验证码图片方法 outCaptcha(),返回map中,对应的客户端的cookie的值的key
+
+ //学习心得图片类型
+ public static final String[] STUDY_EXPERIENCE_IMAGE_TYPE = {"jpg", "jpeg", "gif", "bmp", "png", "svg"};
+
+ //课程下载
+ public static final String COURSE_DOWNLOAD_AES_KEY = "fj0j023rwdopqwpo";
+
+ //m3u8 播放AES key
+ public static final String M3U8_PLAY_AES_KEY = "dfjgj6kqdfvh89he";
+ //m3u8 播放key的分隔符
+ public static final String M3U8_PLAY_KEY_SEPARATOR = "pp&&kk&&";
+
+ public static final String ATTACHMENT_AES_KEY = "sadh8as1d032r0h0";
+ public static final String ATTACHMENT_KEY_SEPARATOR = "ff_&_gg";
+// "jpg", "jpeg", "png", "gif", "bmp", "ico", "svg", "webp", "tif", "tiff", "cdr", "svgz", "xbm", "eps", "pjepg", "heic", "raw", "psd", "ai"
+ public static final String[] IMAGE_TYPE_ARR = {"jpg", "jpeg", "png", "gif", "bmp", "ico", "svg", "webp", "tif", "tiff", "cdr", "svgz", "xbm", "eps", "pjepg", "heic", "raw", "psd", "ai"};
+ public static final String[] list_path_source_type = {"jpg", "jpeg", "png", "gif", "bmp", "ico", "svg", "webp", "tif", "tiff", "cdr", "svgz", "xbm", "eps", "pjepg", "heic", "raw", "psd", "ai", "mp3"};
+ public static final String[] IMAGE_NO_GIF_TYPE_ARR = {"jpg", "jpeg", "bmp", "png"};
+ public static final String[] IMAGE_LITE_TYPE_ARR = {"jpg", "jpeg", "png"};
+ public static final String[] IMAGE_SHOW_TYPE_ARR = {"jpg", "jpeg", "gif", "bmp", "png", "svg", "psd", "tga"};
+ public static final String[] VIDEO_SHOW_TYPE_ARR = {"flv","avi","mpeg","mpg","mp4","rmvb","rm","mov","3gp","f4v","wmv", "pmg", "mkv", "m4v"};
+ public static final String[] DOC_TYPE_ARR = {"doc", "docx", "ppt", "pptx", "pdf", "xls", "xlsx"};
+ public static final String[] yongzhong_doc_type = {"eid","docx","dotx","doc","dot","rtf","txt","uot","htm","wps","wpt"};
+ public static final String[] yongzhong_excel_type = {"eis","xlsx","xltx","xls","xlt","uos","dbf","csv","xml","et","ett"};
+ public static final String[] yongzhong_ppt_type = {"eip","pptx","potx","ppt","pot","ppsx","pps","dps","dpt","uop"};
+ public static final String[] yongzhong_doc_excel_ppt_type = {"eid","docx","dotx","doc","dot","rtf","txt","uot","htm","wps","wpt",
+ "eis","xlsx","xltx","xls","xlt","uos","dbf","csv","xml","et","ett",
+ "eip","pptx","potx","ppt","pot","ppsx","pps","dps","dpt","uop", "pdf"
+ // ,"zip","gz","rar","iso","tar","7z","ar","bz","bz2","xz", "arj"
+
+ };
+ // 相机文件 dng,nef,orf,pef,srw,x3f,srf,arw,sr2
+ //public static final String[] CAMERA_TYPE_ARR = {"cr2", "dcr", "epf", "raf", "kdc", "dcr", "dng", "nef", "orf", "pef", "tiff", "cdr", "svgz", "xbm", "eps", "pjepg", "heic", "raw", "psd", "ai"};
+ public static final String[] CAMERA_TYPE_ARR = {"arw", "mrw", "erf", "raf","cr2", "nrw", "nef", "orf", "rw2", "pef", "srf"
+ , "dcr", "kdc", "dng"};
+
+
+ public static final String[] DOC_SHOW_TYPE_ARR = {"doc", "docx", "ppt", "pptx", "pdf", "xls", "xlsx", "pps", "wps", "txt"};
+ public static final String[] AUDIO_SHOW_TYPE_ARR = {"mp3", "wav", "flac", "mpa"};
+ public static final String[] UNZIP_SHOW_TYPE_ARR = {"tar", "zip", "gzip", "bz2", "rar", "7z", "gz", "iso", "ar", "bz", "xz", "arj"};
+ public static final String[] ZIP_SHOW_TYPE_ARR = {"zip", "tar"};
+ public static final String[] VIDEO_TYPE_ARR = {"mp4", "flv", "rm", "rmvb", "avi", "mkv", "mov", "f4v", "mpeg", "mpg", "vob", "wmv", "ogv", "webm", "3gp", "mts", "m2ts", "m4v", "mpe", "3g2", "asf", "dat", "asx", "wvx"};
+ public static final String[] VIDEO_AUDIO_TYPE_CONVERT = {"mp4", "wav", "flac", "flv", "rm", "rmvb", "avi", "mkv", "mov", "f4v", "mpeg", "mpg", "vob", "wmv", "ogv", "webm", "3gp", "mts", "m2ts", "m4v", "mpe", "3g2", "asf", "dat", "asx", "wvx"};
+ public static final String[] AUDIO_VIDEO_SHOW_TYPE_ARR = {"mp4", "flv", "rm", "rmvb", "avi", "mkv", "mov", "f4v", "mpeg", "mpg", "vob", "wmv", "ogv", "webm", "3gp", "mts", "m2ts", "m4v", "mpe", "3g2", "asf", "dat", "asx", "wvx", "mpa", "mp3", "wav", "wma", "m4a", "ogg", "omf", "amr", "aa3", "flac", "aac", "cda", "aif", "aiff", "mid", "ra", "ape"};
+ public static final String CONVERT_SOURCE_ID_H5_MAP = "convert_source_id_h5";
+ public static final String CONVERT_SOURCE_ID_SWF_MAP = "convert_source_id_swf";
+ public static final String M3U8_KEY_INFO_SEPARATOR = "_&_&_";
+ public static final String M3U8_AES_PASSWORD = "vj90eu321fk01";
+
+ public static final String CLOUD_OPERATION_LOCK_KEY = "cloudOperationLock";
+
+ public static final long CHUNK_FILE_SIZE = 2 * 1024 * 1024;
+
+ //转码文件redis key
+ public static final String CONVERT_FILE_REDIS_KEY_PRE = "convert_file_";
+ //redis存2小时20分钟
+ public static final Long CONVERT_FILE_REDIS_TTL = 8400L;
+ //项目启动10分钟内
+ public static final Long RUN_TIME_OFFSET = 600000L;
+ public static final String IMAGE_LARGE_SIZE_KEY = "imageLargeSize";
+
+
+ //用户发送绑定邮件验证码发送频率限制 REDIS KEY(userId)
+ public static final String EMAIL_BIND_SEND_FREQUENCY_KEY = "email_bind_send_frequency_%d";
+ //用户发送绑定邮件验证码每日限制次数 REDIS KEY(userId)
+ public static final String EMAIL_BIND_SEND_LIMIT_KEY = "email_bind_send_limit_%d";
+
+ //用户发送绑定 同一邮箱 邮件验证码每日限制次数 REDIS KEY(userId、email)
+ public static final String SINGLE_EMAIL_BIND_SEND_LIMIT_KEY = "single_email_bind_send_limit_%d_%s";
+
+ //用户发送绑定邮件验证码每日限制次数
+ public static final Integer EMAIL_BIND_SEND_LIMIT_NUM = 10;
+
+ //用户发送绑定 同一邮箱 邮件验证码每日限制次数
+ public static final Integer SINGLE_EMAIL_BIND_SEND_LIMIT_NUM = 10;
+
+ // 缓存,用户前缀
+ public static final String REDIS_KEY_USER = "user_";
+
+ // 缓存,用户前缀
+ public static final String REDIS_KEY_USER_CODE = "user_verifyCode:";
+ public static final String REDIS_KEY_USER_STATE = "user_state_";
+ public static final String REDIS_KEY_USER_GROUP_AUTH = "user_group_auth";
+ // 普通下载定时删除redis
+ public static final String COMMON_DOWNLOAD_KEY_SET = "commonDownloadKeySet";
+
+ public static final String my_fav_key = "my_fav_key_";
+ public static final String my_tag_key = "my_tag_key_";
+ public static final String my_share_key = "my_share_key_";
+ public static final String SYSTEM_AUTH = "explorer.add,explorer.upload,explorer.view,explorer.download,explorer.share,explorer.remove,explorer.edit,explorer.move,explorer.serverDownload,explorer.search,explorer.unzip,explorer.zip,user.edit,user.fav,explorer.informationView,admin.index.dashboard,admin.index.setting,admin.index.loginLog,admin.index.log,admin.index.server,admin.role.list,admin.role.edit,admin.job.list,admin.job.edit,admin.member.list,admin.member.userEdit,admin.member.groupEdit,admin.auth.list,admin.auth.edit,admin.plugin.list,admin.plugin.edit,admin.storage.list,admin.storage.edit,admin.autoTask.list,admin.autoTask.edit,admin.index.information";
+ public static final String SYSTEM_GROUP_AUTH = "1,2,3,4,5,6,7,8,9,10,11,12,13,14";
+
+
+ public static final String oldInnerServer = "http://video.zdb9.com";
+ public static final String m3u8ConvertUrlPlaceholder = "m3u8_convert_server_url_placeholder";
+
+
+ public static final String async_key_zip_file = "async_key_zip_file:";
+ public static final String progress_key_zip_file = "progress_key_zip_file:";
+ public static final String async_key_zip_file_info = "async_key_zip_file_info:";
+
+ public static final String CONVERT_TIME_KEY = "convert_time_set";
+
+
+ public static final String file_edit_key = "file_edit_key:";
+ public static final String yzwo_file_edit_key = "yzwo_file_edit_key:";
+ public static final String separator = "\\\\";
+ public static final String separatorTO = "/";
+ public static final String systemConfig_captcha = "systemConfig_captcha";
+ public static final String userRoleAuth_key = "userRoleAuth_key";
+ public static final String yzwo_file_edit_user_key = "yzwo_file_edit_user_key:";
+
+ // 压缩预览
+ public static final String FILE_PREVIEW_COMPRESS_KEY = "compress_preview_file_key:";
+ public static final String[] DESIGN_WEB_CLIENT_TYPE_ARR = {"pc", "mb"};
+
+ // 视频编辑redis
+ public static final String video_edit_getVideoShearList = "video_edit_getVideoShearList_key_";
+
+ // 文件夹
+ public static final String dir_user_pathDisplay = "dir_user_pathDisplay_";
+ public static final String dir_group_pathDisplay = "dir_group_pathDisplay";
+
+ // 资讯导入
+ public static final String IMPORT_ARTICLE_LOCK = "importArticleLock_";
+
+ //转成图片的缓存KEY(其中%d为文件ID)
+ public static String infoConvertToJPGKey = "infoConvertToJPG_%d";
+ //转成图片的防并发的缓存KEY(其中%d为文件ID)
+ public static String concurrentConvertToJPGKey = "concurrentConvertToJPG_%d";
+
+
+ public static final DateTimeFormatter dateTimeStandardFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+ public static final DateTimeFormatter dateStandardFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ public static final String BAN_WORDS_LIB_FILE_NAME = "banWords.txt";
+
+ //(非小程序)其他最多装扮数量限制
+ public static final Integer MaxDesignCount = 100;
+
+ public static final String SEARCH_PERMISSION_KEY = "searchComponentPermission";
+ //主页,二级页后缀
+ public static final String GEN_PAGE_SUFFIX = ".shtml";
+
+ //favicon
+ public static final String FAV_ICON_FILENAME = "favicon.png";
+ public static final String FAV_ICON_PATH = "/common/";
+ //装扮url防并发
+ public static final String DESIGN_URL_LOCK_PRE = "design_url_lock";
+ public static final Long DESIGN_URL_LOCK_TTL = 5 * 1000L;
+
+
+ //扫码登录加解密的密钥
+ public static final String ScanLoginSalt = "OPjanpEaoE7ZGl9v";
+
+
+ public static final Integer scanLoginSignatureExpire = 1;
+ public static final Integer scanLoginCodeExpire = 60;
+ //扫码登录校验KEY
+ public static final String SCAN_LOGIN_CODE_REDIS_KEY = "scanLogin_";
+ public static final String logAuthUrl = "/pages/download.html";
+
+ //防并发加锁的REDIS KEY(其中%s为tempAuth)
+ public static final String ScanLoginAuth = "sla_%s";
+ public static final String mesWarning_cache_key = "mesWarning_cache_key";
+ public static final int mesWarning_cache_ttl = 8; // 消息预警缓存有效时间
+ // 消息预警判断持续redis
+ public static final String mesWarning_cpu_key = "mesWarning_cpu_key";
+ public static final String mesWarning_mem_key = "mesWarning_mem_key";
+ public static final String mesWarning_du_key = "mesWarning_du_key";
+ public static final String mesWarning_send_temp_key = "【消息预警】%s %s %s使用占比超过%s,请注意!(您可在管理后台>消息预警,关闭此提醒)";
+
+ //扫码登录的 channelId与标识ID(loginId)的关联关系 HASH REDIS KEY(%s为对应的房间roomName)
+ public static final String ScanLoginIdChannelRelation = "SLIdChannelRelation_%s";
+ //扫码登录的 APP token与 生成的临时授权码的关联关系 HASH REDIS KEY(%s为对应的房间roomName)
+ public static final String ScanLoginTempAuthRelation = "SLTempAuthRelation_%s";
+ //扫码登录的临时授权码REDIS KEY 前缀
+ public static final String ScanLoginTempAuthRedisKeyPrefix = "scanLg";
+ public static final String private_replace_key = "/{dir}/{path}/";
+
+ public static final String async_key_convert_doc_file = "async_key_convert_doc_file_";
+ public static final String progress_key_convert_doc_file = "progress_key_convert_doc_file_";
+
+ public static final String show_img_api_key = "/api/disk/video/img/";
+
+
+ public static final String async_key_unzip_file = "async_key_unzip_file_";
+ public static final String progress_key_unzip_file = "progress_key_unzip_file_";
+ public static final String temp_img_video_key = "temp_img_video_key_";
+ public static final String homeExplorerRedisKey = "homeExplorerRedisKey_";
+ public static final String homeExplorerOneRedisKey = "homeExplorerOneRedisKey_";
+ public static final String async_key_convert_img_video = "async_key_convert_img_video_";
+ public static final String progress_key_convert_img_video = "progress_key_convert_img_video_";
+
+
+
+}
diff --git a/src/main/java/com/svnlan/common/HttpSessionUtil.java b/src/main/java/com/svnlan/common/HttpSessionUtil.java
new file mode 100644
index 0000000..e287ab6
--- /dev/null
+++ b/src/main/java/com/svnlan/common/HttpSessionUtil.java
@@ -0,0 +1,43 @@
+package com.svnlan.common;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Component
+public class HttpSessionUtil {
+ private static final String LANGAUAGE_KEY = "Language"; //lang-country
+
+ @Autowired
+ private HttpServletRequest request;
+ @Autowired
+ private HttpServletResponse response;
+
+ public HttpSessionUtil() {
+ }
+
+ public HttpServletResponse getResponse() {
+ return this.response;
+ }
+
+ public HttpServletRequest getRequest() {
+ return this.request;
+ }
+
+ public String getLanage() {
+ try {
+ return this.request.getHeader(LANGAUAGE_KEY);
+ } catch (Exception var2) {
+ return null;
+ }
+ }
+
+ public String getRequestId() {
+ try {
+ return this.request.getHeader("REQUESTID");
+ } catch (Exception var2) {
+ return null;
+ }
+ }
+
+}
diff --git a/src/main/java/com/svnlan/common/I18nUtils.java b/src/main/java/com/svnlan/common/I18nUtils.java
new file mode 100644
index 0000000..49094fa
--- /dev/null
+++ b/src/main/java/com/svnlan/common/I18nUtils.java
@@ -0,0 +1,86 @@
+package com.svnlan.common;
+
+import lombok.NonNull;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.MessageSource;
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.springframework.stereotype.Component;
+
+import java.util.Locale;
+
+import javax.annotation.Resource;
+
+/**
+ * @Author: sulijuan
+ * @Description: @Autowired 自动装配仅在托管类中有效(例如,注释为@ Component,@ Service或在应用程序上下文xml中定义)。
+ * @Date: 2023/2/6 15:01
+ */
+@Component
+@Slf4j
+public class I18nUtils {
+
+ // 如果当前bean不加@Component注解,则messageSource无法注入,始终为null
+ private static MessageSource messageSource;
+ private static HttpSessionUtil httpSessionUtil;
+
+ @Autowired
+ public void setMessageSource(MessageSource messageSource) {
+ I18nUtils.messageSource = messageSource;
+ }
+ @Autowired
+ public void setHttpSessionUtil(HttpSessionUtil httpSessionUtil) {
+ I18nUtils.httpSessionUtil = httpSessionUtil;
+ }
+ /**
+ * 解析code对应的信息进行返回,如果对应的code不能被解析则抛出异常NoSuchMessageException
+ *
+ * @param code 需要进行解析的code,对应资源文件中的一个属性名
+ * @param args 当对应code对应的信息不存在时需要返回的默认值
+ * @return 国际化翻译值
+ */
+ public static String i18n(String code, Object... args) {
+ return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
+ }
+ /**
+ * 解析code对应的信息进行返回,如果对应的code不能被解析则抛出异常NoSuchMessageException
+ *
+ * @param locale 需要转换的语言
+ * @param code 需要进行解析的code,对应资源文件中的一个属性名
+ * @param args 当对应code对应的信息不存在时需要返回的默认值
+ * @return 国际化翻译值
+ */
+ public static String i18n(Locale locale, String code, Object... args) {
+ return messageSource.getMessage(code, args, locale);
+ }
+ /**
+ * 解析code对应的信息进行返回,如果对应的code不能被解析则返回默认信息defaultMessage。
+ *
+ * @param code 需要进行解析的code,对应资源文件中的一个属性名
+ * @param defaultMessage 当对应code对应的信息不存在时需要返回的默认值
+ * @param args 需要用来替换code对应的信息中包含参数的内容,如:{0},{1,date},{2,time}
+ * @return 对应的Locale
+ */
+ public static String i18nOrDefault(String code, String defaultMessage, Object... args) {
+ return messageSource.getMessage(code, args, defaultMessage, LocaleContextHolder.getLocale());
+ }
+
+ /**
+ * 因为i18n方法如果获取不到对应的键值,会抛异常NoSuchMessageException
+ * 本方法是对i18n方法的封装。当报错时并不抛出异常,而是返回source
+ *
+ * @param source 模板
+ * @param args 参数
+ * @return 返回I18n(正常结束)或者source(抛出异常)
+ * @see #i18n(String, Object...)
+ */
+ public static String tryI18n(@NonNull String source, @NonNull Object... args) {
+ String res;
+ try {
+ res = i18n(source, args);
+ } catch (Exception ignored) {
+ res = source;
+ }
+ return res;
+ }
+}
diff --git a/src/main/java/com/svnlan/common/LogScheduleStateConstants.java b/src/main/java/com/svnlan/common/LogScheduleStateConstants.java
new file mode 100644
index 0000000..2b8724c
--- /dev/null
+++ b/src/main/java/com/svnlan/common/LogScheduleStateConstants.java
@@ -0,0 +1,12 @@
+package com.svnlan.common;
+
+/**
+ * @Author:
+ * @Date:
+ * @Description:
+ */
+public class LogScheduleStateConstants {
+ public static final String UNSTART = "0";
+ public static final String SUCCESS = "1";
+ public static final String FAILURE = "2";
+}
diff --git a/src/main/java/com/svnlan/common/Result.java b/src/main/java/com/svnlan/common/Result.java
new file mode 100644
index 0000000..fa5b7a9
--- /dev/null
+++ b/src/main/java/com/svnlan/common/Result.java
@@ -0,0 +1,166 @@
+package com.svnlan.common;
+
+import com.svnlan.exception.CodeMessageEnum;
+import com.svnlan.exception.SvnlanRuntimeException;
+import org.springframework.util.ObjectUtils;
+
+import java.io.Serializable;
+
+/** @Author: @Description: */
+public class Result implements Serializable {
+
+ private static final long serialVersionUID = -1L;
+
+ /** 状态码 */
+ private Boolean success;
+
+ /** 结果消息 */
+ private String message;
+
+ /** 错误码 */
+ private String code;
+
+ /** 返回的数据 */
+ private Object data;
+
+ private Long timeStamp;
+
+ /**
+ * 构造函数
+ * @param code
+ * @param data
+ */
+ public Result(String code, Object data) {
+ this(true, code, data);
+ }
+ public Result(boolean success, String code, Object data) {
+ this.success = success;
+ this.message = I18nUtils.i18n(code);
+ this.code = code;
+ this.data = data;
+ this.timeStamp = System.currentTimeMillis();
+ }
+
+ public Result(boolean success, String code,String message) {
+ this.success = success;
+ if (ObjectUtils.isEmpty(message)) {
+ this.message = I18nUtils.i18n(code);
+ }else {
+ this.message = message;
+ }
+ this.code = code;
+ this.data = message;
+ this.timeStamp = System.currentTimeMillis();
+ }
+
+ public Result(boolean success, String code,String message, boolean isFmt) {
+ this.success = success;
+ if (isFmt){
+ String m = I18nUtils.i18n(code);
+ this.message = String.format(m,message);
+ }else {
+ this.message = I18nUtils.i18n(code);
+ }
+ this.code = code;
+ this.timeStamp = System.currentTimeMillis();
+ }
+
+ public Result(boolean success, String message) {
+ this.success = success;
+ this.message = message;
+ this.code = "-1";
+ this.timeStamp = System.currentTimeMillis();
+ }
+
+ public Result(boolean success, String code, String message, Object data) {
+ this.success = success;
+ this.message = message;
+ if (ObjectUtils.isEmpty(message)){
+ this.message = I18nUtils.i18n(code);
+ }
+ this.code = code;
+ this.data = data;
+ this.timeStamp = System.currentTimeMillis();
+ }
+
+ public static long getSerialVersionUID() {
+ return serialVersionUID;
+ }
+
+ public Boolean getSuccess() {
+ return success;
+ }
+
+ public void setSuccess(Boolean success) {
+ this.success = success;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public Long getTimeStamp() {
+ return timeStamp;
+ }
+
+ public void setTimeStamp(Long timeStamp) {
+ this.timeStamp = timeStamp;
+ }
+
+ /**
+ * 返回自定义异常
+ *
+ * @param e
+ * @return
+ */
+ public static Result returnSvnException(SvnlanRuntimeException e) {
+ return new Result(Boolean.FALSE, e.getErrorCode(), null);
+ }
+
+ /**
+ * 返回失败
+ *
+ * @param codeMessageEnum
+ * @return
+ */
+ public static Result returnError(CodeMessageEnum codeMessageEnum) {
+ return new Result(Boolean.FALSE, codeMessageEnum.getCode(), null);
+ }
+
+ public static Result returnError(String message) {
+ return new Result(Boolean.FALSE, message);
+ }
+ /**
+ * 返回成功
+ *
+ * @param data
+ * @return
+ */
+ public static Result returnSuccess(Object data) {
+ return new Result(Boolean.TRUE, CodeMessageEnum.success.getCode(), data);
+ }
+
+ public static Result returnSuccess() {
+ return new Result(Boolean.TRUE, CodeMessageEnum.success.getCode(), null);
+ }
+}
diff --git a/src/main/java/com/svnlan/config/MybatisConfig.java b/src/main/java/com/svnlan/config/MybatisConfig.java
new file mode 100644
index 0000000..6ba89fb
--- /dev/null
+++ b/src/main/java/com/svnlan/config/MybatisConfig.java
@@ -0,0 +1,60 @@
+package com.svnlan.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
+import com.github.pagehelper.PageHelper;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+import java.util.Properties;
+
+/**
+ * mybatis配置
+ *
+ * @author lingxu 2023/05/25 10:02
+ */
+@Configuration
+public class MybatisConfig {
+ /**
+ * mp 分页插件
+ */
+ @Bean
+ public PaginationInterceptor paginationInterceptor() {
+ PaginationInterceptor interceptor = new PaginationInterceptor();
+ interceptor.setDialectType(DbType.MYSQL.getDb());
+ return interceptor;
+ }
+
+ /**
+ * 性能分析插件
+ */
+ @Bean
+ @Profile({"dev", "test"})
+ public PerformanceInterceptor performanceInterceptor() {
+ PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
+ performanceInterceptor.setMaxTime(15000);
+ performanceInterceptor.setFormat(false);
+ return performanceInterceptor;
+ }
+
+ /**
+ * 功能描述: 配置mybatis的分页插件pageHelper
+ *
+ * @param:
+ * @return:
+ */
+ @Bean
+ public PageHelper pageHelper() {
+ PageHelper pageHelper = new PageHelper();
+ Properties properties = new Properties();
+ properties.setProperty("offsetAsPageNum", "true");
+ properties.setProperty("rowBoundsWithCount", "true");
+ properties.setProperty("reasonable", "false");
+ //配置mysql数据库的方言
+ properties.setProperty("dialect", "mysql");
+ pageHelper.setProperties(properties);
+ return pageHelper;
+ }
+}
diff --git a/src/main/java/com/svnlan/config/RedisConfig.java b/src/main/java/com/svnlan/config/RedisConfig.java
new file mode 100644
index 0000000..4aaec7d
--- /dev/null
+++ b/src/main/java/com/svnlan/config/RedisConfig.java
@@ -0,0 +1,114 @@
+package com.svnlan.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.ClusterServersConfig;
+import org.redisson.config.Config;
+import org.redisson.config.SingleServerConfig;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * redis配置
+ *
+ * @author lingxu 2023/04/07 10:11
+ */
+@Configuration
+public class RedisConfig {
+
+
+ //读取配置文件中redis的配置
+// @Bean
+// @ConfigurationProperties(prefix = "spring.redis")
+// public JedisConnectionFactory jedisConnectionFactory() {
+// return new JedisConnectionFactory();
+// }
+
+ @Bean
+ public RedisTemplate redisTemplate(LettuceConnectionFactory factory) {
+ //String
+ StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
+
+ //JdkSerialization
+ //JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSgiterializationRedisSerializer();
+
+ //Jackson2Json
+ Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
+ ObjectMapper om = new ObjectMapper();
+ //PropertyAccessor.ALL:所有;JsonAutoDetect.Visibility.ANY修饰范围:ANY-所有
+ om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+ //指定序列化输入的类型,类必须是非final修饰的
+ om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
+ jackson2JsonRedisSerializer.setObjectMapper(om);
+
+ RedisTemplate template = new RedisTemplate<>();
+ //连接工厂
+ template.setConnectionFactory(factory);
+ //全局key的序列化策略
+ template.setKeySerializer(stringRedisSerializer);
+ //全局value的序列化策略
+ template.setValueSerializer(jackson2JsonRedisSerializer);
+ //全局HashKey的序列化策略
+ template.setHashKeySerializer(stringRedisSerializer);
+ //全局HashValue的序列化策略
+ template.setHashValueSerializer(jackson2JsonRedisSerializer);
+ //支持事务
+ template.setEnableTransactionSupport(true);
+ template.afterPropertiesSet();
+ return template;
+ }
+
+ @Resource
+ private Environment environment;
+
+ // 这些环境的 redis 配置将被认做 single
+ private static final List redisSingleList = Arrays.asList("local", "dev", "pro", "pufay");
+
+ @ConditionalOnBean(name = "redisTemplate")
+ @Bean(destroyMethod = "shutdown")
+ public RedissonClient redissonClient(RedisProperties redisProperties) {
+ // 创建配置 指定redis地址及节点信息
+ Config config = new Config();
+ if (Arrays.stream(environment.getActiveProfiles()).anyMatch(redisSingleList::contains)) {
+ SingleServerConfig singleServerConfig = config.useSingleServer()
+ .setDatabase(redisProperties.getDatabase())
+ .setAddress("redis://" + redisProperties.getHost() + ":" + redisProperties.getPort());
+ if (StringUtils.hasText(redisProperties.getPassword())) {
+ singleServerConfig.setPassword(redisProperties.getPassword());
+ }
+ } else {
+ ClusterServersConfig clusterServersConfig = config.useClusterServers();
+ for (String node : redisProperties.getCluster().getNodes()) {
+ clusterServersConfig
+ .addNodeAddress("redis://" + node);
+ }
+ clusterServersConfig.setScanInterval(2000);
+ if (StringUtils.hasText(redisProperties.getPassword())) {
+ clusterServersConfig.setPassword(redisProperties.getPassword());
+ }
+ }
+
+
+ // 根据config创建出RedissonClient实例
+ return Redisson.create(config);
+ }
+
+}
diff --git a/src/main/java/com/svnlan/enums/AdminDocAuthEnum.java b/src/main/java/com/svnlan/enums/AdminDocAuthEnum.java
new file mode 100644
index 0000000..31eb9b2
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/AdminDocAuthEnum.java
@@ -0,0 +1,49 @@
+package com.svnlan.enums;
+
+/**
+ * @Author:
+ * @Description:
+ */
+public enum AdminDocAuthEnum {
+
+ show(1, "admin.auth.show", "文件列表"),
+ showAction(2, "admin.auth.showAction", "文件列表查看"),
+ view(3, "admin.auth.view", "文件预览"),
+ viewAction(4, "admin.auth.viewAction", "文件打开预览"),
+ download(5, "admin.auth.download", "下载/复制"),
+ downloadAction(6, "admin.auth.downloadAction", "下载/复制/文件预览打印"),
+ uploadAction(7, "admin.auth.uploadAction", "文件(夹)上传/远程下载"),
+ edit(8, "admin.auth.edit", "编辑新建"),
+ editAction(9, "admin.auth.editAction", "新建文件(夹)/重命名/粘贴到文件夹/编辑文件/设置备注/创建副本/解、压缩"),
+ removeAction(10, "admin.auth.removeAction", "剪切/复制/移动"),
+ shareAction(11, "admin.auth.shareAction", "外链分享/与他人协作分享"),
+ comment(12, "admin.auth.comment", "文档评论"),
+ commentAction(13, "admin.auth.commentAction", "文档评论查看;添加/删除自己的评论(需编辑权限)"),
+ event(14, "admin.auth.event", "文档动态"),
+ eventAction(15, "admin.auth.eventAction", "文档动态查看、订阅动态"),
+ root(16, "admin.auth.root", "管理权限"),
+ rootAction(17, "admin.auth.rootAction", "设置成员权限/评论管理/历史版本管理"),
+ ;
+
+ private int id;
+
+ private String code;
+
+ private String value;
+
+ AdminDocAuthEnum(int id,String code, String value) {
+ this.id = id;
+ this.code = code;
+ this.value = value;
+ }
+
+ public int getId() { return id; }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/AuthEnum.java b/src/main/java/com/svnlan/enums/AuthEnum.java
new file mode 100644
index 0000000..91f6186
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/AuthEnum.java
@@ -0,0 +1,101 @@
+package com.svnlan.enums;
+
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/6 16:30
+ */
+public enum AuthEnum {
+
+ explorerAdd(1, "explorer.add", ""),
+ explorerUpload(2, "explorer.upload", ""),
+ explorerView(3, "explorer.view", ""),
+ explorerDownload(4, "explorer.download", ""),
+ explorerShare(5, "explorer.share", ""),
+ explorerRemove(6, "explorer.remove", ""),
+ explorerEdit(7, "explorer.edit", ""),
+ explorerMove(8, "explorer.move", ""),
+ explorerServerDownload(9, "explorer.serverDownload", ""),
+ explorerSearch(10, "explorer.search", ""),
+ explorerUnzip(11, "explorer.unzip", ""),
+ explorerZip(12, "explorer.zip", ""),
+
+ userEdit(13, "user.edit", ""),
+ userFav(14, "user.fav", ""),
+
+ adminIndexDashboard(15, "admin.index.dashboard", ""),
+ adminIndexSetting(16, "admin.index.setting", ""),
+ adminIndexLoginLog(17, "admin.index.loginLog", ""),
+ adminIndexLog(18, "admin.index.log", ""),
+ adminIndexServer(19, "admin.index.server", ""),
+ adminRoleList(20, "admin.role.list", ""),
+ adminRoleEdit(21, "admin.role.edit", ""),
+ adminJobList(22, "admin.job.list", ""),
+ adminJobEdit(23, "admin.job.edit", ""),
+ adminMemberList(24, "admin.member.list", ""),
+ adminMemberUserEdit(25, "admin.member.userEdit", ""),
+ adminMemberGroupEdit(26, "admin.member.groupEdit", ""),
+ adminAuthList(26, "admin.auth.list", ""),
+ adminAuthEdit(27, "admin.auth.edit", ""),
+ adminPluginList(28, "admin.plugin.list", ""),
+ adminPluginEdit(29, "admin.plugin.edit", ""),
+ adminStorageList(28, "admin.storage.list", ""),
+ adminStorageEdit(29, "admin.storage.edit", ""),
+ adminAutoTaskList(28, "admin.autoTask.list", ""),
+ adminAutoTaskEdit(29, "admin.autoTask.edit", ""),
+ adminIndexInfo(30, "admin.index.information", ""),
+ explorerInfoView(31, "explorer.informationView", ""),
+ ;
+
+ private int id;
+
+ private String code;
+
+ private String value;
+
+ public static List authList = Arrays.stream(values()).map(AuthEnum::getCode).collect(Collectors.toList());
+
+ AuthEnum(int id, String code, String value) {
+ this.id = id;
+ this.code = code;
+ this.value = value;
+ }
+
+ public static Map getUserAuthMap(String userAuth){
+ List aList = !ObjectUtils.isEmpty(userAuth) ? Arrays.asList(userAuth.split(",")).stream().map(String::valueOf).collect(Collectors.toList()) : null;
+ Map userAuthMap = new HashMap<>(1);
+ for (String code : authList){
+ int auth = 0;
+ if (!CollectionUtils.isEmpty(aList) && aList.contains(code)){
+ auth = 1;
+ }
+ userAuthMap.put(code , auth);
+ }
+ return userAuthMap;
+ }
+
+ public static boolean contains(String busType) {
+ return authList.contains(busType);
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/BusinessTypeEnum.java b/src/main/java/com/svnlan/enums/BusinessTypeEnum.java
new file mode 100644
index 0000000..6fa9aa5
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/BusinessTypeEnum.java
@@ -0,0 +1,26 @@
+package com.svnlan.enums;
+
+/**
+ * @description: 业务类型
+ */
+public enum BusinessTypeEnum {
+
+ COMMON("common", "通用"),
+ SCAN_LOGIN("scanLogin", "扫码登录");
+
+ private String code;
+ private String text;
+
+ BusinessTypeEnum(String code, String text) {
+ this.code = code;
+ this.text = text;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getText() {
+ return text;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/ClientTypeEnum.java b/src/main/java/com/svnlan/enums/ClientTypeEnum.java
new file mode 100644
index 0000000..f10d6db
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/ClientTypeEnum.java
@@ -0,0 +1,64 @@
+package com.svnlan.enums;
+
+import org.springframework.util.CollectionUtils;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/24 16:32
+ */
+public enum ClientTypeEnum {
+ // 1pc , 2h5, 3安卓app, 4 ios-app, 5小程序 6电脑app
+ pc("1", "pc"),
+ h5("2", "h5"),
+ android("3", "安卓"),
+ ios("4", "ios"),
+ mini("5", "小程序"),
+ pcApp("6", "pc app"),
+ other("7", "其他"),
+ ;
+
+
+ private String code;
+
+ private String value;
+
+ /**
+ * 获取所有枚举的 code 集合
+ */
+ public static List getCodeList() {
+ return Arrays.stream(ClientTypeEnum.values()).map(it -> it.code).collect(Collectors.toList());
+ }
+
+ /**
+ * 获取所有枚举的 code 集合
+ * @param exclude 需要排除的类型
+ */
+ public static List getCodeList(List exclude) {
+ return Arrays.stream(ClientTypeEnum.values())
+ .filter(it -> {
+ if (CollectionUtils.isEmpty(exclude)) {
+ return true;
+ }
+ return !exclude.contains(it.code);
+ })
+ .map(it -> it.code).collect(Collectors.toList());
+ }
+
+ ClientTypeEnum(String code, String value) {
+ this.code = code;
+ this.value = value;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/DocumentTypeEnum.java b/src/main/java/com/svnlan/enums/DocumentTypeEnum.java
new file mode 100644
index 0000000..ce124ae
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/DocumentTypeEnum.java
@@ -0,0 +1,93 @@
+package com.svnlan.enums;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/14 14:25
+ */
+public enum DocumentTypeEnum {
+
+ // 文档
+ doc("doc", 1, "explorer.type.doc", "txt,md,pdf,ofd,doc,docx,xls,xlsx,ppt,pptx,xps,pps,ppsx,ods,odt,odp,docm,dot,dotm,xlsb,xlsm,mht,djvu,wps,dpt,csv,et,ett,pages,numbers,key,dotx,vsd,vsdx,mpp", "doc"),
+ // 图片
+ image("image", 2, "explorer.type.image", "jpg,jpeg,png,gif,bmp,ico,svg,webp,tif,tiff,cdr,svgz,xbm,eps,pjepg,heic,raw,psd,ai", "image"),
+ // 音乐
+ music("music", 3, "explorer.type.music", "mp3,wav,wma,m4a,ogg,omf,amr,aa3,flac,aac,cda,aif,aiff,mid,ra,ape,mpa", "music"),
+ // 视频
+ movie("movie", 4, "explorer.type.movie", "mp4,flv,rm,rmvb,avi,mkv,mov,f4v,mpeg,mpg,vob,wmv,ogv,webm,3gp,mts,m2ts,m4v,mpe,3g2,asf,dat,asx,wvx", "movie"),
+ // 压缩包
+ zip("zip", 5, "explorer.type.zip", "zip,gz,rar,iso,tar,7z,ar,bz,bz2,xz,arj", "zip"),
+ // 其他
+ others("other", 6, "explorer.type.others", "swf,html,exe,msi", "other"),
+ ;
+
+ private String code;
+
+ private Integer type;
+
+ private String value;
+
+ private String ext;
+ private String icon;
+
+ DocumentTypeEnum(String code, Integer type, String value, String ext, String icon) {
+ this.type = type;
+ this.ext = ext;
+ this.code = code;
+ this.value = value;
+ this.icon = icon;
+ }
+
+ private static final Map fileExtMap = new HashMap<>();
+
+ static {
+ for (DocumentTypeEnum typeEnum : DocumentTypeEnum.values()) {
+ String[] split = typeEnum.ext.split(",");
+ for (String ext : split) {
+ fileExtMap.put(ext, typeEnum.type);
+ }
+ }
+ }
+
+ /**
+ * 通过文件后缀获取文件类型
+ *
+ * @param ext 文件后缀
+ * @return 文件类型
+ */
+ public static Integer getTypeByExt(String ext) {
+// for (DocumentTypeEnum documentTypeEnum : DocumentTypeEnum.values()) {
+// if (documentTypeEnum.ext.contains(ext)) {
+// return documentTypeEnum.getType();
+// }
+// }
+
+ // 默认为其他类型
+// return others.getType();
+ return Optional.ofNullable(fileExtMap.get(ext)).orElse(others.getType());
+ }
+
+ public Integer getType() {
+ return type;
+ }
+
+ public String getIcon() {
+ return icon;
+ }
+
+ public String getExt() {
+ return ext;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/EventEnum.java b/src/main/java/com/svnlan/enums/EventEnum.java
new file mode 100644
index 0000000..f60033a
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/EventEnum.java
@@ -0,0 +1,46 @@
+package com.svnlan.enums;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/14 11:25
+ */
+public enum EventEnum {
+ mkdir("create", "mkdir"),
+ mkfile("create", "mkfile"),
+ upload("create", "upload"),
+ uploadNew("create", "uploadNew"),
+ copy("create", "copy"),
+ rename("rename", "rename"),
+ recycle("recycle", "toRecycle"),
+ restore("recycle", "restore"),
+ addDesc("addDesc", "addDesc"),
+ shareToAdd("share", "shareToAdd"),
+ edit("edit", "edit"),
+ remove("remove", "remove"),
+ shareLinkAdd("share", "shareLinkAdd"),
+ shareLinkRemove("share", "shareLinkRemove"),
+ shareEdit("share", "shareEdit"),
+ shareLinkEdit("share", "shareLinkEdit"),
+ shareToRemove("share", "shareToRemove"),
+ rollBack("rollBack", "rollBack"),
+ ;
+
+
+ private String code;
+
+ private String value;
+
+ private EventEnum(String code, String value) {
+ this.code = code;
+ this.value = value;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/FindTypeEnum.java b/src/main/java/com/svnlan/enums/FindTypeEnum.java
new file mode 100644
index 0000000..cca90d1
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/FindTypeEnum.java
@@ -0,0 +1,38 @@
+package com.svnlan.enums;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ */
+public enum FindTypeEnum {
+
+ MOBILE("1", "手机"),
+
+ EMAIL("2", "邮箱"),
+
+ WXLOGIN("3", "微信"),
+
+ QQLOGIN("4", "qq登录"),
+
+ WEIBOLOGIN("5", "微博"),
+
+ ALILOGIN("6", "支付宝");
+
+ private String code;
+
+ private String value;
+
+ FindTypeEnum(String code, String value) {
+ this.code = code;
+ this.value = value;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+}
diff --git a/src/main/java/com/svnlan/enums/GroupMetaEnum.java b/src/main/java/com/svnlan/enums/GroupMetaEnum.java
new file mode 100644
index 0000000..5582309
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/GroupMetaEnum.java
@@ -0,0 +1,44 @@
+package com.svnlan.enums;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/10 17:04
+ */
+public enum GroupMetaEnum {
+ namePinyin(1, "namePinyin"),
+ namePinyinSimple(2, "namePinyinSimple"),
+ authShowType(3, "authShowType"),
+ authShowGroup(4, "authShowGroup"),
+ ;
+ private Integer code;
+
+ private String value;
+
+ public static List keyList = Arrays.stream(values()).map(GroupMetaEnum::getValue).collect(Collectors.toList());
+
+ public static List delKeyList(){
+ return Arrays.asList(namePinyin.value, namePinyinSimple.value, authShowType.value, authShowGroup.value);
+ }
+
+ public static boolean contains(String value) {
+ return keyList.contains(value);
+ }
+
+ GroupMetaEnum(Integer code, String value) {
+ this.code = code;
+ this.value = value;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/LogTypeEnum.java b/src/main/java/com/svnlan/enums/LogTypeEnum.java
new file mode 100644
index 0000000..7efe2f0
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/LogTypeEnum.java
@@ -0,0 +1,93 @@
+package com.svnlan.enums;
+
+import com.svnlan.common.I18nUtils;
+import org.springframework.util.ObjectUtils;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/4 11:41
+ */
+public enum LogTypeEnum {
+
+
+ authEdit(1, "admin.auth.edit", "", ""),
+ authRemove(2, "admin.auth.remove", "", ""),
+ groupEdit(3, "admin.group.edit", "", ""),
+ memberAdd(4, "admin.member.add", "", ""),
+ memberEdit(5, "admin.member.edit", "", ""),
+ roleAdd(6, "admin.role.add", "", ""),
+ roleEdit(7, "admin.role.edit", "", ""),
+ fileDownload(8, "explorer.index.fileDownload", "文件下载", "admin.log.downFile"),
+ fileEdit(9, "file.edit", "编辑文件", "admin.log.editFile"),
+ fileMkDir(10, "file.mkdir", "新建文件夹", "log-type-create-mkdir"),
+ fileMkFile(11, "file.mkfile", "新建文件", "log-type-create-mkfile"),
+ fileRemove(12, "file.remove", "删除文件", "admin.log.delFile"),// 彻底删除文件
+ fileRename(13, "file.rename", "重命名", "log-type-rename"),
+ fileshareEdit(14, "file.shareEdit", "编辑协作", ""),
+ fileShareLinkAdd(15, "file.shareLinkAdd", "外链分享", "log.file.shareLink"),
+ fileShareToAdd(16, "file.shareToAdd", "协作分享", "log.file.shareTo"),
+ fileShareToRemove(17, "file.shareToRemove", "取消协作分享", "admin.log.delShareTo"),
+ fileToRecycle(18, "file.toRecycle", "移到回收站", "log-type-recycle-toRecycle"),
+ fileUpload(19, "file.upload", "上传文件", "log-type-create-upload"),
+ loginSubmit(20, "user.index.loginSubmit", "登录", "common.login"),
+ logout(21, "user.index.logout", "退出", "explorer.toolbar.uiLogout"),
+ restore(22, "file.restore", "还原回收站", "explorer.recycleRestore"),
+ copy(23, "file.copy", "文件复制", "admin.role.readCopy"),
+ favDel(24, "explorer.fav.del", "取消收藏", "explorer.delFav"),
+ favAdd(25, "explorer.fav.add", "添加收藏", "explorer.addFav"),
+ move(26, "file.move", "移动文件", "log-type-move"),
+ moveOut(27, "file.moveOut", "移走文件", "log-type-moveOut"),
+ shareLinkRemove(28, "file.shareLinkRemove", "取消外链分享", "admin.log.delLinkTo"),
+ fileShareLinkEdit(15, "file.shareLinkEdit", "编辑分享", "log-type-share-shareEdit"),
+
+ wechatBind(30, "wechat.bind", "", ""),
+
+ wechatUnbind(31, "wechat.unbind", "", ""),
+ zipDownload(32, "explorer.index.zipDownload", "文件夹下载", "admin.log.downFolder"),
+ fileOut(33, "explorer.index.fileOut", "", "admin.log.downFile"),
+ clearTenant(34, "tenant.clear", "租户资源清理", "admin.tenant.clear"),
+ ;
+
+ private int id;
+
+ private String code;
+
+ private String value;
+
+ private String tag;
+
+ private LogTypeEnum(int id,String code, String value, String tag) {
+ this.id = id;
+ this.code = code;
+ this.value = value;
+ this.tag = tag;
+ }
+
+ public static String getValueByCode(String code) {
+ for (LogTypeEnum itemEnum : LogTypeEnum.values()) {
+ if (itemEnum.code.equals(code) && !ObjectUtils.isEmpty(itemEnum.getTag())) {
+ return I18nUtils.i18n(itemEnum.getTag());
+ }
+ }
+ return "其他";
+ }
+
+ public String getTag() {
+ return tag;
+ }
+
+ public void setTag(String tag) {
+ this.tag = tag;
+ }
+
+ public int getId() { return id; }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/MenuEnum.java b/src/main/java/com/svnlan/enums/MenuEnum.java
new file mode 100644
index 0000000..667e04a
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/MenuEnum.java
@@ -0,0 +1,71 @@
+package com.svnlan.enums;
+
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/14 15:18
+ */
+public enum MenuEnum {
+ // 位置
+ position("common.position", "files", "", "1", "position"),
+ // 工具
+ tools("common.tools", "tools", "", "1", "tool"),
+ // 文件类型
+ fileType("common.fileType", "fileType", "explorer.pathDesc.fileType", "0", "fileType"),
+ // 标签
+ tag("common.tag", "fileTag", "explorer.pathDesc.tag", "0", "tag"),
+ ;
+ private String code;
+
+ private String type;
+
+ private String desc;
+
+ private String open;
+ private String icon;
+
+ MenuEnum(String code, String type, String desc, String open, String icon) {
+ this.code = code;
+ this.type = type;
+ this.desc = desc;
+ this.open = open;
+ this.icon = icon;
+ }
+
+ public static String getCode(String msg) {
+ for (MenuEnum codeMsg : MenuEnum.values()) {
+ if (codeMsg.type.equals(msg)) {
+ return codeMsg.code;
+ }
+ }
+ return null;
+ }
+
+ public static String getMsg(String code) {
+ for (MenuEnum codeMsg : MenuEnum.values()) {
+ if (codeMsg.code.equals(code)) {
+ return codeMsg.type;
+ }
+ }
+ return null;
+ }
+
+ public String getIcon() {
+ return icon;
+ }
+ public String getDesc() {
+ return desc;
+ }
+ public String getOpen() {
+ return open;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getType() {
+ return type;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/MetaEnum.java b/src/main/java/com/svnlan/enums/MetaEnum.java
new file mode 100644
index 0000000..8217549
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/MetaEnum.java
@@ -0,0 +1,42 @@
+package com.svnlan.enums;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/13 16:46
+ */
+public enum MetaEnum {
+ namePinyin(1, "namePinyin"),
+ namePinyinSimple(2, "namePinyinSimple"),
+ ;
+ private Integer code;
+
+ private String value;
+
+ public static List keyList = Arrays.stream(values()).map(MetaEnum::getValue).collect(Collectors.toList());
+
+ public static List delKeyList(){
+ return Arrays.asList(namePinyin.value, namePinyinSimple.value);
+ }
+
+ public static boolean contains(String value) {
+ return keyList.contains(value);
+ }
+
+ MetaEnum(Integer code, String value) {
+ this.code = code;
+ this.value = value;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/MyMenuEnum.java b/src/main/java/com/svnlan/enums/MyMenuEnum.java
new file mode 100644
index 0000000..97a5a00
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/MyMenuEnum.java
@@ -0,0 +1,44 @@
+package com.svnlan.enums;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/14 16:37
+ */
+public enum MyMenuEnum {
+ // 收藏夹
+ fav("explorer.toolbar.fav", "", "0", "fav"),
+ // 个人空间
+ rootPath("explorer.toolbar.rootPath", "explorer.pathDesc.home", "1", "space"),
+ ;
+
+ private String code;
+
+ private String desc;
+
+ private String isRoot;
+ private String icon;
+
+
+ MyMenuEnum(String code, String desc, String isRoot, String icon) {
+ this.code = code;
+ this.desc = desc;
+ this.isRoot = isRoot;
+ this.icon = icon;
+ }
+
+ public String getIcon() {
+ return icon;
+ }
+ public String getDesc() {
+ return desc;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getIsRoot() {
+ return isRoot;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/OperatingSystemEnum.java b/src/main/java/com/svnlan/enums/OperatingSystemEnum.java
new file mode 100644
index 0000000..49abba5
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/OperatingSystemEnum.java
@@ -0,0 +1,33 @@
+package com.svnlan.enums;
+
+import org.springframework.util.StringUtils;
+
+/**
+ * 操作系统
+ *
+ * @author lingxu 2023/04/17 10:35
+ */
+public enum OperatingSystemEnum {
+
+ MAC_OS_IPHONE("Mac OS X (iPhone)"),
+ ANDROID("Android"),
+ MAC_OS_X("Mac OS X"),
+ WINDOWS("Windows");
+
+ private String type;
+
+ OperatingSystemEnum(String type) {
+ this.type = type;
+ }
+
+ public static OperatingSystemEnum checkAndGet(String osName) {
+ if (StringUtils.hasText(osName)) {
+ for (OperatingSystemEnum item : OperatingSystemEnum.values()) {
+ if (osName.startsWith(item.type)) {
+ return item;
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/ScanLoginActionEnum.java b/src/main/java/com/svnlan/enums/ScanLoginActionEnum.java
new file mode 100644
index 0000000..e9f2204
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/ScanLoginActionEnum.java
@@ -0,0 +1,72 @@
+package com.svnlan.enums;
+
+/**
+ * @description: 扫码登录消息动作
+ */
+public enum ScanLoginActionEnum {
+
+ CONFIRM("confirm", "确认连接"),
+ FEED_BACK("feedBack", "反馈登录结果"),
+ AUTH("auth", "登录授权"),
+
+ SCAN("scan", "扫描成功")
+ ;
+
+ ScanLoginActionEnum(String code, String text) {
+ this.code = code;
+ this.text = text;
+ }
+
+ private String code;
+ private String text;
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * @description: 包含某CODE
+ * @param code
+ * @return java.lang.Boolean
+ */
+ public static Boolean contains(String code) {
+ Boolean exists = Boolean.FALSE;
+ for (ScanLoginActionEnum scanLoginMsgTypeEnum : ScanLoginActionEnum.values()) {
+ if(scanLoginMsgTypeEnum.getCode().equals(code)) {
+ exists = Boolean.TRUE;
+ }
+ }
+ return exists;
+ }
+
+ /**
+ * @description: 是否包含TV或WEB端发起的动作
+ * @param code
+ * @return java.lang.Boolean
+ */
+ public static Boolean containsTvWebAction(String code) {
+ Boolean exists = Boolean.FALSE;
+ if(CONFIRM.getCode().equals(code) || FEED_BACK.getCode().equals(code)) {
+ exists = Boolean.TRUE;
+ }
+ return exists;
+ }
+
+ /**
+ * @description: 是否包含APP端发起的动作
+ * @param code
+ * @return java.lang.Boolean
+ */
+ public static Boolean containsAppAction(String code) {
+ Boolean exists = Boolean.FALSE;
+ if(CONFIRM.getCode().equals(code) || AUTH.getCode().equals(code)) {
+ exists = Boolean.TRUE;
+ }
+ return exists;
+ }
+
+}
diff --git a/src/main/java/com/svnlan/enums/ScanLoginMsgTypeEnum.java b/src/main/java/com/svnlan/enums/ScanLoginMsgTypeEnum.java
new file mode 100644
index 0000000..30d0a7b
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/ScanLoginMsgTypeEnum.java
@@ -0,0 +1,44 @@
+package com.svnlan.enums;
+
+/**
+ * @description: 扫码登录消息类型
+ */
+public enum ScanLoginMsgTypeEnum {
+
+ TV_SCAN_LOGIN("tvScanLogin", "TV端"),
+ WEB_SCAN_LOGIN("webScanLogin", "web端"),
+ APP_SCAN_LOGIN("appScanLogin", "APP端")
+ ;
+
+ ScanLoginMsgTypeEnum(String code, String text) {
+ this.code = code;
+ this.text = text;
+ }
+
+ private String code;
+ private String text;
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * @description: 包含某CODE
+ * @param code
+ * @return java.lang.Boolean
+ */
+ public static Boolean contains(String code) {
+ Boolean exists = Boolean.FALSE;
+ for (ScanLoginMsgTypeEnum scanLoginMsgTypeEnum : ScanLoginMsgTypeEnum.values()) {
+ if(scanLoginMsgTypeEnum.getCode().equals(code)) {
+ exists = Boolean.TRUE;
+ }
+ }
+ return exists;
+ }
+
+}
diff --git a/src/main/java/com/svnlan/enums/SecurityTypeEnum.java b/src/main/java/com/svnlan/enums/SecurityTypeEnum.java
new file mode 100644
index 0000000..4685050
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/SecurityTypeEnum.java
@@ -0,0 +1,101 @@
+package com.svnlan.enums;
+
+import java.util.Optional;
+
+/**
+ * @Author:
+ * @Description: 安全设置类型
+ */
+public enum SecurityTypeEnum {
+
+ MOBILE("1", "mobilePhone"),
+ WECHAT("2", "wechat"),
+ QQ("3", "qq"),
+ EMAIL("4", "email"),
+ WEIBO("5", "weibo"),
+ ALIPAY("6", "alipay"),
+ EN_WECHAT("7", "enWechat"),
+ DING_DING("8", "dingding"),
+ WECHAT_APP("12", "wechatApp");
+
+ private String code;
+
+ private String value;
+
+ SecurityTypeEnum(String code, String value) {
+ this.code = code;
+ this.value = value;
+ }
+
+ public static SecurityTypeEnum deriveEnum(Integer openIdType) {
+ String type = String.valueOf(Optional.ofNullable(openIdType).orElse(-1));
+ for (SecurityTypeEnum itemEnum : SecurityTypeEnum.values()) {
+ if (itemEnum.code.equals(type)) {
+ return itemEnum;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 1手机号,2微信,3 qq,4 email,5微博,6 支付宝
+ */
+ public static String getValue(String code) {
+ switch (code) {
+ case "1":
+ return MOBILE.getValue();
+ case "2":
+ return WECHAT.getValue();
+ case "3":
+ return QQ.getValue();
+ case "4":
+ return EMAIL.getValue();
+ case "5":
+ return WEIBO.getValue();
+ case "6":
+ return ALIPAY.getValue();
+ case "7":
+ return EN_WECHAT.getValue();
+ case "8":
+ return DING_DING.getValue();
+ case "12":
+ return WECHAT_APP.getValue();
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * 1手机号,2微信,3 qq,4 email,5微博,6 支付宝
+ * getUserInfo type 不等于空时使用
+ */
+ public static String getValueString(String value) {
+ switch (value) {
+ case "mobilePhone":
+ return MOBILE.getValue();
+ case "wechat":
+ return WECHAT.getValue();
+ case "qq":
+ return QQ.getValue();
+ case "email":
+ return EMAIL.getValue();
+ case "weibo":
+ return WEIBO.getValue();
+ case "alipay":
+ return ALIPAY.getValue();
+ case "enWechat":
+ return EN_WECHAT.getValue();
+ case "dingding":
+ return DING_DING.getValue();
+ default:
+ return null;
+ }
+ }
+ public String getCode() {
+ return code;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/SendOperateTypeEnum.java b/src/main/java/com/svnlan/enums/SendOperateTypeEnum.java
new file mode 100644
index 0000000..b959d70
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/SendOperateTypeEnum.java
@@ -0,0 +1,31 @@
+package com.svnlan.enums;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ */
+public enum SendOperateTypeEnum {
+
+ BINDING("1","绑定"),
+ FIND("2","忘记登录密码"),
+ FORGET("3","设置支付密码");
+
+
+ private String code;
+
+ private String value;
+
+ SendOperateTypeEnum(String code, String value) {
+ this.code = code;
+ this.value = value;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+}
diff --git a/src/main/java/com/svnlan/enums/ShareMenuEnum.java b/src/main/java/com/svnlan/enums/ShareMenuEnum.java
new file mode 100644
index 0000000..02e4337
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/ShareMenuEnum.java
@@ -0,0 +1,43 @@
+package com.svnlan.enums;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/4/11 15:42
+ */
+public enum ShareMenuEnum {
+ // 与我协作
+ shareToMe("explorer.toolbar.shareToMe", "", "0", "shareToMe"),
+ info("explorer.toolbar.info", "", "0", "info"),
+ ;
+
+ private String code;
+
+ private String desc;
+
+ private String isRoot;
+ private String icon;
+
+
+ ShareMenuEnum(String code, String desc, String isRoot, String icon) {
+ this.code = code;
+ this.desc = desc;
+ this.isRoot = isRoot;
+ this.icon = icon;
+ }
+
+ public String getIcon() {
+ return icon;
+ }
+ public String getDesc() {
+ return desc;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getIsRoot() {
+ return isRoot;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/SortEnum.java b/src/main/java/com/svnlan/enums/SortEnum.java
new file mode 100644
index 0000000..89768b0
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/SortEnum.java
@@ -0,0 +1,49 @@
+package com.svnlan.enums;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/9 13:50
+ */
+public enum SortEnum {
+ asc("1", "asc"),
+ desc("2", "desc"),
+ ;
+ private String code;
+
+ private String value;
+
+ SortEnum(String code, String value) {
+ this.code = code;
+ this.value = value;
+ }
+
+ public static String getSortType(String value) {
+ switch (value) {
+ case "asc":
+ return asc.getValue();
+ case "up":
+ return asc.getValue();
+ case "desc":
+ return desc.getValue();
+ default:
+ return desc.getValue();
+ }
+ }
+
+ public static List sortList = Arrays.stream(values()).map(SortEnum::getValue).collect(Collectors.toList());
+
+ public static boolean contains(String value) {
+ return sortList.contains(value);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getValue() { return value; }
+}
diff --git a/src/main/java/com/svnlan/enums/SortFieldEnum.java b/src/main/java/com/svnlan/enums/SortFieldEnum.java
new file mode 100644
index 0000000..5cb16b9
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/SortFieldEnum.java
@@ -0,0 +1,47 @@
+package com.svnlan.enums;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/9 14:09
+ */
+public enum SortFieldEnum {
+ sizeUse("1", "sizeUse"),
+ roleID("2", "roleID"),
+ ;
+ private String code;
+
+ private String value;
+
+ SortFieldEnum(String code, String value) {
+ this.code = code;
+ this.value = value;
+ }
+
+ public static String getSortField(String value) {
+ switch (value) {
+ case "sizeUse":
+ return sizeUse.getValue();
+ case "roleID":
+ return roleID.getValue();
+ default:
+ return sizeUse.getValue();
+ }
+ }
+
+ public static List sortList = Arrays.stream(values()).map(SortFieldEnum::getValue).collect(Collectors.toList());
+
+ public static boolean contains(String value) {
+ return sortList.contains(value);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getValue() { return value; }
+}
diff --git a/src/main/java/com/svnlan/enums/SourceFieldEnum.java b/src/main/java/com/svnlan/enums/SourceFieldEnum.java
new file mode 100644
index 0000000..64244fc
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/SourceFieldEnum.java
@@ -0,0 +1,79 @@
+package com.svnlan.enums;
+
+import org.springframework.util.ObjectUtils;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/15 16:28
+ */
+public enum SourceFieldEnum {
+ name("1", "name"),
+ fileType("2", "fileType"),
+ size("3", "size"),
+ modifyTime("4", "modifyTime"),
+ createTime("3", "createTime"),
+ ;
+ private String code;
+
+ private String value;
+
+ SourceFieldEnum(String code, String value) {
+ this.code = code;
+ this.value = value;
+ }
+
+ public static String getSortField(String value) {
+ switch (value) {
+ case "name":
+ return "name_pinyin";
+ case "size":
+ return size.getValue();
+ case "ext":
+ case "fileType":
+ return fileType.getValue();
+ case "modifyTime":
+ return modifyTime.getValue();
+ default:
+ return name.getValue();
+ }
+ }
+
+ public static String getConvertSortField(String value) {
+ if (ObjectUtils.isEmpty(value)){
+ return "stateSort";
+ }
+ switch (value) {
+ case "name":
+ return "io." + name.getValue();
+ case "size":
+ return "io." + size.getValue();
+ case "fileType":
+ case "ext":
+ return "io." + fileType.getValue();
+ case "modifyTime":
+ return "cc." + modifyTime.getValue();
+ case "createTime":
+ return "cc." + createTime.getValue();
+ default:
+ return "stateSort";
+ }
+ }
+
+
+ public static List sortList = Arrays.stream(values()).map(SourceFieldEnum::getValue).collect(Collectors.toList());
+
+ public static boolean contains(String value) {
+ return sortList.contains(value);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getValue() { return value; }
+}
diff --git a/src/main/java/com/svnlan/enums/SourceSortEnum.java b/src/main/java/com/svnlan/enums/SourceSortEnum.java
new file mode 100644
index 0000000..fb78ce0
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/SourceSortEnum.java
@@ -0,0 +1,41 @@
+package com.svnlan.enums;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/15 16:20
+ */
+public enum SourceSortEnum {
+ asc("1", "asc"),
+ desc("2", "desc"),
+ ;
+ private String code;
+
+ private String value;
+
+ SourceSortEnum(String code, String value) {
+ this.code = code;
+ this.value = value;
+ }
+
+ public static String getSortType(String value) {
+ switch (value) {
+ case "up":
+ return asc.getValue();
+ case "asc":
+ return asc.getValue();
+ case "down":
+ return desc.getValue();
+ case "desc":
+ return desc.getValue();
+ default:
+ return desc.getValue();
+ }
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getValue() { return value; }
+}
diff --git a/src/main/java/com/svnlan/enums/ToolsEnum.java b/src/main/java/com/svnlan/enums/ToolsEnum.java
new file mode 100644
index 0000000..001ef44
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/ToolsEnum.java
@@ -0,0 +1,44 @@
+package com.svnlan.enums;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/14 15:40
+ */
+public enum ToolsEnum {
+ // 最近文档
+ recentDoc("explorer.toolbar.recentDoc", "explorer.pathDesc.recentDoc", "recentDoc"),
+ // 我的协作
+ // shareTo("explorer.toolbar.shareTo", "explorer.pathDesc.shareTo", "shareTo"),
+ // 外链分享
+ shareLink("explorer.toolbar.shareLink", "explorer.pathDesc.shareLink", "shareLink"),
+ // 我的相册
+ photo("explorer.toolbar.photo", "explorer.photo.desc", "photo"),
+ // 工具箱
+ toolbox("explorer.toolbar.toolbox", "explorer.toolbox.desc", "toolbox"),
+ // 回收站
+ recycle("explorer.toolbar.recycle", "explorer.pathDesc.recycle", "recycle"),
+ ;
+
+ private String code;
+
+ private String value;
+ private String icon;
+
+ ToolsEnum(String code, String value, String icon) {
+ this.code = code;
+ this.value = value;
+ this.icon = icon;
+ }
+
+ public String getIcon() {
+ return icon;
+ }
+ public String getCode() {
+ return code;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/UserMetaEnum.java b/src/main/java/com/svnlan/enums/UserMetaEnum.java
new file mode 100644
index 0000000..812c02b
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/UserMetaEnum.java
@@ -0,0 +1,42 @@
+package com.svnlan.enums;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/10 17:25
+ */
+public enum UserMetaEnum {
+ namePinyin(1, "namePinyin"),
+ namePinyinSimple(2, "namePinyinSimple"),
+ ;
+ private Integer code;
+
+ private String value;
+
+ public static List keyList = Arrays.stream(values()).map(UserMetaEnum::getValue).collect(Collectors.toList());
+
+ public static List delKeyList(){
+ return Arrays.asList(namePinyin.value, namePinyinSimple.value);
+ }
+
+ public static boolean contains(String value) {
+ return keyList.contains(value);
+ }
+
+ UserMetaEnum(Integer code, String value) {
+ this.code = code;
+ this.value = value;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/UserOptionEnum.java b/src/main/java/com/svnlan/enums/UserOptionEnum.java
new file mode 100644
index 0000000..fb12fa3
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/UserOptionEnum.java
@@ -0,0 +1,88 @@
+package com.svnlan.enums;
+
+
+import com.svnlan.user.domain.UserOption;
+import com.svnlan.utils.ChinesUtil;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/13 10:23
+ */
+public enum UserOptionEnum {
+
+ listSort("listSort", "", "folderInfo"),
+ folderInfoListType("listType", "", "folderInfo"),
+ listType("listType", "icon", ""),
+ listSortField("listSortField", "name", ""),
+ listSortOrder("listSortOrder", "up", ""),
+ fileIconSize("fileIconSize", "80", ""),
+ fileOpenClick("fileOpenClick", "dbclick", ""),
+ fileShowDesc("fileShowDesc", "0", ""),
+ animateOpen("animateOpen", "1", ""),
+ soundOpen("soundOpen", "0", ""),
+ theme("theme", "auto", ""),
+ themeImage("themeImage", "", ""),
+ wall("wall", "4", ""),
+ listTypeKeep("listTypeKeep", "1", ""),
+ listSortKeep("listSortKeep", "1", ""),
+ fileRepeat("fileRepeat", "replace", ""),
+ recycleOpen("recycleOpen", "1", ""),
+ kodAppDefault("kodAppDefault", "", ""),
+ fileIconSizeDesktop("fileIconSizeDesktop", "70", ""),
+ fileIconSizePhoto("fileIconSizePhoto", "120", ""),
+ photoConfig("photoConfig", "", ""),
+ resizeConfig("resizeConfig", "{\"filename\":250,\"filetype\":80,\"filesize\":80,\"filetime\":215,\"editorTreeWidth\":200,\"explorerTreeWidth\":200}", ""),
+ imageThumb("imageThumb", "1", ""),
+ fileSelect("fileSelect", "1", ""),
+ displayHideFile("displayHideFile", "0", ""),
+ filePanel("filePanel", "1", ""),
+ shareToMeShowType("shareToMeShowType", "list", ""),
+ messageSendType("messageSendType", "enter", ""),
+ loginDevice("loginDevice", "", ""),
+ recycleList("recycleList", "[]", "recycle"),
+ ;
+ public static List keyList = Arrays.stream(values()).map(UserOptionEnum::getCode).collect(Collectors.toList());
+
+ public static List sortKeyList = Arrays.asList(listSortField.getCode(),listSortOrder.getCode(),fileIconSize.getCode(),listSortKeep.getCode(),listSort.getCode(),listType.getCode());
+
+ public static boolean contains(String value) {
+ return keyList.contains(value);
+ }
+
+ public static List setDefaultOptionList(Long userID){
+ List paramList = new ArrayList<>();
+ for (UserOptionEnum optionEnum :values()){
+ paramList.add(new UserOption(userID, optionEnum.getType(), optionEnum.getCode(), optionEnum.getValue()));
+ }
+ return paramList;
+ }
+ private String code;
+
+ private String value;
+
+ private String type;
+
+ UserOptionEnum(String code, String value, String type) {
+ this.code = code;
+ this.value = value;
+ this.type = type;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/UserTypeEnum.java b/src/main/java/com/svnlan/enums/UserTypeEnum.java
new file mode 100644
index 0000000..c0fbb79
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/UserTypeEnum.java
@@ -0,0 +1,30 @@
+package com.svnlan.enums;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/8 17:19
+ */
+public enum UserTypeEnum {
+
+ MANAGER(1, "系统管理员"),
+ USER(2, "其他用户"),
+ GUEST(3, "游客"),
+ ;
+ private Integer code;
+
+ private String value;
+
+ UserTypeEnum(Integer code, String value) {
+ this.code = code;
+ this.value = value;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/svnlan/enums/UserTypeExactEnum.java b/src/main/java/com/svnlan/enums/UserTypeExactEnum.java
new file mode 100644
index 0000000..44eab4d
--- /dev/null
+++ b/src/main/java/com/svnlan/enums/UserTypeExactEnum.java
@@ -0,0 +1,47 @@
+package com.svnlan.enums;
+
+/**
+ * @Author:
+ * @Description: 用户具体类型
+ * @Date:
+ */
+public enum UserTypeExactEnum {
+ SYSTEM_ADMIN("1", "系统管理员"),
+ GENERAL_ADMIN("2", "普通管理员"),
+ USER("3", "用户"),
+ ;
+
+ private String typeCode;
+ private String typeName;
+
+ UserTypeExactEnum(String typeCode, String typeName){
+ this.typeCode = typeCode;
+ this.typeName = typeName;
+ }
+
+ public String getTypeCode() {
+ return typeCode;
+ }
+
+ public String getTypeName() {
+ return typeName;
+ }
+
+ /**
+ * @description: 由code得对应的枚举
+ * @param typeCode
+ * @return com.svnlan.jwt.enums.UserTypeExactEnum
+ * @author
+ */
+ public static UserTypeExactEnum getUserTypeExactEnumByCode(String typeCode) {
+ UserTypeExactEnum resultEnum = null;
+ for (UserTypeExactEnum tempEnum : UserTypeExactEnum.values()) {
+ if(tempEnum.getTypeCode().equals(typeCode)) {
+ resultEnum = tempEnum;
+ break;
+ }
+ }
+ return resultEnum;
+ }
+
+}
diff --git a/src/main/java/com/svnlan/exception/CodeMessageEnum.java b/src/main/java/com/svnlan/exception/CodeMessageEnum.java
new file mode 100644
index 0000000..41224af
--- /dev/null
+++ b/src/main/java/com/svnlan/exception/CodeMessageEnum.java
@@ -0,0 +1,181 @@
+package com.svnlan.exception;
+
+/**
+ * @Description: 响应码枚举
+ * @Date:
+ */
+public enum CodeMessageEnum {
+ success("common.success", "成功"),
+ system_error("explorer.systemError", "系统错误"),
+ namePwdNotNull("user.namePwdNotNull", "账号密码不能为空!"),
+ user_pwdNotNull("user.pwdNotNull", "密码不能为空!"),
+ loginNoPermission("user.loginNoPermission", "抱歉,您没有该权限,请使用有此权限的账号登录!"),
+ loginFirst("user.loginFirst", "您尚未登录!请先登录"),
+ bindSignError("user.bindSignError", "签名异常,请重新操作一次!"),
+ bindUpdateError("user.bindUpdateError", "用户信息更新失败,请重试"),
+ bindTypeError("user.bindTypeError", "无效的绑定类型"),
+ bindWxConfigError("user.bindWxConfigError", "获取配置信息异常"),
+ loginTimeout("user.loginTimeout", "当前登录已超时,请重新登录!"),
+ loginTokenError("common.loginTokenError", "登录已失效,请重新登录!"),
+ loginSuccess("common.loginSuccess", "登录成功!"),
+ loginError("common.loginError", "登录失败"),
+ bindSuccess("common.bindSuccess", "绑定成功!"),
+ bindError("common.bindError", "绑定失败"),
+ passwordErrorLock("admin.setting.passwordErrorLock", "密码输入错误锁定"),
+ errorAdminAuth("admin.auth.errorAdmin", "权限不足"),
+ codeError("user.codeError", "验证码错误"),
+ rootPwdEqual("user.rootPwdEqual", "两次密码不一致!"),
+ rootPwdTips("user.rootPwdTips", "请设置管理员密码!"),
+ pwdError("user.pwdError", "用户名或密码错误!"),
+ oldPwdError("user.oldPwdError", "原密码错误!"),
+ userEnabled("user.userEnabled", "账号被禁用或尚未启用!请联系管理员"),
+ invalidEmail("user.invalidEmail", "您没有有效的邮箱地址,请联系管理员修改"),
+ roleError("user.roleError", "所属权限组不存在,请联系管理员"),
+ sendSuccess("user.sendSuccess", "发送成功"),
+ sendFail("user.sendFail", "发送失败"),
+ sendSuccessDesc("user.sendSuccessDesc", "验证码发送成功,请前往查看"),
+ sendFailDesc("user.sendFailDesc", "验证码发送失败,请联系管理员"),
+ codeExpired("user.codeExpired", "验证码已过期,请重新获取"),
+ codeErrorTooMany("user.codeErrorTooMany", "验证码错误次数过多,请重新获取"),
+ codeErrorFreq("user.codeErrorFreq", "发送频率过高,请稍后再试!"),
+ codeErrorCnt("user.codeErrorCnt", "发送次数已超限制,将被锁定%s小时。"),
+ registSuccess("user.registSuccess", "注册成功"),
+ roleDelErrTips("admin.role.delErrTips", "该角色正在被使用,无法删除!"),
+ shareErrorParam("explorer.share.errorParam", "参数错误!"),
+ paramFormatError("explorer.paramFormatError", "参数格式错误!"),
+ errorUser("explorer.share.errorUser", "用户信息错误!"),
+ errorPwd("explorer.share.errorPwd", "密码错误!"),
+ adminAuthError("admin.auth.error", "角色权限错误(没有权限设置)"),
+ authTargetError("admin.auth.targetError", "权限对象类型错误,必须为用户或部门"),
+ ERROR_USER_LOGIN_LOCK("ERROR_USER_LOGIN_LOCK", "抱歉,密码尝试输入错误过多,当前账号已锁定,请1分钟后再试!"),
+
+
+ explorerNotNull("explorer.notNull", "必填项不能为空!"),
+ registRoleEmpty("admin.setting.registRoleEmpty", "角色权限不能为空!"),
+ parentNullError("admin.group.parentNullError", "上级部门不能为空"),
+ picCannotNull("explorer.picCannotNull", "图片地址不能为空!"),
+ inputEmailCode("user.inputEmailCode", "请输入邮箱验证码!"),
+ inputSmsCode("user.inputSmsCode", "请输入短信验证码!"),
+ inputVerifyCode("user.inputVerifyCode", "请输入验证码!"),
+ inputPwd("user.inputPwd", "请输入密码!"),
+ inputPwdAgain("user.inputPwdAgain", "请再次输入密码!"),
+ inputNickName("user.inputNickName", "请输入昵称!"),
+ inputEmail("user.inputEmail", "请输入邮箱地址!"),
+ inputPhone("user.inputPhone", "请输入手机号!"),
+ inputPhoneEmail("user.inputPhoneEmail", "请输入手机/Email!"),
+ invalidPhoneEmail("user.invalidPhoneEmail", "无效的手机/Email!"),
+ defAdminError("admin.install.defAdminError", "管理员账号添加失败!"),
+ passwordCheckError("user.passwordCheckError", "密码格式不符合密码强度规则!"),
+
+ saveSuccess("explorer.saveSuccess", "保存成功!"),
+ saveError("explorer.saveError", "保存失败!"),
+ explorerSuccess("explorer.success", "操作成功!"),
+ explorerError("explorer.error", "操作失败!"),
+ explorerDataError("explorer.dataError", "数据异常!"),
+ userAvatarExt("user.userAvatarExt", "仅支持 JPG、JPEG、PNG 的图片格式!"),
+ ignoreFileSizeTips("admin.role.ignoreFileSizeTips", "抱歉,当文件超出大小限制; 具体请联系管理员!"),
+ msgSysSizeErr("msgWarning.main.msgSysSizeErr", "服务器系统盘剩余空间不足(%s)"),
+ pathNotSupport("explorer.pathNotSupport", "此类型目录不支持该操作!"),
+ pathIsRoot("explorer.pathIsRoot", "已经到根目录了!"),
+ pathNull("explorer.pathNull", "文件夹为空!"),
+ zipFileLarge("explorer.zipFileLarge", "该文件太大,请解压后再进行预览操作!"),
+ charNoSupport("explorer.charNoSupport", "不支持的特殊字符:"),
+ moveError("explorer.moveError", "移动失败!"),
+ lockError("explorer.lockError", "出错了,并发锁定超时!"),
+ lockErrorDesc("explorer.lockErrorDesc", "请稍后再试(可降低请求频率,优化并发相关配置)."),
+ moveSubPathError("explorer.moveSubPathError", "出错了,父目录不能移动到子目录!"),
+ spaceIsFull("explorer.spaceIsFull", "剩余空间不足,请联系管理员!"),
+ sessionSaveError("explorer.saveError", "session写入失败!请查看磁盘是否已满,或咨询服务商。"),
+ pathNotExists("common.pathNotExists", "该文件不存在!"),
+ fileLockError("explorer.fileLockError", "当前文件为锁定状态,请联系锁定者解锁后再试!"),
+ downError("explorer.downError", "下载失败!"),
+ sourceShareDisabled("source.shareDisabled","当前资源禁止分享"),
+ shareNotExist("explorer.share.notExist", "分享不存在"),
+ shareExpiredTips("explorer.share.expiredTips", "抱歉,该分享已过期,请联系分享者!"),
+ shareDownExceedTips("explorer.share.downExceedTips", "抱歉,该分享下载次数超过分享者设置的上限"),
+ shareLoginTips("explorer.share.loginTips", "抱歉,该分享必须登录用户才能访问"),
+ shareNoDownTips("explorer.share.noDownTips", "抱歉,该分享者禁用了下载"),
+ shareNoViewTips("explorer.share.noViewTips", "抱歉,该分享者禁用了预览"),
+ shareNoUploadTips("explorer.share.noUploadTips", "抱歉,该分享者禁用了上传"),
+ shareNeedPwd("explorer.share.needPwd", "该分享需要密码"),
+ shareActionNotSupport("explorer.share.actionNotSupport", "分享内容,不支持该操作"),
+ shareErrorPathTips("explorer.share.errorPathTips", "分享链接错误,或分享者已经取消了该外链分享"),
+
+ selectUserTips("admin.member.selectUserTips", "请选择要操作的账号!"),
+ rptSelectTips("admin.share.rptSelectTips", "请选择待操作项!"),
+ selectValidFolder("explorer.selectValidFolder", "请选择要有效的文件夹!"),
+ selectFolderFile("explorer.selectFolderFile", "选择文件或文件夹!"),
+ renameSuccess("explorer.renameSuccess", "重命名成功!"),
+ noPermissionRead("explorer.noPermissionRead", "您没有读取权限!"),
+ noPermissionDownload("explorer.noPermissionDownload", "您没有下载权限!"),
+ noPermissionWrite("explorer.noPermissionWrite", "该目录没有写权限!"),
+ noPermissionAction("explorer.noPermissionAction", "您没有此权限,请联系管理员!"),
+ noPermissionAuthAll("explorer.noPermissionAuthAll", "%s ,没有此操作权限"),
+ noPermissionWriteAll("explorer.noPermissionWriteAll", "该文件或目录没有写权限!"),
+ noPermissionWriteFile("explorer.noPermissionWriteFile", "该文件没有写权限!"),
+ noPermissionReadAll("explorer.noPermissionReadAll", "该文件或目录没有读权限!"),
+ noPermission("explorer.noPermission", "管理员禁止了此权限!"),
+ noPermissionExt("explorer.noPermissionExt", "管理员禁止了该类型文件权限!"),
+ descTooLong("explorer.descTooLong", "描述长度过长!"),
+ notSupport("explorer.notSupport", "出错了, 不支持该内容格式!"),
+ noPermissionGroup("explorer.noPermissionGroup", "您不在该用户组!"),
+ ERROR_USER_NOT_EXISTS("ERROR_USER_NOT_EXISTS", "用户不存在"),
+ ERROR_USER_PASSWORD_ERROR("ERROR_USER_PASSWORD_ERROR", "密码错误!"),
+ ERROR_USER_EXIST_NAME("ERROR_USER_EXIST_NAME", "用户名已存在"),
+ ERROR_USER_EXIST_PHONE("ERROR_USER_EXIST_PHONE", "手机号已存在"),
+ ERROR_USER_EXIST_EMAIL("ERROR_USER_EXIST_EMAIL", "该邮箱已存在"),
+ ERROR_USER_EXIST_NICKNAME("ERROR_USER_EXIST_NICKNAME", "昵称已存在"),
+ ERROR_IP_NOT_ALLOW("ERROR_IP_NOT_ALLOW", "您当前IP或访问设备不允许登录,请联系管理员"),
+ emailCodeText("admin.emailCodeText", "您正在进行邮箱验证,本次请求的验证码如下,为了保障您帐号的安全性,请及时完成验证。"),
+ repeatError("explorer.repeatError", "操作失败,该名称已存在"),
+ pathExists("explorer.pathExists", "该名称已存在"),
+ groupDelError("explorer.groupDelError", "抱歉部门文件夹不支持删除"),
+ unzipErrorTips("explorer.unzipErrorTips", "出错了!未识别的压缩文件格式; 请检查该文件是否为压缩文件或者是否损坏。"),
+ dragDownloadOpenTips("admin.setting.dragDownloadOpenTips", "请联系管理员在后台设置中开启"),
+ infoTypeDelError("admin.info.typeDelError", "删除失败,有子分类或数据"),
+ DOMAIN_CANNOT_RECOGNIZE("admin.info.domainIdentifyError", "网站无法识别"),
+ ARTICLE_CANNOT_RECOGNIZE("admin.info.articleIdentifyError", "文章无法识别"),
+ domainSupportError("admin.info.domainSupportError", "该网站暂不支持采集"),
+ fileTooLarge("admin.info.fileTooLarge", "文件过大"),
+ EXCEEDS_LIMIT("admin.exceeds.limit", "超出限制"),
+ Enabling_Not_Deleted("admin.design.deleted", "启用状态无法删除"),
+ designUrlLocked("admin.design.url.locked", "当前url被锁定, 暂时不能使用"),
+ SING_INVALID("explorer.SING_INVALID", "签名异常"),
+ TEMP_AUTH_INVALID("explorer.TEMP_AUTH_INVALID", "临时授权码无效(失效)"),
+ QR_INVALID("explorer.QR_INVALID", "二维码已失效"),
+ uploadError("explorer.upload.error", "上传失败"),
+ ;
+ private String code;
+ private String msg;
+
+ CodeMessageEnum(String code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+
+ public static String getCode(String msg) {
+ for (CodeMessageEnum codeMsg : CodeMessageEnum.values()) {
+ if (codeMsg.msg.equals(msg)) {
+ return codeMsg.code;
+ }
+ }
+ return null;
+ }
+
+ public static String getMsg(String code) {
+ for (CodeMessageEnum codeMsg : CodeMessageEnum.values()) {
+ if (codeMsg.code.equals(code)) {
+ return codeMsg.msg;
+ }
+ }
+ return null;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getMsg() {
+ return msg;
+ }
+}
diff --git a/src/main/java/com/svnlan/exception/DingCallbackCrypto.java b/src/main/java/com/svnlan/exception/DingCallbackCrypto.java
new file mode 100644
index 0000000..029d30e
--- /dev/null
+++ b/src/main/java/com/svnlan/exception/DingCallbackCrypto.java
@@ -0,0 +1,396 @@
+package com.svnlan.exception;
+
+import com.alibaba.fastjson.JSON;
+import org.apache.commons.codec.binary.Base64;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.ByteArrayOutputStream;
+import java.lang.reflect.Field;
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * 钉钉加解密
+ *
+ * @author lingxu 2023/03/28 14:30
+ */
+public class DingCallbackCrypto {
+
+ private static final Charset CHARSET = Charset.forName("utf-8");
+ private static final Base64 base64 = new Base64();
+ private byte[] aesKey;
+ private String token;
+ private String corpId;
+ /**
+ * ask getPaddingBytes key固定长度
+ **/
+ private static final Integer AES_ENCODE_KEY_LENGTH = 43;
+ /**
+ * 加密随机字符串字节长度
+ **/
+ private static final Integer RANDOM_LENGTH = 16;
+
+ /**
+ * 构造函数
+ *
+ * @param token 钉钉开放平台上,开发者设置的token
+ * @param encodingAesKey 钉钉开放台上,开发者设置的EncodingAESKey
+ * @param corpId 企业自建应用-事件订阅, 使用appKey
+ * 企业自建应用-注册回调地址, 使用corpId
+ * 第三方企业应用, 使用suiteKey
+ * @throws DingTalkEncryptException 执行失败,请查看该异常的错误码和具体的错误信息
+ */
+ public DingCallbackCrypto(String token, String encodingAesKey, String corpId) throws DingTalkEncryptException {
+ if (null == encodingAesKey || encodingAesKey.length() != AES_ENCODE_KEY_LENGTH) {
+ throw new DingTalkEncryptException(DingTalkEncryptException.AES_KEY_ILLEGAL);
+ }
+ this.token = token;
+ this.corpId = corpId;
+ aesKey = Base64.decodeBase64(encodingAesKey + "=");
+ }
+
+ public Map getEncryptedMap(String plaintext) throws DingTalkEncryptException {
+ return getEncryptedMap(plaintext, System.currentTimeMillis(), Utils.getRandomStr(16));
+ }
+
+ /**
+ * 将和钉钉开放平台同步的消息体加密,返回加密Map
+ *
+ * @param plaintext 传递的消息体明文
+ * @param timeStamp 时间戳
+ * @param nonce 随机字符串
+ * @return
+ * @throws DingTalkEncryptException
+ */
+ public Map getEncryptedMap(String plaintext, Long timeStamp, String nonce) throws DingTalkEncryptException {
+ if (null == plaintext) {
+ throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_PLAINTEXT_ILLEGAL);
+ }
+ if (null == timeStamp) {
+ throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_TIMESTAMP_ILLEGAL);
+ }
+ if (null == nonce) {
+ throw new DingTalkEncryptException(DingTalkEncryptException.ENCRYPTION_NONCE_ILLEGAL);
+ }
+ // 加密
+ String encrypt = encrypt(Utils.getRandomStr(RANDOM_LENGTH), plaintext);
+ String signature = getSignature(token, String.valueOf(timeStamp), nonce, encrypt);
+ Map resultMap = new HashMap<>();
+ resultMap.put("msg_signature", signature);
+ resultMap.put("encrypt", encrypt);
+ resultMap.put("timeStamp", String.valueOf(timeStamp));
+ resultMap.put("nonce", nonce);
+ return resultMap;
+ }
+
+ /**
+ * 密文解密
+ *
+ * @param msgSignature 签名串
+ * @param timeStamp 时间戳
+ * @param nonce 随机串
+ * @param encryptMsg 密文
+ * @return 解密后的原文
+ * @throws DingTalkEncryptException
+ */
+ public String getDecryptMsg(String msgSignature, String timeStamp, String nonce, String encryptMsg) throws DingTalkEncryptException {
+ //校验签名
+ String signature = getSignature(token, timeStamp, nonce, encryptMsg);
+ if (!signature.equals(msgSignature)) {
+ throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR);
+ }
+ // 解密
+ String result = decrypt(encryptMsg);
+ return result;
+ }
+
+ /*
+ * 对明文加密.
+ * @param text 需要加密的明文
+ * @return 加密后base64编码的字符串
+ */
+ private String encrypt(String random, String plaintext) throws DingTalkEncryptException {
+ try {
+ byte[] randomBytes = random.getBytes(CHARSET);
+ byte[] plainTextBytes = plaintext.getBytes(CHARSET);
+ byte[] lengthByte = Utils.int2Bytes(plainTextBytes.length);
+ byte[] corpidBytes = corpId.getBytes(CHARSET);
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ byteStream.write(randomBytes);
+ byteStream.write(lengthByte);
+ byteStream.write(plainTextBytes);
+ byteStream.write(corpidBytes);
+ byte[] padBytes = PKCS7Padding.getPaddingBytes(byteStream.size());
+ byteStream.write(padBytes);
+ byte[] unencrypted = byteStream.toByteArray();
+ byteStream.close();
+ Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+ SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
+ IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16);
+ cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
+ byte[] encrypted = cipher.doFinal(unencrypted);
+ String result = base64.encodeToString(encrypted);
+ return result;
+ } catch (Exception e) {
+ throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_ENCRYPT_TEXT_ERROR);
+ }
+ }
+
+ /*
+ * 对密文进行解密.
+ * @param text 需要解密的密文
+ * @return 解密得到的明文
+ */
+ private String decrypt(String text) throws DingTalkEncryptException {
+ byte[] originalArr;
+ try {
+ // 设置解密模式为AES的CBC模式
+ Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+ SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
+ IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
+ cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
+ // 使用BASE64对密文进行解码
+ byte[] encrypted = Base64.decodeBase64(text);
+ // 解密
+ originalArr = cipher.doFinal(encrypted);
+ } catch (Exception e) {
+ throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_ERROR);
+ }
+
+ String plainText;
+ String fromCorpid;
+ try {
+ // 去除补位字符
+ byte[] bytes = PKCS7Padding.removePaddingBytes(originalArr);
+ // 分离16位随机字符串,网络字节序和corpId
+ byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
+ int plainTextLegth = Utils.bytes2int(networkOrder);
+ plainText = new String(Arrays.copyOfRange(bytes, 20, 20 + plainTextLegth), CHARSET);
+ fromCorpid = new String(Arrays.copyOfRange(bytes, 20 + plainTextLegth, bytes.length), CHARSET);
+ } catch (Exception e) {
+ throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_LENGTH_ERROR);
+ }
+
+ // corpid不相同的情况
+ if (!fromCorpid.equals(corpId)) {
+ throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_CORPID_ERROR);
+ }
+ return plainText;
+ }
+
+ /**
+ * 数字签名
+ *
+ * @param token isv token
+ * @param timestamp 时间戳
+ * @param nonce 随机串
+ * @param encrypt 加密文本
+ * @return
+ * @throws DingTalkEncryptException
+ */
+ public String getSignature(String token, String timestamp, String nonce, String encrypt) throws DingTalkEncryptException {
+ try {
+ String[] array = new String[]{token, timestamp, nonce, encrypt};
+ Arrays.sort(array);
+ System.out.println(JSON.toJSONString(array));
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < 4; i++) {
+ sb.append(array[i]);
+ }
+ String str = sb.toString();
+ System.out.println(str);
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+ md.update(str.getBytes());
+ byte[] digest = md.digest();
+
+ StringBuffer hexstr = new StringBuffer();
+ String shaHex = "";
+ for (int i = 0; i < digest.length; i++) {
+ shaHex = Integer.toHexString(digest[i] & 0xFF);
+ if (shaHex.length() < 2) {
+ hexstr.append(0);
+ }
+ hexstr.append(shaHex);
+ }
+ return hexstr.toString();
+ } catch (Exception e) {
+ throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR);
+ }
+ }
+
+ public static class Utils {
+ public Utils() {
+ }
+
+ public static String getRandomStr(int count) {
+ String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+ Random random = new Random();
+ StringBuffer sb = new StringBuffer();
+
+ for (int i = 0; i < count; ++i) {
+ int number = random.nextInt(base.length());
+ sb.append(base.charAt(number));
+ }
+
+ return sb.toString();
+ }
+
+ public static byte[] int2Bytes(int count) {
+ byte[] byteArr = new byte[]{(byte) (count >> 24 & 255), (byte) (count >> 16 & 255), (byte) (count >> 8 & 255), (byte) (count & 255)};
+ return byteArr;
+ }
+
+ public static int bytes2int(byte[] byteArr) {
+ int count = 0;
+
+ for (int i = 0; i < 4; ++i) {
+ count <<= 8;
+ count |= byteArr[i] & 255;
+ }
+
+ return count;
+ }
+ }
+
+ public static class PKCS7Padding {
+ private static final Charset CHARSET = Charset.forName("utf-8");
+ private static final int BLOCK_SIZE = 32;
+
+ public PKCS7Padding() {
+ }
+
+ public static byte[] getPaddingBytes(int count) {
+ int amountToPad = 32 - count % 32;
+ if (amountToPad == 0) {
+ amountToPad = 32;
+ }
+
+ char padChr = chr(amountToPad);
+ String tmp = new String();
+
+ for (int index = 0; index < amountToPad; ++index) {
+ tmp = tmp + padChr;
+ }
+
+ return tmp.getBytes(CHARSET);
+ }
+
+ public static byte[] removePaddingBytes(byte[] decrypted) {
+ int pad = decrypted[decrypted.length - 1];
+ if (pad < 1 || pad > 32) {
+ pad = 0;
+ }
+
+ return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
+ }
+
+ private static char chr(int a) {
+ byte target = (byte) (a & 255);
+ return (char) target;
+ }
+ }
+
+ public static class DingTalkEncryptException extends Exception {
+ public static final int SUCCESS = 0;
+ public static final int ENCRYPTION_PLAINTEXT_ILLEGAL = 900001;
+ public static final int ENCRYPTION_TIMESTAMP_ILLEGAL = 900002;
+ public static final int ENCRYPTION_NONCE_ILLEGAL = 900003;
+ public static final int AES_KEY_ILLEGAL = 900004;
+ public static final int SIGNATURE_NOT_MATCH = 900005;
+ public static final int COMPUTE_SIGNATURE_ERROR = 900006;
+ public static final int COMPUTE_ENCRYPT_TEXT_ERROR = 900007;
+ public static final int COMPUTE_DECRYPT_TEXT_ERROR = 900008;
+ public static final int COMPUTE_DECRYPT_TEXT_LENGTH_ERROR = 900009;
+ public static final int COMPUTE_DECRYPT_TEXT_CORPID_ERROR = 900010;
+ private static Map msgMap = new HashMap();
+ private Integer code;
+
+ static {
+ msgMap.put(0, "成功");
+ msgMap.put(900001, "加密明文文本非法");
+ msgMap.put(900002, "加密时间戳参数非法");
+ msgMap.put(900003, "加密随机字符串参数非法");
+ msgMap.put(900005, "签名不匹配");
+ msgMap.put(900006, "签名计算失败");
+ msgMap.put(900004, "不合法的aes key");
+ msgMap.put(900007, "计算加密文字错误");
+ msgMap.put(900008, "计算解密文字错误");
+ msgMap.put(900009, "计算解密文字长度不匹配");
+ msgMap.put(900010, "计算解密文字corpid不匹配");
+ }
+
+ public Integer getCode() {
+ return this.code;
+ }
+
+ public DingTalkEncryptException(Integer exceptionCode) {
+ super((String) msgMap.get(exceptionCode));
+ this.code = exceptionCode;
+ }
+ }
+
+ static {
+ try {
+ Security.setProperty("crypto.policy", "limited");
+ RemoveCryptographyRestrictions();
+ } catch (Exception var1) {
+ }
+
+ }
+
+ private static void RemoveCryptographyRestrictions() throws Exception {
+ Class> jceSecurity = getClazz("javax.crypto.JceSecurity");
+ Class> cryptoPermissions = getClazz("javax.crypto.CryptoPermissions");
+ Class> cryptoAllPermission = getClazz("javax.crypto.CryptoAllPermission");
+ if (jceSecurity != null) {
+ setFinalStaticValue(jceSecurity, "isRestricted", false);
+ PermissionCollection defaultPolicy = (PermissionCollection) getFieldValue(jceSecurity, "defaultPolicy", (Object) null, PermissionCollection.class);
+ if (cryptoPermissions != null) {
+ Map, ?> map = (Map) getFieldValue(cryptoPermissions, "perms", defaultPolicy, Map.class);
+ map.clear();
+ }
+
+ if (cryptoAllPermission != null) {
+ Permission permission = (Permission) getFieldValue(cryptoAllPermission, "INSTANCE", (Object) null, Permission.class);
+ defaultPolicy.add(permission);
+ }
+ }
+
+ }
+
+ private static Class> getClazz(String className) {
+ Class clazz = null;
+
+ try {
+ clazz = Class.forName(className);
+ } catch (Exception var3) {
+ }
+
+ return clazz;
+ }
+
+ private static void setFinalStaticValue(Class> srcClazz, String fieldName, Object newValue) throws Exception {
+ Field field = srcClazz.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ Field modifiersField = Field.class.getDeclaredField("modifiers");
+ modifiersField.setAccessible(true);
+ modifiersField.setInt(field, field.getModifiers() & -17);
+ field.set((Object) null, newValue);
+ }
+
+ private static T getFieldValue(Class> srcClazz, String fieldName, Object owner, Class dstClazz) throws Exception {
+ Field field = srcClazz.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ return dstClazz.cast(field.get(owner));
+ }
+
+}
diff --git a/src/main/java/com/svnlan/exception/SvnlanRuntimeException.java b/src/main/java/com/svnlan/exception/SvnlanRuntimeException.java
new file mode 100644
index 0000000..42540be
--- /dev/null
+++ b/src/main/java/com/svnlan/exception/SvnlanRuntimeException.java
@@ -0,0 +1,124 @@
+package com.svnlan.exception;
+
+import com.svnlan.common.I18nUtils;
+
+/**
+ * @Author:
+ * @Description: 自定义运行时异常,抛出不符合业务需求的结果异常
+ * @Modified:
+ */
+public class SvnlanRuntimeException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 错误编码
+ */
+ private String errorCode;
+
+ /**
+ * 消息是否为属性文件中的Key
+ */
+ private boolean propertiesKey = true;
+
+ /**
+ * 构造一个基本异常.
+ *
+ * @param i18eCode 信息描述
+ */
+ public SvnlanRuntimeException(String i18eCode) {
+ // 根据资源文件的属性名以及当前语言环境,获取国际化信息
+ super(I18nUtils.tryI18n(i18eCode));
+ this.setErrorCode(i18eCode);
+ }
+
+ public SvnlanRuntimeException(String i18eCode, Object... args) {
+ // 根据资源文件的属性名,属性值中的参数以及当前语言环境,获取国际化信息
+ // args用来替换资源文件属性值中的占位符参数
+ super(I18nUtils.tryI18n(i18eCode, args));
+ this.setErrorCode(i18eCode);
+ }
+ /**
+ * 构造一个基本异常.
+ *
+ * @param errorCode 错误编码
+ * @param message 信息描述
+ */
+ /* public SvnlanRuntimeException(String errorCode, String message)
+ {
+ this(errorCode, message, true);
+ }*/
+
+ /**
+ * 构造一个基本异常.
+ *
+ * @param errorCode 错误编码
+ * @param message 信息描述
+ */
+ public SvnlanRuntimeException(String errorCode, String message, Throwable cause)
+ {
+ this(errorCode, message, cause, true);
+ }
+
+ /**
+ * 构造一个基本异常.
+ *
+ * @param errorCode 错误编码
+ * @param message 信息描述
+ * @param propertiesKey 消息是否为属性文件中的Key
+ */
+ public SvnlanRuntimeException(String errorCode, String message, boolean propertiesKey)
+ {
+ super(message);
+ this.setErrorCode(errorCode);
+ this.setPropertiesKey(propertiesKey);
+ }
+
+ /**
+ * 构造一个基本异常.
+ *
+ * @param errorCode 错误编码
+ * @param message 信息描述
+ */
+ public SvnlanRuntimeException(String errorCode, String message, Throwable cause, boolean propertiesKey)
+ {
+ super(message, cause);
+ this.setErrorCode(errorCode);
+ this.setPropertiesKey(propertiesKey);
+ }
+
+ /**
+ * 构造一个基本异常.
+ *
+ * @param message 信息描述
+ * @param cause 根异常类(可以存入任何异常)
+ */
+ public SvnlanRuntimeException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public SvnlanRuntimeException(CodeMessageEnum codeMessageEnum) {
+ this(codeMessageEnum.getCode(), codeMessageEnum.getMsg());
+ }
+
+ public String getErrorCode()
+ {
+ return errorCode;
+ }
+
+ public void setErrorCode(String errorCode)
+ {
+ this.errorCode = errorCode;
+ }
+
+ public boolean isPropertiesKey()
+ {
+ return propertiesKey;
+ }
+
+ public void setPropertiesKey(boolean propertiesKey)
+ {
+ this.propertiesKey = propertiesKey;
+ }
+}
diff --git a/src/main/java/com/svnlan/home/controller/CommentController.java b/src/main/java/com/svnlan/home/controller/CommentController.java
new file mode 100644
index 0000000..03be193
--- /dev/null
+++ b/src/main/java/com/svnlan/home/controller/CommentController.java
@@ -0,0 +1,103 @@
+package com.svnlan.home.controller;
+
+import com.svnlan.common.Result;
+import com.svnlan.exception.CodeMessageEnum;
+import com.svnlan.exception.SvnlanRuntimeException;
+import com.svnlan.home.domain.Comment;
+import com.svnlan.home.dto.CommentDto;
+import com.svnlan.home.service.CommentService;
+import com.svnlan.jwt.domain.LoginUser;
+import com.svnlan.utils.JsonUtils;
+import com.svnlan.utils.LogUtil;
+import com.svnlan.utils.LoginUserUtil;
+import com.svnlan.utils.PageResult;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/8/1 14:19
+ */
+@RestController
+public class CommentController {
+
+ @Resource
+ CommentService commentService;
+ @Resource
+ LoginUserUtil loginUserUtil;
+
+ /**
+ * @Description: 添加评论
+ * @params: [dto]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/comment/save", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String saveComment(@RequestBody CommentDto dto) {
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ Comment comment = commentService.saveComment(dto, loginUser);
+
+ result = new Result(true, CodeMessageEnum.success.getCode(), comment);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), e.getMessage());
+ } catch (Exception e) {
+ LogUtil.error(e, "保存评论失败" + JsonUtils.beanToJson(dto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 删除评论
+ * @params: [dto]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/comment/del", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String delComment(@RequestBody CommentDto dto) {
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ commentService.delComment(dto, loginUser);
+ result = new Result(true, CodeMessageEnum.success.getCode(), null);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), e.getMessage());
+ } catch (Exception e) {
+ LogUtil.error(e, "删除评论失败" + JsonUtils.beanToJson(dto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 评论列表
+ * @params: [dto]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/comment/list", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String getCommentList(CommentDto dto) {
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+
+ PageResult re = null;
+ try {
+ re = commentService.getCommentList(dto, loginUser);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "分享列表" + JsonUtils.beanToJson(dto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+}
diff --git a/src/main/java/com/svnlan/home/controller/CommonLabelController.java b/src/main/java/com/svnlan/home/controller/CommonLabelController.java
new file mode 100644
index 0000000..be55c73
--- /dev/null
+++ b/src/main/java/com/svnlan/home/controller/CommonLabelController.java
@@ -0,0 +1,245 @@
+package com.svnlan.home.controller;
+
+import com.svnlan.common.GlobalConfig;
+import com.svnlan.common.Result;
+import com.svnlan.exception.CodeMessageEnum;
+import com.svnlan.exception.SvnlanRuntimeException;
+import com.svnlan.home.dto.CheckFileDTO;
+import com.svnlan.home.dto.LabelDto;
+import com.svnlan.home.service.CommonLabelService;
+import com.svnlan.home.utils.UserAuthTool;
+import com.svnlan.home.vo.CommonLabelVo;
+import com.svnlan.jwt.domain.LoginUser;
+import com.svnlan.utils.JsonUtils;
+import com.svnlan.utils.LogUtil;
+import com.svnlan.utils.LoginUserUtil;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Author: sulijuan
+ * @Description: 标签
+ * @Date: 2023/3/2 10:52
+ */
+@RestController
+public class CommonLabelController {
+ @Resource
+ LoginUserUtil loginUserUtil;
+
+ @Resource
+ CommonLabelService commonLabelService;
+ @Resource
+ UserAuthTool userAuthTool;
+ @Resource
+ StringRedisTemplate stringRedisTemplate;
+
+ @RequestMapping(value = "/api/disk/tag/add", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String addTag(@Valid @RequestBody LabelDto labelDto){
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ // 校验标签权限
+ userAuthTool.checkUserTagPermission(loginUser);
+
+ commonLabelService.addTag(labelDto, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), null);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "添加标签" + JsonUtils.beanToJson(labelDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ @RequestMapping(value = "/api/disk/tag/edit", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String editTag(@Valid @RequestBody LabelDto labelDto){
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ // 校验标签权限
+ userAuthTool.checkUserTagPermission(loginUser);
+
+ commonLabelService.editTag(labelDto, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), null);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "编辑标签" + JsonUtils.beanToJson(labelDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ @RequestMapping(value = "/api/disk/tag/list", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String list(LabelDto labelDto){
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ List list = commonLabelService.getTagList(labelDto, loginUser);
+ result = new Result(true, CodeMessageEnum.success.getCode(), list);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "编辑标签" + JsonUtils.beanToJson(labelDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ @RequestMapping(value = "/api/disk/tag/fileTag", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String fileTag(@Valid @RequestBody LabelDto labelDto){
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ // 校验标签权限
+ userAuthTool.checkUserTagPermission(loginUser);
+
+ commonLabelService.fileTag(labelDto, loginUser);
+ result = new Result(true, CodeMessageEnum.success.getCode(), null);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "操作关联标签" + JsonUtils.beanToJson(labelDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+ @RequestMapping(value = "/api/disk/tag/del", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String delTag(@Valid @RequestBody LabelDto labelDto){
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ // 校验标签权限
+ userAuthTool.checkUserTagPermission(loginUser);
+
+ commonLabelService.delTag(labelDto, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), null);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "编辑标签" + JsonUtils.beanToJson(labelDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 标签下的文件置顶
+ * @params: [updateFileDTO]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/tag/moveTop", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String moveTop(@Valid @RequestBody CheckFileDTO labelDto){
+ Result result;
+ Map resultMap = new HashMap<>(1);
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ // 校验标签权限
+ userAuthTool.checkUserTagPermission(loginUser);
+
+ boolean success = commonLabelService.moveTop(labelDto, resultMap, loginUser);
+ result = new Result(success, CodeMessageEnum.success.getCode(), resultMap);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), resultMap);
+ } catch (Exception e){
+ LogUtil.error(e, "标签下的文件置顶失败" + JsonUtils.beanToJson(labelDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), resultMap);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+ /**
+ * @Description: 标签下的文件置底
+ * @params: [updateFileDTO]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/tag/moveBottom", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String moveBottom(@Valid @RequestBody CheckFileDTO labelDto){
+ Result result;
+ Map resultMap = new HashMap<>(1);
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ // 校验标签权限
+ userAuthTool.checkUserTagPermission(loginUser);
+
+ boolean success = commonLabelService.moveBottom(labelDto, resultMap, loginUser);
+ result = new Result(success, CodeMessageEnum.success.getCode(), resultMap);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), resultMap);
+ } catch (Exception e){
+ LogUtil.error(e, "标签下的文件置底失败" + JsonUtils.beanToJson(labelDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), resultMap);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+
+
+ /**
+ * @Description: 标签夹置顶
+ * @params: [updateFileDTO]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/tag/top", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String tagTop(@Valid @RequestBody LabelDto labelDto){
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ // 校验标签权限
+ userAuthTool.checkUserTagPermission(loginUser);
+
+ boolean success = commonLabelService.tagTop(labelDto, loginUser);
+ result = new Result(success, CodeMessageEnum.success.getCode(), null);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "标签置顶失败" + JsonUtils.beanToJson(labelDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+ /**
+ * @Description: 标签置底
+ * @params: [updateFileDTO]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/tag/bottom", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String tagBottom(@Valid @RequestBody LabelDto labelDto){
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ // 校验标签权限
+ userAuthTool.checkUserTagPermission(loginUser);
+
+ boolean success = commonLabelService.tagBottom(labelDto, loginUser);
+ result = new Result(success, CodeMessageEnum.success.getCode(), null);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "标签置底失败" + JsonUtils.beanToJson(labelDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+}
diff --git a/src/main/java/com/svnlan/home/controller/DingController.java b/src/main/java/com/svnlan/home/controller/DingController.java
new file mode 100644
index 0000000..2125eee
--- /dev/null
+++ b/src/main/java/com/svnlan/home/controller/DingController.java
@@ -0,0 +1,97 @@
+package com.svnlan.home.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.svnlan.common.GlobalConfig;
+import com.svnlan.common.Result;
+import com.svnlan.exception.CodeMessageEnum;
+import com.svnlan.exception.DingCallbackCrypto;
+import com.svnlan.exception.SvnlanRuntimeException;
+import com.svnlan.home.dto.DingDto;
+import com.svnlan.home.dto.LabelDto;
+import com.svnlan.home.vo.CommonLabelVo;
+import com.svnlan.jwt.domain.LoginUser;
+import com.svnlan.utils.JsonUtils;
+import com.svnlan.utils.LogUtil;
+import org.apache.tomcat.util.bcel.classfile.Constant;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/3/28 14:54
+ */
+@RestController
+public class DingController {
+
+
+ @Value("${dingding.token}")
+ private String dingToken;
+ @Value("${dingding.aes.key}")
+ private String dingAesKey;
+ @Value("${dingding.app.key}")
+ private String ownKey;
+
+ @PostMapping("/api/disk/dingCallback2")
+ public Map eventCallback(HttpServletRequest request,
+ @RequestParam(value = "msg_signature", required = false) String msg_signature,
+ @RequestParam(value = "timestamp", required = false) String timeStamp,
+ @RequestParam(value = "nonce", required = false) String nonce,
+ @RequestBody(required = false) JSONObject json) throws DingCallbackCrypto.DingTalkEncryptException {
+ DingCallbackCrypto callbackCrypto = new DingCallbackCrypto(dingToken, dingAesKey, ownKey);
+ Map successMap = callbackCrypto.getEncryptedMap("success");
+ LogUtil.info(successMap.toString());
+ return successMap;
+ }
+
+ @PostMapping("/api/disk/dingCallback")
+ public Map callBack(
+ @RequestParam(value = "msg_signature", required = false) String msg_signature,
+ @RequestParam(value = "timestamp", required = false) String timeStamp,
+ @RequestParam(value = "nonce", required = false) String nonce,
+ @RequestBody(required = false) JSONObject json) {
+ try {
+ // 1. 从http请求中获取加解密参数
+
+ // 2. 使用加解密类型
+ // Constant.OWNER_KEY 说明:
+ // 1、开发者后台配置的订阅事件为应用级事件推送,此时OWNER_KEY为应用的APP_KEY。
+ // 2、调用订阅事件接口订阅的事件为企业级事件推送,
+ // 此时OWNER_KEY为:企业的appkey(企业内部应用)或SUITE_KEY(三方应用)
+ DingCallbackCrypto callbackCrypto = new DingCallbackCrypto(dingToken, dingAesKey, ownKey);
+ String encryptMsg = json.getString("encrypt");
+ String decryptMsg = callbackCrypto.getDecryptMsg(msg_signature, timeStamp, nonce, encryptMsg);
+
+ // 3. 反序列化回调事件json数据
+ JSONObject eventJson = JSON.parseObject(decryptMsg);
+ String eventType = eventJson.getString("EventType");
+
+ // 4. 根据EventType分类处理
+ if ("check_url".equals(eventType)) {
+ // 测试回调url的正确性
+ LogUtil.info("测试回调url的正确性");
+ } else if ("user_add_org".equals(eventType)) {
+ // 处理通讯录用户增加事件
+ LogUtil.info("发生了:" + eventType + "事件");
+ } else {
+ // 添加其他已注册的
+ LogUtil.info("发生了:" + eventType + "事件");
+ }
+
+ // 5. 返回success的加密数据
+ Map successMap = callbackCrypto.getEncryptedMap("success");
+ return successMap;
+
+ } catch (DingCallbackCrypto.DingTalkEncryptException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/svnlan/home/controller/ExplorerFileController.java b/src/main/java/com/svnlan/home/controller/ExplorerFileController.java
new file mode 100644
index 0000000..995b228
--- /dev/null
+++ b/src/main/java/com/svnlan/home/controller/ExplorerFileController.java
@@ -0,0 +1,111 @@
+package com.svnlan.home.controller;
+
+import com.svnlan.common.Result;
+import com.svnlan.exception.CodeMessageEnum;
+import com.svnlan.exception.SvnlanRuntimeException;
+import com.svnlan.home.dto.HomeExplorerDTO;
+import com.svnlan.home.service.ExplorerFileService;
+import com.svnlan.jwt.domain.LoginUser;
+import com.svnlan.jwt.tool.JWTTool;
+import com.svnlan.utils.JsonUtils;
+import com.svnlan.utils.LogUtil;
+import com.svnlan.utils.LoginUserUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/4/25 14:15
+ */
+@RestController
+public class ExplorerFileController {
+
+ @Autowired
+ ExplorerFileService explorerFileService;
+ @Resource
+ JWTTool jwtTool;
+ @Resource
+ LoginUserUtil loginUserUtil;
+
+ /**
+ * @Description: 压缩包预览
+ * @params: [homeExp, request]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/4/25 14:23
+ * @Modified:
+ */
+ @GetMapping("/api/disk/unzipList")
+ public String unzipList(HomeExplorerDTO homeExp, HttpServletRequest request) {
+ String prefix = this.jwtTool.findApiPrefix(request);
+ Result result;
+ Object re;
+ LoginUser loginUser = loginUserUtil.getLoginUser(request);
+ try {
+ if (ObjectUtils.isEmpty(loginUser)){
+ loginUser = new LoginUser();
+ loginUser.setUserID(0L);
+ loginUser.setUserType(4);
+ loginUser.setName("demo");
+ loginUser.setNickname("游客");
+ }
+ re = explorerFileService.unzipList(homeExp, loginUser);
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error(e, prefix + " Svnlan error!");
+ //处理异常
+ result = new Result(false, e.getErrorCode(), null);
+ return JsonUtils.beanToJson(result);
+ } catch (Exception e) {
+ LogUtil.error(e, prefix + " Exception error!");
+ //处理异常
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ // 返回平台信息
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ return JsonUtils.beanToJson(result);
+ }
+ /**
+ * @Description: 查看压缩包是否有密码
+ * @params: [homeExp, request]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/5/5 14:54
+ * @Modified:
+ */
+ @GetMapping("/api/disk/checkIsEncrypted")
+ public String checkZipIsEncrypted(HomeExplorerDTO homeExp, HttpServletRequest request) {
+ String prefix = this.jwtTool.findApiPrefix(request);
+ Result result;
+ Object re;
+ LoginUser loginUser = loginUserUtil.getLoginUser(request);
+ try {
+ if (ObjectUtils.isEmpty(loginUser)){
+ result = new Result(false, CodeMessageEnum.bindSignError.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ re = explorerFileService.checkZipIsEncrypted(homeExp);
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error(e, prefix + " Svnlan error!");
+ //处理异常
+ result = new Result(false, e.getErrorCode(), null);
+ return JsonUtils.beanToJson(result);
+ } catch (Exception e) {
+ LogUtil.error(e, prefix + " Exception error!");
+ //处理异常
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ // 返回平台信息
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ return JsonUtils.beanToJson(result);
+ }
+
+}
diff --git a/src/main/java/com/svnlan/home/controller/ExplorerOperationsController.java b/src/main/java/com/svnlan/home/controller/ExplorerOperationsController.java
new file mode 100644
index 0000000..3f9b919
--- /dev/null
+++ b/src/main/java/com/svnlan/home/controller/ExplorerOperationsController.java
@@ -0,0 +1,105 @@
+package com.svnlan.home.controller;
+
+import com.svnlan.common.GlobalConfig;
+import com.svnlan.common.Result;
+import com.svnlan.exception.CodeMessageEnum;
+import com.svnlan.exception.SvnlanRuntimeException;
+import com.svnlan.home.dto.CheckFileDTO;
+import com.svnlan.home.dto.ExplorerOperationsDTO;
+import com.svnlan.home.dto.ExplorerShareDTO;
+import com.svnlan.home.service.ExplorerOperationsService;
+import com.svnlan.home.vo.HomeExplorerVO;
+import com.svnlan.jwt.domain.LoginUser;
+import com.svnlan.jwt.tool.JWTTool;
+import com.svnlan.utils.JsonUtils;
+import com.svnlan.utils.LogUtil;
+import com.svnlan.utils.LoginUserUtil;
+import io.swagger.annotations.Api;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+
+/**
+ * @author KingMgg
+ * @data 2023/2/7 16:07
+ */
+@Api("用户操作")
+@RestController
+public class ExplorerOperationsController {
+
+ @Autowired
+ ExplorerOperationsService operationsService;
+ @Resource
+ JWTTool jwtTool;
+ @Resource
+ LoginUserUtil loginUserUtil;
+
+
+ /**
+ * 初始化io_source的 parentLevel 父路径id; 例如: ,0,2,5,10,
+ *
+ * @param
+ * @return
+ */
+ @RequestMapping(value = "/api/disk/initSourcePathLevel", method = RequestMethod.GET)
+ public String initSourcePathLevel(ExplorerOperationsDTO dto) {
+ Result result;
+ try {
+ operationsService.initSourcePathLevel(dto.getSourceID());
+ result = new Result(true, CodeMessageEnum.success.getCode(), null);
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error(e, " initSourcePathLevel Svnlan error!");
+ //处理异常
+ result = new Result(false, e.getErrorCode(), null);
+ return JsonUtils.beanToJson(result);
+ } catch (Exception e) {
+ LogUtil.error(e, " initSourcePathLevel Exception error!");
+ //处理异常
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 根据入参统计文件夹的size
+ * @params: [operation 需要统计的文件夹ID(多个用英文逗号,隔开),status=1则统计未删除的,不传默认都统计]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/9/9 12:51
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/countSize", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String zip(@RequestBody CheckFileDTO updateFileDTO) {
+ Result result;
+ Map resultMap = new HashMap<>(1);
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ if (ObjectUtils.isEmpty(loginUser.getUserType()) || loginUser.getUserType().intValue() != 1) {
+ result = new Result(false, CodeMessageEnum.errorAdminAuth.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ try {
+ operationsService.countSize(updateFileDTO, resultMap, loginUser);
+ result = new Result(true, CodeMessageEnum.success.getCode(), resultMap);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), resultMap);
+ } catch (Exception e) {
+ LogUtil.error(e, "压缩zip失败" + JsonUtils.beanToJson(updateFileDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), resultMap);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+
+}
diff --git a/src/main/java/com/svnlan/home/controller/FileDocConvertController.java b/src/main/java/com/svnlan/home/controller/FileDocConvertController.java
new file mode 100644
index 0000000..0ec506b
--- /dev/null
+++ b/src/main/java/com/svnlan/home/controller/FileDocConvertController.java
@@ -0,0 +1,107 @@
+package com.svnlan.home.controller;
+
+import com.svnlan.common.GlobalConfig;
+import com.svnlan.common.Result;
+import com.svnlan.exception.CodeMessageEnum;
+import com.svnlan.exception.SvnlanRuntimeException;
+import com.svnlan.home.dto.CheckFileDTO;
+import com.svnlan.home.service.FileDocConvertService;
+import com.svnlan.jwt.domain.LoginUser;
+import com.svnlan.jwt.tool.JWTTool;
+import com.svnlan.utils.JsonUtils;
+import com.svnlan.utils.LogUtil;
+import com.svnlan.utils.LoginUserUtil;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.http.MediaType;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/6/28 13:40
+ */
+@RestController
+public class FileDocConvertController {
+
+ @Resource
+ FileDocConvertService fileDocConvertService;
+ @Resource
+ JWTTool jwtTool;
+ @Resource
+ LoginUserUtil loginUserUtil;
+ @Resource
+ StringRedisTemplate stringRedisTemplate;
+
+ /**
+ * @Description: 文件互转功能
+ * @params: [updateFileDTO, request]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/6/28 14:02
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/doc/convert", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String doc2Convert(@RequestBody CheckFileDTO updateFileDTO, HttpServletRequest request){
+ String prefix = this.jwtTool.findApiPrefix(request);
+ Result result;
+ Map re = null;
+ try {
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ LogUtil.info(prefix + " videoCommonDto=" + JsonUtils.beanToJson(updateFileDTO));
+ re = fileDocConvertService.doc2Convert(updateFileDTO, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, prefix + "文件互转失败 " + JsonUtils.beanToJson(updateFileDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ // 视频转码
+ /*if (!CollectionUtils.isEmpty(list)) {
+ for (CommonSource source : list) {
+ ConvertDTO convertDTO = new ConvertDTO();
+ convertDTO.setBusId(source.getSourceID());
+ convertDTO.setBusType("cloud");
+ convertDTO.setOtherType("docConvert");
+ String serverUrl = HttpUtil.getRequestRootUrl(null);
+ source.setDomain(serverUrl);
+ convertDTO.setDomain(serverUrl);
+ convertUtil.doConvert(convertDTO, source);
+ }
+ }*/
+ return JsonUtils.beanToJson(result);
+ }
+
+ @RequestMapping(value = "/api/disk/doc/convert/taskAction", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String zipTaskAction(HttpServletResponse response, CheckFileDTO updateFileDTO) {
+ Result result;
+ Map resultMap = new HashMap<>(1);
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ boolean success = true;
+ try {
+ success = fileDocConvertService.taskAction(updateFileDTO, resultMap, loginUser);
+ result = new Result(success, CodeMessageEnum.success.getCode(), resultMap);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), resultMap);
+ } catch (Exception e) {
+ LogUtil.error(e, "taskAction转换失败" + JsonUtils.beanToJson(updateFileDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), resultMap);
+ }
+ if (!ObjectUtils.isEmpty(resultMap) && resultMap.containsKey("status") && "1".equals(resultMap.get("status").toString())) {
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+}
diff --git a/src/main/java/com/svnlan/home/controller/FilePreViewController.java b/src/main/java/com/svnlan/home/controller/FilePreViewController.java
new file mode 100644
index 0000000..1b7a4f2
--- /dev/null
+++ b/src/main/java/com/svnlan/home/controller/FilePreViewController.java
@@ -0,0 +1,56 @@
+package com.svnlan.home.controller;
+
+import com.svnlan.annotation.VisitRecord;
+import com.svnlan.common.Result;
+import com.svnlan.exception.CodeMessageEnum;
+import com.svnlan.exception.SvnlanRuntimeException;
+import com.svnlan.home.dto.CheckFileDTO;
+import com.svnlan.home.service.FilePreViewService;
+import com.svnlan.jwt.domain.LoginUser;
+import com.svnlan.utils.JsonUtils;
+import com.svnlan.utils.LogUtil;
+import com.svnlan.utils.LoginUserUtil;
+import org.springframework.http.MediaType;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/4/26 16:38
+ */
+@RestController
+public class FilePreViewController {
+ @Resource
+ LoginUserUtil loginUserUtil;
+ @Resource
+ FilePreViewService filePreViewService;
+
+ @RequestMapping(value = "/api/disk/previewXml", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String preview(HttpServletResponse response, CheckFileDTO checkFileDTO){
+
+ if (ObjectUtils.isEmpty(checkFileDTO.getShareCode())){
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ if (ObjectUtils.isEmpty(loginUser)){
+ Result result = new Result(false, CodeMessageEnum.bindSignError.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ checkFileDTO.setLoginUser(loginUser);
+ }
+ try {
+ return filePreViewService.getPreviewXml(checkFileDTO);
+ } catch (SvnlanRuntimeException e){
+ LogUtil.error(e, "previewXml 云盘获取预览信息失败");
+ } catch (Exception e){
+ LogUtil.error(e, "previewXml error 云盘获取预览信息失败");
+
+ }
+ return "";
+ }
+}
diff --git a/src/main/java/com/svnlan/home/controller/HomeExplorerController.java b/src/main/java/com/svnlan/home/controller/HomeExplorerController.java
new file mode 100644
index 0000000..e908fbb
--- /dev/null
+++ b/src/main/java/com/svnlan/home/controller/HomeExplorerController.java
@@ -0,0 +1,501 @@
+package com.svnlan.home.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.svnlan.annotation.VisitRecord;
+import com.svnlan.common.GlobalConfig;
+import com.svnlan.common.Result;
+import com.svnlan.exception.CodeMessageEnum;
+import com.svnlan.exception.SvnlanRuntimeException;
+import com.svnlan.home.domain.CommonSource;
+import com.svnlan.home.domain.IOSource;
+import com.svnlan.home.dto.AddCloudDirectoryDTO;
+import com.svnlan.home.dto.AddSubCloudDirectoryDTO;
+import com.svnlan.home.dto.HomeExplorerDTO;
+import com.svnlan.home.dto.HomeSettingDTO;
+import com.svnlan.home.service.HomeExplorerService;
+import com.svnlan.home.service.SourceFileService;
+import com.svnlan.home.service.SourceHistoryService;
+import com.svnlan.home.vo.*;
+import com.svnlan.jwt.domain.LoginUser;
+import com.svnlan.jwt.tool.JWTTool;
+import com.svnlan.user.service.IoSourceService;
+import com.svnlan.user.service.SystemLogService;
+import com.svnlan.utils.JsonUtils;
+import com.svnlan.utils.LogUtil;
+import com.svnlan.utils.LoginUserUtil;
+import com.svnlan.utils.PageResult;
+import io.swagger.annotations.Api;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author KingMgg
+ * @data 2023/2/6 11:43
+ */
+@Api("首页的文件管理目录")
+@RestController
+public class HomeExplorerController {
+
+ @Autowired
+ HomeExplorerService homeExplorerService;
+
+ @Resource
+ private LoginUserUtil loginUserUtil;
+ @Resource
+ JWTTool jwtTool;
+ @Resource
+ SourceHistoryService sourceHistoryService;
+ @Resource
+ IoSourceService ioSourceService;
+ @Resource
+ SourceFileService sourceFileService;
+ @Resource
+ StringRedisTemplate stringRedisTemplate;
+
+
+ @Resource
+ private SystemLogService systemLogService;
+
+ /**
+ * 获取文件目录
+ *
+ * @param homeExp
+ * @return
+ */
+ @VisitRecord(isAsync = true)
+ @GetMapping("/api/disk/list/path")
+ public String homeExplorer(HomeExplorerDTO homeExp, HttpServletRequest request) {
+ String prefix = this.jwtTool.findApiPrefix(request);
+ Result result;
+ HomeExplorerResult explorerResult;
+ LoginUser loginUser = loginUserUtil.getLoginUser(request);
+ try {
+ if (ObjectUtils.isEmpty(loginUser)) {
+ result = new Result(false, CodeMessageEnum.bindSignError.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ explorerResult = homeExplorerService.homeExplorer(homeExp, loginUser);
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error(e, prefix + " Svnlan error!");
+ //处理异常
+ result = new Result(false, e.getErrorCode(), e.getMessage());
+ return JsonUtils.beanToJson(result);
+ } catch (Exception e) {
+ LogUtil.error(e, prefix + " Exception error!");
+ //处理异常
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ // 返回平台信息
+ result = new Result(true, CodeMessageEnum.success.getCode(), explorerResult);
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * 获取文件详情
+ *
+ * @param
+ * @return
+ */
+ @VisitRecord(isAsync = true)
+ @GetMapping("/api/disk/getFileDetail")
+ public String getFileDetail(HomeExplorerVO homeExplorerVO, HttpServletRequest request) {
+ String prefix = this.jwtTool.findApiPrefix(request);
+ HomeFileDetailVO fileDetail;
+ Result result;
+ try {
+ fileDetail = homeExplorerService.getFileDetail(homeExplorerVO);
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error(e, prefix + " Svnlan error!");
+ //处理异常
+ result = new Result(false, e.getErrorCode(), null);
+ return JsonUtils.beanToJson(result);
+ } catch (Exception e) {
+ LogUtil.error(e, prefix + " Exception error!");
+ //处理异常
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ result = new Result(true, CodeMessageEnum.success.getCode(), fileDetail);
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 创建文件夹
+ * @params: [homeExplorerVO, httpServletRequest]
+ * @Return: com.svnlan.common.Result
+ * @Modified:
+ */
+ @PostMapping("/api/disk/createFolder")
+ public String createFolder(@RequestBody HomeExplorerVO homeExplorerVO, HttpServletRequest httpServletRequest) {
+ String prefix = this.jwtTool.findApiPrefix(httpServletRequest);
+ LoginUser loginUser = loginUserUtil.getLoginUser(httpServletRequest);
+ if (null == loginUser.getUserID()) {
+ throw new SvnlanRuntimeException(CodeMessageEnum.loginFirst.getMsg());
+ }
+ Result result;
+ homeExplorerVO.setTargetID(loginUser.getUserID());
+ homeExplorerVO.setCreateUser(loginUser.getUserID());
+ homeExplorerVO.setModifyUser(loginUser.getUserID());
+ homeExplorerVO.setIsFolder(1);
+ try {
+ IOSource source = homeExplorerService.createDir(homeExplorerVO, loginUser);
+ Map resultMap = new HashMap<>(1);
+ resultMap.put("source", source);
+ result = new Result(true, CodeMessageEnum.success.getCode(), resultMap);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error(e, prefix + " Svnlan error!");
+ //处理异常
+ result = new Result(false, e.getErrorCode(),e.getMessage(), null);
+ return JsonUtils.beanToJson(result);
+ } catch (Exception e) {
+ LogUtil.error(e, prefix + " Exception error!");
+ //处理异常
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 设置文件夹操作(排序、图标大小等)
+ * @params: [homeExplorerVO, httpServletRequest]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/2/18 10:51
+ * @Modified:
+ */
+ @PostMapping("/api/disk/folder/setting")
+ public String folderSetting(@RequestBody HomeSettingDTO homeExplorerVO, HttpServletRequest httpServletRequest) {
+ String prefix = this.jwtTool.findApiPrefix(httpServletRequest);
+ LoginUser loginUser = loginUserUtil.getLoginUser(httpServletRequest);
+ if (null == loginUser.getUserID()) {
+ throw new SvnlanRuntimeException(CodeMessageEnum.loginFirst.getMsg());
+ }
+ Result result;
+ homeExplorerVO.setTargetID(loginUser.getUserID());
+ homeExplorerVO.setCreateUser(loginUser.getUserID());
+ homeExplorerVO.setModifyUser(loginUser.getUserID());
+ homeExplorerVO.setIsFolder(1);
+ try {
+ homeExplorerService.folderSetting(homeExplorerVO, loginUser);
+
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error(e, prefix + " Svnlan error!");
+ //处理异常
+ result = new Result(false, e.getErrorCode(), null);
+ return JsonUtils.beanToJson(result);
+ } catch (Exception e) {
+ LogUtil.error(e, prefix + " Exception error!");
+ //处理异常
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ result = new Result(true, CodeMessageEnum.success.getCode(), true);
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 文件动态
+ * @params: [homeExplorerVO, request]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/2/22 16:10
+ * @Modified:
+ */
+ @GetMapping("/api/disk/pathLog")
+ public String pathLog(HomeExplorerDTO homeExplorerVO, HttpServletRequest request) {
+ String prefix = this.jwtTool.findApiPrefix(request);
+ PageResult re;
+ Result result;
+ try {
+ re = homeExplorerService.getPathLog(homeExplorerVO);
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error(e, prefix + " Svnlan error!");
+ //处理异常
+ result = new Result(false, e.getErrorCode(), null);
+ return JsonUtils.beanToJson(result);
+ } catch (Exception e) {
+ LogUtil.error(e, prefix + " Exception error!");
+ //处理异常
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * 获取系统设置
+ *
+ * @param
+ * @return
+ */
+ @VisitRecord(isAsync = true)
+ @GetMapping("/api/disk/home")
+ public String home(HttpServletRequest request) {
+ String prefix = this.jwtTool.findApiPrefix(request);
+ Result result;
+ Map explorerResult;
+ try {
+ explorerResult = homeExplorerService.systemOpenInfo();
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error(e, prefix + " Svnlan error!");
+ //处理异常
+ result = new Result(false, e.getErrorCode(), null);
+ return JsonUtils.beanToJson(result);
+ } catch (Exception e) {
+ LogUtil.error(e, prefix + " Exception error!");
+ //处理异常
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ // 返回平台信息
+ result = new Result(true, CodeMessageEnum.success.getCode(), explorerResult);
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * 获取文件历史记录
+ *
+ * @param
+ * @return
+ */
+ @GetMapping("/api/disk/history/get")
+ public String sourceHistoryList(HttpServletRequest request, HomeExplorerDTO homeExplorerDTO) {
+ String prefix = this.jwtTool.findApiPrefix(request);
+ Result result;
+ HomeExplorerResult explorerResult;
+ try {
+ explorerResult = sourceHistoryService.getSourceHistoryList(homeExplorerDTO);
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error(e, prefix + " Svnlan error!");
+ //处理异常
+ result = new Result(false, e.getErrorCode(), null);
+ return JsonUtils.beanToJson(result);
+ } catch (Exception e) {
+ LogUtil.error(e, prefix + " Exception error!");
+ //处理异常
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ // 返回平台信息
+ result = new Result(true, CodeMessageEnum.success.getCode(), explorerResult);
+ return JsonUtils.beanToJson(result);
+ }
+
+ @PostMapping("/api/disk/history/setDetail")
+ public String sourceHistorySetDetail(HttpServletRequest request, @RequestBody HomeExplorerDTO homeExplorerDTO) {
+ String prefix = this.jwtTool.findApiPrefix(request);
+ Result result;
+ try {
+ sourceHistoryService.setHistoryDetail(homeExplorerDTO);
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error(e, prefix + " Svnlan error!");
+ //处理异常
+ result = new Result(false, e.getErrorCode(), null);
+ return JsonUtils.beanToJson(result);
+ } catch (Exception e) {
+ LogUtil.error(e, prefix + " Exception error!");
+ //处理异常
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ // 返回平台信息
+ result = new Result(true, CodeMessageEnum.success.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+
+
+ /**
+ * @Description: 删除历史版本
+ * @params: [request, homeExplorerDTO]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/3/31 15:48
+ * @Modified:
+ */
+ @PostMapping("/api/disk/history/delete")
+ public String sourceHistoryDelete(HttpServletRequest request, @RequestBody HomeExplorerDTO homeExplorerDTO) {
+ String prefix = this.jwtTool.findApiPrefix(request);
+ Result result;
+ try {
+ sourceHistoryService.deleteHistory(homeExplorerDTO);
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error(e, prefix + " Svnlan error!");
+ //处理异常
+ result = new Result(false, e.getErrorCode(), null);
+ return JsonUtils.beanToJson(result);
+ } catch (Exception e) {
+ LogUtil.error(e, prefix + " Exception error!");
+ //处理异常
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ // 返回平台信息
+ result = new Result(true, CodeMessageEnum.success.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 历史记录设置当前版本
+ * @params: [request, homeExplorerDTO]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/4/20 11:23
+ * @Modified:
+ */
+ @PostMapping("/api/disk/history/setVersion")
+ public String setHistoryRevision(HttpServletRequest request, @RequestBody HomeExplorerDTO homeExplorerDTO) {
+ String prefix = this.jwtTool.findApiPrefix(request);
+ Result result;
+ try {
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ sourceHistoryService.setHistoryRevision(homeExplorerDTO, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error(e, prefix + " Svnlan error!");
+ //处理异常
+ result = new Result(false, e.getErrorCode(), null);
+ return JsonUtils.beanToJson(result);
+ } catch (Exception e) {
+ LogUtil.error(e, prefix + " Exception error!");
+ //处理异常
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ // 返回平台信息
+ result = new Result(true, CodeMessageEnum.success.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+
+ @GetMapping("/api/disk/parentSourceList")
+ public String parentSourceList(HttpServletRequest request, HomeExplorerDTO homeExplorerDTO) {
+ String prefix = this.jwtTool.findApiPrefix(request);
+ Result result;
+ List re;
+ try {
+ re = sourceHistoryService.parentSourceList(homeExplorerDTO, loginUserUtil.getLoginUser());
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error(e, prefix + " Svnlan error!");
+ //处理异常
+ result = new Result(false, e.getErrorCode(), null);
+ return JsonUtils.beanToJson(result);
+ } catch (Exception e) {
+ LogUtil.error(e, prefix + " Exception error!");
+ //处理异常
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ // 返回平台信息
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ return JsonUtils.beanToJson(result);
+ }
+
+
+ /**
+ * 获取用户文件类型占比
+ */
+ @GetMapping("/api/disk/userProportion")
+ public Result getFileTypeProportionByUserId() {
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ List jsonList = ioSourceService.getFileTypeProportionByUserId(loginUser.getUserID());
+
+ return Result.returnSuccess(
+ new JSONObject().fluentPut("fileTypeProportion", jsonList)
+ );
+ }
+
+ @RequestMapping(value = "/api/disk/addBatchDirectory", method = RequestMethod.POST)
+ public String addBatchDirectory(@Valid @RequestBody AddCloudDirectoryDTO addCloudDirectoryDTO) {
+ Result result = null;
+ try {
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ List list = sourceFileService.addBatchDirectory(addCloudDirectoryDTO, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), list);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), e.getMessage(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "云盘文件夹批量创建失败" + JsonUtils.beanToJson(addCloudDirectoryDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ @RequestMapping(value = "/api/disk/homeExplorer", method = RequestMethod.GET)
+ public String homeExplorerVo(HomeExplorerDTO homeExp, HttpServletRequest request) {
+ Result result = null;
+ try {
+ HomeExplorerVO re = homeExplorerService.getHomeExplorer(homeExp, loginUserUtil.getLoginUser());
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "/api/disk/homeExplorer获取详情" + JsonUtils.beanToJson(homeExp));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ @RequestMapping(value = "/api/disk/execImgVideoThumb", method = RequestMethod.GET)
+ public String execImgVideoThumb(HomeExplorerDTO homeExp, HttpServletRequest request) {
+ Result result = null;
+ try {
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ HomeExplorerVO re = homeExplorerService.execImgVideoThumb(homeExp, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "/api/disk/execImgVideoThumb" + JsonUtils.beanToJson(homeExp));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * 用户登陆设置统计
+ */
+ @RequestMapping(value = "/api/disk/loginDevice/stat", method = RequestMethod.GET)
+ public Result userLoginDeviceStat() {
+ return Result.returnSuccess(systemLogService.selectUserLoginDeviceStat(30, loginUserUtil.getLoginUserId()));
+ }
+
+ /**
+ * @Description: 获得文件夹下的图片列表
+ * @params: [homeExp, request]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/getImgList", method = RequestMethod.GET)
+ public String getImgList(HomeExplorerDTO homeExp) {
+ Result result = null;
+ try {
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ List re = sourceFileService.getImgList(homeExp, loginUser);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "/api/disk/getImgList" + JsonUtils.beanToJson(homeExp));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+}
+
+
diff --git a/src/main/java/com/svnlan/home/controller/M3u8Controller.java b/src/main/java/com/svnlan/home/controller/M3u8Controller.java
new file mode 100644
index 0000000..cd4bab2
--- /dev/null
+++ b/src/main/java/com/svnlan/home/controller/M3u8Controller.java
@@ -0,0 +1,95 @@
+package com.svnlan.home.controller;
+
+import com.svnlan.exception.SvnlanRuntimeException;
+import com.svnlan.home.service.M3u8Service;
+import com.svnlan.home.dto.*;
+import com.svnlan.home.utils.CommonConvertUtil;
+import com.svnlan.utils.LogUtil;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+
+/**
+ * @Author:
+ * @Description:
+ * @Date:
+ */
+@RestController
+public class M3u8Controller {
+ @Resource
+ private M3u8Service m3u8Service;
+ @Resource
+ private CommonConvertUtil commonConvertUtil;
+
+ @RequestMapping(value = "/api/disk/mu/key", method = RequestMethod.GET)
+ public String getKey(HttpServletResponse response,String key){
+ try {
+ m3u8Service.getKey(key,response);
+ } catch (Exception e){
+ LogUtil.error(e, "获取key失败");
+ }
+ return "error";
+ }
+
+ @RequestMapping(value = "/api/disk/mu/getM3u8.m3u8", method = RequestMethod.GET)
+ public String getM3u8(HttpServletResponse response, HttpServletRequest request, GetM3u8DTO getM3u8DTO){
+ try {
+ m3u8Service.getM3u8(getM3u8DTO, response, request);
+ } catch (SvnlanRuntimeException e) {
+ return e.getMessage();
+ } catch (Exception e){
+ LogUtil.error(e, "获取m3u8失败");
+ }
+ return "error";
+ }
+
+ /**
+ * @Description: m3u8鉴权接口
+ * @params: [response, request, getM3u8DTO]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/mu/getMyM3u8.m3u8", method = RequestMethod.GET)
+ public String getM3u8WithAuth(HttpServletResponse response, HttpServletRequest request,@Valid GetM3u8NewDTO getM3u8DTO){
+ try {
+ String m3u8WithAuth = m3u8Service.getM3u8WithAuth(getM3u8DTO, response, request, 0);
+ if (m3u8WithAuth != null){
+ return m3u8WithAuth;
+ }
+ } catch (SvnlanRuntimeException e) {
+ return e.getMessage();
+ } catch (Exception e){
+ LogUtil.error(e, "获取m3u8失败");
+ }
+ return "error";
+ }
+
+
+ /**
+ * @Description: m3u8鉴权接口api
+ * @params: [response, request, getM3u8DTO]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/service/mu/getMyM3u8.m3u8", method = RequestMethod.GET)
+ public String getCommonM3u8WithAuth(HttpServletResponse response, HttpServletRequest request, GetMyM3u8DTO getMyM3u8DTO){
+ GetM3u8NewDTO getM3u8DTO;
+ try {
+ getM3u8DTO = commonConvertUtil.convertGetM3u8NewDTO(getMyM3u8DTO);
+ String m3u8WithAuth = m3u8Service.getM3u8WithAuth(getM3u8DTO, response, request, 1);
+ if (m3u8WithAuth != null){
+ return m3u8WithAuth;
+ }
+ } catch (SvnlanRuntimeException e) {
+ return e.getMessage();
+ } catch (Exception e){
+ LogUtil.error(e, "/api/common/service/mu/getMyM3u8.m3u8 获取m3u8失败");
+ }
+ return "error";
+ }
+}
diff --git a/src/main/java/com/svnlan/home/controller/NoticeController.java b/src/main/java/com/svnlan/home/controller/NoticeController.java
new file mode 100644
index 0000000..75d6138
--- /dev/null
+++ b/src/main/java/com/svnlan/home/controller/NoticeController.java
@@ -0,0 +1,66 @@
+package com.svnlan.home.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.google.common.collect.Lists;
+import com.svnlan.common.Result;
+import com.svnlan.user.service.NoticeService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * C 端 通知
+ *
+ * @author lingxu 2023/05/20 10:54
+ */
+@Slf4j
+@RestController("noticeWebController")
+@RequestMapping("api/notice")
+public class NoticeController {
+ @Resource
+ private NoticeService noticeService;
+
+ /**
+ * C端查询通知消息列表
+ */
+ @GetMapping("read/list/page")
+ public Result noticeList(@RequestParam("currentPage") Integer currentPage, @RequestParam("pageSize") Integer pageSize) {
+ JSONObject jsonObject = noticeService.pageList(currentPage, pageSize);
+ return Result.returnSuccess(jsonObject);
+ }
+
+
+ /**
+ * C端查询未读消息数
+ */
+ @GetMapping("unread")
+ public Result hasNoticeUnread() {
+ return Result.returnSuccess(noticeService.hasNoticeUnread());
+ }
+
+ /**
+ * C端消息信息
+ */
+ @GetMapping("info")
+ public Result noticeInfo(Long id) {
+
+ List ids = Lists.asList(id, new Long[]{});
+ List previewList = noticeService.preview(ids);
+ if (!CollectionUtils.isEmpty(previewList)) {
+ JSONObject jsonObject = previewList.get(0);
+ if (Objects.equals(jsonObject.getInteger("status"), 1)) {
+ noticeService.executeNoticeRead(id);
+ return Result.returnSuccess(previewList.get(0));
+ }
+ }
+ return Result.returnSuccess();
+ }
+
+}
diff --git a/src/main/java/com/svnlan/home/controller/ShareController.java b/src/main/java/com/svnlan/home/controller/ShareController.java
new file mode 100644
index 0000000..d84f7ba
--- /dev/null
+++ b/src/main/java/com/svnlan/home/controller/ShareController.java
@@ -0,0 +1,333 @@
+package com.svnlan.home.controller;
+
+import com.svnlan.annotation.CreateGroup;
+import com.svnlan.common.GlobalConfig;
+import com.svnlan.common.Result;
+import com.svnlan.exception.CodeMessageEnum;
+import com.svnlan.exception.SvnlanRuntimeException;
+import com.svnlan.home.dto.HomeExplorerDTO;
+import com.svnlan.home.dto.ShareDTO;
+import com.svnlan.home.service.ShareService;
+import com.svnlan.home.vo.HomeExplorerResult;
+import com.svnlan.home.vo.ShareVo;
+import com.svnlan.jwt.domain.LoginUser;
+import com.svnlan.user.dto.ShareReportDTO;
+import com.svnlan.user.dto.UserDTO;
+import com.svnlan.user.service.ShareReportService;
+import com.svnlan.user.vo.SelectAuthVo;
+import com.svnlan.utils.JsonUtils;
+import com.svnlan.utils.LogUtil;
+import com.svnlan.utils.LoginUserUtil;
+import com.svnlan.utils.PageResult;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Author: sulijuan
+ * @Description: 分享/协作
+ * @Date: 2023/3/3 13:33
+ */
+@RestController
+public class ShareController {
+
+ @Resource
+ LoginUserUtil loginUserUtil;
+ @Resource
+ ShareService shareService;
+ @Resource
+ StringRedisTemplate stringRedisTemplate;
+
+ /**
+ * @Description: 添加外部分享
+ * @params: [shareDTO]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/3/3 14:41
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/userShare/save", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String saveShare(@Valid @RequestBody ShareDTO shareDTO) {
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ shareService.saveShare(shareDTO, loginUser);
+ stringRedisTemplate.delete(GlobalConfig.my_share_key + loginUser.getUserID());
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), null);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "保存分享失败" + JsonUtils.beanToJson(shareDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 取消外部分享
+ * @params: [shareDTO]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/3/3 14:41
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/userShare/cancel", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String cancelShare(@Valid @RequestBody ShareDTO shareDTO) {
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ shareService.cancelShare(shareDTO, loginUser);
+ stringRedisTemplate.delete(GlobalConfig.my_share_key + loginUser.getUserID());
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), null);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "取消分享失败" + JsonUtils.beanToJson(shareDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 获得单个分享链接详情
+ * @params: [labelDto]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/3/3 13:37
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/userShare/get", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String getShare(ShareDTO shareDTO) {
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ ShareVo re = shareService.getShare(shareDTO, loginUser);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "获得单个分享链接详情失败" + JsonUtils.beanToJson(shareDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 分享列表
+ * @params: [shareDTO]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/3/8 14:17
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/userShare/list", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String getShareList(HomeExplorerDTO shareDTO) {
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+
+ HomeExplorerResult re = null;
+ try {
+ re = shareService.getShareList(shareDTO, loginUser);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "分享列表" + JsonUtils.beanToJson(shareDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 对外查询分享配置
+ * @params: [shareDTO]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/3/6 16:11
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/share/get", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String getShareFile(ShareDTO shareDTO) {
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ ShareVo re = shareService.getShareFile(shareDTO, loginUser);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, " 对外查询分享配置失败" + JsonUtils.beanToJson(shareDTO));
+ if (e instanceof IllegalArgumentException) {
+ result = new Result(false, e.getMessage());
+ }else{
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 查询分享下文件夹列表
+ * @params: [shareDTO]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/3/7 17:30
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/share/pathList", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String getShareFileList(HomeExplorerDTO shareDTO) {
+ Result result;
+ try {
+ HomeExplorerResult re = shareService.getLinkShareList(shareDTO);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, " 对外查询分享配置失败" + JsonUtils.beanToJson(shareDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ @RequestMapping(value = "/api/disk/share/menu", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String getShareMenuList(HomeExplorerDTO shareDTO) {
+ Result result;
+ try {
+ shareDTO.setIsFolder(1);
+ HomeExplorerResult re = shareService.getLinkShareList(shareDTO);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, " 对外查询分享左边菜单列表失败" + JsonUtils.beanToJson(shareDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 与我协作列表
+ * @params: [shareDTO]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/3/8 14:17
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/userShare/shareToMe", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String shareToMe(HomeExplorerDTO shareDTO) {
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+
+ HomeExplorerResult re = null;
+ try {
+ re = shareService.shareToMeList(shareDTO, loginUser);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "与我协作列表" + JsonUtils.beanToJson(shareDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 选择协作部门或用户列表
+ * @params: [shareDTO]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/3/9 9:10
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/userShare/groupList", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String userGroupList(HomeExplorerDTO shareDTO) {
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+
+ SelectAuthVo re = null;
+ try {
+ re = shareService.userGroupList(shareDTO, loginUser);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "选择协作部门或用户列表 error" + JsonUtils.beanToJson(shareDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ @RequestMapping(value = "/api/disk/share/previewNum", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String previewNum(ShareDTO shareDTO) {
+ Result result;
+ Map re = null;
+ String key = "previewNum_" + shareDTO.getShareCode();
+ try {
+ final Boolean setFlag = this.stringRedisTemplate.opsForValue().setIfAbsent(key, "1");
+ if (setFlag == null || !setFlag) {
+ // 流程处理中
+ re = new HashMap<>(1);
+ re.put("numView", 0);
+ } else {
+ re = shareService.previewNum(shareDTO);
+ }
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, " 对外查询分享配置失败" + JsonUtils.beanToJson(shareDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ } finally {
+ this.stringRedisTemplate.delete(key);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 选择协作部门或用户列表 (用于搜索,只返回用户)
+ * @params: [shareDTO]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/5/8 16:54
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/userShare/userList", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String userList(UserDTO shareDTO) {
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+
+ PageResult re = null;
+ try {
+ re = shareService.getUserList(loginUser, shareDTO);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "选择用户列表 error" + JsonUtils.beanToJson(shareDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ @Resource
+ private ShareReportService shareReportService;
+
+ /**
+ * 对分享的举报
+ * 可以匿名举报
+ */
+ @PostMapping("api/disk/share/report")
+ public Result shareReport(@RequestBody @Validated(CreateGroup.class) ShareReportDTO dto) {
+ shareReportService.shareReport(dto);
+ return Result.returnSuccess();
+ }
+}
diff --git a/src/main/java/com/svnlan/home/controller/UploadController.java b/src/main/java/com/svnlan/home/controller/UploadController.java
new file mode 100644
index 0000000..b39fc90
--- /dev/null
+++ b/src/main/java/com/svnlan/home/controller/UploadController.java
@@ -0,0 +1,888 @@
+package com.svnlan.home.controller;
+
+import com.svnlan.annotation.VisitRecord;
+import com.svnlan.common.GlobalConfig;
+import com.svnlan.common.Result;
+import com.svnlan.exception.CodeMessageEnum;
+import com.svnlan.exception.SvnlanRuntimeException;
+import com.svnlan.home.domain.CommonSource;
+import com.svnlan.home.dto.*;
+import com.svnlan.home.dto.convert.ConvertDTO;
+import com.svnlan.home.service.*;
+import com.svnlan.home.utils.ConvertUtil;
+import com.svnlan.home.utils.FileUtil;
+import com.svnlan.home.utils.UserAuthTool;
+import com.svnlan.home.vo.CommonSourceVO;
+import com.svnlan.home.vo.IoSourceAuthVo;
+import com.svnlan.jwt.domain.LoginUser;
+import com.svnlan.tools.SystemSortTool;
+import com.svnlan.utils.*;
+import com.svnlan.webdav.MimeTypeEnum;
+import org.apache.commons.io.IOUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/16 9:03
+ */
+
+@RestController
+@CrossOrigin
+public class UploadController {
+ @Resource
+ LoginUserUtil loginUserUtil;
+ @Resource
+ ConvertUtil convertUtil;
+ @Resource
+ private UploadService uploadService;
+ @Resource
+ SystemSortTool systemSortTool;
+ @Resource
+ StringRedisTemplate stringRedisTemplate;
+ @Resource
+ private UploadZipService uploadZipService;
+ @Resource
+ private FavService favService;
+ @Resource
+ AuthService authService;
+ @Resource
+ UserAuthTool userAuthTool;
+ @Resource
+ VideoGetService videoGetService;
+
+ @Value("${environment.type}")
+ private String environmentType;
+
+
+ @RequestMapping(value = "/api/disk/upload", method = RequestMethod.POST)
+ public String upload(@Valid UploadDTO uploadDTO) {
+ String uuid = RandomUtil.getuuid();
+ try {
+ String ip = IpUtil.getIp(HttpUtil.getRequest());
+ LogUtil.info("文件大小, " + uploadDTO.getFile().getSize() + ", ip," + ip + ", uuid" + uuid);
+ } catch (Exception e) {
+ LogUtil.error(e, "文件日志失败");
+ }
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ Result result;
+ if (ObjectUtils.isEmpty(loginUser)) {
+ result = new Result(false, CodeMessageEnum.bindSignError.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ try {
+ CommonSource commonSource = new CommonSource();
+ String serverUrl = HttpUtil.getRequestRootUrl(null);
+ commonSource.setDomain(serverUrl);
+
+ CommonSourceVO commonSourceVO = null;
+ if (!ObjectUtils.isEmpty(uploadDTO.getPath()) && !"0".equals(uploadDTO.getPath())) {
+ // 编辑上传覆盖文件
+ commonSourceVO = uploadService.fileUpload(uploadDTO, loginUser, commonSource);
+ } else {
+ // 上传文件
+ commonSourceVO = uploadService.upload(uploadDTO, loginUser, commonSource);
+ }
+
+ if (!ObjectUtils.isEmpty(commonSourceVO.getPath())){
+ commonSourceVO.setPreviewPath(FileUtil.getShowImageUrl(commonSourceVO.getPath(), commonSourceVO.getName()));
+ }
+
+ result = new Result(commonSourceVO.getState().equals(1),
+ CodeMessageEnum.success.getCode(),
+ commonSourceVO);
+
+ // 异步合并则不转码,转码放到异步执行
+ if (ObjectUtils.isEmpty(commonSource.getCheckMerge()) || !commonSource.getCheckMerge()) {
+ commonSource.setUserID(loginUser.getUserID());
+ // 试着转码
+ uploadService.tryToConvertFile(commonSourceVO, commonSource, uploadDTO.getBusType());
+ }
+
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error("上传: " + e.getMessage());
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ uploadDTO.setFile(null);
+ LogUtil.error(e, "上传失败, dto:" + JsonUtils.beanToJson(uploadDTO) + ", e:" + e.getMessage());
+ result = new Result(false, CodeMessageEnum.uploadError.getCode(), null);
+ } finally {
+ stringRedisTemplate.delete(systemSortTool.getUserSpaceKey(loginUser.getUserID()));
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ }
+ String resultStr = JsonUtils.beanToJson(result);
+ LogUtil.info("返回, " + resultStr + ", uuid" + uuid);
+ return resultStr;
+ }
+
+ /**
+ * @Description: 查看文件是否存在, 秒传
+ * @params: [checksum]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/upload/check", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public Result check(@Valid CheckFileDTO checkFileDTO) {
+ String path = ObjectUtils.isEmpty(checkFileDTO.getPath()) ? "file" : checkFileDTO.getPath();
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ switch (path) {
+ case "file":
+ return this.checkFile(checkFileDTO, loginUser);
+ case "chunk":
+ return this.checkChunk(checkFileDTO, loginUser);
+ default:
+ return this.checkFile(checkFileDTO, loginUser);
+ }
+ }
+
+ public Result checkFile(CheckFileDTO checkFileDTO, LoginUser loginUser) {
+ Map resultMap = null;
+ try {
+
+ if (!ObjectUtils.isEmpty(checkFileDTO.getPath()) && !"0".equals(checkFileDTO.getPath())) {
+ // 编辑上传覆盖文件
+ resultMap = uploadService.checkFileReplace(checkFileDTO, loginUser);
+ } else {
+ resultMap = uploadService.checkFile(checkFileDTO, loginUser);
+ }
+ return new Result(true, CodeMessageEnum.success.getCode(), resultMap);
+ } catch (SvnlanRuntimeException e) {
+ return new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "秒传失败");
+ } finally {
+ stringRedisTemplate.delete(systemSortTool.getUserSpaceKey(loginUser.getUserID()));
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ }
+ return new Result(false, CodeMessageEnum.uploadError.getCode(), null);
+ }
+
+ public Result checkChunk(CheckFileDTO checkChunkDTO, LoginUser loginUser) {
+ try {
+ Map resultMap = uploadService.checkChunk(checkChunkDTO, loginUser);
+ return new Result(true, CodeMessageEnum.success.getCode(), resultMap);
+ } catch (SvnlanRuntimeException e) {
+ return new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+
+ }
+ return new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+
+ /**
+ * @Description: 预览
+ * @params: [response, previewAttachDTO]
+ * @Return: void
+ * @Author: sulijuan
+ * @Date: 2023/2/17 10:43
+ * @Modified:
+ */
+ @VisitRecord(isAsync = true)
+ @RequestMapping(value = "/api/disk/preview", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String preview(HttpServletResponse response, CheckFileDTO checkFileDTO) {
+
+ if (ObjectUtils.isEmpty(checkFileDTO.getShareCode())) {
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ if (ObjectUtils.isEmpty(loginUser)) {
+ Result result = new Result(false, CodeMessageEnum.bindSignError.getCode(), null);
+ return JsonUtils.beanToJson(result);
+ }
+ checkFileDTO.setLoginUser(loginUser);
+ }
+ String path = ObjectUtils.isEmpty(checkFileDTO.getPath()) ? "info" : checkFileDTO.getPath();
+ switch (path) {
+ case "attachment":
+ this.previewAttach(response, checkFileDTO);
+ break;
+ case "info":
+ return this.getPreviewInfo(checkFileDTO);
+ case "edit":
+ return this.getPreviewEditInfo(checkFileDTO);
+ case "refresh":
+ return this.getPreviewRefreshInfo(checkFileDTO);
+ case "fileUrl":
+ return this.getPreviewFileUrl(checkFileDTO);
+ default:
+ this.previewAttach(response, checkFileDTO);
+ break;
+ }
+ return "";
+ }
+
+ /**
+ * @Description: 预览
+ * @params: [response, checkFileDTO]
+ * @Return: void
+ * @Author: sulijuan
+ * @Date: 2023/2/17 11:24
+ * @Modified:
+ */
+ public void previewAttach(HttpServletResponse response, CheckFileDTO checkFileDTO) {
+ String resultStr = "";
+ try {
+ resultStr = uploadService.returnSource(checkFileDTO, null, response);
+// response.sendRedirect(resultStr);
+ } catch (SvnlanRuntimeException e) {
+ resultStr = e.getMessage();
+ } catch (Exception e) {
+ LogUtil.error(e, "预览失败" + JsonUtils.beanToJson(checkFileDTO));
+ }
+// return resultStr;
+
+ }
+
+ @RequestMapping(value = "/api/disk/preview/{fileName}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public void previewAttachWithName(HttpServletResponse response, CheckFileDTO previewAttachDTO, @PathVariable("fileName") String passedFileName) {
+ String resultStr = "";
+ try {
+ resultStr = uploadService.returnSource(previewAttachDTO, passedFileName, response);
+// response.sendRedirect(resultStr);
+ } catch (SvnlanRuntimeException e) {
+ resultStr = e.getMessage();
+ } catch (Exception e) {
+ LogUtil.error(e, "预览失败" + JsonUtils.beanToJson(previewAttachDTO));
+ }
+// return resultStr;
+ }
+
+ /**
+ * @Description: 预览信息
+ * @params: [getCloudPreviewDTO]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ public String getPreviewInfo(CheckFileDTO checkFileDTO) {
+ Result result;
+ try {
+ Map re = uploadService.getPreviewInfo(checkFileDTO);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "云盘获取预览信息失败");
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ public String getPreviewEditInfo(CheckFileDTO checkFileDTO) {
+ Result result;
+ try {
+ Map re = favService.getPreviewEditInfo(checkFileDTO);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "云盘获取文档编辑链接信息失败");
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ public String getPreviewRefreshInfo(CheckFileDTO checkFileDTO) {
+ Result result;
+ try {
+ Map re = favService.getPreviewRefreshInfo(checkFileDTO);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ LogUtil.error(e, "云盘获取文档预览信息");
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ public String getPreviewFileUrl(CheckFileDTO checkFileDTO) {
+ return favService.getPreviewFileUrl(checkFileDTO);
+ }
+
+ /**
+ * @Description: 文件操作
+ * @params: [updateFileDTO]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @VisitRecord(isAsync = true)
+ @RequestMapping(value = "/api/disk/operation", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String copyFile(@Valid @RequestBody CheckFileDTO updateFileDTO) {
+ Result result;
+ Map resultMap = new HashMap<>(1);
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ boolean success = uploadService.updateFile(updateFileDTO, resultMap, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerOneRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(success, CodeMessageEnum.success.getCode(), resultMap);
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error(e, "operation操作失败,updateFileDTO=" + JsonUtils.beanToJson(updateFileDTO));
+ result = new Result(false, e.getErrorCode(), e.getMessage(), resultMap);
+ } catch (Exception e) {
+ LogUtil.error(e, "云盘文件复制失败" + JsonUtils.beanToJson(updateFileDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), resultMap);
+ } finally {
+ stringRedisTemplate.delete(systemSortTool.getUserSpaceKey(loginUser.getUserID()));
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * 预览/下载
+ */
+ @RequestMapping(value = "/api/disk/attachment/{fileName}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String getAttachmentWithName(HttpServletResponse response, @Valid GetAttachmentDTO getAttachmentDTO,
+ @PathVariable("fileName") String passedFileName) {
+ String resultStr = "";
+ try {
+ if ("dev".equals(environmentType)){
+ getAttachmentDTO.setGetInfo(2);
+ }
+ Map resultMap = new HashMap<>();
+ resultStr = uploadService.getAttachment(response, getAttachmentDTO, passedFileName, resultMap);
+ LogUtil.info("resultStr=" + resultStr + ",attachment" + JsonUtils.beanToJson(getAttachmentDTO) + ",resultMap=" + JsonUtils.beanToJson(resultMap));
+ if (!StringUtil.isEmpty(resultStr) && resultStr.indexOf("http") == 0) {
+ //获取信息
+ if (getAttachmentDTO.getGetInfo() == 1) {
+ Result result = Result.returnSuccess(resultMap);
+ LogUtil.info("attachment true");
+ return JsonUtils.beanToJson(result);
+ }else {
+ response.sendRedirect(resultStr);
+ }
+ }else {
+ outFile(response,resultStr,passedFileName, true);
+ return "";
+ }
+ } catch (SvnlanRuntimeException e) {
+ resultStr = e.getMessage();
+ } catch (Exception e) {
+ LogUtil.error(e, "预览失败" + JsonUtils.beanToJson(getAttachmentDTO));
+ }
+ LogUtil.info("resultStr=" + resultStr + ",attachment" + JsonUtils.beanToJson(getAttachmentDTO));
+
+ return resultStr;
+ }
+ /**
+ * 视频切图预览/下载
+ */
+ @RequestMapping(value = "/api/disk/video/img/{fileName}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public void getVideoImgAttachmentWithName(HttpServletResponse response, HttpServletRequest request, @Valid VideoCommonDto videoCommonDto,
+ @PathVariable("fileName") String passedFileName) {
+ String resultStr = "";
+ boolean check = true;
+ try {
+ Map resultMap = new HashMap<>();
+ resultStr = videoGetService.getVideoShearImg(response, videoCommonDto, passedFileName, resultMap);
+ /*if (!StringUtil.isEmpty(resultStr) && resultStr.indexOf("http") == 0) {
+ check = true;
+ //获取信息
+ response.sendRedirect(resultStr);
+ }*/
+ } catch (SvnlanRuntimeException e) {
+ resultStr = e.getMessage();
+ check = false;
+ LogUtil.error(e, "getVideoImgAttachmentWithName 预览失败" + JsonUtils.beanToJson(videoCommonDto) + ",resultStr=" + resultStr);
+ } catch (Exception e) {
+ check = false;
+ LogUtil.error(e, "getVideoImgAttachmentWithName 预览失败" + JsonUtils.beanToJson(videoCommonDto) + ",resultStr=" + resultStr);
+ }
+ LogUtil.info(check + "-check,getVideoImgAttachmentWithName resultStr=" + resultStr + ",attachment" + JsonUtils.beanToJson(videoCommonDto));
+
+ boolean isDown = false;
+ if (!ObjectUtils.isEmpty(videoCommonDto.getIsDown()) && "1".equals(videoCommonDto.getIsDown())){
+ isDown = true;
+ }
+
+ String ext = resultStr.substring(resultStr.lastIndexOf(".") + 1);
+ if ("mp4".equals(ext)){
+ outMp4File(resultStr, request, response,passedFileName);
+ return;
+ }
+
+ if (check){
+ outFile(response,resultStr,passedFileName, isDown);
+ }
+ }
+
+ private void outFile(HttpServletResponse response, String resultStr, String passedFileName, boolean isDown){
+
+ File file = new File(resultStr);
+ if (!file.exists()) {
+ LogUtil.error("outFile 该资源不存在或不可预览");
+ return;
+ }
+ // 获取文件后缀
+ String ext = resultStr.substring(resultStr.lastIndexOf(".") + 1);
+
+ try (FileInputStream fis = new FileInputStream(file); ServletOutputStream sos = response.getOutputStream()) {
+ String mineType = MimeTypeEnum.getContentType(ext);
+ response.setContentType(mineType);
+ if (isDown) {
+ response.setHeader("Content-Disposition", "attachment;filename="
+ // 解决中文名称乱码的问题
+ + new String(passedFileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
+ }
+ IOUtils.copy(fis, sos);
+ sos.close();
+ fis.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ LogUtil.error("outFile 拷贝文件流出错 resultStr=" + resultStr);
+ }
+ }
+
+
+ //path为本地文件路劲
+ public void outMp4File(String path, HttpServletRequest request, HttpServletResponse response, String passedFileName) {
+
+ LogUtil.info("outMp4File path=" + path);
+ RandomAccessFile targetFile = null;
+ OutputStream outputStream = null;
+ try {
+ outputStream = response.getOutputStream();
+ response.reset();
+ //获取请求头中Range的值
+ String rangeString = request.getHeader(HttpHeaders.RANGE);
+
+ response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
+ response.setHeader(HttpHeaders.CONTENT_TYPE, "video/mp4");
+ //打开文件
+ File file = new File(path);
+ if (file.exists()) {
+ //使用RandomAccessFile读取文件
+ targetFile = new RandomAccessFile(file, "r");
+ long fileLength = targetFile.length();
+ long requestSize = (int) fileLength;
+ //分段下载视频
+ if (StringUtils.hasText(rangeString)) {
+ //从Range中提取需要获取数据的开始和结束位置
+ long requestStart = 0, requestEnd = 0;
+ String[] ranges = rangeString.split("=");
+ if (ranges.length > 1) {
+ String[] rangeDatas = ranges[1].split("-");
+ requestStart = Integer.parseInt(rangeDatas[0]);
+ if (rangeDatas.length > 1) {
+ requestEnd = Integer.parseInt(rangeDatas[1]);
+ }
+ }
+ if (requestEnd != 0 && requestEnd > requestStart) {
+ requestSize = requestEnd - requestStart + 1;
+ }
+ //根据协议设置请求头
+ if (!StringUtils.hasText(rangeString)) {
+ response.setHeader(HttpHeaders.CONTENT_LENGTH, fileLength + "");
+ } else {
+ long length;
+ if (requestEnd > 0) {
+ length = requestEnd - requestStart + 1;
+ response.setHeader(HttpHeaders.CONTENT_LENGTH, "" + length);
+ response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + requestStart + "-" + requestEnd + "/" + fileLength);
+ } else {
+ length = fileLength - requestStart;
+ response.setHeader(HttpHeaders.CONTENT_LENGTH, "" + length);
+ response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + requestStart + "-" + (fileLength - 1) + "/"
+ + fileLength);
+ }
+ }
+ //断点传输下载视频返回206
+ response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
+ //设置targetFile,从自定义位置开始读取数据
+ targetFile.seek(requestStart);
+ } else {
+ //如果Range为空则下载整个视频
+ //response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + passedFileName);
+ //设置文件长度
+ response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileLength));
+ response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + 0 + "-" + (fileLength - 1) + "/"
+ + fileLength);
+ }
+
+ //从磁盘读取数据流返回
+ byte[] cache = new byte[4096];
+ try {
+ while (requestSize > 0) {
+ int len = targetFile.read(cache);
+ if (requestSize < cache.length) {
+ outputStream.write(cache, 0, (int) requestSize);
+ } else {
+ outputStream.write(cache, 0, len);
+ if (len < cache.length) {
+ break;
+ }
+ }
+ requestSize -= cache.length;
+ }
+ } catch (IOException e) {
+ // tomcat原话。写操作IO异常几乎总是由于客户端主动关闭连接导致,所以直接吃掉异常打日志
+ //比如使用video播放视频时经常会发送Range为0- 的范围只是为了获取视频大小,之后就中断连接了
+ LogUtil.error(e, "play error");
+ }
+ } else {
+ throw new RuntimeException("文件路劲有误");
+ }
+ outputStream.flush();
+ } catch (Exception e) {
+ LogUtil.error(e,"文件传输错误");
+ throw new RuntimeException("文件传输错误");
+ }finally {
+ if(outputStream != null){
+ try {
+ outputStream.close();
+ } catch (IOException e) {
+ LogUtil.error(e,"流释放错误");
+ }
+ }
+ if(targetFile != null){
+ try {
+ targetFile.close();
+ } catch (IOException e) {
+ LogUtil.error(e,"文件流释放错误");
+ }
+ }
+ }
+ }
+ /**
+ * @Description: txt 写入文件
+ * @params: [uploadDTO]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/3/1 13:29
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/fileSave", method = RequestMethod.POST)
+ public String fileSave(@RequestBody SaveUploadDTO uploadDTO) {
+ String uuid = RandomUtil.getuuid();
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ Result result;
+ try {
+ if (ObjectUtils.isEmpty(uploadDTO.getTaskID())) {
+ uploadDTO.setTaskID(RandomUtil.getuuid());
+ }
+ CommonSource commonSourceVO = uploadService.fileSave(uploadDTO, loginUser);
+ result = new Result(true, CodeMessageEnum.success.getCode(), commonSourceVO);
+ } catch (SvnlanRuntimeException e) {
+ LogUtil.error("上传fileSave: " + e.getMessage());
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e) {
+ uploadDTO.setFile(null);
+ LogUtil.error(e, "上传失败fileSave, dto:" + JsonUtils.beanToJson(uploadDTO) + ", e:" + e.getMessage());
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }finally {
+ stringRedisTemplate.delete(systemSortTool.getUserSpaceKey(loginUser.getUserID()));
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ }
+ String resultStr = JsonUtils.beanToJson(result);
+ LogUtil.info("返回, " + resultStr + ", uuid" + uuid);
+ return resultStr;
+ }
+
+ /**
+ * @Description: 收藏夹置顶
+ * @params: [updateFileDTO]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/fav/moveTop", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String moveTop(@Valid @RequestBody CheckFileDTO updateFileDTO) {
+ Result result;
+ Map resultMap = new HashMap<>(1);
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ // 校验标签权限
+ userAuthTool.checkUserTagPermission(loginUser);
+
+ boolean success = favService.moveTop(updateFileDTO, resultMap, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(success, CodeMessageEnum.success.getCode(), resultMap);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), resultMap);
+ } catch (Exception e) {
+ LogUtil.error(e, "收藏夹置顶失败" + JsonUtils.beanToJson(updateFileDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), resultMap);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 收藏夹置底
+ * @params: [updateFileDTO]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/fav/moveBottom", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String moveBottom(@Valid @RequestBody CheckFileDTO updateFileDTO) {
+ Result result;
+ Map resultMap = new HashMap<>(1);
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ // 校验标签权限
+ userAuthTool.checkUserTagPermission(loginUser);
+
+ boolean success = favService.moveBottom(updateFileDTO, resultMap, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(success, CodeMessageEnum.success.getCode(), resultMap);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), resultMap);
+ } catch (Exception e) {
+ LogUtil.error(e, "收藏夹置底失败" + JsonUtils.beanToJson(updateFileDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), resultMap);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * zip 压缩
+ */
+ @VisitRecord(isAsync = true)
+ @RequestMapping(value = "/api/disk/zip", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String zip(@RequestBody CheckFileDTO updateFileDTO) {
+ Result result;
+ Map resultMap = new HashMap<>(1);
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ boolean success = uploadZipService.zipFile(updateFileDTO, resultMap, loginUser);
+ result = new Result(success, CodeMessageEnum.success.getCode(), resultMap);
+ if (!ObjectUtils.isEmpty(loginUser)){
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ }
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), e.getMessage(), resultMap);
+ } catch (Exception e) {
+ LogUtil.error(e, "压缩zip失败" + JsonUtils.beanToJson(updateFileDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), resultMap);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ @RequestMapping(value = "/api/disk/zip/taskAction", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String zipTaskAction(HttpServletResponse response, CheckFileDTO updateFileDTO) {
+ Result result;
+ Map resultMap = new HashMap<>(1);
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ boolean success = true;
+ try {
+ success = uploadZipService.taskAction(updateFileDTO, resultMap);
+ result = new Result(success, CodeMessageEnum.success.getCode(), resultMap);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), resultMap);
+ } catch (Exception e) {
+ LogUtil.error(e, "taskAction压缩zip失败" + JsonUtils.beanToJson(updateFileDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), resultMap);
+ }
+
+ if (!ObjectUtils.isEmpty(updateFileDTO.getOperation()) && "down".equals(updateFileDTO.getOperation())) {
+ if (!ObjectUtils.isEmpty(resultMap) && resultMap.containsKey("finalFilePath")) {
+ String cdnPath = systemSortTool.getCdnPath(resultMap.get("finalFilePath").toString(), resultMap.get("fileName").toString());
+
+ LogUtil.info("taskAction ,*** resultMap=" + JsonUtils.beanToJson(resultMap));
+ //获取信息
+ if (!ObjectUtils.isEmpty(updateFileDTO.getGetInfo()) && updateFileDTO.getGetInfo() == 1) {
+ resultMap.put("cdnPath", cdnPath);
+ result = Result.returnSuccess(resultMap);
+ return JsonUtils.beanToJson(result);
+ } else {
+ resultMap.put("downloadUrl", cdnPath);
+ result = Result.returnSuccess(resultMap);
+ /*try {
+ response.sendRedirect(cdnPath);
+ }catch (Exception e){
+ LogUtil.error(e, "taskAction zip 下载失败");
+ }*/
+ }
+ }
+ }else {
+ if (!ObjectUtils.isEmpty(resultMap) && resultMap.containsKey("status") && "1".equals(resultMap.get("status").toString())
+ && !ObjectUtils.isEmpty(loginUser)) {
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ }
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 解压
+ * @params: [sourceID]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/3/24 14:16
+ * @Modified:
+ */
+ @VisitRecord(isAsync = true)
+ @RequestMapping(value = "/api/disk/unZip", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String unZip(@RequestBody CheckFileDTO checkFileDTO) {
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ List list = null;
+ try {
+ if (ObjectUtils.isEmpty(checkFileDTO.getTaskID())){
+ checkFileDTO.setTaskID(RandomUtil.getuuid());
+ }
+ list = uploadZipService.unZip(checkFileDTO, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), checkFileDTO);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), e.getMessage(), checkFileDTO);
+ } catch (Exception e) {
+ LogUtil.error(e, "解压失败 checkFileDTO=" + checkFileDTO);
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), checkFileDTO);
+ }
+ // 视频转码
+ if (!CollectionUtils.isEmpty(list)) {
+ for (CommonSource source : list) {
+ ConvertDTO convertDTO = new ConvertDTO();
+ convertDTO.setBusId(source.getSourceID());
+ convertDTO.setBusType("cloud");
+ convertDTO.setOtherType("unZip");
+ String serverUrl = HttpUtil.getRequestRootUrl(null);
+ source.setDomain(serverUrl);
+ convertDTO.setDomain(serverUrl);
+ convertUtil.doConvert(convertDTO, source);
+ }
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ @RequestMapping(value = "/api/disk/unZip/taskAction", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String unZipTaskAction(HttpServletResponse response, CheckFileDTO updateFileDTO) {
+ Result result;
+ Map resultMap = new HashMap<>(1);
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ boolean success = true;
+ try {
+ success = uploadZipService.taskActionUnZip(updateFileDTO, resultMap, loginUser);
+ result = new Result(success, CodeMessageEnum.success.getCode(), resultMap);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), resultMap);
+ } catch (Exception e) {
+ LogUtil.error(e, "解压 taskAction失败" + JsonUtils.beanToJson(updateFileDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), resultMap);
+ }
+
+ if (!ObjectUtils.isEmpty(resultMap) && resultMap.containsKey("status") && "1".equals(resultMap.get("status").toString())) {
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ }
+
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 设置文档权限
+ * @params: [checkFileDTO]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/4/11 17:16
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/setAuth", method = RequestMethod.POST)
+ public String setAuth(@RequestBody CheckFileDTO checkFileDTO) {
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ authService.setAuth(checkFileDTO, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), checkFileDTO);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), e.getMessage(), checkFileDTO);
+ } catch (Exception e) {
+ LogUtil.error(e, "设置文档权限 checkFileDTO=" + checkFileDTO);
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), checkFileDTO);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 获取文档权限
+ * @params: [checkFileDTO]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Modified:
+ */
+ @GetMapping(value = "/api/disk/getSourceAuth")
+ public String getSourceAuth(CheckFileDTO checkFileDTO) {
+ Result result;
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ try {
+ List list = authService.getSourceAuth(checkFileDTO, loginUser);
+ result = new Result(true, CodeMessageEnum.success.getCode(), list);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), checkFileDTO);
+ } catch (Exception e) {
+ LogUtil.error(e, "获取文档权限 checkFileDTO=" + checkFileDTO);
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), checkFileDTO);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ @RequestMapping(value = "/api/disk/preview/get", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String getPreview(HttpServletResponse response, CheckFileDTO checkFileDTO) {
+
+ Map re = null;
+
+ Result result;
+ try {
+ re = uploadService.getFileContent(checkFileDTO);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), checkFileDTO);
+ } catch (Exception e) {
+ LogUtil.error(e, "/api/disk/preview/get checkFileDTO=" + checkFileDTO);
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), checkFileDTO);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ @RequestMapping(value = "/api/disk/preview/blob", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String getPreviewBlob(HttpServletResponse response, CheckFileDTO checkFileDTO) {
+
+ Map re = null;
+
+ Result result;
+ try {
+ re = uploadService.getFileContentBlob(checkFileDTO);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), checkFileDTO);
+ } catch (Exception e) {
+ LogUtil.error(e, "/api/disk/preview/blob checkFileDTO=" + checkFileDTO);
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), checkFileDTO);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ @RequestMapping(value = "/api/disk/preview/byte", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String getPreviewByte(HttpServletResponse response, CheckFileDTO checkFileDTO) {
+
+ Map re = null;
+
+ Result result;
+ try {
+ re = uploadService.getFileContentByte(checkFileDTO);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), checkFileDTO);
+ } catch (Exception e) {
+ LogUtil.error(e, "/api/disk/preview/byte checkFileDTO=" + checkFileDTO);
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), checkFileDTO);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+}
diff --git a/src/main/java/com/svnlan/home/controller/VideoGetController.java b/src/main/java/com/svnlan/home/controller/VideoGetController.java
new file mode 100644
index 0000000..1ac9061
--- /dev/null
+++ b/src/main/java/com/svnlan/home/controller/VideoGetController.java
@@ -0,0 +1,375 @@
+package com.svnlan.home.controller;
+
+import com.svnlan.common.GlobalConfig;
+import com.svnlan.common.Result;
+import com.svnlan.exception.CodeMessageEnum;
+import com.svnlan.exception.SvnlanRuntimeException;
+import com.svnlan.home.domain.CommonSource;
+import com.svnlan.home.dto.CheckFileDTO;
+import com.svnlan.home.dto.VideoCommonDto;
+import com.svnlan.home.dto.convert.ConvertDTO;
+import com.svnlan.home.service.VideoGetService;
+import com.svnlan.home.service.VideoImagesService;
+import com.svnlan.home.utils.ConvertUtil;
+import com.svnlan.home.utils.ObjUtil;
+import com.svnlan.jwt.domain.LoginUser;
+import com.svnlan.utils.*;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.http.MediaType;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+
+/**
+ * @Author: sulijuan
+ * @Description: 视频剪辑
+ * @Date: 2023/5/17 11:27
+ */
+@RestController
+public class VideoGetController {
+
+ @Resource
+ VideoGetService videoGetService;
+ @Resource
+ LoginUserUtil loginUserUtil;
+ @Resource
+ ConvertUtil convertUtil;
+ @Resource
+ StringRedisTemplate stringRedisTemplate;
+ @Resource
+ VideoImagesService videoImagesService;
+
+ /**
+ * @Description: 根据帧数获取图片
+ * @params: [videoCommonDto]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/video/imgList", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String videoList(VideoCommonDto videoCommonDto){
+ Result result;
+ List re = null;
+ try {
+ re = videoGetService.getVideoShearListAll(videoCommonDto);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "获取视频失败" + JsonUtils.beanToJson(videoCommonDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ @RequestMapping(value = "/api/disk/video/checkImgCut", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String checkImgCut(VideoCommonDto videoCommonDto){
+ Result result;
+ boolean re = false;
+ try {
+ re = videoGetService.checkImgCut(videoCommonDto);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "获取视频失败" + JsonUtils.beanToJson(videoCommonDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 视频剪切
+ * @params: [videoCommonDto]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/video/cut", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String videoCut(@RequestBody VideoCommonDto videoCommonDto){
+ Result result;
+ Map re = null;
+ try {
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ LogUtil.info("/api/disk/video/cut videoCommonDto=" + JsonUtils.beanToJson(videoCommonDto));
+ re = videoGetService.cutVideo(videoCommonDto, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "cut剪切视频失败 " + JsonUtils.beanToJson(videoCommonDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 视频剪切
+ * @params: [videoCommonDto]
+ * @Return: java.lang.String
+ * @Author: sulijuan
+ * @Date: 2023/5/18 16:56
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/video/cutSave", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String videoCutSave(@RequestBody VideoCommonDto videoCommonDto){
+ Result result;
+ Map re = null;
+ try {
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ LogUtil.info("/api/disk/video/cutSave videoCommonDto=" + JsonUtils.beanToJson(videoCommonDto));
+ re = videoGetService.cutVideoSave(videoCommonDto, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ if (re.containsKey("convertList")){
+ List list = ObjUtil.objectToList(re.get("convertList"), CommonSource.class);
+ // 视频转码
+ if (!CollectionUtils.isEmpty(list)){
+ for (CommonSource source : list){
+ ConvertDTO convertDTO = new ConvertDTO();
+ convertDTO.setBusId(source.getSourceID());
+ convertDTO.setBusType("cloud");
+ convertDTO.setOtherType("cutVideo");
+ String serverUrl = HttpUtil.getRequestRootUrl(null);
+ source.setDomain(serverUrl);
+ convertDTO.setDomain(serverUrl);
+ convertUtil.doConvert(convertDTO, source);
+ }
+ }
+ re.put("convertList", null);
+ }
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "cutSave剪切视频失败" + JsonUtils.beanToJson(videoCommonDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+ /**
+ * @Description: 视频拆分
+ * @params: [videoCommonDto]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/video/splitSave", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String videoSplitSave(@RequestBody VideoCommonDto videoCommonDto){
+ Result result;
+ Map re = null;
+ try {
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ LogUtil.info("/api/disk/video/cutSave videoCommonDto=" + JsonUtils.beanToJson(videoCommonDto));
+ re = videoGetService.splitVideoSave(videoCommonDto, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ if (re.containsKey("convertList")){
+ List list = ObjUtil.objectToList(re.get("convertList"), CommonSource.class);
+ // 视频转码
+ if (!CollectionUtils.isEmpty(list)){
+ String serverUrl = HttpUtil.getRequestRootUrl(null);
+ for (CommonSource source : list){
+ ConvertDTO convertDTO = new ConvertDTO();
+ convertDTO.setBusId(source.getSourceID());
+ convertDTO.setBusType("cloud");
+ convertDTO.setOtherType("splitVideo");
+ source.setDomain(serverUrl);
+ convertDTO.setDomain(serverUrl);
+ convertUtil.doConvert(convertDTO, source);
+ }
+ }
+ re.put("convertList", null);
+ }
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "splitSave拆分视频失败" + JsonUtils.beanToJson(videoCommonDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 视频合并
+ * @params: [videoCommonDto]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/video/mergeSave", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String videoMergeSave(@RequestBody VideoCommonDto videoCommonDto){
+ Result result;
+ Map re = null;
+ try {
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ LogUtil.info("/api/disk/video/videoMergeSave videoCommonDto=" + JsonUtils.beanToJson(videoCommonDto));
+ re = videoGetService.mergeVideoSave(videoCommonDto, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "videoMergeSave合并视频失败" + JsonUtils.beanToJson(videoCommonDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 视频转码
+ * @params: [videoCommonDto]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/video/convertSave", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String videoConvertSave(@RequestBody VideoCommonDto videoCommonDto){
+ Result result;
+ Map re = null;
+ try {
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ LogUtil.info("/api/disk/video/videoConvertSave videoCommonDto=" + JsonUtils.beanToJson(videoCommonDto));
+ re = videoGetService.convertVideoSave(videoCommonDto, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "videoConvertSave转码视频失败" + JsonUtils.beanToJson(videoCommonDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 视频设置
+ * @params: [videoCommonDto]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/video/setting", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String videoConfigSave(@RequestBody VideoCommonDto videoCommonDto){
+ Result result;
+ Map re = null;
+ try {
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ LogUtil.info("/api/disk/video/videoConfigSave videoCommonDto=" + JsonUtils.beanToJson(videoCommonDto));
+ re = videoGetService.videoConfigSave(videoCommonDto, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "videoConvertSave转码视频失败" + JsonUtils.beanToJson(videoCommonDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 视频剪切-照相
+ * @params: [videoCommonDto]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/video/cutImg", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String videoCutImg(@RequestBody VideoCommonDto videoCommonDto){
+ Result result;
+ Map re = null;
+ try {
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ LogUtil.info("/api/disk/video/cutImg videoCommonDto=" + JsonUtils.beanToJson(videoCommonDto));
+ re = videoGetService.cutVideoImg(videoCommonDto, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "cut剪切视频失败 " + JsonUtils.beanToJson(videoCommonDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ /**
+ * @Description: 视频剪切-抽取音频
+ * @params: [videoCommonDto]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/video/copyAudio", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String videoCopyAudio(@RequestBody VideoCommonDto videoCommonDto){
+ Result result;
+ Map re = null;
+ try {
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ LogUtil.info("/api/disk/video/copyAudio videoCommonDto=" + JsonUtils.beanToJson(videoCommonDto));
+ re = videoGetService.copyAudio(videoCommonDto, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "cut剪切视频失败 " + JsonUtils.beanToJson(videoCommonDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+ /**
+ * @Description: 图片转视频
+ * @params: [videoCommonDto]
+ * @Return: java.lang.String
+ * @Modified:
+ */
+ @RequestMapping(value = "/api/disk/video/imagesToVideo", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String imagesToVideo(@RequestBody VideoCommonDto videoCommonDto){
+ Result result;
+ Map re = null;
+ try {
+ if (ObjectUtils.isEmpty(videoCommonDto.getTaskID())){
+ videoCommonDto.setTaskID(RandomUtil.getuuid());
+ }
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ LogUtil.info("/api/disk/video/imagesToVideo videoCommonDto=" + JsonUtils.beanToJson(videoCommonDto));
+ re = videoImagesService.imagesToVideo(videoCommonDto, loginUser);
+ result = new Result(true, CodeMessageEnum.success.getCode(), re);
+ } catch (SvnlanRuntimeException e){
+ result = new Result(false, e.getErrorCode(), null);
+ } catch (Exception e){
+ LogUtil.error(e, "imagesToVideo " + JsonUtils.beanToJson(videoCommonDto));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), null);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+
+ @RequestMapping(value = "/api/disk/video/imagesToVideo/taskAction", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
+ public String imagesToVideoTaskAction(HttpServletResponse response, CheckFileDTO updateFileDTO) {
+ Result result;
+ Map resultMap = new HashMap<>(1);
+ LoginUser loginUser = loginUserUtil.getLoginUser();
+ boolean success = true;
+ try {
+ success = videoImagesService.taskAction(updateFileDTO, resultMap, loginUser);
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ result = new Result(success, CodeMessageEnum.success.getCode(), resultMap);
+ } catch (SvnlanRuntimeException e) {
+ result = new Result(false, e.getErrorCode(), resultMap);
+ } catch (Exception e) {
+ LogUtil.error(e, "imagesToVideo taskAction 失败" + JsonUtils.beanToJson(updateFileDTO));
+ result = new Result(false, CodeMessageEnum.system_error.getCode(), resultMap);
+ }
+ if (!ObjectUtils.isEmpty(resultMap) && resultMap.containsKey("status") && "1".equals(resultMap.get("status").toString())) {
+ stringRedisTemplate.opsForHash().getOperations().expire(GlobalConfig.homeExplorerRedisKey + loginUser.getUserID(), 1, TimeUnit.MILLISECONDS);
+ }
+ return JsonUtils.beanToJson(result);
+ }
+}
diff --git a/src/main/java/com/svnlan/home/controller/YzCallbackController.java b/src/main/java/com/svnlan/home/controller/YzCallbackController.java
new file mode 100644
index 0000000..c08287a
--- /dev/null
+++ b/src/main/java/com/svnlan/home/controller/YzCallbackController.java
@@ -0,0 +1,36 @@
+package com.svnlan.home.controller;
+
+import com.svnlan.common.Result;
+import com.svnlan.exception.CodeMessageEnum;
+import com.svnlan.home.dto.YzOfficDto;
+import com.svnlan.home.service.YzService;
+import com.svnlan.utils.JsonUtils;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+
+import javax.annotation.Resource;
+
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/4/7 13:37
+ */
+@RestController
+public class YzCallbackController {
+
+ @Resource
+ YzService yzService;
+
+ @PostMapping(value = "/api/disk/yzwo/office", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public String YzCallback(YzOfficDto officDto, MultipartFile file) {
+
+
+ yzService.yzCallback(officDto, file);
+ Result re = new Result(true, CodeMessageEnum.success.getCode(), true);
+ return JsonUtils.beanToJson(re);
+ }
+
+}
diff --git a/src/main/java/com/svnlan/home/dao/CommentDao.java b/src/main/java/com/svnlan/home/dao/CommentDao.java
new file mode 100644
index 0000000..aa3f227
--- /dev/null
+++ b/src/main/java/com/svnlan/home/dao/CommentDao.java
@@ -0,0 +1,23 @@
+package com.svnlan.home.dao;
+
+import com.svnlan.home.domain.Comment;
+import com.svnlan.home.vo.CommentVo;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/8/1 14:20
+ */
+public interface CommentDao {
+
+ int insert(Comment comment);
+ int setCommentCount(Comment comment);
+ int deleteComment(Long commentID);
+ List getCommentList(Map map);
+ long getCountComment(Map map);
+ Integer checkCommentExist(Long commentID);
+ CommentVo getTargetIdByCommentId(Long commentID);
+}
diff --git a/src/main/java/com/svnlan/home/dao/CommonLabelDao.java b/src/main/java/com/svnlan/home/dao/CommonLabelDao.java
new file mode 100644
index 0000000..4b3aa11
--- /dev/null
+++ b/src/main/java/com/svnlan/home/dao/CommonLabelDao.java
@@ -0,0 +1,28 @@
+package com.svnlan.home.dao;
+
+import com.svnlan.home.domain.CommonLabel;
+import com.svnlan.home.vo.CommonLabelVo;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/14 17:22
+ */
+public interface CommonLabelDao {
+
+ int insert(CommonLabel commonLabel);
+ int update(CommonLabel commonLabel);
+ int deleteTag(Long labelId);
+ int updateStatus(CommonLabel commonLabel);
+
+ List getUserLabelList(Long userID);
+ List getInfoLabelList(Long userID);
+
+ Integer getMaxSort(@Param("userID") Long userID, @Param("tagType") Integer tagType);
+ int updateSort(@Param("labelId") Long labelId, @Param("sort") Integer sort);
+
+ List checkLabelNameRepeat(@Param("labelName") String labelName, @Param("userID") Long userID, @Param("tagType") Integer tagType);
+}
diff --git a/src/main/java/com/svnlan/home/dao/CommonScheduleDao.java b/src/main/java/com/svnlan/home/dao/CommonScheduleDao.java
new file mode 100644
index 0000000..08145aa
--- /dev/null
+++ b/src/main/java/com/svnlan/home/dao/CommonScheduleDao.java
@@ -0,0 +1,42 @@
+package com.svnlan.home.dao;
+
+import com.svnlan.home.domain.CommonSchedule;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 功能描述:
+ *
+ * @author:
+ * @date:
+ */
+public interface CommonScheduleDao {
+
+ int insert(CommonSchedule record);
+
+ int insertSelective(CommonSchedule record);
+
+ CommonSchedule selectByPrimaryKey(String commonScheduleId);
+
+ int updateByPrimaryKeySelective(CommonSchedule record);
+
+ int updateByPrimaryKey(CommonSchedule record);
+
+ int updateOperateTime(String commonScheduleId);
+
+ int getCountById(@Param("commonScheduleId") String commonScheduleId, @Param("gmtModified") String gmtModified);
+
+ /**
+ * @Description:验证定时任务是不是当天执行了
+ * @params: [commonScheduleId, gmtModified]
+ * @Return: int
+ * @Modified:
+ */
+ int getCountByDay(@Param("commonScheduleId") String commonScheduleId, @Param("gmtModified") String gmtModified);
+
+ /**
+ * @description: 由日志ID得对应定时任务信息
+ * @param logScheduleId
+ */
+ CommonSchedule findCommonScheduleByLogScheduleId(Long logScheduleId);
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/svnlan/home/dao/ExplorerOperationsDao.java b/src/main/java/com/svnlan/home/dao/ExplorerOperationsDao.java
new file mode 100644
index 0000000..bd4804f
--- /dev/null
+++ b/src/main/java/com/svnlan/home/dao/ExplorerOperationsDao.java
@@ -0,0 +1,24 @@
+package com.svnlan.home.dao;
+
+import com.svnlan.home.domain.IOSource;
+import com.svnlan.home.vo.HomeExplorerShareDetailVO;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author KingMgg
+ * @data 2023/2/7 16:13
+ */
+public interface ExplorerOperationsDao {
+
+ List getAllSourceList(Map paramMap);
+ int batchUpdateLevel(List list);
+ List getSourceListByLevelToContSize(@Param("parentLevel") String parentLevel, @Param("status") Integer status);
+ int batchUpdateSizeByCountSize(List list);
+
+
+
+
+}
diff --git a/src/main/java/com/svnlan/home/dao/HomeExplorerDao.java b/src/main/java/com/svnlan/home/dao/HomeExplorerDao.java
new file mode 100644
index 0000000..ce76009
--- /dev/null
+++ b/src/main/java/com/svnlan/home/dao/HomeExplorerDao.java
@@ -0,0 +1,77 @@
+package com.svnlan.home.dao;
+
+import com.svnlan.home.domain.IOSource;
+import com.svnlan.home.dto.AddSubCloudDirectoryDTO;
+import com.svnlan.home.vo.HomeExplorerVO;
+import com.svnlan.home.vo.HomeFileDetailVO;
+import com.svnlan.user.vo.GroupSizeVo;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author KingMgg
+ * @data 2023/2/6 11:51
+ */
+public interface HomeExplorerDao {
+ /**
+ * 分类列表下面的子分类列表 根据参数判断 文件 文件夹
+ *
+ * @return
+ */
+ List getHomeExplorer(Map paramMap);
+ Long getCountHomeExplorer(Map paramMap);
+ /** 收藏夹*/
+ List getUserFavExplorer(Map paramMap);
+ /** 回收站*/
+ List getUserRecycleExplorer(Map paramMap);
+ /** 最近文档*/
+ List getUserRencentExplorer(Map paramMap);
+
+ /**
+ * 创建文件夹
+ *
+ * @return
+ */
+ int createDir(IOSource source);
+ int createDirectory(AddSubCloudDirectoryDTO source);
+
+
+ /**
+ * 获取文件详情
+ *
+ * @param fileID
+ * @return
+ */
+ HomeFileDetailVO getFileDetail(Long fileID);
+ HomeExplorerVO getHomeSpace(@Param("targetID") Long targetID, @Param("parentID") Long parentID);
+
+ HomeExplorerVO getEnterpriseSpace();
+ List getUserSpace(@Param("userID") Long userID, @Param("groupID") Long groupID);
+ List getSourceChileCont(List list);
+
+ /**
+ * 修改云盘空间使用大小
+ *
+ * @param paramMap
+ * @return
+ */
+ void updateMemory(Map paramMap);
+ int updateMemoryList(Map paramMap);
+ void updateUserMemory(Map paramMap);
+ void updateSubtractUseUserMemory(Map paramMap);
+ int batchUpdateGroupMemoryList(@Param("list") List list);
+ HomeExplorerVO getOneSourceInfo(Long sourceID);
+ List getUserGroupSourceList(Long userID);
+ List getSystemGroupSourceList();
+ Integer getUserIdentityInfo(Long userID);
+ String getParentName(Long sourceID);
+ List getParentNameList(@Param("list") List list);
+ Integer checkUserRecycleExplorer(Long userID);
+ String getGroupParentLevel(Long groupID);
+ List getGroupParentLevelList(@Param("list") List list);
+ List getImgAndAudioHomeExplorer(@Param("list") List list, @Param("lnkAudio") Integer lnkAudio);
+ List getFolderAndImgAndAudioHomeExplorer(@Param("list") List list, @Param("lnkAudio") Integer lnkAudio);
+ List getImgByFolderList(Map paramMap);
+}
diff --git a/src/main/java/com/svnlan/home/dao/IoFileDao.java b/src/main/java/com/svnlan/home/dao/IoFileDao.java
new file mode 100644
index 0000000..7cf53d8
--- /dev/null
+++ b/src/main/java/com/svnlan/home/dao/IoFileDao.java
@@ -0,0 +1,70 @@
+package com.svnlan.home.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.svnlan.home.domain.CommonSource;
+import com.svnlan.home.domain.IOFile;
+import com.svnlan.home.domain.IOFileMeta;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/16 13:57
+ */
+public interface IoFileDao extends BaseMapper {
+
+ CommonSource getFileAttachment(Long sourceID);
+
+ int insert(IOFile ioFile);
+ int batchInsert(List list);
+ int insertMeta(IOFileMeta ioFile);
+ int batchInsertMeta(List list);
+ List getSameSourceEmptyInfo(@Param("hashMd5") String hashMd5, @Param("size") Long size);
+ int updateVideoConvert(CommonSource commonSource);
+ int updateSameFile(@Param("commonSource") CommonSource commonSource, @Param("list") List list);
+ int updateDocConvert(CommonSource commonSource);
+
+ List getSameSourceEmptyInfoDoc(@Param("hashMd5") String hashMd5, @Param("size") Long size);
+ int updateSameFileSwf(@Param("map") Map updateMap, @Param("list") List list);
+
+ void updateSameFileDoc(@Param("map") Map docPath, @Param("list") List list);
+ CommonSource selectByChecksum(@Param("hashMd5") String hashMd5, @Param("size") Long size);
+ CommonSource selectByChecksumAndTime(@Param("hashMd5") String hashMd5, @Param("size") Long size, @Param("time") Long time);
+
+ int removeUserFile(List list);
+ int removeUserFileMeta(List list);
+ int removeUserFileContents(List list);
+ String getFileUrlValue(Long fileID);
+ List getFileUrlValueList(List list);
+ int updateFileUrlValue(List list);
+ int updateOneFileUrlValue(@Param("fileID") Long fileID, @Param("value") String value);
+ int updateAudioConvert(CommonSource commonSource);
+ int updateCameraConvert(CommonSource commonSource);
+ IOFileMeta getFileValue(Long sourceID);
+
+ CommonSource findCommonSourceById(Long sourceID);
+ int deleteFileOrgPath(Long fileID);
+ CommonSource getHistoryFileAttachment(@Param("id") Long id);
+
+ @Select("SELECT `name`, `path`, size, modifyTime, createTime FROM io_file WHERE fileID = #{id} AND isExistFile = 1")
+ IOFile getFileByFieldId(@Param("id") Long fileID);
+ int updateFileMd5ByPath(@Param("hashMd5") String hashMd5, @Param("path") String path);
+ CommonSource getHistoryFileAttachmentUrl(@Param("id") Long id);
+ CommonSource getFileAttachmentUrl(Long sourceID);
+ int updateFileMd5AndSizeByFileID(@Param("hashMd5") String hashMd5, @Param("fileID") Long fileID, @Param("size") Long size);
+
+ int updateVideoFilePath(@Param("fileID") Long fileID, @Param("path") String path);
+
+ int updateH264Info(CommonSource commonSource);
+
+ @Select("SELECT SUM(size) FROM io_file WHERE path like CONCAT(#{location},'%')")
+ Long selectStorageUsage(String location);
+
+ @Update("UPDATE io_file SET size = #{size} WHERE fileID = #{fileID}")
+ void updateFileSize(@Param("fileID") Long fileID, @Param("size") long size);
+}
diff --git a/src/main/java/com/svnlan/home/dao/IoSourceAuthDao.java b/src/main/java/com/svnlan/home/dao/IoSourceAuthDao.java
new file mode 100644
index 0000000..e42a7e4
--- /dev/null
+++ b/src/main/java/com/svnlan/home/dao/IoSourceAuthDao.java
@@ -0,0 +1,22 @@
+package com.svnlan.home.dao;
+
+import com.svnlan.home.domain.IoSourceAuth;
+import com.svnlan.home.vo.IoSourceAuthVo;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/4/11 17:21
+ */
+public interface IoSourceAuthDao {
+
+ int insert(IoSourceAuth ioSourceEvent);
+ int batchInsert(List list);
+ int deleteSourceAuth(Long sourceID);
+ List getSourceAuthBySourceID(Long sourceID);
+ List getGroupNameListByGID(List list);
+ List getSourceAuthBySourceIDList(@Param("list") List list, @Param("targetID") Long targetID);
+}
diff --git a/src/main/java/com/svnlan/home/dao/IoSourceDao.java b/src/main/java/com/svnlan/home/dao/IoSourceDao.java
new file mode 100644
index 0000000..55b4de8
--- /dev/null
+++ b/src/main/java/com/svnlan/home/dao/IoSourceDao.java
@@ -0,0 +1,142 @@
+package com.svnlan.home.dao;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.svnlan.home.domain.CommonSource;
+import com.svnlan.home.domain.IOFile;
+import com.svnlan.home.domain.IOSource;
+import com.svnlan.home.dto.SourceOpDto;
+import com.svnlan.home.vo.IOSourceVo;
+import com.svnlan.home.vo.ParentPathDisplayVo;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/14 11:13
+ */
+public interface IoSourceDao extends BaseMapper {
+
+ int insert(IOSource source);
+
+ int batchInsert(List list);
+
+ CommonSource getSourceInfo(Long sourceID);
+
+ List getSourceInfoList(List list);
+
+ List copySourceList(List list);
+
+ List copySourceListByLevel(List list);
+
+ int deleteDirOrFile(List list);
+
+ int deleteSourceByParent(List list);
+
+ int restoreSourceByParent(@Param("list") List list, @Param("userID") Long userID);
+
+ int batchFileRename(@Param("list") List list, @Param("userID") Long userID);
+
+ int batchUpdateParent(List list);
+
+ int restoreDirOrFile(@Param("list") List list, @Param("userID") Long userID);
+
+ int removeUserSource(List list);
+
+ int removeUserSourceByParent(List list);
+
+ List getFileIDBySourceID(List list);
+
+ List getFileCountBySourceID(List list);
+
+ int updateSourceMemoryList(@Param("list") List list, @Param("memory") Long memory);
+
+ int subtractSourceMemoryList(@Param("list") List list, @Param("memory") Long memory);
+
+ int batchUpdateSourceMemoryList(@Param("list") List list);
+
+ int batchSubtractSourceMemoryList(@Param("list") List list);
+
+ Integer getMaxSort(Long parentID);
+
+ int updateSort(@Param("sourceID") Long sourceID, @Param("sort") Integer sort);
+
+ int updateSourceInfo(IOSource source);
+
+ List copySourcePathList(List list);
+
+ List copySourcePathListByLevel(List list);
+
+ List getSourceFileInfoList(List list);
+
+ int updateSourceModifyUser(IOSource source);
+
+ int updateFileSize(IOSource source);
+
+ List getSourceNameList(Long sourceID);
+
+ List checkSourceNameList(Long sourceID);
+
+ List fileCount();
+
+ @Select("SELECT COUNT(sourceID) count, `type` FROM io_source WHERE isFolder = 0 AND `type` IS NOT NULL GROUP BY `type`")
+ List getFileTypeProportion();
+
+ List getFileCountByPath(List list);
+
+
+ @Select("SELECT name FROM io_source WHERE sourceID = #{id}")
+ IOSource getSourceNameBySourceId(@Param("id") Long sourceID);
+
+ List getUserDirectoryAndFile(@Param("userId") Long userId, @Param("parentId") Long parentId);
+
+
+ @Select("SELECT sourceID, isFolder, `name`, parentID, parentLevel, fileID, modifyTime, createTime FROM io_source WHERE targetID = #{userId} AND isDelete = 0 AND parentID = #{parentId}")
+ List getSourceInfoByParentIdAndUser(@Param("parentId") Long id, @Param("userId") long userId);
+
+
+ @Select("SELECT `name`, sourceID, parentLevel, modifyTime, createTime, targetType, targetID,parentID, isFolder, storageID from io_source where targetID = #{userId} AND parentID = 0 AND isFolder = 1 AND targetType = 1 AND isDelete = 0")
+ IOSourceVo getUserRootDirectory(@Param("userId") Long userId);
+
+ @Select("SELECT sourceID, parentLevel FROM io_source WHERE targetID = #{userId} AND `name` = #{lastPathName} AND isFolder = #{isFolder} and isDelete = 0")
+ List getSourceByNameAndUserId(@Param("lastPathName") String lastPathName, @Param("userId") Long userId, @Param("isFolder") Integer isFolder);
+
+ @Select("SELECT COUNT(sourceID) count, `type` FROM io_source WHERE createUser = #{userId} and isFolder = 0 AND `type` IS NOT NULL GROUP BY `type`")
+ List getFileTypeProportionByUserId(@Param("userId") Long userId);
+
+ int batchUpdateParentAndName(List list);
+
+ IOFile getFileContentByNameAndUserId(@Param("fileName") String fileName, @Param("userId") Long userId, @Param("isVideoFile") Boolean isVideoFile);
+
+ @Select("SELECT name FROM io_source WHERE isFolder = 1 AND `name` LIKE CONCAT(#{lastPath}, '%') AND parentLevel = #{parentLevel} AND isDelete = 0")
+ List getDirectoryByParentLevelAndName(String parentLevel, String lastPath);
+
+
+ @Select("SELECT sourceID,parentLevel,isFolder, modifyTime, createTime, `size`, fileID, `name`, targetType, targetID, parentID, storageID FROM io_source WHERE targetID = #{userId} AND parentLevel = #{parentLevel} AND name = #{name} AND isDelete = 0")
+ IOSourceVo querySourceVoByParentLevelAndUserIdAndName(@Param("parentLevel") String parentLevel, @Param("userId") Long userId, @Param("name") String name);
+
+ List getParentPathDisplay(List list);
+
+ String getSourceName(Long sourceID);
+ int updateSourceAddSizeInfo(IOSource source);
+ int updateSourceConvertSize(@Param("sourceID") Long sourceID, @Param("convertSize") Long convertSize);
+ int updateSourceThumbSize(@Param("sourceID") Long sourceID, @Param("thumbSize") Long thumbSize);
+
+ List getDesktopSourceList(@Param("parentID") Long parentID, @Param("name") String name);
+
+ Long getSourceSize(@Param("sourceID") Long sourceID);
+ int updateSourceSize(@Param("sourceID") Long sourceID, @Param("size") Long size);
+
+ @Select("SELECT fileType ft, COUNT(sourceID) c, SUM(size) s FROM io_source WHERE isFolder = 0 AND targetType = 1 GROUP BY fileType")
+ List selectFileProportion();
+
+
+ @Select("SELECT targetType ty, SUM(size) s FROM io_source WHERE isFolder = 0 GROUP BY targetType")
+ List getTargetTypeProportion();
+
+ List getParentPathDisplayByIds(List list);
+ int updateSourceDesc(@Param("sourceID") Long sourceID, @Param("description") String description);
+}
diff --git a/src/main/java/com/svnlan/home/dao/IoSourceEventDao.java b/src/main/java/com/svnlan/home/dao/IoSourceEventDao.java
new file mode 100644
index 0000000..e533ea8
--- /dev/null
+++ b/src/main/java/com/svnlan/home/dao/IoSourceEventDao.java
@@ -0,0 +1,27 @@
+package com.svnlan.home.dao;
+
+import com.alibaba.fastjson.JSONObject;
+import com.svnlan.home.domain.IoSourceEvent;
+import com.svnlan.home.vo.IoSourceEventVo;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.springframework.data.util.Pair;
+
+import java.util.List;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/14 11:16
+ */
+public interface IoSourceEventDao {
+
+ int insert(IoSourceEvent ioSourceEvent);
+ int batchInsert(List list);
+ List getSourceEventBySourceID(@Param("sourceID") Long sourceID, @Param("isFolder") int isFolder);
+
+ @Select("SELECT DATE(FROM_UNIXTIME(createTime)) `date`, COUNT(1) count from io_source_event WHERE createTime >= #{timeRange.first} AND createTime <= #{timeRange.second} GROUP BY `date` ORDER BY `date`")
+ List queryFileOperateCount(@Param("timeRange") Pair timeRange);
+
+ List queryVideoFileOperateCount(@Param("timeRange") Pair timeRange);
+}
diff --git a/src/main/java/com/svnlan/home/dao/IoSourceHistoryDao.java b/src/main/java/com/svnlan/home/dao/IoSourceHistoryDao.java
new file mode 100644
index 0000000..2bc2270
--- /dev/null
+++ b/src/main/java/com/svnlan/home/dao/IoSourceHistoryDao.java
@@ -0,0 +1,33 @@
+package com.svnlan.home.dao;
+
+import com.svnlan.home.domain.CommonSource;
+import com.svnlan.home.domain.IoSourceHistory;
+import com.svnlan.home.vo.HomeExplorerVO;
+import com.svnlan.home.vo.IoSourceHistoryVo;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/3/24 17:07
+ */
+public interface IoSourceHistoryDao {
+
+ int insert(IoSourceHistory ioSourceHistory);
+ int batchInsert(List list);
+ List getSourceHistoryBySourceID(Map hashMap);
+ Long getCountSourceHistoryBySourceID(Map hashMap);
+ int updateDetail(@Param("id") Long id, @Param("detail") String detail);
+ int updateVerDetail(IoSourceHistory ioSourceHistory);
+ int updateVerSource(IoSourceHistory ioSourceHistory);
+ IoSourceHistory getFileInfoBySourceID(@Param("sourceID") Long sourceID);
+ CommonSource getHistorySourceInfo(Long id);
+ int delByID(@Param("id") Long id);
+ int delBySourceID(@Param("sourceID") Long sourceID);
+ IoSourceHistory getHistoryInfo(@Param("id") Long id);
+ IoSourceHistory getHistoryInfoByFileId(@Param("sourceID") Long sourceID, @Param("fileID") Long fileID);
+ int updateSize(@Param("id") Long id, @Param("size") Long size, @Param("detail") String detail);
+}
diff --git a/src/main/java/com/svnlan/home/dao/IoSourceMetaDao.java b/src/main/java/com/svnlan/home/dao/IoSourceMetaDao.java
new file mode 100644
index 0000000..a6faedc
--- /dev/null
+++ b/src/main/java/com/svnlan/home/dao/IoSourceMetaDao.java
@@ -0,0 +1,27 @@
+package com.svnlan.home.dao;
+
+import com.svnlan.home.domain.IOSourceMeta;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/13 16:01
+ */
+public interface IoSourceMetaDao {
+
+ int delMetaBySourceID(@Param("sourceID") Long sourceID, @Param("list")List list);
+
+ int delMetaBySourceIDList(@Param("sourceIdList") List sourceIdList, @Param("list")List list);
+
+ int batchInsert(List list);
+ int insert(IOSourceMeta iOSourceMeta);
+ List getSourceMetaListBySourceID(@Param("sourceID") Long sourceID, @Param("list")List list);
+ IOSourceMeta getSourceMetaVoBySourceID(@Param("sourceID") Long sourceID, @Param("key")String key);
+ List getSourceMetaListByParam(@Param("sourceIdList") List sourceIdList, @Param("list")List list);
+ int updateMetaByKey(@Param("sourceID") Long sourceID, @Param("key") String key, @Param("desc") String desc);
+ String getValueMetaByKey(@Param("sourceID") Long sourceID, @Param("key") String key);
+ String getSourceIDMetaByKey(@Param("value") String value, @Param("key") String key);
+}
diff --git a/src/main/java/com/svnlan/home/dao/IoSourceRecycleDao.java b/src/main/java/com/svnlan/home/dao/IoSourceRecycleDao.java
new file mode 100644
index 0000000..40615f7
--- /dev/null
+++ b/src/main/java/com/svnlan/home/dao/IoSourceRecycleDao.java
@@ -0,0 +1,21 @@
+package com.svnlan.home.dao;
+
+import com.svnlan.home.domain.IOSource;
+import com.svnlan.home.domain.IoSourceRecycle;
+import com.svnlan.home.dto.SourceOpDto;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/2/18 16:44
+ */
+public interface IoSourceRecycleDao {
+
+ int insert(IoSourceRecycle ioSourceRecycle);
+ int batchInsert(List list);
+ int deleteUserRecycle(@Param("userID")Long userID, @Param("targetType") Integer targetType, @Param("list") List list);
+ List getUserRecycleBinList(Long userID);
+}
diff --git a/src/main/java/com/svnlan/home/dao/LogScheduleDao.java b/src/main/java/com/svnlan/home/dao/LogScheduleDao.java
new file mode 100644
index 0000000..6415a48
--- /dev/null
+++ b/src/main/java/com/svnlan/home/dao/LogScheduleDao.java
@@ -0,0 +1,35 @@
+package com.svnlan.home.dao;
+
+import com.svnlan.home.domain.LogSchedule;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * 功能描述:
+ *
+ * @author:
+ * @date:
+ */
+public interface LogScheduleDao {
+ /**
+ * 功能描述: 添加日志
+ *
+ * @param record
+ * @return int
+ */
+ int insert(LogSchedule record);
+
+ int updateByPrimaryKey(LogSchedule record);
+
+
+// int updateLogSuccess(@Param("logScheduleId") Long logScheduleId, @Param("state") String state, @Param("remark") String remark);
+
+ LogSchedule getLogScheduleInfo(@Param("commonScheduleId") String scheduleId, @Param("gmtStart") Date date);
+
+ LogSchedule getLogScheduleInfoLock(@Param("commonScheduleId") String scheduleId, @Param("gmtStart") Date date);
+
+ int updateLogSuccess(Map map);
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/svnlan/home/dao/ShareDao.java b/src/main/java/com/svnlan/home/dao/ShareDao.java
new file mode 100644
index 0000000..63a78d3
--- /dev/null
+++ b/src/main/java/com/svnlan/home/dao/ShareDao.java
@@ -0,0 +1,41 @@
+package com.svnlan.home.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.svnlan.home.domain.Share;
+import com.svnlan.home.vo.HomeExplorerVO;
+import com.svnlan.home.vo.ShareVo;
+import com.svnlan.user.vo.UserVo;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Author: sulijuan
+ * @Description:
+ * @Date: 2023/3/3 13:46
+ */
+public interface ShareDao extends BaseMapper {
+
+ int insert(Share share);
+ int update(Share share);
+ int updateNumView(@Param("shareID") Long shareID, @Param("numView") Integer numView);
+ int updateNumDownload(@Param("shareID") Long shareID, @Param("numDownload") Integer numDownload);
+ int delete(Long shareID);
+ int deleteList(List list);
+ ShareVo getShare(@Param("sourceID") Long sourceID, @Param("userID") Long userID, @Param("isShareTo") Integer isShareTo, @Param("isLink") Integer isLink);
+ ShareVo getShareById(Long shareID);
+ List getShareList(Map map);
+ List checkUserIsShare(@Param("userID") Long userID);
+ List getShareByCode(@Param("shareCode") String shareCode);
+
+ HomeExplorerVO getLinkShareInfo(Long sourceID);
+ List getShareToMeList(Map map);
+ List getLinkShareList(Map map);
+
+ List getSelectUserListByParam(Map map);
+ List getNotGroupUserListByParam(Map map);
+ List getShareByIdList(List list);
+
+ void updateStatus(@Param("operateType") Integer operateType,@Param("ids") List