提交 39f37d43 编写于 作者: L lsh

pc web端拦截器,登录代码完成

上级 62cd0b74
......@@ -18,7 +18,7 @@
**<p align="center">【📣最近通知】还有什么想要产品/技术上友好的建议或意见,请跟我们联系,将纳入开源贡献者并官网致谢,还会收到社区奖励的小礼品哦!~</p>**
**<p align="center">管店云 V2.0 正式发布啦,源代码会陆续发布出来,欢迎大家提前体验!<a href="https://guanxdian.cn/demo" target="_blank">点击立即体验~</a></p>**
**<p align="center">管店云 V2.0 正式发布啦,源代码会陆续发布出来,欢迎大家提前体验!<a href="https://www.guanxdian.com" target="_blank">点击立即体验~</a></p>**
**<p align="center">如果您觉得我们的开源项目很有帮助,请点击 :star: Star 支持 管店云 开源团队:heart:</p>**
......@@ -81,7 +81,7 @@
## 2.1 在线体验
开源演示地址:[https://guanxdian.cn/demo](https://guanxdian.cn/demo)
开源演示地址:[https://www.guanxdian.com](https://www.guanxdian.com)
默认账号密码:添加微信领取 `guanxdian`
......
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bytechainx.psi</groupId>
<artifactId>psi-opensource</artifactId>
<version>2.1.0</version>
</parent>
<artifactId>psi-common</artifactId>
<packaging>jar</packaging>
<name>psi-common</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- jfinal -->
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>jfinal</artifactId>
<version>5.1.1</version>
</dependency>
<!-- jfinal-undertow 开发、部署一体化 web 服务器 -->
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>jfinal-undertow</artifactId>
<version>2.8</version>
</dependency>
<!-- 开发 WebSockets 时开启下面的依赖 -->
<!-- <dependency> <groupId>io.undertow</groupId> <artifactId>undertow-websockets-jsr</artifactId>
<version>2.0.32.Final</version> </dependency> -->
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>jfinal-weixin</artifactId>
<version>3.4</version>
</dependency>
<!-- cos 文件上传 -->
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>cos</artifactId>
<version>2022.2</version>
</dependency>
<!-- junit 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.java-websocket/Java-WebSocket -->
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.6</version>
</dependency>
<!-- log4j 日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
<!-- ehcache 缓存 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.11</version>
</dependency>
<!-- druid 数据源连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
<!-- log4j 日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- mysql 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
<dependency>
<groupId>de.ruedigermoeller</groupId>
<artifactId>fst</artifactId>
<version>2.29</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.68</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.6.8</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>17.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.28</version>
</dependency>
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.github.heqiao2010</groupId>
<artifactId>lunar</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.huifu.adapay.core/adapay-core-sdk -->
<dependency>
<groupId>com.huifu.adapay.core</groupId>
<artifactId>adapay-core-sdk</artifactId>
<version>1.2.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.huifu.adapay/adapay-java-sdk -->
<dependency>
<groupId>com.huifu.adapay</groupId>
<artifactId>adapay-java-sdk</artifactId>
<version>1.2.10</version>
</dependency>
<dependency>
<groupId>com.huifu.adapay</groupId>
<artifactId>adapay-sdk-merchant</artifactId>
<version>1.2.7</version>
<scope>system</scope>
<systemPath>D:/eclipse/Workspaces/Oomph/psi-common/src/main/resources/lib/adapay-sdk-merchant-1.2.7.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.20.RELEASE</version>
</dependency>
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.5</version>
</dependency>
</dependencies>
<build>
<directory>target</directory>
<testOutputDirectory>target/test-classes</testOutputDirectory>
<outputDirectory>target/classes</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<!-- 不包含使用插件在测试完成后再拷贝资源文件过去防止冲突 -->
<excludes>
<exclude>**/*.java</exclude>
</excludes>
<filtering>true</filtering>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
<filtering>true</filtering>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<compilerId>csharp</compilerId>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-csharp</artifactId>
<version>1.6</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<forkMode>once</forkMode>
<argLine>-XX:PermSize=256M</argLine>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>2.5</version>
<configuration>
<filesets>
<fileset>
<directory>${basedir}/classes/lib</directory>
<includes>
<include>**/*.jar</include>
</includes>
<followSymlinks>false</followSymlinks>
</fileset>
</filesets>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<!-- Source folder -->
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<defaultGoal>compile</defaultGoal>
</build>
<!-- 使用阿里 maven 库 -->
<repositories>
<repository>
<id>ali-maven</id>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
</repository>
</repositories>
</project>
\ No newline at end of file
#!/bin/bash
# ----------------------------------------------------------------------
#
# 使用说明:
# 1: 该脚本使用前需要首先修改 MAIN_CLASS 值,使其指向实际的启动类
#
# 2:使用命令行 ./jfinal.sh start | stop | restart 可启动/关闭/重启项目
#
# 3: JAVA_OPTS 可通过 -D 传入 undertow.port 与 undertow.host 这类参数覆盖
# 配置文件中的相同值此外还有 undertow.resourcePath、undertow.ioThreads、
# undertow.workerThreads 共五个参数可通过 -D 进行传入,该功能尽可能减少了
# 修改 undertow 配置文件的必要性
#
# 4: JAVA_OPTS 可传入标准的 java 命令行参数,例如 -Xms256m -Xmx1024m 这类常用参数
#
# 5: 函数 start() 给出了 4 种启动项目的命令行,根据注释中的提示自行选择合适的方式
#
# ----------------------------------------------------------------------
# 启动入口类,该脚本文件用于别的项目时要改这里
MAIN_CLASS=com.bytechainx.psi.core.App
if [[ "$MAIN_CLASS" == "com.yourpackage.YourMainClass" ]]; then
echo "请先修改 MAIN_CLASS 的值为你自己项目启动Class,然后再执行此脚本。"
exit 0
fi
COMMAND="$1"
if [[ "$COMMAND" != "start" ]] && [[ "$COMMAND" != "stop" ]] && [[ "$COMMAND" != "restart" ]]; then
echo "Usage: $0 start | stop | restart"
exit 0
fi
# Java 命令行参数,根据需要开启下面的配置,改成自己需要的,注意等号前后不能有空格
# JAVA_OPTS="-Xms256m -Xmx1024m -Dundertow.port=80 -Dundertow.host=0.0.0.0"
# JAVA_OPTS="-Dundertow.port=80 -Dundertow.host=0.0.0.0"
# 生成 class path 值
APP_BASE_PATH=$(cd `dirname $0`; pwd)
CP=${APP_BASE_PATH}/config:${APP_BASE_PATH}/lib/*
function start()
{
# 运行为后台进程,并在控制台输出信息
java -Xverify:none ${JAVA_OPTS} -cp ${CP} ${MAIN_CLASS} &
# 运行为后台进程,并且不在控制台输出信息
# nohup java -Xverify:none ${JAVA_OPTS} -cp ${CP} ${MAIN_CLASS} >/dev/null 2>&1 &
# 运行为后台进程,并且将信息输出到 output.log 文件
# nohup java -Xverify:none ${JAVA_OPTS} -cp ${CP} ${MAIN_CLASS} > output.log &
# 运行为非后台进程,多用于开发阶段,快捷键 ctrl + c 可停止服务
# java -Xverify:none ${JAVA_OPTS} -cp ${CP} ${MAIN_CLASS}
}
function stop()
{
# 支持集群部署
kill `pgrep -f ${APP_BASE_PATH}` 2>/dev/null
# kill 命令不使用 -9 参数时,会回调 onStop() 方法,确定不需要此回调建议使用 -9 参数
# kill `pgrep -f ${MAIN_CLASS}` 2>/dev/null
# 以下代码与上述代码等价
# kill $(pgrep -f ${MAIN_CLASS}) 2>/dev/null
}
if [[ "$COMMAND" == "start" ]]; then
start
elif [[ "$COMMAND" == "stop" ]]; then
stop
else
stop
start
fi
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
<!--
assembly 打包配置更多配置可参考官方文档:
http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html
-->
<id>release</id>
<!--
设置打包格式,可同时设置多种格式,常用格式有:dir、zip、tar、tar.gz
dir 格式便于在本地测试打包结果
zip 格式便于 windows 系统下解压运行
tar、tar.gz 格式便于 linux 系统下解压运行
-->
<formats>
<format>dir</format>
<format>zip</format>
<!-- <format>tar.gz</format> -->
</formats>
<!-- 打 zip 设置为 true 时,会在 zip 包中生成一个根目录,打 dir 时设置为 false 少层目录 -->
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<!-- src/main/resources 全部 copy 到 config 目录下 -->
<fileSet>
<directory>${basedir}/src/main/resources</directory>
<outputDirectory>config</outputDirectory>
</fileSet>
<!-- WebContent 全部 copy 到 webapp 目录下 -->
<fileSet>
<directory>${basedir}/src/main/webapp</directory>
<outputDirectory>webapp</outputDirectory>
<excludes>
<!-- **/* 前缀用法,可以匹配所有路径,例如:**/*.txt -->
<exclude>WEB-INF</exclude>
<exclude>WEB-INF/web.xml</exclude>
</excludes>
</fileSet>
<!-- 项目根下面的脚本文件 copy 到根目录下 -->
<fileSet>
<directory>${basedir}</directory>
<outputDirectory></outputDirectory>
<!-- 脚本文件在 linux 下的权限设为 755,无需 chmod 可直接运行 -->
<fileMode>755</fileMode>
<lineEnding>unix</lineEnding>
<includes>
<include>*.sh</include>
</includes>
</fileSet>
<fileSet>
<directory>${basedir}</directory>
<outputDirectory></outputDirectory>
<fileMode>755</fileMode>
<lineEnding>windows</lineEnding>
<includes>
<include>*.bat</include>
</includes>
</fileSet>
<!-- 项目 lib 目录下的本地 jar 包全部 copy 到 lib 目录下 -->
<!-- fileSet>
<directory>${basedir}/lib</directory>
<outputDirectory>lib</outputDirectory>
</fileSet -->
</fileSets>
<!-- 依赖的 jar 包 copy 到 lib 目录下 -->
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bytechainx.psi</groupId>
<artifactId>psi-opensource</artifactId>
<version>2.1.0</version>
</parent>
<artifactId>psi-web</artifactId>
<packaging>jar</packaging>
<name>psi-web</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>
<dependencies>
<dependency>
<groupId>com.bytechainx.psi</groupId>
<artifactId>psi-fund</artifactId>
<version>2.1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.bytechainx.psi</groupId>
<artifactId>psi-sale</artifactId>
<version>2.1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.bytechainx.psi</groupId>
<artifactId>psi-purchase</artifactId>
<version>2.1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.alchim31.maven</groupId>
<artifactId>yuicompressor-maven-plugin</artifactId>
<version>1.5.1</version>
</dependency>
</dependencies>
<build>
<!-- 添加 includes 配置后,excludes 默认为所有文件 **/*.*,反之亦然 该规则在 maven-jar-plugin
等插件中同样适用 -->
<resources>
<!-- 添加该配置是为了将 .sql 文件打入 jar 包 -->
<resource>
<directory>src/main/java</directory>
<includes>
<!-- **/* 前缀用法,可以匹配所有路径 -->
<include>**/*.sql</include>
</includes>
</resource>
<!-- 没有添加 resources 配置时,src/main/resources 目录是默认配置 一旦添加 resources 配置指向
src/main/java 目录时,原先的默认配置被取代, 所以需要添加如下配置将默认配置再添加进来,否则无法使用 src/main/resources
下的资源文件 -->
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<!-- java8 保留参数名编译参数 -->
<compilerArgument>-parameters</compilerArgument>
<compilerArguments>
<verbose />
</compilerArguments>
</configuration>
</plugin>
<!-- jar 包中的配置文件优先级高于 config 目录下的 "同名文件" 因此,打包时需要排除掉 jar 包中来自 src/main/resources
目录的 配置文件,否则部署时 config 目录中的同名配置文件不会生效 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<excludes>
<!-- *.* 用法,可以匹配 jar 包根目录下所有文件 *.xxx 用法,可以匹配 jar 包根目录下特定扩展名文件,例如:*.xml
**/* 前缀用法,可以匹配所有路径,例如:**/*.txt -->
<exclude>*.*</exclude>
</excludes>
</configuration>
</plugin>
<!-- 使用 mvn clean package 打包 更多配置可参考官方文档:http://maven.apache.org/plugins/maven-assembly-plugin/single-mojo.html -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<!-- 打包生成的文件名 -->
<finalName>${project.artifactId}</finalName>
<!-- jar 等压缩文件在被打包进入 zip、tar.gz 时是否压缩,设置为 false 可加快打包速度 -->
<recompressZippedFiles>false</recompressZippedFiles>
<!-- 打包生成的文件是否要追加 package.xml 中定义的 id 值 -->
<appendAssemblyId>true</appendAssemblyId>
<!-- 指向打包描述文件 package.xml -->
<descriptors>
<descriptor>package.xml</descriptor>
</descriptors>
<!-- 打包结果输出的基础目录 -->
<outputDirectory>${project.build.directory}/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- JavaScript CSS Compress -->
<plugin>
<groupId>com.samaxes.maven</groupId>
<artifactId>minify-maven-plugin</artifactId>
<version>1.7.6</version>
<executions>
<execution>
<id>default-minify</id>
<configuration>
<webappTargetDir>${project.build.directory}/classes</webappTargetDir>
<charset>UTF-8</charset>
<closureWarningLevels>
<es5Strict>OFF</es5Strict>
</closureWarningLevels>
<cssSourceDir>src/main/webapp/resources</cssSourceDir>
<!--将压缩后的css文件放到以下目录下-->
<cssTargetDir>../static</cssTargetDir>
<cssIncludes>
<cssInclude>**/*.css</cssInclude>
</cssIncludes>
<cssExcludes>
<cssExclude>**/*.min.css</cssExclude>
<jsExclude>**/barQrCode/**</jsExclude>
<jsExclude>**/bootstrap/**</jsExclude>
<jsExclude>**/echarts/**</jsExclude>
<jsExclude>**/jquery/**</jsExclude>
<jsExclude>**/jquery-color/**</jsExclude>
<jsExclude>**/jQuery-contextMenu/**</jsExclude>
<jsExclude>**/layer/**</jsExclude>
<jsExclude>**/My97DatePicker/**</jsExclude>
<jsExclude>**/wangeditor/**</jsExclude>
</cssExcludes>
<!-- 压缩src/main/resources/static目录下的所有js文件,但是排除*.min.js文件; -->
<jsSourceDir>src/main/webapp/resources</jsSourceDir>
<!--将压缩后的js文件放到以下目录下-->
<jsTargetDir>../static</jsTargetDir>
<jsIncludes>
<jsInclude>**/*.js</jsInclude>
</jsIncludes>
<jsExcludes>
<jsExclude>**/*.min.js</jsExclude>
<jsExclude>**/jquery-ui.js</jsExclude>
<jsExclude>**/barQrCode/**</jsExclude>
<jsExclude>**/bootstrap/**</jsExclude>
<jsExclude>**/echarts/**</jsExclude>
<jsExclude>**/jquery/**</jsExclude>
<jsExclude>**/jquery-color/**</jsExclude>
<jsExclude>**/jQuery-contextMenu/**</jsExclude>
<jsExclude>**/layer/**</jsExclude>
<jsExclude>**/My97DatePicker/**</jsExclude>
<jsExclude>**/wangeditor/**</jsExclude>
</jsExcludes>
<!-- 使用closure压缩时的压缩级别,默认值为SIMPLE_OPTIMIZATIONS。可选值: -->
<!-- WHITESPACE_ONLY:只压缩空格和转换一些特殊符号 -->
<!-- SIMPLE_OPTIMIZATIONS:简单的压缩 -->
<!-- ADVANCED_OPTIMIZATIONS:高级压缩,此压缩方式下可能会将引用的第3方框架的方法名称修改,导致js报错;慎用。 -->
<closureCompilationLevel>SIMPLE_OPTIMIZATIONS</closureCompilationLevel>
<webappSourceDir>${project.basedir}</webappSourceDir>
<!-- js压缩引擎,默认值为YUI。可选值: -->
<!-- YUI: 使用YUI Compressor压缩; -->
<!-- CLOSURE: 使用Google Closure Compiler压缩 -->
<jsEngine>CLOSURE</jsEngine>
<skipMerge>true</skipMerge><!-- 不合并js/css -->
<nosuffix>true</nosuffix><!-- 压缩后的文件不.js前添加.min前缀 -->
</configuration>
<goals>
<goal>minify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!-- 使用阿里 maven 库 -->
<repositories>
<repository>
<id>ali-maven</id>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
</repository>
</repositories>
</project>
\ No newline at end of file
/**
*
*/
package com.bytechainx.psi.web.web.controller;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import com.bytechainx.psi.common.CommonConstant;
import com.bytechainx.psi.common.EnumConstant.AuditStatusEnum;
import com.bytechainx.psi.common.EnumConstant.DataStatusEnum;
import com.bytechainx.psi.common.EnumConstant.MsgTypeEnum;
import com.bytechainx.psi.common.EnumConstant.OrderPayStatusEnum;
import com.bytechainx.psi.common.EnumConstant.OrderStatusEnum;
import com.bytechainx.psi.common.EnumConstant.StockWarnTypeEnum;
import com.bytechainx.psi.common.EnumConstant.UserActiveStatusEnum;
import com.bytechainx.psi.common.Permissions;
import com.bytechainx.psi.common.dto.ConditionFilter;
import com.bytechainx.psi.common.dto.ConditionFilter.Operator;
import com.bytechainx.psi.common.dto.UserSession;
import com.bytechainx.psi.common.kit.DateUtil;
import com.bytechainx.psi.common.model.GoodsPrice;
import com.bytechainx.psi.common.model.InventoryStock;
import com.bytechainx.psi.common.model.MsgNotice;
import com.bytechainx.psi.common.model.MsgNoticeSend;
import com.bytechainx.psi.common.model.PurchaseOrder;
import com.bytechainx.psi.common.model.SaleOrder;
import com.bytechainx.psi.common.model.SaleOrderGoods;
import com.bytechainx.psi.common.model.TenantAdmin;
import com.bytechainx.psi.common.model.TraderBalanceAccount;
import com.bytechainx.psi.common.service.msg.MsgNoticeService;
import com.bytechainx.psi.purchase.service.PurchaseBookOrderService;
import com.bytechainx.psi.purchase.service.PurchaseOrderService;
import com.bytechainx.psi.purchase.service.StatPurchaseService;
import com.bytechainx.psi.purchase.service.StockGoodsQualityService;
import com.bytechainx.psi.purchase.service.StockInfoService;
import com.bytechainx.psi.purchase.service.StockWarehouseService;
import com.bytechainx.psi.sale.service.SaleBookOrderService;
import com.bytechainx.psi.sale.service.SaleOrderService;
import com.bytechainx.psi.sale.service.StatHotSaleService;
import com.bytechainx.psi.sale.service.StatSaleService;
import com.bytechainx.psi.web.web.controller.base.BaseController;
import com.bytechainx.psi.web.web.interceptor.PermissionInterceptor;
import com.jfinal.aop.Clear;
import com.jfinal.aop.Inject;
import com.jfinal.core.Path;
import com.jfinal.kit.Kv;
import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.ehcache.CacheKit;
import com.jfinal.plugin.redis.Cache;
import com.jfinal.plugin.redis.Redis;
/**
* 首页
* @author defier
*/
@Path("/dashboard")
public class DashboardController extends BaseController {
@Inject
private MsgNoticeService msgNoticeService;
@Inject
private StockWarehouseService warehouseService;
@Inject
private StatSaleService statSaleService;
@Inject
private SaleBookOrderService saleBookOrderService;
@Inject
private SaleOrderService saleOrderService;
@Inject
private PurchaseBookOrderService purchaseBookOrderService;
@Inject
private PurchaseOrderService purchaseOrderService;
@Inject
private StockInfoService stockInfoService;
@Inject
private StockGoodsQualityService stockGoodsQualityService;
@Inject
private StatPurchaseService statPurchaseService;
@Inject
private StatHotSaleService statHotSaleService;
public void index() {
}
public void home() {
UserSession session = getUserSession();
SaleOrder todaySaleStat = CacheKit.get(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.todaySaleStat");
if(todaySaleStat == null) {
todaySaleStat = statSaleService.sumByCustomer(null, null, DateUtil.getDayStr(new Date())+" 00:00:00", DateUtil.getSecondStr(new Date()));
CacheKit.put(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.todaySaleStat", todaySaleStat);
}
SaleOrder yesterdaySaleStat = CacheKit.get(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.yesterdaySaleStat");
if(yesterdaySaleStat == null) {
yesterdaySaleStat = statSaleService.sumByCustomer(null, null, DateUtil.getDayStr(DateUtil.daysAddOrSub(new Date(),-1))+" 00:00:00", DateUtil.getDayStr(DateUtil.daysAddOrSub(new Date(),-1))+" 23:59:59");
CacheKit.put(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.yesterdaySaleStat", yesterdaySaleStat);
}
SaleOrder monthSaleStat = CacheKit.get(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.monthSaleStat");
if(monthSaleStat == null) {
monthSaleStat = statSaleService.sumByCustomer(null, null, DateUtil.getMonthFirstDay()+" 00:00:00", DateUtil.getMonthLastDay()+" 23:59:59");
CacheKit.put(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.monthSaleStat", monthSaleStat);
}
SaleOrder preMonthSaleStat = CacheKit.get(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.preMonthSaleStat");
if(preMonthSaleStat == null) {
preMonthSaleStat = statSaleService.sumByCustomer(null, null, DateUtil.getPreMonthFirstDay()+" 00:00:00", DateUtil.getPreMonthLastDay()+" 23:59:59");
CacheKit.put(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.preMonthSaleStat", preMonthSaleStat);
}
setAttr("todaySaleStat", todaySaleStat);
setAttr("yesterdaySaleStat", yesterdaySaleStat);
setAttr("monthSaleStat", monthSaleStat);
setAttr("preMonthSaleStat", preMonthSaleStat);
// 待收款销售单
Page<SaleOrder> saleOrderPage = CacheKit.get(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.saleOrderPage");
if(saleOrderPage == null) {
Kv condKv = Kv.create();
conditionFilterStore(condKv, Permissions.sale_sale); // 添加门店过滤条件
condKv.set("order_status", OrderStatusEnum.normal.getValue());
condKv.set("audit_status", AuditStatusEnum.pass.getValue());
ConditionFilter filter = new ConditionFilter();
filter.setOperator(Operator.neq);
filter.setValue(OrderPayStatusEnum.finish.getValue());
condKv.set("pay_status", filter);
saleOrderPage = saleOrderService.paginate(null, null, condKv, 1, pageSize);
CacheKit.put(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.saleOrderPage", saleOrderPage);
}
// 待付款进货单
Page<PurchaseOrder> purchaseOrderPage = CacheKit.get(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.purchaseOrderPage");
if(purchaseOrderPage == null) {
Kv condKv = Kv.create();
conditionFilterStore(condKv, Permissions.sale_sale); // 添加门店过滤条件
condKv.set("order_status", OrderStatusEnum.normal.getValue());
condKv.set("audit_status", AuditStatusEnum.pass.getValue());
ConditionFilter filter = new ConditionFilter();
filter.setOperator(Operator.neq);
filter.setValue(OrderPayStatusEnum.finish.getValue());
condKv.set("pay_status", filter);
purchaseOrderPage = purchaseOrderService.paginate(null, null, condKv, 1, pageSize);
CacheKit.put(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.purchaseOrderPage", purchaseOrderPage);
}
// 库存预警
Page<InventoryStock> stockInfoPage = CacheKit.get(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.stockInfoPage");
if(stockInfoPage == null) {
Kv condKv = Kv.create();
condKv.set("data_status", DataStatusEnum.enable.getValue());
ConditionFilter filter = new ConditionFilter();
filter.setOperator(Operator.neq);
filter.setValue(StockWarnTypeEnum.ok.getValue());
condKv.set("warn_type", filter);
stockInfoPage = stockInfoService.paginate(condKv, 1, pageSize);
CacheKit.put(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.stockInfoPage", stockInfoPage);
}
if(session.hasOper(Permissions.sensitiveData_account_stat)) {
//账户余额
TraderBalanceAccount sumTraderBalanceAccount = TraderBalanceAccount.dao.findFirst("select sum(balance) as balance from trader_balance_account where data_status = ?", DataStatusEnum.enable.getValue());
// 库存总成本
BigDecimal sumStockAmount = CacheKit.get(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.sumStockAmount");
if(sumStockAmount == null) {
List<InventoryStock> sumInventoryStock = InventoryStock.dao.find("select goods_info_id,spec_1_id,spec_option_1_id,spec_2_id,spec_option_2_id,spec_3_id,spec_option_3_id,unit_id,sum(stock) as stock from inventory_stock where data_status = ? group by goods_info_id,spec_1_id,spec_option_1_id,spec_2_id,spec_option_2_id,spec_3_id,spec_option_3_id,unit_id", DataStatusEnum.enable.getValue());
sumStockAmount = BigDecimal.ZERO; // 库存成本
for (InventoryStock inventoryStock : sumInventoryStock) {
GoodsPrice price = inventoryStock.getGoodsPrice();
if(price == null) {
continue;
}
sumStockAmount = sumStockAmount.add(price.getAvgCostPrice().multiply(inventoryStock.getStock()));
}
CacheKit.put(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.sumStockAmount", sumStockAmount);
}
// 应收欠款
SaleOrder sumSaleReceipt = CacheKit.get(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.sumSaleReceipt");
if(sumSaleReceipt == null) {
sumSaleReceipt = statSaleService.sumByCustomer(null, null, null, null);
CacheKit.put(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.sumSaleReceipt", sumSaleReceipt);
}
// 应付欠款
PurchaseOrder sumPurchasePay = CacheKit.get(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.sumPurchasePay");
if(sumPurchasePay == null) {
sumPurchasePay = statPurchaseService.sumBySupplier(null, null, null, null);
CacheKit.put(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.sumPurchasePay", sumPurchasePay);
}
setAttr("sumBalance", sumTraderBalanceAccount.getBalance());
setAttr("sumBalance", sumTraderBalanceAccount.getBalance());
setAttr("sumStockAmount", sumStockAmount);
setAttr("sumSaleReceipt", sumSaleReceipt);
setAttr("sumPurchasePay", sumPurchasePay);
}
setAttr("waitingPaySaleOrderCount", saleOrderPage.getTotalRow());
setAttr("waitingPayPurchaseOrderCount", purchaseOrderPage.getTotalRow());
setAttr("stockInfoWarnCount", stockInfoPage.getTotalRow());
}
/**
* 统计销售量,按天统计,年度按月统计
*/
public void loadSaleStatByDay() {
Integer days = getInt("days"); // 30:近30天,90:近一季度, 365:近1年
if(days == null) {
renderJson(Ret.fail("参数非法"));
}
List<SaleOrder> saleStatList = CacheKit.get(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.loadSaleStatByDay.saleStatList."+days);
List<Date> saleStatDayList = CacheKit.get(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.loadSaleStatByDay.saleStatDayList."+days);
if(saleStatList == null) {
saleStatList = new ArrayList<>();
saleStatDayList = new ArrayList<>();
int time = days;
if(days == 365) {
time = 12;// 12个月,按月统计
}
for (int beforeDay = time-1; beforeDay >= 0; beforeDay--) {
Date dayDate = DateUtil.daysAddOrSubNow(-beforeDay);
String startTime = DateUtil.getDayStr(dayDate)+" 00:00:00";
String endTime = DateUtil.getDayStr(dayDate)+" 23:59:59";
if(days == 365) {
dayDate = DateUtil.getYearMonthDate(DateUtil.monthsAddOrSub(new Date(), -beforeDay));
startTime = DateUtil.getMonthFirstDay(dayDate)+" 00:00:00";
endTime = DateUtil.getMonthLastDay(dayDate)+" 23:59:59";
}
SaleOrder saleStat = statSaleService.sumByCustomer(null, null, startTime, endTime);
saleStatList.add(saleStat);
saleStatDayList.add(dayDate);
}
CacheKit.put(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.loadSaleStatByDay.saleStatList."+days, saleStatList);
CacheKit.put(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.loadSaleStatByDay.saleStatDayList."+days, saleStatDayList);
}
setAttr("saleStatList", saleStatList);
setAttr("saleStatDayList", saleStatDayList);
setAttr("days", days);
}
/**
* 统计销售量,按天统计,年度按月统计
*/
public void loadGoodsStatByDay() {
Integer days = getInt("days"); // 30:近30天,90:近一季度, 365:近1年
if(days == null || days > 365) {
renderJson(Ret.fail("参数非法"));
}
Page<SaleOrderGoods> goodsStatPage = CacheKit.get(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.loadGoodsStatByDay.goodsStatList."+days);
if(goodsStatPage == null) {
Date dayDate = DateUtil.daysAddOrSubNow(-days);
String startTime = DateUtil.getDayStr(dayDate)+" 00:00:00";
String endTime = DateUtil.getDayStr(new Date())+" 23:59:59";
goodsStatPage = statHotSaleService.paginate(null, startTime, endTime, 1, 16);
// 升序排序
Collections.sort(goodsStatPage.getList(), Comparator.comparing(SaleOrderGoods::getBuyNumber));
CacheKit.put(CommonConstant.CACHE_NAME_ONE_MINUTE_STORE, "home.stat.loadGoodsStatByDay.goodsStatList."+days, goodsStatPage);
}
setAttr("goodsStatList", goodsStatPage.getList());
}
/**
* 检测请求执行结果
*/
public void checkRequestResult() {
String requestId = get("request_id");
if(StringUtils.isEmpty(requestId)) {
renderJson(Ret.fail("非法请求..."));
return;
}
Cache redis = Redis.use();
String response = redis.lpop(requestId);
if(response == null) {
renderJson(Ret.fail("waiting"));
return;
}
renderJson(response);
}
/**
* 心跳
*/
public void heartBeat() {
TenantAdmin tenantAdmin = getCurrentAdmin();
if(tenantAdmin.getActiveStatus() != UserActiveStatusEnum.enable.getValue()) {
tenantAdmin = TenantAdmin.dao.findById(tenantAdmin.getId()); // 避免缓存没有更新
if(tenantAdmin.getActiveStatus() != UserActiveStatusEnum.enable.getValue()) {
removeSessionAttr(CommonConstant.SESSION_ID_KEY);
renderJson(Ret.fail("用户状态异常"));
return;
}
}
UserSession session = getUserSession();
session.setHeartTime(new Date());
// 重要的消息需要再右下角弹窗,紧急的直接居中弹窗。
Page<MsgNoticeSend> noticePage = msgNoticeService.paginate(getAdminId(), false, 1, 10);
Ret ret = Ret.ok();
if(noticePage.getTotalRow() > 0) {
for (MsgNoticeSend msg : noticePage.getList()) {
MsgNotice msgNotice = msg.getMsgNotice();
msg.put("msg_level", msgNotice.getMsgLevel());
msg.put("msg_type_name", MsgTypeEnum.getEnum(msgNotice.getMsgType()).getName());
msg.put("title", msgNotice.getTitle());
}
ret.set("noticePage", noticePage);// FIXME 单独一个待办事项???待审核销售单、进货单,销售订单预计发货到期、这些都要且只要生成一条消息到消息通知表
}
tenantAdmin.setOnlineTimes(tenantAdmin.getOnlineTimes()+2); // 心跳2分钟一次
tenantAdmin.setUpdatedAt(new Date());
tenantAdmin.update();
renderJson(ret);
}
/**
* 客服
*/
@Clear(PermissionInterceptor.class)
public void service() {
}
}
/**
*
*/
package com.bytechainx.psi.web.web.controller;
import java.util.Date;
import com.bytechainx.psi.common.EnumConstant.ExportStatusEnum;
import com.bytechainx.psi.common.model.TenantExportLog;
import com.bytechainx.psi.common.service.export.ExportLogService;
import com.bytechainx.psi.web.web.controller.base.BaseController;
import com.jfinal.aop.Inject;
import com.jfinal.core.Path;
import com.jfinal.plugin.activerecord.Page;
/**
* 导出任务信息
* @author defier
*/
@Path("/export/log")
public class ExportLogController extends BaseController {
@Inject
private ExportLogService exportLogService;
public void index() {
keepPara("targetId");
}
public void list() {
int pageNumber = getInt("pageNumber", 1);
pageSize = getPageSize();
Page<TenantExportLog> page = exportLogService.paginate(getAdminId(), pageNumber, pageSize);
for (TenantExportLog exportLog : page.getList()) {
if(exportLog.getExportStatus() == ExportStatusEnum.ing.getValue() && exportLog.getCreatedAt().getTime() + (10*60*1000) <= System.currentTimeMillis()) {
exportLog.setExportStatus(ExportStatusEnum.fail.getValue());
exportLog.setErrorDesc("导出超时");
exportLog.setUpdatedAt(new Date());
exportLog.update();
}
}
setAttr("page", page);
keepPara("targetId");
}
}
/**
*
*/
package com.bytechainx.psi.web.web.controller;
import com.bytechainx.psi.common.kit.FileKit;
import com.bytechainx.psi.web.config.AppConfig;
import com.bytechainx.psi.web.web.controller.base.BaseController;
import com.jfinal.core.Path;
import com.jfinal.kit.Kv;
import com.jfinal.kit.Ret;
import com.jfinal.upload.UploadFile;
/**
* 上传文件
* @author defier
*/
@Path("/upload")
public class UploadController extends BaseController {
public void index() {
UploadFile uploadFile = getFile();
if(uploadFile == null) {
renderJson(Ret.fail("上传文件不存在"));
return;
}
Ret ret = FileKit.uploadImage(uploadFile, AppConfig.resourceUploadPath);
//return Ret.ok().set("filePath", filePath).set("thumbPath", thumbPath);
renderJson(ret);
}
/**
* wangeditor编辑器文件上传接口
*/
public void wangeditorApi() {
UploadFile uploadFile = getFile();
if(uploadFile == null) {
renderJson(Ret.fail("上传文件不存在"));
return;
}
Ret ret = FileKit.uploadImage(uploadFile, AppConfig.resourceUploadPath);
//return Ret.ok().set("filePath", filePath).set("thumbPath", thumbPath);
Kv _ret = Kv.create();
if(ret.isOk()) {
String imgUrl = AppConfig.resourceUploadDomain + ret.getStr("thumbPath");
_ret.set("errno", 0); // 成功
_ret.set("data", Kv.by("url", imgUrl).set("href", imgUrl));
} else {
_ret.set("errno", 1); // 失败
_ret.set("message", ret.getStr("MSG"));
}
renderJson(_ret);
}
}
package com.bytechainx.psi.web.web.controller.account;
import java.util.Date;
import org.apache.commons.lang.StringUtils;
import com.bytechainx.psi.common.CommonConstant;
import com.bytechainx.psi.common.EnumConstant.UserActiveStatusEnum;
import com.bytechainx.psi.common.dto.SmsCodeDto;
import com.bytechainx.psi.common.kit.CipherkeyUtil;
import com.bytechainx.psi.common.kit.SmsKit;
import com.bytechainx.psi.common.model.TenantAdmin;
import com.bytechainx.psi.common.service.setting.TenantAdminService;
import com.bytechainx.psi.web.web.controller.base.BaseController;
import com.bytechainx.psi.web.web.interceptor.PermissionInterceptor;
import com.jfinal.aop.Before;
import com.jfinal.aop.Clear;
import com.jfinal.aop.Inject;
import com.jfinal.core.Path;
import com.jfinal.kit.Ret;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.tx.Tx;
/**
* 帐户登录
*/
@Path("/account")
public class AccountController extends BaseController {
private static final Log LOG = Log.getLog(AccountController.class);
@Inject
private TenantAdminService tenantAdminService;
/**
* 查看账户
*/
public void edit() {
TenantAdmin currentAdmin = getCurrentAdmin();
currentAdmin.remove("password", "encrypt");
setAttr("account", currentAdmin);
}
/**
* 修改
*/
@Before(Tx.class)
public void update() {
String realName = get("real_name");
String mobile = get("mobile");
if(StringUtils.isEmpty(realName)) {
renderJson(Ret.fail("真实姓名不能为空"));
}
if(StringUtils.isEmpty(mobile)) {
renderJson(Ret.fail("手机号不能为空"));
}
TenantAdmin currentAdmin = getCurrentAdmin();
currentAdmin.setRealName(realName);
currentAdmin.setMobile(mobile);
Ret ret = tenantAdminService.update(currentAdmin);
if(ret.isOk()) {
getUserSession().setRealName(realName);
}
renderJson(ret);
}
/**
* 修改密码
*/
public void editPwd() {
}
/**
* 修改密码
*/
public void updatePwd() {
Ret ret = tenantAdminService.updatePwd(getAdminId(), getPara("old_password"), getPara("new_password"));
renderJson(ret);
}
/**
* 退出
*/
@Clear(PermissionInterceptor.class)
public void logout() {
removeSessionAttr(CommonConstant.SESSION_ID_KEY);
String url = getCookie(CommonConstant.COOKIE_TENANT_URL_CODE);
redirect(url);
}
/**
* 激活帐户
*/
public void activeIndex() {
TenantAdmin currentAdmin = getCurrentAdmin();
currentAdmin.remove("password", "encrypt");
setAttr("currentAdmin", currentAdmin);
}
/**
* 激活帐户
*/
public void active() {
try {
String smsCode = getPara("smsCode");
if (StringUtils.isEmpty(smsCode)) {
renderJson(Ret.fail("验证码不能为空"));
return;
}
SmsCodeDto smsCodeDto = (SmsCodeDto) getSessionAttr(CommonConstant.SESSION_SMS_CODE);
if (smsCodeDto == null) {
renderJson(Ret.fail("无效的短信验证码"));
return;
}
long currentTime = System.currentTimeMillis();
long sendTime = smsCodeDto.getSendTime().getTime();
boolean isOutTime = currentTime - sendTime > 5 * 60 * 1000; // 5分钟超时
if (isOutTime) {
removeSessionAttr(CommonConstant.SESSION_SMS_CODE);
renderJson(Ret.fail("短信验证码超时"));
return;
}
if (!StringUtils.equals(smsCode, smsCodeDto.getCode())) {
renderJson(Ret.fail("短信验证码输入不正确"));
return;
}
String newPwd = getPara("newPwd");
if (StringUtils.isEmpty(newPwd)) {
renderJson(Ret.fail("新密码不能为空"));
return;
}
removeSessionAttr(CommonConstant.SESSION_SMS_CODE);
TenantAdmin admin = TenantAdmin.dao.findById(getAdminId());
String encodePassword = CipherkeyUtil.encodePassword(newPwd, admin.getEncrypt());
admin.setActiveStatus(UserActiveStatusEnum.enable.getValue());
admin.setPassword(encodePassword);
admin.setUpdatedAt(new Date());
admin.update();
renderJson(Ret.ok("激活帐户成功"));
} catch (Exception e) {
LOG.error("激活帐户异常", e);
renderJson(Ret.fail("激活帐户异常:"+e.getMessage()));
}
}
/**
* 发送手机验证码
*/
public void sendActiveCode() {
TenantAdmin admin = getCurrentAdmin();
if (admin == null) {
renderJson(Ret.fail("手机号输入错误"));
return;
}
Ret ret = SmsKit.activeCode(admin.getMobile());
if(ret.isOk()) {
setSessionAttr(CommonConstant.SESSION_SMS_CODE, new SmsCodeDto(ret.getStr("smsCode"), new Date(), admin.getMobile()));
}
renderJson(ret);
}
}
package com.bytechainx.psi.web.web.controller.account;
import java.util.Date;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import com.bytechainx.psi.common.CommonConstant;
import com.bytechainx.psi.common.EnumConstant.FlagEnum;
import com.bytechainx.psi.common.EnumConstant.UserActiveStatusEnum;
import com.bytechainx.psi.common.dto.SmsCodeDto;
import com.bytechainx.psi.common.dto.UserSession;
import com.bytechainx.psi.common.kit.CipherkeyUtil;
import com.bytechainx.psi.common.kit.SmsKit;
import com.bytechainx.psi.common.model.TenantAdmin;
import com.bytechainx.psi.common.model.TenantRole;
import com.bytechainx.psi.common.service.setting.TenantRoleService;
import com.bytechainx.psi.web.config.AppConfig;
import com.bytechainx.psi.web.web.controller.base.BaseController;
import com.bytechainx.psi.web.web.interceptor.PermissionInterceptor;
import com.jfinal.aop.Clear;
import com.jfinal.aop.Inject;
import com.jfinal.core.Path;
import com.jfinal.kit.Ret;
import com.jfinal.log.Log;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpStatus;
/**
* 登录
* @author defier
*
*/
@Clear({PermissionInterceptor.class})
@Path("/")
public class LoginController extends BaseController {
private static final Log LOG = Log.getLog(LoginController.class);
@Inject
private TenantRoleService roleService;
public void index() {
try {
Integer adminId = getAdminId();
if(adminId != null) { // 登录状态,但不是同一个租户,则退出
render("dashboard/index.html");
return;
}
removeSessionAttr(CommonConstant.SESSION_ID_KEY);
setAttr("tenantOrg", getCurrentTenant());
setAttr("version", AppConfig.version);
} catch (Exception e) {
LOG.error("加载租户登录界面异常", e);
renderError(HttpStatus.HTTP_INTERNAL_ERROR);
}
}
/**
* 登录
*/
public void login() {
try {
String mobile = getPara("mobile");
String password = getPara("password");// 密码
String mac = getPara("mac");
if (StringUtils.isEmpty(mobile) || StringUtils.isEmpty(password)) {
renderJson(Ret.fail("手机号或者密码不能为空"));
return;
}
TenantAdmin admin = TenantAdmin.dao.findBy(mobile);
if (admin == null) {
renderJson(Ret.fail("手机号或者密码不正确"));
return;
}
if(admin.getLoginFlag() == FlagEnum.NO.getValue()) {
renderJson(Ret.fail("用户不可登录"));
return;
}
if(admin.getActiveStatus() == UserActiveStatusEnum.disable.getValue()) {
renderJson(Ret.fail("用户已被禁用,无法登录"));
return;
}
if(StringUtils.isNotEmpty(admin.getMac()) && !StringUtils.equalsIgnoreCase(admin.getMac(), mac)) {
renderJson(Ret.fail("当前电脑禁止登录系统"));
return;
}
// 验证密码
String encodePassword = CipherkeyUtil.encodePassword(password, admin.getEncrypt());
if (!StringUtils.equals(admin.getPassword(), encodePassword)) {
renderJson(Ret.fail("手机号或者密码不正确"));
return;
}
// 登录数据换成分两个数据,一个是以用户ID为key,value为sessionid的,一个是以sessionid为key,value为usersession的两个数据
removeOnlineSession(CommonConstant.ONLINE_USER_ID_PC_CACHE, admin.getId());
String ip = ServletUtil.getClientIP(getRequest());
if(admin.getLoginCount() <= 0) {
admin.setFirstLoginIp(ip);
admin.setFirstLoginTime(new Date());
}
admin.setUpdatedAt(new Date());
admin.setLastLoginIp(ip);
admin.setLastLoginTime(new Date());
admin.setLoginCount(admin.getLoginCount()+1);
admin.update();
TenantRole role = admin.getRole();
UserSession session = new UserSession();
session.setTenantAdminId(admin.getId());
session.setSuperFlag(role.getSuperFlag());
session.setHeartTime(new Date());
session.setLoginIp(ip);
session.setRealName(admin.getRealName());
if(!role.getSuperFlag()) { // 非超级管理员,加载权限
Set<String> operCodes = roleService.findOperByRoleId(admin.getRoleId());
session.setOperCodeSet(operCodes);
}
// 用户放入redis
addOnlineSession(CommonConstant.ONLINE_USER_ID_PC_CACHE, admin.getId(), getSession().getId());
setSessionAttr(CommonConstant.SESSION_ID_KEY, session);
LOG.info("用户登录成功, adminId:%s", admin.getId());
if(admin.getActiveStatus() == UserActiveStatusEnum.waiting.getValue()) { // 待激活
renderJson(Ret.ok("首次登录,进入帐户激活...").set("status", UserActiveStatusEnum.waiting.getValue()));
} else {
renderJson(Ret.ok("登录成功,欢迎使用『管店云』进销存系统..."));
}
} catch (Exception e) {
LOG.error("用户登录异常", e);
renderJson(Ret.fail("用户登录异常:"+e.getMessage()));
}
}
/**
* 忘记密码
*/
public void forgetPwd() {
}
/**
* 发送手机验证码
*/
public void sendSmsCode() {
String mobile = getPara("mobile");
if(StringUtils.isEmpty(mobile)) {
renderJson(Ret.fail("手机号不能为空"));
return;
}
TenantAdmin admin = TenantAdmin.dao.findBy(mobile);
if (admin == null) {
renderJson(Ret.fail("手机号输入错误"));
return;
}
Ret ret = SmsKit.forgetPwd(mobile);
if(ret.isOk()) {
setSessionAttr(CommonConstant.SESSION_SMS_CODE, new SmsCodeDto(ret.getStr("smsCode"), new Date(), mobile));
}
renderJson(ret);
}
/**
* 更新密码
*/
public void updatePwd() {
try {
String mobile = getPara("mobile");
if (StringUtils.isEmpty(mobile)) {
renderJson(Ret.fail("手机号不能为空"));
return;
}
String smsCode = getPara("smsCode");
if (StringUtils.isEmpty(smsCode)) {
renderJson(Ret.fail("验证码不能为空"));
return;
}
SmsCodeDto smsCodeDto = (SmsCodeDto) getSessionAttr(CommonConstant.SESSION_SMS_CODE);
if (smsCodeDto == null) {
renderJson(Ret.fail("无效的短信验证码"));
return;
}
long currentTime = System.currentTimeMillis();
long sendTime = smsCodeDto.getSendTime().getTime();
boolean isOutTime = currentTime - sendTime > 5 * 60 * 1000; // 5分钟超时
if (isOutTime) {
removeSessionAttr(CommonConstant.SESSION_SMS_CODE);
renderJson(Ret.fail("短信验证码超时"));
return;
}
if (!StringUtils.equals(smsCode, smsCodeDto.getCode())) {
renderJson(Ret.fail("短信验证码输入不正确"));
return;
}
String newPwd = getPara("newPwd");
if (StringUtils.isEmpty(newPwd)) {
renderJson(Ret.fail("新密码不能为空"));
return;
}
TenantAdmin admin = TenantAdmin.dao.findBy(mobile);
if (admin == null) {
renderJson(Ret.fail("手机号输入错误"));
return;
}
removeSessionAttr(CommonConstant.SESSION_SMS_CODE);
String encodePassword = CipherkeyUtil.encodePassword(newPwd, admin.getEncrypt());
admin.setPassword(encodePassword);
admin.setUpdatedAt(new Date());
admin.update();
renderJson(Ret.ok("修改密码成功"));
} catch (Exception e) {
LOG.error("修改用户密码异常", e);
renderJson(Ret.fail("修改用户密码异常:"+e.getMessage()));
}
}
}
package com.bytechainx.psi.web.web.interceptor;
import java.lang.reflect.Method;
import java.util.Date;
import org.apache.commons.lang.StringUtils;
import com.bytechainx.psi.common.EnumConstant.OperLogTypeEnum;
import com.bytechainx.psi.common.EnumConstant.PlatformTypeEnum;
import com.bytechainx.psi.common.Permissions;
import com.bytechainx.psi.common.annotation.Permission;
import com.bytechainx.psi.common.model.TenantAdmin;
import com.bytechainx.psi.common.model.TenantOperLog;
import com.bytechainx.psi.web.web.controller.base.BaseController;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import cn.hutool.extra.servlet.ServletUtil;
/**
* 操作日志拦截器,统一在这里记录日志
*
* @author defier
*
*/
public class OperLogInterceptor implements Interceptor {
@Override
public void intercept(Invocation ai) {
ai.invoke();
// ACTION执行后记录日志,多线程记录,提升访问性能
new Thread(() -> writeOperLog(ai)).start();
}
/**
* 记录操作日志
* @param ai
*/
private void writeOperLog(Invocation ai) {
BaseController controller = (BaseController) ai.getController();
String methodName = ai.getMethodName();
TenantAdmin admin = null;
Integer logType = null;
if (StringUtils.contains(methodName, "delete")) {
logType = OperLogTypeEnum.delete.getValue();
} else if (StringUtils.contains(methodName, "create")) {
logType = OperLogTypeEnum.create.getValue();
} else if (StringUtils.contains(methodName, "update")) {
logType = OperLogTypeEnum.update.getValue();
} else if (StringUtils.contains(methodName, "disable")) {
logType = OperLogTypeEnum.setting.getValue();
} else if (StringUtils.contains(methodName, "enable")) {
logType = OperLogTypeEnum.setting.getValue();
} else if (StringUtils.contains(methodName, "close")) {
logType = OperLogTypeEnum.setting.getValue();
} else if (StringUtils.contains(methodName, "audit")) {
logType = OperLogTypeEnum.setting.getValue();
} else if (StringUtils.contains(methodName, "login")) {
logType = OperLogTypeEnum.login.getValue();
admin = TenantAdmin.dao.findBy(controller.getPara("mobile"));
} else if (StringUtils.contains(methodName, "logout")) {
logType = OperLogTypeEnum.login.getValue();
}
// 没有日志类型,则不记录
if(logType == null) {
return;
}
if (admin == null) {
admin = controller.getCurrentAdmin();
}
if (admin == null) {
return;
}
Permissions permissionCode = null;
Method method = ai.getMethod();
Permission permission = method.getAnnotation(Permission.class);
if (permission != null && permission.value() != null) {
permissionCode = permission.value()[0];
}
StringBuffer operDesc = new StringBuffer(); // 操作描述
if(permissionCode != null) {
Permissions parentPermission = Permissions.getEnum(permissionCode.name().substring(0, permissionCode.name().lastIndexOf("_")));
if(StringUtils.contains(methodName, "enable")) { // 在权限里面的名称不管是启用还是停用,都是停用,使用的同一个权限,这里特殊判断下。
operDesc.append(parentPermission.getName()+":启用");
} else {
operDesc.append(parentPermission.getName()+":"+permissionCode.getName());
}
String dataId = controller.getPara("id") == null ? controller.getPara("ids") : controller.getPara("id");; // 修改删除等数据的ID
if(StringUtils.isNotEmpty(dataId)) {
operDesc.append(", id:"+dataId);
}
}
if(StringUtils.contains(methodName, "login")) {
operDesc.append("登录");
} else if(StringUtils.contains(methodName, "logout")) {
operDesc.append("退出");
}
TenantOperLog log = new TenantOperLog();
log.setLogType(logType);
log.setOperPerson(admin.getRealName());
log.setTenantAdminId(admin.getId());
log.setOperDesc(operDesc.toString());
log.setOperTime(new Date());
log.setPlatformType(PlatformTypeEnum.web.getValue());
log.setOperIp(ServletUtil.getClientIP(controller.getRequest()));
log.save();
}
}
package com.bytechainx.psi.web.web.interceptor;
import java.lang.reflect.Method;
import com.bytechainx.psi.common.CommonConstant;
import com.bytechainx.psi.common.Permissions;
import com.bytechainx.psi.common.annotation.Permission;
import com.bytechainx.psi.common.dto.UserSession;
import com.bytechainx.psi.web.config.AppConfig;
import com.bytechainx.psi.web.web.controller.base.BaseController;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.kit.Ret;
/**
* 需要登录权限才能访问
*
* @author defier
*
*/
public class PermissionInterceptor implements Interceptor {
@Override
public void intercept(Invocation inv) {
BaseController controller = (BaseController) inv.getController();
// 判断是否登录
UserSession session = controller.getSessionAttr(CommonConstant.SESSION_ID_KEY);
if (session == null) {
redirectLogin(controller);
return;
}
// 判断租户是否到期
Integer tenantId = controller.getSessionAttr(CommonConstant.SESSION_TENANT_ID);
if(tenantId == null) {
redirectLogin(controller);
return;
}
// 判断是否有权限
Permissions[] operCodes = {};
Method method = inv.getMethod();
Permission permission = method.getAnnotation(Permission.class);
if (permission != null && permission.value() != null) {
operCodes = permission.value();
}
if(!session.hasAnyOper(operCodes)) { // 无权限
forward(controller);
return;
}
inv.invoke();
}
/**
* @param controller
*/
public void redirectLogin(BaseController controller) {
String url = controller.getCookie(CommonConstant.COOKIE_TENANT_URL_CODE);
if(controller.isJsonRequest()) {
controller.renderJson(Ret.fail("登录超时,请重新登录").set("loginUrl", url));
} else if (controller.isAjaxHtmlRequest()) {
controller.render(AppConfig.noLoginViews);
} else {
controller.redirect(url);
}
}
private void forward(BaseController controller) {
if (controller.isJsonRequest()) {
controller.renderJson(Ret.fail("没有操作权限"));
} else if (controller.isAjaxHtmlRequest()) {
controller.render(AppConfig.noPermissionViews);
} else { // 正常的http请求
controller.renderHtml("<script>alert('没有操作权限');location.href='/account/logout';</script>");
}
}
}
package com.bytechainx.psi.web.web.interceptor;
import com.bytechainx.psi.common.CommonConstant;
import com.bytechainx.psi.common.model.TenantOrg;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
/**
* 一些公共数据,在此类中处理
* @author defier
*
*/
public class ViewContextInterceptor implements Interceptor {
// private final static String TOKEN_NAME = "_mvc_token";
@Override
public void intercept(Invocation ai) {
Controller controller = ai.getController();
controller.setAttr("session", controller.getSessionAttr(CommonConstant.SESSION_ID_KEY));
Integer tenantId = controller.getSessionAttr(CommonConstant.SESSION_TENANT_ID);
if(tenantId != null && tenantId > 0) {
TenantOrg currentTenant = TenantOrg.dao.findCacheById();
controller.setAttr("currentTenant", currentTenant);
}
/**
String methodName = ai.getMethodName();
if (StringUtils.contains(methodName, "add") || StringUtils.contains(methodName, "edit")) {
controller.createToken(TOKEN_NAME);
}
if (StringUtils.contains(methodName, "create") || StringUtils.contains(methodName, "update")) {
if(!controller.validateToken(TOKEN_NAME)) {
controller.renderJson(Ret.fail("操作过于频繁"));
return;
}
}
**/
ai.invoke();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册