commit 11485c6cbe8c821f81ae1b5eb3d2dbd07e060760 Author: cherry Date: Wed May 15 15:52:13 2024 +0800 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d23656a --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +!**/src/main/resources/temp/ +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..cb28b0e Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..5f0536e --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/deploy/bin/shutdown.bat b/deploy/bin/shutdown.bat new file mode 100644 index 0000000..dd1e70e --- /dev/null +++ b/deploy/bin/shutdown.bat @@ -0,0 +1,13 @@ +@echo off + +if not exist "%JAVA_HOME%\bin\jps.exe" echo Please set the JAVA_HOME variable in your environment, We need java(x64)! jdk8 or later is better! & EXIT /B 1 + +setlocal + +set "PATH=%JAVA_HOME%\bin;%PATH%" + +echo killing per-ftp + +for /f "tokens=1" %%i in ('jps -m ^| find "per-ftp"') do ( taskkill /F /PID %%i ) + +echo Done! diff --git a/deploy/bin/shutdown.sh b/deploy/bin/shutdown.sh new file mode 100644 index 0000000..d149a7f --- /dev/null +++ b/deploy/bin/shutdown.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +cd `dirname $0`/../target +target_dir=`pwd` + +pid=`ps ax | grep -i 'per-ftp' | grep ${target_dir} | grep java | grep -v grep | awk '{print $1}'` +if [ -z "$pid" ] ; then + echo "No per-ftp running.." + exit 0; +fi + +echo "The per-ftp(${pid}) is running..." + +kill ${pid} + +echo "Send shutdown request to per-ftp(${pid}) OK" diff --git a/deploy/bin/startup.bat b/deploy/bin/startup.bat new file mode 100644 index 0000000..f9b4afb --- /dev/null +++ b/deploy/bin/startup.bat @@ -0,0 +1,30 @@ +@echo off + +if not exist "%JAVA_HOME%\bin\java.exe" echo Please set the JAVA_HOME variable in your environment, We need java(x64)! jdk8 or later is better! & EXIT /B 1 +set "JAVA=%JAVA_HOME%\bin\java.exe" + +setlocal enabledelayedexpansion + +set BASE_DIR=%~dp0 +rem added double quotation marks to avoid the issue caused by the folder names containing spaces. +rem removed the last 5 chars(which means \bin\) to get the base DIR. +set BASE_DIR="%BASE_DIR:~0,-5%" + +set DEFAULT_SEARCH_LOCATIONS="classpath:/,classpath:/config/,file:./,file:./config/" +set CUSTOM_SEARCH_LOCATIONS=%DEFAULT_SEARCH_LOCATIONS%,file:%BASE_DIR%/conf/ + + +set SERVER=per-ftp + + +set "JAVA_OPT=%JAVA_OPT% -Xms1024m -Xmx1024m -Xmn512m" + + +set "JAVA_OPT=%JAVA_OPT% -Dsystem.basedir=%BASE_DIR%" +set "JAVA_OPT=%JAVA_OPT% -Dloader.path=%BASE_DIR%/plugins/health -jar %BASE_DIR%\target\%SERVER%.jar" +set "JAVA_OPT=%JAVA_OPT% --spring.config.location=%CUSTOM_SEARCH_LOCATIONS%" +set "JAVA_OPT=%JAVA_OPT% --logging.config=%BASE_DIR%/conf/log4j2.xml" + +call "%JAVA%" %JAVA_OPT% per-ftp %* + +pause \ No newline at end of file diff --git a/deploy/bin/startup.sh b/deploy/bin/startup.sh new file mode 100644 index 0000000..5ec96ca --- /dev/null +++ b/deploy/bin/startup.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +error_exit () +{ + echo "ERROR: $1 !!" + exit 1 +} +[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$HOME/jdk/java +[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java +[ ! -e "$JAVA_HOME/bin/java" ] && unset JAVA_HOME + + +if [ -z "$JAVA_HOME" ]; then + error_exit "Please set the JAVA_HOME variable in your environment, We need java(x64)! jdk8 or later is better!" +fi + + +export SERVER="knowledgebase" + +export JAVA_HOME +export JAVA="$JAVA_HOME/bin/java" +export BASE_DIR=`cd $(dirname $0)/..; pwd` +export DEFAULT_SEARCH_LOCATIONS="classpath:/,classpath:/config/,file:./,file:./config/" +export CUSTOM_SEARCH_LOCATIONS=${DEFAULT_SEARCH_LOCATIONS},file:${BASE_DIR}/conf/ + +#=========================================================================================== +# JVM Configuration +#=========================================================================================== +JAVA_OPT="${JAVA_OPT} -Xms512m -Xmx512m -Xmn512m" +#JAVA_OPT="${JAVA_OPT} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n" +JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext:${BASE_DIR}/plugins/cmdb:${BASE_DIR}/plugins/mysql" + + +JAVA_OPT="${JAVA_OPT} -Dsystem.basedir=${BASE_DIR}" +JAVA_OPT="${JAVA_OPT} -Dloader.path=${BASE_DIR}/plugins/health -jar ${BASE_DIR}/target/${SERVER}.jar" +JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}" +#JAVA_OPT="${JAVA_OPT} --spring.config.location=${CUSTOM_SEARCH_LOCATIONS}" +JAVA_OPT="${JAVA_OPT} --logging.config=${BASE_DIR}/conf/log4j2.xml" +JAVA_OPT="${JAVA_OPT} --server.max-http-header-size=524288" + +if [ ! -d "${BASE_DIR}/logs" ]; then + mkdir ${BASE_DIR}/logs +fi + +echo "$JAVA ${JAVA_OPT}" + + +echo "knowledgeis starting ..." + + +nohup $JAVA ${JAVA_OPT} per-ftp >> /dev/null 2>&1 & +echo "knowledge is starting,you can check the ${BASE_DIR}/logs/default.log" diff --git a/doc/db/01-kb.sql b/doc/db/01-kb.sql new file mode 100644 index 0000000..5e3611c --- /dev/null +++ b/doc/db/01-kb.sql @@ -0,0 +1,551 @@ +-- ---------------------------- +-- Table structure for kb_attachment +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_attachment"; +CREATE TABLE "public"."kb_attachment" +( + "attachment_name" varchar COLLATE "pg_catalog"."default", + "attachment_path" varchar COLLATE "pg_catalog"."default", + "create_time" int4, + "create_by_id" varchar COLLATE "pg_catalog"."default", + "id" int8 +) +; +COMMENT +ON COLUMN "public"."kb_attachment"."attachment_name" IS '附件名'; +COMMENT +ON COLUMN "public"."kb_attachment"."attachment_path" IS '附件路径 不到host 例如 /20240301/uthjkksjhlgl.jpg?xxx'; +COMMENT +ON COLUMN "public"."kb_attachment"."create_by_id" IS '上传附件的人id'; +COMMENT +ON TABLE "public"."kb_attachment" IS '附件表'; + +-- ---------------------------- +-- Table structure for kb_base +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_base"; +CREATE TABLE "public"."kb_base" +( + "id" int8 NOT NULL, + "base_name" varchar COLLATE "pg_catalog"."default", + "create_time" int4, + "create_by_id" varchar COLLATE "pg_catalog"."default", + "create_by_name" varchar COLLATE "pg_catalog"."default", + "dept_id" varchar COLLATE "pg_catalog"."default", + "is_public" int4, + "update_by_id" varchar COLLATE "pg_catalog"."default", + "update_by_name" varchar COLLATE "pg_catalog"."default", + "update_time" int4, + "category_count" int8, + "knowledge_count" int8, + "dept_name" varchar COLLATE "pg_catalog"."default" +) +; +COMMENT +ON COLUMN "public"."kb_base"."base_name" IS '库名'; +COMMENT +ON COLUMN "public"."kb_base"."dept_id" IS '部门id'; +COMMENT +ON COLUMN "public"."kb_base"."is_public" IS '是否公开 0 非公开 1 公开'; +COMMENT +ON TABLE "public"."kb_base" IS '库'; + +-- ---------------------------- +-- Table structure for kb_browse_history +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_browse_history"; +CREATE TABLE "public"."kb_browse_history" +( + "id" int8 NOT NULL, + "user_id" varchar COLLATE "pg_catalog"."default", + "knowledge_id" int8, + "create_time" int4 +) +; +COMMENT +ON TABLE "public"."kb_browse_history" IS '浏览历史'; + +-- ---------------------------- +-- Table structure for kb_category +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_category"; +CREATE TABLE "public"."kb_category" +( + "id" int8 NOT NULL, + "pid" int8, + "category_name" varchar COLLATE "pg_catalog"."default", + "create_time" int4, + "create_by_id" varchar COLLATE "pg_catalog"."default", + "update_time" int4, + "update_by_id" varchar COLLATE "pg_catalog"."default", + "kb_count" int4, + "base_id" int8, + "category_full_name" varchar COLLATE "pg_catalog"."default" +) +; +COMMENT +ON COLUMN "public"."kb_category"."pid" IS '父级id'; +COMMENT +ON COLUMN "public"."kb_category"."category_name" IS '分类名字'; +COMMENT +ON COLUMN "public"."kb_category"."create_time" IS '创建时间'; +COMMENT +ON COLUMN "public"."kb_category"."create_by_id" IS '创建id'; +COMMENT +ON COLUMN "public"."kb_category"."update_time" IS '更新时间'; +COMMENT +ON COLUMN "public"."kb_category"."update_by_id" IS '更新id'; +COMMENT +ON COLUMN "public"."kb_category"."kb_count" IS '知识数量'; +COMMENT +ON COLUMN "public"."kb_category"."base_id" IS '库id'; +COMMENT +ON COLUMN "public"."kb_category"."category_full_name" IS '分类串'; +COMMENT +ON TABLE "public"."kb_category" IS '分类表'; + +-- ---------------------------- +-- Table structure for kb_ik +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_ik"; +CREATE TABLE "public"."kb_ik" +( + "id" int8 NOT NULL, + "user_id" varchar COLLATE "pg_catalog"."default", + "user_name" varchar COLLATE "pg_catalog"."default", + "word" varchar COLLATE "pg_catalog"."default", + "create_time" int4, + "browse_history_id" int8 +) +; +COMMENT +ON COLUMN "public"."kb_ik"."user_name" IS '用户名'; +COMMENT +ON COLUMN "public"."kb_ik"."word" IS '分词结果'; +COMMENT +ON COLUMN "public"."kb_ik"."browse_history_id" IS '搜索历史的id'; +COMMENT +ON TABLE "public"."kb_ik" IS '搜索的分词表, 便于以后做智能推荐'; + +-- ---------------------------- +-- Table structure for kb_knowledge +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_knowledge"; +CREATE TABLE "public"."kb_knowledge" +( + "id" int8 NOT NULL, + "title" varchar(255) COLLATE "pg_catalog"."default", + "description" varchar(255) COLLATE "pg_catalog"."default", + "category_id" int8, + "create_time" int4, + "create_by_id" varchar COLLATE "pg_catalog"."default", + "create_by_name" varchar(255) COLLATE "pg_catalog"."default", + "update_time" int4, + "update_by_id" varchar COLLATE "pg_catalog"."default", + "update_by_name" varchar COLLATE "pg_catalog"."default", + "is_text" int4 DEFAULT 0, + "is_image" int4 DEFAULT 0, + "is_doc" int4 DEFAULT 0, + "is_video" int4 DEFAULT 0, + "is_publish" int4 DEFAULT 0, + "collection_num" int4 DEFAULT 0, + "view_num" int4 DEFAULT 0, + "base_id" int8, + "attachment_type" varchar COLLATE "pg_catalog"."default", + "resource" varchar COLLATE "pg_catalog"."default", + "publish_time" int4, + "implement_time" int4, + "comment_num" int8, + "is_public" int4, + "attachment_path" varchar COLLATE "pg_catalog"."default" +) +; +COMMENT +ON COLUMN "public"."kb_knowledge"."title" IS '标题'; +COMMENT +ON COLUMN "public"."kb_knowledge"."description" IS '摘要'; +COMMENT +ON COLUMN "public"."kb_knowledge"."category_id" IS '分类id'; +COMMENT +ON COLUMN "public"."kb_knowledge"."create_time" IS '创建时间'; +COMMENT +ON COLUMN "public"."kb_knowledge"."create_by_id" IS '创建者id'; +COMMENT +ON COLUMN "public"."kb_knowledge"."create_by_name" IS '创建者姓名'; +COMMENT +ON COLUMN "public"."kb_knowledge"."update_time" IS '更新时间'; +COMMENT +ON COLUMN "public"."kb_knowledge"."update_by_id" IS '更新者id'; +COMMENT +ON COLUMN "public"."kb_knowledge"."update_by_name" IS '更新者姓名'; +COMMENT +ON COLUMN "public"."kb_knowledge"."is_text" IS '是否是文本类型 0 否 1 是'; +COMMENT +ON COLUMN "public"."kb_knowledge"."is_image" IS '是否是图片类型 0 否 1 是'; +COMMENT +ON COLUMN "public"."kb_knowledge"."is_doc" IS '是否是文档类型 0 否 1 是'; +COMMENT +ON COLUMN "public"."kb_knowledge"."is_video" IS '是否是视频类型 0 否 1 是'; +COMMENT +ON COLUMN "public"."kb_knowledge"."is_publish" IS '是否发布 0 未发布 1 已发布'; +COMMENT +ON COLUMN "public"."kb_knowledge"."collection_num" IS '收藏量'; +COMMENT +ON COLUMN "public"."kb_knowledge"."view_num" IS '浏览量'; +COMMENT +ON COLUMN "public"."kb_knowledge"."attachment_type" IS '附件类型 pdf doc docx 等'; +COMMENT +ON COLUMN "public"."kb_knowledge"."publish_time" IS '发布时间'; +COMMENT +ON COLUMN "public"."kb_knowledge"."implement_time" IS '实施时间'; +COMMENT +ON COLUMN "public"."kb_knowledge"."attachment_path" IS '附件路径'; + +-- ---------------------------- +-- Table structure for kb_knowledge_attachment +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_knowledge_attachment"; +CREATE TABLE "public"."kb_knowledge_attachment" +( + "knowledge_id" int8, + "attachment_id" int8, + "id" bigserial +) +; + +-- ---------------------------- +-- Table structure for kb_knowledge_category +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_knowledge_category"; +CREATE TABLE "public"."kb_knowledge_category" +( + "id" int8, + "knowledge_id" int8, + "category_id" int8 NOT NULL +) +; +COMMENT +ON TABLE "public"."kb_knowledge_category" IS '知识的分类'; + +-- ---------------------------- +-- Table structure for kb_knowledge_collection +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_knowledge_collection"; +CREATE TABLE "public"."kb_knowledge_collection" +( + "id" int8 NOT NULL, + "knowlegde_id" int8, + "user_id" varchar COLLATE "pg_catalog"."default", + "create_time" int4 +) +; +COMMENT +ON TABLE "public"."kb_knowledge_collection" IS '个人收藏表'; + +-- ---------------------------- +-- Table structure for kb_knowledge_comment +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_knowledge_comment"; +CREATE TABLE "public"."kb_knowledge_comment" +( + "id" int8 NOT NULL, + "comment" varchar COLLATE "pg_catalog"."default", + "knowledge_id" int8, + "create_time" int4, + "create_by_id" varchar COLLATE "pg_catalog"."default", + "create_by_name" varchar COLLATE "pg_catalog"."default", + "update_time" int4, + "update_by_id" varchar COLLATE "pg_catalog"."default", + "update_by_name" varchar COLLATE "pg_catalog"."default" +) +; +COMMENT +ON COLUMN "public"."kb_knowledge_comment"."comment" IS '评论内容'; +COMMENT +ON COLUMN "public"."kb_knowledge_comment"."knowledge_id" IS '知识id'; +COMMENT +ON COLUMN "public"."kb_knowledge_comment"."create_time" IS '创建时间'; +COMMENT +ON COLUMN "public"."kb_knowledge_comment"."create_by_id" IS '创建者id'; +COMMENT +ON COLUMN "public"."kb_knowledge_comment"."create_by_name" IS '创建者姓名'; +COMMENT +ON TABLE "public"."kb_knowledge_comment" IS '知识评论'; + +-- ---------------------------- +-- Table structure for kb_knowledge_content +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_knowledge_content"; +CREATE TABLE "public"."kb_knowledge_content" +( + "knowledge_id" int8, + "knowledge_content" text COLLATE "pg_catalog"."default", + "id" bigserial +) +; +COMMENT +ON COLUMN "public"."kb_knowledge_content"."knowledge_id" IS '知识id'; +COMMENT +ON COLUMN "public"."kb_knowledge_content"."knowledge_content" IS '知识内容'; +COMMENT +ON TABLE "public"."kb_knowledge_content" IS '知识内容'; + +-- ---------------------------- +-- Table structure for kb_knowledge_img +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_knowledge_img"; +CREATE TABLE "public"."kb_knowledge_img" +( + "knowledge_id" int8, + "img_path" varchar COLLATE "pg_catalog"."default", + "id" bigserial +) +; +COMMENT +ON TABLE "public"."kb_knowledge_img" IS '知识附件上传上来的pdf转的图片'; + +-- ---------------------------- +-- Table structure for kb_knowledge_resource +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_knowledge_resource"; +CREATE TABLE "public"."kb_knowledge_resource" +( + "knowledge_id" int8, + "resource_id" int8, + "id" bigserial +) +; +COMMENT +ON COLUMN "public"."kb_knowledge_resource"."knowledge_id" IS '知识id'; +COMMENT +ON COLUMN "public"."kb_knowledge_resource"."resource_id" IS '来源id'; +COMMENT +ON TABLE "public"."kb_knowledge_resource" IS '知识来源表'; + +-- ---------------------------- +-- Table structure for kb_knowledge_tag +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_knowledge_tag"; +CREATE TABLE "public"."kb_knowledge_tag" +( + "knowledge_id" int8, + "tag_id" int8, + "id" bigserial +) +; +COMMENT +ON COLUMN "public"."kb_knowledge_tag"."knowledge_id" IS '知识id'; +COMMENT +ON COLUMN "public"."kb_knowledge_tag"."tag_id" IS '标签id'; +COMMENT +ON TABLE "public"."kb_knowledge_tag" IS '知识的标签表'; + +-- ---------------------------- +-- Table structure for kb_menu +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_menu"; +CREATE TABLE "public"."kb_menu" +( + "id" int8 NOT NULL, + "menu_name" varchar COLLATE "pg_catalog"."default", + "menu_path" varchar COLLATE "pg_catalog"."default" +) +; +COMMENT +ON COLUMN "public"."kb_menu"."menu_name" IS '菜单名'; +COMMENT +ON COLUMN "public"."kb_menu"."menu_path" IS '菜单路径'; +COMMENT +ON TABLE "public"."kb_menu" IS '通过user_id查询菜单 前端展示这些菜单实现权限控制'; + +-- ---------------------------- +-- Table structure for kb_resource +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_resource"; +CREATE TABLE "public"."kb_resource" +( + "id" int8 NOT NULL, + "resource_name" varchar COLLATE "pg_catalog"."default", + "create_time" int4, + "update_time" int4, + "create_by_id" varchar COLLATE "pg_catalog"."default", + "update_by_id" varchar COLLATE "pg_catalog"."default", + "create_by_name" varchar COLLATE "pg_catalog"."default", + "update_by_name" varchar COLLATE "pg_catalog"."default" +) +; +COMMENT +ON COLUMN "public"."kb_resource"."resource_name" IS '来源名'; +COMMENT +ON COLUMN "public"."kb_resource"."create_time" IS '创建时间'; +COMMENT +ON COLUMN "public"."kb_resource"."update_time" IS '更新时间'; +COMMENT +ON COLUMN "public"."kb_resource"."create_by_id" IS '创建者id'; +COMMENT +ON COLUMN "public"."kb_resource"."update_by_id" IS '更新者id'; +COMMENT +ON COLUMN "public"."kb_resource"."create_by_name" IS '创建者姓名'; +COMMENT +ON COLUMN "public"."kb_resource"."update_by_name" IS '更新者姓名'; +COMMENT +ON TABLE "public"."kb_resource" IS '来源表'; + +-- ---------------------------- +-- Table structure for kb_search_history +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_search_history"; +CREATE TABLE "public"."kb_search_history" +( + "id" int8 NOT NULL, + "user_id" varchar COLLATE "pg_catalog"."default", + "user_name" varchar COLLATE "pg_catalog"."default", + "search_word" varchar COLLATE "pg_catalog"."default", + "create_time" int4 +) +; +COMMENT +ON COLUMN "public"."kb_search_history"."user_id" IS '用户id'; +COMMENT +ON COLUMN "public"."kb_search_history"."user_name" IS '用户姓名'; +COMMENT +ON COLUMN "public"."kb_search_history"."search_word" IS '搜索词'; +COMMENT +ON COLUMN "public"."kb_search_history"."create_time" IS '创建时间'; +COMMENT +ON TABLE "public"."kb_search_history" IS '搜索历史'; + +-- ---------------------------- +-- Table structure for kb_tag +-- ---------------------------- +DROP TABLE IF EXISTS "public"."kb_tag"; +CREATE TABLE "public"."kb_tag" +( + "id" int8 NOT NULL, + "tag_name" varchar COLLATE "pg_catalog"."default", + "create_time" int4, + "update_time" int4, + "create_by_id" varchar COLLATE "pg_catalog"."default", + "update_by_id" varchar COLLATE "pg_catalog"."default", + "create_by_name" varchar COLLATE "pg_catalog"."default", + "update_by_name" varchar COLLATE "pg_catalog"."default" +) +; +COMMENT +ON COLUMN "public"."kb_tag"."tag_name" IS '标签名'; +COMMENT +ON COLUMN "public"."kb_tag"."create_time" IS '创建时间'; +COMMENT +ON COLUMN "public"."kb_tag"."update_time" IS '更新时间'; +COMMENT +ON COLUMN "public"."kb_tag"."create_by_id" IS '创建者id'; +COMMENT +ON COLUMN "public"."kb_tag"."update_by_id" IS '更新者id'; +COMMENT +ON COLUMN "public"."kb_tag"."create_by_name" IS '创建者姓名'; +COMMENT +ON COLUMN "public"."kb_tag"."update_by_name" IS '更新者姓名'; +COMMENT +ON TABLE "public"."kb_tag" IS '标签表'; + +-- ---------------------------- +-- Primary Key structure for table kb_base +-- ---------------------------- +ALTER TABLE "public"."kb_base" + ADD CONSTRAINT "kb_base_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table kb_browse_history +-- ---------------------------- +ALTER TABLE "public"."kb_browse_history" + ADD CONSTRAINT "kb_browse_history_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table kb_category +-- ---------------------------- +ALTER TABLE "public"."kb_category" + ADD CONSTRAINT "kb_category_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table kb_ik +-- ---------------------------- +ALTER TABLE "public"."kb_ik" + ADD CONSTRAINT "kb_ik_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table kb_knowledge +-- ---------------------------- +ALTER TABLE "public"."kb_knowledge" + ADD CONSTRAINT "kb_knowledge_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table kb_knowledge_attachment +-- ---------------------------- +ALTER TABLE "public"."kb_knowledge_attachment" + ADD CONSTRAINT "kb_knowledge_attachment_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table kb_knowledge_category +-- ---------------------------- +ALTER TABLE "public"."kb_knowledge_category" + ADD CONSTRAINT "kb_knowledge_category_pkey" PRIMARY KEY ("category_id"); + +-- ---------------------------- +-- Primary Key structure for table kb_knowledge_collection +-- ---------------------------- +ALTER TABLE "public"."kb_knowledge_collection" + ADD CONSTRAINT "kb_collection_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table kb_knowledge_comment +-- ---------------------------- +ALTER TABLE "public"."kb_knowledge_comment" + ADD CONSTRAINT "kb_comment_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table kb_knowledge_content +-- ---------------------------- +ALTER TABLE "public"."kb_knowledge_content" + ADD CONSTRAINT "kb_knowlegde_content_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table kb_knowledge_img +-- ---------------------------- +ALTER TABLE "public"."kb_knowledge_img" + ADD CONSTRAINT "kb_knowledge_img_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table kb_knowledge_resource +-- ---------------------------- +ALTER TABLE "public"."kb_knowledge_resource" + ADD CONSTRAINT "kb_knowledge_resource_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table kb_knowledge_tag +-- ---------------------------- +ALTER TABLE "public"."kb_knowledge_tag" + ADD CONSTRAINT "kb_knowlegde_tag_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table kb_menu +-- ---------------------------- +ALTER TABLE "public"."kb_menu" + ADD CONSTRAINT "kb_menu_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table kb_resource +-- ---------------------------- +ALTER TABLE "public"."kb_resource" + ADD CONSTRAINT "kb_resource_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table kb_search_history +-- ---------------------------- +ALTER TABLE "public"."kb_search_history" + ADD CONSTRAINT "kb_search_history_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table kb_tag +-- ---------------------------- +ALTER TABLE "public"."kb_tag" + ADD CONSTRAINT "kb_tag_pkey" PRIMARY KEY ("id"); diff --git a/doc/es/1.0.index b/doc/es/1.0.index new file mode 100644 index 0000000..a785060 --- /dev/null +++ b/doc/es/1.0.index @@ -0,0 +1,59 @@ + +公共库 mapping + +PUT knowledge-public +{"mappings": { +"dynamic": "false", +"properties": { +"id": { +"type": "long" +}, +"title": { +"type": "text", +"analyzer": "ik_max_word", +"search_analyzer": "ik_smart" +}, +"content": { +"type": "text", +"analyzer": "ik_smart", +"search_analyzer": "ik_smart" +}, +"createTime": { +"type": "long" +}, +"createById": { +"type": "keyword" +}, +"createByName": { +"type": "keyword" +}, +"updateTime": { +"type": "long" +}, +"updateById": { +"type": "keyword" +}, +"updateByName": { +"type": "keyword" +}, +"categoryId": { +"type": "long" +}, +"baseId": { +"type": "long" +}, +"deptId":{ +"type":"keyword" +}, +"resourcesList": { +"type": "text", +"fields": { +"keyword": { +"type": "keyword" +}}}, +"collectionUsers": { +"type": "text", +"fields": { +"keyword": { +"type": "keyword" +}}}}}} diff --git a/mvnw b/mvnw new file mode 100644 index 0000000..66df285 --- /dev/null +++ b/mvnw @@ -0,0 +1,308 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.2.0 +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "$(uname)" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME + else + JAVA_HOME="/Library/Java/Home"; export JAVA_HOME + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=$(java-config --jre-home) + fi +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --unix "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --unix "$CLASSPATH") +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && + JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=$(which readlink) + if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then + if $darwin ; then + javaHome="$(dirname "\"$javaExecutable\"")" + javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" + else + javaExecutable="$(readlink -f "\"$javaExecutable\"")" + fi + javaHome="$(dirname "\"$javaExecutable\"")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=$(cd "$wdir/.." || exit 1; pwd) + fi + # end of workaround + done + printf '%s' "$(cd "$basedir" || exit 1; pwd)" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + # Remove \r in case we run on Windows within Git Bash + # and check out the repository with auto CRLF management + # enabled. Otherwise, we may read lines that are delimited with + # \r\n and produce $'-Xarg\r' rather than -Xarg due to word + # splitting rules. + tr -s '\r\n' ' ' < "$1" + fi +} + +log() { + if [ "$MVNW_VERBOSE" = true ]; then + printf '%s\n' "$1" + fi +} + +BASE_DIR=$(find_maven_basedir "$(dirname "$0")") +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR +log "$MAVEN_PROJECTBASEDIR" + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" +if [ -r "$wrapperJarPath" ]; then + log "Found $wrapperJarPath" +else + log "Couldn't find $wrapperJarPath, downloading it ..." + + if [ -n "$MVNW_REPOURL" ]; then + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + else + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + fi + while IFS="=" read -r key value; do + # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) + safeValue=$(echo "$value" | tr -d '\r') + case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; + esac + done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + log "Downloading from: $wrapperUrl" + + if $cygwin; then + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") + fi + + if command -v wget > /dev/null; then + log "Found wget ... using wget" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + log "Found curl ... using curl" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + else + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + fi + else + log "Falling back to using Java to download" + javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaSource=$(cygpath --path --windows "$javaSource") + javaClass=$(cygpath --path --windows "$javaClass") + fi + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + log " - Compiling MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/javac" "$javaSource") + fi + if [ -e "$javaClass" ]; then + log " - Running MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +# If specified, validate the SHA-256 sum of the Maven wrapper jar file +wrapperSha256Sum="" +while IFS="=" read -r key value; do + case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; + esac +done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" +if [ -n "$wrapperSha256Sum" ]; then + wrapperSha256Result=false + if command -v sha256sum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + elif command -v shasum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." + echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." + exit 1 + fi + if [ $wrapperSha256Result = false ]; then + echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 + echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 + echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + exit 1 + fi +fi + +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --windows "$CLASSPATH") + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +# shellcheck disable=SC2086 # safe args +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..95ba6f5 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,205 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.2.0 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..bd60a10 --- /dev/null +++ b/pom.xml @@ -0,0 +1,266 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.4 + + + com.kb + knowledgeBase + 0.0.1-SNAPSHOT + knowledgeBase + knowledgeBase + + 21 + + + + + + com.alibaba + druid + 1.2.18 + + + + com.spring4all + swagger-spring-boot-starter + 1.9.0.RELEASE + + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + org.postgresql + postgresql + + + mysql + mysql-connector-java + 5.1.47 + + + org.projectlombok + lombok + 1.18.32 + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + com.baomidou + mybatis-plus-boot-starter + 3.5.5 + + + + org.springframework.boot + spring-boot-starter-data-elasticsearch + 2.3.12.RELEASE + + + + com.fasterxml.jackson.core + jackson-databind + 2.12.3 + + + + jakarta.json + jakarta.json-api + 2.0.1 + + + io.minio + minio + 8.0.3 + + + cn.hutool + hutool-all + 5.8.16 + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-logging + + + + + + commons-io + commons-io + 2.11.0 + + + + commons-lang + commons-lang + 2.6 + + + + org.springframework.boot + spring-boot-starter-aop + + + + org.springframework.kafka + spring-kafka + + + + org.apache.poi + poi + 5.2.2 + + + org.apache.poi + poi + 3.14 + + + org.apache.poi + poi-scratchpad + 3.14 + + + org.apache.poi + poi-ooxml + 3.14 + + + fr.opensagres.xdocreport + xdocreport + 1.0.6 + + + org.apache.poi + poi-ooxml-schemas + 3.14 + + + org.apache.poi + ooxml-schemas + 1.3 + + + + org.apache.pdfbox + pdfbox + 3.0.1 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + utf-8 + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assembly + package + + single + + + + src/main/assembly/assembly.xml + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + + lib + /BOOT-INF/lib/ + + **/*.jar + + + + src/main/java + + **/*.xml + **/*.yml + + false + + + src/main/resources + + **/*.yml + **/*.xml + + false + + + + + diff --git a/src/main/assembly/assembly.xml b/src/main/assembly/assembly.xml new file mode 100644 index 0000000..0c549c2 --- /dev/null +++ b/src/main/assembly/assembly.xml @@ -0,0 +1,47 @@ + + bin + + tar.gz + + true + + + + 775 + target/${project.build.finalName}.jar + knowledgebase.jar + ./target + + + + + + src/main/resources + ./conf + + application.yml + + + + + src/main/resources/logconf + ./conf + + log4j2.xml + + + + + 775 + deploy/bin + ./bin + + + deploy/db + ./db + + + + diff --git a/src/main/java/com/kb/knowledgebase/KnowledgeBaseApplication.java b/src/main/java/com/kb/knowledgebase/KnowledgeBaseApplication.java new file mode 100644 index 0000000..a2c5b1d --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/KnowledgeBaseApplication.java @@ -0,0 +1,18 @@ +package com.kb.knowledgebase; + +import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.kb.knowledgebase.modules.**.mapper") +@Slf4j +public class KnowledgeBaseApplication { + + public static void main(String[] args) { + SpringApplication.run(KnowledgeBaseApplication.class, args); + log.info("====================================启动完成===================================="); + } + +} diff --git a/src/main/java/com/kb/knowledgebase/authority/AuthorityController.java b/src/main/java/com/kb/knowledgebase/authority/AuthorityController.java new file mode 100644 index 0000000..3d865d1 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/authority/AuthorityController.java @@ -0,0 +1,51 @@ +package com.kb.knowledgebase.authority; + +import com.kb.knowledgebase.modules.common.BaseController; +import com.kb.knowledgebase.modules.common.ResponseResult; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@Api(tags = {"授权"}) +@RestController +@RequestMapping("/knowledgeSystem") +public class AuthorityController extends BaseController { + + @Autowired + private AuthorityServiceImpl authorityServiceImpl; + + + @ApiOperation("获取授权信息(Token)") + @GetMapping("/getAuthority") + public ResponseResult getAuthority(@RequestParam("auth_code") String authCode) { + return result(authorityServiceImpl.getToken(authCode)); + } + + @ApiOperation("刷新令牌") + @GetMapping("/refreshToken") + public ResponseResult refreshToken(@RequestParam("token") String token) { + return result(authorityServiceImpl.refreshToken(token)); + } + + @ApiOperation("获取个人信息") + @GetMapping("/getUserInfo") + public ResponseResult getUserInfo(@RequestParam("token") String token) { + return result(authorityServiceImpl.getUserInfoFromThreadLocalUtil(token)); + } + + @ApiOperation("登出(注销令牌)") + @GetMapping("/logout") + public ResponseResult logout(@RequestParam("token") String token) { + authorityServiceImpl.logout(token); + return result(); + } + + @ApiOperation("登出回调接口") + @PostMapping("/logoutCallback") + public ResponseResult logoutCallback(@RequestBody AuthorityToken token) { + authorityServiceImpl.deleteLocalToken(token.getToken()); + return result(); + } + +} diff --git a/src/main/java/com/kb/knowledgebase/authority/AuthorityServiceImpl.java b/src/main/java/com/kb/knowledgebase/authority/AuthorityServiceImpl.java new file mode 100644 index 0000000..7b39029 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/authority/AuthorityServiceImpl.java @@ -0,0 +1,317 @@ +package com.kb.knowledgebase.authority; + +import cn.hutool.json.JSON; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.kb.knowledgebase.entity.MyException; +import com.kb.knowledgebase.entity.ReturnCode; +import com.kb.knowledgebase.entity.knowledge.Attachment; +import com.kb.knowledgebase.modules.knowledge.mapper.AttachmentMapper; +import com.kb.knowledgebase.modules.util.CommonDateUtil; +import com.kb.knowledgebase.modules.util.SignUtil; +import io.netty.util.internal.StringUtil; +import lombok.extern.slf4j.Slf4j; +import okhttp3.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Map; +import java.util.Objects; +import java.util.TreeMap; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +@Service +@Slf4j +public class AuthorityServiceImpl implements IAuthorityService { + + @Autowired + private StringRedisTemplate stringRedisTemplate; + + @Value("${app.baseUrl}") + private String appBaseUrl; + + @Value("${app.key}") + private String appKey; + + @Value("${app.secret}") + private String appSecret; + + + /** + * 获取令牌 + * + * @param authCode 授权码 + * @return token + */ + @Override + public AuthorityToken getToken(String authCode) { + log.info("获取令牌: " + authCode); + OkHttpClient client = new OkHttpClient(); + + // 定义签名参数 + Map paramMap = new TreeMap<>(); + paramMap.put("authCode", authCode); + // 时间戳 + final Long systemTimeMillis = CommonDateUtil.getSystemTimeMillis(); + String systemTime = systemTimeMillis.toString(); + Request request = new Request.Builder() + .url(doCreateUrl("/dgpc/sso/getToken", paramMap)) + .method("GET", null) + .addHeader("appKey", appKey) + .addHeader("timestamp", systemTime) + .addHeader("sign", SignUtil.getSign(appKey, appSecret, paramMap, systemTime)) + .build(); + try { + try (Response response = client.newCall(request).execute()) { + if (response.body() != null) { + final JSON responseJSON = doGetResponseJSON(response); + + final JSON dataJSON = (JSON) responseJSON.getByPath("data"); + + // 访问令牌 + String token = String.valueOf(dataJSON.getByPath("token")); + // 刷新令牌 + String refreshToken = String.valueOf(dataJSON.getByPath("refreshToken")); + + // 访问令牌的有效期(秒) + Long expiresIn = Long.parseLong(String.valueOf(dataJSON.getByPath("expires"))); + AuthorityToken authorityToken = new AuthorityToken(); + authorityToken.setToken(token); + authorityToken.setRefreshToken(refreshToken); + authorityToken.setExpiresIn(expiresIn); + + final UserInfo userInfo = getUserInfo(token); + authorityToken.setUserInfo(userInfo); + + stringRedisTemplate.opsForValue().set(token, JSONUtil.toJsonStr(authorityToken), expiresIn - 500, TimeUnit.SECONDS); + + return authorityToken; + } + } + + } catch (IOException e) { + throw new RuntimeException(e); + } + + return null; + } + + /** + * 刷新令牌 + * + * @param token 旧令牌 + * @return token + */ + @Override + public AuthorityToken refreshToken(String token) { + log.info("刷新令牌: " + token); + final AuthorityToken authorityToken = JSONUtil.toBean(stringRedisTemplate.opsForValue().get(token), AuthorityToken.class); + if (StringUtil.isNullOrEmpty(authorityToken.getRefreshToken())) { + throw new MyException(ReturnCode.AUTH_ERROR); + } + + return doRefreshToken(authorityToken.getRefreshToken()); + } + + private AuthorityToken doRefreshToken(String refreshToken) { + // 定义签名参数 + Map paramMap = new TreeMap<>(); + paramMap.put("refreshToken", refreshToken); + // 时间戳 + final Long systemTimeMillis = CommonDateUtil.getSystemTimeMillis(); + String systemTime = systemTimeMillis.toString(); + Request request = new Request.Builder() + .url(doCreateUrl("/dgpc/sso/refreshToken", paramMap)) + .method("GET", null) + .addHeader("appKey", appKey) + .addHeader("timestamp", systemTime) + .addHeader("sign", SignUtil.getSign(appKey, appSecret, paramMap, systemTime)) + .build(); + OkHttpClient client = new OkHttpClient(); + try { + try (Response response = client.newCall(request).execute()) { + if (response.body() != null) { + final JSON responseJSON = doGetResponseJSON(response); + + final JSON dataJSON = (JSON) responseJSON.getByPath("data"); + // 访问令牌 + String newToken = String.valueOf(dataJSON.getByPath("token")); + // 刷新令牌 + String newRefreshToken = String.valueOf(dataJSON.getByPath("refreshToken")); + // 访问令牌的有效期(秒) + Long expiresIn = Long.parseLong(String.valueOf(dataJSON.getByPath("expires"))); + // 返回值 + AuthorityToken authorityTokenResult = new AuthorityToken(); + authorityTokenResult.setToken(newToken); + authorityTokenResult.setRefreshToken(newRefreshToken); + authorityTokenResult.setExpiresIn(expiresIn); + + final UserInfo userInfo = getUserInfo(authorityTokenResult.getToken()); + authorityTokenResult.setUserInfo(userInfo); + + // 存redis + stringRedisTemplate.opsForValue().set(newToken, JSONUtil.toJsonStr(authorityTokenResult), expiresIn - 500, TimeUnit.SECONDS); + + return authorityTokenResult; + } + } + + } catch (IOException e) { + throw new RuntimeException(e); + } + return null; + } + + private static JSON doGetResponseJSON(Response response) throws IOException { + assert response.body() != null; + final String str = response.body().string(); + return JSONUtil.parse(str); + } + + + /** + * 获取用户信息 + * + * @param token 令牌 + * @return 用户信息 + */ + @Override + public UserInfo getUserInfo(String token) { + log.info("获取用户信息: " + token); + + OkHttpClient client = new OkHttpClient(); + + String url = "/dgpc/sso/info"; + // 定义签名参数 + Map paramMap = new TreeMap<>(); + paramMap.put("token", token); + // 时间戳 + String systemTime = CommonDateUtil.getSystemTimeMillis().toString(); + // 定义请求参数 + RequestBody requestBody = RequestBody.create(JSONUtil.toJsonStr(paramMap), + MediaType.parse(APPLICATION_JSON_VALUE)); + // 发请求 + Request request = new Request.Builder() + .url(doGetFullUrl(url)) + .post(requestBody) + .addHeader("appKey", appKey) + .addHeader("timestamp", systemTime) + .addHeader("sign", SignUtil.getSign(appKey, appSecret, paramMap, systemTime)) + .build(); + + try { + try (Response response = client.newCall(request).execute()) { + if (response.body() != null) { + final JSON responseJSON = doGetResponseJSON(response); + + final JSONObject dataJSON = (JSONObject) responseJSON.getByPath("data"); + final UserInfo userInfo = JSONUtil.toBean(dataJSON, UserInfo.class); + if (null != userInfo.getDeptIds() && userInfo.getDeptIds().length > 0) { + userInfo.setDeptIds(Arrays.stream(userInfo.getDeptIds()) + .filter(StringUtils::hasText) + .toArray(String[]::new) + ); + } + return userInfo; + } + } + + } catch (IOException e) { + throw new RuntimeException(e); + } + + return null; + } + + /** + * 注销令牌 + * + * @param token 令牌 + */ + @Override + public void logout(String token) { + log.info("注销令牌: " + token); + OkHttpClient client = new OkHttpClient(); + + String url = "/dgpc/sso/logout"; + // 定义签名参数 + Map paramMap = new TreeMap<>(); + paramMap.put("token", token); + // 时间戳 + String systemTime = CommonDateUtil.getSystemTimeMillis().toString(); + // 定义请求参数 + RequestBody requestBody = new FormBody.Builder() + .add("token", token) + .build(); + // 发请求 + Request request = new Request.Builder() + .url(doGetFullUrl(url)) + .post(requestBody) + .addHeader("appKey", appKey) + .addHeader("timestamp", systemTime) + .addHeader("sign", SignUtil.getSign(appKey, appSecret, paramMap, systemTime)) + .build(); + + try (Response response = client.newCall(request).execute()) { + if (response.body() != null) { + final String res = response.body().string(); + log.info("logout res: " + res); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * 获取用户信息(从ThreadLocalUtil) + * + * @param token 令牌 + * @return 用户信息 + */ + @Override + public UserInfo getUserInfoFromThreadLocalUtil(String token) { + return ThreadLocalUtil.getUserInfo(); + } + + /** + * 回调登出(本地令牌销毁) + * + * @param token 令牌 + * @return 用户信息 + */ + @Override + public void deleteLocalToken(String token) { + log.info("回调登出(本地令牌销毁)" + token); + stringRedisTemplate.delete(token); + } + + private HttpUrl doCreateUrl(String url, Map paramMap) { + final HttpUrl httpUrl = HttpUrl.parse(doGetFullUrl(url)); + + assert httpUrl != null; + HttpUrl.Builder urlBuilder = httpUrl.newBuilder(); + + if (!CollectionUtils.isEmpty(paramMap)) { + for (Map.Entry entry : paramMap.entrySet()) { + urlBuilder.addQueryParameter(entry.getKey(), entry.getValue()); + } + } + + return urlBuilder.build(); + } + + private String doGetFullUrl(String url) { + return appBaseUrl + url; + } + +} diff --git a/src/main/java/com/kb/knowledgebase/authority/AuthorityToken.java b/src/main/java/com/kb/knowledgebase/authority/AuthorityToken.java new file mode 100644 index 0000000..19ca6fe --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/authority/AuthorityToken.java @@ -0,0 +1,32 @@ +package com.kb.knowledgebase.authority; + +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@ToString +@ApiModel(value="AuthorityToken对象", description="令牌对象") +public class AuthorityToken extends BaseEntity implements Serializable { + + @ApiModelProperty(value = "访问令牌") + private String token; + + @ApiModelProperty(value = "刷新令牌") + private String refreshToken; + + @ApiModelProperty(value = "过期秒数") + private Long expiresIn; + + @ApiModelProperty(value = "用户信息") + private UserInfo userInfo; +} diff --git a/src/main/java/com/kb/knowledgebase/authority/IAuthorityService.java b/src/main/java/com/kb/knowledgebase/authority/IAuthorityService.java new file mode 100644 index 0000000..31bf4cf --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/authority/IAuthorityService.java @@ -0,0 +1,54 @@ +package com.kb.knowledgebase.authority; + +import com.baomidou.mybatisplus.extension.service.IService; + +public interface IAuthorityService { + /** + * 获取令牌 + * + * @param authCode 授权码 + * @return token + */ + AuthorityToken getToken(String authCode); + + /** + * 刷新令牌 + * + * @param token 旧令牌 + * @return token + */ + AuthorityToken refreshToken(String token); + + /** + * 获取用户信息 + * + * @param token 令牌 + * @return 用户信息 + */ + UserInfo getUserInfo(String token); + + /** + * 注销令牌 + * + * @param token 令牌 + */ + void logout(String token); + + /** + * 获取用户信息(从ThreadLocalUtil) + * + * @param token 令牌 + * @return 用户信息 + */ + UserInfo getUserInfoFromThreadLocalUtil(String token); + + /** + * 回调登出(本地令牌销毁) + * + * @param token 令牌 + * @return 用户信息 + */ + void deleteLocalToken(String token); + + +} diff --git a/src/main/java/com/kb/knowledgebase/authority/MyInterceptor.java b/src/main/java/com/kb/knowledgebase/authority/MyInterceptor.java new file mode 100644 index 0000000..0115741 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/authority/MyInterceptor.java @@ -0,0 +1,82 @@ +package com.kb.knowledgebase.authority; + +import cn.hutool.json.JSONUtil; +import com.kb.knowledgebase.config.KbProperties; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@Slf4j +@Component +public class MyInterceptor implements HandlerInterceptor { + + private static final String HEADER_BEARER_PREFIX = "Bearer "; + @Autowired + private IAuthorityService authorityServiceImpl; + @Autowired + private StringRedisTemplate stringRedisTemplate; + @Autowired + private KbProperties kbProperties; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + + UserInfo userInfo = doGetUserInfo(request); + if (null == userInfo) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + return false; + } + + ThreadLocalUtil.setUserInfo(userInfo); + return true; + } + + private UserInfo doGetUserInfo(HttpServletRequest request) { + String token = request.getHeader(HttpHeaders.AUTHORIZATION); + if (!StringUtils.hasText(token)) { + if (Boolean.TRUE.equals(kbProperties.getMockUserEnabled())) { + UserInfo userInfo = new UserInfo(); + userInfo.setId("U123123123"); + userInfo.setUsername("test01"); + userInfo.setDeptId("D01"); + userInfo.setDeptName("部门1"); + return userInfo; + } + + return null; + + } + + final int idx = token.indexOf(HEADER_BEARER_PREFIX); + if (idx >= 0) { + token = token.substring(idx + HEADER_BEARER_PREFIX.length()); + } + + final String tkStr = stringRedisTemplate.opsForValue().get(token); + if (!StringUtils.hasText(tkStr)) { + log.warn("无效的令牌, 空"); + return null; + } + + try { + final AuthorityToken authorityToken = JSONUtil.toBean(tkStr, AuthorityToken.class); + return authorityToken.getUserInfo(); + } catch (Exception e) { + log.info("token invalid", e); + } + return null; + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { + ThreadLocalUtil.clearUserInfo(); // 清除用户信息,避免内存泄漏 + } + +} diff --git a/src/main/java/com/kb/knowledgebase/authority/ThreadLocalUtil.java b/src/main/java/com/kb/knowledgebase/authority/ThreadLocalUtil.java new file mode 100644 index 0000000..4626480 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/authority/ThreadLocalUtil.java @@ -0,0 +1,18 @@ +package com.kb.knowledgebase.authority; + +public class ThreadLocalUtil { + private static final ThreadLocal userInfoThreadLocal = new ThreadLocal<>(); + + public static UserInfo getUserInfo() { + return userInfoThreadLocal.get(); + } + + public static void setUserInfo(UserInfo userInfo) { + userInfoThreadLocal.set(userInfo); + } + + public static void clearUserInfo() { + userInfoThreadLocal.remove(); + } + +} diff --git a/src/main/java/com/kb/knowledgebase/authority/UserInfo.java b/src/main/java/com/kb/knowledgebase/authority/UserInfo.java new file mode 100644 index 0000000..6cff35a --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/authority/UserInfo.java @@ -0,0 +1,56 @@ +package com.kb.knowledgebase.authority; + +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@ToString +@ApiModel(value="UserInfo对象", description="用户信息对象") +public class UserInfo extends BaseEntity implements Serializable { + + @ApiModelProperty(value="用户ID") + private String id; + + @ApiModelProperty(value="用户姓名") + private String username; + + @ApiModelProperty(value="租户ID") + private String tenantId; + + @ApiModelProperty(value="租户名称") + private String tenantName; + + @ApiModelProperty(value="机构ID") + private String deptId; + + @ApiModelProperty(value="机构名称") + private String deptName; + + @ApiModelProperty(value="机构ID集合,一个用户多个机构场景") + private String[] deptIds; + + @ApiModelProperty(value="登录账号") + private String account; + + @ApiModelProperty(value="手机号") + private String phone; + + @ApiModelProperty(value="邮箱") + private String email; + + @ApiModelProperty(value="是否启用(0:否;1:是)") + private Boolean enabled; + + @ApiModelProperty(value="角色ID集合") + private String[] roleIdSet; +} diff --git a/src/main/java/com/kb/knowledgebase/config/ElasticSearchClientConfig.java b/src/main/java/com/kb/knowledgebase/config/ElasticSearchClientConfig.java new file mode 100644 index 0000000..eaee691 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/config/ElasticSearchClientConfig.java @@ -0,0 +1,65 @@ +package com.kb.knowledgebase.config; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.util.StringUtils; + +@Configuration +public class ElasticSearchClientConfig { + @Value("${elasticsearch.endpoint}") + private String endpoint; + + @Value("${elasticsearch.port}") + private Integer port; + + @Value("${elasticsearch.scheme}") + private String scheme; + + @Value("${elasticsearch.username:}") + private String username; + + @Value("${elasticsearch.password:}") + private String password; + + @Bean + public ElasticsearchClient elasticsearchClient(){ + //获取可以用来操作ES的java客户端 +// RestHighLevelClient restHighLevelClient = new RestHighLevelClient( +// RestClient.builder(new HttpHost("127.0.0.1", 9200,"http"))); +// return restHighLevelClient; + + + HttpHost host = new HttpHost(endpoint, port, scheme); + RestClientBuilder builder = RestClient.builder(host); + + if (StringUtils.hasText(username) && StringUtils.hasText(password)) { + CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password)); + builder.setHttpClientConfigCallback(f -> f.setDefaultCredentialsProvider(credentialsProvider)); + } + + RestClient restClient = builder.build(); + + + // 使用Jackson映射器创建传输层 + ElasticsearchTransport transport = new RestClientTransport( + restClient, new JacksonJsonpMapper()); + + // 创建API客户端 + ElasticsearchClient client = new ElasticsearchClient(transport); + + return client; + } +} diff --git a/src/main/java/com/kb/knowledgebase/config/GlobalExceptionHandler.java b/src/main/java/com/kb/knowledgebase/config/GlobalExceptionHandler.java new file mode 100644 index 0000000..ff89238 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/config/GlobalExceptionHandler.java @@ -0,0 +1,48 @@ +package com.kb.knowledgebase.config; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.kb.knowledgebase.entity.MyException; +import com.kb.knowledgebase.modules.common.BaseController; +import com.kb.knowledgebase.modules.common.ResponseResult; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +import javax.servlet.http.HttpServletRequest; +import javax.xml.transform.Result; +import java.util.HashMap; + +/** + * 全局异常捕获 + */ +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(value = Exception.class) + public Object handleException(Exception e, HttpServletRequest request) { + log.info("请求错误,请求地址{},错误信息:", request.getRequestURL(), e); + return ResponseResult.error("系统异常","500", new Object[0]); + + } + + @ExceptionHandler(value = MyException.class) + public Object handleCommonException(MyException ex) { + log.error("通用异常信息", ex); + return ResponseResult.error(ex.getMessage(), new Object[0]); + } + + + +} + + diff --git a/src/main/java/com/kb/knowledgebase/config/KbConfig.java b/src/main/java/com/kb/knowledgebase/config/KbConfig.java new file mode 100644 index 0000000..96db302 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/config/KbConfig.java @@ -0,0 +1,14 @@ +package com.kb.knowledgebase.config; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * @author quangz + * @version 1.0 + */ +@Configuration +@EnableConfigurationProperties(KbProperties.class) +public class KbConfig { + +} diff --git a/src/main/java/com/kb/knowledgebase/config/KbProperties.java b/src/main/java/com/kb/knowledgebase/config/KbProperties.java new file mode 100644 index 0000000..27b4798 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/config/KbProperties.java @@ -0,0 +1,17 @@ +package com.kb.knowledgebase.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * @author quangz + * @version 1.0 + */ +@Data +@ConfigurationProperties("kb") +public class KbProperties { + /** + * 是否启用mock用户 + */ + private Boolean mockUserEnabled; +} diff --git a/src/main/java/com/kb/knowledgebase/config/MinIoClientConfig.java b/src/main/java/com/kb/knowledgebase/config/MinIoClientConfig.java new file mode 100644 index 0000000..09bbedc --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/config/MinIoClientConfig.java @@ -0,0 +1,33 @@ +package com.kb.knowledgebase.config; + +import io.minio.MinioClient; +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; + +@Data +@Component +public class MinIoClientConfig { + @Value("${minio.endpoint}") + private String endpoint; + + @Value("${minio.accessKey}") + private String accessKey; + + @Value("${minio.secretKey}") + private String secretKey; + + /** + * 注入minio 客户端 + * + * @return + */ + @Bean + public MinioClient minioClient() { + return MinioClient.builder() + .endpoint(endpoint) + .credentials(accessKey, secretKey) + .build(); + } +} diff --git a/src/main/java/com/kb/knowledgebase/config/MybatisConfig.java b/src/main/java/com/kb/knowledgebase/config/MybatisConfig.java new file mode 100644 index 0000000..7cd420b --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/config/MybatisConfig.java @@ -0,0 +1,18 @@ +package com.kb.knowledgebase.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MybatisConfig { + //分页拦截器 + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL)); + return interceptor; + } +} diff --git a/src/main/java/com/kb/knowledgebase/config/RedisConfig.java b/src/main/java/com/kb/knowledgebase/config/RedisConfig.java new file mode 100644 index 0000000..da7bfb5 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/config/RedisConfig.java @@ -0,0 +1,21 @@ +package com.kb.knowledgebase.config; + +import com.kb.knowledgebase.authority.AuthorityToken; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +public class RedisConfig { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new StringRedisSerializer()); + return redisTemplate; + } +} diff --git a/src/main/java/com/kb/knowledgebase/config/WebConfig.java b/src/main/java/com/kb/knowledgebase/config/WebConfig.java new file mode 100644 index 0000000..ab30a5a --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/config/WebConfig.java @@ -0,0 +1,52 @@ +package com.kb.knowledgebase.config; + +import cn.hutool.core.date.DatePattern; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.kb.knowledgebase.authority.MyInterceptor; +import com.kb.knowledgebase.core.jackson.KbJavaTimeModule; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.Locale; +import java.util.TimeZone; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Autowired + private MyInterceptor myInterceptor; + + private static final String ASIA_SHANGHAI = "Asia/Shanghai"; + + @Bean + @ConditionalOnMissingBean + public Jackson2ObjectMapperBuilderCustomizer customizer() { + return builder -> { + builder.locale(Locale.CHINA); + builder.timeZone(TimeZone.getTimeZone(ASIA_SHANGHAI)); + builder.simpleDateFormat(DatePattern.NORM_DATETIME_PATTERN); + builder.serializerByType(Long.class, ToStringSerializer.instance); + builder.modules(new KbJavaTimeModule()); + }; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(myInterceptor) + .addPathPatterns("/attachment/**") + .addPathPatterns("/category/**") + .addPathPatterns("/knowledgeBase/**") + .addPathPatterns("/knowledge/**") + .addPathPatterns("/mine/**") + .addPathPatterns("/statistics/**") + .addPathPatterns("/tag/**") + .addPathPatterns("/resource/**"); + } + + +} diff --git a/src/main/java/com/kb/knowledgebase/config/corsConfig.java b/src/main/java/com/kb/knowledgebase/config/corsConfig.java new file mode 100644 index 0000000..8a96961 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/config/corsConfig.java @@ -0,0 +1,25 @@ +package com.kb.knowledgebase.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +@Configuration +public class corsConfig { + @Bean + public CorsFilter corsFilter() { + CorsConfiguration configuration = new CorsConfiguration(); + configuration.addAllowedOriginPattern("*"); // 允许谁跨域 + configuration.setAllowCredentials(true); // 传cookie + configuration.addAllowedMethod("*"); // 允许哪些方法跨域 post/get + configuration.addAllowedHeader("*"); // 允许哪些头信息 + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", configuration); // 拦截一切请求 + + return new CorsFilter(source); + } + +} diff --git a/src/main/java/com/kb/knowledgebase/core/jackson/KbJavaTimeModule.java b/src/main/java/com/kb/knowledgebase/core/jackson/KbJavaTimeModule.java new file mode 100644 index 0000000..5e8847e --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/core/jackson/KbJavaTimeModule.java @@ -0,0 +1,54 @@ +package com.kb.knowledgebase.core.jackson; + +import cn.hutool.core.date.DatePattern; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.datatype.jsr310.PackageVersion; +import com.fasterxml.jackson.datatype.jsr310.deser.*; +import com.fasterxml.jackson.datatype.jsr310.ser.*; + +import java.time.*; +import java.time.format.DateTimeFormatter; + +/** + * @author quangz + * @version 1.0 + */ +public class KbJavaTimeModule extends SimpleModule { + public KbJavaTimeModule() { + super(PackageVersion.VERSION); + + // ======================= 时间序列化规则 =============================== + // yyyy-MM-dd HH:mm:ss + this.addSerializer(LocalDateTime.class, + new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN))); + // yyyy-MM-dd + this.addSerializer(LocalDate.class, + new LocalDateSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN))); + // HH:mm:ss + this.addSerializer(LocalTime.class, + new LocalTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN))); + + // Instant 类型序列化 + this.addSerializer(Instant.class, InstantSerializer.INSTANCE); + + // Duration 类型序列化 + this.addSerializer(Duration.class, DurationSerializer.INSTANCE); + + // ======================= 时间反序列化规则 ============================== + // yyyy-MM-dd HH:mm:ss + this.addDeserializer(LocalDateTime.class, + new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN))); + // yyyy-MM-dd + this.addDeserializer(LocalDate.class, + new LocalDateDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN))); + // HH:mm:ss + this.addDeserializer(LocalTime.class, + new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN))); + // Instant 反序列化 + this.addDeserializer(Instant.class, InstantDeserializer.INSTANT); + + // Duration 反序列化 + this.addDeserializer(Duration.class, DurationDeserializer.INSTANCE); + + } +} diff --git a/src/main/java/com/kb/knowledgebase/entity/MyException.java b/src/main/java/com/kb/knowledgebase/entity/MyException.java new file mode 100644 index 0000000..918b165 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/MyException.java @@ -0,0 +1,45 @@ +package com.kb.knowledgebase.entity; + + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Data +public class MyException extends RuntimeException { + //错误码 + private String code; + + //错误信息 + private String message; + + + public MyException() { + super(); + } + + /** + * 自定义300 + * @param message + */ + public MyException(String message) { + super(message); + this.code = "300"; + this.message = message; + } + public MyException(ReturnCode returnCode) { + super(returnCode.getMsg()); + this.code = returnCode.getCode(); + this.message = returnCode.getMsg(); + } + public MyException(ReturnCode returnCode,String message) { + super(message); + this.code = returnCode.getCode(); + this.message = message; + } + + +} + + + diff --git a/src/main/java/com/kb/knowledgebase/entity/ReturnCode.java b/src/main/java/com/kb/knowledgebase/entity/ReturnCode.java new file mode 100644 index 0000000..32d5be3 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/ReturnCode.java @@ -0,0 +1,19 @@ +package com.kb.knowledgebase.entity; + +public enum ReturnCode { + CUSTOM_ERROR("300","自定义错误类型"),//自定义错误 + AUTH_ERROR("310","授权错误"); + private String code; + private String msg; + ReturnCode(String code, String msg) { + this.code = code; + this.msg = msg; + } + public String getCode() { + return code; + } + + public String getMsg() { + return msg; + } +} diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/Attachment.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/Attachment.java new file mode 100644 index 0000000..2382010 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/Attachment.java @@ -0,0 +1,44 @@ +package com.kb.knowledgebase.entity.knowledge; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@TableName("KB_ATTACHMENT") +@ToString +@ApiModel(value="Attachment对象", description="附件对象") +public class Attachment extends BaseEntity { + @ApiModelProperty(value="id") + @TableId(value = "ID" ,type = IdType.ASSIGN_ID) + private Long id; + + @ApiModelProperty(value="附件名字") + @TableField(value = "ATTACHMENT_NAME") + private String attachmentName; + + @ApiModelProperty(value="附件路径") + @TableField(value = "ATTACHMENT_PATH") + private String attachmentPath; + + @ApiModelProperty(value="创建时间") + @TableField(value = "CREATE_TIME") + private Long createTime; + + @ApiModelProperty(value="创建者") + @TableField(value = "CREATE_BY_ID") + private String createById; + + + +} diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/Category.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/Category.java new file mode 100644 index 0000000..817678a --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/Category.java @@ -0,0 +1,76 @@ +package com.kb.knowledgebase.entity.knowledge; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@TableName("KB_CATEGORY") +@ToString +@ApiModel(value="Category对象", description="分类对象") +public class Category extends BaseEntity implements Serializable { + + @ApiModelProperty(value="id") + @TableId(value = "ID" ,type = IdType.ASSIGN_ID) + private Long id; + + @ApiModelProperty(value="父级id") + @TableField(value = "PID") + private Long pid; + + @ApiModelProperty(value="分类名字") + @TableField(value = "CATEGORY_NAME") + private String categoryName; + + @ApiModelProperty(value="创建时间") + @TableField(value = "CREATE_TIME") + private Long createTime; + + @ApiModelProperty(value="创建id") + @TableField(value = "CREATE_BY_ID") + private String createById; + + @ApiModelProperty(value="更新时间") + @TableField(value = "UPDATE_TIME") + private Long updateTime; + + @ApiModelProperty(value="更新id") + @TableField(value = "UPDATE_BY_ID") + private String updateById; + + @ApiModelProperty(value="知识数量") + @TableField(value = "KB_COUNT") + private int kbCount; + + @ApiModelProperty(value="库id") + @TableField(value = "BASE_ID") + private Long baseId; + + @ApiModelProperty(value="分类串") + @TableField(value = "CATEGORY_FULL_NAME") + private String categoryFullName; + + @ApiModelProperty(value="占比") + @TableField(exist = false) + private String proportion; + + @ApiModelProperty(value="子节点") + @TableField(exist = false) + private List childrenList; + + +} diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/Knowledge.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/Knowledge.java new file mode 100644 index 0000000..00120bf --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/Knowledge.java @@ -0,0 +1,213 @@ +package com.kb.knowledgebase.entity.knowledge; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.models.auth.In; +import lombok.*; +import lombok.experimental.Accessors; +import org.springframework.data.annotation.Transient; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@TableName("KB_KNOWLEDGE") +@ToString +@ApiModel(value="Knowledge对象", description="知识库对象") +public class Knowledge extends BaseEntity implements Serializable { + + + @ApiModelProperty(value="id") + @TableId(value = "ID" ,type = IdType.ASSIGN_ID) + private Long id; + + /**[ + * { + * name :"标签" + * id "xx" + * }, + * { + * name :"标签2", + * id :"x1x" + * } + *] + */ + @ApiModelProperty(value="标签组") + @TableField(exist = false) + @Transient + private List> tags; + + + @ApiModelProperty(value="来源组") + @TableField(exist = false) + @Transient + private List> resources; + + @ApiModelProperty(value="es存的来源id列表") + @TableField(exist = false) + @Transient + private List resourcesList; + + /**[ + * { + * name :"标签" + * path "xx" + * }, + * { + * name :"标签2", + * path :"x1x" + * } + *] + */ + @ApiModelProperty(value="附件组") + @TableField(exist = false) + @Transient + private List> attachments; + + @ApiModelProperty(value="标题") + @TableField(value = "TITLE") + private String title; + + @ApiModelProperty(value="摘要") + @TableField(value = "DESCRIPTION") + private String description; + + @ApiModelProperty(value="内容") + @TableField(exist = false) + private String content; + + + @ApiModelProperty(value="知识类型") + @TableField(value = "IS_TEXT") + private Integer isText; + + @ApiModelProperty(value="知识类型") + @TableField(value = "IS_IMAGE") + private Integer isImage; + + @ApiModelProperty(value="知识类型") + @TableField(value = "IS_DOC") + private Integer isDoc; + + @ApiModelProperty(value="知识类型") + @TableField(value = "IS_VIDEO") + private Integer isVideo; + + + @ApiModelProperty(value="收藏量") + @TableField(value = "COLLECTION_NUM") + private Integer collectionNum; + @ApiModelProperty(value="评论数量") + @TableField(value = "COMMENT_NUM") + private int commentNum; + + @ApiModelProperty(value="浏览量") + @TableField(value = "VIEW_NUM") + private Integer viewNum; + + @ApiModelProperty(value="创建时间") + @TableField(value = "CREATE_TIME") + private Long createTime; + + @ApiModelProperty(value="创建者id") + @TableField(value = "CREATE_BY_ID") + private String createById; + @ApiModelProperty(value="创建者名") + @TableField(value = "CREATE_BY_NAME") + private String createByName; + + @ApiModelProperty(value="更新时间") + @TableField(value = "UPDATE_TIME") + private Long updateTime; + + @ApiModelProperty(value="更新者id") + @TableField(value = "UPDATE_BY_ID") + private String updateById; + + @ApiModelProperty(value="创建者名") + @TableField(value = "UPDATE_BY_NAME") + private String updateByName; + + @ApiModelProperty(value="类别ID") + @TableField(value = "CATEGORY_ID") + private Long categoryId; + + @ApiModelProperty(value="是否发布") + @TableField(value = "IS_PUBLISH") + private Integer isPublish; + + @ApiModelProperty(value="标签串") + @TableField(exist = false) + private String strTags; + + @ApiModelProperty(value="分类串") + @TableField(exist = false) + private String strCategoryIds; + + @ApiModelProperty(value="库id") + @TableField(value = "BASE_ID") + private Long baseId; + + @ApiModelProperty(value="是否公开") + @TableField(value = "IS_PUBLIC") + private Integer isPublic; + + @ApiModelProperty(value="来源") + @TableField(value = "resource") + private String resource; + + + + + + @ApiModelProperty(value="附件 改成一个附件") + @TableField(value = "ATTACHMENT_PATH") + private String attachmentPath; + + @ApiModelProperty(value="只有一个附件 根据类型展示图标") + @TableField(value = "ATTACHMENT_TYPE") + private String attachmentType; + + @ApiModelProperty(value="发布时间 不是文章发布时间") + @TableField(value = "PUBLISH_TIME") + private Long publishTime; + + @ApiModelProperty(value="发实施时间") + @TableField(value = "IMPLEMENT_TIME") + private Long implementTime; + + @ApiModelProperty(value="pdf图片路径") + @TableField(exist = false) + private List imgPaths; + + @ApiModelProperty(value="库名称") + @TableField(exist = false) + private String baseName; + + @ApiModelProperty(value="库名称") + @TableField(exist = false) + private Integer isCollection; + + @ApiModelProperty(value="收藏者列表 不加es插进来就报错") + @TableField(exist = false) + private List collectionUsers; + + @ApiModelProperty(value="文件名") + @TableField(exist = false) + private String fileName; + + + @ApiModelProperty(value="deptid") + @TableField(exist = false) + private String deptId; +} diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeBase.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeBase.java new file mode 100644 index 0000000..038eeaf --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeBase.java @@ -0,0 +1,80 @@ +package com.kb.knowledgebase.entity.knowledge; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@TableName("KB_BASE") +@ToString +@ApiModel(value="KnowledgeBase对象", description="库对象") +public class KnowledgeBase extends BaseEntity implements Serializable { + + @ApiModelProperty(value="id") + @TableId(value = "ID" ,type = IdType.ASSIGN_ID) + private Long id; + + @ApiModelProperty(value="库名") + @TableField(value = "BASE_NAME") + private String baseName; + + @ApiModelProperty(value="创建时间") + @TableField(value = "CREATE_TIME") + private Long createTime; + + @ApiModelProperty(value="创建者id") + @TableField(value = "CREATE_BY_ID") + private String createById; + + @ApiModelProperty(value="创建者姓名") + @TableField(value = "CREATE_BY_NAME") + private String createByName; + + @ApiModelProperty(value="更新时间") + @TableField(value = "UPDATE_TIME") + private Long updateTime; + + @ApiModelProperty(value="更新者id") + @TableField(value = "UPDATE_BY_ID") + private String updateById; + + @ApiModelProperty(value="更新者姓名") + @TableField(value = "UPDATE_BY_NAME") + private String updateByName; + + @ApiModelProperty(value="部门id") + @TableField(value = "DEPT_ID") + private String deptId; + + @ApiModelProperty(value="是否公开 0 非公开 2 公开") + @TableField(value = "IS_PUBLIC") + private int isPublic; + + @ApiModelProperty(value="类目数量") + @TableField(value = "CATEGORY_COUNT") + private Long categoryCount; + + @ApiModelProperty(value="知识数量") + @TableField(value = "KNOWLEDGE_COUNT") + private Long knowledgeCount; + + @ApiModelProperty(value="部门名称") + @TableField(value = "DEPT_NAME") + private String deptName; + + + +} diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeCollection.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeCollection.java new file mode 100644 index 0000000..a265629 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeCollection.java @@ -0,0 +1,54 @@ +package com.kb.knowledgebase.entity.knowledge; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@TableName("KB_KNOWLEDGE_COLLECTION") +@ToString +@ApiModel(value="KnowledgeCollection对象", description="收藏对象") +public class KnowledgeCollection extends BaseEntity implements Serializable { + + @ApiModelProperty(value="id") + @TableId(value = "ID" ,type = IdType.ASSIGN_ID) + private Long id; + + @ApiModelProperty(value="知识ID") + @TableField(value = "KNOWLEGDE_ID") + private Long knowlegdeId; + + @ApiModelProperty(value="用户ID") + @TableField(value = "USER_ID") + private String userId; + + @ApiModelProperty(value="创建时间") + @TableField(value = "CREATE_TIME") + private Long createTime; + + @ApiModelProperty(value="知识对象") + @TableField(exist = false) + private Knowledge knowledge; + + @ApiModelProperty(value="主题库串") + @TableField(exist = false) + private String baseStr; + + @ApiModelProperty(value="总数") + @TableField(exist = false) + private Long total; + +} diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeComment.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeComment.java new file mode 100644 index 0000000..53bde59 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeComment.java @@ -0,0 +1,70 @@ +package com.kb.knowledgebase.entity.knowledge; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@TableName("KB_KNOWLEDGE_COMMENT") +@ToString +@ApiModel(value="KnowledgeComment对象", description="知识评论对象") +public class KnowledgeComment extends BaseEntity implements Serializable { + + @ApiModelProperty(value="id") + @TableId(value = "ID" ,type = IdType.ASSIGN_ID) + private Long id; + + @ApiModelProperty(value="评论内容") + @TableField(value = "COMMENT") + private String comment; + + @ApiModelProperty(value="知识id") + @TableField(value = "KNOWLEDGE_ID") + private Long knowledgeId; + + @ApiModelProperty(value="创建时间") + @TableField(value = "CREATE_TIME") + private Long createTime; + + @ApiModelProperty(value="创建者id") + @TableField(value = "CREATE_BY_ID") + private String createById; + + @ApiModelProperty(value="创建者姓名") + @TableField(value = "CREATE_BY_NAME") + private String createByName; + + @ApiModelProperty(value="更新时间") + @TableField(value = "UPDATE_TIME") + private Long updateTime; + + @ApiModelProperty(value="更新id") + @TableField(value = "UPDATE_BY_ID") + private String updateById; + + @ApiModelProperty(value="更新者姓名") + @TableField(value = "UPDATE_BY_NAME") + private String updateByName; + + @ApiModelProperty(value="知识标题") + @TableField(exist = false) + private String title; + + @ApiModelProperty(value="知识摘要") + @TableField(exist = false) + private String description; +} diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeEs.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeEs.java new file mode 100644 index 0000000..4ae4123 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeEs.java @@ -0,0 +1,94 @@ +package com.kb.knowledgebase.entity.knowledge; + + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; +import org.springframework.data.annotation.Transient; + +import java.io.Serializable; +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@ToString +@ApiModel(value="KnowledgeEs对象", description="知识库请求对象") +public class KnowledgeEs implements Serializable { + @ApiModelProperty(value="id") + @TableId(value = "ID" ,type = IdType.ASSIGN_ID) + private Long id; + + @ApiModelProperty(value="标题") + @TableField(value = "TITLE") + private String title; + + @ApiModelProperty(value="内容") + @TableField(value = "CONTENT") + private String content; + + @ApiModelProperty(value="创建时间") + @TableField(value = "CREATE_TIME") + private Long createTime; + + @ApiModelProperty(value="创建者id") + @TableField(value = "CREATE_BY_ID") + private String createById; + @ApiModelProperty(value="创建者名") + @TableField(value = "CREATE_BY_NAME") + private String createByName; + + @ApiModelProperty(value="更新时间") + @TableField(value = "UPDATE_TIME") + private Long updateTime; + + @ApiModelProperty(value="更新者id") + @TableField(value = "UPDATE_BY_ID") + private String updateById; + + @ApiModelProperty(value="创建者名") + @TableField(value = "UPDATE_BY_NAME") + private String updateByName; + + @ApiModelProperty(value="类别ID") + @TableField(value = "CATEGORY_ID") + private Long categoryId; + + @ApiModelProperty(value="库id") + @TableField(value = "BASE_ID") + private Long baseId; + + @ApiModelProperty(value="资源") + @TableField(value = "RESOURCE") + private String resource; + + @ApiModelProperty(value="部门id") + @TableField(value = "DEPT_ID") + private String deptId; + + @ApiModelProperty(value="附件 改成一个附件") + @TableField(value = "ATTACHMENT_PATH") + private String attachmentPath; + + @ApiModelProperty(value="类型") + @TableField(value = "ATTACHMENT_TYPE") + private String attachmentType; + + @ApiModelProperty(value="收藏者列表") + @TableField(exist = false) + private List collectionUsers; + + + @ApiModelProperty(value="es存的来源id列表") + @TableField(exist = false) + @Transient + private List resourcesList; + +} diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeResource.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeResource.java new file mode 100644 index 0000000..f7d843a --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeResource.java @@ -0,0 +1,37 @@ +package com.kb.knowledgebase.entity.knowledge; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@TableName("KB_KNOWLEDGE_RESOURCE") +@ToString +@ApiModel(value="KnowlegdeResource对象", description="知识来源对象") +public class KnowledgeResource extends BaseEntity implements Serializable { + + @ApiModelProperty(value="id") + @TableId(value = "ID" ,type = IdType.AUTO) + private Long id; + + @ApiModelProperty(value="知识id") + @TableField(value = "KNOWLEDGE_ID") + private Long knowlegdeId; + + @ApiModelProperty(value="来源id") + @TableField(value = "RESOURCE_ID") + private Long resourceId; +} diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeTag.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeTag.java new file mode 100644 index 0000000..50408ce --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeTag.java @@ -0,0 +1,37 @@ +package com.kb.knowledgebase.entity.knowledge; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@TableName("KB_KNOWLEDGE_TAG") +@ToString +@ApiModel(value="KnowledgeTag对象", description="知识标签对象") +public class KnowledgeTag extends BaseEntity implements Serializable { + + @ApiModelProperty(value="id") + @TableId(value = "ID" ,type = IdType.AUTO) + private Long id; + + @ApiModelProperty(value="知识id") + @TableField(value = "KNOWLEDGE_ID") + private Long knowlegdeId; + + @ApiModelProperty(value="标签id") + @TableField(value = "TAG_ID") + private Long tagId; +} diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeVo.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeVo.java new file mode 100644 index 0000000..e18a224 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/KnowledgeVo.java @@ -0,0 +1,153 @@ +package com.kb.knowledgebase.entity.knowledge; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@TableName("KB_KNOWLEDGE") +@ToString +@ApiModel(value="KnowledgeVo对象", description="知识库请求对象") +public class KnowledgeVo extends BaseEntity implements Serializable { + + @ApiModelProperty(value="id") + @TableId(value = "ID" ,type = IdType.ASSIGN_ID) + private Long id; + /**[ + * { + * name :"标签" + * id "xx" + * }, + * { + * name :"标签2", + * id :"x1x" + * } + *] + */ + @ApiModelProperty(value="标签组") + @TableField(exist = false) + private List> tags; + + /**[ + * { + * name :"标签" + * path "xx" + * }, + * { + * name :"标签2", + * path :"x1x" + * } + *] + */ + @ApiModelProperty(value="附件组") + @TableField(exist = false) + private List> attachments; + + @ApiModelProperty(value="查询关键词") + @TableField(exist = false) + private String keyword; + + @ApiModelProperty(value="标题") + @TableField(value = "TITLE") + private String title; + + @ApiModelProperty(value="内容") + @TableField(value = "CONTENT") + private String content; + + @ApiModelProperty(value="知识类型") + @TableField(value = "IS_TEXT") + private Integer isText; + @ApiModelProperty(value="知识类型") + @TableField(value = "IS_IMAGE") + private Integer isImage; + @ApiModelProperty(value="知识类型") + @TableField(value = "IS_DOC") + private Integer isDoc; + @ApiModelProperty(value="知识类型") + @TableField(value = "IS_VIDEO") + private Integer isVideo; + + @ApiModelProperty(value="收藏量") + @TableField(value = "COLLECTION_NUM") + private Integer collectionNum; + + @ApiModelProperty(value="创建时间") + @TableField(value = "CREATE_TIME") + private Long createTime; + + @ApiModelProperty(value="创建者id") + @TableField(value = "CREATE_BY_ID") + private String createById; + @ApiModelProperty(value="创建者名") + @TableField(value = "CREATE_BY_NAME") + private String createByName; + + @ApiModelProperty(value="更新时间") + @TableField(value = "UPDATE_TIME") + private Long updateTime; + + @ApiModelProperty(value="更新者id") + @TableField(value = "UPDATE_BY_ID") + private String updateById; + + @ApiModelProperty(value="创建者名") + @TableField(value = "UPDATE_BY_NAME") + private String updateByName; + + @ApiModelProperty(value="类别ID") + @TableField(value = "CATEGORY_ID") + private Long categoryId; + + @ApiModelProperty(value="来源list") + @TableField(exist = false) + private List resources; + + @ApiModelProperty(value="类别ID及下级id") + @TableField(exist = false) + private List categoryIds; + + + + @ApiModelProperty(value="收藏的文章id 给es查询(哭了)") + @TableField(exist = false) + private List knowledgeIds; + + @ApiModelProperty(value="是否发布") + @TableField(value = "IS_PUBLISH") + private Integer isPublish; + + @ApiModelProperty(value="库id") + @TableField(value = "BASE_ID") + private Long baseId; + + @ApiModelProperty(value="是否公开") + @TableField(value = "IS_PUBLIC") + private Integer isPublic; + + @ApiModelProperty(value="资源") + @TableField(value = "RESOURCE") + private String resource; + + @ApiModelProperty(value="收藏者id") + @TableField(exist = false) + private String colletionUserId; + + +} + diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/Resource.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/Resource.java new file mode 100644 index 0000000..dfe949e --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/Resource.java @@ -0,0 +1,59 @@ +package com.kb.knowledgebase.entity.knowledge; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@TableName("KB_RESOURCE") +@ToString +@ApiModel(value="Resource对象", description="来源对象") +public class Resource extends BaseEntity implements Serializable { + + @ApiModelProperty(value="id") + @TableId(value = "ID" ,type = IdType.ASSIGN_ID) + private Long id; + + @ApiModelProperty(value="来源名") + @TableField(value = "RESOURCE_NAME") + private String resourceName; + + @ApiModelProperty(value="创建时间") + @TableField(value = "CREATE_TIME") + private Long createTime; + + @ApiModelProperty(value="创建者id") + @TableField(value = "CREATE_BY_ID") + private String createById; + + @ApiModelProperty(value="更新时间") + @TableField(value = "UPDATE_TIME") + private Long updateTime; + + @ApiModelProperty(value="更新者id") + @TableField(value = "UPDATE_BY_ID") + private String updateById; + + @ApiModelProperty(value="创建者姓名") + @TableField(value = "CREATE_BY_NAME") + private String createByName; + + @ApiModelProperty(value="更新者姓名") + @TableField(value = "UPDATE_BY_NAME") + private String updateByName; + + +} diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/SearchHistory.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/SearchHistory.java new file mode 100644 index 0000000..495e0fb --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/SearchHistory.java @@ -0,0 +1,48 @@ +package com.kb.knowledgebase.entity.knowledge; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@TableName("KB_SEARCH_HISTORY") +@ToString +@ApiModel(value="SearchHistory对象", description="查询历史") +public class SearchHistory implements Serializable { + + + @ApiModelProperty(value="id") + @TableId(value = "ID" ,type = IdType.ASSIGN_ID) + private Long id; + + @ApiModelProperty(value="用户id") + @TableField(value = "USER_ID") + private String userId; + + @ApiModelProperty(value="用户姓名") + @TableField(value = "USER_NAME") + private String userName; + + @ApiModelProperty(value="查询关键词") + @TableField(value = "SEARCH_WORD") + private String searchWord; + + @ApiModelProperty(value="查询时间") + @TableField(value = "CREATE_TIME") + private Long createTime; + + + +} diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/StatisticsCategoryResult.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/StatisticsCategoryResult.java new file mode 100644 index 0000000..f2f5333 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/StatisticsCategoryResult.java @@ -0,0 +1,28 @@ +package com.kb.knowledgebase.entity.knowledge; + +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@ToString +@ApiModel(value="StatisticsCategoryResult", description="分类统计对象") +public class StatisticsCategoryResult extends BaseEntity implements Serializable { + + @ApiModelProperty(value="合计") + private Long total; + + @ApiModelProperty(value="详细列表") + private List categoryList; + +} diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/StatisticsKnowledgeResult.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/StatisticsKnowledgeResult.java new file mode 100644 index 0000000..715d5ef --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/StatisticsKnowledgeResult.java @@ -0,0 +1,28 @@ +package com.kb.knowledgebase.entity.knowledge; + +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@ToString +@ApiModel(value="StatisticsKnowledgeResult对象", description="知识统计对象") +public class StatisticsKnowledgeResult extends BaseEntity implements Serializable { + + @ApiModelProperty(value="合计") + private Long total; + + @ApiModelProperty(value="详细列表") + private List knowledgeBaseList; + +} diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/StatisticsResult.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/StatisticsResult.java new file mode 100644 index 0000000..047ffcc --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/StatisticsResult.java @@ -0,0 +1,23 @@ +package com.kb.knowledgebase.entity.knowledge; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@ToString +@ApiModel(value="统计图表对象", description="图表对象") +public class StatisticsResult { + + @ApiModelProperty(value="统计数") + private int value; + + @ApiModelProperty(value="名称") + private String name; +} diff --git a/src/main/java/com/kb/knowledgebase/entity/knowledge/Tag.java b/src/main/java/com/kb/knowledgebase/entity/knowledge/Tag.java new file mode 100644 index 0000000..65ca2d4 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/entity/knowledge/Tag.java @@ -0,0 +1,60 @@ +package com.kb.knowledgebase.entity.knowledge; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.kb.knowledgebase.modules.common.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@Builder +@TableName("KB_TAG") +@ToString +@ApiModel(value="Tag对象", description="标签对象") +public class Tag extends BaseEntity implements Serializable { + + @ApiModelProperty(value="id") + @TableId(value = "ID" ,type = IdType.ASSIGN_ID) + private Long id; + + @ApiModelProperty(value="标签名") + @TableField(value = "TAG_NAME") + private String tagName; + + @ApiModelProperty(value="创建时间") + @TableField(value = "CREATE_TIME") + private Long createTime; + + @ApiModelProperty(value="创建者id") + @TableField(value = "CREATE_BY_ID") + private String createById; + + @ApiModelProperty(value="更新时间") + @TableField(value = "UPDATE_TIME") + private Long updateTime; + + @ApiModelProperty(value="更新者id") + @TableField(value = "UPDATE_BY_ID") + private String updateById; + + @ApiModelProperty(value="创建者姓名") + @TableField(value = "CREATE_BY_NAME") + private String createByName; + + @ApiModelProperty(value="更新者姓名") + @TableField(value = "UPDATE_BY_NAME") + private String updateByName; + + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/common/BaseController.java b/src/main/java/com/kb/knowledgebase/modules/common/BaseController.java new file mode 100644 index 0000000..2f5a406 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/common/BaseController.java @@ -0,0 +1,47 @@ +package com.kb.knowledgebase.modules.common; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.kb.knowledgebase.modules.util.CommonPageUtil; + +public class BaseController + // extends BaseController +{ + + protected IPage getIPage(BaseEntity model) { + return CommonPageUtil.getIPage(model); + } + + protected ResponseResult result(IPage iPage) { + return new ResponseResult<>(iPage); + } + + protected ResponseResult result(E obj) { + return new ResponseResult<>(ResponseResult.STATUS_SUCCESS, "成功", obj); + } + + protected ResponseResult result(E obj,Long currentPage,Long pageSize,Long total) { + return new ResponseResult<>(ResponseResult.STATUS_SUCCESS, "成功",obj,currentPage ,pageSize, total); + } + + protected ResponseResult result() { + return new ResponseResult<>(ResponseResult.STATUS_SUCCESS, "成功", new Object[0]); + } + + /** + * 自定义异常 + * @param msg + * @return + */ + protected ResponseResult resultError(String msg) { + return new ResponseResult<>(ResponseResult.STATUS_ERROR, msg); + } + + protected ResponseResult resultError(String msg, Object... args) { + return new ResponseResult<>(ResponseResult.STATUS_ERROR, msg, args); + } + + protected ResponseResult resultError() { + return this.resultError(""); + } + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/common/BaseEntity.java b/src/main/java/com/kb/knowledgebase/modules/common/BaseEntity.java new file mode 100644 index 0000000..610684c --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/common/BaseEntity.java @@ -0,0 +1,40 @@ +package com.kb.knowledgebase.modules.common; + +import com.baomidou.mybatisplus.annotation.TableField; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + + +@EqualsAndHashCode +@Data +public class BaseEntity { + + // @Override + public Integer getCurrentPage() { + return currentPage; + } + + // @Override + public void setCurrentPage(Integer currentPage) { + this.currentPage = currentPage; + } + + // @Override + public Integer getPageSize() { + return pageSize; + } + + // @Override + public void setPageSize(Integer pageSize) { + this.pageSize = pageSize; + } + + @ApiModelProperty(value = "页码",hidden = true) + @TableField(exist = false) + private Integer currentPage = 1; + + @ApiModelProperty(value = "页面条数",hidden = true) + @TableField(exist = false) + private Integer pageSize = 10; +} diff --git a/src/main/java/com/kb/knowledgebase/modules/common/BaseExcelModel.java b/src/main/java/com/kb/knowledgebase/modules/common/BaseExcelModel.java new file mode 100644 index 0000000..ae2a1a7 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/common/BaseExcelModel.java @@ -0,0 +1,56 @@ +package com.kb.knowledgebase.modules.common; + +import com.baomidou.mybatisplus.annotation.TableField; +import io.swagger.annotations.ApiModelProperty; + +public class BaseExcelModel { + /** 错误提示信息 */ + @TableField(exist = false) + @ApiModelProperty(hidden = true) + private String errorMsg; + + /** 错误行数 */ + @TableField(exist = false) + @ApiModelProperty(hidden = true) + private Integer rowNum; + + public Integer getRowNum() { + return rowNum; + } + + public void setRowNum(Integer integer) { + this.rowNum = integer; + } + + public String getErrorMsg() { + return errorMsg; + } +// --------------------- + + // @Override + public Integer getCurrentPage() { + return currentPage; + } + + // @Override + public void setCurrentPage(Integer currentPage) { + this.currentPage = currentPage; + } + + // @Override + public Integer getPageSize() { + return pageSize; + } + + // @Override + public void setPageSize(Integer pageSize) { + this.pageSize = pageSize; + } + @ApiModelProperty(value = "页码",hidden = true) + @TableField(exist = false) + private Integer currentPage; + + @ApiModelProperty(value = "页面条数",hidden = true) + @TableField(exist = false) + private Integer pageSize; +} diff --git a/src/main/java/com/kb/knowledgebase/modules/common/CommonParam.java b/src/main/java/com/kb/knowledgebase/modules/common/CommonParam.java new file mode 100644 index 0000000..a2db78a --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/common/CommonParam.java @@ -0,0 +1,18 @@ +package com.kb.knowledgebase.modules.common; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public interface CommonParam { + Integer PAGE_SIZE = 10; + Integer CURRENT_PAGE = 1; + + String BUCKET_NAME = "knowledge"; + + String RESOURCE_DIR = "/tmp"; + + String KEYWORD_RANKING = "kb_keyword_ranking"; + + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/common/ResponseResult.java b/src/main/java/com/kb/knowledgebase/modules/common/ResponseResult.java new file mode 100644 index 0000000..1078235 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/common/ResponseResult.java @@ -0,0 +1,95 @@ +package com.kb.knowledgebase.modules.common; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@ToString +@EqualsAndHashCode +public class ResponseResult implements Serializable { + + private static final long serialVersionUID = -5945988848945139985L; + + public static final String STATUS_SUCCESS = "200"; + + public static final String STATUS_ERROR = "300"; + + @ApiModelProperty(value = "状态码", example = "500") + private String code; + + @ApiModelProperty(value = "状态描述(用户显示,支持多语言)", example = "操作成功") + private String message; + + @ApiModelProperty("业务数据") + private T data; + + @ApiModelProperty("分页参数") + private PageParam pageParam; + + public ResponseResult() { + } + public static ResponseResult error(String msg, Object... args) { + ResponseResult result = new ResponseResult(); + result.setCode(STATUS_ERROR); + result.setMessage(msg); + return result; + } + public static ResponseResult error(String msg, String code,Object... args) { + ResponseResult result = new ResponseResult(); + result.setCode(code); + result.setMessage(msg); + return result; + } + public ResponseResult(String code, String message, T data) { + this.code = code; + this.message = message; + if (null == data) { + this.data = (T) (new Object()); + } else { + this.data = data; + } + } + + /** + * @param iPage + */ + public ResponseResult(IPage iPage) { + this("200", "成功", (T) (iPage.getRecords())); + this.pageParam = new PageParam(iPage.getCurrent(), iPage.getSize(), iPage.getTotal(), iPage.getPages()); + } + + public ResponseResult(String code, String message,T data,Long currentPage,Long pageSize,Long total) { + this.code = code; + this.message = message; + if (null == data) { + this.data = (T) (new Object()); + } else { + this.data = data; + } + double ceil = Math.ceil((double)total / (double)pageSize); + this.pageParam = new PageParam(currentPage,pageSize,total,(long)ceil); + } + public ResponseResult(String code, String message) { + this(code, message, null); + } + + +} + +@Data +@AllArgsConstructor +@NoArgsConstructor +class PageParam { + @ApiModelProperty(value = "页码", example = "1") + private long pageNumber; + @ApiModelProperty(value = "页面条数", example = "10") + private long pageSize; + @ApiModelProperty(value = "总数据条数", example = "9999") + private long total; + @ApiModelProperty(value = "总分页数", example = "100") + private long totalPage; +} diff --git a/src/main/java/com/kb/knowledgebase/modules/common/log/annotation/SysLog.java b/src/main/java/com/kb/knowledgebase/modules/common/log/annotation/SysLog.java new file mode 100644 index 0000000..eee245c --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/common/log/annotation/SysLog.java @@ -0,0 +1,26 @@ +package com.kb.knowledgebase.modules.common.log.annotation; + +import java.lang.annotation.*; + +/** + * 操作日志注解 + * + * @author quangz + * @version 1.0 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface SysLog { + /** + * 描述 + * @return {String} + */ + String value() default ""; + + /** + * 操作类型 + * @return {String} + */ + String type() default ""; +} diff --git a/src/main/java/com/kb/knowledgebase/modules/common/log/aspect/SysLogAspect.java b/src/main/java/com/kb/knowledgebase/modules/common/log/aspect/SysLogAspect.java new file mode 100644 index 0000000..6dc2e9d --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/common/log/aspect/SysLogAspect.java @@ -0,0 +1,58 @@ +package com.kb.knowledgebase.modules.common.log.aspect; + +import com.kb.knowledgebase.modules.common.log.annotation.SysLog; +import com.kb.knowledgebase.modules.common.log.dto.SysLogDTO; +import com.kb.knowledgebase.modules.common.log.event.SysLogEvent; +import com.kb.knowledgebase.modules.common.log.util.SysLogUtils; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.context.ApplicationEventPublisher; + +/** + * @author quangz + * @version 1.0 + */ +@Slf4j +@Aspect +@RequiredArgsConstructor +public class SysLogAspect { + + private final ApplicationEventPublisher publisher; + + @SneakyThrows + @Around("@annotation(sysLog)") + public Object around(ProceedingJoinPoint point, SysLog sysLog) { + String strClassName = point.getTarget().getClass().getName(); + String strMethodName = point.getSignature().getName(); + log.debug("[类名]:{},[方法]:{}", strClassName, strMethodName); + + String value = sysLog.value(); + + SysLogDTO logDTO = SysLogUtils.createSysLog(); + if (null == logDTO) { + return point.proceed(); + } + + logDTO.setType(sysLog.type()); + logDTO.setOperationDesc(value); + // 发送异步日志事件 + Long startTime = System.currentTimeMillis(); + Object obj = null; + try { + obj = point.proceed(); + } catch (Exception e) { + obj = e; + throw e; + } finally { + Long endTime = System.currentTimeMillis(); + logDTO.setDuration(String.valueOf(endTime - startTime)); + publisher.publishEvent(new SysLogEvent(point.getTarget(), logDTO, obj)); + } + return obj; + } + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/common/log/config/LogAutoConfiguration.java b/src/main/java/com/kb/knowledgebase/modules/common/log/config/LogAutoConfiguration.java new file mode 100644 index 0000000..3c89ebe --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/common/log/config/LogAutoConfiguration.java @@ -0,0 +1,41 @@ +package com.kb.knowledgebase.modules.common.log.config; + +import com.kb.knowledgebase.modules.common.log.aspect.SysLogAspect; +import com.kb.knowledgebase.modules.common.log.listener.SysLogMqListener; +import com.kb.knowledgebase.modules.common.log.util.SysLogUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeansException; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; + +/** + * @author quangz + * @version 1.0 + */ +@Slf4j +@EnableAsync +@Configuration +public class LogAutoConfiguration implements ApplicationContextAware { + + @Bean + @ConditionalOnProperty(value = "kb.log.mq.enabled", havingValue = "true") + public SysLogMqListener sysLogMqListener() { + log.info("log mq enabled"); + return new SysLogMqListener(); + } + + @Bean + public SysLogAspect sysLogAspect(ApplicationEventPublisher publisher) { + return new SysLogAspect(publisher); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + SysLogUtils.setApplicationContext(applicationContext); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/common/log/constant/SysLogTypeConstants.java b/src/main/java/com/kb/knowledgebase/modules/common/log/constant/SysLogTypeConstants.java new file mode 100644 index 0000000..1800255 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/common/log/constant/SysLogTypeConstants.java @@ -0,0 +1,29 @@ +package com.kb.knowledgebase.modules.common.log.constant; + +/** + * @author quangz + * @version 1.0 + */ +public interface SysLogTypeConstants { + + /** + * 新增 + */ + String ADD = "add"; + + /** + * 查询 + */ + String QUERY = "query"; + + /** + * 更新 + */ + String UPDATE = "update"; + + /** + * 删除 + */ + String DELETE = "delete"; + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/common/log/dto/SysLogDTO.java b/src/main/java/com/kb/knowledgebase/modules/common/log/dto/SysLogDTO.java new file mode 100644 index 0000000..973a35a --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/common/log/dto/SysLogDTO.java @@ -0,0 +1,55 @@ +package com.kb.knowledgebase.modules.common.log.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author quangz + * @version 1.0 + */ +@Data +public class SysLogDTO { + + @ApiModelProperty(value="用户ID") + private String userId; + + @ApiModelProperty(value="用户所属机构id") + private String deptId; + + @ApiModelProperty(value="用户名称") + private String userName; + + @ApiModelProperty(value="机构名称") + private String userDeptName; + + @ApiModelProperty(value="应用key") + private String appKey; + + @ApiModelProperty(value="应用名称") + private String appName; + + @ApiModelProperty(value="租户id") + private String tenantId; + + @ApiModelProperty(value="请求时间(yyyy-MM-dd HH:mm:ss)") + private String requestTime; + + @ApiModelProperty(value="请求ip") + private String ip; + + @ApiModelProperty(value="操作类型") + private String type; + + @ApiModelProperty(value="操作描述") + private String operationDesc; + + @ApiModelProperty(value="请求参数") + private String params; + + @ApiModelProperty(value="请求结果") + private String result; + + @ApiModelProperty(value="操作时长(ms)") + private String duration; + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/common/log/event/SysLogEvent.java b/src/main/java/com/kb/knowledgebase/modules/common/log/event/SysLogEvent.java new file mode 100644 index 0000000..4ad3013 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/common/log/event/SysLogEvent.java @@ -0,0 +1,23 @@ +package com.kb.knowledgebase.modules.common.log.event; + +import com.kb.knowledgebase.modules.common.log.dto.SysLogDTO; +import lombok.Getter; +import org.springframework.context.ApplicationEvent; + +/** + * @author quangz + * @version 1.0 + */ +@Getter +public class SysLogEvent extends ApplicationEvent { + + private final SysLogDTO sysLog; + private final Object result; + + public SysLogEvent(Object source, SysLogDTO sysLog, Object result) { + super(source); + this.sysLog = sysLog; + this.result = result; + + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/common/log/listener/SysLogMqListener.java b/src/main/java/com/kb/knowledgebase/modules/common/log/listener/SysLogMqListener.java new file mode 100644 index 0000000..09f2f3f --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/common/log/listener/SysLogMqListener.java @@ -0,0 +1,57 @@ +package com.kb.knowledgebase.modules.common.log.listener; + +import cn.hutool.json.JSONUtil; +import com.kb.knowledgebase.modules.common.ResponseResult; +import com.kb.knowledgebase.modules.common.log.dto.SysLogDTO; +import com.kb.knowledgebase.modules.common.log.event.SysLogEvent; +import com.kb.knowledgebase.modules.util.ResponseResultUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.event.EventListener; +import org.springframework.core.annotation.Order; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.scheduling.annotation.Async; + +/** + * @author quangz + * @version 1.0 + */ +@Slf4j +public class SysLogMqListener { + + @Value("${kb.log.mq.topic:sys-log}") + private String topic; + + @Autowired + private KafkaTemplate kafkaTemplate; + + @Async + @Order + @EventListener(SysLogEvent.class) + public void saveSysLog(SysLogEvent event) { + log.info("sending log"); + SysLogDTO sysLog = event.getSysLog(); + Object result = event.getResult(); + + if (null == result) { + result = ResponseResultUtils.result(); + } else if (result instanceof Exception) { + result = ResponseResultUtils.resultError(((Exception) result).getMessage()); + } + + sysLog.setResult(JSONUtil.toJsonStr(result)); + + final String msg = JSONUtil.toJsonStr(sysLog); + + kafkaTemplate.send(topic, msg); + log.info("log sent"); + + if (log.isDebugEnabled()) { + log.debug("log sent msg: " + msg); + } + + } + + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/common/log/util/SysLogUtils.java b/src/main/java/com/kb/knowledgebase/modules/common/log/util/SysLogUtils.java new file mode 100644 index 0000000..94a9215 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/common/log/util/SysLogUtils.java @@ -0,0 +1,81 @@ +/* + * + * Copyright (c) 2018-2025, ihospital All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: ihospital + * + */ + +package com.kb.knowledgebase.modules.common.log.util; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.URLUtil; +import cn.hutool.extra.servlet.ServletUtil; +import cn.hutool.http.HttpUtil; +import com.kb.knowledgebase.authority.ThreadLocalUtil; +import com.kb.knowledgebase.authority.UserInfo; +import com.kb.knowledgebase.modules.common.log.dto.SysLogDTO; +import lombok.experimental.UtilityClass; +import org.springframework.context.ApplicationContext; +import org.springframework.core.env.Environment; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.util.Date; +import java.util.Objects; + +/** + * 系统日志工具类 + * + * @author L.cm + */ +@UtilityClass +public class SysLogUtils { + + private String appKey; + private String appName; + + public SysLogDTO createSysLog() { + HttpServletRequest request = ((ServletRequestAttributes) Objects + .requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); + + SysLogDTO sysLog = new SysLogDTO(); + + final UserInfo userInfo = ThreadLocalUtil.getUserInfo(); + if (null == userInfo) { + return null; + } + + sysLog.setUserId(userInfo.getId()); + sysLog.setDeptId(userInfo.getDeptId()); + sysLog.setUserName(userInfo.getUsername()); + sysLog.setUserDeptName(userInfo.getDeptName()); + sysLog.setTenantId(userInfo.getTenantId()); + + sysLog.setAppKey(appKey); + sysLog.setAppName(appName); + sysLog.setRequestTime(DateUtil.formatDateTime(new Date())); + sysLog.setIp(ServletUtil.getClientIP(request)); + + return sysLog; + } + + public void setApplicationContext(ApplicationContext applicationContext) { + final Environment environment = applicationContext.getEnvironment(); + appKey = environment.getProperty("app.key"); + appName = environment.getProperty("app.name", "知识库"); + } + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/elasticsearch/impl/ElasticSearchServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/elasticsearch/impl/ElasticSearchServiceImpl.java new file mode 100644 index 0000000..f82a519 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/elasticsearch/impl/ElasticSearchServiceImpl.java @@ -0,0 +1,602 @@ +package com.kb.knowledgebase.modules.elasticsearch.impl; + +import cn.hutool.core.util.StrUtil; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.FieldValue; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.mapping.DynamicMapping; +import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery; +import co.elastic.clients.elasticsearch.core.*; +import co.elastic.clients.elasticsearch.core.search.Hit; +import co.elastic.clients.elasticsearch.core.search.HitsMetadata; +import co.elastic.clients.elasticsearch.indices.CreateIndexResponse; +import co.elastic.clients.json.JsonData; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.kb.knowledgebase.authority.ThreadLocalUtil; +import com.kb.knowledgebase.entity.knowledge.Knowledge; +import com.kb.knowledgebase.entity.knowledge.KnowledgeEs; +import com.kb.knowledgebase.entity.knowledge.KnowledgeVo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static cn.hutool.http.HtmlUtil.cleanHtmlTag; +import static cn.hutool.http.HtmlUtil.removeHtmlTag; + +/** + * elasticSearch操作类 + * 操作knowledge和comment 索引 + * + */ +@Service +@Slf4j +public class ElasticSearchServiceImpl { + + @Autowired + @Qualifier("elasticsearchClient") // 找名字为elasticsearchClient的bean + private ElasticsearchClient client; + /** + * 默认的索引 + */ + String index = "knowledge"; + String commentiIdex = "comment"; + String highLightPreTags = ""; + String highLightPostTags = ""; + + String KB_TITLE = "title"; + String KB_CONTENT = "content"; + String KB_IS_PUBLISH = "isPublish"; + + String KB_BASE_ID = "baseId"; + + String KB_CREATE_TIME = "createTime"; + String KB_CREATE_BY_ID = "createById"; + String KB_CREATE_BY_NAME = "createByName"; + String KB_CATEGORY_ID = "categoryId"; + + String KB_RESOURCE = "resource"; + String KB_RESOURCES_LIST = "resourcesList"; + + + String KB_ID = "id"; + String KB_UPDATE_TIME = "updateTime"; + String KB_UPDATE_BY_ID = "updateById"; + String KB_UPDATE_BY_NAME = "updateByName"; + + String KB_COLLECTION_USERS = "collectionUsers"; + + + String KB_DEPT_ID = "deptId"; + + String COLLLECTION_BASE = "knowledge-public"; + public void createDocument(KnowledgeEs knowledge, String index) { + try { + CreateResponse createResponse = client.create(e->e.index(index).id(knowledge.getId().toString()).document(knowledge)); + System.out.println(createResponse.result()); + log.info("新增es中文章id为{} index为{}",knowledge.getId(),index); + } catch (IOException e) { + log.error("新增es中文章id为{} index为{}时报错:{}",knowledge.getId(),index,e.getMessage()); + throw new RuntimeException(e); + } + } + /** + * 通过id获取 + * @param id + */ + public void queryDocumentById(String id,String index){ + // 构建查询请求 + GetResponse response = null; + try { + response = client.get(e -> e.index(index).id(id), Knowledge.class); + } catch (IOException e) { + throw new RuntimeException(e); + } + System.out.println(response.source().toString()); + } + + /** + * 收藏中查询 跨索引查询 需要两个索引 + * @param knowledges + * @param knowledgeVo + * @return + */ + public Long selectCollectionDocument(List knowledges,KnowledgeVo knowledgeVo,String index){ + String indexPublic = COLLLECTION_BASE; + /** + * 朵个索引查询数据 + */ + List indexList = new ArrayList(){{add(indexPublic);}}; + if(StrUtil.isNotBlank(index)) indexList.add(index); + + log.info("收藏接口查询搜索引{}",indexList); + try { + Integer finalCurrentPage = knowledgeVo.getCurrentPage(); + Integer finalPageSize = knowledgeVo.getPageSize(); + //条件查询器 + BoolQuery.Builder boolQuery = new BoolQuery.Builder(); + if(!StrUtil.isEmpty(knowledgeVo.getKeyword())){ + log.info("Keyword不为空 值:{}",knowledgeVo.getKeyword()); + boolQuery.must(m->m.multiMatch( mm-> mm + .fields(KB_TITLE,KB_CONTENT) + .query(knowledgeVo.getKeyword()) + )); + } + //用户id + if(!StrUtil.isEmpty(knowledgeVo.getColletionUserId())){ + log.info("ColletionUserId不为空 值:{}",knowledgeVo.getColletionUserId()); + boolQuery.must(m -> m + .term( + t -> t + .field(KB_COLLECTION_USERS + ".keyword").value(knowledgeVo.getColletionUserId()) + )); + } +// List knowledgeIds = knowledgeVo.getKnowledgeIds(); + //文章id范围查询 +// if(null != knowledgeIds && knowledgeIds.size()>0){ +// log.info("knowledgeIds不为空 值:{}", knowledgeVo.getKnowledgeIds()); +// List collect = knowledgeIds.stream().map(FieldValue::of).collect(Collectors.toList()); +// boolQuery.must( +// m -> m +// .terms( +// v -> v +// .field(KB_ID).terms( +// term -> term +// .value(collect))) +// ); +// } + + SearchResponse response = client.search( + s -> s + .index(indexList) + .query( + q -> q + .bool(boolQuery.build())) + .highlight( + h -> h + .preTags(highLightPreTags) + .postTags(highLightPostTags) + .fields(KB_TITLE,hf->hf) + .fields(KB_CONTENT, + hf -> hf + .fragmentSize(200) //匹配字符显示200字符 + .numberOfFragments(3)//最多匹配3次 + .noMatchSize(200))) + .from((finalCurrentPage-1)*finalPageSize) + .size(finalPageSize) + .sort( + so -> so + .field( + f -> f + .field(KB_UPDATE_TIME).order(SortOrder.Desc))) + , + Knowledge.class + ); + HitsMetadata hitsMetadata = response.hits(); + Long total = hitsMetadata.total().value(); + List> hits = hitsMetadata.hits(); + + for (Hit hit : hits) { + Knowledge knowledge = hit.source(); + Map> highlight = hit.highlight(); + if (!highlight.isEmpty()){ + List title = highlight.get(KB_TITLE); + if(title != null && title.size() > 0){//title高亮 + knowledge.setTitle(title.get(0)); + } + List content = highlight.get(KB_CONTENT); + if(content != null && content.size() > 0){//content高亮 + knowledge.setContent(content.get(0)); + } + } + + //List sort = hit.sort(); +// System.out.println(sort); +// if (sort.size() > 0) { +// String s = sort.get(0); +// Knowledge.setDistance(s); +// } + knowledges.add(knowledge); + } + return total; + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + /** + * (公共查询)四个搜索条件 关键字 分类 类型(四大类) 来源 + * (私人查询:收藏,) + * @param knowledgeVo + */ + public Long selectDocument(List knowledges,KnowledgeVo knowledgeVo,String index,boolean isHighLight){ + try { + String deptId = ThreadLocalUtil.getUserInfo().getDeptId(); + Integer finalCurrentPage = knowledgeVo.getCurrentPage(); + Integer finalPageSize = knowledgeVo.getPageSize(); + //条件查询器 + BoolQuery.Builder boolQuery = new BoolQuery.Builder(); + if(!StrUtil.isEmpty(knowledgeVo.getKeyword())){ + log.info("Keyword不为空 值:{}",knowledgeVo.getKeyword()); + boolQuery.must(m->m.multiMatch( mm-> mm + .fields(KB_TITLE,KB_CONTENT) + .query(knowledgeVo.getKeyword()) + )); + } + List categoryIds = knowledgeVo.getCategoryIds(); + if(null != categoryIds && categoryIds.size() > 0){ + log.info("categoryIds不为空 值:{}", knowledgeVo.getCategoryIds()); + List collect = categoryIds.stream().map(FieldValue::of).collect(Collectors.toList()); + boolQuery.must(m -> m + .terms(v -> v + .field(KB_CATEGORY_ID).terms(term->term.value(collect))) + ); + } + //用户id + if(!StrUtil.isEmpty(knowledgeVo.getCreateById())){ + log.info("CreateById不为空 值:{}",knowledgeVo.getCreateById()); + boolQuery.must(m -> m + .term( + t -> t + .field(KB_CREATE_BY_ID).value(knowledgeVo.getCreateById()) + )); + } + + //来源 +// List resources = knowledgeVo.getResources(); +// if(null != resources && resources.size()>0){ +// log.info("resources不为空 值:{}", knowledgeVo.getResources()); +// List collect = resources.stream().map(FieldValue::of).collect(Collectors.toList()); +// boolQuery.must( +// m -> m +// .terms( +// v -> v +// .field(KB_RESOURCE).terms( +// term -> term +// .value(collect))) +// ); +// } +// List knowledgeIds = knowledgeVo.getKnowledgeIds(); + //文章id范围查询 +// if(null != knowledgeIds && knowledgeIds.size()>0){ +// log.info("knowledgeIds不为空 值:{}", knowledgeVo.getKnowledgeIds()); +// List collect = knowledgeIds.stream().map(FieldValue::of).collect(Collectors.toList()); +// boolQuery.must( +// m -> m +// .terms( +// v -> v +// .field(KB_ID).terms( +// term -> term +// .value(collect))) +// ); +// } + + //如果查询私有库 是私有库和公开库一起查询, 而且要加deptId + List indexUmi = new ArrayList<>(); + if(COLLLECTION_BASE.equalsIgnoreCase(index)){ + indexUmi.add(index); + }else{ + indexUmi.add(index); + indexUmi.add(COLLLECTION_BASE); + //本部门查询 查询public中数据要加上部门号 + boolQuery.must(m -> m + .term( + t -> t + .field(KB_DEPT_ID).value(deptId) + )); + + } + log.info("查询索引{}",indexUmi); + SearchResponse response = client.search( + s -> s + .index(indexUmi) + .query( + q -> q + .bool(boolQuery.build())) + .highlight( + h -> h + .preTags(highLightPreTags) + .postTags(highLightPostTags) + .fields(KB_TITLE,hf->hf) + .fields(KB_CONTENT, + hf -> hf + .fragmentSize(200) //匹配字符显示200字符 + .numberOfFragments(3)//最多匹配3次 + .noMatchSize(200))) + .from((finalCurrentPage-1)*finalPageSize) + .size(finalPageSize) + .sort( + so -> so + .field( + f -> f + .field(KB_UPDATE_TIME).order(SortOrder.Desc))) + , + Knowledge.class + ); + HitsMetadata hitsMetadata = response.hits(); + Long total = hitsMetadata.total().value(); + List> hits = hitsMetadata.hits(); + + for (Hit hit : hits) { + Knowledge knowledge = hit.source(); + if(isHighLight){ + Map> highlight = hit.highlight(); + if (!highlight.isEmpty()){ + List title = highlight.get(KB_TITLE); + if(title != null && title.size() > 0){//title高亮 + knowledge.setTitle(title.get(0)); + } + List content = highlight.get(KB_CONTENT); + if(content != null && content.size() > 0){//content高亮 + knowledge.setContent(content.get(0)); + } + } + } + + + //List sort = hit.sort(); +// System.out.println(sort); +// if (sort.size() > 0) { +// String s = sort.get(0); +// Knowledge.setDistance(s); +// } + knowledges.add(knowledge); + } + return total; + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + + + /** + * 修改 知识的收藏者列表 + * @param knowledgeId + * @param users + */ + public void changeCollection(Long knowledgeId, List users,String index){ + Map map = new HashMap<>(); + map.put(KB_COLLECTION_USERS, users); + try { + client.update(builder -> builder + .index(index) + .id(knowledgeId.toString()) + .doc(map),Knowledge.class); + log.info("修改es收藏人列表中文章id为{},index为{}",knowledgeId,index); + } catch (IOException e) { + log.error("修改es收藏人列表中文章id为{},index为{}时报错:{}",knowledgeId,index,e.getMessage()); + throw new RuntimeException(e); + } + } + public void changeCategoryId(Long sourceCategoryId, Long destCategoryId, String index){ + try { + + //"ctx._source."+ KB_CATEGORY_ID +" = 'new_value'" +// Script script = new Script.Builder() +// .inline(i -> i.source()) +// .build(); + client.updateByQuery( u -> u + .index(index) + .query( q -> q + .term( t -> t + .field(KB_CATEGORY_ID) + .value(sourceCategoryId)) + ) + .script( s-> s.inline( i -> i + .source("ctx._source." + KB_CATEGORY_ID + "=params.newValue") + .params("newValue", JsonData.of(destCategoryId)) + + )) + + + ); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + /** + * + * @param knowledge 里面要有id + */ + public void updateDocument(Knowledge knowledge, String index){ + Map map = new HashMap<>(); + //更新时间更新者 + if(!StrUtil.isEmpty(knowledge.getUpdateById())){ + map.put(KB_UPDATE_BY_ID, knowledge.getUpdateById()); + } + if(!StrUtil.isEmpty(knowledge.getCreateByName())){ + map.put(KB_UPDATE_BY_NAME, knowledge.getUpdateByName()); + } + map.put(KB_UPDATE_TIME, knowledge.getUpdateTime()); + // 分类id categoryId + if(knowledge.getCategoryId() != null && knowledge.getCategoryId() != Long.MIN_VALUE){ + map.put(KB_CATEGORY_ID, knowledge.getCategoryId()); + } + if(knowledge.getBaseId() != null && knowledge.getBaseId() != Long.MIN_VALUE){ + map.put(KB_BASE_ID, knowledge.getBaseId()); + } + //文章内容 + if(!StrUtil.isEmpty(knowledge.getContent())){ + map.put(KB_CONTENT, cleanHtmlTag(removeHtmlTag(knowledge.getContent(), "style"))); + } + if(!StrUtil.isEmpty(knowledge.getTitle())){ + map.put(KB_TITLE, knowledge.getTitle()); + } + if(!StrUtil.isEmpty(knowledge.getTitle())){ + map.put(KB_RESOURCE, knowledge.getResource()); + } + if(null != knowledge.getResourcesList() && knowledge.getResourcesList().size() > 0){ + map.put(KB_RESOURCES_LIST,knowledge.getResourcesList()); + } +// if(knowledge.getTags() != null && knowledge.getTags().size() > 0){ +// map.put("tags", knowledge.getTags()); +// } +// if(knowledge.getAttachments() != null && knowledge.getAttachments().size() > 0){ +// map.put("attachments", knowledge.getAttachments()); +// } + try { + client.update(builder -> builder + .index(index) + .id(knowledge.getId().toString()) + .doc(map),Knowledge.class); + log.info("修改es中文章id为{},index为{}",knowledge.getId(),index); + } catch (IOException e) { + log.error("修改es中文章id为{},index为{}时报错:{}",knowledge.getId(),index,e.getMessage()); + throw new RuntimeException(e); + } + } + + + + /** + * 通过id删除文档 + * @param id + */ + public void deleteDocument(Long id,String index){ + try { + DeleteResponse delete = client.delete(DeleteRequest.of(h -> h.index(index).id(id.toString()))); + log.info("删除es中文章id为{},index为{}",id,index); + } catch (IOException e) { + log.error("删除es中文章id为{},index为{}时报错:{}",id,index,e.getMessage()); + throw new RuntimeException(e); + } + + } + public void queryIk(String keyword,String index){ + } + + + /** + * 转移索引 从库中转移 并删除原数据 + * @param id 数据id + * @param sourceIndex 来源索引 + * @param destIndex 转移到的索引 + */ + public void transferDocument(Long id,String sourceIndex ,String destIndex){ + try { + client.reindex(r -> r + .source(s -> s + .index(sourceIndex) + .query(q -> q.term( + + t -> t + .field(KB_ID).value(id) + )) + + ) + .dest(d -> d.index(destIndex)) + ); + client.deleteByQuery( d -> d + .index(sourceIndex) + .query( + q -> q + .term( m -> m + .field(KB_ID).value(id) + ))); + log.info("从{}转移id为{}的文档到{}",sourceIndex,id,destIndex); + } catch (IOException e) { + log.error("从{}转移id为{}的文档到{}报错{}:",sourceIndex,id,destIndex,e.getMessage()); + throw new RuntimeException(e); + } + } + + public void transferDocumentByBaseId(Long baseId,String sourceIndex ,String destIndex){ + try { + client.reindex(r -> r + .source(s -> s + .index(sourceIndex) + .query(q -> q.term( + t -> t + .field(KB_BASE_ID).value(baseId) + )) + + ) + .dest(d -> d.index(destIndex)) + ); + + client.deleteByQuery( d -> d + .index(sourceIndex) + .query( + q -> q + .term( m -> m + .field(KB_BASE_ID).value(baseId) + ))); + log.info("从{}转移库id为{}的文档到{}",sourceIndex,baseId,destIndex); + } catch (IOException e) { + log.error("从{}转移库idid为{}的文档到{}报错:{}",sourceIndex,baseId,destIndex,e.getMessage()); + throw new RuntimeException(e); + } + } + + + /** + * 判断索引是否存在 + * @param index + * @return + */ + public boolean indexExist(String index){ + try { + return client.indices().exists(e -> e.index(index)).value(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * 创建索引 + */ + public void createIndex(String index){ + try { + log.info("es试图创建索引{}", index); + boolean indexExist = client.indices().exists(e -> e.index(index)).value(); + if(indexExist) { + log.info("es试图创建索引{},但是已存在", index); + return; + } + CreateIndexResponse createIndexResponse = client.indices() + .create(c -> c + .index(index) + .mappings(m -> m + .dynamic(DynamicMapping.False) + .properties(KB_ID,p -> p.long_( l -> l)) + .properties(KB_TITLE, p ->p.text(t -> t.analyzer("ik_max_word").searchAnalyzer("ik_smart"))) + .properties(KB_CONTENT, p ->p.text(t -> t.analyzer("ik_smart").searchAnalyzer("ik_smart"))) + .properties(KB_CREATE_TIME, p->p.long_(l -> l)) + .properties(KB_CREATE_BY_ID, p->p.keyword(k -> k)) + .properties(KB_DEPT_ID, p->p.keyword(k -> k)) + .properties(KB_CREATE_BY_NAME, p->p.keyword(k -> k)) + .properties(KB_UPDATE_TIME, p->p.long_(l -> l)) + .properties(KB_UPDATE_BY_ID, p->p.keyword(k -> k)) + .properties(KB_UPDATE_BY_NAME, p->p.keyword(k -> k)) + .properties(KB_CATEGORY_ID, p->p.long_(l -> l)) + .properties(KB_BASE_ID, p->p.long_(l -> l)) + .properties(KB_RESOURCES_LIST, p->p.text(t ->t.fields("keywords", f->f.keyword(k -> k)))) + .properties(KB_COLLECTION_USERS, p->p.text(t ->t.fields("keywords", f->f.keyword(k -> k)))) + ) + ); + log.info("es试图创建索引{},结果{}", index,createIndexResponse.acknowledged()); + } catch (JsonProcessingException e ) { + throw new RuntimeException(e); + }catch (IOException e){ + throw new RuntimeException(e); + } + + +// indexMapping.put("properties", ) +// +// createIndexRequest.mapping(); +// +// client.indices().create() + } + + + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/file/FileController.java b/src/main/java/com/kb/knowledgebase/modules/file/FileController.java new file mode 100644 index 0000000..8623f99 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/file/FileController.java @@ -0,0 +1,26 @@ +package com.kb.knowledgebase.modules.file; + +import org.springframework.beans.factory.annotation.Autowired; +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.servlet.http.HttpServletResponse; +import java.io.InputStream; + +@RestController +@RequestMapping("/file") +public class FileController { + + @Autowired + private FileService fileService; + + @GetMapping("/fileDownload") + public void fileDownload(@RequestParam("path") String path, HttpServletResponse response){ + fileService.fileDownload(path,response); + } + + + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/file/FileService.java b/src/main/java/com/kb/knowledgebase/modules/file/FileService.java new file mode 100644 index 0000000..fa58132 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/file/FileService.java @@ -0,0 +1,8 @@ +package com.kb.knowledgebase.modules.file; + +import javax.servlet.http.HttpServletResponse; +import java.io.InputStream; + +public interface FileService { + void fileDownload(String filePath, HttpServletResponse response); +} diff --git a/src/main/java/com/kb/knowledgebase/modules/file/FileServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/file/FileServiceImpl.java new file mode 100644 index 0000000..0a8d727 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/file/FileServiceImpl.java @@ -0,0 +1,72 @@ +package com.kb.knowledgebase.modules.file; + +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.kb.knowledgebase.modules.common.CommonParam; +import com.kb.knowledgebase.modules.util.MinioUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URLEncoder; + +@Service +@Slf4j +public class FileServiceImpl implements FileService{ + @Autowired + private MinioUtil minioUtil; + + @Override + public void fileDownload(String filePath, HttpServletResponse response) { + + InputStream inputStream = null; + OutputStream outputStream = null; + try { + if (StringUtils.isBlank(filePath)) { + response.setHeader("Content-type", "text/html;charset=UTF-8"); + String data = "文件下载失败"; + OutputStream ps = response.getOutputStream(); + ps.write(data.getBytes("UTF-8")); + return; + } + outputStream = response.getOutputStream(); + // 获取文件对象 + inputStream = minioUtil.getObject(CommonParam.BUCKET_NAME, filePath); + byte buf[] = new byte[1024]; + int length = 0; + response.reset(); + response.setHeader("Content-Disposition", "attachment;filename=" + + URLEncoder.encode(filePath.substring(filePath.lastIndexOf("/") + 1), "UTF-8")); + response.setContentType("application/octet-stream"); + response.setCharacterEncoding("UTF-8"); + // 输出文件 + while ((length = inputStream.read(buf)) > 0) { + outputStream.write(buf, 0, length); + } + log.info("{}下载成功",filePath); + inputStream.close(); + } catch (Throwable ex) { + response.setHeader("Content-type", "text/html;charset=UTF-8"); + String data = "文件下载失败"; + try { + OutputStream ps = response.getOutputStream(); + ps.write(data.getBytes("UTF-8")); + } catch (IOException e) { + e.printStackTrace(); + } + } finally { + try { + outputStream.close(); + if (inputStream != null) { + inputStream.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/callable/Pdf2ImgCallable.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/callable/Pdf2ImgCallable.java new file mode 100644 index 0000000..b560c66 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/callable/Pdf2ImgCallable.java @@ -0,0 +1,82 @@ +package com.kb.knowledgebase.modules.knowledge.callable; + +import com.kb.knowledgebase.modules.common.CommonParam; +import com.kb.knowledgebase.modules.util.MinioUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.pdfbox.Loader; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.rendering.PDFRenderer; +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.Callable; + +@Slf4j +public class Pdf2ImgCallable implements Callable> { + + + private MinioUtil minioUtil; + private final List pageList; + private final String filePath; + private float scale = 300/72f; + + public Pdf2ImgCallable(List pageList,String filePath,MinioUtil minioUtil){ + this.pageList = pageList; + this.filePath = filePath; + this.minioUtil = minioUtil; + + } + @Override + public List call() { + List filepaths = new ArrayList<>(); + log.info("处理{}",pageList.toString()); + try (PDDocument document = Loader.loadPDF(new File(filePath))){ + PDFRenderer pdfRenderer = new PDFRenderer(document); + for (Integer i : pageList) { + BufferedImage image = null; + try { + image = pdfRenderer.renderImage(i, scale); + } catch (IOException e) { + throw new RuntimeException(e); + } +// String outputImagePath = "d:/20221121/3pdf/" + (i + 1) + ".png"; +// try { +// ImageIO.write(image, "PNG", new File(outputImagePath)); +// } catch (IOException e) { +// throw new RuntimeException(e); +// } + //String fileName = UUID.randomUUID().toString(); + String objectName = new SimpleDateFormat("yyyy/MM/dd/").format(new Date()) + + UUID.randomUUID().toString().replaceAll("-", "") + +".png" + ; + InputStream inputStream = bufferedImageToInputStream(image); + minioUtil.uploadFile("knowledge",objectName,inputStream); + filepaths.add(objectName); + } + log.info("处理完成{}",pageList.toString()); + } catch (IOException e) { + throw new RuntimeException(e); + } + return filepaths; + } + + public static InputStream bufferedImageToInputStream(BufferedImage image) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + try { + ImageIO.write(image, "png", outputStream); + } catch (IOException e) { + throw new RuntimeException(e); + } + return new ByteArrayInputStream(outputStream.toByteArray()); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/CategoryConstants.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/CategoryConstants.java new file mode 100644 index 0000000..f957ba0 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/CategoryConstants.java @@ -0,0 +1,48 @@ +package com.kb.knowledgebase.modules.knowledge.constant; + +/** + * 分类常量 + * + * @author quangz + * @version 1.0 + */ +public interface CategoryConstants { + + /*分类串分隔符*/ + String CATEGORY_FULL_NAME_SEPARATOR = "/"; + + /*根目录节点ID*/ + int ROOT_PID = 0; + + /*分类类别(0:本部门)*/ + Integer OWN_DEPT = 0; + + /*分类类别(1:公开部门)*/ + Integer PUB_DEPT = 1; + + /*列名:id*/ + String ID = "id"; + + /*列名:更新时间*/ + String UPDATE_TIME = "update_time"; + + /*列名:更新者*/ + String UPDATE_BY_ID = "update_by_id"; + + /*知识查询-根节点名称:全部*/ + String ROOT_NAME_ALL = "全部"; + + /*知识查询-根节点id:-1*/ + Long ROOT_ID_ALL = (long) -1; + + /*格式:#0.00*/ + String FORMAT_DECIMAL = "#0.00"; + + /*0占比:0.00*/ + String DEFAULT_PROPORTION = "0.00"; + + /*合计初期值:0*/ + int BASE_TOTAL = 0; + + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/KbBaseConstants.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/KbBaseConstants.java new file mode 100644 index 0000000..13ed3bc --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/KbBaseConstants.java @@ -0,0 +1,19 @@ +package com.kb.knowledgebase.modules.knowledge.constant; + +/** + * 主题库常量 + * + * @author quangz + * @version 1.0 + */ +public interface KbBaseConstants { + + /*是否公开:1 公开*/ + int IS_PUBLIC_PUB = 1; + + /*错误信息:删除主题库时还存在知识关联*/ + String BASE_ASSOCIATION_MSG = "此主题库下有关联的分类或知识,不可以删除。"; + + /*错误信息:主题库名字重复*/ + String BASENAME_REPEAT_MSG = "主题库名称重复,请重新输入。"; +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/KnowledgeConstants.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/KnowledgeConstants.java new file mode 100644 index 0000000..3c23290 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/KnowledgeConstants.java @@ -0,0 +1,36 @@ +package com.kb.knowledgebase.modules.knowledge.constant; + +import cn.hutool.core.map.MapUtil; + +/** + * 知识常量 + * + * @author quangz + * @version 1.0 + */ +public interface KnowledgeConstants { + + /** + * 完整分类串 + */ + String CATEGORY_FULL_NAME = "category_full_name"; + /** + * 收藏数量 + */ + String COLLECTION_NUM = "collection_num"; + /** + * 浏览量 + */ + String VIEW_NUM = "view_num"; + /** + * 库名 + */ + String BASE_NAME = "base_name"; + /** + * 本人是否收藏 + */ + String IS_COLLECTION = "is_collection"; + + + String RESOURCE = "resource"; +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/MineConstants.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/MineConstants.java new file mode 100644 index 0000000..6208039 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/MineConstants.java @@ -0,0 +1,13 @@ +package com.kb.knowledgebase.modules.knowledge.constant; + +/** + * 【我的】常量 + * + * @author quangz + * @version 1.0 + */ +public interface MineConstants { + + /*内容截取长度(画面显示概要长度)*/ + int CONTENT_LENGTH = 500; +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/ResourceConstants.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/ResourceConstants.java new file mode 100644 index 0000000..1501ae2 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/ResourceConstants.java @@ -0,0 +1,17 @@ +package com.kb.knowledgebase.modules.knowledge.constant; + +/** + * 来源常量 + * + * @author quangz + * @version 1.0 + */ +public interface ResourceConstants { + + /*错误信息:来源重复*/ + String RESOURCE_REPEAT_MSG = "来源名称重复,请重新输入。"; + + /*错误信息:删除来源时还存在知识关联*/ + String RESOURCE_ASSOCIATION_MSG = "目前还有其他知识关联此来源,不能删除"; + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/TagConstants.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/TagConstants.java new file mode 100644 index 0000000..08b9ca9 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/constant/TagConstants.java @@ -0,0 +1,17 @@ +package com.kb.knowledgebase.modules.knowledge.constant; + +/** + * 标签常量 + * + * @author quangz + * @version 1.0 + */ +public interface TagConstants { + + /*错误信息:标签重复*/ + String TAG_REPEAT_MSG = "标签名称重复,请重新输入。"; + + /*错误信息:删除标签时还存在知识关联*/ + String TAG_ASSOCIATION_MSG = "目前还有其他知识关联此标签,不能删除"; + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/AttachmentController.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/AttachmentController.java new file mode 100644 index 0000000..4970e9b --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/AttachmentController.java @@ -0,0 +1,48 @@ +package com.kb.knowledgebase.modules.knowledge.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.kb.knowledgebase.entity.knowledge.Attachment; +import com.kb.knowledgebase.modules.common.BaseController; +import com.kb.knowledgebase.modules.common.ResponseResult; +import com.kb.knowledgebase.modules.knowledge.service.IAttachmentService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.Authorization; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@Api(tags = {"附件操作"}) +@RestController +@RequestMapping("/attachment") +public class AttachmentController extends BaseController { + @Autowired + private IAttachmentService attachmentService; + + @ApiOperation("附件基本操作-分页") + @PostMapping("/query/page") + public ResponseResult queryAttachmentPage(@RequestBody Attachment attachment){ + IPage attachmentIPage = attachmentService.queryAttachmentPage(attachment); + return result(attachmentIPage); + } + + @ApiOperation("附件基本操作-新增") + @PostMapping("/add") + public ResponseResult addAttachment(@RequestParam("file") MultipartFile file){ + Attachment attachment = attachmentService.addAttachment(file); + return result(attachment); + } + @ApiOperation("附件基本操作-删除") + @PostMapping("/delete") + public ResponseResult deleteAttachment(@RequestBody List list){ + System.out.println(list); +// attachmentService.deleteAttachment(attachment); + return result(); + } + + + + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/CategoryController.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/CategoryController.java new file mode 100644 index 0000000..f4a7933 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/CategoryController.java @@ -0,0 +1,73 @@ +package com.kb.knowledgebase.modules.knowledge.controller; + +import com.kb.knowledgebase.entity.knowledge.Category; +import com.kb.knowledgebase.entity.knowledge.StatisticsCategoryResult; +import com.kb.knowledgebase.modules.common.BaseController; +import com.kb.knowledgebase.modules.common.ResponseResult; +import com.kb.knowledgebase.modules.common.log.annotation.SysLog; +import com.kb.knowledgebase.modules.knowledge.service.ICategoryService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static com.kb.knowledgebase.modules.common.log.constant.SysLogTypeConstants.*; + + +@Api(tags = {"知识库-知识类别设置"}) +@RestController +@RequestMapping("/category") +public class CategoryController extends BaseController { + + @Autowired + private ICategoryService iCategoryService; + + @SysLog(value = "知识库-知识类别设置-查询", type = QUERY) + @ApiOperation("知识库-知识类别设置-查询") + @PostMapping(value = "/selectCategory") + public ResponseResult> selectCategory(@RequestBody Category category) { + List categoryList = iCategoryService.selectCategoryList(category); + return result(categoryList); + } + + @SysLog(value = "知识库-知识类别设置-创建分类", type = ADD) + @ApiOperation("知识库-知识类别设置-创建分类") + @PostMapping(value = "/addCategory") + public ResponseResult addCategory(@RequestBody Category category) { + iCategoryService.addCategory(category); + return result(); + } + + @SysLog(value = "知识库-知识类别设置-编辑分类", type = UPDATE) + @ApiOperation("知识库-知识类别设置-编辑分类") + @PostMapping(value = "/updateCategory") + public ResponseResult updateCategory(@RequestBody Category category) { + iCategoryService.updateCategory(category); + return result(); + } + + @SysLog(value = "知识库-知识类别设置-删除分类", type = DELETE) + @ApiOperation("知识库-知识类别设置-删除分类") + @PostMapping(value = "/deleteCategory") + public ResponseResult deleteCategory(@RequestBody Category category) { + iCategoryService.deleteCategory(category); + return result(); + } + + @SysLog(value = "知识库-知识查询-分类树", type = QUERY) + @ApiOperation("知识库-知识查询-分类树") + @GetMapping(value = "/selectKnowledgeCategoryList") + public ResponseResult> selectKnowledgeCategoryList(@RequestParam Integer categoryType) { + return result(iCategoryService.selectKnowledgeCategoryList(categoryType)); + } + + @SysLog(value = "知识库-知识统计-分类统计", type = QUERY) + @ApiOperation("知识库-知识统计-分类统计") + @GetMapping(value = "/selectCategoryStatistics") + public ResponseResult selectCategoryStatistics(@RequestParam Long baseId) { + return result(iCategoryService.selectCategoryStatistics(baseId)); + } + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/KnowledgeBaseController.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/KnowledgeBaseController.java new file mode 100644 index 0000000..9877790 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/KnowledgeBaseController.java @@ -0,0 +1,70 @@ +package com.kb.knowledgebase.modules.knowledge.controller; + +import com.kb.knowledgebase.entity.knowledge.KnowledgeBase; +import com.kb.knowledgebase.entity.knowledge.StatisticsKnowledgeResult; +import com.kb.knowledgebase.modules.common.ResponseResult; +import com.kb.knowledgebase.modules.common.log.annotation.SysLog; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeBaseService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static com.kb.knowledgebase.modules.common.log.constant.SysLogTypeConstants.*; + + +@Api(tags = {"知识库-主题库"}) +@RestController +@RequestMapping("/knowledgeBase") +public class KnowledgeBaseController extends com.kb.knowledgebase.modules.common.BaseController { + + @Autowired + private IKnowledgeBaseService iKnowledgeBaseService; + + @SysLog(value = "知识库-主题库-查询", type = QUERY) + @ApiOperation("知识库-主题库-查询") + @GetMapping(value = "/selectKnowledgeBase") + public ResponseResult> selectKnowledgeBase() { + return result(iKnowledgeBaseService.selectKnowledgeBaseList()); + } + + @SysLog(value = "知识库-主题库-添加", type = ADD) + @ApiOperation("知识库-主题库-添加") + @PostMapping(value = "/addKnowledgeBase") + public ResponseResult addKnowledgeBase(@RequestBody KnowledgeBase knowledgeBase) { + iKnowledgeBaseService.addKnowledgeBase(knowledgeBase); + return result(); + } + + @SysLog(value = "知识库-主题库-更新", type = UPDATE) + @ApiOperation("知识库-主题库-更新") + @PostMapping(value = "/updateKnowledgeBase") + public ResponseResult updateKnowledgeBase(@RequestBody KnowledgeBase knowledgeBase) { + iKnowledgeBaseService.updateKnowledgeBase(knowledgeBase); + return result(); + } + + @SysLog(value = "知识库-主题库-删除", type = DELETE) + @ApiOperation("知识库-主题库-删除") + @GetMapping(value = "/deleteKnowledgeBase") + public ResponseResult deleteKnowledgeBase(@RequestParam Long id) { + iKnowledgeBaseService.deleteKnowledgeBase(id); + return result(); + } + + @SysLog(value = "知识库-知识统计-部门知识统计", type = QUERY) + @ApiOperation("知识库-知识统计-部门知识统计") + @GetMapping(value = "/deptKnowledgeStatistics") + public ResponseResult deptKnowledgeStatistics() { + return result(iKnowledgeBaseService.deptKnowledgeStatistics()); + } + + @SysLog(value = "知识库-知识统计-公开知识统计", type = QUERY) + @ApiOperation("知识库-知识统计-公开知识统计") + @GetMapping(value = "/pubDeptKnowledgeStatistics") + public ResponseResult pubDeptKnowledgeStatistics() { + return result(iKnowledgeBaseService.pubDeptKnowledgeStatistics()); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/KnowledgeController.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/KnowledgeController.java new file mode 100644 index 0000000..a608a5b --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/KnowledgeController.java @@ -0,0 +1,165 @@ +package com.kb.knowledgebase.modules.knowledge.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.kb.knowledgebase.entity.knowledge.Knowledge; +import com.kb.knowledgebase.entity.knowledge.KnowledgeComment; +import com.kb.knowledgebase.entity.knowledge.KnowledgeVo; +import com.kb.knowledgebase.modules.common.BaseController; +import com.kb.knowledgebase.modules.common.ResponseResult; +import com.kb.knowledgebase.modules.common.log.annotation.SysLog; +import com.kb.knowledgebase.modules.elasticsearch.impl.ElasticSearchServiceImpl; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.ZSetOperations; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.util.*; + +import static cn.hutool.http.HtmlUtil.removeHtmlTag; + + +@Api(tags = {"知识库基本操作"}) +@RestController +@RequestMapping("/knowledge") +public class KnowledgeController extends BaseController { + @Autowired + private IKnowledgeService iKnowledgeService; + + /** + * 基于elasticSearch查询 + * @param knowledge + * @return + */ + @SysLog(value = "知识库-知识管理-知识查询", type = "query") + @ApiOperation("知识库基本操作-分页") + @PostMapping("/query/page") + public ResponseResult> queryKnowledgePage(@RequestBody KnowledgeVo knowledge){ + List knowledgeList = new ArrayList<>(); + Long total = iKnowledgeService.queryKnowledgePage(knowledge,knowledgeList); + return result(knowledgeList,new Long(knowledge.getCurrentPage()),new Long(knowledge.getPageSize()),total); + } + + @SysLog(value = "知识库-知识管理-用户收藏知识查询", type = "query") + @ApiOperation("知识库基本操作-查询收藏内知识") + @PostMapping("/collection/query/page") + public ResponseResult> queryCollectionKnowledgePage(@RequestBody KnowledgeVo knowledge){ + List knowledgeList = new ArrayList<>(); + Long total = iKnowledgeService.queryCollectionKnowledgePage(knowledge,knowledgeList); + return result(knowledgeList,new Long(knowledge.getCurrentPage()),new Long(knowledge.getPageSize()),total); + } + + + + @SysLog(value = "知识库-知识管理-主题库内知识查询", type = "query") + @ApiOperation("知识库基本操作-分页 库内知识 不走es查询 ") + @PostMapping("/base/query/page") + public ResponseResult queryKnowledgePageByBaseId(@RequestBody KnowledgeVo knowledge){ + IPage knowledgeIPage = iKnowledgeService.queryKnowledgePageByBaseId(knowledge); + return result(knowledgeIPage); + } + + @SysLog(value = "知识库-知识管理-知识新增", type = "add") + @ApiOperation("知识库基本操作-新增") + @PostMapping("/add") + public ResponseResult addKnowledge(@RequestBody Knowledge knowledge){ + iKnowledgeService.addKnowledge(knowledge); + return result(); + } + @SysLog(value = "知识库-知识管理-知识删除", type = "delete") + @ApiOperation("知识库基本操作-删除") + @PostMapping("/delete") + public ResponseResult knowledgeDelete(@RequestBody Knowledge knowledge){ + iKnowledgeService.deleteKnowledge(knowledge); + return result(); + } + @SysLog(value = "知识库-知识管理-知识更新", type = "update") + @ApiOperation("知识库基本操作-更新") + @PostMapping("/update") + public ResponseResult knowledgeUpdate(@RequestBody Knowledge knowledge){ + iKnowledgeService.updateKnowledge(knowledge); + return result(); + } + + @SysLog(value = "知识库-知识管理-知识详情", type = "detail") + @ApiOperation("知识库基本操作-详细") + @PostMapping("/detail") + public ResponseResult getKnowledgeDetail(@RequestBody Knowledge knowledge) + { + Knowledge res = iKnowledgeService.getKnowledgeDetail(knowledge); + return result(res); + } + + @SysLog(value = "知识库-知识管理-上架下架知识", type = "update") + @ApiOperation("知识库基本操作-上架 下架") + @PostMapping("/publishKnowledge") + public ResponseResult publishKnowledge(@RequestBody Knowledge knowledge){ + iKnowledgeService.publishKnowledge(knowledge); + return result(); + } + + @SysLog(value = "知识库-知识管理-知识转移", type = "update") + @ApiOperation("知识库基本操作-转移") + @PostMapping("/transferKnowledge") + public ResponseResult transferKnowledge(@RequestBody Knowledge knowledge) { + iKnowledgeService.transferKnowledge(knowledge); + + return result(); + } + /** + * 最新知识排行 + * @return + */ + @SysLog(value = "知识库-知识管理-主题库内知识查询", type = "query") + @GetMapping("/selectNewKnowledgeRanking") + public ResponseResult newKnowledgeRanking(){ + return result(iKnowledgeService.newKnowledgeRanking()); + } + + /** + * 最热知识排行 + * @return + */ + @SysLog(value = "知识库-知识管理-热门知识排行", type = "query") + @GetMapping("/selectHotKnowledgeRanking") + public ResponseResult hotKnowledgeRanking(){ + return result(iKnowledgeService.hotKnowledgeRanking()); + } + + + @SysLog(value = "知识库-知识管理-知识推荐", type = "query") + @GetMapping("/recommend") + public ResponseResult recommend(){return result(iKnowledgeService.recommend());} + /** + * 上传minio并生成外链 + * @param file + * @return + */ + @SysLog(value = "知识库-知识管理-上传文件转换", type = "add") + @PostMapping("/upload/file") + public ResponseResult> uploadKnowledge(@RequestParam("file") MultipartFile file) { + Map s = iKnowledgeService.uploadKnowledge(file); + return result(s); + } + + /** + * 关键词热词 + * @return + */ + @SysLog(value = "知识库-知识管理-热门关键词", type = "query") + @GetMapping("/keywordRanking") + public ResponseResult getkeywordsRanking(){ + Set> typedTuples = iKnowledgeService.getkeywordsRanking(); + return result(typedTuples); + } + + + @GetMapping("/fileDownload") + public void fileDownload(@RequestParam("path") String path, HttpServletResponse response){ + iKnowledgeService.fileDownload(path,response); + } + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/MineController.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/MineController.java new file mode 100644 index 0000000..11ff7f0 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/MineController.java @@ -0,0 +1,83 @@ +package com.kb.knowledgebase.modules.knowledge.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.kb.knowledgebase.entity.knowledge.Knowledge; +import com.kb.knowledgebase.entity.knowledge.KnowledgeCollection; +import com.kb.knowledgebase.entity.knowledge.KnowledgeVo; +import com.kb.knowledgebase.modules.common.BaseController; +import com.kb.knowledgebase.modules.common.ResponseResult; +import com.kb.knowledgebase.modules.common.log.annotation.SysLog; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeCollectionService; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeService; +import io.netty.util.internal.StringUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; + +import static com.kb.knowledgebase.modules.common.log.constant.SysLogTypeConstants.*; + + +@Api(tags = {"知识库-我的"}) +@RestController +@RequestMapping("/mine") +public class MineController extends BaseController { + + @Autowired + private IKnowledgeCollectionService iKnowledgeCollectionService; + + @Autowired + private IKnowledgeService iKnowledgeService; + +// @ApiOperation("知识库-我的-我的评论-初期查询") +// @PostMapping(value = "/selectKnowledgeComment") +// public ResponseResult> selectKnowledgeComment(@RequestParam String userId) { +// return result(iKnowledgeCommentService.selectKnowledgeComment(userId)); +// } +// +// @ApiOperation("知识库-我的-我的评论-编辑") +// @PostMapping(value = "/updateKnowledgeComment") +// public ResponseResult updateKnowledgeComment(@RequestParam Long id, @RequestParam String comment) { +// iKnowledgeCommentService.updateKnowledgeComment(id,comment); +// return result(); +// } +// +// @ApiOperation("知识库-我的-我的评论-删除") +// @PostMapping(value = "/deleteKnowledgeComment") +// public ResponseResult deleteKnowledgeComment(@RequestParam Long id) { +// iKnowledgeCommentService.deleteKnowledgeComment(id); +// return result(); +// } + @SysLog(value = "知识库-我的收藏-初期查询", type = QUERY) + @ApiOperation("知识库-我的收藏-初期查询") + @PostMapping(value = "/selectKnowledgeCollection") + public ResponseResult> selectKnowledgeCollection(@RequestBody KnowledgeVo knowledge) { + if (StringUtil.isNullOrEmpty(knowledge.getKeyword())) { + IPage page = iKnowledgeCollectionService.selectKnowledgeCollection(knowledge); + return result(page.getRecords(),new Long(knowledge.getCurrentPage()),new Long(knowledge.getPageSize()),page.getTotal()); + } else { + List knowledgeList = new ArrayList<>(); + Long total = iKnowledgeService.queryCollectionKnowledgePage(knowledge,knowledgeList); + return result(knowledgeList,new Long(knowledge.getCurrentPage()),new Long(knowledge.getPageSize()),total); + } + } + @SysLog(value = "知识库-我的收藏-取消收藏", type = DELETE) + @ApiOperation("知识库-我的收藏-取消收藏") + @GetMapping(value = "/cancelKnowledgeCollection") + public ResponseResult cancelKnowledgeCollection(@RequestParam Long id) { + iKnowledgeCollectionService.cancelKnowledgeCollection(id); + return result(); + } + + @SysLog(value = "知识库-我的收藏-添加收藏", type = ADD) + @ApiOperation("知识库-我的收藏-添加收藏") + @GetMapping(value = "/addKnowledgeCollection") + public ResponseResult addKnowledgeCollection(@RequestParam Long kid) { + iKnowledgeCollectionService.addKnowledgeCollection(kid); + return result(); + } + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/ResourceController.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/ResourceController.java new file mode 100644 index 0000000..f5a5724 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/ResourceController.java @@ -0,0 +1,47 @@ +package com.kb.knowledgebase.modules.knowledge.controller; + +import com.kb.knowledgebase.entity.knowledge.Resource; +import com.kb.knowledgebase.modules.common.BaseController; +import com.kb.knowledgebase.modules.common.ResponseResult; +import com.kb.knowledgebase.modules.common.log.annotation.SysLog; +import com.kb.knowledgebase.modules.knowledge.service.IResourceService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static com.kb.knowledgebase.modules.common.log.constant.SysLogTypeConstants.*; + + +@Api(tags = {"知识库-来源管理"}) +@RestController +@RequestMapping("/resource") +public class ResourceController extends BaseController { + + @Autowired + private IResourceService iResourceService; + @SysLog(value = "知识库-来源管理-来源查询/刷新", type = QUERY) + @ApiOperation("知识库-来源管理-来源查询/刷新") + @GetMapping(value = "/selectResource") + public ResponseResult> selectResource(@RequestParam String resourceName) { + return result(iResourceService.selectResourceList(resourceName)); + } + + @SysLog(value = "知识库-来源管理-添加来源", type = ADD) + @ApiOperation("知识库-来源管理-添加来源") + @PostMapping(value = "/addResource") + public ResponseResult addResource(@RequestBody Resource resource) { + iResourceService.addResource(resource); + return result(); + } + + @SysLog(value = "知识库-来源管理-删除来源", type = DELETE) + @ApiOperation("知识库-来源管理-删除来源") + @GetMapping(value = "/deleteResource") + public ResponseResult deleteResource(@RequestParam Long id) { + iResourceService.deleteResource(id); + return result(); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/StatisticsController.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/StatisticsController.java new file mode 100644 index 0000000..1dcd8c6 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/StatisticsController.java @@ -0,0 +1,88 @@ +package com.kb.knowledgebase.modules.knowledge.controller; + +import com.kb.knowledgebase.entity.knowledge.StatisticsResult; +import com.kb.knowledgebase.modules.common.BaseController; +import com.kb.knowledgebase.modules.common.ResponseResult; +import com.kb.knowledgebase.modules.common.log.annotation.SysLog; +import com.kb.knowledgebase.modules.knowledge.service.IStatisticsService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +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 java.util.List; + +import static com.kb.knowledgebase.modules.common.log.constant.SysLogTypeConstants.QUERY; + +@Api(tags = {"知识库-数量统计"}) +@RestController +@RequestMapping("/statistics") +public class StatisticsController extends BaseController { + + + @Autowired + private IStatisticsService statisticsService; + /** + * 全平台接口统计 + * @return + */ + @SysLog(value = "知识库-类别统计-查询", type = QUERY) + @ApiOperation("知识库-类别统计-查询") + @GetMapping(value = "/queryTypeStatistics") + public ResponseResult> queryTypeStatistics(){ + return result(statisticsService.queryTypeStatistics()); + } + + @SysLog(value = "知识库-来源统计-查询", type = QUERY) + @ApiOperation("知识库-来源统计-查询") + @GetMapping(value = "/queryResourceStatistics") + public ResponseResult> queryResourceStatistics(){ + return result(statisticsService.queryResourceStatistics()); + } + + @SysLog(value = "知识库-大类统计-查询", type = QUERY) + @ApiOperation("知识库-大类统计-查询") + @GetMapping(value = "/queryCategoryStatistics") + public ResponseResult> queryCategoryStatistics(){ + return result(statisticsService.queryCategoryStatistics()); + } + + @SysLog(value = "知识库-库-查询", type = QUERY) + @ApiOperation("知识库-库-查询") + @GetMapping(value = "/queryBaseCount") + public ResponseResult queryBaseCount(@RequestParam("is_public") Integer isPublic){ + return result(statisticsService.queryBaseCount(isPublic)); + } + + @SysLog(value = "知识库-知识概览-部门知识概览", type = QUERY) + @ApiOperation("知识库-知识概览-部门知识概览") + @GetMapping(value = "/deptKnowledgeStatistics") + public ResponseResult> deptKnowledgeStatistics(){ + return result(statisticsService.deptKnowledgeStatistics()); + } + + @SysLog(value = "知识库-知识概览-部门主题库概览(饼图)", type = QUERY) + @ApiOperation("知识库-知识概览-部门主题库概览(饼图)") + @GetMapping(value = "/deptBaseStatistics") + public ResponseResult> deptBaseStatistics(){ + return result(statisticsService.deptBaseStatistics()); + } + + @SysLog(value = "知识库-知识概览-部门知识来源概览", type = QUERY) + @ApiOperation("知识库-知识概览-部门知识来源概览") + @GetMapping(value = "/deptResourceStatistics") + public ResponseResult> deptResourceStatistics(){ + return result(statisticsService.deptResourceStatistics()); + } + + @SysLog(value = "知识库-知识概览-公开知识概览", type = QUERY) + @ApiOperation("知识库-知识概览-公开知识概览") + @GetMapping(value = "/pubKnowledgeStatistics") + public ResponseResult> pubKnowledgeStatistics(){ + return result(statisticsService.pubKnowledgeStatistics()); + } + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/TagController.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/TagController.java new file mode 100644 index 0000000..7b35814 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/controller/TagController.java @@ -0,0 +1,48 @@ +package com.kb.knowledgebase.modules.knowledge.controller; + +import com.kb.knowledgebase.entity.knowledge.Tag; +import com.kb.knowledgebase.modules.common.BaseController; +import com.kb.knowledgebase.modules.common.ResponseResult; +import com.kb.knowledgebase.modules.common.log.annotation.SysLog; +import com.kb.knowledgebase.modules.knowledge.service.ITagService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static com.kb.knowledgebase.modules.common.log.constant.SysLogTypeConstants.*; + + +@Api(tags = {"知识库-标签管理"}) +@RestController +@RequestMapping("/tag") +public class TagController extends BaseController { + + @Autowired + private ITagService iTagService; + + @SysLog(value = "知识库-标签管理-标签查询/刷新", type = QUERY) + @ApiOperation("知识库-标签管理-标签查询/刷新") + @GetMapping(value = "/selectTag") + public ResponseResult> selectTag(@RequestParam String tagName) { + return result(iTagService.selectTagList(tagName)); + } + + @SysLog(value = "知识库-标签管理-添加标签", type = ADD) + @ApiOperation("知识库-标签管理-添加标签") + @PostMapping(value = "/addTag") + public ResponseResult addTag(@RequestBody Tag tag) { + iTagService.addTag(tag); + return result(); + } + + @SysLog(value = "知识库-标签管理-删除标签", type = DELETE) + @ApiOperation("知识库-标签管理-删除标签") + @GetMapping(value = "/deleteTag") + public ResponseResult deleteTag(@RequestParam Long id) { + iTagService.deleteTag(id); + return result(); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/AttachmentMapper.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/AttachmentMapper.java new file mode 100644 index 0000000..a70f8e4 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/AttachmentMapper.java @@ -0,0 +1,13 @@ +package com.kb.knowledgebase.modules.knowledge.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.kb.knowledgebase.entity.knowledge.Attachment; +import org.apache.ibatis.annotations.Param; + +public interface AttachmentMapper extends BaseMapper { + + IPage queryAttachmentPage(Page page, @Param("param") Attachment attachment); + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/CategoryMapper.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/CategoryMapper.java new file mode 100644 index 0000000..6311502 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/CategoryMapper.java @@ -0,0 +1,34 @@ +package com.kb.knowledgebase.modules.knowledge.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.kb.knowledgebase.entity.knowledge.Category; +import com.kb.knowledgebase.entity.knowledge.StatisticsResult; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface CategoryMapper extends BaseMapper { + + /** + * 知识类别设置-查询 + * @param category 分类查询条件 + * @return 结果集 + */ + List selectCategoryList(Category category); + + /** + * 知识概览-知识大类统计 + * @return 结果集 + */ + List selectOneLevelStatistics(); + + /** + * 获取子级ID(包含自ID) + * @param pid 父id + * @return 结果集 + */ + List selectCategoryListByPid(@Param("pid") Long pid); + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeBaseMapper.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeBaseMapper.java new file mode 100644 index 0000000..ffc96f6 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeBaseMapper.java @@ -0,0 +1,19 @@ +package com.kb.knowledgebase.modules.knowledge.mapper; + +import com.kb.knowledgebase.entity.knowledge.KnowledgeBase; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface KnowledgeBaseMapper extends com.baomidou.mybatisplus.core.mapper.BaseMapper { + + /** + * 主题库-查询 + * + * @param deptId 部门id + * @return 结果集 + */ + List selectKnowledgeBaseList(String deptId); + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeCollectionMapper.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeCollectionMapper.java new file mode 100644 index 0000000..2d38d63 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeCollectionMapper.java @@ -0,0 +1,34 @@ +package com.kb.knowledgebase.modules.knowledge.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.kb.knowledgebase.entity.knowledge.Knowledge; +import com.kb.knowledgebase.entity.knowledge.KnowledgeCollection; +import com.kb.knowledgebase.entity.knowledge.KnowledgeVo; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; + +@Repository +public interface KnowledgeCollectionMapper extends BaseMapper { + /** + * 我的-我的收藏-初期查询 + * + * @param knowledge 收藏 + * @return 结果集 + */ + IPage selectKnowledgeCollection(Page page , @Param("param") KnowledgeVo knowledge); + + /** + * 查询收藏用户List + * + * @param kid 收藏 + * @return 结果集 + */ + List selectCollectionUserList(Long kid); + + List> queryResources(@Param("list") List list); +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeCommentMapper.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeCommentMapper.java new file mode 100644 index 0000000..5fcb5ab --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeCommentMapper.java @@ -0,0 +1,20 @@ +package com.kb.knowledgebase.modules.knowledge.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.kb.knowledgebase.entity.knowledge.KnowledgeComment; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface KnowledgeCommentMapper extends BaseMapper { + /** + * 我的-我的评论-初期查询 + * + * @param userId 用户id + * @return 结果集 + */ + List selectKnowledgeComment(@Param("userId")String userId); + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeMapper.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeMapper.java new file mode 100644 index 0000000..63db905 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeMapper.java @@ -0,0 +1,94 @@ +package com.kb.knowledgebase.modules.knowledge.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.kb.knowledgebase.entity.knowledge.Knowledge; +import com.kb.knowledgebase.entity.knowledge.KnowledgeBase; +import com.kb.knowledgebase.entity.knowledge.KnowledgeVo; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; + +@Repository +public interface KnowledgeMapper extends BaseMapper { + IPage queryKnowledgePage(Page page , @Param("param") Knowledge knowledge); + + + IPage queryKnowledgePageByBaseId(Page page , @Param("param") KnowledgeVo knowledge); + + List> queryResources(@Param("list") List list); + + List> queryAddtionalData(@Param("userId") String userId,@Param("list") List list); + + + int getBaseCount(@Param("deptId") String deptId); + + List queryKnowledgePage(@Param("param") Knowledge knowledge); + + + List newKnowledgeRanking(@Param("num") int number); + + List hotKnowledgeRanking(@Param("num") int number); + List hotKnowledgeRanking1(@Param("num") int number, @Param("list") List list); + + + + List> queryTotal(@Param("type") String type); + + void addKnowledgeTags(@Param("list") List list, @Param("id") Long id); + + void deleteKnowledgeTags(@Param("id") Long id); + + void addKnowledgeResource(@Param("list") List list, @Param("id") Long id); + + void deleteKnowledgeResource(@Param("id") Long id); + void addKnowledgeContent(@Param("id")Long id, @Param("content") String content); + + void updateKnowledgeContent(@Param("id")Long id, @Param("content") String content); + void deleteKnowledgeContent(@Param("id")Long id); + + void addKnowledgeImgPaths(@Param("id")Long id, @Param("list") List imgPaths); + + void deleteKnowledgeImgPaths(@Param("id")Long id); + + void addKnowledgeAttachments(@Param("list") List list, @Param("id") Long id); + + List selectKnowledgeImgPaths(@Param("id") Long id); + KnowledgeBase queryKnowledgeDeptId(@Param("id") Long id); + KnowledgeBase queryDeptIdByKnowledgeId(@Param("id") Long id); + + + Knowledge getKnowledgeDetail(@Param("id") Long id,@Param("userId") String userId); + + + String getContentById(@Param("id") Long id); + + void incrViewNum(@Param("id") Long id); + + List>selectTagsById(@Param("id") Long id); + List>selectResourcesById(@Param("id") Long id); + + + //库内知识量+1 + void incrBaseKbCount(@Param("id") Long id); + //分类知识量+1 + void incrCategoryKbCount(@Param("id") Long id); + + + void decrBaseKbCount(@Param("id") Long id); + //分类知识量+1 + void decrCategoryKbCount(@Param("id") Long id); + + //查询用户收藏列表 做查询用 + List getColletionListByUserId(@Param("userId") String id); + + void isTransfer(Long sourceBaseId, Long destBaseId); + + + + + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeResourceMapper.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeResourceMapper.java new file mode 100644 index 0000000..1318fbf --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeResourceMapper.java @@ -0,0 +1,10 @@ +package com.kb.knowledgebase.modules.knowledge.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.kb.knowledgebase.entity.knowledge.KnowledgeResource; +import org.springframework.stereotype.Repository; + +@Repository +public interface KnowledgeResourceMapper extends BaseMapper { + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeTagMapper.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeTagMapper.java new file mode 100644 index 0000000..21d0452 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/KnowledgeTagMapper.java @@ -0,0 +1,10 @@ +package com.kb.knowledgebase.modules.knowledge.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.kb.knowledgebase.entity.knowledge.KnowledgeTag; +import org.springframework.stereotype.Repository; + +@Repository +public interface KnowledgeTagMapper extends BaseMapper { + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/ResourceMapper.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/ResourceMapper.java new file mode 100644 index 0000000..bf6b04c --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/ResourceMapper.java @@ -0,0 +1,20 @@ +package com.kb.knowledgebase.modules.knowledge.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.kb.knowledgebase.entity.knowledge.Resource; +import com.kb.knowledgebase.entity.knowledge.StatisticsResult; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface ResourceMapper extends BaseMapper { + + /** + * 来源管理-来源查询 + * + * @param resourceName 来源名称 + * @return 结果集 + */ + List selectResourceList(String resourceName); +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/SearchHistoryMapper.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/SearchHistoryMapper.java new file mode 100644 index 0000000..b0ef677 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/SearchHistoryMapper.java @@ -0,0 +1,12 @@ +package com.kb.knowledgebase.modules.knowledge.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.kb.knowledgebase.entity.knowledge.SearchHistory; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +@Repository +public interface SearchHistoryMapper extends BaseMapper { + String searchHotWords(@Param("userId") String userId); + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/StatisticsMapper.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/StatisticsMapper.java new file mode 100644 index 0000000..d4b280c --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/StatisticsMapper.java @@ -0,0 +1,39 @@ +package com.kb.knowledgebase.modules.knowledge.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.kb.knowledgebase.entity.knowledge.StatisticsResult; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; + +@Repository +public interface StatisticsMapper extends BaseMapper { + Map queryTypeStatistics(); + + Map queryResourceStatistics(); + + /** + * 部门知识概览 + * + * @param deptId 部门id + * @return 统计结果 + */ + Map deptKnowledgeStatistics(String deptId); + + /** + * 部门知识概览 + * + * @param deptId 部门id + * @return 统计结果 + */ + List deptResourceStatistics(String deptId); + + /** + * 公开知识概览 + * + * @return 统计结果 + */ + Map pubKnowledgeStatistics(); + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/TagMapper.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/TagMapper.java new file mode 100644 index 0000000..990b156 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/mapper/TagMapper.java @@ -0,0 +1,20 @@ +package com.kb.knowledgebase.modules.knowledge.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.kb.knowledgebase.entity.knowledge.Tag; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface TagMapper extends BaseMapper { + + /** + * 标签管理-标签查询 + * + * @param tagName 类别名称 + * @return 结果集 + */ + List selectTagList(String tagName); + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IAttachmentService.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IAttachmentService.java new file mode 100644 index 0000000..b868355 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IAttachmentService.java @@ -0,0 +1,15 @@ +package com.kb.knowledgebase.modules.knowledge.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.kb.knowledgebase.entity.knowledge.Attachment; +import org.springframework.web.multipart.MultipartFile; + +public interface IAttachmentService extends IService { + + IPage queryAttachmentPage(Attachment attachment); + + Attachment addAttachment(MultipartFile file); + + void deleteAttachment(Attachment attachment); +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/ICategoryService.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/ICategoryService.java new file mode 100644 index 0000000..6fce6a0 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/ICategoryService.java @@ -0,0 +1,67 @@ +package com.kb.knowledgebase.modules.knowledge.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.kb.knowledgebase.entity.knowledge.Category; +import com.kb.knowledgebase.entity.knowledge.StatisticsCategoryResult; +import com.kb.knowledgebase.entity.knowledge.StatisticsResult; + +import java.util.List; + +public interface ICategoryService extends IService { + /** + * 知识类别设置-查询 + * + * @param category 分类查询条件 + * @return 结果集 + */ + List selectCategoryList(Category category); + + /** + * 知识类别设置-创建分类 + * + * @param category 分类 + */ + void addCategory(Category category); + + /** + * 知识类别设置-编辑分类 + * + * @param category 分类 + */ + void updateCategory(Category category); + + /** + * 知识类别设置-删除分类 + * + * @param category 分类 + */ + void deleteCategory(Category category); + + /** + * 知识概览-知识大类统计 + * @return 结果集(一级分类名称,知识数量) + */ + List selectOneLevelStatistics(); + + /** + * 获取子级ID(包含自ID) + * @param pid 父id + * @return 结果集 + */ + List selectCategoryListByPid(Long pid); + + /** + * 知识查询-分类树 + * @param categoryType 分类类别 0:本部门 1:公开部门 + * @return 结果集 + */ + List selectKnowledgeCategoryList(Integer categoryType); + + /** + * 知识统计-分类统计 + * + * @param baseId 分类查询条件 + * @return 结果集 + */ + StatisticsCategoryResult selectCategoryStatistics(Long baseId); +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeBaseService.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeBaseService.java new file mode 100644 index 0000000..0e36733 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeBaseService.java @@ -0,0 +1,49 @@ +package com.kb.knowledgebase.modules.knowledge.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.kb.knowledgebase.entity.knowledge.KnowledgeBase; +import com.kb.knowledgebase.entity.knowledge.StatisticsKnowledgeResult; + +import java.util.List; + +public interface IKnowledgeBaseService extends IService { + /** + * 主题库-查询 + * + * @return 结果集 + */ + List selectKnowledgeBaseList(); + + /** + * 主题库-添加 + * + * @param knowledgeBase 主题库信息 + */ + void addKnowledgeBase(KnowledgeBase knowledgeBase); + + /** + * 主题库-更新 + * + * @param knowledgeBase 主题库信息 + */ + void updateKnowledgeBase(KnowledgeBase knowledgeBase); + + /** + * 主题库-删除 + * + * @param id 主题库id + */ + void deleteKnowledgeBase(Long id); + + /** + * 部门知识统计 + * + */ + StatisticsKnowledgeResult deptKnowledgeStatistics(); + + /** + * 公开知识统计 + * + */ + StatisticsKnowledgeResult pubDeptKnowledgeStatistics(); +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeCollectionService.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeCollectionService.java new file mode 100644 index 0000000..15f1992 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeCollectionService.java @@ -0,0 +1,34 @@ +package com.kb.knowledgebase.modules.knowledge.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.kb.knowledgebase.entity.knowledge.Knowledge; +import com.kb.knowledgebase.entity.knowledge.KnowledgeCollection; +import com.kb.knowledgebase.entity.knowledge.KnowledgeVo; + +import java.util.List; + +public interface IKnowledgeCollectionService extends IService { + /** + * 我的-我的收藏-查询 + * + * @param knowledge 收藏 + * @return 结果集 + */ + IPage selectKnowledgeCollection(KnowledgeVo knowledge); + + /** + * 我的-我的收藏-取消收藏 + * + * @param id 收藏id + */ + void cancelKnowledgeCollection(Long id); + + /** + * 我的-我的收藏-增加收藏 + * + * @param kid 知识id + */ + void addKnowledgeCollection(Long kid); + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeCommentService.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeCommentService.java new file mode 100644 index 0000000..2b3f817 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeCommentService.java @@ -0,0 +1,34 @@ +package com.kb.knowledgebase.modules.knowledge.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.kb.knowledgebase.entity.knowledge.KnowledgeComment; + +import java.util.List; + +public interface IKnowledgeCommentService extends IService { + /** + * 我的-我的评论-初期查询 + * + * @param userId 用户id + * @return 结果集 + */ + List selectKnowledgeComment(String userId); + + /** + * 我的-我的评论-编辑 + * + * @param id 评论ID + * @param comment 评论内容 + * + */ + void updateKnowledgeComment(Long id, String comment); + + /** + * 我的-我的评论-删除 + * + * @param id 评论ID + * + */ + void deleteKnowledgeComment(Long id); + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeResourceService.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeResourceService.java new file mode 100644 index 0000000..3cd74d3 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeResourceService.java @@ -0,0 +1,22 @@ +package com.kb.knowledgebase.modules.knowledge.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.kb.knowledgebase.entity.knowledge.KnowledgeResource; + +public interface IKnowledgeResourceService extends IService { + /** + * 查询知识和来源关联 + * + * @param resourceId 来源id + * + */ + Long selectKnowledgeResourceCount(Long resourceId); + + /** + * 删除知识和来源关联 + * + * @param resourceId 来源id + * + */ + void deleteKnowledgeResource(Long resourceId); +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeService.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeService.java new file mode 100644 index 0000000..b440c35 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeService.java @@ -0,0 +1,62 @@ +package com.kb.knowledgebase.modules.knowledge.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.kb.knowledgebase.entity.knowledge.Knowledge; +import com.kb.knowledgebase.entity.knowledge.KnowledgeVo; +import org.springframework.data.redis.core.ZSetOperations; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public interface IKnowledgeService extends IService { + + Long queryKnowledgePage(KnowledgeVo knowledge,List knowledges); + + void changeCollection(Long knowledgeId, List users); + + void changeCategoryId(Long sourceCategoryId, Long destCategoryId,Long baseId); + + /* + 知识转移接口 + 1.单独knowledgeId转移 (更新数据库 更新es文档) xxxx没有这个希求 + 2.分类转移 , 知识全部修改id(更新数据库 更新es文档) xxxx只修改上级分类也不用写,修改自己的分类才需要写 + 3.修改库 数据更改baseId (更新数据库 es索引值转移) 目前做这个就够了 + */ + void transDocumentByBaseId(Long baseId, int isPublic,String deptId); + + + + Long queryCollectionKnowledgePage(KnowledgeVo knowledge, List knowledges); + + IPage queryKnowledgePageByBaseId(KnowledgeVo knowledge); + + Knowledge getKnowledgeDetail(Knowledge knowledge); + + void publishKnowledge(Knowledge knowledge); + + void transferKnowledge(Knowledge knowledge); + + void addKnowledge(Knowledge knowledge); + void updateKnowledge(Knowledge knowledge); + void deleteKnowledge(Knowledge knowledge); + + List newKnowledgeRanking(); + List hotKnowledgeRanking(); + + List recommend(); + + Map uploadKnowledge(MultipartFile file); + + Set> getkeywordsRanking(); + + + void createIndex(String deptId); + + + + void fileDownload(String filePath, HttpServletResponse response); +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeTagService.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeTagService.java new file mode 100644 index 0000000..613220a --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IKnowledgeTagService.java @@ -0,0 +1,22 @@ +package com.kb.knowledgebase.modules.knowledge.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.kb.knowledgebase.entity.knowledge.KnowledgeTag; + +public interface IKnowledgeTagService extends IService { + /** + * 查询知识和标签关联 + * + * @param tagId 标签id + * + */ + Long selectKnowledgeTagCount(Long tagId); + + /** + * 删除知识和标签关联 + * + * @param tagId 标签id + * + */ + void deleteKnowledgeTag(Long tagId); +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IResourceService.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IResourceService.java new file mode 100644 index 0000000..9d11951 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IResourceService.java @@ -0,0 +1,33 @@ +package com.kb.knowledgebase.modules.knowledge.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.kb.knowledgebase.entity.knowledge.Resource; +import com.kb.knowledgebase.entity.knowledge.StatisticsResult; +import com.kb.knowledgebase.entity.knowledge.Tag; + +import java.util.List; + +public interface IResourceService extends IService { + /** + * 来源管理-来源查询 + * + * @param resourceName 来源名称 + * @return 结果集 + */ + List selectResourceList(String resourceName); + + /** + * 来源管理-来源标签 + * + * @param resource 来源信息 + */ + void addResource(Resource resource); + + /** + * 来源管理-删除来源 + * + * @param id 来源id + */ + void deleteResource(Long id); + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/ISearchHistoryService.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/ISearchHistoryService.java new file mode 100644 index 0000000..faeab91 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/ISearchHistoryService.java @@ -0,0 +1,11 @@ +package com.kb.knowledgebase.modules.knowledge.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.kb.knowledgebase.authority.UserInfo; +import com.kb.knowledgebase.entity.knowledge.SearchHistory; + +public interface ISearchHistoryService extends IService { + void insertHistory(UserInfo userInfo, String keyword); + + String searchHotWords(); +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IStatisticsService.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IStatisticsService.java new file mode 100644 index 0000000..42cd011 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/IStatisticsService.java @@ -0,0 +1,32 @@ +package com.kb.knowledgebase.modules.knowledge.service; + +import com.kb.knowledgebase.entity.knowledge.StatisticsResult; + +import java.util.List; +import java.util.Map; + + + +public interface IStatisticsService { + + + List queryTypeStatistics(); + List queryResourceStatistics(); + List queryCategoryStatistics(); + + Map queryBaseCount(Integer isPublic); + + /*部门知识概览*/ + List deptKnowledgeStatistics(); + + /*部门主题库概览*/ + List deptBaseStatistics(); + + /*部门知识来源概览*/ + List deptResourceStatistics(); + + /*公开知识概览*/ + List pubKnowledgeStatistics(); + + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/ITagService.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/ITagService.java new file mode 100644 index 0000000..20709aa --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/ITagService.java @@ -0,0 +1,31 @@ +package com.kb.knowledgebase.modules.knowledge.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.kb.knowledgebase.entity.knowledge.Tag; + +import java.util.List; + +public interface ITagService extends IService { + /** + * 标签管理-标签查询 + * + * @param tagName 类别名称 + * @return 结果集 + */ + List selectTagList(String tagName); + + /** + * 标签管理-添加标签 + * + * @param tag 标签信息 + */ + void addTag(Tag tag); + + /** + * 标签管理-删除标签 + * + * @param id 标签id + */ + void deleteTag(Long id); + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/AttachmentServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/AttachmentServiceImpl.java new file mode 100644 index 0000000..559d04d --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/AttachmentServiceImpl.java @@ -0,0 +1,68 @@ +package com.kb.knowledgebase.modules.knowledge.service.impl; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.kb.knowledgebase.entity.knowledge.Attachment; +import com.kb.knowledgebase.modules.knowledge.mapper.AttachmentMapper; +import com.kb.knowledgebase.modules.knowledge.service.IAttachmentService; +import com.kb.knowledgebase.modules.util.CommonDateUtil; +import com.kb.knowledgebase.modules.util.MinioUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.UUID; + +@Service +@Slf4j +public class AttachmentServiceImpl extends ServiceImpl implements IAttachmentService { + + @Autowired + private MinioUtil minioUtil; + + @Override + public IPage queryAttachmentPage(Attachment attachment) { + + Page page = new Page<>(attachment.getCurrentPage(), attachment.getPageSize()); + return baseMapper.queryAttachmentPage(page, attachment); + } + + @Override + @Transactional + public Attachment addAttachment(MultipartFile file) { + String dataUrl = ""; + //FileNameUtil.getName(); //文件全名 + String fileName = file.getOriginalFilename(); + String objectName = new SimpleDateFormat("yyyy/MM/dd/").format(new Date()) + + fileName.substring(0, fileName.indexOf('.') - 1) + + "-" + UUID.randomUUID().toString().replaceAll("-", "") + + fileName.substring(fileName.lastIndexOf(".")); + String contentType = file.getContentType(); + + //minio上传文件 前端使用form-data上传 key是file + minioUtil.uploadFile("knowledge",file,objectName,contentType); + //生成外链给前端用 + dataUrl = minioUtil.getPresignedObjectUrl("knowledge", objectName); + //attachment这里没有路径 + Long time = CommonDateUtil.getSystemTime(); + Attachment attachment = Attachment.builder() + .createTime(time) + .createById("xxx") + .attachmentName(fileName) + .attachmentPath(dataUrl) + .build(); + baseMapper.insert(attachment); + + return attachment; + } + + @Override + public void deleteAttachment(Attachment attachment) { +// minioUtil.removeFiles("knowledge"); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/CategoryServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/CategoryServiceImpl.java new file mode 100644 index 0000000..60f53bc --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/CategoryServiceImpl.java @@ -0,0 +1,382 @@ +package com.kb.knowledgebase.modules.knowledge.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.kb.knowledgebase.authority.ThreadLocalUtil; +import com.kb.knowledgebase.authority.UserInfo; +import com.kb.knowledgebase.entity.knowledge.Category; +import com.kb.knowledgebase.entity.knowledge.StatisticsResult; +import com.kb.knowledgebase.entity.knowledge.*; +import com.kb.knowledgebase.modules.knowledge.constant.CategoryConstants; +import com.kb.knowledgebase.modules.knowledge.constant.KbBaseConstants; +import com.kb.knowledgebase.modules.knowledge.constant.KnowledgeConstants; +import com.kb.knowledgebase.modules.knowledge.mapper.CategoryMapper; +import com.kb.knowledgebase.modules.knowledge.mapper.KnowledgeBaseMapper; +import com.kb.knowledgebase.modules.knowledge.mapper.KnowledgeMapper; +import com.kb.knowledgebase.modules.knowledge.service.ICategoryService; +import com.kb.knowledgebase.modules.util.CommonDateUtil; +import com.mysql.jdbc.StringUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class CategoryServiceImpl extends ServiceImpl implements ICategoryService { + + @Autowired + private KnowledgeMapper knowledgeMapper; + + @Autowired + private KnowledgeBaseMapper knowledgeBaseMapper; + + /** + * 知识类别设置-查询 + * + * @param category 分类查询条件 + * @return 结果集 + */ + @Override + public List selectCategoryList(Category category) { + List categoryList; + if (StringUtils.isNullOrEmpty(category.getCategoryName())) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Category::getBaseId, category.getBaseId()); + categoryList = baseMapper.selectList(queryWrapper); + } else { + categoryList = baseMapper.selectCategoryList(category); + } + + return categoryList.stream().filter(t -> t.getPid() == CategoryConstants.ROOT_PID).map( + m -> { + m.setChildrenList(getChildren(m, categoryList, CategoryConstants.BASE_TOTAL)); + return m; + } + ).collect(Collectors.toList()); + } + + /** + * 知识类别设置-创建分类 + * + * @param category 分类 + */ + @Override + @Transactional + public void addCategory(Category category) { + // 用户ID + String userId = ThreadLocalUtil.getUserInfo().getId(); + // 获取系统时间戳 + Long time = CommonDateUtil.getSystemTime(); + + // 创建时间 + category.setCreateTime(time); + // 更新时间 + category.setUpdateTime(time); + // 创建id + category.setCreateById(userId); + // 更新id + category.setUpdateById(userId); + // 分类串 + if (category.getPid() == CategoryConstants.ROOT_PID) { + category.setCategoryFullName(category.getCategoryName()); + } else { + category.setCategoryFullName(baseMapper.selectById(category.getPid()).getCategoryFullName() + .concat(CategoryConstants.CATEGORY_FULL_NAME_SEPARATOR).concat(category.getCategoryName())); + } + + baseMapper.insert(category); + + // 更新主题库分数类 + updateCategoryCount(category.getBaseId()); + + } + + + /** + * 知识类别设置-编辑分类 + * + * @param category 分类 + */ + @Override + @Transactional + public void updateCategory(Category category) { + // 获取系统时间戳 + Long time = CommonDateUtil.getSystemTime(); + + // 更新内容 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + // id + updateWrapper.eq(Category::getId, category.getId()); + // 父级id + updateWrapper.set(Category::getPid, category.getPid()); + // 分类名字 + updateWrapper.set(Category::getCategoryName, category.getCategoryName()); + // 更新时间 + updateWrapper.set(Category::getUpdateTime, time); + // 更新id + updateWrapper.set(Category::getUpdateById, ThreadLocalUtil.getUserInfo().getId()); + // 分类串 + if (category.getPid() == CategoryConstants.ROOT_PID) { + updateWrapper.set(Category::getCategoryFullName, category.getCategoryName()); + } else { + updateWrapper.set(Category::getCategoryFullName, baseMapper.selectById(category.getPid()).getCategoryFullName() + .concat(CategoryConstants.CATEGORY_FULL_NAME_SEPARATOR).concat(category.getCategoryName())); + } + baseMapper.update(updateWrapper); + + // 更新子节点 + List categoryList = baseMapper.selectCategoryListByPid(category.getId()); + categoryList.forEach(getCategory -> { + categoryList.stream().filter(t -> Objects.equals(t.getPid(), getCategory.getId())).map( + m -> { + m.setCategoryFullName(getCategory.getCategoryFullName().concat(CategoryConstants.CATEGORY_FULL_NAME_SEPARATOR).concat(m.getCategoryName())); + return m; + } + ).collect(Collectors.toList()); + }); + + this.updateBatchById(categoryList); + + } + + /** + * 知识类别设置-删除分类 + * + * @param category 分类 + */ + @Override + @Transactional + public void deleteCategory(Category category) { + Category oldCategory = baseMapper.selectById(category.getId()); + + // 分类的知识数量大于0,更新到新分类 + if (oldCategory.getKbCount() > 0) { + UserInfo userInfo = ThreadLocalUtil.getUserInfo(); + Long time = CommonDateUtil.getSystemTime(); + // 知识-更新条件 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + // 分类id + updateWrapper.eq(Knowledge::getCategoryId, category.getId()); + + // 知识-更新内容 + // 分类id + updateWrapper.set(Knowledge::getCategoryId, category.getPid()); + // 更新时间 + updateWrapper.set(Knowledge::getUpdateTime, time); + // 更新id + updateWrapper.set(Knowledge::getUpdateById, userInfo.getId()); + // 更新者姓名 + updateWrapper.set(Knowledge::getUpdateByName, userInfo.getUsername()); + + knowledgeMapper.update(updateWrapper); + } + // 删除分类 + baseMapper.deleteById(category); + + // 更新主题库分数类 + updateCategoryCount(oldCategory.getBaseId()); + } + + /** + * 知识概览-知识大类统计 + * + * @return 结果集(一级分类名称, 知识数量) + */ + @Override + public List selectOneLevelStatistics() { + return baseMapper.selectOneLevelStatistics(); + } + + /** + * 获取子级ID(包含自ID) + * + * @param pid 父id + * @return 结果集 + */ + @Override + public List selectCategoryListByPid(Long pid) { + List categoryList = baseMapper.selectCategoryListByPid(pid); + + return categoryList.stream().filter(t -> Objects.equals(t.getId(), pid)).map( + m -> { + m.setChildrenList(getChildren(m, categoryList, CategoryConstants.BASE_TOTAL)); + return m; + } + ).collect(Collectors.toList()); + } + + /** + * 知识查询-分类树 + * + * @param categoryType 分类类别 0:本部门 1:公开部门 + * @return 结果集 + */ + @Override + public List selectKnowledgeCategoryList(Integer categoryType) { + // 根节点 + Category category = new Category(); + category.setId(CategoryConstants.ROOT_ID_ALL); + category.setCategoryName(CategoryConstants.ROOT_NAME_ALL); + category.setChildrenList(getBaseCategoryList(categoryType)); + + List list = new ArrayList<>(); + list.add(category); + return list; + } + + /** + * 知识统计-分类统计 + * + * @param baseId 分类查询条件 + * @return 结果集 + */ + @Override + public StatisticsCategoryResult selectCategoryStatistics(Long baseId) { + List categoryList; + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Category::getBaseId, baseId); + categoryList = baseMapper.selectList(queryWrapper); + + // 合计 + long total = categoryList.stream().mapToLong(Category::getKbCount).sum(); + DecimalFormat df = new DecimalFormat(CategoryConstants.FORMAT_DECIMAL); + + return new StatisticsCategoryResult(total, categoryList.stream() + .filter(t -> t.getPid() == CategoryConstants.ROOT_PID).map( + m -> { + // 占比 + if (total != CategoryConstants.BASE_TOTAL) { + m.setProportion(df.format(((double)m.getKbCount() / total) * 100)); + } else { + m.setProportion(CategoryConstants.DEFAULT_PROPORTION); + } + // 子节点 + m.setChildrenList(getChildren(m, categoryList, total)); + return m; + } + ).collect(Collectors.toList())); + } + + /** + * 构造树形菜单 + * + * @param category 根节点 + * @param list 所有节点 + * @return 根节点信息 + */ + private List getChildren(Category category, List list, long total) { + DecimalFormat df = new DecimalFormat(CategoryConstants.FORMAT_DECIMAL); + return list.stream().filter(t -> { + return Objects.equals(t.getPid(), category.getId()); + }).map( + m -> { + if (total != CategoryConstants.BASE_TOTAL) { + m.setProportion(df.format((m.getKbCount() * 100L) / total)); + } else { + m.setProportion(CategoryConstants.FORMAT_DECIMAL); + } + m.setChildrenList(getChildren(m, list, total)); + return m; + } + ).collect(Collectors.toList()); + } + + /** + * 更新子节点分类串(暂时废除) + * + * @param fullName 父分类串 + * @param category 根节点 + * @param list 所有节点 + * @return 节点信息 + */ + private List updateChildren(String fullName, List list, Category category) { + return list.stream().filter(t -> { + return Objects.equals(t.getPid(), category.getId()); + }).map( + m -> { + String newFullname = fullName.concat(CategoryConstants.CATEGORY_FULL_NAME_SEPARATOR).concat(m.getCategoryName()); + m.setCategoryFullName(newFullname); + updateChildren(newFullname, list, m); + return m; + } + ).collect(Collectors.toList()); + } + + /** + * 获取主题库分类树 + * + * @param categoryType 分类类别 0:本部门 1:公开部门 + * @return 结果集 + */ + private List getBaseCategoryList(Integer categoryType) { + // 主题库list + List kBaseresultList = new ArrayList<>(); + + // 查找主题库list + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + // 本部门分类 + if (Objects.equals(categoryType, CategoryConstants.OWN_DEPT)) { + queryWrapper.eq(KnowledgeBase::getDeptId, ThreadLocalUtil.getUserInfo().getDeptId()); + + // 公开分类 + } else if (Objects.equals(categoryType, CategoryConstants.PUB_DEPT)) { + queryWrapper.eq(KnowledgeBase::getIsPublic, KbBaseConstants.IS_PUBLIC_PUB); + // 不包含本部门 +// queryWrapper.ne(KnowledgeBase::getDeptId, ThreadLocalUtil.getUserInfo().getDeptId()); + } + List knowledgeBaseList = knowledgeBaseMapper.selectList(queryWrapper); + + // 查找分类 + knowledgeBaseList.forEach(knowledgeBase -> { + // 主题 + Category kBaseCategory = new Category(); + kBaseCategory.setId(knowledgeBase.getId()); + if (Objects.equals(categoryType, CategoryConstants.PUB_DEPT)) { + kBaseCategory.setCategoryName(knowledgeBase.getDeptName().concat("-").concat(knowledgeBase.getBaseName())); + } else { + kBaseCategory.setCategoryName(knowledgeBase.getBaseName()); + } + + LambdaQueryWrapper categoryQueryWrapper = new LambdaQueryWrapper<>(); + categoryQueryWrapper.eq(Category::getBaseId, knowledgeBase.getId()); + List categoryList = baseMapper.selectList(categoryQueryWrapper); + List resultList = categoryList.stream().filter(t -> t.getPid() == CategoryConstants.ROOT_PID).map( + m -> { + m.setChildrenList(getChildren(m, categoryList, CategoryConstants.BASE_TOTAL)); + return m; + } + ).collect(Collectors.toList()); + + kBaseCategory.setChildrenList(resultList); + kBaseresultList.add(kBaseCategory); + }); + + return kBaseresultList; + } + + /** + * 更新主题库分类数 + * + * @param baseId 库Id + */ + private void updateCategoryCount(Long baseId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Category::getBaseId, baseId); + Long count = baseMapper.selectCount(queryWrapper); + + LambdaUpdateWrapper UpdateWrapper = new LambdaUpdateWrapper<>(); + UpdateWrapper.eq(KnowledgeBase::getId, baseId); + UpdateWrapper.set(KnowledgeBase::getCategoryCount, count); + knowledgeBaseMapper.update(UpdateWrapper); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeBaseServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeBaseServiceImpl.java new file mode 100644 index 0000000..7f23d11 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeBaseServiceImpl.java @@ -0,0 +1,163 @@ +package com.kb.knowledgebase.modules.knowledge.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.kb.knowledgebase.authority.ThreadLocalUtil; +import com.kb.knowledgebase.authority.UserInfo; +import com.kb.knowledgebase.entity.MyException; +import com.kb.knowledgebase.entity.ReturnCode; +import com.kb.knowledgebase.entity.knowledge.KnowledgeBase; +import com.kb.knowledgebase.entity.knowledge.StatisticsKnowledgeResult; +import com.kb.knowledgebase.modules.knowledge.constant.KbBaseConstants; +import com.kb.knowledgebase.modules.knowledge.constant.TagConstants; +import com.kb.knowledgebase.modules.knowledge.mapper.KnowledgeBaseMapper; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeBaseService; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeService; +import com.kb.knowledgebase.modules.util.CommonDateUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Slf4j +public class KnowledgeBaseServiceImpl extends ServiceImpl implements IKnowledgeBaseService { + + @Autowired + private IKnowledgeService iKnowledgeService; + + /** + * 主题库-查询 + * + * @return 结果集 + */ + @Override + public List selectKnowledgeBaseList() { + + return baseMapper.selectKnowledgeBaseList(ThreadLocalUtil.getUserInfo().getDeptId()); + } + + /** + * 主题库-添加 + * + * @param knowledgeBase 主题库信息 + */ + @Override + @Transactional + public void addKnowledgeBase(KnowledgeBase knowledgeBase) { + UserInfo userInfo = ThreadLocalUtil.getUserInfo(); + // 主题库名check + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(KnowledgeBase::getBaseName, knowledgeBase.getBaseName()); + lambdaQueryWrapper.eq(KnowledgeBase::getDeptId,userInfo.getDeptId()); + if (baseMapper.selectCount(lambdaQueryWrapper) != 0) { + throw new MyException(ReturnCode.CUSTOM_ERROR, KbBaseConstants.BASENAME_REPEAT_MSG); + } + + Long time = CommonDateUtil.getSystemTime(); + // 部门id + knowledgeBase.setDeptId(userInfo.getDeptId()); + // 部门名称 + knowledgeBase.setDeptName(userInfo.getDeptName()); + // 创建时间 + knowledgeBase.setCreateTime(time); + // 创建用户ID + knowledgeBase.setCreateById(userInfo.getId()); + // 创建用户名 + knowledgeBase.setCreateByName(userInfo.getUsername()); + // 更新时间 + knowledgeBase.setUpdateTime(time); + // 更新用户ID + knowledgeBase.setUpdateById(userInfo.getId()); + // 更新用户名 + knowledgeBase.setUpdateByName(userInfo.getUsername()); + // 知识数量 + knowledgeBase.setKnowledgeCount(0L); + // 类目数量 + knowledgeBase.setCategoryCount(0L); + baseMapper.insert(knowledgeBase); + + // 索引 + iKnowledgeService.createIndex(userInfo.getDeptId()); + } + + /** + * 主题库-更新 + * + * @param knowledgeBase 主题库信息 + */ + @Override + @Transactional + public void updateKnowledgeBase(KnowledgeBase knowledgeBase) { + // 获取原主题库信息 + KnowledgeBase oldKnowledgeBase = baseMapper.selectById(knowledgeBase.getId()); + + // 更新内容 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(KnowledgeBase::getId, knowledgeBase.getId()); + // 主题库名 + updateWrapper.set(KnowledgeBase::getBaseName, knowledgeBase.getBaseName()); + // 是否公开 + updateWrapper.set(KnowledgeBase::getIsPublic, knowledgeBase.getIsPublic()); + // 更新时间 + updateWrapper.set(KnowledgeBase::getUpdateTime, CommonDateUtil.getSystemTime()); + // 更新用户ID + updateWrapper.set(KnowledgeBase::getUpdateById, ThreadLocalUtil.getUserInfo().getId()); + // 更新用户名 + updateWrapper.set(KnowledgeBase::getUpdateByName, ThreadLocalUtil.getUserInfo().getUsername()); + baseMapper.update(updateWrapper); + + // 判断属性是否变更 + if (knowledgeBase.getIsPublic() != oldKnowledgeBase.getIsPublic()) { + // 知识转移 + iKnowledgeService.transDocumentByBaseId(knowledgeBase.getId(), knowledgeBase.getIsPublic(), oldKnowledgeBase.getDeptId()); + } + } + + /** + * 主题库-删除 + * + * @param id 主题库id + */ + @Override + @Transactional + public void deleteKnowledgeBase(Long id) { + // 判断该主题库ID下是否关联分类和知识 + KnowledgeBase knowledgeBase = baseMapper.selectById(id); + if (knowledgeBase != null + && (knowledgeBase.getKnowledgeCount() != 0 + || knowledgeBase.getCategoryCount() != 0)) { + throw new MyException(ReturnCode.CUSTOM_ERROR, KbBaseConstants.BASE_ASSOCIATION_MSG); + } + baseMapper.deleteById(id); + } + + /** + * 部门知识统计 + */ + @Override + public StatisticsKnowledgeResult deptKnowledgeStatistics() { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(KnowledgeBase::getDeptId, ThreadLocalUtil.getUserInfo().getDeptId()); + List list = baseMapper.selectList(queryWrapper); + + return new StatisticsKnowledgeResult(list.stream().mapToLong(KnowledgeBase::getKnowledgeCount).sum(), list); + } + + /** + * 公开知识统计 + */ + @Override + public StatisticsKnowledgeResult pubDeptKnowledgeStatistics() { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(KnowledgeBase::getIsPublic, KbBaseConstants.IS_PUBLIC_PUB); + // 不包含本部门 +// queryWrapper.ne(KnowledgeBase::getDeptId, ThreadLocalUtil.getUserInfo().getDeptId()); + List list = baseMapper.selectList(queryWrapper); + return new StatisticsKnowledgeResult(list.stream().mapToLong(KnowledgeBase::getKnowledgeCount).sum(), list); + } + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeCollectionServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeCollectionServiceImpl.java new file mode 100644 index 0000000..87522da --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeCollectionServiceImpl.java @@ -0,0 +1,152 @@ +package com.kb.knowledgebase.modules.knowledge.service.impl; + +import cn.hutool.core.map.MapUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.kb.knowledgebase.authority.ThreadLocalUtil; +import com.kb.knowledgebase.entity.knowledge.Knowledge; +import com.kb.knowledgebase.entity.knowledge.KnowledgeCollection; +import com.kb.knowledgebase.entity.knowledge.KnowledgeVo; +import com.kb.knowledgebase.modules.knowledge.constant.MineConstants; +import com.kb.knowledgebase.modules.knowledge.mapper.KnowledgeCollectionMapper; +import com.kb.knowledgebase.modules.knowledge.mapper.KnowledgeMapper; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeCollectionService; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeService; +import com.kb.knowledgebase.modules.util.CommonDateUtil; +import io.netty.util.internal.StringUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static cn.hutool.http.HtmlUtil.cleanHtmlTag; +import static cn.hutool.http.HtmlUtil.removeHtmlTag; + +@Service +@Slf4j +public class KnowledgeCollectionServiceImpl extends ServiceImpl implements IKnowledgeCollectionService { + + @Autowired + private KnowledgeMapper knowledgeMapper; + + @Autowired + private IKnowledgeService iKnowledgeService; + + /** + * 我的-我的收藏-查询 + * + * @param knowledge 收藏 + * @return 结果集 + */ + @Override + public IPage selectKnowledgeCollection(KnowledgeVo knowledge) { + Page page = new Page<>(knowledge.getCurrentPage(), knowledge.getPageSize()); + knowledge.setColletionUserId(ThreadLocalUtil.getUserInfo().getId()); + IPage list = baseMapper.selectKnowledgeCollection(page, knowledge); + + list.getRecords().stream().map(e -> { + if (!StringUtil.isNullOrEmpty(e.getContent())) { + String content = cleanHtmlTag(removeHtmlTag(e.getContent(), "style")); + e.setContent(content.substring(0, Math.min(content.length(), MineConstants.CONTENT_LENGTH))); + } + return e; + }).collect(Collectors.toList()); + + //新增来源字段 + if(list.getRecords() != null && list.getRecords().size() > 0){ + List collect = list.getRecords().stream().map(m -> m.getId()).collect(Collectors.toList()); + List> maps = baseMapper.queryResources(collect); + + Map resourceMap = maps.stream().collect(Collectors.toMap( + m -> MapUtil.getLong(m,"knowledge_id"), + m -> MapUtil.getStr(m,"resource") + )); + list.getRecords().forEach( + f -> f.setResource(MapUtil.getStr(resourceMap,f.getId())) + ); + } + + return list; + } + + /** + * 我的-我的收藏-取消收藏 + * + * @param id 知识id + */ + @Override + @Transactional + public void cancelKnowledgeCollection(Long id) { + // 更新知识收藏数量 + updateKnowledgeCollectionNum(id, false); + // 取消收藏 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(KnowledgeCollection::getKnowlegdeId, id); + queryWrapper.eq(KnowledgeCollection::getUserId, ThreadLocalUtil.getUserInfo().getId()); + baseMapper.delete(queryWrapper); + + // 更改收藏者列表 + iKnowledgeService.changeCollection(id, + baseMapper.selectCollectionUserList(id)); + } + + /** + * 我的-我的收藏-增加收藏 + * + * @param kid 知识id + */ + @Override + @Transactional + public void addKnowledgeCollection(Long kid) { + // 更新知识收藏数量 + updateKnowledgeCollectionNum(kid, true); + + // 增加收藏 + KnowledgeCollection knowledgeCollection = new KnowledgeCollection(); + // 知识id + knowledgeCollection.setKnowlegdeId(kid); + // 用户id + knowledgeCollection.setUserId(ThreadLocalUtil.getUserInfo().getId()); + // 创建时间 + knowledgeCollection.setCreateTime(CommonDateUtil.getSystemTime()); + baseMapper.insert(knowledgeCollection); + + // 更改收藏者列表 + iKnowledgeService.changeCollection(kid, baseMapper.selectCollectionUserList(kid)); + } + + /** + * 更新知识收藏数量 + * + * @param knowlegdeId 收藏id + * @param flg true:增加 false:减少 + */ + private void updateKnowledgeCollectionNum(Long knowlegdeId, boolean flg) { + // 获取系统时间戳 + Long time = CommonDateUtil.getSystemTime(); + // 更新知识收藏数量 + Knowledge knowledge = knowledgeMapper.selectById(knowlegdeId); + LambdaUpdateWrapper KnowledgeUpdate = new LambdaUpdateWrapper<>(); + KnowledgeUpdate.eq(Knowledge::getId, knowlegdeId); + if (flg) { + KnowledgeUpdate.set(Knowledge::getCollectionNum, knowledge.getCollectionNum() + 1); + } else { + KnowledgeUpdate.set(Knowledge::getCollectionNum, knowledge.getCollectionNum() - 1); + } + // 更新时间 + KnowledgeUpdate.set(Knowledge::getUpdateTime, time); + // 更新者id + KnowledgeUpdate.set(Knowledge::getUpdateById, ThreadLocalUtil.getUserInfo().getId()); + // 更新者姓名 + KnowledgeUpdate.set(Knowledge::getUpdateByName, ThreadLocalUtil.getUserInfo().getUsername()); + knowledgeMapper.update(KnowledgeUpdate); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeCommentServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeCommentServiceImpl.java new file mode 100644 index 0000000..c029637 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeCommentServiceImpl.java @@ -0,0 +1,64 @@ +package com.kb.knowledgebase.modules.knowledge.service.impl; + +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.kb.knowledgebase.entity.knowledge.KnowledgeComment; +import com.kb.knowledgebase.modules.knowledge.mapper.KnowledgeCommentMapper; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeCommentService; +import com.kb.knowledgebase.modules.util.CommonDateUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Slf4j +public class KnowledgeCommentServiceImpl extends ServiceImpl implements IKnowledgeCommentService { + + /** + * 我的-我的评论-初期查询 + * + * @param userId 用户id + * @return 结果集 + */ + @Override + public List selectKnowledgeComment(String userId) { + return baseMapper.selectKnowledgeComment(userId); + } + + /** + * 我的-我的评论-编辑 + * + * @param id 评论ID + * @param comment 评论内容 + * + */ + @Override + @Transactional + public void updateKnowledgeComment(Long id, String comment) { + Long time = CommonDateUtil.getSystemTime(); + // 评论-更新条件 + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + // 评论id + updateWrapper.eq("id", id); + + // 评论-更新内容 + // 评论内容 + updateWrapper.set("comment", comment); + // 更新时间 + updateWrapper.set("update_time", time); + baseMapper.update(updateWrapper); + } + + /** + * 我的-我的评论-删除 + * + * @param id 评论ID + */ + @Override + @Transactional + public void deleteKnowledgeComment(Long id) { + baseMapper.deleteById(id); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeResourceServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeResourceServiceImpl.java new file mode 100644 index 0000000..0fbaf1b --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeResourceServiceImpl.java @@ -0,0 +1,54 @@ +package com.kb.knowledgebase.modules.knowledge.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.kb.knowledgebase.authority.ThreadLocalUtil; +import com.kb.knowledgebase.authority.UserInfo; +import com.kb.knowledgebase.entity.MyException; +import com.kb.knowledgebase.entity.ReturnCode; +import com.kb.knowledgebase.entity.knowledge.KnowledgeResource; +import com.kb.knowledgebase.entity.knowledge.KnowledgeTag; +import com.kb.knowledgebase.entity.knowledge.Tag; +import com.kb.knowledgebase.modules.knowledge.mapper.KnowledgeResourceMapper; +import com.kb.knowledgebase.modules.knowledge.mapper.KnowledgeTagMapper; +import com.kb.knowledgebase.modules.knowledge.mapper.TagMapper; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeResourceService; +import com.kb.knowledgebase.modules.knowledge.service.ITagService; +import com.kb.knowledgebase.modules.util.CommonDateUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Slf4j +public class KnowledgeResourceServiceImpl extends ServiceImpl implements IKnowledgeResourceService { + + /** + * 查询知识和来源关联 + * + * @param resourceId 来源id + */ + @Override + public Long selectKnowledgeResourceCount(Long resourceId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(KnowledgeResource::getResourceId, resourceId); + return baseMapper.selectCount(lambdaQueryWrapper); + } + + /** + * 删除知识和来源关联 + * + * @param resourceId 来源id + */ + @Override + @Transactional + public void deleteKnowledgeResource(Long resourceId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(KnowledgeResource::getResourceId, resourceId); + baseMapper.delete(lambdaQueryWrapper); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeServiceImpl.java new file mode 100644 index 0000000..52caeda --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeServiceImpl.java @@ -0,0 +1,921 @@ +package com.kb.knowledgebase.modules.knowledge.service.impl; + +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.kb.knowledgebase.authority.ThreadLocalUtil; +import com.kb.knowledgebase.authority.UserInfo; +import com.kb.knowledgebase.entity.MyException; +import com.kb.knowledgebase.entity.knowledge.*; +import com.kb.knowledgebase.modules.common.CommonParam; +import com.kb.knowledgebase.modules.elasticsearch.impl.ElasticSearchServiceImpl; +import com.kb.knowledgebase.modules.knowledge.constant.KnowledgeConstants; +import com.kb.knowledgebase.modules.knowledge.mapper.KnowledgeMapper; +import com.kb.knowledgebase.modules.knowledge.service.ICategoryService; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeService; +import com.kb.knowledgebase.modules.knowledge.service.ISearchHistoryService; +import com.kb.knowledgebase.modules.util.CommonDateUtil; +import com.kb.knowledgebase.modules.util.FileConvertUtil; +import com.kb.knowledgebase.modules.util.MinioUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.core.ZSetOperations; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URLEncoder; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; + +import static cn.hutool.http.HtmlUtil.cleanHtmlTag; +import static cn.hutool.http.HtmlUtil.removeHtmlTag; + +@Service +@Slf4j +public class KnowledgeServiceImpl extends ServiceImpl implements IKnowledgeService { + + private String KB_BASEK_POST = "public"; + @Autowired + private ISearchHistoryService searchHisttoryService; + + @Value("${host.imgHost}") + private String localHost; + @Autowired + private MinioUtil minioUtil; + + @Autowired + private FileConvertUtil fileConvertUtil; + + int subLength = 200; + @Autowired + private ElasticSearchServiceImpl elasticSearchService; + + @Autowired + private ICategoryService categoryService; + + @Autowired + private StringRedisTemplate stringRedisTemplate; + + + @Override + public void changeCollection(Long knowledgeId, List users){ + //找到它的库然后根据ispublic查看更新私有库还是公开库 + String esIndex = queryDeptIdByKnowledgeId(knowledgeId); + elasticSearchService.changeCollection(knowledgeId,users,esIndex); + } + + /** + * 修改分类时批量修改es分类 + * @param sourceCategoryId + * @param destCategoryId + * @param baseId + */ + @Override + public void changeCategoryId(Long sourceCategoryId, Long destCategoryId, Long baseId) { + elasticSearchService.changeCategoryId( + sourceCategoryId, + destCategoryId, + queryDeptIdByBaseId(baseId) + ); + } + + + /** + * 库的公开属性改变的时候 库内知识需要转移 + * @param baseId 库id + * @param isPublic 是否要公开 + */ + @Override + public void transDocumentByBaseId(Long baseId, int isPublic,String deptId) { + String sourceIndex = ""; + String destIndex = ""; + if(isPublic == 1){ + sourceIndex = convertEsIndex(deptId); + destIndex = convertEsIndex(KB_BASEK_POST); + }else if(isPublic == 0){ + sourceIndex= convertEsIndex(KB_BASEK_POST); + destIndex = convertEsIndex(deptId); + } + elasticSearchService.transferDocumentByBaseId(baseId, sourceIndex, destIndex); + } + + @Override + public Long queryCollectionKnowledgePage(KnowledgeVo knowledgeVo, List knowledges) { + //查询收藏 + String userId = ThreadLocalUtil.getUserInfo().getId(); + knowledgeVo.setColletionUserId(userId); + String esIndex = convertEsIndex(ThreadLocalUtil.getUserInfo().getDeptId()); + + //判断有没有主题库 没有主题库就搞一个空传进去就不会搜索这个库了 + int baseCount = baseMapper.getBaseCount(ThreadLocalUtil.getUserInfo().getDeptId()); + if(baseCount == 0 ) esIndex = null; + + Long aLong = elasticSearchService.selectCollectionDocument(knowledges, knowledgeVo,esIndex); + if(aLong!= 0) { + //knowledges需要做处理 有一些指标没有 部门串,分类串, 查看数,收藏数 是否收藏 + List collect = knowledges.stream().map(m -> m.getId()).collect(Collectors.toList()); + List> stringObjectMap = baseMapper.queryAddtionalData(ThreadLocalUtil.getUserInfo().getId(), collect); + + Map> addtionalData = stringObjectMap.stream().collect(Collectors.toMap( + m -> (Long) m.get("id"), + m -> m + )); + knowledges.stream().forEach(k -> { + Long id = k.getId(); + Map stringObjectMap1 = addtionalData.get(id); + if (null != stringObjectMap1) { + k.setStrCategoryIds(MapUtil.getStr(stringObjectMap1, KnowledgeConstants.CATEGORY_FULL_NAME)); + k.setCollectionNum(MapUtil.getInt(stringObjectMap1, KnowledgeConstants.COLLECTION_NUM)); + k.setViewNum(MapUtil.getInt(stringObjectMap1, KnowledgeConstants.VIEW_NUM)); + k.setBaseName(MapUtil.getStr(stringObjectMap1, KnowledgeConstants.BASE_NAME)); + k.setIsCollection(MapUtil.getInt(stringObjectMap1, KnowledgeConstants.IS_COLLECTION)); + k.setResource(MapUtil.getStr(stringObjectMap1, KnowledgeConstants.RESOURCE)); + } + + }); + } + return aLong; + } + /** + * 查询知道带分页 + * @param knowledgeVo + * @param knowledges + * @return + */ + @Override + public Long queryKnowledgePage(KnowledgeVo knowledgeVo,List knowledges) { + + //判断有没有主题库 如果没有返回空 + int baseCount = baseMapper.getBaseCount(ThreadLocalUtil.getUserInfo().getDeptId()); + if(baseCount == 0 )return 0L; + + if(!StrUtil.isEmpty(knowledgeVo.getKeyword())) { + //查询的时候把关键词存数据库 + searchHisttoryService.insertHistory(ThreadLocalUtil.getUserInfo(),knowledgeVo.getKeyword()); + //把关键词存到redis做排行榜 + stringRedisTemplate.opsForZSet().incrementScore(CommonParam.KEYWORD_RANKING,knowledgeVo.getKeyword(),1); + + } + + String esIndex = knowledgeVo.getIsPublic() == 1 ? + convertEsIndex(null) + : + convertEsIndex(ThreadLocalUtil.getUserInfo().getDeptId()); + Long aLong = elasticSearchService.selectDocument(knowledges, knowledgeVo, esIndex, true); + //knowledges需要做处理 有一些指标没有 部门串,分类串, 查看数,收藏数 是否收藏 + List collect = knowledges.stream().map(m -> m.getId()).collect(Collectors.toList()); + + List> stringObjectMap = baseMapper.queryAddtionalData(ThreadLocalUtil.getUserInfo().getId(),collect); + Map> addtionalData = stringObjectMap.stream().collect(Collectors.toMap( + m -> (Long)m.get("id"), + m -> m, + (k,v) -> v + )); + + Iterator iterator = knowledges.iterator(); + while (iterator.hasNext()){ + Knowledge knowledge = iterator.next(); + Long id = knowledge.getId(); + Map stringObjectMap1 = addtionalData.get(id); + if(null != stringObjectMap1){ + knowledge.setStrCategoryIds(MapUtil.getStr(stringObjectMap1, KnowledgeConstants.CATEGORY_FULL_NAME)); + knowledge.setCollectionNum(MapUtil.getInt(stringObjectMap1, KnowledgeConstants.COLLECTION_NUM)); + knowledge.setViewNum(MapUtil.getInt(stringObjectMap1, KnowledgeConstants.VIEW_NUM)); + knowledge.setBaseName(MapUtil.getStr(stringObjectMap1, KnowledgeConstants.BASE_NAME)); + knowledge.setIsCollection(MapUtil.getInt(stringObjectMap1, KnowledgeConstants.IS_COLLECTION)); + knowledge.setResource(MapUtil.getStr(stringObjectMap1, KnowledgeConstants.RESOURCE)); + } + } + +// knowledges.stream().forEach( f -> { +// f.setTitle(""+f.getTitle() + ""); +// f.setContent(""+f.getContent() + ""); +// }); + + return aLong; + } + + + + @Override + public IPage queryKnowledgePageByBaseId(KnowledgeVo knowledge) { + + //从categoryid做出他及其以下的分类id + if(knowledge.getCategoryId() != null){ + List categoryList = categoryService.selectCategoryListByPid(knowledge.getCategoryId()); + List collect = categoryList.stream().map(m -> m.getId()).collect(Collectors.toList()); + knowledge.setCategoryIds(collect); + } + + Page page = new Page<>(knowledge.getCurrentPage(),knowledge.getPageSize()); + IPage knowledgeIPage = baseMapper.queryKnowledgePageByBaseId(page, knowledge); + + if(knowledgeIPage.getRecords() != null && knowledgeIPage.getRecords().size() > 0){ + List collect = knowledgeIPage.getRecords().stream().map(m -> m.getId()).collect(Collectors.toList()); + List> maps = baseMapper.queryResources(collect); + + Map resourceMap = maps.stream().collect(Collectors.toMap( + m -> MapUtil.getLong(m,"knowledge_id"), + m -> MapUtil.getStr(m,"resource") + )); + knowledgeIPage.getRecords().forEach( + f -> f.setResource( MapUtil.getStr(resourceMap,f.getId())) + ); + } + + + return knowledgeIPage; + } + + @Override + @Transactional + public Knowledge getKnowledgeDetail(Knowledge knowledge) { + //需要 title 主题库名字 分类串 来源 发布时间 浏览量 收藏量 正文 图片路径 + + Knowledge knowledgeDetail = baseMapper.getKnowledgeDetail(knowledge.getId(),ThreadLocalUtil.getUserInfo().getId()); + //拼一个图片数组 改为生成外链 + List imgPaths = selectKnowledgeImgPaths(knowledge); + if(imgPaths.size() > 0){ +// List collect = +// imgPaths.stream() +// .map(f -> minioHost + f ).collect(Collectors.toList()); + List collect = imgPaths.stream().map( f -> + minioUtil.getPresignedObjectUrl(CommonParam.BUCKET_NAME,f) + ).collect(Collectors.toList()); + + knowledgeDetail.setImgPaths(collect); + }else{ + knowledgeDetail.setImgPaths(new ArrayList<>()); + } + + //拼一个分类串 + //浏览量+1 + baseMapper.incrViewNum(knowledge.getId()); + + //标签 + List> maps = baseMapper.selectTagsById(knowledge.getId()); + List> maps1 = new ArrayList<>(); + maps.stream().forEach(m ->{ + Map objectObjectHashMap = new HashMap<>(); + objectObjectHashMap.put("id",MapUtil.getStr(m,"id")); + objectObjectHashMap.put("name",MapUtil.getStr(m,"name")); + maps1.add(objectObjectHashMap); + }); + knowledgeDetail.setTags(maps1); + + + //来源列表 + List> resourcesMaps = baseMapper.selectResourcesById(knowledge.getId()); + List> maps2 = new ArrayList<>(); + resourcesMaps.stream().forEach(m ->{ + Map objectObjectHashMap = new HashMap<>(); + objectObjectHashMap.put("id",MapUtil.getStr(m,"id")); + objectObjectHashMap.put("name",MapUtil.getStr(m,"name")); + maps2.add(objectObjectHashMap); + }); + knowledgeDetail.setResources(maps2); + + //文件名拼接host + String attachmentPath = knowledgeDetail.getAttachmentPath(); + if(StrUtil.isNotBlank(attachmentPath)){ + knowledgeDetail.setAttachmentPath( localHost + attachmentPath); + knowledgeDetail.setFileName(attachmentPath.substring(attachmentPath.lastIndexOf("/") + 1)); + } + //设置文件名字 + + return knowledgeDetail; + } + + @Override + @Transactional + public void publishKnowledge(Knowledge knowledge) { + if(knowledge.getIsPublish() != 1 && knowledge.getIsPublish() != 0) throw new MyException("参数不正确"); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper(); + lambdaUpdateWrapper.eq(Knowledge::getId,knowledge.getId()); + lambdaUpdateWrapper.set(Knowledge::getIsPublish ,knowledge.getIsPublish()); + baseMapper.update(lambdaUpdateWrapper); + + if(knowledge.getIsPublish() == 1) { + //上架es + Knowledge kbOne = baseMapper.selectById(knowledge.getId()); + String content = baseMapper.getContentById(knowledge.getId()); + kbOne.setContent(content); + String esIndex = this.queryDeptIdByBaseId(kbOne.getBaseId()); + addKnowledgeToEs(kbOne,esIndex); + }else{ + //下架es + String esIndex = queryDeptIdByKnowledgeId(knowledge.getId()); + elasticSearchService.deleteDocument(knowledge.getId(), esIndex); + } + } + + /** + * 转移知识 + * 需要获取 knowledgeid baseid categoryid 之后转移 + * 先查出知识详情 然后作对比 + * @param knowledge + */ + @Override + @Transactional + public void transferKnowledge(Knowledge knowledge) { + + UserInfo userInfo = ThreadLocalUtil.getUserInfo(); + Long time = CommonDateUtil.getSystemTime(); + knowledge.setUpdateTime(time); + knowledge.setUpdateById(userInfo.getId()); + knowledge.setUpdateByName(userInfo.getUsername()); + //数据库中数据 + Knowledge kbOne = baseMapper.selectById(knowledge.getId()); + String esSourceIndex = queryDeptIdByBaseId(kbOne.getBaseId()); + String esDestIndex = ""; + int change = 0; + LambdaUpdateWrapper knowledgeLambdaUpdateWrapper = new LambdaUpdateWrapper<>(); + knowledgeLambdaUpdateWrapper.eq(Knowledge::getId,knowledge.getId()); + //分类id不相等 只需要更新es 不需要转移索引 + if(null != knowledge.getCategoryId() && !kbOne.getCategoryId().equals(knowledge.getCategoryId())){ + knowledgeLambdaUpdateWrapper.set(Knowledge::getCategoryId,knowledge.getCategoryId()); + baseMapper.incrCategoryKbCount(knowledge.getCategoryId()); + baseMapper.decrCategoryKbCount(kbOne.getCategoryId()); + change++; + } + //库属性不相等 比如从公开转移到非公开 更新es数据之后要转移索引 + if(null != knowledge.getBaseId() && !kbOne.getBaseId().equals(knowledge.getBaseId())){ + knowledgeLambdaUpdateWrapper.set(Knowledge::getBaseId,knowledge.getBaseId()); + baseMapper.incrBaseKbCount(knowledge.getBaseId()); + baseMapper.decrBaseKbCount(kbOne.getBaseId()); + esDestIndex = queryDeptIdByBaseId( knowledge.getBaseId()); + change++; + } + if(change != 0){ + //更新es + if(kbOne.getIsPublish() == 1) elasticSearchService.updateDocument(knowledge, esSourceIndex); + //最后更新数据库 不然前面es找索引要找不到了 + baseMapper.update(knowledgeLambdaUpdateWrapper); // 更新库和分类 + //等两秒 + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + //两个库id不相等 则转移索引 + if(!esSourceIndex.equals(esDestIndex) && StrUtil.isNotEmpty(esDestIndex)){ + log.info("转移id为{}的知识,来源索引{},转移后的索引{}",knowledge.getId(),esSourceIndex,esDestIndex); + elasticSearchService.transferDocument(knowledge.getId(),esSourceIndex,esDestIndex); + } + } + + + + + /** + * 检查参数 + * @param knowledge + */ + public void checkParam(Knowledge knowledge){ + if(knowledge.getCategoryId() == null + || + knowledge.getBaseId() == null + || + StrUtil.isEmpty(knowledge.getTitle()) +// || +// StrUtil.isEmpty(knowledge.getResource()) + || + null == knowledge.getIsPublish() + ){ + throw new MyException("参数不全"); + } + } + /** + * 新增知识 + * @param knowledge + */ + @Override + @Transactional + public void addKnowledge(Knowledge knowledge) { + Knowledge.KnowledgeBuilder builder = Knowledge.builder(); + //TODO: 检查变参数 + checkParam(knowledge); + builder.isPublish(knowledge.getIsPublish()); + builder.title(knowledge.getTitle()); + builder.baseId(knowledge.getBaseId()); + builder.categoryId(knowledge.getCategoryId()); + builder.resource(knowledge.getResource()); + builder.content(knowledge.getContent()); + builder.attachmentType(knowledge.getAttachmentType()); + + Long time = CommonDateUtil.getSystemTime(); + builder.createTime(time) + .updateTime(time); + //用户信息存储 + UserInfo userInfo = ThreadLocalUtil.getUserInfo(); + builder.createById(userInfo.getId()) + .updateById(userInfo.getId()) + .createByName(userInfo.getUsername()) + .updateByName(userInfo.getUsername()); + + //发布时间 + if(null != knowledge.getPublishTime()){ + builder.publishTime(knowledge.getPublishTime()); + } + //实施时间 + if(null != knowledge.getImplementTime()){ + builder.implementTime(knowledge.getImplementTime()); + } + if(!StrUtil.isEmpty(knowledge.getAttachmentPath())){ + builder.attachmentPath(knowledge.getAttachmentPath()); + } + Knowledge buildKnowledge = builder.build(); + //TODO: 存储知识信息 + baseMapper.insert(buildKnowledge); +// knowledge.setId(insert); + //获取前subLength个字符作为摘要 + //String substring = cleanHtml.substring(0, Math.min(subLength, cleanHtml.length())); + //knowledge.setDescription(substring); + //标题 + 完整分类 + 发布人名称 + 发布部门名称 + 来源 + 标签 + 正文纯文本 + + + knowledge.setId(buildKnowledge.getId()); + //TODO: 存PDF文件转的图片路径 + if(null != knowledge.getImgPaths() && knowledge.getImgPaths().size() > 0){ + addKnowledgeImgPaths(knowledge); + } + //TODO: 存附件 + //addKnowledgeAttachments(knowledge); + //TODO: 存标签 + addKnowledgeTags(knowledge); + //TODO: 存内容 + addKnowledgeContent(knowledge); + //TODO: 存来源 + addKnowledgeResource(knowledge); + //TODO: 分类和库 知识量 +1 + //库内知识量+1 + baseMapper.incrBaseKbCount(buildKnowledge.getBaseId()); + //分类知识量+1 + baseMapper.incrCategoryKbCount(buildKnowledge.getCategoryId()); + //TODO: 存es 如果是发布状态是1 + //通过baseid获取到库信息deptid 之后才知道修改哪个库 + if(!StrUtil.isEmpty(buildKnowledge.getContent())){ + buildKnowledge.setContent(cleanHtmlTag(removeHtmlTag(buildKnowledge.getContent(), "style")));//去掉html标签 + } + //没有内容也要发布到es 因为可以查标题 + String esIndex = this.queryDeptIdByBaseId(knowledge.getBaseId()); + if(knowledge.getIsPublish() == 1) addKnowledgeToEs(knowledge,esIndex); + } + + /** + * 存数据到es 做了es类处理 避免多余字段存到es + * @param knowledge + * @param esIndex + */ + public void addKnowledgeToEs(Knowledge knowledge,String esIndex){ + KnowledgeEs.KnowledgeEsBuilder builder = KnowledgeEs.builder(); + builder.id(knowledge.getId()); + builder.title(knowledge.getTitle()); + builder.baseId(knowledge.getBaseId()); + builder.categoryId(knowledge.getCategoryId()); + builder.resource(knowledge.getResource()); + builder.deptId(ThreadLocalUtil.getUserInfo().getDeptId()); + if(!StrUtil.isEmpty(knowledge.getContent())) builder.content(cleanHtmlTag(removeHtmlTag(knowledge.getContent(), "style"))); + builder.attachmentType(knowledge.getAttachmentType()); + + Long time = CommonDateUtil.getSystemTime(); + builder.createTime(time) + .updateTime(time); + //用户信息存储 + UserInfo userInfo = ThreadLocalUtil.getUserInfo(); + builder.createById(userInfo.getId()) + .updateById(userInfo.getId()) + .createByName(userInfo.getUsername()) + .updateByName(userInfo.getUsername()); + + if(!StrUtil.isEmpty(knowledge.getAttachmentPath())){ + builder.attachmentPath(knowledge.getAttachmentPath()); + } + + if(null != knowledge.getResources() && knowledge.getResources().size() > 0){ + List ids = knowledge.getResources().stream().map(m -> MapUtil.getLong(m, "id")).collect(Collectors.toList()); + builder.resourcesList(ids); + } + KnowledgeEs buildKnowledge = builder.build(); + elasticSearchService.createDocument(buildKnowledge, esIndex); + } + @Override + @Transactional + public void updateKnowledge(Knowledge knowledge) { + Knowledge.KnowledgeBuilder builder = Knowledge.builder(); + //TODO: 检查变参数 + if(knowledge.getId() == null || knowledge.getIsPublish() == null){ + throw new MyException("参数不全"); + } + builder.id(knowledge.getId()); + builder.isPublish(knowledge.getIsPublish()); + builder.title(knowledge.getTitle()); + builder.categoryId(knowledge.getCategoryId()); + builder.resource(knowledge.getResource()); + builder.content(knowledge.getContent()); + builder.attachmentType(knowledge.getAttachmentType()); + + Long time = CommonDateUtil.getSystemTime(); + builder.updateTime(time); + //用户信息存储 + UserInfo userInfo = ThreadLocalUtil.getUserInfo(); + builder.updateById(userInfo.getId()) + .updateByName(userInfo.getUsername()); + + if(!StrUtil.isEmpty(knowledge.getAttachmentPath())){ + builder.attachmentPath(knowledge.getAttachmentPath()); + } + + if(null != knowledge.getResources() && knowledge.getResources().size() > 0){ + List ids = knowledge.getResources().stream().map(m -> MapUtil.getLong(m, "id")).collect(Collectors.toList()); + builder.resourcesList(ids); + } + + Knowledge buildKnowledge = builder.build(); + + Knowledge kbOne = baseMapper.selectById(knowledge.getId()); + int published = 1; + if(kbOne.getIsPublish() == 0) published = 0; + + baseMapper.updateById(buildKnowledge); + + //TODO: 存PDF文件转的图片路径 + if(null != knowledge.getImgPaths() && knowledge.getImgPaths().size() > 0) updateKnowledgeImgPaths(knowledge); + + //TODO: 存附件 + //addKnowledgeAttachments(knowledge); + //TODO: 存标签 + updateKnowledgeTags(knowledge); + //TODO: 存内容 + updateKnowledgeContent(knowledge); + //TODO: 存来源 + updateKnowledgeResource(knowledge); + //TODO: 存es 如果是发布状态是1 + + String esIndex = this.queryDeptIdByKnowledgeId(knowledge.getId()); + //TODO前端传过来发布状态是1 + if(knowledge.getIsPublish() == 1){ + if(published == 0){ + //新增到es + addKnowledgeToEs(knowledge,esIndex); + }else{ + //更新到es + elasticSearchService.updateDocument(buildKnowledge, esIndex); + } + } + + + } + + + + @Override + @Transactional + public void deleteKnowledge(Knowledge knowledge) { + + //删除先删除es 不然找不到deptid了 + String esIndex = this.queryDeptIdByKnowledgeId(knowledge.getId()); + elasticSearchService.deleteDocument(knowledge.getId(), esIndex); + + Knowledge kbOne = baseMapper.selectById(knowledge.getId()); + //库内知识量-1 + baseMapper.decrBaseKbCount(kbOne.getBaseId()); + //分类知识量-1 + baseMapper.decrCategoryKbCount(kbOne.getCategoryId()); + + baseMapper.deleteById(knowledge.getId()); + deleteKnowledgeContent(knowledge); + deleteKnowledgeTags(knowledge); + deleteKnowledgeImgPaths(knowledge); + + } + + @Override + public List newKnowledgeRanking() {return baseMapper.newKnowledgeRanking(10);} + + @Override + public List hotKnowledgeRanking() {return baseMapper.hotKnowledgeRanking(10);} + + @Override + public List recommend() { + //查询搜索前五的数据 搜索es 如果搜不到的话 + String s = searchHisttoryService.searchHotWords(); + List knowledgeList = new ArrayList<>(); + log.info("此人查询的前十的知识关键词是{}",s); + Long aLong = 0L; + if(!StrUtil.isEmpty(s)){ //关键词不为空查询关键词 + KnowledgeVo knowledgeVo = KnowledgeVo.builder() + .keyword(s) + .build(); + aLong = elasticSearchService.selectDocument(knowledgeList, knowledgeVo, convertEsIndex(KB_BASEK_POST),false); + } + if( aLong < 10 ){ //用热搜补全 + List collect = knowledgeList.stream().map(m -> m.getId()).collect(Collectors.toList()); + + List knowledges = baseMapper.hotKnowledgeRanking1(10 - aLong.intValue(),collect); + knowledgeList.addAll(knowledges); + } + return knowledgeList; + } + + + @Override + public Map uploadKnowledge(MultipartFile file) { + Map returnResult = new HashMap<>(); + String fileName = file.getOriginalFilename(); + //通过后缀判断文件类型 + String extension = fileName.substring(fileName.lastIndexOf(".") + 1); + returnResult.put("postfix",extension); + + + if(!"pdf".equalsIgnoreCase(extension) && !"doc".equalsIgnoreCase(extension) &&!"docx".equalsIgnoreCase(extension)){ + throw new MyException("文件格式不符合要求"); + } + String objectName = new SimpleDateFormat("yyyy/MM/dd/").format(new Date()) + + fileName.substring(0, fileName.lastIndexOf('.')) + + "-" + UUID.randomUUID().toString().replaceAll("-", "") + + fileName.substring(fileName.lastIndexOf(".")); + String contentType = file.getContentType(); + //minio上传文件 前端使用form-data上传 key是file + minioUtil.uploadFile(CommonParam.BUCKET_NAME,file,objectName,contentType); + //生成外链给前端用 +// String attachmentPath = "/" + CommonParam.BUCKET_NAME + "/" + objectName; + String attachmentPath = objectName; + returnResult.put("attachmentPath",attachmentPath); + log.info("上传到minio文件路径{}",attachmentPath); + if("pdf".equalsIgnoreCase(extension)){ //pdf转img 图片存minio和数据库中 不做ocr处理 + List imgPaths = fileConvertUtil.pdf2img(attachmentPath); // 得到图片路径 + //每个path拼上host前台才能显示 + returnResult.put("data",imgPaths); + returnResult.put("host",localHost); + } + else if("doc".equalsIgnoreCase(extension)){ // doc转html 内容存数据库 图片存minio + try { + String s = fileConvertUtil.doc2html(file); + returnResult.put("data",s); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + else if("docx".equalsIgnoreCase(extension)){ // docx转html 内容存数据库 图片存minio + try { + String s = fileConvertUtil.docx2html(attachmentPath); + returnResult.put("data",s); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + //如果是桶是public 可以直接访问 + //return "/" + CommonParam.BUCKET_NAME + "/" + objectName; + return returnResult; + } + + /** + * 关键词排行榜 + * + * @return + */ + @Override + public Set> getkeywordsRanking() { + //取分数最高前十名 + Set> typedTuples = stringRedisTemplate.opsForZSet().reverseRangeWithScores(CommonParam.KEYWORD_RANKING, 0, 9); + return typedTuples; + + + } + + /** + * 新增es索引 + * @param deptId + */ + @Override + public void createIndex(String deptId) { + elasticSearchService.createIndex(convertEsIndex(deptId)); + } + + @Override + public void fileDownload(String filePath, HttpServletResponse response) { + + InputStream inputStream = null; + OutputStream outputStream = null; + try { + if (StringUtils.isBlank(filePath)) { + response.setHeader("Content-type", "text/html;charset=UTF-8"); + String data = "文件下载失败"; + OutputStream ps = response.getOutputStream(); + ps.write(data.getBytes("UTF-8")); + return; + } + outputStream = response.getOutputStream(); + // 获取文件对象 + inputStream = minioUtil.getObject(CommonParam.BUCKET_NAME, filePath); + byte buf[] = new byte[1024]; + int length = 0; + response.reset(); + response.setHeader("Content-Disposition", "attachment;filename=" + + URLEncoder.encode(filePath.substring(filePath.lastIndexOf("/") + 1), "UTF-8")); + response.setContentType("application/octet-stream"); + response.setCharacterEncoding("UTF-8"); + // 输出文件 + while ((length = inputStream.read(buf)) > 0) { + outputStream.write(buf, 0, length); + } + log.info("下载成功"); + inputStream.close(); + } catch (Throwable ex) { + response.setHeader("Content-type", "text/html;charset=UTF-8"); + String data = "文件下载失败"; + try { + OutputStream ps = response.getOutputStream(); + ps.write(data.getBytes("UTF-8")); + } catch (IOException e) { + e.printStackTrace(); + } + } finally { + try { + outputStream.close(); + if (inputStream != null) { + inputStream.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + + + } + + + /** + * 增加知识的标签 + * @param knowledge + */ + public void addKnowledgeTags(Knowledge knowledge){ + //判断标签是 + if(null != knowledge.getTags() && knowledge.getTags().size() > 0){ + log.info("存储标签"); + List ids = knowledge.getTags().stream().map(m -> MapUtil.getLong(m, "id")).collect(Collectors.toList()); + baseMapper.addKnowledgeTags(ids,knowledge.getId()); + } + } + /** + * 更新知识的标签 + * @param knowledge + */ + @Transactional + public void updateKnowledgeTags(Knowledge knowledge){ + deleteKnowledgeTags(knowledge); + addKnowledgeTags(knowledge); + } + /** + * 删除知识的标签 + * @param knowledge + */ + public void deleteKnowledgeTags(Knowledge knowledge){ + baseMapper.deleteKnowledgeTags(knowledge.getId()); + } + + + public void addKnowledgeResource(Knowledge knowledge){ + if(null != knowledge.getResources() && knowledge.getResources().size() > 0) { + log.info("存储来源"); + List ids = knowledge.getResources().stream().map(m -> MapUtil.getLong(m, "id")).collect(Collectors.toList()); + baseMapper.addKnowledgeResource(ids, knowledge.getId()); + } + } + @Transactional + public void updateKnowledgeResource(Knowledge knowledge){ + deleteKnowledgeResource(knowledge); + addKnowledgeResource(knowledge); + } + public void deleteKnowledgeResource(Knowledge knowledge){ + baseMapper.deleteKnowledgeResource(knowledge.getId()); + } + + /** + * 增加知识的附件 + * @param knowledge + */ + public void addKnowledgeAttachments(Knowledge knowledge){ + //判断标签是 + if(null != knowledge.getAttachments() && knowledge.getAttachments().size() > 0){ + log.info("存储附件"); + List ids = knowledge.getAttachments().stream().map(m -> MapUtil.getInt(m, "attachmentId")).collect(Collectors.toList()); + baseMapper.addKnowledgeAttachments(ids,knowledge.getId()); + } + } + + /** + * 增加知识的内容 + * @param knowledge + */ + public void addKnowledgeContent(Knowledge knowledge){ + baseMapper.addKnowledgeContent(knowledge.getId(),knowledge.getContent()); + } + /** + * 更新知识的内容 + * @param knowledge + */ + public void updateKnowledgeContent(Knowledge knowledge){ + baseMapper.updateKnowledgeContent(knowledge.getId(),knowledge.getContent()); + } + /** + * 删除知识的内容 + * @param knowledge + */ + public void deleteKnowledgeContent(Knowledge knowledge){ + baseMapper.deleteKnowledgeContent(knowledge.getId()); + } + + /** + * 存pdf转的图片路径 + * @param knowledge + */ + public List selectKnowledgeImgPaths(Knowledge knowledge){ + return baseMapper.selectKnowledgeImgPaths(knowledge.getId()); + } + /** + * 存pdf转的图片路径 + * @param knowledge + */ + public void addKnowledgeImgPaths(Knowledge knowledge){ + baseMapper.addKnowledgeImgPaths(knowledge.getId(),knowledge.getImgPaths()); + } + /** + * 更新pdf转的图片路径 + * @param knowledge + */ + public void updateKnowledgeImgPaths(Knowledge knowledge){ + deleteKnowledgeImgPaths(knowledge); + addKnowledgeImgPaths(knowledge); + } + /** + * 删除pdf转的图片路径 + * @param knowledge + */ + public void deleteKnowledgeImgPaths(Knowledge knowledge){ + baseMapper.deleteKnowledgeImgPaths(knowledge.getId()); + } + + + + /** + * 通过knowledgeId寻找库中的deptid 从而知道es存到哪个库中 + * es的库名必须是小写 要toLowerCase + */ + public String queryDeptIdByKnowledgeId(Long knowledgeId){ + KnowledgeBase knowledgeBase = baseMapper.queryDeptIdByKnowledgeId(knowledgeId); + String esIndex = ""; + if(knowledgeBase.getIsPublic() == 1){ + //放公开库 + esIndex = KB_BASEK_POST; + }else{ + //获取deptid + esIndex = knowledgeBase.getDeptId(); + } + return convertEsIndex(esIndex); + } + /** + * 通过baseId寻找库中的deptid 从而知道es存到哪个库中 + * es的库名必须是小写 要toLowerCase + */ + public String queryDeptIdByBaseId(Long baseId){ + KnowledgeBase knowledgeBase = baseMapper.queryKnowledgeDeptId(baseId); + String esIndex = ""; + if(knowledgeBase.getIsPublic() == 1){ + //放公开库 + esIndex = KB_BASEK_POST; + }else{ + //获取deptid + esIndex = knowledgeBase.getDeptId(); + } + return convertEsIndex(esIndex); + } + /** + * 通过deptId获取知识库的索引 + * @param deptId + */ + public String convertEsIndex(String deptId){ + if(StrUtil.isEmpty(deptId)){ + deptId = KB_BASEK_POST; + }else{ + deptId = deptId.toLowerCase(); + } + return "knowledge-" + deptId; + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeTagServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeTagServiceImpl.java new file mode 100644 index 0000000..5d1b01e --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/KnowledgeTagServiceImpl.java @@ -0,0 +1,42 @@ +package com.kb.knowledgebase.modules.knowledge.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.kb.knowledgebase.entity.knowledge.KnowledgeResource; +import com.kb.knowledgebase.entity.knowledge.KnowledgeTag; +import com.kb.knowledgebase.modules.knowledge.mapper.KnowledgeResourceMapper; +import com.kb.knowledgebase.modules.knowledge.mapper.KnowledgeTagMapper; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeResourceService; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeTagService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Slf4j +public class KnowledgeTagServiceImpl extends ServiceImpl implements IKnowledgeTagService { + + /** + * 查询知识和标签关联 + * + * @param tagId 标签id + */ + @Override + public Long selectKnowledgeTagCount(Long tagId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(KnowledgeTag::getTagId, tagId); + return baseMapper.selectCount(lambdaQueryWrapper); + } + + /** + * 删除知识和标签关联 + * + * @param tagId 标签id + */ + @Override + public void deleteKnowledgeTag(Long tagId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(KnowledgeTag::getTagId, tagId); + baseMapper.delete(lambdaQueryWrapper); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/PdfToImageServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/PdfToImageServiceImpl.java new file mode 100644 index 0000000..ce063ab --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/PdfToImageServiceImpl.java @@ -0,0 +1,50 @@ +package com.kb.knowledgebase.modules.knowledge.service.impl; + +import com.kb.knowledgebase.modules.util.threadpool.ExecutorUtil; +import com.kb.knowledgebase.modules.util.threadpool.TaskPoolProperty; +import lombok.extern.slf4j.Slf4j; +import org.apache.pdfbox.Loader; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.rendering.PDFRenderer; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.concurrent.ThreadPoolExecutor; + +@Service +@Slf4j +public class PdfToImageServiceImpl { + + public File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException { + File file = new File(multipartFile.getOriginalFilename()); + multipartFile.transferTo(file); + return file; + } + + + /** + * PDF 转单张图片 + * + * @param pdfFile PDF文件 + * + */ + public void processPdfFile(MultipartFile pdfFile) { + ThreadPoolExecutor threadPoolExecutor = ExecutorUtil.getThreadPool(new TaskPoolProperty(),"ProcessPdfThread"); + threadPoolExecutor.execute(() -> { + // PDF转图片 + try { + PDDocument document = Loader.loadPDF(convertMultipartFileToFile(pdfFile)); + PDFRenderer renderer = new PDFRenderer(document); + BufferedImage image = renderer.renderImageWithDPI(0, 300); // 300 DPI + ImageIO.write(image, "PNG", new File("output.png")); + document.close(); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/ResourceServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/ResourceServiceImpl.java new file mode 100644 index 0000000..0b78091 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/ResourceServiceImpl.java @@ -0,0 +1,89 @@ +package com.kb.knowledgebase.modules.knowledge.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.kb.knowledgebase.authority.ThreadLocalUtil; +import com.kb.knowledgebase.authority.UserInfo; +import com.kb.knowledgebase.entity.MyException; +import com.kb.knowledgebase.entity.ReturnCode; +import com.kb.knowledgebase.entity.knowledge.Resource; +import com.kb.knowledgebase.modules.knowledge.constant.ResourceConstants; +import com.kb.knowledgebase.modules.knowledge.mapper.ResourceMapper; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeResourceService; +import com.kb.knowledgebase.modules.knowledge.service.IResourceService; +import com.kb.knowledgebase.modules.util.CommonDateUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Slf4j +public class ResourceServiceImpl extends ServiceImpl implements IResourceService { + + @Autowired + private IKnowledgeResourceService iKnowledgeResourceService; + + /** + * 来源管理-来源查询 + * + * @param resourceName 来源名称 + * @return 结果集 + */ + @Override + public List selectResourceList(String resourceName) { + return baseMapper.selectResourceList(resourceName); + } + + /** + * 来源管理-添加来源 + * + * @param resource 来源信息 + */ + @Override + @Transactional + public void addResource(Resource resource) { + // 来源重复Check + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(Resource::getResourceName, resource.getResourceName()); + if (baseMapper.exists(lambdaQueryWrapper)) { + throw new MyException(ReturnCode.CUSTOM_ERROR, ResourceConstants.RESOURCE_REPEAT_MSG); + } else { + UserInfo userInfo = ThreadLocalUtil.getUserInfo(); + // 获取系统时间戳 + Long time = CommonDateUtil.getSystemTime(); + // 创建时间 + resource.setCreateTime(time); + // 更新时间 + resource.setUpdateTime(time); + // 创建id + resource.setCreateById(userInfo.getId()); + // 创建者姓名 + resource.setCreateByName(userInfo.getUsername()); + // 更新id + resource.setUpdateById(userInfo.getId()); + // 更新者姓名 + resource.setUpdateByName(userInfo.getUsername()); + baseMapper.insert(resource); + } + } + + /** + * 来源管理-删除来源 + * + * @param id 来源id + */ + @Override + @Transactional + public void deleteResource(Long id) { + if (iKnowledgeResourceService.selectKnowledgeResourceCount(id) > 0) { + throw new MyException(ReturnCode.CUSTOM_ERROR,ResourceConstants.RESOURCE_ASSOCIATION_MSG); + } + // 删除知识和来源关联 + iKnowledgeResourceService.deleteKnowledgeResource(id); + // 删除来源 + baseMapper.deleteById(id); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/SearchHistoryServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/SearchHistoryServiceImpl.java new file mode 100644 index 0000000..35ec17d --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/SearchHistoryServiceImpl.java @@ -0,0 +1,33 @@ +package com.kb.knowledgebase.modules.knowledge.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.kb.knowledgebase.authority.ThreadLocalUtil; +import com.kb.knowledgebase.authority.UserInfo; +import com.kb.knowledgebase.entity.knowledge.SearchHistory; +import com.kb.knowledgebase.modules.knowledge.mapper.SearchHistoryMapper; +import com.kb.knowledgebase.modules.knowledge.service.ISearchHistoryService; +import com.kb.knowledgebase.modules.util.CommonDateUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class SearchHistoryServiceImpl extends ServiceImpl implements ISearchHistoryService { + + + @Override + public void insertHistory(UserInfo userInfo, String keyword) { + SearchHistory sh = SearchHistory.builder() + .userId(userInfo.getId()) + .userName(userInfo.getUsername()) + .createTime(CommonDateUtil.getSystemTime()) + .searchWord(keyword).build(); + baseMapper.insert(sh); + } + + @Override + public String searchHotWords() { + UserInfo userInfo = ThreadLocalUtil.getUserInfo(); + return baseMapper.searchHotWords(userInfo.getId()); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/StatisticsServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/StatisticsServiceImpl.java new file mode 100644 index 0000000..bfc278b --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/StatisticsServiceImpl.java @@ -0,0 +1,110 @@ +package com.kb.knowledgebase.modules.knowledge.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.kb.knowledgebase.authority.ThreadLocalUtil; +import com.kb.knowledgebase.entity.knowledge.KnowledgeBase; +import com.kb.knowledgebase.entity.knowledge.StatisticsResult; +import com.kb.knowledgebase.modules.knowledge.mapper.KnowledgeBaseMapper; +import com.kb.knowledgebase.modules.knowledge.mapper.StatisticsMapper; +import com.kb.knowledgebase.modules.knowledge.service.ICategoryService; +import com.kb.knowledgebase.modules.knowledge.service.IResourceService; +import com.kb.knowledgebase.modules.knowledge.service.IStatisticsService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Slf4j +@Service +public class StatisticsServiceImpl extends ServiceImpl implements IStatisticsService { + @Autowired + private ICategoryService categoryService; + + @Autowired + private KnowledgeBaseMapper knowledgeBaseMapper; + + + @Override + public List queryTypeStatistics() { + Map map = baseMapper.queryTypeStatistics(); + return map.entrySet().stream().map(e -> + new StatisticsResult(e.getValue().intValue(), e.getKey()) + ).collect(Collectors.toList()); + + } + + @Override + public List queryResourceStatistics() { + Map map = baseMapper.queryResourceStatistics(); + return map.entrySet().stream().map(e -> + new StatisticsResult(e.getValue().intValue(), e.getKey()) + ).collect(Collectors.toList()); + } + + @Override + public List queryCategoryStatistics() { + return categoryService.selectOneLevelStatistics(); + } + + @Override + public Map queryBaseCount(Integer isPublic) { + + return null; + } + + /** + * 部门知识概览 + * + * @return 统计结果 + */ + @Override + public List deptKnowledgeStatistics() { + Map map = baseMapper.deptKnowledgeStatistics(ThreadLocalUtil.getUserInfo().getDeptId()); + return map.entrySet().stream().map(e -> + new StatisticsResult(e.getValue().intValue(), e.getKey()) + ).collect(Collectors.toList()); + } + + /** + * 部门主题库概览 + * + * @return 统计结果 + */ + @Override + public List deptBaseStatistics() { + LambdaQueryWrapper LambdaQueryWrapper = new LambdaQueryWrapper<>(); + LambdaQueryWrapper.eq(KnowledgeBase::getDeptId,ThreadLocalUtil.getUserInfo().getDeptId()); + List knowledgeBaseList = knowledgeBaseMapper.selectList(LambdaQueryWrapper); + return knowledgeBaseList.stream().map(knowledgeBase -> + new StatisticsResult(Math.toIntExact(knowledgeBase.getKnowledgeCount()),knowledgeBase.getBaseName()) + ).collect(Collectors.toList()); + } + + /** + * 部门知识来源概览 + * + * @return 统计结果 + */ + @Override + public List deptResourceStatistics() { + return baseMapper.deptResourceStatistics(ThreadLocalUtil.getUserInfo().getDeptId()); + } + + /** + * 公开知识概览 + * + * @return 统计结果 + */ + @Override + public List pubKnowledgeStatistics() { + Map map = baseMapper.pubKnowledgeStatistics(); + return map.entrySet().stream().map(e -> + new StatisticsResult(e.getValue().intValue(), e.getKey()) + ).collect(Collectors.toList()); + } + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/TagServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/TagServiceImpl.java new file mode 100644 index 0000000..f2461ab --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/TagServiceImpl.java @@ -0,0 +1,89 @@ +package com.kb.knowledgebase.modules.knowledge.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.kb.knowledgebase.authority.ThreadLocalUtil; +import com.kb.knowledgebase.authority.UserInfo; +import com.kb.knowledgebase.entity.MyException; +import com.kb.knowledgebase.entity.ReturnCode; +import com.kb.knowledgebase.entity.knowledge.Tag; +import com.kb.knowledgebase.modules.knowledge.constant.TagConstants; +import com.kb.knowledgebase.modules.knowledge.mapper.TagMapper; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeTagService; +import com.kb.knowledgebase.modules.knowledge.service.ITagService; +import com.kb.knowledgebase.modules.util.CommonDateUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Slf4j +public class TagServiceImpl extends ServiceImpl implements ITagService { + + @Autowired + private IKnowledgeTagService iKnowledgeTagService; + + /** + * 标签管理-标签查询 + * + * @param tagName 类别名称 + * @return 结果集 + */ + @Override + public List selectTagList(String tagName) { + return baseMapper.selectTagList(tagName); + } + + /** + * 标签管理-添加标签 + * + * @param tag 标签信息 + */ + @Override + @Transactional + public void addTag(Tag tag) { + // 标签重复Check + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(Tag::getTagName, tag.getTagName()); + if (baseMapper.exists(lambdaQueryWrapper)) { + throw new MyException(ReturnCode.CUSTOM_ERROR, TagConstants.TAG_REPEAT_MSG); + } else { + UserInfo userInfo = ThreadLocalUtil.getUserInfo(); + // 获取系统时间戳 + Long time = CommonDateUtil.getSystemTime(); + // 创建时间 + tag.setCreateTime(time); + // 更新时间 + tag.setUpdateTime(time); + // 创建id + tag.setCreateById(userInfo.getId()); + // 创建者姓名 + tag.setCreateByName(userInfo.getUsername()); + // 更新id + tag.setUpdateById(userInfo.getId()); + // 更新者姓名 + tag.setUpdateByName(userInfo.getUsername()); + baseMapper.insert(tag); + } + } + + /** + * 标签管理-删除标签 + * + * @param id 标签id + */ + @Override + @Transactional + public void deleteTag(Long id) { + if (iKnowledgeTagService.selectKnowledgeTagCount(id) > 0) { + throw new MyException(ReturnCode.CUSTOM_ERROR,TagConstants.TAG_ASSOCIATION_MSG); + } + // 删除知识和标签关联 + iKnowledgeTagService.deleteKnowledgeTag(id); + // 删除标签 + baseMapper.deleteById(id); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/Word2Html.java b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/Word2Html.java new file mode 100644 index 0000000..614e5ea --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/knowledge/service/impl/Word2Html.java @@ -0,0 +1,208 @@ +package com.kb.knowledgebase.modules.knowledge.service.impl; + +import java.io.*; +import java.net.URL; +import java.net.URLConnection; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import com.kb.knowledgebase.modules.common.CommonParam; +import com.kb.knowledgebase.modules.util.MinioUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.hwpf.HWPFDocument; +import org.apache.poi.hwpf.converter.PicturesManager; +import org.apache.poi.hwpf.converter.WordToHtmlConverter; +import org.apache.poi.hwpf.usermodel.PictureType; +import org.apache.poi.xwpf.converter.core.FileImageExtractor; +import org.apache.poi.xwpf.converter.core.FileURIResolver; +import org.apache.poi.xwpf.converter.core.IURIResolver; +import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter; +import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.poi.xwpf.usermodel.XWPFPicture; +import org.apache.poi.xwpf.usermodel.XWPFPictureData; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.w3c.dom.Document; + +/** + * 将word以上版本转成Html + * + * @author lgn + * + */ +@Service +@Slf4j +public class Word2Html { + + @Autowired + private MinioUtil minioUtil; + + + + /** + * 将Word2007+转成Html + * docx + * @throws Exception + */ + public void word2007ToHtml() throws Exception { + String filePath = "d:\\20221121\\"; + String fileName = "cc.docx"; + String htmlName = "cc.html"; + final String file = filePath + fileName; + File f = new File(file); + ByteArrayOutputStream htmlStream = new ByteArrayOutputStream(); + String htmlStr = null; + if (!f.exists()) { + System.out.println("Sorry File does not Exists!"); + } else { + /* 判断是否为docx文件 */ + // 1)加载word文档生成XWPFDocument对象 + FileInputStream in = new FileInputStream(f); + XWPFDocument document = new XWPFDocument(in); + // 2)解析XHTML配置(这里设置IURIResolver来设置图片存放的目录) + + File directory = new File("src/main/resources/temp/"); + String localPath = ""; + try { + localPath = directory.getCanonicalPath() + "\\" + UUID.randomUUID().toString(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + File imageFolderFile = new File(localPath); // 转入temp路径 + XHTMLOptions options = XHTMLOptions.create().URIResolver(new FileURIResolver(imageFolderFile)); + options.setExtractor(new FileImageExtractor(imageFolderFile)); + options.setIgnoreStylesIfUnused(false); + options.setFragment(true); + + // 3)将XWPFDocument转换成XHTML + //FileOutputStream out = new FileOutputStream(new File(filePath + htmlName)); + XHTMLConverter.getInstance().convert(document, htmlStream, options); + // 解析HTML并上传图片到MinIO + htmlStr = htmlStream.toString(); + String middleImageDirStr = "/word/media"; + String imageDirStr = localPath + middleImageDirStr; + File imageDir = new File(imageDirStr); + String[] imageList = imageDir.list(); + String format = new SimpleDateFormat("yyyy/MM/dd/").format(new Date()); + if (imageList != null) { + for (int i = 0; i < imageList.length; i++) { + try { + String oneImagePathStr = imageDirStr + "/" + imageList[i]; + File fileImage = new File(oneImagePathStr); + if (fileImage.exists()) { + log.info("处理图片{}开始。。。。。。。。",i); + String objectName = format + + UUID.randomUUID().toString().replaceAll("-", "") + + imageList[i].substring(imageList[i].lastIndexOf(".") - 1) + ; + InputStream is = new FileInputStream(oneImagePathStr); + minioUtil.uploadFile(CommonParam.BUCKET_NAME,objectName,is); + htmlStr = htmlStr.replace(oneImagePathStr, "http://ali03.wandoubaba.com:55151/"+CommonParam.BUCKET_NAME+ "/"+objectName); + + } + }catch (Exception e) { + log.info("upload docxToHtmlText exception", e); + }finally { + htmlStream.close(); + } + + } + System.out.println(htmlStr); + } + + + + + } + } + + /** + * word2003转换成html + * 对于doc,可以用下面这种方式: + * @throws Exception + */ + public void word2003ToHtml() throws Exception { + String filePath = "d:\\20221121\\"; + String fileName = "ff.doc"; + String htmlName = "ff.html"; + final String imagePath = filePath + "/image/"; + final String file = filePath + fileName; + InputStream input = new FileInputStream(new File(file)); + HWPFDocument wordDocument = new HWPFDocument(input); + WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter( + DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument()); + //设置图片存储位置 + wordToHtmlConverter.setPicturesManager(new PicturesManager() { + + public String savePicture(byte[] content, PictureType pictureType, String suggestedName, float widthInches, + float heightInches) { +// File imgPath=new File(imagePath); +// if (!imgPath.exists()) {//目录不存在则创建目录 +// imgPath.mkdirs(); +// } +// File file = new File(imagePath+suggestedName); +// try { +// FileOutputStream os = new FileOutputStream(file); +// os.write(content); +// os.close(); +// } catch (FileNotFoundException e) { +// e.printStackTrace(); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// String newPath=imagePath+suggestedName; + + InputStream imhinput = new ByteArrayInputStream(content); + String newPath = "/xbb/" + UUID.randomUUID().toString() + suggestedName; + minioUtil.uploadFile(CommonParam.BUCKET_NAME, newPath, imhinput); + return "http://ali03.wandoubaba.com:55151/" + CommonParam.BUCKET_NAME + newPath; + } + }); + + //解析word文档 +// wordToHtmlConverter.processDocument(wordDocument); +// Document htmlDocument = wordToHtmlConverter.getDocument(); +// File htmlFile = new File(filePath+htmlName); +// FileOutputStream outStream = new FileOutputStream(htmlFile); +// DOMSource domSource = new DOMSource(htmlDocument); +// StreamResult streamResult = new StreamResult(outStream); +// TransformerFactory factory = TransformerFactory.newInstance(); +// Transformer serializer = factory.newTransformer(); +// serializer.setOutputProperty(OutputKeys.ENCODING,"utf-8"); +// serializer.setOutputProperty(OutputKeys.INDENT, "yes"); +// serializer.setOutputProperty(OutputKeys.METHOD, "html"); +// serializer.transform(domSource, streamResult); +// outStream.close(); + + wordToHtmlConverter.processDocument(wordDocument); + Document htmlDocument = wordToHtmlConverter.getDocument(); + File htmlFile = new File(filePath+htmlName); + StringWriter writer = new StringWriter(); + DOMSource domSource = new DOMSource(htmlDocument); + StreamResult streamResult = new StreamResult(writer); + TransformerFactory factory = TransformerFactory.newInstance(); + Transformer serializer = factory.newTransformer(); + serializer.setOutputProperty(OutputKeys.ENCODING,"utf-8"); + serializer.setOutputProperty(OutputKeys.INDENT, "yes"); + serializer.setOutputProperty(OutputKeys.METHOD, "html"); + serializer.transform(domSource, streamResult); + + String xmlString = writer.getBuffer().toString(); + System.out.println(xmlString); + } + + +} + diff --git a/src/main/java/com/kb/knowledgebase/modules/minio/service/impl/MinioServiceImpl.java b/src/main/java/com/kb/knowledgebase/modules/minio/service/impl/MinioServiceImpl.java new file mode 100644 index 0000000..8e09c80 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/minio/service/impl/MinioServiceImpl.java @@ -0,0 +1,10 @@ +package com.kb.knowledgebase.modules.minio.service.impl; + +import org.springframework.stereotype.Service; + +@Service +public class MinioServiceImpl { + public void upload(){ + + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/util/CommonDateUtil.java b/src/main/java/com/kb/knowledgebase/modules/util/CommonDateUtil.java new file mode 100644 index 0000000..97bef78 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/util/CommonDateUtil.java @@ -0,0 +1,21 @@ +package com.kb.knowledgebase.modules.util; + +public class CommonDateUtil { + /** + * 获取系统时间戳(不含毫秒) + * + * @return 系统时间戳(不含毫秒) + */ + public static Long getSystemTime() { + return System.currentTimeMillis() / 1000; + } + + /** + * 获取系统时间戳(含毫秒) + * + * @return 系统时间戳(含毫秒) + */ + public static Long getSystemTimeMillis() { + return System.currentTimeMillis(); + } +} \ No newline at end of file diff --git a/src/main/java/com/kb/knowledgebase/modules/util/CommonPageUtil.java b/src/main/java/com/kb/knowledgebase/modules/util/CommonPageUtil.java new file mode 100644 index 0000000..b596ce7 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/util/CommonPageUtil.java @@ -0,0 +1,46 @@ +package com.kb.knowledgebase.modules.util; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.kb.knowledgebase.modules.common.BaseEntity; +import com.kb.knowledgebase.modules.common.BaseExcelModel; + +public class CommonPageUtil { + /** + * 初始化分页抽象类 + * + * @param pageNumber 页数 + * @param pageSize 每页条数 + * @return 分页抽象类 + */ + public IPage initIPage(Long pageNumber, Long pageSize) { + IPage iPage = new Page<>(); + if (pageNumber == null || pageNumber < 1L) { + pageNumber = 1L; + } + if (pageSize == null || pageSize < 1L) { + pageSize = 10L; + } + iPage.setCurrent(pageNumber); + iPage.setSize(pageSize); + return iPage; + } + + /** + * 如果currentPage/pageSize为空 默认返回前10行 + * @param model + * @param + * @return + */ + public static Page getIPage(BaseEntity model) { + Integer currentPage = model.getCurrentPage(); + Integer pageSize = model.getPageSize(); + if (null == currentPage) { + currentPage = 1; + } + if (null == pageSize) { + pageSize = 10; + } + return new Page(currentPage, pageSize); + } +} \ No newline at end of file diff --git a/src/main/java/com/kb/knowledgebase/modules/util/FileConvertUtil.java b/src/main/java/com/kb/knowledgebase/modules/util/FileConvertUtil.java new file mode 100644 index 0000000..6c3016a --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/util/FileConvertUtil.java @@ -0,0 +1,307 @@ +package com.kb.knowledgebase.modules.util; + +import cn.hutool.core.util.StrUtil; +import com.kb.knowledgebase.entity.MyException; +import com.kb.knowledgebase.modules.common.CommonParam; +import com.kb.knowledgebase.modules.knowledge.callable.Pdf2ImgCallable; +import com.kb.knowledgebase.modules.util.threadpool.ExecutorUtil; +import com.kb.knowledgebase.modules.util.threadpool.TaskPoolProperty; +import lombok.extern.slf4j.Slf4j; +import org.apache.pdfbox.Loader; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.fdf.FDFDocument; +import org.apache.poi.hwpf.HWPFDocument; +import org.apache.poi.hwpf.converter.PicturesManager; +import org.apache.poi.hwpf.converter.WordToHtmlConverter; +import org.apache.poi.hwpf.usermodel.PictureType; +import org.apache.poi.xwpf.converter.core.FileImageExtractor; +import org.apache.poi.xwpf.converter.core.FileURIResolver; +import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter; +import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.multipart.MultipartFile; +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.*; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadPoolExecutor; + +@Component +@Slf4j +public class FileConvertUtil { + + + @Value("${minio.bucketName}") + private String bucketName; + + @Value("${minio.threadDealeachTime}") + private int threadDealeachTime; //线程每次处理几个 + + @Value("${host.imgHost}") + private String localHost; + @Autowired + private MinioUtil minioUtil; + /** + * + * @param filePath minio中文件地址 ex: /knowledge/2024/04/25/1dd4c42a3506419a8f410ddc91c4fce8.png + * v2 修改了地址 2024/04/25/1dd4c42a3506419a8f410ddc91c4fce8.png + * + * @return localpath 本地文件地址 + */ + public String copyFile(String filePath){ + //获取文件真实路径 去掉桶路径 + String imgFilePath = filePath; + + log.info("minio文件路径为{}",imgFilePath); + //判断文件是否存在 + boolean objectExist = minioUtil.isObjectExist(CommonParam.BUCKET_NAME, imgFilePath); + if(!objectExist){ + throw new MyException("miniio中文件不存在!"); + } +// minioUtil.copyFile() + File directory = new File(CommonParam.RESOURCE_DIR); + String localPath = ""; + try { + localPath = directory.getCanonicalPath() + + "\\" + UUID.randomUUID().toString() + + imgFilePath.substring(imgFilePath.lastIndexOf("." )); + } catch (IOException e) { + throw new RuntimeException(e); + } + log.info("copy文件路径{}",localPath); + if(StrUtil.isEmpty(localPath)){ + throw new MyException("copy文件失败"); + } + + //文件写入到本地 + try { + this.writeToLocal(localPath,imgFilePath); + } catch (IOException e) { + throw new RuntimeException(e); + } + return localPath; + } + /** + * minio文件路径 + * @param filePath + */ + public List pdf2img(String filePath){ + log.info("进入pdf2img,文件路径{}", filePath); + //获取到的本地文件 + String localPathFile = this.copyFile(filePath); + + ThreadPoolExecutor threadPoolExecutor = ExecutorUtil.getThreadPool(new TaskPoolProperty(), TaskPoolProperty.THREAD_POOL_EXECUTOR_PREFIX); + List allImagePath = new ArrayList<>(); + List>> futureList = new ArrayList<>(); + long startTime = System.currentTimeMillis(); + + try { + // 加载PDF文档 + PDDocument document = Loader.loadPDF(new File(localPathFile)); + // 遍历每一页并将其转换为图片 + int pdfPage = document.getNumberOfPages(); + document.close(); + //数组 + List pageList= new ArrayList(){}; + for (int pageIndex = 0; pageIndex < pdfPage; pageIndex++) { + if((pageIndex % this.threadDealeachTime == 0 || pageIndex == document.getNumberOfPages() -1) && pageIndex != 0){ + pageList.add(pageIndex); + futureList.add(threadPoolExecutor.submit(new Pdf2ImgCallable(pageList,localPathFile,minioUtil))); + pageList = new ArrayList<>(); + }else{ + pageList.add(pageIndex); + } + } + if(pageList.size() != 0){ //遍历之后如果还有值 则继续线程池执行 + futureList.add(threadPoolExecutor.submit(new Pdf2ImgCallable(pageList,localPathFile,minioUtil))); + } + boolean flag = true; + String errorMsg = ""; + Integer sum = 0; + + for (Future> future : futureList) { + try { + List filepaths = future.get(); + allImagePath.addAll(filepaths); + } catch (Exception e) { + log.error("线程错误信息 ===> ", e); + flag = false; + errorMsg = e.getMessage(); + } + } + } catch (IOException e) { + e.printStackTrace(); + }finally { + threadPoolExecutor.shutdown(); + while (!threadPoolExecutor.isTerminated()) { + // 当前线程池是否全部完成:方案二:添加计数器 + } + log.info("pdf文件处理完成 文件路径{} 开始返回结果",filePath); + deleteLocal(localPathFile); + } + return allImagePath; + } + + /** + * 将InputStream写入本地文件 + * @param destination 写入本地目录 + * @param input 输入流 + * @throws IOException + */ + public void writeToLocal(String destination, InputStream input) + throws IOException { + int index; + byte[] bytes = new byte[1024]; + FileOutputStream downloadFile = new FileOutputStream(destination); + while ((index = input.read(bytes)) != -1) { + downloadFile.write(bytes, 0, index); + downloadFile.flush(); + } + downloadFile.close(); + input.close(); + } + public void writeToLocal(String destination, String filePath) + throws IOException { + log.info("writeToLocal 存入路径为{} minip文件路径为{}",destination, filePath); + InputStream input = minioUtil.getObject(CommonParam.BUCKET_NAME, filePath); + int index; + byte[] bytes = new byte[1024]; + FileOutputStream downloadFile = new FileOutputStream(destination); + while ((index = input.read(bytes)) != -1) { + downloadFile.write(bytes, 0, index); + downloadFile.flush(); + } + downloadFile.close(); + input.close(); + } + public void deleteLocal(String filePath){ + File file = new File(filePath); + boolean delete = file.delete(); + if(!delete){ + throw new MyException("文件删除失败,请检查"); + } + } + + + public String docx2html(String filePath) throws Exception{ + String localPath = this.copyFile(filePath); + File f = new File(localPath); + ByteArrayOutputStream htmlStream = new ByteArrayOutputStream(); + String htmlStr = null; + /* 判断是否为docx文件 */ + // 1)加载word文档生成XWPFDocument对象 + FileInputStream in = new FileInputStream(f); + XWPFDocument document = new XWPFDocument(in); + // 2)解析XHTML配置(这里设置IURIResolver来设置图片存放的目录) + + File directory = new File(CommonParam.RESOURCE_DIR); +// String localPath = ""; + String saveLocalPath = ""; + try { + saveLocalPath = directory.getCanonicalPath() + "\\" + UUID.randomUUID().toString(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + File imageFolderFile = new File(saveLocalPath); // 转入temp路径 + if(!imageFolderFile.exists()){ + imageFolderFile.mkdirs(); + } + XHTMLOptions options = XHTMLOptions.create().URIResolver(new FileURIResolver(imageFolderFile)); + options.setExtractor(new FileImageExtractor(imageFolderFile)); + options.setIgnoreStylesIfUnused(false); + options.setFragment(true); + // 3)将XWPFDocument转换成XHTML + //FileOutputStream out = new FileOutputStream(new File(filePath + htmlName)); + XHTMLConverter.getInstance().convert(document, htmlStream, options); + // 解析HTML并上传图片到MinIO + htmlStr = htmlStream.toString(); + String middleImageDirStr = "/word/media"; + String imageDirStr = saveLocalPath + middleImageDirStr; + File imageDir = new File(imageDirStr); + String[] imageList = imageDir.list(); + String format = new SimpleDateFormat("/yyyy/MM/dd/").format(new Date()); + if (imageList != null) { + for (int i = 0; i < imageList.length; i++) { + try { + String oneImagePathStr = imageDirStr + "/" + imageList[i]; + File fileImage = new File(oneImagePathStr); + if (fileImage.exists()) { + log.info("处理图片{}开始。。。。。。。。",i); + String objectName = format + + UUID.randomUUID().toString().replaceAll("-", "") + + imageList[i].substring(imageList[i].lastIndexOf(".")) + ; + InputStream is = new FileInputStream(oneImagePathStr); + minioUtil.uploadFile(CommonParam.BUCKET_NAME,objectName,is); +// htmlStr = htmlStr.replace(oneImagePathStr, minioUtil.getPresignedObjectUrl(CommonParam.BUCKET_NAME,objectName) ); + //改成下载接口 不用外链 + htmlStr = htmlStr.replace(oneImagePathStr, localHost + objectName ); + + } + }catch (Exception e) { + log.info("上传docx转html报错", e); + }finally { + htmlStream.close(); + } + + } +// System.out.println(htmlStr); + } + return htmlStr; + + } + public String doc2html(MultipartFile file)throws Exception{ + //String localPath = this.copyFile(filePath); // 本地文件path +// InputStream input = new FileInputStream(file); + InputStream input = file.getInputStream(); + HWPFDocument wordDocument = new HWPFDocument(input); + WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter( + DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument()); + String format = new SimpleDateFormat("/yyyy/MM/dd/").format(new Date()); + wordToHtmlConverter.setPicturesManager(new PicturesManager() { + public String savePicture(byte[] content, PictureType pictureType, String suggestedName, float widthInches, + float heightInches) { + InputStream imhinput = new ByteArrayInputStream(content); + String objectName = format + + UUID.randomUUID().toString().replaceAll("-", "") + + suggestedName; + minioUtil.uploadFile(CommonParam.BUCKET_NAME, objectName, imhinput); + + //不使用外链 使用下载接口就可以写入img标签 + return localHost + objectName; + + //return minioUtil.getPresignedObjectUrl(CommonParam.BUCKET_NAME,objectName); + } + }); + wordToHtmlConverter.processDocument(wordDocument); + Document htmlDocument = wordToHtmlConverter.getDocument(); + StringWriter writer = new StringWriter(); + DOMSource domSource = new DOMSource(htmlDocument); + StreamResult streamResult = new StreamResult(writer); + TransformerFactory factory = TransformerFactory.newInstance(); + Transformer serializer = factory.newTransformer(); + serializer.setOutputProperty(OutputKeys.ENCODING,"utf-8"); + serializer.setOutputProperty(OutputKeys.INDENT, "yes"); + serializer.setOutputProperty(OutputKeys.METHOD, "html"); + serializer.transform(domSource, streamResult); + + String xmlString = writer.getBuffer().toString(); + return xmlString; + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/util/MinioUtil.java b/src/main/java/com/kb/knowledgebase/modules/util/MinioUtil.java new file mode 100644 index 0000000..abc039f --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/util/MinioUtil.java @@ -0,0 +1,415 @@ +package com.kb.knowledgebase.modules.util; + +import cn.hutool.core.util.StrUtil; +import io.minio.*; +import io.minio.http.Method; +import io.minio.messages.Bucket; +import io.minio.messages.DeleteObject; +import io.minio.messages.Item; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.*; + +/** + * MinIO工具类 + * + */ +@Component +@Slf4j +public class MinioUtil { + + @Autowired + private MinioClient minioClient; + + /** + * 启动SpringBoot容器的时候初始化Bucket + * 如果没有Bucket则创建 + * + */ + @SneakyThrows(Exception.class) + private void createBucket(String bucketName) { + if (!bucketExists(bucketName)) { + minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); + } + } + + /** + * 判断Bucket是否存在,true:存在,false:不存在 + * + */ + @SneakyThrows(Exception.class) + public boolean bucketExists(String bucketName) { + return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); + } + + /** + * 获得Bucket的策略 + * + */ + @SneakyThrows(Exception.class) + public String getBucketPolicy(String bucketName) { + return minioClient.getBucketPolicy(GetBucketPolicyArgs + .builder() + .bucket(bucketName) + .build()); + } + + /** + * 获得所有Bucket列表 + * + */ + @SneakyThrows(Exception.class) + public List getAllBuckets() { + return minioClient.listBuckets(); + } + + /** + * 根据bucketName获取其相关信息 + * + */ + @SneakyThrows(Exception.class) + public Optional getBucket(String bucketName) { + return getAllBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst(); + } + + /** + * 根据bucketName删除Bucket,true:删除成功; false:删除失败,文件或已不存在 + * + */ + @SneakyThrows(Exception.class) + public void removeBucket(String bucketName) { + minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build()); + } + + + + /** + * 判断文件是否存在 + * + */ + public boolean isObjectExist(String bucketName, String objectName) { + boolean exist = true; + try { + minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build()); + } catch (Exception e) { + log.error("[Minio工具类]>>>> 判断文件是否存在, 异常:", e); + exist = false; + } + return exist; + } + + /** + * 判断文件夹是否存在 + * + */ + public boolean isFolderExist(String bucketName, String objectName) { + boolean exist = false; + try { + Iterable> results = minioClient.listObjects( + ListObjectsArgs.builder().bucket(bucketName).prefix(objectName).recursive(false).build()); + for (Result result : results) { + Item item = result.get(); + if (item.isDir() && objectName.equals(item.objectName())) { + exist = true; + } + } + } catch (Exception e) { + log.error("[Minio工具类]>>>> 判断文件夹是否存在,异常:", e); + exist = false; + } + return exist; + } + + /** + * 根据文件前置查询文件 + * + * @param bucketName 存储桶 + * @param prefix 前缀 + * @param recursive 是否使用递归查询 + * @return MinioItem 列表 + */ + @SneakyThrows(Exception.class) + public List getAllObjectsByPrefix(String bucketName, + String prefix, + boolean recursive) { + List list = new ArrayList<>(); + Iterable> objectsIterator = minioClient.listObjects( + ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(recursive).build()); + if (objectsIterator != null) { + for (Result o : objectsIterator) { + Item item = o.get(); + list.add(item); + } + } + return list; + } + + /** + * 获取文件流 + * + * @param bucketName 存储桶 + * @param objectName 文件名 + * @return 二进制流 + */ + @SneakyThrows(Exception.class) + public InputStream getObject(String bucketName, String objectName) { + return minioClient.getObject( + GetObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .build()); + } + + /** + * 断点下载 + * + * @param bucketName 存储桶 + * @param objectName 文件名称 + * @param offset 起始字节的位置 + * @param length 要读取的长度 + * @return 二进制流 + */ + @SneakyThrows(Exception.class) + public InputStream getObject(String bucketName, String objectName, long offset, long length) { + return minioClient.getObject( + GetObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .offset(offset) + .length(length) + .build()); + } + + /** + * 获取路径下文件列表 + * + * @param bucketName 存储桶 + * @param prefix 文件名称 + * @param recursive 是否递归查找,false:模拟文件夹结构查找 + * @return 二进制流 + */ + public Iterable> listObjects(String bucketName, String prefix, boolean recursive) { + return minioClient.listObjects( + ListObjectsArgs.builder() + .bucket(bucketName) + .prefix(prefix) + .recursive(recursive) + .build()); + } + + /** + * 使用MultipartFile进行文件上传 + * + * @param bucketName 存储桶 + * @param file 文件名 + * @param objectName 对象名 + * @param contentType 类型 + */ + @SneakyThrows(Exception.class) + public void uploadFile(String bucketName, MultipartFile file, String objectName, String contentType) { + InputStream inputStream = file.getInputStream(); + minioClient.putObject( + PutObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .contentType(contentType) + .stream(inputStream, inputStream.available(), -1) + .build()); + inputStream.close(); + } + + + /** + * 图片上传 + */ + public ObjectWriteResponse uploadImage(String bucketName, String imageBase64, String imageName) { + if (!StrUtil.isEmpty(imageBase64)) { + InputStream in = base64ToInputStream(imageBase64); + String newName = System.currentTimeMillis() + "_" + imageName + ".jpg"; + String year = String.valueOf(new Date().getYear()); + String month = String.valueOf(new Date().getMonth()); + return uploadFile(bucketName, year + "/" + month + "/" + newName, in); + + } + + return null; + } + + public static InputStream base64ToInputStream(String base64) { + ByteArrayInputStream stream = null; + try { + byte[] bytes = Base64.getDecoder().decode(base64.trim()); + stream = new ByteArrayInputStream(bytes); + } catch (Exception e) { + e.printStackTrace(); + } + return stream; + } + + + /** + * 上传本地文件 + * + * @param bucketName 存储桶 + * @param objectName 对象名称 + * @param fileName 本地文件路径 + */ + @SneakyThrows(Exception.class) + public ObjectWriteResponse uploadFile(String bucketName, String objectName, String fileName) { + return minioClient.uploadObject( + UploadObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .filename(fileName) + .build()); + } + + /** + * 通过流上传文件 + * + * @param bucketName 存储桶 + * @param objectName 文件对象 + * @param inputStream 文件流 + */ + @SneakyThrows(Exception.class) + public ObjectWriteResponse uploadFile(String bucketName, String objectName, InputStream inputStream) { + PutObjectArgs build = PutObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .stream(inputStream, inputStream.available(), -1) + .build(); + return minioClient.putObject( + build); + } + + + /** + * 创建文件夹或目录 + * + * @param bucketName 存储桶 + * @param objectName 目录路径 + */ + @SneakyThrows(Exception.class) + public ObjectWriteResponse createDir(String bucketName, String objectName) { + return minioClient.putObject( + PutObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .stream(new ByteArrayInputStream(new byte[]{}), 0, -1) + .build()); + } + + /** + * 获取文件信息, 如果抛出异常则说明文件不存在 + * + * @param bucketName 存储桶 + * @param objectName 文件名称 + */ + @SneakyThrows(Exception.class) + public String getFileStatusInfo(String bucketName, String objectName) { + return minioClient.statObject( + StatObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .build()).toString(); + } + + /** + * 拷贝文件 + * + * @param bucketName 存储桶 + * @param objectName 文件名 + * @param srcBucketName 目标存储桶 + * @param srcObjectName 目标文件名 + */ + @SneakyThrows(Exception.class) + public ObjectWriteResponse copyFile(String bucketName, String objectName, String srcBucketName, String srcObjectName) { + return minioClient.copyObject( + CopyObjectArgs.builder() + .source(CopySource.builder().bucket(bucketName).object(objectName).build()) + .bucket(srcBucketName) + .object(srcObjectName) + .build()); + } + + /** + * 删除文件 + * + * @param bucketName 存储桶 + * @param objectName 文件名称 + */ + @SneakyThrows(Exception.class) + public void removeFile(String bucketName, String objectName) { + minioClient.removeObject( + RemoveObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .build()); + } + + /** + * 批量删除文件 + * + * @param bucketName 存储桶 + * @param keys 需要删除的文件列表 + */ + public void removeFiles(String bucketName, List keys) { + List objects = new LinkedList<>(); + keys.forEach(s -> { + objects.add(new DeleteObject(s)); + try { + removeFile(bucketName, s); + } catch (Exception e) { + log.error("[Minio工具类]>>>> 批量删除文件,异常:", e); + } + }); + } + + /** + * 获取文件外链 + * + * @param bucketName 存储桶 + * @param objectName 文件名 + * @param expires 过期时间 <=7 秒 (外链有效时间(单位:秒)) + * @return url + */ + @SneakyThrows(Exception.class) + public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) { + GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().expiry(expires).bucket(bucketName).object(objectName).build(); + return minioClient.getPresignedObjectUrl(args); + } + + /** + * 获得文件外链 + * + * @return url + */ + @SneakyThrows(Exception.class) + public String getPresignedObjectUrl(String bucketName, String objectName) { + GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder() + .bucket(bucketName) + .object(objectName) + .method(Method.GET).build(); + return minioClient.getPresignedObjectUrl(args); + } + + /** + * 将URLDecoder编码转成UTF8 + * + */ + public String getUtf8ByURLDecoder(String str) throws UnsupportedEncodingException { + String url = str.replaceAll("%(?![0-9a-fA-F]{2})", "%25"); + return URLDecoder.decode(url, "UTF-8"); + } +} + + + diff --git a/src/main/java/com/kb/knowledgebase/modules/util/ResponseResultUtils.java b/src/main/java/com/kb/knowledgebase/modules/util/ResponseResultUtils.java new file mode 100644 index 0000000..dd1d311 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/util/ResponseResultUtils.java @@ -0,0 +1,21 @@ +package com.kb.knowledgebase.modules.util; + +import com.kb.knowledgebase.modules.common.ResponseResult; +import lombok.experimental.UtilityClass; + +/** + * @author quangz + * @version 1.0 + */ +@UtilityClass +public class ResponseResultUtils { + + public ResponseResult result() { + return new ResponseResult<>(ResponseResult.STATUS_SUCCESS, "成功", new Object[0]); + } + + public ResponseResult resultError(String msg) { + return new ResponseResult<>(ResponseResult.STATUS_ERROR, msg); + } + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/util/SignUtil.java b/src/main/java/com/kb/knowledgebase/modules/util/SignUtil.java new file mode 100644 index 0000000..8e4ba81 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/util/SignUtil.java @@ -0,0 +1,30 @@ +package com.kb.knowledgebase.modules.util; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.util.DigestUtils; + +import java.util.Map; +import java.util.TreeMap; +import java.util.stream.Collectors; + +public class SignUtil { + /** + * 获取签名 + * + * @param appKey key + * @param appSecret secret + * @param paramMap 参数 + * @param systemTime 时间戳 + * @return sign + */ + public static String getSign(String appKey, String appSecret, + Map paramMap, + String systemTime) { + Map param = new TreeMap<>(); + param.put("appKey",appKey); + param.putAll(paramMap); + param.put("timestamp",systemTime); + String trim = param.entrySet().stream() .map(entry -> String.join("=", entry.getKey(), entry.getValue())).collect(Collectors.joining("&")).trim() .concat("&appSecret=").concat(appSecret); + return DigestUtils.md5DigestAsHex(trim.getBytes()).toUpperCase(); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/util/threadpool/ExecutorUtil.java b/src/main/java/com/kb/knowledgebase/modules/util/threadpool/ExecutorUtil.java new file mode 100644 index 0000000..d3cede6 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/util/threadpool/ExecutorUtil.java @@ -0,0 +1,32 @@ +package com.kb.knowledgebase.modules.util.threadpool; + +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + + +public class ExecutorUtil { + + private ExecutorUtil() { + } + + public static ThreadPoolExecutor getThreadPool(TaskPoolProperty taskPoolProperty, String prefix) { + return configPool( + taskPoolProperty.getCorePoolSize(), + taskPoolProperty.getMaxPoolSize(), + taskPoolProperty.getKeepAliveSeconds(), + taskPoolProperty.getQueueCapacity(), + prefix + ); + } + + private static ThreadPoolExecutor configPool(int corePoolSize, int maxPoolSize, int keepAliveSeconds, int queueCapacity, String prefix) { + + int ioCpuN = Runtime.getRuntime().availableProcessors() * 2 + 1; + corePoolSize = Math.max(ioCpuN, corePoolSize); + maxPoolSize = Math.max(maxPoolSize, corePoolSize * 2); + return new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveSeconds, TimeUnit.SECONDS, new LinkedBlockingDeque<>(queueCapacity), new TvmThreadFactory(prefix), new TvmRejectHandler()); + } + + +} diff --git a/src/main/java/com/kb/knowledgebase/modules/util/threadpool/TaskPoolProperty.java b/src/main/java/com/kb/knowledgebase/modules/util/threadpool/TaskPoolProperty.java new file mode 100644 index 0000000..b6c46f3 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/util/threadpool/TaskPoolProperty.java @@ -0,0 +1,54 @@ +package com.kb.knowledgebase.modules.util.threadpool; + + +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + + + +@Configuration +@ConfigurationProperties(prefix = "thread-pool") +public class TaskPoolProperty { + + public static final String THREAD_POOL_EXECUTOR_PREFIX = "KB-POOL-"; + + @Getter + private int corePoolSize = 10; + + @Getter + private int maxPoolSize = 20; + + @Getter + private int keepAliveSeconds = 300; + + @Getter + private int queueCapacity = 300; + + @Getter + private int threadPageSize = 10000; + + @Getter + private int threadCommitSize = 1000; + + /** + * 单例线程池 TODO 备用 + */ +// @Bean("tvmThreadPool") +// public ThreadPoolExecutor getTvmThreadPool(){ +// int ioCpuN = Runtime.getRuntime().availableProcessors() * 2 + 1; +// corePoolSize = Math.max(ioCpuN, corePoolSize); +// maxPoolSize = Math.max(maxPoolSize, corePoolSize * 2); +// return new ThreadPoolExecutor( +// corePoolSize, +// maxPoolSize, +// keepAliveSeconds, +// TimeUnit.SECONDS, +// new LinkedBlockingDeque<>(queueCapacity), +// new TvmThreadFactory(THREAD_POOL_EXECUTOR_PREFIX), +// new TvmRejectHandler() +// ); +// } + +} \ No newline at end of file diff --git a/src/main/java/com/kb/knowledgebase/modules/util/threadpool/TvmRejectHandler.java b/src/main/java/com/kb/knowledgebase/modules/util/threadpool/TvmRejectHandler.java new file mode 100644 index 0000000..f8ddf73 --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/util/threadpool/TvmRejectHandler.java @@ -0,0 +1,14 @@ +package com.kb.knowledgebase.modules.util.threadpool; + +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadPoolExecutor; + + +public class TvmRejectHandler implements RejectedExecutionHandler { + @Override + public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { + // 拒绝策略 + throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + executor.toString()); + } +} diff --git a/src/main/java/com/kb/knowledgebase/modules/util/threadpool/TvmThreadFactory.java b/src/main/java/com/kb/knowledgebase/modules/util/threadpool/TvmThreadFactory.java new file mode 100644 index 0000000..a0e7f7f --- /dev/null +++ b/src/main/java/com/kb/knowledgebase/modules/util/threadpool/TvmThreadFactory.java @@ -0,0 +1,25 @@ +package com.kb.knowledgebase.modules.util.threadpool; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + + +public class TvmThreadFactory implements ThreadFactory { + + private final String namePrefix; + private final AtomicInteger nextid = new AtomicInteger(1); + + /** + * 定义线程组名称,使用jstack来排查线程问题 + * + * @param namePrefix + */ + public TvmThreadFactory(String namePrefix) { + this.namePrefix = namePrefix + "-"; + } + + @Override + public Thread newThread(Runnable task) { + return new Thread(null, task, namePrefix + nextid.getAndIncrement(), 0); + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 0000000..ccce349 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,55 @@ +logging: + level: + com.kb.knowledgebase.modules: debug + org.springframework: warn + +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + username: postgres + password: f9RgqEgqzR4EJdG76Y + url: jdbc:postgresql://ali04.wandoubaba.com:55152/knowledgebase +# username: root +# password: root +# url: jdbc:mysql://127.0.0.1:3306/knowledgebase?characterEncoding=utf8&useUnicode=true&serverTimezone=UTC +# driver-class-name: com.mysql.jdbc.Driver + redis: + host: ali04.wandoubaba.com + port: 55153 + password: Sh6tRSw7zFvNDXfpr6 + servlet: + multipart: + max-request-size: 1000MB + max-file-size: 100MB + +# y6kS69zHjPowf8VPGBzd rkKZE4AXbmmwugma4xo7xVyIQCerU60lH5lGWhIM +# Minio 配置 +minio: + endpoint: http://ali04.wandoubaba.com:55151 #对象存储服务的URL + accessKey: xgWBFLspgcm773w6Pt #y6kS69zHjPowf8VPGBzd #Access key账户 写账号也可以 + secretKey: TtuYekULaCVUM7Jw3b #rkKZE4AXbmmwugma4xo7xVyIQCerU60lH5lGWhIM #Secret key密码 + bucketName: knowledge # 桶名称 + expire: 7200 # 过期时间 + threadDealeachTime: 10 +elasticsearch: + endpoint: ali04.wandoubaba.com + port: 55154 + scheme: http + +host: + imgHost: http://ali04.wandoubaba.com:55181/file/fileDownload?path= #前端预览和下载的接口前缀 + + +mybatis-plus: + mapper-locations: classpath*:mapper/**/*.xml + +app: + baseUrl: http://172.16.18.170:19090 + key: cloudwalk_knowledge + secret: d83d52bfc2e0c6bc48edefe981c81aeacd474e55 + +kb: + mock-user-enabled: true + + + diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 0000000..c316511 --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,59 @@ +logging: + level: + com.kb.knowledgebase.modules: debug + org.springframework: warn + +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + username: postgres + password: f9RgqEgqzR4EJdG76Y + url: jdbc:postgresql://172.17.0.1:55152/knowledgebase + # username: root + # password: root + # url: jdbc:mysql://127.0.0.1:3306/knowledgebase?characterEncoding=utf8&useUnicode=true&serverTimezone=UTC + # driver-class-name: com.mysql.jdbc.Driver + redis: + host: 172.17.0.1 + port: 55153 + password: Sh6tRSw7zFvNDXfpr6 + servlet: + multipart: + max-request-size: 1000MB + max-file-size: 100MB + + kafka: + bootstrap-servers: 192.168.20.171:9092,192.168.20.184:9092,192.168.20.32:9092 + +# y6kS69zHjPowf8VPGBzd rkKZE4AXbmmwugma4xo7xVyIQCerU60lH5lGWhIM +# Minio 配置 +minio: + endpoint: http://172.24.70.24:55151 #对象存储服务的URL + accessKey: xgWBFLspgcm773w6Pt #Access key账户 写账号也可以 + secretKey: TtuYekULaCVUM7Jw3b #Secret key密码 + bucketName: knowledge # 桶名称 + expire: 7200 # 过期时间 + threadDealeachTime: 10 +elasticsearch: + endpoint: 172.17.0.1 + port: 55154 + scheme: http + +host: + imgHost: http://172.24.70.24:55181/file/fileDownload?path= #前端预览和下载的接口前缀 + + + +mybatis-plus: + mapper-locations: classpath*:mapper/**/*.xml + +app: + baseUrl: http://172.24.70.65:9090 + key: cloudwalk_knowledge + secret: d83d52bfc2e0c6bc48edefe981c81aeacd474e55 + +kb: + log: + mq: + enabled: true + topic: external_operation_log diff --git a/src/main/resources/application-sit.yml b/src/main/resources/application-sit.yml new file mode 100644 index 0000000..89f825c --- /dev/null +++ b/src/main/resources/application-sit.yml @@ -0,0 +1,59 @@ +logging: + level: + com.kb.knowledgebase.modules: debug + org.springframework: warn + +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + username: postgres + password: f9RgqEgqzR4EJdG76Y + url: jdbc:postgresql://172.17.0.1:55152/knowledgebase + # username: root + # password: root + # url: jdbc:mysql://127.0.0.1:3306/knowledgebase?characterEncoding=utf8&useUnicode=true&serverTimezone=UTC + # driver-class-name: com.mysql.jdbc.Driver + redis: + host: 172.17.0.1 + port: 55153 + password: Sh6tRSw7zFvNDXfpr6 + servlet: + multipart: + max-request-size: 1000MB + max-file-size: 100MB + + kafka: + bootstrap-servers: 192.168.90.69:9092 + +# y6kS69zHjPowf8VPGBzd rkKZE4AXbmmwugma4xo7xVyIQCerU60lH5lGWhIM +# Minio 配置 +minio: + endpoint: http://127.0.0.1:9000 #对象存储服务的URL + accessKey: y6kS69zHjPowf8VPGBzd #Access key账户 写账号也可以 + secretKey: rkKZE4AXbmmwugma4xo7xVyIQCerU60lH5lGWhIM #Secret key密码 + bucketName: knowledge # 桶名称 + expire: 7200 # 过期时间 + threadDealeachTime: 10 +elasticsearch: + endpoint: localhost + port: 9200 + scheme: http + +host: + imgHost: http://172.17.0.1:55181/file/fileDownload?path= #前端预览和下载的接口前缀 + + + +mybatis-plus: + mapper-locations: classpath*:mapper/**/*.xml + +app: + baseUrl: http://172.16.18.170:19090 + key: cloudwalk_knowledge + secret: d83d52bfc2e0c6bc48edefe981c81aeacd474e55 + +kb: + log: + mq: + enabled: true + topic: external_operation_log diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..b15bae1 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,13 @@ +server: + port: 55181 + + +spring: + application: + name: knowledgeBase + profiles: + active: dev + + + + diff --git a/src/main/resources/logconf/log4j2.xml b/src/main/resources/logconf/log4j2.xml new file mode 100644 index 0000000..7038b58 --- /dev/null +++ b/src/main/resources/logconf/log4j2.xml @@ -0,0 +1,81 @@ + + + + + ${sys:system.basedir}/logs + UTF-8 + + ???? + %xwEx + %5p + yyyy-MM-dd HH:mm:ss.SSS + %clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD} + %d{${LOG_DATEFORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} ${sys:PID} --- [%t] %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/AttachmentMapper.xml b/src/main/resources/mapper/AttachmentMapper.xml new file mode 100644 index 0000000..98ea5e4 --- /dev/null +++ b/src/main/resources/mapper/AttachmentMapper.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/CategoryMapper.xml b/src/main/resources/mapper/CategoryMapper.xml new file mode 100644 index 0000000..568e4a8 --- /dev/null +++ b/src/main/resources/mapper/CategoryMapper.xml @@ -0,0 +1,162 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/KnowledgeBaseMapper.xml b/src/main/resources/mapper/KnowledgeBaseMapper.xml new file mode 100644 index 0000000..35ffc2b --- /dev/null +++ b/src/main/resources/mapper/KnowledgeBaseMapper.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/KnowledgeCollectionMapper.xml b/src/main/resources/mapper/KnowledgeCollectionMapper.xml new file mode 100644 index 0000000..a480dc5 --- /dev/null +++ b/src/main/resources/mapper/KnowledgeCollectionMapper.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/KnowledgeCommentMapper.xml b/src/main/resources/mapper/KnowledgeCommentMapper.xml new file mode 100644 index 0000000..25b4332 --- /dev/null +++ b/src/main/resources/mapper/KnowledgeCommentMapper.xml @@ -0,0 +1,31 @@ + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/KnowledgeMapper.xml b/src/main/resources/mapper/KnowledgeMapper.xml new file mode 100644 index 0000000..3cf19aa --- /dev/null +++ b/src/main/resources/mapper/KnowledgeMapper.xml @@ -0,0 +1,340 @@ + + + + + + + + + + + + + + + where a.id in + + ${id} + + + + + + + + + + + + INSERT INTO KB_KNOWLEDGE_TAG + ( + KNOWLEDGE_ID, + TAG_ID + ) + + VALUES + + (${id}, ${item}) + + + + INSERT INTO KB_KNOWLEDGE_RESOURCE + ( + KNOWLEDGE_ID, + RESOURCE_ID + ) + + VALUES + + (${id}, ${item}) + + + + DELETE FROM KB_KNOWLEDGE_TAG WHERE KNOWLEDGE_ID = ${id} + + + DELETE FROM KB_KNOWLEDGE_RESOURCE WHERE KNOWLEDGE_ID = ${id} + + + INSERT INTO KB_KNOWLEDGE_ATTACHMENT + ( + KNOWLEDGE_ID, + ATTACHMENT_ID + ) + + VALUES + + (${id}, #{item}) + + + + + + + INSERT INTO KB_KNOWLEDGE_IMG + ( + KNOWLEDGE_ID, + IMG_PATH + ) + + VALUES + + (${id}, #{item,jdbcType=VARCHAR}) + + + + DELETE FROM KB_KNOWLEDGE_IMG WHERE KNOWLEDGE_ID = ${id} + + + INSERT INTO KB_KNOWLEDGE_CONTENT + ( + KNOWLEDGE_ID, + KNOWLEDGE_CONTENT + ) + VALUES + ( + ${id}, + #{content} + ) + + + + UPDATE KB_KNOWLEDGE_CONTENT + SET KNOWLEDGE_CONTENT = #{content} + WHERE KNOWLEDGE_ID = ${id} + + + + DELETE FROM KB_KNOWLEDGE_CONTENT WHERE KNOWLEDGE_ID = ${id} + + + + + + + + + + + + + + UPDATE kb_knowledge SET VIEW_NUM = VIEW_NUM +1 WHERE ID = ${id} + + + UPDATE kb_base SET knowledge_count = knowledge_count +1 WHERE ID = ${id} + + + UPDATE kb_category SET kb_count = kb_count +1 WHERE ID = ${id} + + + + UPDATE kb_base SET knowledge_count = knowledge_count -1 WHERE ID = ${id} + + + UPDATE kb_category SET kb_count = kb_count -1 WHERE ID = ${id} + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ResourceMapper.xml b/src/main/resources/mapper/ResourceMapper.xml new file mode 100644 index 0000000..0272b7d --- /dev/null +++ b/src/main/resources/mapper/ResourceMapper.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/SearchHistoryMapper.xml b/src/main/resources/mapper/SearchHistoryMapper.xml new file mode 100644 index 0000000..bb88bb3 --- /dev/null +++ b/src/main/resources/mapper/SearchHistoryMapper.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/StatisticsMapper.xml b/src/main/resources/mapper/StatisticsMapper.xml new file mode 100644 index 0000000..d721cb9 --- /dev/null +++ b/src/main/resources/mapper/StatisticsMapper.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/TagMapper.xml b/src/main/resources/mapper/TagMapper.xml new file mode 100644 index 0000000..aca3ee3 --- /dev/null +++ b/src/main/resources/mapper/TagMapper.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/src/main/resources/temp/2edb773a-d7a6-4084-809b-95503243e6ac/word/media/image1.png b/src/main/resources/temp/2edb773a-d7a6-4084-809b-95503243e6ac/word/media/image1.png new file mode 100644 index 0000000..4014009 Binary files /dev/null and b/src/main/resources/temp/2edb773a-d7a6-4084-809b-95503243e6ac/word/media/image1.png differ diff --git a/src/main/resources/temp/2edb773a-d7a6-4084-809b-95503243e6ac/word/media/image2.png b/src/main/resources/temp/2edb773a-d7a6-4084-809b-95503243e6ac/word/media/image2.png new file mode 100644 index 0000000..99a5f09 Binary files /dev/null and b/src/main/resources/temp/2edb773a-d7a6-4084-809b-95503243e6ac/word/media/image2.png differ diff --git a/src/main/resources/temp/2edb773a-d7a6-4084-809b-95503243e6ac/word/media/image3.emf b/src/main/resources/temp/2edb773a-d7a6-4084-809b-95503243e6ac/word/media/image3.emf new file mode 100644 index 0000000..5505853 Binary files /dev/null and b/src/main/resources/temp/2edb773a-d7a6-4084-809b-95503243e6ac/word/media/image3.emf differ diff --git a/src/main/resources/temp/64bb7ef1-2dad-4ddb-9b14-25593be0c983.docx b/src/main/resources/temp/64bb7ef1-2dad-4ddb-9b14-25593be0c983.docx new file mode 100644 index 0000000..45d8666 Binary files /dev/null and b/src/main/resources/temp/64bb7ef1-2dad-4ddb-9b14-25593be0c983.docx differ diff --git a/src/main/resources/temp/a946cbd8-78c0-4ebf-a382-45baf5f76c88/word/media/image1.png b/src/main/resources/temp/a946cbd8-78c0-4ebf-a382-45baf5f76c88/word/media/image1.png new file mode 100644 index 0000000..4014009 Binary files /dev/null and b/src/main/resources/temp/a946cbd8-78c0-4ebf-a382-45baf5f76c88/word/media/image1.png differ diff --git a/src/main/resources/temp/a946cbd8-78c0-4ebf-a382-45baf5f76c88/word/media/image2.png b/src/main/resources/temp/a946cbd8-78c0-4ebf-a382-45baf5f76c88/word/media/image2.png new file mode 100644 index 0000000..99a5f09 Binary files /dev/null and b/src/main/resources/temp/a946cbd8-78c0-4ebf-a382-45baf5f76c88/word/media/image2.png differ diff --git a/src/main/resources/temp/a946cbd8-78c0-4ebf-a382-45baf5f76c88/word/media/image3.emf b/src/main/resources/temp/a946cbd8-78c0-4ebf-a382-45baf5f76c88/word/media/image3.emf new file mode 100644 index 0000000..5505853 Binary files /dev/null and b/src/main/resources/temp/a946cbd8-78c0-4ebf-a382-45baf5f76c88/word/media/image3.emf differ diff --git a/src/main/resources/temp/d61bd041-be77-471d-ad17-993c734d6e28.docx b/src/main/resources/temp/d61bd041-be77-471d-ad17-993c734d6e28.docx new file mode 100644 index 0000000..ecd4103 Binary files /dev/null and b/src/main/resources/temp/d61bd041-be77-471d-ad17-993c734d6e28.docx differ diff --git a/src/test/java/com/kb/knowledgebase/FileConvertUtilTest.java b/src/test/java/com/kb/knowledgebase/FileConvertUtilTest.java new file mode 100644 index 0000000..37a57f0 --- /dev/null +++ b/src/test/java/com/kb/knowledgebase/FileConvertUtilTest.java @@ -0,0 +1,43 @@ +package com.kb.knowledgebase; + +import com.kb.knowledgebase.modules.common.CommonParam; +import com.kb.knowledgebase.modules.util.FileConvertUtil; +import com.kb.knowledgebase.modules.util.MinioUtil; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.List; + +@SpringBootTest +public class FileConvertUtilTest { + @Autowired + private FileConvertUtil fileConvertUtil; + + @Autowired + private MinioUtil minioUtil; + @Test + public void png2img(){ //pass + List strings = fileConvertUtil.pdf2img("/knowledge/1.pdf"); //2min18sec 最大线程号17 + System.out.println(strings); + } + @Test + public void doc2html() throws Exception { //pass + //String s = fileConvertUtil.doc2html("/knowledge/ff.doc"); + //System.out.println(s); + } + @Test + public void docx2html() throws Exception {//xx + String s = fileConvertUtil.docx2html("/knowledge/cc.docx"); + System.out.println(s); + } + + @Test + public void xx(){ + String imgFilePath = "sadjkasjdlpl.png"; + String c = imgFilePath.substring(imgFilePath.lastIndexOf("." ) -1 ); + System.out.println(c); + } + + +} diff --git a/src/test/java/com/kb/knowledgebase/KnowledgeBaseApplicationTests.java b/src/test/java/com/kb/knowledgebase/KnowledgeBaseApplicationTests.java new file mode 100644 index 0000000..9affbc2 --- /dev/null +++ b/src/test/java/com/kb/knowledgebase/KnowledgeBaseApplicationTests.java @@ -0,0 +1,169 @@ +package com.kb.knowledgebase; + +import com.kb.knowledgebase.modules.util.MinioUtil; +import org.apache.poi.hwpf.HWPFDocument; +import org.apache.poi.hwpf.converter.PicturesManager; +import org.apache.poi.hwpf.converter.WordToHtmlConverter; +import org.apache.poi.hwpf.usermodel.PictureType; +import org.apache.poi.xwpf.converter.core.BasicURIResolver; +import org.apache.poi.xwpf.converter.core.FileImageExtractor; +import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter; +import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.*; + +@SpringBootTest +class KnowledgeBaseApplicationTests { + + @Test + void contextLoads() { + } + + + + @Test + public void word2007ToHtml() throws Exception { + String filepath = "d:/20221121/"; + String sourceFileName =filepath+"abc.docx"; + String targetFileName = filepath+"abc.html"; + String imagePathStr = filepath+"/image/"; + OutputStreamWriter outputStreamWriter = null; + try { + XWPFDocument document = new XWPFDocument(new FileInputStream(sourceFileName)); + XHTMLOptions options = XHTMLOptions.create(); + // 存放图片的文件夹 + options.setExtractor(new FileImageExtractor(new File(imagePathStr))); + // html中图片的路径 + options.URIResolver(new BasicURIResolver("image")); + + + + outputStreamWriter = new OutputStreamWriter(new FileOutputStream(targetFileName), "utf-8"); + XHTMLConverter xhtmlConverter = (XHTMLConverter) XHTMLConverter.getInstance(); + xhtmlConverter.convert(document, outputStreamWriter, options); + } finally { + if (outputStreamWriter != null) { + outputStreamWriter.close(); + } + } + } + + @Test + public void test(){ + DocxToHtml("d:/20221121/dd.doc","d:/20221121/dd.html"); + } + public static void DocxToHtml(String fileAllName,String outPutFile){ + HWPFDocument wordDocument; + try { + //根据输入文件路径与名称读取文件流 + InputStream in=new FileInputStream(fileAllName); + //把文件流转化为输入wordDom对象 + wordDocument = new HWPFDocument(in); + //通过反射构建dom创建者工厂 + DocumentBuilderFactory domBuilderFactory=DocumentBuilderFactory.newInstance(); + //生成dom创建者 + DocumentBuilder domBuilder=domBuilderFactory.newDocumentBuilder(); + //生成dom对象 + Document dom=domBuilder.newDocument(); + //生成针对Dom对象的转化器 + WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(dom); + //转化器重写内部方法 + wordToHtmlConverter.setPicturesManager( new PicturesManager() + { + public String savePicture(byte[] content, + PictureType pictureType, String suggestedName, + float widthInches, float heightInches ) + { + return suggestedName; + } + } ); + //转化器开始转化接收到的dom对象 + wordToHtmlConverter.processDocument(wordDocument); + //保存文档中的图片 + /* List pics=wordDocument.getPicturesTable().getAllPictures(); + if(pics!=null){ + for(int i=0;i\r\n"); + + + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Test + public static void PdfToImage(String pdfurl) { + StringBuffer buffer = new StringBuffer(); + FileOutputStream fos; + PDDocument document; + File pdfFile; + int size; + BufferedImage image; + FileOutputStream out; + Long randStr = 0l; + //PDF转换成HTML保存的文件夹 + String path = "d:/20221121/pdfimg"; + File htmlsDir = new File(path); + if (!htmlsDir.exists()) { + htmlsDir.mkdirs(); + } + File htmlDir = new File(path + "/"); + if (!htmlDir.exists()) { + htmlDir.mkdirs(); + } + try { + //遍历处理pdf附件 + randStr = System.currentTimeMillis(); + buffer.append("\r\n"); + buffer.append("\r\n"); + buffer.append("\r\n"); + buffer.append("\r\n"); + buffer.append("\r\n"); + buffer.append("\r\n"); + document = new PDDocument(); + //pdf附件 + pdfFile = new File(pdfurl); + document = Loader.loadPDF(pdfFile, (String) null); + size = document.getNumberOfPages(); + Long start = System.currentTimeMillis(), end = null; + System.out.println("===>pdf : " + pdfFile.getName() + " , size : " + size); + PDFRenderer reader = new PDFRenderer(document); + for (int i = 0; i < size; i++) { + //image = newPDFRenderer(document).renderImageWithDPI(i,130,ImageType.RGB); + image = reader.renderImage(i, 1.5f); + //生成图片,保存位置 + out = new FileOutputStream(path + "/" + "image" + "_" + i + ".jpg"); + ImageIO.write(image, "png", out); //使用png的清晰度 + //将图片路径追加到网页文件里 + buffer.append("\r\n"); + image = null; + out.flush(); + out.close(); + } + reader = null; + document.close(); + buffer.append("\r\n"); + buffer.append(""); + end = System.currentTimeMillis() - start; + System.out.println("===> Reading pdf times: " + (end / 1000)); + start = end = null; + //生成网页文件 + fos = new FileOutputStream(path + randStr + ".html"); + System.out.println(path + randStr + ".html"); + fos.write(buffer.toString().getBytes()); + fos.flush(); + fos.close(); + buffer.setLength(0); + + + } catch (Exception e) { + System.out.println("===>Reader parse pdf to jpg error : " + e.getMessage()); + e.printStackTrace(); + } + + } + +} diff --git a/src/test/java/com/kb/knowledgebase/Word2HtmlTest.java b/src/test/java/com/kb/knowledgebase/Word2HtmlTest.java new file mode 100644 index 0000000..29a20ad --- /dev/null +++ b/src/test/java/com/kb/knowledgebase/Word2HtmlTest.java @@ -0,0 +1,34 @@ +package com.kb.knowledgebase; + +import com.kb.knowledgebase.modules.knowledge.service.impl.Word2Html; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class Word2HtmlTest { + @Autowired + private Word2Html word2Html; + + @Test + public void docx2h(){ + try { + word2Html.word2007ToHtml(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + @Test + public void dooc2h(){ + try { + word2Html.word2003ToHtml(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void testgpt(){ + + } +} diff --git a/src/test/java/com/kb/knowledgebase/esCollectiontest.java b/src/test/java/com/kb/knowledgebase/esCollectiontest.java new file mode 100644 index 0000000..55887a1 --- /dev/null +++ b/src/test/java/com/kb/knowledgebase/esCollectiontest.java @@ -0,0 +1,74 @@ +package com.kb.knowledgebase; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.kb.knowledgebase.authority.ThreadLocalUtil; +import com.kb.knowledgebase.authority.UserInfo; +import com.kb.knowledgebase.entity.knowledge.Knowledge; +import com.kb.knowledgebase.entity.knowledge.KnowledgeVo; +import com.kb.knowledgebase.modules.elasticsearch.impl.ElasticSearchServiceImpl; +import com.kb.knowledgebase.modules.knowledge.service.IKnowledgeService; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@SpringBootTest +public class esCollectiontest { + @Autowired + private IKnowledgeService iKnowledgeService; + + @Autowired + private ElasticSearchServiceImpl elasticSearchService; + @Test + public void esc(){ + iKnowledgeService.changeCollection( 1785872401314631682L, + new ArrayList() + {{ + add("U123123123"); + add("U1231231234"); + add("U1231231235"); + }} + ); + } + @Test + public void queryCollectionKnowledgePage(){ + UserInfo userInfo = new UserInfo(); + userInfo.setId("U123123123"); + userInfo.setUsername("test01"); + userInfo.setDeptId("D01"); + ThreadLocalUtil.setUserInfo(userInfo); + KnowledgeVo build = KnowledgeVo.builder().keyword("").build(); + List knowledgeList = new ArrayList<>(); + Long aLong = iKnowledgeService.queryCollectionKnowledgePage(build, knowledgeList); + } + + + + + @Test + public void transDocumentByBaseId(){ + + iKnowledgeService.transDocumentByBaseId(1785147078553899009L,1,"d01"); + } + + @Test + public void changeCategoryId() + { + elasticSearchService.changeCategoryId(1779432065126584321L, 1779432065126584322L, "knowledge-public"); + } + + @Test + public void indexExist(){ + elasticSearchService.indexExist("knowledge-d011"); + } + + @Test + public void createIndex(){ + elasticSearchService.createIndex("test3"); + } +} diff --git a/src/test/java/com/kb/knowledgebase/pdf2Img.java b/src/test/java/com/kb/knowledgebase/pdf2Img.java new file mode 100644 index 0000000..81e1e12 --- /dev/null +++ b/src/test/java/com/kb/knowledgebase/pdf2Img.java @@ -0,0 +1,108 @@ +package com.kb.knowledgebase; + +import com.kb.knowledgebase.modules.knowledge.callable.Pdf2ImgCallable; +import com.kb.knowledgebase.modules.util.MinioUtil; +import com.kb.knowledgebase.modules.util.threadpool.ExecutorUtil; +import com.kb.knowledgebase.modules.util.threadpool.TaskPoolProperty; +import lombok.extern.slf4j.Slf4j; +import org.apache.pdfbox.Loader; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.rendering.PDFRenderer; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadPoolExecutor; + +@Slf4j +@SpringBootTest +public class pdf2Img { + + @Autowired + private MinioUtil minioUtil; + @Test + public void cherrytest(){ + List list = new ArrayList<>(); + for(int i = 0; i < 699;i++){ + if(i%20 == 0 || i == 699 -1){ + list.add(i); + //log.info("调用"); + System.out.println(list); + list.clear(); + }else{ + list.add(i); + } + } + } + @Test + public void p2i(){ + ThreadPoolExecutor threadPoolExecutor = ExecutorUtil.getThreadPool(new TaskPoolProperty(), TaskPoolProperty.THREAD_POOL_EXECUTOR_PREFIX); + + List>> futureList = new ArrayList<>(); + long startTime = System.currentTimeMillis(); + + try { + // 指定PDF文件路径 + String pdfFilePath = "d:/20221121/2.pdf"; + // 加载PDF文档 + PDDocument document = Loader.loadPDF(new File(pdfFilePath)); + // 设置图像分辨率(DPI) + int dpi = 300; // 这里设置为300 DPI,你可以根据需要调整 + // 创建PDFRenderer对象 + //PDFRenderer pdfRenderer = new PDFRenderer(document); + // 设置渲染的缩放比例 + float scale = dpi / 72f; + // 遍历每一页并将其转换为图片 + int pdfPage = document.getNumberOfPages(); + document.close(); + //数组 + List pageList= new ArrayList(){{add(0);}}; + for (int pageIndex = 1; pageIndex < pdfPage; pageIndex++) { + + if(pageIndex % 10 == 0 || pageIndex == document.getNumberOfPages() -1){ + pageList.add(pageIndex); + futureList.add(threadPoolExecutor.submit(new Pdf2ImgCallable(pageList,pdfFilePath,minioUtil))); + pageList = new ArrayList<>(); + }else{ + pageList.add(pageIndex); + + } + + // 渲染指定页的PDF为BufferedImage + //BufferedImage image = pdfRenderer.renderImage(pageIndex,scale); + // 生成图片文件名 + //String outputImagePath = "d:/20221121/1pdf/" + (pageIndex + 1) + ".png"; + // 保存图片到文件 + //ImageIO.write(image, "PNG", new File(outputImagePath)); + } + + boolean flag = true; + String errorMsg = ""; + Integer sum = 0; + for (Future> future : futureList) { + try { + future.get(); + } catch (Exception e) { + log.error("线程错误信息 ===> ", e); + flag = false; + errorMsg = e.getMessage(); + } + } + } catch (IOException e) { + e.printStackTrace(); + }finally { + threadPoolExecutor.shutdown(); + while (!threadPoolExecutor.isTerminated()) { + // 当前线程池是否全部完成:方案二:添加计数器 + } + } + } + +}