1.优化上传个人头像错误提示框。
2.增加bootstrap fileinput插件。 3.增加通过Excel文件批量添加用户功能。
This commit is contained in:
parent
c5b2b8d5ca
commit
dcbd2b2210
23
pom.xml
23
pom.xml
@ -40,6 +40,7 @@
|
|||||||
<kaptcha.version>2.3.2</kaptcha.version>
|
<kaptcha.version>2.3.2</kaptcha.version>
|
||||||
<swagger.version>2.7.0</swagger.version>
|
<swagger.version>2.7.0</swagger.version>
|
||||||
<jsoup.version>1.11.3</jsoup.version>
|
<jsoup.version>1.11.3</jsoup.version>
|
||||||
|
<poi.version>3.17</poi.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@ -83,13 +84,6 @@
|
|||||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- spring-boot-devtools -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-devtools</artifactId>
|
|
||||||
<optional>true</optional> <!-- 表示依赖不会传递 -->
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- thymeleaf网页解析 -->
|
<!-- thymeleaf网页解析 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.sourceforge.nekohtml</groupId>
|
<groupId>net.sourceforge.nekohtml</groupId>
|
||||||
@ -238,7 +232,6 @@
|
|||||||
<artifactId>springfox-swagger-ui</artifactId>
|
<artifactId>springfox-swagger-ui</artifactId>
|
||||||
<version>${swagger.version}</version>
|
<version>${swagger.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- HTML解析器 -->
|
<!-- HTML解析器 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jsoup</groupId>
|
<groupId>org.jsoup</groupId>
|
||||||
@ -246,6 +239,18 @@
|
|||||||
<version>${jsoup.version}</version>
|
<version>${jsoup.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- POI-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>poi</artifactId>
|
||||||
|
<version>${poi.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>poi-ooxml</artifactId>
|
||||||
|
<version>${poi.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@ -255,7 +260,7 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
|
<executable>true</executable>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
@ -171,68 +171,69 @@ insert into sys_menu values('22', '用户删除', '4', '4', '#', 'F', '0', 'sy
|
|||||||
insert into sys_menu values('23', '用户保存', '4', '5', '#', 'F', '0', 'system:user:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('23', '用户保存', '4', '5', '#', 'F', '0', 'system:user:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('24', '批量删除', '4', '6', '#', 'F', '0', 'system:user:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('24', '批量删除', '4', '6', '#', 'F', '0', 'system:user:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('25', '重置密码', '4', '7', '#', 'F', '0', 'system:user:resetPwd', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('25', '重置密码', '4', '7', '#', 'F', '0', 'system:user:resetPwd', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
|
insert into sys_menu values('26', '批量新增', '4', '8', '#', 'F', '0', 'system:user:batchAdd', '#', 'admin', '2018-06-02 11-33-00', 'ry', '2018-06-02 11-33-00', '');
|
||||||
-- 角色管理按钮
|
-- 角色管理按钮
|
||||||
insert into sys_menu values('26', '角色查询', '5', '1', '#', 'F', '0', 'system:role:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('27', '角色查询', '5', '1', '#', 'F', '0', 'system:role:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('27', '角色新增', '5', '2', '#', 'F', '0', 'system:role:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('28', '角色新增', '5', '2', '#', 'F', '0', 'system:role:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('28', '角色修改', '5', '3', '#', 'F', '0', 'system:role:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('29', '角色修改', '5', '3', '#', 'F', '0', 'system:role:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('29', '角色删除', '5', '4', '#', 'F', '0', 'system:role:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('30', '角色删除', '5', '4', '#', 'F', '0', 'system:role:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('30', '角色保存', '5', '5', '#', 'F', '0', 'system:role:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('31', '角色保存', '5', '5', '#', 'F', '0', 'system:role:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('31', '批量删除', '5', '6', '#', 'F', '0', 'system:role:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('32', '批量删除', '5', '6', '#', 'F', '0', 'system:role:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
-- 菜单管理按钮
|
-- 菜单管理按钮
|
||||||
insert into sys_menu values('32', '菜单查询', '6', '1', '#', 'F', '0', 'system:menu:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('33', '菜单查询', '6', '1', '#', 'F', '0', 'system:menu:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('33', '菜单新增', '6', '2', '#', 'F', '0', 'system:menu:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('34', '菜单新增', '6', '2', '#', 'F', '0', 'system:menu:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('34', '菜单修改', '6', '3', '#', 'F', '0', 'system:menu:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('35', '菜单修改', '6', '3', '#', 'F', '0', 'system:menu:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('35', '菜单删除', '6', '4', '#', 'F', '0', 'system:menu:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('36', '菜单删除', '6', '4', '#', 'F', '0', 'system:menu:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('36', '菜单保存', '6', '5', '#', 'F', '0', 'system:menu:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('37', '菜单保存', '6', '5', '#', 'F', '0', 'system:menu:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
-- 部门管理按钮
|
-- 部门管理按钮
|
||||||
insert into sys_menu values('37', '部门查询', '7', '1', '#', 'F', '0', 'system:dept:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('38', '部门查询', '7', '1', '#', 'F', '0', 'system:dept:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('38', '部门新增', '7', '2', '#', 'F', '0', 'system:dept:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('39', '部门新增', '7', '2', '#', 'F', '0', 'system:dept:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('39', '部门修改', '7', '3', '#', 'F', '0', 'system:dept:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('40', '部门修改', '7', '3', '#', 'F', '0', 'system:dept:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('40', '部门删除', '7', '4', '#', 'F', '0', 'system:dept:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('41', '部门删除', '7', '4', '#', 'F', '0', 'system:dept:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('41', '部门保存', '7', '5', '#', 'F', '0', 'system:dept:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('42', '部门保存', '7', '5', '#', 'F', '0', 'system:dept:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
-- 岗位管理按钮
|
-- 岗位管理按钮
|
||||||
insert into sys_menu values('42', '岗位查询', '8', '1', '#', 'F', '0', 'system:post:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('43', '岗位查询', '8', '1', '#', 'F', '0', 'system:post:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('43', '岗位新增', '8', '2', '#', 'F', '0', 'system:post:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('44', '岗位新增', '8', '2', '#', 'F', '0', 'system:post:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('44', '岗位修改', '8', '3', '#', 'F', '0', 'system:post:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('45', '岗位修改', '8', '3', '#', 'F', '0', 'system:post:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('45', '岗位删除', '8', '4', '#', 'F', '0', 'system:post:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('46', '岗位删除', '8', '4', '#', 'F', '0', 'system:post:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('46', '岗位保存', '8', '5', '#', 'F', '0', 'system:post:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('47', '岗位保存', '8', '5', '#', 'F', '0', 'system:post:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('47', '批量删除', '8', '6', '#', 'F', '0', 'system:post:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('48', '批量删除', '8', '6', '#', 'F', '0', 'system:post:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
-- 字典管理按钮
|
-- 字典管理按钮
|
||||||
insert into sys_menu values('48', '字典查询', '9', '1', '#', 'F', '0', 'system:dict:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('49', '字典查询', '9', '1', '#', 'F', '0', 'system:dict:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('49', '字典新增', '9', '2', '#', 'F', '0', 'system:dict:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('50', '字典新增', '9', '2', '#', 'F', '0', 'system:dict:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('50', '字典修改', '9', '3', '#', 'F', '0', 'system:dict:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('51', '字典修改', '9', '3', '#', 'F', '0', 'system:dict:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('51', '字典删除', '9', '4', '#', 'F', '0', 'system:dict:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('52', '字典删除', '9', '4', '#', 'F', '0', 'system:dict:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('52', '字典保存', '9', '5', '#', 'F', '0', 'system:dict:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('53', '字典保存', '9', '5', '#', 'F', '0', 'system:dict:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('53', '批量删除', '9', '6', '#', 'F', '0', 'system:dict:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('54', '批量删除', '9', '6', '#', 'F', '0', 'system:dict:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
-- 参数设置按钮
|
-- 参数设置按钮
|
||||||
insert into sys_menu values('54', '参数查询', '10', '1', '#', 'F', '0', 'system:config:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('55', '参数查询', '10', '1', '#', 'F', '0', 'system:config:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('55', '参数新增', '10', '2', '#', 'F', '0', 'system:config:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('56', '参数新增', '10', '2', '#', 'F', '0', 'system:config:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('56', '参数修改', '10', '3', '#', 'F', '0', 'system:config:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('57', '参数修改', '10', '3', '#', 'F', '0', 'system:config:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('57', '参数删除', '10', '4', '#', 'F', '0', 'system:config:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('58', '参数删除', '10', '4', '#', 'F', '0', 'system:config:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('58', '参数保存', '10', '5', '#', 'F', '0', 'system:config:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('59', '参数保存', '10', '5', '#', 'F', '0', 'system:config:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('59', '批量删除', '10', '6', '#', 'F', '0', 'system:config:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('60', '批量删除', '10', '6', '#', 'F', '0', 'system:config:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
-- 操作日志按钮
|
-- 操作日志按钮
|
||||||
insert into sys_menu values('60', '操作查询', '11', '1', '#', 'F', '0', 'monitor:operlog:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('61', '操作查询', '11', '1', '#', 'F', '0', 'monitor:operlog:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('61', '批量删除', '11', '2', '#', 'F', '0', 'monitor:operlog:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('62', '批量删除', '11', '2', '#', 'F', '0', 'monitor:operlog:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('62', '详细信息', '11', '3', '#', 'F', '0', 'monitor:operlog:detail', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('63', '详细信息', '11', '3', '#', 'F', '0', 'monitor:operlog:detail', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
-- 登录日志按钮
|
-- 登录日志按钮
|
||||||
insert into sys_menu values('63', '登录查询', '12', '1', '#', 'F', '0', 'monitor:logininfor:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('64', '登录查询', '12', '1', '#', 'F', '0', 'monitor:logininfor:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('64', '批量删除', '12', '2', '#', 'F', '0', 'monitor:logininfor:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('65', '批量删除', '12', '2', '#', 'F', '0', 'monitor:logininfor:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
-- 在线用户按钮
|
-- 在线用户按钮
|
||||||
insert into sys_menu values('65', '在线查询', '13', '1', '#', 'F', '0', 'monitor:online:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('66', '在线查询', '13', '1', '#', 'F', '0', 'monitor:online:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('66', '批量强退', '13', '2', '#', 'F', '0', 'monitor:online:batchForceLogout', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('67', '批量强退', '13', '2', '#', 'F', '0', 'monitor:online:batchForceLogout', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('67', '单条强退', '13', '3', '#', 'F', '0', 'monitor:online:forceLogout', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('68', '单条强退', '13', '3', '#', 'F', '0', 'monitor:online:forceLogout', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
-- 定时任务按钮
|
-- 定时任务按钮
|
||||||
insert into sys_menu values('68', '任务查询', '14', '1', '#', 'F', '0', 'monitor:job:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('69', '任务查询', '14', '1', '#', 'F', '0', 'monitor:job:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('69', '任务新增', '14', '2', '#', 'F', '0', 'monitor:job:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('70', '任务新增', '14', '2', '#', 'F', '0', 'monitor:job:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('70', '任务修改', '14', '3', '#', 'F', '0', 'monitor:job:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('71', '任务修改', '14', '3', '#', 'F', '0', 'monitor:job:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('71', '任务删除', '14', '4', '#', 'F', '0', 'monitor:job:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('72', '任务删除', '14', '4', '#', 'F', '0', 'monitor:job:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('72', '任务保存', '14', '5', '#', 'F', '0', 'monitor:job:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('73', '任务保存', '14', '5', '#', 'F', '0', 'monitor:job:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('73', '状态修改', '14', '6', '#', 'F', '0', 'monitor:job:changeStatus', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('74', '状态修改', '14', '6', '#', 'F', '0', 'monitor:job:changeStatus', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('74', '批量删除', '14', '7', '#', 'F', '0', 'monitor:job:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('75', '批量删除', '14', '7', '#', 'F', '0', 'monitor:job:batchRemove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
-- 代码生成按钮
|
-- 代码生成按钮
|
||||||
insert into sys_menu values('75', '生成查询', '16', '1', '#', 'F', '0', 'tool:gen:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('76', '生成查询', '16', '1', '#', 'F', '0', 'tool:gen:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
insert into sys_menu values('76', '生成代码', '16', '2', '#', 'F', '0', 'tool:gen:code', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
insert into sys_menu values('77', '生成代码', '16', '2', '#', 'F', '0', 'tool:gen:code', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
|
||||||
|
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
@ -341,6 +342,7 @@ insert into sys_role_menu values ('1', '73');
|
|||||||
insert into sys_role_menu values ('1', '74');
|
insert into sys_role_menu values ('1', '74');
|
||||||
insert into sys_role_menu values ('1', '75');
|
insert into sys_role_menu values ('1', '75');
|
||||||
insert into sys_role_menu values ('1', '76');
|
insert into sys_role_menu values ('1', '76');
|
||||||
|
insert into sys_role_menu values ('1', '77');
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- 8、用户与岗位关联表 用户1-N岗位
|
-- 8、用户与岗位关联表 用户1-N岗位
|
||||||
|
78
src/main/java/com/ruoyi/common/utils/ExcelImportUtils.java
Normal file
78
src/main/java/com/ruoyi/common/utils/ExcelImportUtils.java
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
package com.ruoyi.common.utils;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
||||||
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入Excel工具类
|
||||||
|
*/
|
||||||
|
public class ExcelImportUtils {
|
||||||
|
|
||||||
|
/** 是否是2003的excel,返回true是2003Excel文件**/
|
||||||
|
public static boolean isExcel2003(String filePath){
|
||||||
|
return filePath.matches("^.+\\.(?i)(xls)$");
|
||||||
|
}
|
||||||
|
/** 是否是2007以上的excel,返回true是2007Excel文件**/
|
||||||
|
public static boolean isExcel2007(String filePath){
|
||||||
|
return filePath.matches("^.+\\.(?i)(xlsx)$");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 验证EXCEL文件
|
||||||
|
*
|
||||||
|
* @param filePath
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean validateExcel(String filePath) {
|
||||||
|
if (filePath == null || !(isExcel2003(filePath) || isExcel2007(filePath))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单元格的值
|
||||||
|
* @param cell
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getCellValue(Cell cell) {
|
||||||
|
String value = "";
|
||||||
|
if (cell != null) {
|
||||||
|
switch(cell.getCellTypeEnum()){
|
||||||
|
case NUMERIC:// 数字
|
||||||
|
value = cell.getNumericCellValue()+ " ";
|
||||||
|
if(HSSFDateUtil.isCellDateFormatted(cell)){
|
||||||
|
Date date = cell.getDateCellValue();
|
||||||
|
if(date != null){
|
||||||
|
value = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,date); // 日期格式化
|
||||||
|
}else{
|
||||||
|
value = "";
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
// 解析cell时候 数字类型默认是double类型的 但是想要获取整数类型 需要格式化
|
||||||
|
value = new DecimalFormat("0").format(cell.getNumericCellValue());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STRING: // 字符串
|
||||||
|
value = cell.getStringCellValue();
|
||||||
|
break;
|
||||||
|
case BOOLEAN: // Boolean类型
|
||||||
|
value = cell.getBooleanCellValue()+"";
|
||||||
|
break;
|
||||||
|
case BLANK: // 空值
|
||||||
|
value = "";
|
||||||
|
break;
|
||||||
|
case ERROR: // 错误类型
|
||||||
|
value ="非法字符";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
value = "未知类型";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return value.trim();
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,5 @@
|
|||||||
package com.ruoyi.project.system.user.controller;
|
package com.ruoyi.project.system.user.controller;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.framework.aspectj.lang.annotation.Log;
|
import com.ruoyi.framework.aspectj.lang.annotation.Log;
|
||||||
import com.ruoyi.framework.web.controller.BaseController;
|
import com.ruoyi.framework.web.controller.BaseController;
|
||||||
@ -25,6 +12,17 @@ import com.ruoyi.project.system.role.service.IRoleService;
|
|||||||
import com.ruoyi.project.system.user.domain.User;
|
import com.ruoyi.project.system.user.domain.User;
|
||||||
import com.ruoyi.project.system.user.domain.UserStatus;
|
import com.ruoyi.project.system.user.domain.UserStatus;
|
||||||
import com.ruoyi.project.system.user.service.IUserService;
|
import com.ruoyi.project.system.user.service.IUserService;
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户信息
|
* 用户信息
|
||||||
@ -35,7 +33,7 @@ import com.ruoyi.project.system.user.service.IUserService;
|
|||||||
@RequestMapping("/system/user")
|
@RequestMapping("/system/user")
|
||||||
public class UserController extends BaseController
|
public class UserController extends BaseController
|
||||||
{
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(UserController.class);
|
||||||
private String prefix = "system/user";
|
private String prefix = "system/user";
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -172,6 +170,28 @@ public class UserController extends BaseController
|
|||||||
return userService.saveUser(user) > 0 ? Message.success() : Message.error();
|
return userService.saveUser(user) > 0 ? Message.success() : Message.error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量新增用户
|
||||||
|
*/
|
||||||
|
@RequiresPermissions("system:user:batchAdd")
|
||||||
|
@Log(title = "系统管理", action = "用户管理-批量新增用户")
|
||||||
|
@PostMapping("/batchAdd")
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
@ResponseBody
|
||||||
|
public Message batchAdd( @RequestParam("uploadfile") MultipartFile file)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if(!file.isEmpty()){
|
||||||
|
int rows=userService.batchImportUsers(file);
|
||||||
|
return Message.success(String.valueOf(rows));
|
||||||
|
}
|
||||||
|
return Message.error();
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error("批量添加用户失败 !", e);
|
||||||
|
return Message.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验用户名
|
* 校验用户名
|
||||||
*/
|
*/
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package com.ruoyi.project.system.user.mapper;
|
package com.ruoyi.project.system.user.mapper;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import com.ruoyi.project.system.user.domain.User;
|
import com.ruoyi.project.system.user.domain.User;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户表 数据层
|
* 用户表 数据层
|
||||||
*
|
*
|
||||||
@ -108,4 +109,12 @@ public interface UserMapper
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public User checkEmailUnique(String email);
|
public User checkEmailUnique(String email);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量添加用户
|
||||||
|
* @param userList
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int batchAddUser(List<User> userList);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package com.ruoyi.project.system.user.service;
|
package com.ruoyi.project.system.user.service;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import com.ruoyi.project.system.user.domain.User;
|
import com.ruoyi.project.system.user.domain.User;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户 业务层
|
* 用户 业务层
|
||||||
@ -133,4 +135,11 @@ public interface IUserService
|
|||||||
*/
|
*/
|
||||||
public String selectUserPostGroup(Long userId);
|
public String selectUserPostGroup(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Excel批量导入用户
|
||||||
|
* @param myFile
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int batchImportUsers(MultipartFile myFile);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package com.ruoyi.project.system.user.service;
|
package com.ruoyi.project.system.user.service;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import com.ruoyi.common.constant.UserConstants;
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
|
import com.ruoyi.common.exception.user.UserException;
|
||||||
|
import com.ruoyi.common.utils.ExcelImportUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.security.ShiroUtils;
|
import com.ruoyi.common.utils.security.ShiroUtils;
|
||||||
import com.ruoyi.framework.shiro.service.PasswordService;
|
import com.ruoyi.framework.shiro.service.PasswordService;
|
||||||
|
import com.ruoyi.project.system.dept.domain.Dept;
|
||||||
|
import com.ruoyi.project.system.dept.service.IDeptService;
|
||||||
import com.ruoyi.project.system.post.domain.Post;
|
import com.ruoyi.project.system.post.domain.Post;
|
||||||
import com.ruoyi.project.system.post.mapper.PostMapper;
|
import com.ruoyi.project.system.post.mapper.PostMapper;
|
||||||
import com.ruoyi.project.system.role.domain.Role;
|
import com.ruoyi.project.system.role.domain.Role;
|
||||||
@ -18,6 +18,19 @@ import com.ruoyi.project.system.user.domain.UserRole;
|
|||||||
import com.ruoyi.project.system.user.mapper.UserMapper;
|
import com.ruoyi.project.system.user.mapper.UserMapper;
|
||||||
import com.ruoyi.project.system.user.mapper.UserPostMapper;
|
import com.ruoyi.project.system.user.mapper.UserPostMapper;
|
||||||
import com.ruoyi.project.system.user.mapper.UserRoleMapper;
|
import com.ruoyi.project.system.user.mapper.UserRoleMapper;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户 业务层处理
|
* 用户 业务层处理
|
||||||
@ -27,7 +40,7 @@ import com.ruoyi.project.system.user.mapper.UserRoleMapper;
|
|||||||
@Service("userService")
|
@Service("userService")
|
||||||
public class UserServiceImpl implements IUserService
|
public class UserServiceImpl implements IUserService
|
||||||
{
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserMapper userMapper;
|
private UserMapper userMapper;
|
||||||
|
|
||||||
@ -46,6 +59,10 @@ public class UserServiceImpl implements IUserService
|
|||||||
@Autowired
|
@Autowired
|
||||||
private PasswordService passwordService;
|
private PasswordService passwordService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IDeptService deptService;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据条件分页查询用户对象
|
* 根据条件分页查询用户对象
|
||||||
*
|
*
|
||||||
@ -178,6 +195,245 @@ public class UserServiceImpl implements IUserService
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据Execl 批量保存用户
|
||||||
|
* 1. 使用HSSFWorkbook 打开或者创建 “Excel对象”
|
||||||
|
* 2. 用HSSFWorkbook返回对象或者创建sheet对象
|
||||||
|
* 3. 用sheet返回行对象,用行对象得到Cell对象
|
||||||
|
* 4. 对Cell对象进行读写
|
||||||
|
* @param myFile
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int batchImportUsers(MultipartFile myFile) {
|
||||||
|
//Excel工作簿
|
||||||
|
Workbook workbook=null;
|
||||||
|
//获取文件名
|
||||||
|
String filename=myFile.getOriginalFilename();
|
||||||
|
log.info("【ExeclfileName】{}",filename);
|
||||||
|
//根据文件名判断文件是2003版本还是2007版本
|
||||||
|
if(ExcelImportUtils.isExcel2003(filename)){
|
||||||
|
try {
|
||||||
|
workbook=new HSSFWorkbook(myFile.getInputStream());//2003版本
|
||||||
|
}catch (IOException e){
|
||||||
|
log.error("获取Excel2003流错误"+e.getMessage());
|
||||||
|
}
|
||||||
|
}else if(ExcelImportUtils.isExcel2007(filename)){
|
||||||
|
try {
|
||||||
|
workbook=new XSSFWorkbook(myFile.getInputStream());//2007以上版本
|
||||||
|
}catch (IOException e){
|
||||||
|
log.error("获取Excel2007以上版本流错误"+e.getMessage());
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
|
||||||
|
throw new UserException("1000",new Object[]{"文件不是Excel格式"});
|
||||||
|
}
|
||||||
|
//得到第一个sheet
|
||||||
|
Sheet sheet = workbook.getSheetAt(0);
|
||||||
|
//得到Excel的行数
|
||||||
|
int totalRows = sheet.getLastRowNum();
|
||||||
|
log.info("【rows】{}",totalRows);
|
||||||
|
//新建用户list
|
||||||
|
List<User> users=new ArrayList<User>();
|
||||||
|
|
||||||
|
List<Dept> depts;
|
||||||
|
List<Role> roles;
|
||||||
|
List<Post> posts;
|
||||||
|
|
||||||
|
//如果行数为空
|
||||||
|
/**
|
||||||
|
* getPhysicalNumberOfRows
|
||||||
|
*
|
||||||
|
* 获取有记录的行数,即:最后有数据的行是第n行,前面有m行是空行没数据,则返回n-m;
|
||||||
|
*/
|
||||||
|
if((totalRows==0)&&(sheet.getPhysicalNumberOfRows()==0)){
|
||||||
|
throw new UserException("1001",new Object[]{"数据为空 请填写数据"});
|
||||||
|
}else{
|
||||||
|
//获取全部部门信息
|
||||||
|
depts=deptService.selectDeptAll();
|
||||||
|
//获取全部角色信息
|
||||||
|
roles=roleMapper.selectRolesAll();
|
||||||
|
//获取全部岗位信息
|
||||||
|
posts=postMapper.selectPostAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=1;i<=totalRows;i++){
|
||||||
|
Row row = sheet.getRow(i);
|
||||||
|
if(row!=null){
|
||||||
|
User user=new User();
|
||||||
|
//登录名(用户名)
|
||||||
|
String userName=ExcelImportUtils.getCellValue(row.getCell(0));
|
||||||
|
if(userName.isEmpty()){
|
||||||
|
continue;
|
||||||
|
}else{
|
||||||
|
//判断用户名是否唯一
|
||||||
|
if(checkLoginNameUnique(userName).equals(UserConstants.USER_NAME_UNIQUE)){
|
||||||
|
user.setLoginName(userName);
|
||||||
|
}else {
|
||||||
|
log.error("【rows】{}行用户名已经存在",i+1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//姓名
|
||||||
|
String userRealName=ExcelImportUtils.getCellValue(row.getCell(1));
|
||||||
|
user.setUserName(userRealName);
|
||||||
|
//性别
|
||||||
|
String userSex=ExcelImportUtils.getCellValue(row.getCell(2));
|
||||||
|
if(StringUtils.isNotEmpty(userSex)){
|
||||||
|
if(userSex.equals("男")){
|
||||||
|
user.setSex("0");
|
||||||
|
}else if(userSex.equals("女")){
|
||||||
|
user.setSex("1");
|
||||||
|
}else {
|
||||||
|
user.setSex("2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//密码
|
||||||
|
String passWord=ExcelImportUtils.getCellValue(row.getCell(3));
|
||||||
|
user.randomSalt();
|
||||||
|
user.setPassword(passwordService.encryptPassword(userName, passWord, user.getSalt()));
|
||||||
|
//部门
|
||||||
|
String dept=ExcelImportUtils.getCellValue(row.getCell(4));
|
||||||
|
if(StringUtils.isNotEmpty(dept)){
|
||||||
|
for (int k=0;k<depts.size();k++){
|
||||||
|
if(dept.equals(depts.get(k).getDeptName())){
|
||||||
|
user.setDeptId(depts.get(k).getDeptId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
user.setCreateBy(ShiroUtils.getLoginName());
|
||||||
|
//角色--多个角色以","分割
|
||||||
|
String userRolesExcel=ExcelImportUtils.getCellValue(row.getCell(5));
|
||||||
|
if(StringUtils.isNotEmpty(userRolesExcel)){
|
||||||
|
//Set可以去掉重复的值,
|
||||||
|
Set<Long> sets=new HashSet<Long>();
|
||||||
|
//判断是否有"," 号
|
||||||
|
if(userRolesExcel.contains(",")){
|
||||||
|
List<String> results= Arrays.asList(userRolesExcel.split(","));
|
||||||
|
for(String s:results){
|
||||||
|
for(int l=0;l<roles.size();l++){
|
||||||
|
if(s.equals(roles.get(l).getRoleName())){
|
||||||
|
sets.add(roles.get(l).getRoleId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}else {
|
||||||
|
for(int j=0;j<roles.size();j++){
|
||||||
|
if(userRolesExcel.equals(roles.get(j).getRoleName())){
|
||||||
|
sets.add(roles.get(j).getRoleId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
for(Long longTes:sets){
|
||||||
|
log.info("username={},longTes={}",userName,longTes);
|
||||||
|
}
|
||||||
|
user.setRoleIds((Long[]) sets.toArray(new Long[sets.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
//岗位--多个岗位以","分割
|
||||||
|
String userPostExcel=ExcelImportUtils.getCellValue(row.getCell(6));
|
||||||
|
if(StringUtils.isNotEmpty(userPostExcel)){
|
||||||
|
//去掉重复的值,
|
||||||
|
Set<Long> setPosts=new HashSet<Long>();
|
||||||
|
//判断是否有"," 号
|
||||||
|
if(userPostExcel.contains(",")){
|
||||||
|
List<String> resultsp= Arrays.asList(userPostExcel.split(","));
|
||||||
|
for(String p:resultsp){
|
||||||
|
for(int h=0;h<posts.size();h++){
|
||||||
|
if(p.equals(posts.get(h).getPostName())){
|
||||||
|
setPosts.add(posts.get(h).getPostId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}else {
|
||||||
|
for(int m=0;m<posts.size();m++){
|
||||||
|
if(userPostExcel.equals(posts.get(m).getPostName())){
|
||||||
|
setPosts.add(posts.get(m).getPostId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Long longTest:setPosts){
|
||||||
|
log.info("username={},longTest={}",userName,longTest);
|
||||||
|
}
|
||||||
|
user.setPostIds((Long[]) setPosts.toArray(new Long[setPosts.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
//手机号
|
||||||
|
String phoneNumber=ExcelImportUtils.getCellValue(row.getCell(7));
|
||||||
|
if(StringUtils.isNotEmpty(phoneNumber)){
|
||||||
|
//验证是否是手机号
|
||||||
|
if(phoneNumber.matches(UserConstants.MOBILE_PHONE_NUMBER_PATTERN)){
|
||||||
|
user.setPhonenumber(phoneNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//邮箱
|
||||||
|
String userEmail=ExcelImportUtils.getCellValue(row.getCell(8));
|
||||||
|
if(StringUtils.isNotEmpty(userEmail)){
|
||||||
|
//验证是否是邮箱
|
||||||
|
if(userEmail.matches(UserConstants.EMAIL_PATTERN)){
|
||||||
|
user.setEmail(userEmail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
users.add(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//实际添加行数
|
||||||
|
int realRow=0;
|
||||||
|
//如果添加的列表不为空
|
||||||
|
if(users.size()>0){
|
||||||
|
//批量插入用户
|
||||||
|
realRow=userMapper.batchAddUser(users);
|
||||||
|
}
|
||||||
|
System.out.println(realRow);
|
||||||
|
if(realRow>0){
|
||||||
|
//用户和角色关联
|
||||||
|
List<UserRole> userRoles=new ArrayList<UserRole>();
|
||||||
|
//用户和岗位关联
|
||||||
|
List<UserPost> userPosts=new ArrayList<UserPost>();
|
||||||
|
for(User test:users){
|
||||||
|
System.out.println("userID="+test.getUserId());
|
||||||
|
System.out.println("username="+test.getUserName());
|
||||||
|
System.out.println("useroleids"+Arrays.toString(test.getRoleIds()));
|
||||||
|
System.out.println("userpostids"+Arrays.toString(test.getPostIds()));
|
||||||
|
|
||||||
|
//添加用户-角色关联表
|
||||||
|
for(int q=0;q<test.getRoleIds().length;q++){
|
||||||
|
UserRole userRole=new UserRole();
|
||||||
|
userRole.setUserId(test.getUserId());
|
||||||
|
userRole.setRoleId(test.getRoleIds()[q]);
|
||||||
|
userRoles.add(userRole);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int r=0;r<test.getPostIds().length;r++){
|
||||||
|
UserPost userPost=new UserPost();
|
||||||
|
userPost.setUserId(test.getUserId());
|
||||||
|
userPost.setPostId(test.getPostIds()[r]);
|
||||||
|
userPosts.add(userPost);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//批量添加用户-角色关联数据
|
||||||
|
userRoleMapper.batchUserRole(userRoles);
|
||||||
|
|
||||||
|
//批量添加用户-岗位关联数据
|
||||||
|
userPostMapper.batchUserPost(userPosts);
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
return realRow;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改用户信息
|
* 修改用户信息
|
||||||
*
|
*
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# 项目名称、版本、版权年份
|
# 项目名称、版本、版权年份
|
||||||
ruoyi:
|
ruoyi:
|
||||||
name: RuoYi
|
name: RuoYi
|
||||||
version: 1.1.5
|
version: 1.1.6
|
||||||
copyrightYear: 2018
|
copyrightYear: 2018
|
||||||
profile: D:/profile/
|
profile: D:/profile/
|
||||||
|
|
||||||
|
@ -160,4 +160,37 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
)
|
)
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
|
<insert id="batchAddUser" useGeneratedKeys="true" keyProperty="userId" >
|
||||||
|
insert into sys_user(
|
||||||
|
dept_id,
|
||||||
|
login_name,
|
||||||
|
user_name,
|
||||||
|
email,
|
||||||
|
phonenumber,
|
||||||
|
sex,
|
||||||
|
password,
|
||||||
|
salt,
|
||||||
|
status,
|
||||||
|
create_by,
|
||||||
|
remark,
|
||||||
|
create_time
|
||||||
|
)values
|
||||||
|
<foreach item="item" index="index" collection="list" separator=",">
|
||||||
|
(
|
||||||
|
#{item.deptId},
|
||||||
|
#{item.loginName},
|
||||||
|
#{item.userName},
|
||||||
|
#{item.email},
|
||||||
|
#{item.phonenumber},
|
||||||
|
#{item.sex},
|
||||||
|
#{item.password},
|
||||||
|
#{item.salt},
|
||||||
|
#{item.status},
|
||||||
|
#{item.createBy},
|
||||||
|
#{item.remark},
|
||||||
|
sysdate()
|
||||||
|
)
|
||||||
|
</foreach>
|
||||||
|
</insert>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
554
src/main/resources/static/css/plugins/fileinput/fileinput.css
Normal file
554
src/main/resources/static/css/plugins/fileinput/fileinput.css
Normal file
@ -0,0 +1,554 @@
|
|||||||
|
/*!
|
||||||
|
* bootstrap-fileinput v4.4.9
|
||||||
|
* http://plugins.krajee.com/file-input
|
||||||
|
*
|
||||||
|
* Krajee default styling for bootstrap-fileinput.
|
||||||
|
*
|
||||||
|
* Author: Kartik Visweswaran
|
||||||
|
* Copyright: 2014 - 2018, Kartik Visweswaran, Krajee.com
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause
|
||||||
|
* https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
.file-loading input[type=file], input[type=file].file-loading {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-no-browse {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
bottom: 20%;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
font-size: 0;
|
||||||
|
opacity: 0;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
outline: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-hidden, .file-caption-icon, .file-zoom-dialog .modal-header:before, .file-zoom-dialog .modal-header:after, .file-input-new .file-preview, .file-input-new .close, .file-input-new .glyphicon-file, .file-input-new .fileinput-remove-button, .file-input-new .fileinput-upload-button, .file-input-new .no-browse .input-group-btn, .file-input-ajax-new .fileinput-remove-button, .file-input-ajax-new .fileinput-upload-button, .file-input-ajax-new .no-browse .input-group-btn, .hide-content .kv-file-content {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-file input[type=file], .file-caption-icon, .file-preview .fileinput-remove, .krajee-default .file-thumb-progress, .file-zoom-dialog .btn-navigate, .file-zoom-dialog .floating-buttons {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input, .file-loading:before, .btn-file, .file-caption, .file-preview, .krajee-default.file-preview-frame, .krajee-default .file-thumbnail-footer, .file-zoom-dialog .modal-dialog {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-error-message pre, .file-error-message ul, .krajee-default .file-actions, .krajee-default .file-other-error {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-error-message pre, .file-error-message ul {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-drag-handle, .krajee-default .file-upload-indicator {
|
||||||
|
float: left;
|
||||||
|
margin: 5px 0 -5px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-thumb-progress .progress, .krajee-default .file-thumb-progress .progress-bar {
|
||||||
|
height: 11px;
|
||||||
|
font-size: 9px;
|
||||||
|
line-height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-caption-info, .krajee-default .file-size-info {
|
||||||
|
display: block;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 160px;
|
||||||
|
height: 15px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content > .file-object.type-video, .file-zoom-content > .file-object.type-flash, .file-zoom-content > .file-object.type-image {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content > .file-object.type-video, .file-zoom-content > .file-object.type-flash {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content > .file-object.type-pdf, .file-zoom-content > .file-object.type-html, .file-zoom-content > .file-object.type-text, .file-zoom-content > .file-object.type-default {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate-2 {
|
||||||
|
transform: rotateY(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate-3 {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate-4 {
|
||||||
|
transform: rotate(180deg) rotateY(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate-5 {
|
||||||
|
transform: rotate(270deg) rotateY(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate-6 {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate-7 {
|
||||||
|
transform: rotate(90deg) rotateY(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate-8 {
|
||||||
|
transform: rotate(270deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-loading:before {
|
||||||
|
content: " Loading...";
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: 20px;
|
||||||
|
line-height: 16px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-variant: small-caps;
|
||||||
|
color: #999;
|
||||||
|
background: transparent url(../img/loading.gif) top left no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-object {
|
||||||
|
margin: 0 0 -5px 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-file {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-file input[type=file] {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
min-width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
text-align: right;
|
||||||
|
opacity: 0;
|
||||||
|
background: none repeat scroll 0 0 transparent;
|
||||||
|
cursor: inherit;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-file ::-ms-browse {
|
||||||
|
font-size: 10000px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption .file-caption-name {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption.icon-visible .file-caption-icon {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption.icon-visible .file-caption-name {
|
||||||
|
padding-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption-icon {
|
||||||
|
left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-error-message {
|
||||||
|
color: #a94442;
|
||||||
|
background-color: #f2dede;
|
||||||
|
margin: 5px;
|
||||||
|
border: 1px solid #ebccd1;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-error-message pre {
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption-disabled {
|
||||||
|
background-color: #eee;
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview {
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 8px;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview .btn-xs {
|
||||||
|
padding: 1px 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview .fileinput-remove {
|
||||||
|
top: 1px;
|
||||||
|
right: 1px;
|
||||||
|
line-height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview .clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview-image {
|
||||||
|
font: 40px Impact, Charcoal, sans-serif;
|
||||||
|
color: #008000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default.file-preview-frame {
|
||||||
|
margin: 8px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
box-shadow: 1px 1px 5px 0 #a2958a;
|
||||||
|
padding: 6px;
|
||||||
|
float: left;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default.file-preview-frame .kv-file-content {
|
||||||
|
width: 213px;
|
||||||
|
height: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default.file-preview-frame .file-thumbnail-footer {
|
||||||
|
height: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default.file-preview-frame:not(.file-preview-error):hover {
|
||||||
|
box-shadow: 3px 3px 5px 0 #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-preview-text {
|
||||||
|
display: block;
|
||||||
|
color: #428bca;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||||
|
outline: none;
|
||||||
|
padding: 8px;
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-preview-html {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 8px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-other-icon {
|
||||||
|
font-size: 6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-footer-buttons {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-footer-caption {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 4px;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #777;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-preview-error {
|
||||||
|
opacity: 0.65;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-thumb-progress {
|
||||||
|
height: 11px;
|
||||||
|
top: 37px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default.kvsortable-ghost {
|
||||||
|
background: #e1edf7;
|
||||||
|
border: 2px solid #a1abff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-preview-other:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-preview-frame:not(.file-preview-error) .file-footer-caption:hover {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-upload-progress .progress {
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
margin: 10px 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-upload-progress .progress-bar {
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*noinspection CssOverwrittenProperties*/
|
||||||
|
.file-zoom-dialog .file-other-icon {
|
||||||
|
font-size: 22em;
|
||||||
|
font-size: 50vmin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .modal-dialog {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .modal-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .btn-navigate {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
background: transparent;
|
||||||
|
text-decoration: none;
|
||||||
|
outline: none;
|
||||||
|
opacity: 0.7;
|
||||||
|
top: 45%;
|
||||||
|
font-size: 4em;
|
||||||
|
color: #1c94c4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .btn-navigate:not([disabled]):hover {
|
||||||
|
outline: none;
|
||||||
|
box-shadow: none;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .floating-buttons {
|
||||||
|
top: 5px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .btn-navigate[disabled] {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .btn-prev {
|
||||||
|
left: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .btn-next {
|
||||||
|
right: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .kv-zoom-title {
|
||||||
|
font-weight: 300;
|
||||||
|
color: #999;
|
||||||
|
max-width: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-new .no-browse .form-control {
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-ajax-new .no-browse .form-control {
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption-main {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-thumb-loading {
|
||||||
|
background: transparent url(../img/loading.gif) no-repeat scroll center center content-box !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-drop-zone {
|
||||||
|
border: 1px dashed #aaa;
|
||||||
|
border-radius: 4px;
|
||||||
|
height: 100%;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: 12px 15px 12px 12px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-drop-zone.clickable:hover {
|
||||||
|
border: 2px dashed #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-drop-zone.clickable:focus {
|
||||||
|
border: 2px solid #5acde2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-drop-zone .file-preview-thumbnails {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-drop-zone-title {
|
||||||
|
color: #aaa;
|
||||||
|
font-size: 1.6em;
|
||||||
|
padding: 85px 10px;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-highlighted {
|
||||||
|
border: 2px dashed #999 !important;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-uploading {
|
||||||
|
background: url(../img/loading-sm.gif) no-repeat center bottom 10px;
|
||||||
|
opacity: 0.65;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 576px) {
|
||||||
|
.file-zoom-dialog .modal-dialog {
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
.file-zoom-dialog .modal-lg {
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-fullscreen.modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-fullscreen .modal-dialog {
|
||||||
|
position: fixed;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-fullscreen .modal-content {
|
||||||
|
border-radius: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-fullscreen .modal-body {
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-buttons {
|
||||||
|
z-index: 3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-buttons .btn-kv {
|
||||||
|
margin-left: 3px;
|
||||||
|
z-index: 3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content {
|
||||||
|
height: 480px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content .file-preview-image {
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content .file-preview-video {
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content .is-portrait-gt4 {
|
||||||
|
margin-top: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content > .file-object.type-image {
|
||||||
|
height: auto;
|
||||||
|
min-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content > .file-object.type-audio {
|
||||||
|
width: auto;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 767px) {
|
||||||
|
.file-preview-thumbnails {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .modal-header {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 350px) {
|
||||||
|
.krajee-default.file-preview-frame .kv-file-content {
|
||||||
|
width: 160px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-loading[dir=rtl]:before {
|
||||||
|
background: transparent url(../img/loading.gif) top right no-repeat;
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-sortable .file-drag-handle {
|
||||||
|
cursor: move;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-sortable .file-drag-handle:hover {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clickable .file-drop-zone-title {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-zoom-actions .btn-kv {
|
||||||
|
margin-left: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview-initial.sortable-chosen {
|
||||||
|
background-color: #d9edf7;
|
||||||
|
}
|
12
src/main/resources/static/css/plugins/fileinput/fileinput.min.css
vendored
Normal file
12
src/main/resources/static/css/plugins/fileinput/fileinput.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
4463
src/main/resources/static/js/plugins/fileinput/fileinput.js
Normal file
4463
src/main/resources/static/js/plugins/fileinput/fileinput.js
Normal file
File diff suppressed because it is too large
Load Diff
12
src/main/resources/static/js/plugins/fileinput/fileinput.min.js
vendored
Normal file
12
src/main/resources/static/js/plugins/fileinput/fileinput.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
100
src/main/resources/static/js/plugins/fileinput/locales/zh.js
Normal file
100
src/main/resources/static/js/plugins/fileinput/locales/zh.js
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/*!
|
||||||
|
* FileInput Chinese Translations
|
||||||
|
*
|
||||||
|
* This file must be loaded after 'fileinput.js'. Patterns in braces '{}', or
|
||||||
|
* any HTML markup tags in the messages must not be converted or translated.
|
||||||
|
*
|
||||||
|
* @see http://github.com/kartik-v/bootstrap-fileinput
|
||||||
|
* @author kangqf <kangqingfei@gmail.com>
|
||||||
|
*
|
||||||
|
* NOTE: this file must be saved in UTF-8 encoding.
|
||||||
|
*/
|
||||||
|
(function ($) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
$.fn.fileinputLocales['zh'] = {
|
||||||
|
fileSingle: '文件',
|
||||||
|
filePlural: '个文件',
|
||||||
|
browseLabel: '选择 …',
|
||||||
|
removeLabel: '移除',
|
||||||
|
removeTitle: '清除选中文件',
|
||||||
|
cancelLabel: '取消',
|
||||||
|
cancelTitle: '取消进行中的上传',
|
||||||
|
uploadLabel: '上传',
|
||||||
|
uploadTitle: '上传选中文件',
|
||||||
|
msgNo: '没有',
|
||||||
|
msgNoFilesSelected: '未选择文件',
|
||||||
|
msgCancelled: '取消',
|
||||||
|
msgPlaceholder: '选择 {files}...',
|
||||||
|
msgZoomModalHeading: '详细预览',
|
||||||
|
msgFileRequired: '必须选择一个文件上传.',
|
||||||
|
msgSizeTooSmall: '文件 "{name}" (<b>{size} KB</b>) 必须大于限定大小 <b>{minSize} KB</b>.',
|
||||||
|
msgSizeTooLarge: '文件 "{name}" (<b>{size} KB</b>) 超过了允许大小 <b>{maxSize} KB</b>.',
|
||||||
|
msgFilesTooLess: '你必须选择最少 <b>{n}</b> {files} 来上传. ',
|
||||||
|
msgFilesTooMany: '选择的上传文件个数 <b>({n})</b> 超出最大文件的限制个数 <b>{m}</b>.',
|
||||||
|
msgFileNotFound: '文件 "{name}" 未找到!',
|
||||||
|
msgFileSecured: '安全限制,为了防止读取文件 "{name}".',
|
||||||
|
msgFileNotReadable: '文件 "{name}" 不可读.',
|
||||||
|
msgFilePreviewAborted: '取消 "{name}" 的预览.',
|
||||||
|
msgFilePreviewError: '读取 "{name}" 时出现了一个错误.',
|
||||||
|
msgInvalidFileName: '文件名 "{name}" 包含非法字符.',
|
||||||
|
msgInvalidFileType: '不正确的类型 "{name}". 只支持 "{types}" 类型的文件.',
|
||||||
|
msgInvalidFileExtension: '不正确的文件扩展名 "{name}". 只支持 "{extensions}" 的文件扩展名.',
|
||||||
|
msgFileTypes: {
|
||||||
|
'image': 'image',
|
||||||
|
'html': 'HTML',
|
||||||
|
'text': 'text',
|
||||||
|
'video': 'video',
|
||||||
|
'audio': 'audio',
|
||||||
|
'flash': 'flash',
|
||||||
|
'pdf': 'PDF',
|
||||||
|
'object': 'object'
|
||||||
|
},
|
||||||
|
msgUploadAborted: '该文件上传被中止',
|
||||||
|
msgUploadThreshold: '处理中...',
|
||||||
|
msgUploadBegin: '正在初始化...',
|
||||||
|
msgUploadEnd: '完成',
|
||||||
|
msgUploadEmpty: '无效的文件上传.',
|
||||||
|
msgUploadError: '上传出错',
|
||||||
|
msgValidationError: '验证错误',
|
||||||
|
msgLoading: '加载第 {index} 文件 共 {files} …',
|
||||||
|
msgProgress: '加载第 {index} 文件 共 {files} - {name} - {percent}% 完成.',
|
||||||
|
msgSelected: '{n} {files} 选中',
|
||||||
|
msgFoldersNotAllowed: '只支持拖拽文件! 跳过 {n} 拖拽的文件夹.',
|
||||||
|
msgImageWidthSmall: '图像文件的"{name}"的宽度必须是至少{size}像素.',
|
||||||
|
msgImageHeightSmall: '图像文件的"{name}"的高度必须至少为{size}像素.',
|
||||||
|
msgImageWidthLarge: '图像文件"{name}"的宽度不能超过{size}像素.',
|
||||||
|
msgImageHeightLarge: '图像文件"{name}"的高度不能超过{size}像素.',
|
||||||
|
msgImageResizeError: '无法获取的图像尺寸调整。',
|
||||||
|
msgImageResizeException: '调整图像大小时发生错误。<pre>{errors}</pre>',
|
||||||
|
msgAjaxError: '{operation} 发生错误. 请重试!',
|
||||||
|
msgAjaxProgressError: '{operation} 失败',
|
||||||
|
ajaxOperations: {
|
||||||
|
deleteThumb: '删除文件',
|
||||||
|
uploadThumb: '上传文件',
|
||||||
|
uploadBatch: '批量上传',
|
||||||
|
uploadExtra: '表单数据上传'
|
||||||
|
},
|
||||||
|
dropZoneTitle: '拖拽文件到这里 …<br>支持多文件同时上传',
|
||||||
|
dropZoneClickTitle: '<br>(或点击{files}按钮选择文件)',
|
||||||
|
fileActionSettings: {
|
||||||
|
removeTitle: '删除文件',
|
||||||
|
uploadTitle: '上传文件',
|
||||||
|
uploadRetryTitle: '重试',
|
||||||
|
zoomTitle: '查看详情',
|
||||||
|
dragTitle: '移动 / 重置',
|
||||||
|
indicatorNewTitle: '没有上传',
|
||||||
|
indicatorSuccessTitle: '上传',
|
||||||
|
indicatorErrorTitle: '上传错误',
|
||||||
|
indicatorLoadingTitle: '上传 ...'
|
||||||
|
},
|
||||||
|
previewZoomButtonTitles: {
|
||||||
|
prev: '预览上一个文件',
|
||||||
|
next: '预览下一个文件',
|
||||||
|
toggleheader: '缩放',
|
||||||
|
fullscreen: '全屏',
|
||||||
|
borderless: '无边界模式',
|
||||||
|
close: '关闭当前预览'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(window.jQuery);
|
2471
src/main/resources/static/js/plugins/fileinput/plugins/piexif.js
Normal file
2471
src/main/resources/static/js/plugins/fileinput/plugins/piexif.js
Normal file
File diff suppressed because it is too large
Load Diff
1
src/main/resources/static/js/plugins/fileinput/plugins/piexif.min.js
vendored
Normal file
1
src/main/resources/static/js/plugins/fileinput/plugins/piexif.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
812
src/main/resources/static/js/plugins/fileinput/plugins/purify.js
Normal file
812
src/main/resources/static/js/plugins/fileinput/plugins/purify.js
Normal file
@ -0,0 +1,812 @@
|
|||||||
|
;(function(factory) {
|
||||||
|
'use strict';
|
||||||
|
/* global window: false, define: false, module: false */
|
||||||
|
var root = typeof window === 'undefined' ? null : window;
|
||||||
|
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
define(function(){ return factory(root); });
|
||||||
|
} else if (typeof module !== 'undefined') {
|
||||||
|
module.exports = factory(root);
|
||||||
|
} else {
|
||||||
|
root.DOMPurify = factory(root);
|
||||||
|
}
|
||||||
|
}(function factory(window) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var DOMPurify = function(window) {
|
||||||
|
return factory(window);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Version label, exposed for easier checks
|
||||||
|
* if DOMPurify is up to date or not
|
||||||
|
*/
|
||||||
|
DOMPurify.version = '0.7.4';
|
||||||
|
|
||||||
|
if (!window || !window.document || window.document.nodeType !== 9) {
|
||||||
|
// not running in a browser, provide a factory function
|
||||||
|
// so that you can pass your own Window
|
||||||
|
DOMPurify.isSupported = false;
|
||||||
|
return DOMPurify;
|
||||||
|
}
|
||||||
|
|
||||||
|
var document = window.document;
|
||||||
|
var originalDocument = document;
|
||||||
|
var DocumentFragment = window.DocumentFragment;
|
||||||
|
var HTMLTemplateElement = window.HTMLTemplateElement;
|
||||||
|
var NodeFilter = window.NodeFilter;
|
||||||
|
var NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap;
|
||||||
|
var Text = window.Text;
|
||||||
|
var Comment = window.Comment;
|
||||||
|
var DOMParser = window.DOMParser;
|
||||||
|
|
||||||
|
// As per issue #47, the web-components registry is inherited by a
|
||||||
|
// new document created via createHTMLDocument. As per the spec
|
||||||
|
// (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
|
||||||
|
// a new empty registry is used when creating a template contents owner
|
||||||
|
// document, so we use that as our parent document to ensure nothing
|
||||||
|
// is inherited.
|
||||||
|
if (typeof HTMLTemplateElement === 'function') {
|
||||||
|
var template = document.createElement('template');
|
||||||
|
if (template.content && template.content.ownerDocument) {
|
||||||
|
document = template.content.ownerDocument;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var implementation = document.implementation;
|
||||||
|
var createNodeIterator = document.createNodeIterator;
|
||||||
|
var getElementsByTagName = document.getElementsByTagName;
|
||||||
|
var createDocumentFragment = document.createDocumentFragment;
|
||||||
|
var importNode = originalDocument.importNode;
|
||||||
|
|
||||||
|
var hooks = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expose whether this browser supports running the full DOMPurify.
|
||||||
|
*/
|
||||||
|
DOMPurify.isSupported =
|
||||||
|
typeof implementation.createHTMLDocument !== 'undefined' &&
|
||||||
|
document.documentMode !== 9;
|
||||||
|
|
||||||
|
/* Add properties to a lookup table */
|
||||||
|
var _addToSet = function(set, array) {
|
||||||
|
var l = array.length;
|
||||||
|
while (l--) {
|
||||||
|
if (typeof array[l] === 'string') {
|
||||||
|
array[l] = array[l].toLowerCase();
|
||||||
|
}
|
||||||
|
set[array[l]] = true;
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Shallow clone an object */
|
||||||
|
var _cloneObj = function(object) {
|
||||||
|
var newObject = {};
|
||||||
|
var property;
|
||||||
|
for (property in object) {
|
||||||
|
if (object.hasOwnProperty(property)) {
|
||||||
|
newObject[property] = object[property];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We consider the elements and attributes below to be safe. Ideally
|
||||||
|
* don't add any new ones but feel free to remove unwanted ones.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* allowed element names */
|
||||||
|
var ALLOWED_TAGS = null;
|
||||||
|
var DEFAULT_ALLOWED_TAGS = _addToSet({}, [
|
||||||
|
|
||||||
|
// HTML
|
||||||
|
'a','abbr','acronym','address','area','article','aside','audio','b',
|
||||||
|
'bdi','bdo','big','blink','blockquote','body','br','button','canvas',
|
||||||
|
'caption','center','cite','code','col','colgroup','content','data',
|
||||||
|
'datalist','dd','decorator','del','details','dfn','dir','div','dl','dt',
|
||||||
|
'element','em','fieldset','figcaption','figure','font','footer','form',
|
||||||
|
'h1','h2','h3','h4','h5','h6','head','header','hgroup','hr','html','i',
|
||||||
|
'img','input','ins','kbd','label','legend','li','main','map','mark',
|
||||||
|
'marquee','menu','menuitem','meter','nav','nobr','ol','optgroup',
|
||||||
|
'option','output','p','pre','progress','q','rp','rt','ruby','s','samp',
|
||||||
|
'section','select','shadow','small','source','spacer','span','strike',
|
||||||
|
'strong','style','sub','summary','sup','table','tbody','td','template',
|
||||||
|
'textarea','tfoot','th','thead','time','tr','track','tt','u','ul','var',
|
||||||
|
'video','wbr',
|
||||||
|
|
||||||
|
// SVG
|
||||||
|
'svg','altglyph','altglyphdef','altglyphitem','animatecolor',
|
||||||
|
'animatemotion','animatetransform','circle','clippath','defs','desc',
|
||||||
|
'ellipse','filter','font','g','glyph','glyphref','hkern','image','line',
|
||||||
|
'lineargradient','marker','mask','metadata','mpath','path','pattern',
|
||||||
|
'polygon','polyline','radialgradient','rect','stop','switch','symbol',
|
||||||
|
'text','textpath','title','tref','tspan','view','vkern',
|
||||||
|
|
||||||
|
// SVG Filters
|
||||||
|
'feBlend','feColorMatrix','feComponentTransfer','feComposite',
|
||||||
|
'feConvolveMatrix','feDiffuseLighting','feDisplacementMap',
|
||||||
|
'feFlood','feFuncA','feFuncB','feFuncG','feFuncR','feGaussianBlur',
|
||||||
|
'feMerge','feMergeNode','feMorphology','feOffset',
|
||||||
|
'feSpecularLighting','feTile','feTurbulence',
|
||||||
|
|
||||||
|
//MathML
|
||||||
|
'math','menclose','merror','mfenced','mfrac','mglyph','mi','mlabeledtr',
|
||||||
|
'mmuliscripts','mn','mo','mover','mpadded','mphantom','mroot','mrow',
|
||||||
|
'ms','mpspace','msqrt','mystyle','msub','msup','msubsup','mtable','mtd',
|
||||||
|
'mtext','mtr','munder','munderover',
|
||||||
|
|
||||||
|
//Text
|
||||||
|
'#text'
|
||||||
|
]);
|
||||||
|
|
||||||
|
/* Allowed attribute names */
|
||||||
|
var ALLOWED_ATTR = null;
|
||||||
|
var DEFAULT_ALLOWED_ATTR = _addToSet({}, [
|
||||||
|
|
||||||
|
// HTML
|
||||||
|
'accept','action','align','alt','autocomplete','background','bgcolor',
|
||||||
|
'border','cellpadding','cellspacing','checked','cite','class','clear','color',
|
||||||
|
'cols','colspan','coords','datetime','default','dir','disabled',
|
||||||
|
'download','enctype','face','for','headers','height','hidden','high','href',
|
||||||
|
'hreflang','id','ismap','label','lang','list','loop', 'low','max',
|
||||||
|
'maxlength','media','method','min','multiple','name','noshade','novalidate',
|
||||||
|
'nowrap','open','optimum','pattern','placeholder','poster','preload','pubdate',
|
||||||
|
'radiogroup','readonly','rel','required','rev','reversed','rows',
|
||||||
|
'rowspan','spellcheck','scope','selected','shape','size','span',
|
||||||
|
'srclang','start','src','step','style','summary','tabindex','title',
|
||||||
|
'type','usemap','valign','value','width','xmlns',
|
||||||
|
|
||||||
|
// SVG
|
||||||
|
'accent-height','accumulate','additivive','alignment-baseline',
|
||||||
|
'ascent','attributename','attributetype','azimuth','basefrequency',
|
||||||
|
'baseline-shift','begin','bias','by','clip','clip-path','clip-rule',
|
||||||
|
'color','color-interpolation','color-interpolation-filters','color-profile',
|
||||||
|
'color-rendering','cx','cy','d','dx','dy','diffuseconstant','direction',
|
||||||
|
'display','divisor','dur','edgemode','elevation','end','fill','fill-opacity',
|
||||||
|
'fill-rule','filter','flood-color','flood-opacity','font-family','font-size',
|
||||||
|
'font-size-adjust','font-stretch','font-style','font-variant','font-weight',
|
||||||
|
'fx', 'fy','g1','g2','glyph-name','glyphref','gradientunits','gradienttransform',
|
||||||
|
'image-rendering','in','in2','k','k1','k2','k3','k4','kerning','keypoints',
|
||||||
|
'keysplines','keytimes','lengthadjust','letter-spacing','kernelmatrix',
|
||||||
|
'kernelunitlength','lighting-color','local','marker-end','marker-mid',
|
||||||
|
'marker-start','markerheight','markerunits','markerwidth','maskcontentunits',
|
||||||
|
'maskunits','max','mask','mode','min','numoctaves','offset','operator',
|
||||||
|
'opacity','order','orient','orientation','origin','overflow','paint-order',
|
||||||
|
'path','pathlength','patterncontentunits','patterntransform','patternunits',
|
||||||
|
'points','preservealpha','r','rx','ry','radius','refx','refy','repeatcount',
|
||||||
|
'repeatdur','restart','result','rotate','scale','seed','shape-rendering',
|
||||||
|
'specularconstant','specularexponent','spreadmethod','stddeviation','stitchtiles',
|
||||||
|
'stop-color','stop-opacity','stroke-dasharray','stroke-dashoffset','stroke-linecap',
|
||||||
|
'stroke-linejoin','stroke-miterlimit','stroke-opacity','stroke','stroke-width',
|
||||||
|
'surfacescale','targetx','targety','transform','text-anchor','text-decoration',
|
||||||
|
'text-rendering','textlength','u1','u2','unicode','values','viewbox',
|
||||||
|
'visibility','vert-adv-y','vert-origin-x','vert-origin-y','word-spacing',
|
||||||
|
'wrap','writing-mode','xchannelselector','ychannelselector','x','x1','x2',
|
||||||
|
'y','y1','y2','z','zoomandpan',
|
||||||
|
|
||||||
|
// MathML
|
||||||
|
'accent','accentunder','bevelled','close','columnsalign','columnlines',
|
||||||
|
'columnspan','denomalign','depth','display','displaystyle','fence',
|
||||||
|
'frame','largeop','length','linethickness','lspace','lquote',
|
||||||
|
'mathbackground','mathcolor','mathsize','mathvariant','maxsize',
|
||||||
|
'minsize','movablelimits','notation','numalign','open','rowalign',
|
||||||
|
'rowlines','rowspacing','rowspan','rspace','rquote','scriptlevel',
|
||||||
|
'scriptminsize','scriptsizemultiplier','selection','separator',
|
||||||
|
'separators','stretchy','subscriptshift','supscriptshift','symmetric',
|
||||||
|
'voffset',
|
||||||
|
|
||||||
|
// XML
|
||||||
|
'xlink:href','xml:id','xlink:title','xml:space','xmlns:xlink'
|
||||||
|
]);
|
||||||
|
|
||||||
|
/* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
|
||||||
|
var FORBID_TAGS = null;
|
||||||
|
|
||||||
|
/* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
|
||||||
|
var FORBID_ATTR = null;
|
||||||
|
|
||||||
|
/* Decide if custom data attributes are okay */
|
||||||
|
var ALLOW_DATA_ATTR = true;
|
||||||
|
|
||||||
|
/* Decide if unknown protocols are okay */
|
||||||
|
var ALLOW_UNKNOWN_PROTOCOLS = false;
|
||||||
|
|
||||||
|
/* Output should be safe for jQuery's $() factory? */
|
||||||
|
var SAFE_FOR_JQUERY = false;
|
||||||
|
|
||||||
|
/* Output should be safe for common template engines.
|
||||||
|
* This means, DOMPurify removes data attributes, mustaches and ERB
|
||||||
|
*/
|
||||||
|
var SAFE_FOR_TEMPLATES = false;
|
||||||
|
|
||||||
|
/* Specify template detection regex for SAFE_FOR_TEMPLATES mode */
|
||||||
|
var MUSTACHE_EXPR = /\{\{[\s\S]*|[\s\S]*\}\}/gm;
|
||||||
|
var ERB_EXPR = /<%[\s\S]*|[\s\S]*%>/gm;
|
||||||
|
|
||||||
|
/* Decide if document with <html>... should be returned */
|
||||||
|
var WHOLE_DOCUMENT = false;
|
||||||
|
|
||||||
|
/* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html string.
|
||||||
|
* If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
|
||||||
|
*/
|
||||||
|
var RETURN_DOM = false;
|
||||||
|
|
||||||
|
/* Decide if a DOM `DocumentFragment` should be returned, instead of a html string */
|
||||||
|
var RETURN_DOM_FRAGMENT = false;
|
||||||
|
|
||||||
|
/* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM
|
||||||
|
* `Node` is imported into the current `Document`. If this flag is not enabled the
|
||||||
|
* `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by
|
||||||
|
* DOMPurify. */
|
||||||
|
var RETURN_DOM_IMPORT = false;
|
||||||
|
|
||||||
|
/* Output should be free from DOM clobbering attacks? */
|
||||||
|
var SANITIZE_DOM = true;
|
||||||
|
|
||||||
|
/* Keep element content when removing element? */
|
||||||
|
var KEEP_CONTENT = true;
|
||||||
|
|
||||||
|
/* Tags to ignore content of when KEEP_CONTENT is true */
|
||||||
|
var FORBID_CONTENTS = _addToSet({}, [
|
||||||
|
'audio', 'head', 'math', 'script', 'style', 'svg', 'video'
|
||||||
|
]);
|
||||||
|
|
||||||
|
/* Tags that are safe for data: URIs */
|
||||||
|
var DATA_URI_TAGS = _addToSet({}, [
|
||||||
|
'audio', 'video', 'img', 'source'
|
||||||
|
]);
|
||||||
|
|
||||||
|
/* Attributes safe for values like "javascript:" */
|
||||||
|
var URI_SAFE_ATTRIBUTES = _addToSet({}, [
|
||||||
|
'alt','class','for','id','label','name','pattern','placeholder',
|
||||||
|
'summary','title','value','style','xmlns'
|
||||||
|
]);
|
||||||
|
|
||||||
|
/* Keep a reference to config to pass to hooks */
|
||||||
|
var CONFIG = null;
|
||||||
|
|
||||||
|
/* Ideally, do not touch anything below this line */
|
||||||
|
/* ______________________________________________ */
|
||||||
|
|
||||||
|
var formElement = document.createElement('form');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _parseConfig
|
||||||
|
*
|
||||||
|
* @param optional config literal
|
||||||
|
*/
|
||||||
|
var _parseConfig = function(cfg) {
|
||||||
|
/* Shield configuration object from tampering */
|
||||||
|
if (typeof cfg !== 'object') {
|
||||||
|
cfg = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set configuration parameters */
|
||||||
|
ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ?
|
||||||
|
_addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
|
||||||
|
ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ?
|
||||||
|
_addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
|
||||||
|
FORBID_TAGS = 'FORBID_TAGS' in cfg ?
|
||||||
|
_addToSet({}, cfg.FORBID_TAGS) : {};
|
||||||
|
FORBID_ATTR = 'FORBID_ATTR' in cfg ?
|
||||||
|
_addToSet({}, cfg.FORBID_ATTR) : {};
|
||||||
|
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
|
||||||
|
ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
|
||||||
|
SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY || false; // Default false
|
||||||
|
SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
|
||||||
|
WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
|
||||||
|
RETURN_DOM = cfg.RETURN_DOM || false; // Default false
|
||||||
|
RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
|
||||||
|
RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT || false; // Default false
|
||||||
|
SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
|
||||||
|
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
||||||
|
|
||||||
|
if (SAFE_FOR_TEMPLATES) {
|
||||||
|
ALLOW_DATA_ATTR = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RETURN_DOM_FRAGMENT) {
|
||||||
|
RETURN_DOM = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Merge configuration parameters */
|
||||||
|
if (cfg.ADD_TAGS) {
|
||||||
|
if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
|
||||||
|
ALLOWED_TAGS = _cloneObj(ALLOWED_TAGS);
|
||||||
|
}
|
||||||
|
_addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
|
||||||
|
}
|
||||||
|
if (cfg.ADD_ATTR) {
|
||||||
|
if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
|
||||||
|
ALLOWED_ATTR = _cloneObj(ALLOWED_ATTR);
|
||||||
|
}
|
||||||
|
_addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add #text in case KEEP_CONTENT is set to true */
|
||||||
|
if (KEEP_CONTENT) { ALLOWED_TAGS['#text'] = true; }
|
||||||
|
|
||||||
|
// Prevent further manipulation of configuration.
|
||||||
|
// Not available in IE8, Safari 5, etc.
|
||||||
|
if (Object && 'freeze' in Object) { Object.freeze(cfg); }
|
||||||
|
|
||||||
|
CONFIG = cfg;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _forceRemove
|
||||||
|
*
|
||||||
|
* @param a DOM node
|
||||||
|
*/
|
||||||
|
var _forceRemove = function(node) {
|
||||||
|
try {
|
||||||
|
node.parentNode.removeChild(node);
|
||||||
|
} catch (e) {
|
||||||
|
node.outerHTML = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _initDocument
|
||||||
|
*
|
||||||
|
* @param a string of dirty markup
|
||||||
|
* @return a DOM, filled with the dirty markup
|
||||||
|
*/
|
||||||
|
var _initDocument = function(dirty) {
|
||||||
|
/* Create a HTML document using DOMParser */
|
||||||
|
var doc, body;
|
||||||
|
try {
|
||||||
|
doc = new DOMParser().parseFromString(dirty, 'text/html');
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
/* Some browsers throw, some browsers return null for the code above
|
||||||
|
DOMParser with text/html support is only in very recent browsers. */
|
||||||
|
if (!doc) {
|
||||||
|
doc = implementation.createHTMLDocument('');
|
||||||
|
body = doc.body;
|
||||||
|
body.parentNode.removeChild(body.parentNode.firstElementChild);
|
||||||
|
body.outerHTML = dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Work on whole document or just its body */
|
||||||
|
if (typeof doc.getElementsByTagName === 'function') {
|
||||||
|
return doc.getElementsByTagName(
|
||||||
|
WHOLE_DOCUMENT ? 'html' : 'body')[0];
|
||||||
|
}
|
||||||
|
return getElementsByTagName.call(doc,
|
||||||
|
WHOLE_DOCUMENT ? 'html' : 'body')[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _createIterator
|
||||||
|
*
|
||||||
|
* @param document/fragment to create iterator for
|
||||||
|
* @return iterator instance
|
||||||
|
*/
|
||||||
|
var _createIterator = function(root) {
|
||||||
|
return createNodeIterator.call(root.ownerDocument || root,
|
||||||
|
root,
|
||||||
|
NodeFilter.SHOW_ELEMENT
|
||||||
|
| NodeFilter.SHOW_COMMENT
|
||||||
|
| NodeFilter.SHOW_TEXT,
|
||||||
|
function() { return NodeFilter.FILTER_ACCEPT; },
|
||||||
|
false
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _isClobbered
|
||||||
|
*
|
||||||
|
* @param element to check for clobbering attacks
|
||||||
|
* @return true if clobbered, false if safe
|
||||||
|
*/
|
||||||
|
var _isClobbered = function(elm) {
|
||||||
|
if (elm instanceof Text || elm instanceof Comment) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( typeof elm.nodeName !== 'string'
|
||||||
|
|| typeof elm.textContent !== 'string'
|
||||||
|
|| typeof elm.removeChild !== 'function'
|
||||||
|
|| !(elm.attributes instanceof NamedNodeMap)
|
||||||
|
|| typeof elm.removeAttribute !== 'function'
|
||||||
|
|| typeof elm.setAttribute !== 'function'
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _sanitizeElements
|
||||||
|
*
|
||||||
|
* @protect nodeName
|
||||||
|
* @protect textContent
|
||||||
|
* @protect removeChild
|
||||||
|
*
|
||||||
|
* @param node to check for permission to exist
|
||||||
|
* @return true if node was killed, false if left alive
|
||||||
|
*/
|
||||||
|
var _sanitizeElements = function(currentNode) {
|
||||||
|
var tagName, content;
|
||||||
|
/* Execute a hook if present */
|
||||||
|
_executeHook('beforeSanitizeElements', currentNode, null);
|
||||||
|
|
||||||
|
/* Check if element is clobbered or can clobber */
|
||||||
|
if (_isClobbered(currentNode)) {
|
||||||
|
_forceRemove(currentNode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now let's check the element's type and name */
|
||||||
|
tagName = currentNode.nodeName.toLowerCase();
|
||||||
|
|
||||||
|
/* Execute a hook if present */
|
||||||
|
_executeHook('uponSanitizeElement', currentNode, {
|
||||||
|
tagName: tagName
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Remove element if anything forbids its presence */
|
||||||
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
||||||
|
/* Keep content except for black-listed elements */
|
||||||
|
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]
|
||||||
|
&& typeof currentNode.insertAdjacentHTML === 'function') {
|
||||||
|
try {
|
||||||
|
currentNode.insertAdjacentHTML('AfterEnd', currentNode.innerHTML);
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
_forceRemove(currentNode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert markup to cover jQuery behavior */
|
||||||
|
if (SAFE_FOR_JQUERY && !currentNode.firstElementChild &&
|
||||||
|
(!currentNode.content || !currentNode.content.firstElementChild)) {
|
||||||
|
currentNode.innerHTML = currentNode.textContent.replace(/</g, '<');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanitize element content to be template-safe */
|
||||||
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
|
||||||
|
/* Get the element's text content */
|
||||||
|
content = currentNode.textContent;
|
||||||
|
content = content.replace(MUSTACHE_EXPR, ' ');
|
||||||
|
content = content.replace(ERB_EXPR, ' ');
|
||||||
|
currentNode.textContent = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Execute a hook if present */
|
||||||
|
_executeHook('afterSanitizeElements', currentNode, null);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
var DATA_ATTR = /^data-[\w.\u00B7-\uFFFF-]/;
|
||||||
|
var IS_ALLOWED_URI = /^(?:(?:(?:f|ht)tps?|mailto|tel):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;
|
||||||
|
var IS_SCRIPT_OR_DATA = /^(?:\w+script|data):/i;
|
||||||
|
/* This needs to be extensive thanks to Webkit/Blink's behavior */
|
||||||
|
var ATTR_WHITESPACE = /[\x00-\x20\xA0\u1680\u180E\u2000-\u2029\u205f\u3000]/g;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _sanitizeAttributes
|
||||||
|
*
|
||||||
|
* @protect attributes
|
||||||
|
* @protect nodeName
|
||||||
|
* @protect removeAttribute
|
||||||
|
* @protect setAttribute
|
||||||
|
*
|
||||||
|
* @param node to sanitize
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
var _sanitizeAttributes = function(currentNode) {
|
||||||
|
var attr, name, value, lcName, idAttr, attributes, hookEvent, l;
|
||||||
|
/* Execute a hook if present */
|
||||||
|
_executeHook('beforeSanitizeAttributes', currentNode, null);
|
||||||
|
|
||||||
|
attributes = currentNode.attributes;
|
||||||
|
|
||||||
|
/* Check if we have attributes; if not we might have a text node */
|
||||||
|
if (!attributes) { return; }
|
||||||
|
|
||||||
|
hookEvent = {
|
||||||
|
attrName: '',
|
||||||
|
attrValue: '',
|
||||||
|
keepAttr: true
|
||||||
|
};
|
||||||
|
l = attributes.length;
|
||||||
|
|
||||||
|
/* Go backwards over all attributes; safely remove bad ones */
|
||||||
|
while (l--) {
|
||||||
|
attr = attributes[l];
|
||||||
|
name = attr.name;
|
||||||
|
value = attr.value;
|
||||||
|
lcName = name.toLowerCase();
|
||||||
|
|
||||||
|
/* Execute a hook if present */
|
||||||
|
hookEvent.attrName = lcName;
|
||||||
|
hookEvent.attrValue = value;
|
||||||
|
hookEvent.keepAttr = true;
|
||||||
|
_executeHook('uponSanitizeAttribute', currentNode, hookEvent );
|
||||||
|
value = hookEvent.attrValue;
|
||||||
|
|
||||||
|
/* Remove attribute */
|
||||||
|
// Safari (iOS + Mac), last tested v8.0.5, crashes if you try to
|
||||||
|
// remove a "name" attribute from an <img> tag that has an "id"
|
||||||
|
// attribute at the time.
|
||||||
|
if (lcName === 'name' &&
|
||||||
|
currentNode.nodeName === 'IMG' && attributes.id) {
|
||||||
|
idAttr = attributes.id;
|
||||||
|
attributes = Array.prototype.slice.apply(attributes);
|
||||||
|
currentNode.removeAttribute('id');
|
||||||
|
currentNode.removeAttribute(name);
|
||||||
|
if (attributes.indexOf(idAttr) > l) {
|
||||||
|
currentNode.setAttribute('id', idAttr.value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// This avoids a crash in Safari v9.0 with double-ids.
|
||||||
|
// The trick is to first set the id to be empty and then to
|
||||||
|
// remove the attriubute
|
||||||
|
if (name === 'id') {
|
||||||
|
currentNode.setAttribute(name, '');
|
||||||
|
}
|
||||||
|
currentNode.removeAttribute(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Did the hooks approve of the attribute? */
|
||||||
|
if (!hookEvent.keepAttr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure attribute cannot clobber */
|
||||||
|
if (SANITIZE_DOM &&
|
||||||
|
(lcName === 'id' || lcName === 'name') &&
|
||||||
|
(value in window || value in document || value in formElement)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanitize attribute content to be template-safe */
|
||||||
|
if (SAFE_FOR_TEMPLATES) {
|
||||||
|
value = value.replace(MUSTACHE_EXPR, ' ');
|
||||||
|
value = value.replace(ERB_EXPR, ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
/* Check the name is permitted */
|
||||||
|
(ALLOWED_ATTR[lcName] && !FORBID_ATTR[lcName] && (
|
||||||
|
/* Check no script, data or unknown possibly unsafe URI
|
||||||
|
unless we know URI values are safe for that attribute */
|
||||||
|
URI_SAFE_ATTRIBUTES[lcName] ||
|
||||||
|
IS_ALLOWED_URI.test(value.replace(ATTR_WHITESPACE,'')) ||
|
||||||
|
/* Keep image data URIs alive if src is allowed */
|
||||||
|
(lcName === 'src' && value.indexOf('data:') === 0 &&
|
||||||
|
DATA_URI_TAGS[currentNode.nodeName.toLowerCase()])
|
||||||
|
)) ||
|
||||||
|
/* Allow potentially valid data-* attributes:
|
||||||
|
* At least one character after "-" (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
||||||
|
* XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
||||||
|
* We don't need to check the value; it's always URI safe.
|
||||||
|
*/
|
||||||
|
(ALLOW_DATA_ATTR && DATA_ATTR.test(lcName)) ||
|
||||||
|
/* Allow unknown protocols:
|
||||||
|
* This provides support for links that are handled by protocol handlers which may be unknown
|
||||||
|
* ahead of time, e.g. fb:, spotify:
|
||||||
|
*/
|
||||||
|
(ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA.test(value.replace(ATTR_WHITESPACE,'')))
|
||||||
|
) {
|
||||||
|
/* Handle invalid data-* attribute set by try-catching it */
|
||||||
|
try {
|
||||||
|
currentNode.setAttribute(name, value);
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Execute a hook if present */
|
||||||
|
_executeHook('afterSanitizeAttributes', currentNode, null);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _sanitizeShadowDOM
|
||||||
|
*
|
||||||
|
* @param fragment to iterate over recursively
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
var _sanitizeShadowDOM = function(fragment) {
|
||||||
|
var shadowNode;
|
||||||
|
var shadowIterator = _createIterator(fragment);
|
||||||
|
|
||||||
|
/* Execute a hook if present */
|
||||||
|
_executeHook('beforeSanitizeShadowDOM', fragment, null);
|
||||||
|
|
||||||
|
while ( (shadowNode = shadowIterator.nextNode()) ) {
|
||||||
|
/* Execute a hook if present */
|
||||||
|
_executeHook('uponSanitizeShadowNode', shadowNode, null);
|
||||||
|
|
||||||
|
/* Sanitize tags and elements */
|
||||||
|
if (_sanitizeElements(shadowNode)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Deep shadow DOM detected */
|
||||||
|
if (shadowNode.content instanceof DocumentFragment) {
|
||||||
|
_sanitizeShadowDOM(shadowNode.content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check attributes, sanitize if necessary */
|
||||||
|
_sanitizeAttributes(shadowNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Execute a hook if present */
|
||||||
|
_executeHook('afterSanitizeShadowDOM', fragment, null);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _executeHook
|
||||||
|
* Execute user configurable hooks
|
||||||
|
*
|
||||||
|
* @param {String} entryPoint Name of the hook's entry point
|
||||||
|
* @param {Node} currentNode
|
||||||
|
*/
|
||||||
|
var _executeHook = function(entryPoint, currentNode, data) {
|
||||||
|
if (!hooks[entryPoint]) { return; }
|
||||||
|
|
||||||
|
hooks[entryPoint].forEach(function(hook) {
|
||||||
|
hook.call(DOMPurify, currentNode, data, CONFIG);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sanitize
|
||||||
|
* Public method providing core sanitation functionality
|
||||||
|
*
|
||||||
|
* @param {String} dirty string
|
||||||
|
* @param {Object} configuration object
|
||||||
|
*/
|
||||||
|
DOMPurify.sanitize = function(dirty, cfg) {
|
||||||
|
var body, currentNode, oldNode, nodeIterator, returnNode;
|
||||||
|
/* Make sure we have a string to sanitize.
|
||||||
|
DO NOT return early, as this will return the wrong type if
|
||||||
|
the user has requested a DOM object rather than a string */
|
||||||
|
if (!dirty) {
|
||||||
|
dirty = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stringify, in case dirty is an object */
|
||||||
|
if (typeof dirty !== 'string') {
|
||||||
|
if (typeof dirty.toString !== 'function') {
|
||||||
|
throw new TypeError('toString is not a function');
|
||||||
|
} else {
|
||||||
|
dirty = dirty.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check we can run. Otherwise fall back or ignore */
|
||||||
|
if (!DOMPurify.isSupported) {
|
||||||
|
if (typeof window.toStaticHTML === 'object'
|
||||||
|
|| typeof window.toStaticHTML === 'function') {
|
||||||
|
return window.toStaticHTML(dirty);
|
||||||
|
}
|
||||||
|
return dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assign config vars */
|
||||||
|
_parseConfig(cfg);
|
||||||
|
|
||||||
|
/* Exit directly if we have nothing to do */
|
||||||
|
if (!RETURN_DOM && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
|
||||||
|
return dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the document to work on */
|
||||||
|
body = _initDocument(dirty);
|
||||||
|
|
||||||
|
/* Check we have a DOM node from the data */
|
||||||
|
if (!body) {
|
||||||
|
return RETURN_DOM ? null : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get node iterator */
|
||||||
|
nodeIterator = _createIterator(body);
|
||||||
|
|
||||||
|
/* Now start iterating over the created document */
|
||||||
|
while ( (currentNode = nodeIterator.nextNode()) ) {
|
||||||
|
|
||||||
|
/* Fix IE's strange behavior with manipulated textNodes #89 */
|
||||||
|
if (currentNode.nodeType === 3 && currentNode === oldNode) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanitize tags and elements */
|
||||||
|
if (_sanitizeElements(currentNode)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shadow DOM detected, sanitize it */
|
||||||
|
if (currentNode.content instanceof DocumentFragment) {
|
||||||
|
_sanitizeShadowDOM(currentNode.content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check attributes, sanitize if necessary */
|
||||||
|
_sanitizeAttributes(currentNode);
|
||||||
|
|
||||||
|
oldNode = currentNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return sanitized string or DOM */
|
||||||
|
if (RETURN_DOM) {
|
||||||
|
|
||||||
|
if (RETURN_DOM_FRAGMENT) {
|
||||||
|
returnNode = createDocumentFragment.call(body.ownerDocument);
|
||||||
|
|
||||||
|
while (body.firstChild) {
|
||||||
|
returnNode.appendChild(body.firstChild);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
returnNode = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RETURN_DOM_IMPORT) {
|
||||||
|
/* adoptNode() is not used because internal state is not reset
|
||||||
|
(e.g. the past names map of a HTMLFormElement), this is safe
|
||||||
|
in theory but we would rather not risk another attack vector.
|
||||||
|
The state that is cloned by importNode() is explicitly defined
|
||||||
|
by the specs. */
|
||||||
|
returnNode = importNode.call(originalDocument, returnNode, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* addHook
|
||||||
|
* Public method to add DOMPurify hooks
|
||||||
|
*
|
||||||
|
* @param {String} entryPoint
|
||||||
|
* @param {Function} hookFunction
|
||||||
|
*/
|
||||||
|
DOMPurify.addHook = function(entryPoint, hookFunction) {
|
||||||
|
if (typeof hookFunction !== 'function') { return; }
|
||||||
|
hooks[entryPoint] = hooks[entryPoint] || [];
|
||||||
|
hooks[entryPoint].push(hookFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* removeHook
|
||||||
|
* Public method to remove a DOMPurify hook at a given entryPoint
|
||||||
|
* (pops it from the stack of hooks if more are present)
|
||||||
|
*
|
||||||
|
* @param {String} entryPoint
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
DOMPurify.removeHook = function(entryPoint) {
|
||||||
|
if (hooks[entryPoint]) {
|
||||||
|
hooks[entryPoint].pop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* removeHooks
|
||||||
|
* Public method to remove all DOMPurify hooks at a given entryPoint
|
||||||
|
*
|
||||||
|
* @param {String} entryPoint
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
DOMPurify.removeHooks = function(entryPoint) {
|
||||||
|
if (hooks[entryPoint]) {
|
||||||
|
hooks[entryPoint] = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* removeAllHooks
|
||||||
|
* Public method to remove all DOMPurify hooks
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
DOMPurify.removeAllHooks = function() {
|
||||||
|
hooks = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
return DOMPurify;
|
||||||
|
}));
|
1
src/main/resources/static/js/plugins/fileinput/plugins/purify.min.js
vendored
Normal file
1
src/main/resources/static/js/plugins/fileinput/plugins/purify.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1590
src/main/resources/static/js/plugins/fileinput/plugins/sortable.js
Normal file
1590
src/main/resources/static/js/plugins/fileinput/plugins/sortable.js
Normal file
File diff suppressed because it is too large
Load Diff
1
src/main/resources/static/js/plugins/fileinput/plugins/sortable.min.js
vendored
Normal file
1
src/main/resources/static/js/plugins/fileinput/plugins/sortable.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -5,8 +5,11 @@ $(document).ready(function(){
|
|||||||
$('body').layout({ west__size: 185 });
|
$('body').layout({ west__size: 185 });
|
||||||
queryUserList();
|
queryUserList();
|
||||||
queryDeptTreeDaTa();
|
queryDeptTreeDaTa();
|
||||||
|
//加载文件输入框
|
||||||
|
fileinputlist();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function queryUserList() {
|
function queryUserList() {
|
||||||
var columns = [{
|
var columns = [{
|
||||||
checkbox: true
|
checkbox: true
|
||||||
@ -119,7 +122,25 @@ function queryDeptTreeDaTa()
|
|||||||
loadTree();
|
loadTree();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/** 初始化文件框*/
|
||||||
|
function fileinputlist(){
|
||||||
|
$('#uploadfile').fileinput({
|
||||||
|
language: 'zh', //设置语言
|
||||||
|
showPreview: false,//是否显示预览,不写默认为true
|
||||||
|
showUpload: false, //是否显示上传按钮,跟随文本框的那个
|
||||||
|
showRemove : true, //显示移除按钮,跟随文本框的那个
|
||||||
|
showCaption: true,//是否显示标题,就是那个文本框
|
||||||
|
uploadAsync : false, //默认异步上传
|
||||||
|
elErrorContainer: '#upload-file-errors',
|
||||||
|
maxFileCount: 1, //表示允许同时上传的最大文件个数
|
||||||
|
maxFileSize: 102400, //单位为kb,如果为0表示不限制文件大小
|
||||||
|
enctype: 'multipart/form-data',
|
||||||
|
dropZoneTitle: '拖拽文件到这里 …<br>仅仅支持单个文件同时上传',//重新定义提示
|
||||||
|
msgFilesTooMany: '选择上传的文件数量({n}) 超过允许的最大数值{m}!',
|
||||||
|
allowedFileExtensions: ["xls", "xlsx"],
|
||||||
|
uploadUrl: prefix+'/batchAdd'
|
||||||
|
});
|
||||||
|
}
|
||||||
/*用户管理-部门*/
|
/*用户管理-部门*/
|
||||||
function dept() {
|
function dept() {
|
||||||
var url = ctx + "system/dept";
|
var url = ctx + "system/dept";
|
||||||
@ -144,6 +165,42 @@ function add() {
|
|||||||
var url = prefix + '/add';
|
var url = prefix + '/add';
|
||||||
layer_showAuto("新增用户", url);
|
layer_showAuto("新增用户", url);
|
||||||
}
|
}
|
||||||
|
/*用户管理-批量新增*/
|
||||||
|
function batchAdd() {
|
||||||
|
//文件默认上传方法,传ID:uploadfile
|
||||||
|
$('#uploadfile').fileinput("upload");
|
||||||
|
//同步上传错误处理
|
||||||
|
$('#uploadfile').on('filebatchuploaderror', function(event, data, msg) {
|
||||||
|
// get message
|
||||||
|
$.modalAlert(msg, "error");
|
||||||
|
//重置
|
||||||
|
$('#uploadfile').fileinput("clear");
|
||||||
|
$('#uploadfile').fileinput("reset");
|
||||||
|
$('#uploadfile').fileinput('refresh');
|
||||||
|
$('#uploadfile').fileinput('enable');
|
||||||
|
});
|
||||||
|
//同步上传后从后台返回结果
|
||||||
|
$('#uploadfile').on('filebatchuploadsuccess', function(event, data, previewId, index) {
|
||||||
|
var result = data.response;
|
||||||
|
if (result.code == 0) {
|
||||||
|
//刷新数据表格
|
||||||
|
$('.bootstrap-table').bootstrapTable('refresh');
|
||||||
|
var count = result.msg;
|
||||||
|
$.modalAlert("成功导入" +count+ "条数据","success");
|
||||||
|
$('#uploadfile').fileinput('reset');
|
||||||
|
$('#exampleModal').modal('hide');
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$.modalAlert(result.msg, "error");
|
||||||
|
//重置
|
||||||
|
$('#uploadfile').fileinput("clear");
|
||||||
|
$('#uploadfile').fileinput("reset");
|
||||||
|
$('#uploadfile').fileinput('refresh');
|
||||||
|
$('#uploadfile').fileinput('enable');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*用户管理-重置密码*/
|
/*用户管理-重置密码*/
|
||||||
function resetPwd(userId) {
|
function resetPwd(userId) {
|
||||||
|
BIN
src/main/resources/static/template/用户导入模板.xlsx
Normal file
BIN
src/main/resources/static/template/用户导入模板.xlsx
Normal file
Binary file not shown.
@ -39,7 +39,7 @@ $(window).load(function() {
|
|||||||
options.imgSrc = e.target.result;
|
options.imgSrc = e.target.result;
|
||||||
//根据MIME判断上传的文件是不是图片类型
|
//根据MIME判断上传的文件是不是图片类型
|
||||||
if((options.imgSrc).indexOf("image/")==-1){
|
if((options.imgSrc).indexOf("image/")==-1){
|
||||||
alert("错误提示\n" + " 请上传图片类型!");
|
parent.layer.alert("文件格式错误,请上传图片类型,如:JPG,JEPG,PNG后缀的文件。", {icon: 2,title:"系统提示"});
|
||||||
} else {
|
} else {
|
||||||
cropper = $('.imageBox').cropbox(options);
|
cropper = $('.imageBox').cropbox(options);
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,9 @@
|
|||||||
<link href="/ruoyi/css/RuoYi.css" th:href="@{/ruoyi/css/RuoYi.css}" rel="stylesheet"/>
|
<link href="/ruoyi/css/RuoYi.css" th:href="@{/ruoyi/css/RuoYi.css}" rel="stylesheet"/>
|
||||||
<link href="/ajax/libs/jquery-layout/jquery.layout-latest.css" th:href="@{/ajax/libs/jquery-layout/jquery.layout-latest.css}" rel="stylesheet"/>
|
<link href="/ajax/libs/jquery-layout/jquery.layout-latest.css" th:href="@{/ajax/libs/jquery-layout/jquery.layout-latest.css}" rel="stylesheet"/>
|
||||||
<link href="/ajax/libs/jquery-ztree/3.5/css/metro/zTreeStyle.css" th:href="@{/ajax/libs/jquery-ztree/3.5/css/metro/zTreeStyle.css}" rel="stylesheet"/>
|
<link href="/ajax/libs/jquery-ztree/3.5/css/metro/zTreeStyle.css" th:href="@{/ajax/libs/jquery-ztree/3.5/css/metro/zTreeStyle.css}" rel="stylesheet"/>
|
||||||
|
<!-- 文件输入框-->
|
||||||
|
<link href="/css/plugins/fileinput/fileinput.min.css" th:href="@{/css/plugins/fileinput/fileinput.min.css}" rel="stylesheet"/>
|
||||||
|
|
||||||
<body class="white-bg">
|
<body class="white-bg">
|
||||||
<div class="ui-layout-west">
|
<div class="ui-layout-west">
|
||||||
<div class="main-content">
|
<div class="main-content">
|
||||||
@ -33,6 +36,10 @@
|
|||||||
<button class="btn btn-outline btn-default" onclick="javascript:add()" shiro:hasPermission="system:user:add">
|
<button class="btn btn-outline btn-default" onclick="javascript:add()" shiro:hasPermission="system:user:add">
|
||||||
<i class="fa fa-plus"></i> 新增
|
<i class="fa fa-plus"></i> 新增
|
||||||
</button>
|
</button>
|
||||||
|
<button class="btn btn-outline btn-default" data-toggle="modal" data-target="#exampleModal" shiro:hasPermission="system:user:batchAdd">
|
||||||
|
<i class="fa fa-plus-square"></i> 批量新增
|
||||||
|
</button>
|
||||||
|
|
||||||
<button class="btn btn-outline btn-default" onclick="javascript:batchRemove()" shiro:hasPermission="system:user:batchRemove">
|
<button class="btn btn-outline btn-default" onclick="javascript:batchRemove()" shiro:hasPermission="system:user:batchRemove">
|
||||||
<i class="fa fa-trash-o"></i> 删除
|
<i class="fa fa-trash-o"></i> 删除
|
||||||
</button>
|
</button>
|
||||||
@ -43,10 +50,46 @@
|
|||||||
data-sort-name="create_time" data-sort-order="desc">
|
data-sort-name="create_time" data-sort-order="desc">
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Modal -->
|
||||||
|
|
||||||
|
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3 class="modal-title" id="exampleModalLabel">导入Execl表</h3>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
<a class="btn" style="font-size:15px" href="../static/template/用户导入模板.xlsx" th:href="@{/template/用户导入模板.xlsx}">
|
||||||
|
用户导入模板.xlsx
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="file-loading">
|
||||||
|
<input id="uploadfile" name="uploadfile" multiple type="file" accept=".xls,.xlsx">
|
||||||
|
</div>
|
||||||
|
<div id="upload-file-errors"></div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
|
||||||
|
<button type="button" class="btn btn-primary" onclick="javascript:batchAdd()">保存</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div th:include="include :: footer"></div>
|
<div th:include="include :: footer"></div>
|
||||||
<script src="/ruoyi/system/user/user.js" th:src="@{/ruoyi/system/user/user.js}"></script>
|
<script src="/ruoyi/system/user/user.js" th:src="@{/ruoyi/system/user/user.js}"></script>
|
||||||
<script src="/ajax/libs/jquery-layout/jquery.layout-latest.js" th:src="@{/ajax/libs/jquery-layout/jquery.layout-latest.js}"></script>
|
<script src="/ajax/libs/jquery-layout/jquery.layout-latest.js" th:src="@{/ajax/libs/jquery-layout/jquery.layout-latest.js}"></script>
|
||||||
<script src="/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.all-3.5.js" th:src="@{/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.all-3.5.js}"></script>
|
<script src="/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.all-3.5.js" th:src="@{/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.all-3.5.js}"></script>
|
||||||
|
|
||||||
|
<!-- 文件输入框-->
|
||||||
|
<script src="/js/plugins/fileinput/fileinput.min.js" th:src="@{/js/plugins/fileinput/fileinput.min.js}"></script>
|
||||||
|
<script src="/js/plugins/fileinput/locales/zh.js" th:src="@{/js/plugins/fileinput/locales/zh.js}"></script>
|
||||||
|
<script src="/js/plugins/fileinput/plugins/piexif.js" th:src="@{/js/plugins/fileinput/plugins/piexif.js}"></script>
|
||||||
|
<script src="/js/plugins/fileinput/plugins/purify.js" th:src="@{/js/plugins/fileinput/plugins/purify.js}"></script>
|
||||||
|
<script src="/js/plugins/fileinput/plugins/sortable.js" th:src="@{/js/plugins/fileinput/plugins/sortable.js}"></script>
|
||||||
|
|
||||||
<script th:inline="javascript">
|
<script th:inline="javascript">
|
||||||
var editFlag = [[${@permissionService.hasPermi('system:user:edit')}]];
|
var editFlag = [[${@permissionService.hasPermi('system:user:edit')}]];
|
||||||
var removeFlag = [[${@permissionService.hasPermi('system:user:remove')}]];
|
var removeFlag = [[${@permissionService.hasPermi('system:user:remove')}]];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user