分布式文件系统 SpringBoot+FastDFS+Vue.js【三】

分布式文件系统 SpringBoot+FastDFS+Vue.js【三】

  • 七、创建后台--分角色管理
    • 7.1.创建后台数据库表
    • 7.2.创建实体类
      • 7.2.1.Admin
      • 7.2.2.Menu
      • 7.2.3.MenuBean
      • 7.2.4.Role
      • 7.2.5.RoleMenu
    • 7.3.编辑配置文件application.yml
    • 7.4.编写工具类
      • 7.4.1.AuthContextHolder
      • 7.4.2.HttpUtils
      • 7.4.3.StringUtils
      • 7.4.4.JwtHelper
      • 7.4.5.MD5
      • 7.4.6.ShiroMD5
    • 7.5.Mapper层
      • 7.5.1.AdminMapper.xml
      • 7.5.2.MenuMapper.xml
      • 7.5.3.RoleMenuMapper.xml
      • 7.5.4.AdminMapper
      • 7.5.5.MenuMapper
      • 7.5.6.RoleMenuMapper
    • 7.6.Service层
      • 7.6.1.AdminService
      • 7.6.2.MenuBeanService
      • 7.6.3.MenuService
      • 7.6.4.RoleMenuService
      • 7.6.5.AdminServiceImpl
      • 7.6.6.MenuBeanServiceImpl
      • 7.6.7.MenuServiceImpl
      • 7.6.8.RoleMenuServiceImpl
    • 7.7.controller层
      • 7.7.1.AdminController
      • 7.7.2.MenuController
    • 7.8.前端vue改造
      • 7.8.1.登录login.vue
      • 7.8.2.后台页面admin.vue
      • 7.8.2.后台顶部页面navcon.vue
      • 7.8.2.后台左侧页面leftnav.vue
      • 7.8.2.主界面main.vue
      • 7.8.3.identify.vue
      • 7.8.4.request.js
      • 7.8.5.store.js
      • 7.8.6.util.js
      • 7.8.7.index.js
      • 7.8.8.admin.js
      • 7.8.9.menu.js
      • 7.8.10.main.js
    • 7.9.效果展示
  • endl

七、创建后台–分角色管理

7.1.创建后台数据库表

USE fastdfs;CREATE TABLE `admin` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '管理员表id',`role_id` int(11) DEFAULT '0' COMMENT '角色id',`role_name` varchar(50) DEFAULT NULL COMMENT '角色名',`name` varchar(100) NOT NULL COMMENT '管理员名',`password` varchar(50) NOT NULL COMMENT '管理员密码',`sex` varchar(50) DEFAULT NULL COMMENT '性别(男,女)',`age` int(11) DEFAULT NULL COMMENT '年龄',`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(0:未工作 1:工作中)',`email` varchar(50) DEFAULT NULL COMMENT '邮箱',`phone` varchar(11) DEFAULT NULL COMMENT '手机号',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',`is_deleted` tinyint(4) NOT NULL DEFAULT '1' COMMENT '删除标记(0:不可用 1:可用)',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=39 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='管理员表';CREATE TABLE `role` (`role_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '角色表id',`role_name` varchar(25) NOT NULL COMMENT '角色名\r\n1.医生\r\n2.科室\r\n3.医院管理员\r\n4.超级管理员',`description` varchar(255) DEFAULT NULL COMMENT '角色描述',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',`is_delete` tinyint(4) NOT NULL DEFAULT '1' COMMENT '删除标记(0:不可用 1:可用)',PRIMARY KEY (`role_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='角色表';CREATE TABLE `menu` (`menu_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '资源ID',`menu_name` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '资源名称',`parent_id` int(11) DEFAULT NULL COMMENT '父id',`url` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '资源路径',`menus` tinyint(4) DEFAULT '1' COMMENT '是否有子菜单(0:是,1:)',`icon` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '图标',`create_time` datetime NOT NULL COMMENT '创建日期',`update_time` datetime NOT NULL COMMENT '更新时间',`is_delete` tinyint(4) NOT NULL DEFAULT '1' COMMENT '删除标记(0:不可用 1:可用)',PRIMARY KEY (`menu_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8 COLLATE=utf8_bin ROW_FORMAT=COMPACT COMMENT='菜单栏表';CREATE TABLE `role_menu` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '角色菜单表id',`role_id` int(11) NOT NULL COMMENT '角色表id(外键)',`menu_id` int(11) NOT NULL COMMENT '菜单表id(外键)',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',`is_delete` tinyint(4) NOT NULL DEFAULT '1' COMMENT '删除标记(0:不可用 1:可用)',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=137 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;INSERT INTO `admin` VALUES (1, 1, '超级管理员', 'root', '123456', '女', 18, 0, '123456@qq.com', '12345678902', '2021-06-30 12:14:13', '2024-02-14 21:40:26', 1);
INSERT INTO `admin` VALUES (2, 2, '用户', 'admin', '123456', '男', 17, 0, '123456@qq.com', '12345678902', '2021-06-30 12:14:13', '2022-03-13 08:41:45', 1);INSERT INTO `menu` VALUES (2, '文件管理', 0, '', 1, 'el-icon-folder', '2021-06-27 19:58:39', '2024-02-14 22:20:52', 1);
INSERT INTO `menu` VALUES (3, '我的文件', 2, 'file', 0, 'nel-icon-folder-opened', '2021-06-27 21:36:01', '2024-02-14 22:19:50', 1);
INSERT INTO `menu` VALUES (4, '用户管理', 0, '', 1, 'el-icon-user', '2024-02-14 21:58:54', '2024-02-14 22:00:02', 1);
INSERT INTO `menu` VALUES (5, '用户', 4, 'user', 0, 'el-icon-s-custom', '2021-06-27 21:37:17', '2024-02-14 22:15:37', 1);
INSERT INTO `menu` VALUES (6, '个人信息管理', 0, NULL, 1, 'el-icon-user', '2022-03-04 17:12:46', '2024-02-14 21:59:26', 1);
INSERT INTO `menu` VALUES (7, '我的信息', 6, 'info', 0, 'el-icon-user', '2022-03-04 17:13:23', '2024-02-14 22:00:27', 1);
INSERT INTO `menu` VALUES (8, '修改邮箱', 6, 'email', 0, 'el-icon-user', '2022-03-05 10:53:37', '2024-02-14 22:00:29', 1);
INSERT INTO `menu` VALUES (9, '修改密码', 6, 'password', 0, 'el-icon-user', '2022-03-05 10:54:53', '2024-02-14 22:00:33', 1);
INSERT INTO `menu` VALUES (10, '文件上传', 2, 'upload', 0, 'el-icon-upload', '2024-02-14 22:18:49', '2024-02-14 22:18:49', 1);INSERT INTO `role` VALUES (1, '超级管理员', '拥有所有权限', '2022-03-04 14:46:19', '2022-03-04 15:30:00', 1);
INSERT INTO `role` VALUES (2, '用户', '用户', '2022-03-04 14:46:19', '2024-02-14 21:53:44', 1);INSERT INTO `role_menu` VALUES (1, 2, 10, '2024-02-14 22:20:19', '2024-02-14 22:20:19', 1);
INSERT INTO `role_menu` VALUES (2, 2, 2, '2024-02-14 22:02:28', '2024-02-14 22:14:49', 1);
INSERT INTO `role_menu` VALUES (3, 2, 3, '2024-02-14 22:02:37', '2024-02-14 22:14:49', 1);
INSERT INTO `role_menu` VALUES (4, 2, 6, '2024-02-14 22:03:05', '2024-02-14 22:14:49', 1);
INSERT INTO `role_menu` VALUES (5, 2, 7, '2024-02-14 22:03:15', '2024-02-14 22:14:49', 1);
INSERT INTO `role_menu` VALUES (6, 2, 8, '2024-02-14 22:03:23', '2024-02-14 22:14:49', 1);
INSERT INTO `role_menu` VALUES (7, 2, 9, '2024-02-14 22:03:36', '2024-02-14 22:14:49', 1);
INSERT INTO `role_menu` VALUES (9, 1, 4, '2024-02-14 22:04:10', '2024-02-14 22:14:55', 1);
INSERT INTO `role_menu` VALUES (10, 1, 5, '2024-02-14 22:04:18', '2024-02-14 22:14:55', 1);
INSERT INTO `role_menu` VALUES (11, 1, 6, '2024-02-14 22:04:25', '2024-02-14 22:14:55', 1);
INSERT INTO `role_menu` VALUES (12, 1, 7, '2024-02-14 22:04:33', '2024-02-14 22:14:55', 1);
INSERT INTO `role_menu` VALUES (13, 1, 8, '2024-02-14 22:04:44', '2024-02-14 22:14:55', 1);
INSERT INTO `role_menu` VALUES (14, 1, 9, '2024-02-14 22:04:53', '2024-02-14 22:14:55', 1);

7.2.创建实体类

7.2.1.Admin

/*** 管理员表*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Repository
public class Admin implements Serializable {private Integer id; //管理员表idprivate Integer roleId; //角色idprivate String roleName; //角色名private String name; //管理员名private String password; //管理员密码private String sex; //性别(男,女)private Integer age; //年龄private Integer status; //状态(0:未工作 1:工作中)private String email; //邮箱private String phone; //手机号private LocalDateTime createTime; //创建时间private LocalDateTime updateTime; //更新时间private Integer isDeleted; //删除标记(0:不可用 1:可用)
}

7.2.2.Menu

/*** 菜单栏表*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Repository
public class Menu implements Serializable {private Integer menuId; //资源IDprivate String menuName; //资源名称private Integer parentId; //父idprivate String url; //资源路径private Integer menus; //是否有子菜单(0:是,1:否)private String icon; //图标private LocalDateTime createTime; //创建日期private LocalDateTime updateTime; //更新时间private Integer isDelete; //删除标记(0:不可用 1:可用)
}

7.2.3.MenuBean

/*** 菜单栏表*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Repository
public class MenuBean implements Serializable {private Integer menuId; //资源IDprivate String menuName; //资源名称private Integer parentId; //父idprivate String url; //资源路径private Integer menus; //是否有子菜单(0:是,1:否)private String icon; //图标private List<Menu> menuList;
}

7.2.4.Role

/*** 角色表*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Repository
public class Role implements Serializable {private Integer roleId; //角色表idprivate String roleName; //角色名 1.用户 2.超级管理员private String description; //角色描述private LocalDateTime createTime; //创建时间private LocalDateTime updateTime; //更新时间private Integer isDelete; //删除标记(0:不可用 1:可用)
}

7.2.5.RoleMenu

/*** 角色菜单中间表*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Repository
public class RoleMenu implements Serializable {private Integer id; //角色菜单表idprivate Integer roleId; //角色表id(外键)private Integer menuId; //菜单表id(外键)private LocalDateTime createTime; //创建时间private LocalDateTime updateTime; //更新时间private Integer isDelete; //删除标记(0:不可用 1:可用)
}

7.3.编辑配置文件application.yml

server:port: 9090#Mybatis配置
mybatis:# 如果是放在src/main/java目录下 classpath:/com/yourpackage/*/mapper/*Mapper.xml# 如果是放在resource目录 classpath:/mapper/*Mapper.xmlconfiguration: #sql日志log-impl: org.apache.ibatis.logging.stdout.StdOutImpl#驼峰命名map-underscore-to-camel-case: truemapper-locations: classpath:com/orange/fastdfs/mapper/*.xml#spring事务管理日志
logging:level:org.springframework.jdbc.support.JdbcTransactionManager: debugspring:application:name: fastdfs-java  #应用的名字jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+8#数据库连接信息datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.229.141:3306/fastdfs?characterEncoding=utf-8&&useSSL=falseusername: rootpassword: 123456type: com.alibaba.druid.pool.DruidDataSource#数据源其他配置initialSize: 5minIdle: 5maxActive: 20maxWait: 60000timeBetweenEvictionRunsMillis: 60000minEvictableIdleTimeMillis: 300000validationQuery: SELECT 1 FROM DUALtestWhileIdle: truetestOnBorrow: falsetestOnReturn: falsepoolPreparedStatements: true#   配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙filters: stat,wallmaxPoolPreparedStatementPerConnectionSize: 20useGlobalDataSourceStat: trueconnectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500# 文件上传的配置
# linux临时文件目录
# mkdir -p /data/tmp/updatefileservlet:multipart:location: /data/tmp/updatefilemax-file-size: 10MBmax-request-size: 10MB

7.4.编写工具类

7.4.1.AuthContextHolder

/*** 获取当前用户信息工具类**/
public class AuthContextHolder {//获取当前用户idpublic static Integer getAdminId(HttpServletRequest request) {//从header获取tokenString token = request.getHeader("token");//jwt从token获取useridInteger adminId = JwtHelper.getAdminId(token);return adminId;}//获取当前用户名称public static String getAdminName(HttpServletRequest request) {//从header获取tokenString token = request.getHeader("token");//jwt从token获取useridString adminName = JwtHelper.getAdminName(token);return adminName;}}

7.4.2.HttpUtils

public class HttpUtils {/*** 将通知参数转化为字符串*/public static String readData(HttpServletRequest request) {BufferedReader br = null;try {StringBuilder result = new StringBuilder();br = request.getReader();for (String line; (line = br.readLine()) != null; ) {if (result.length() > 0) {result.append("\n");}result.append(line);}return result.toString();} catch (IOException e) {throw new RuntimeException(e);} finally {if (br != null) {try {br.close();} catch (IOException e) {e.printStackTrace();}}}}
}

7.4.3.StringUtils

public final class StringUtils {public static boolean isEmpty(CharSequence cs) {return cs == null || cs.length() == 0;}public static boolean isBlank(CharSequence cs) {if (cs != null) {int length = cs.length();for(int i = 0; i < length; ++i) {if (!Character.isWhitespace(cs.charAt(i))) {return false;}}}return true;}public static boolean isNotBlank(CharSequence cs) {return !isBlank(cs);}
}

7.4.4.JwtHelper

/*** JWT token 工具类**/
@Data
@Component
@ConfigurationProperties(prefix = "jwt")
public class JwtHelper {//过期时间private static long tokenExpiration;//签名秘钥private static String tokenSignKey;//请求头private static String tokenHeader;//校验token是否正确public static boolean verify(String token,Integer adminId,String adminName) {try {String id = String.valueOf(adminId);Algorithm algorithm = Algorithm.HMAC256(id);JWTVerifier verifier = JWT.require(algorithm).withClaim("adminName", adminName).withClaim("adminId",adminId).build();DecodedJWT jwt = verifier.verify(token);return true;} catch (Exception e) {return false;}}/*** 生成签名*/public static String createToken(Integer adminId,String adminName) {try {// 指定过期时间Date date = new Date(System.currentTimeMillis() + tokenExpiration);String id = String.valueOf(adminId);Algorithm algorithm = Algorithm.HMAC256(id);return JWT.create().withSubject("admin").withClaim("adminName", adminName).withClaim("adminId",adminId).withExpiresAt(date).sign(algorithm);} catch (UnsupportedEncodingException e) {return null;}}//根据token字符串得到用户idpublic static Integer getAdminId(String token) {if(StringUtils.isBlank(token)) {return null;}try {DecodedJWT jwt = JWT.decode(token);return jwt.getClaim("adminId").asInt();} catch (JWTDecodeException e) {return null;}}//根据token字符串得到用户名称public static String getAdminName(String token) {if(StringUtils.isBlank(token)) {return "";}try {DecodedJWT jwt = JWT.decode(token);return jwt.getClaim("adminName").asString();} catch (JWTDecodeException e) {return null;}}public static long getTokenExpiration() {return tokenExpiration;}public static void setTokenExpiration(long tokenExpiration) {JwtHelper.tokenExpiration = tokenExpiration;}public static String getTokenSignKey() {return tokenSignKey;}public static void setTokenSignKey(String tokenSignKey) {JwtHelper.tokenSignKey = tokenSignKey;}public static String getTokenHeader() {return tokenHeader;}public static void setTokenHeader(String tokenHeader) {JwtHelper.tokenHeader = tokenHeader;}public static void main(String[] args) {String token = JwtHelper.createToken(1,"小鱼儿");System.out.println(token);System.out.println(JwtHelper.getAdminId(token));System.out.println(JwtHelper.getAdminName(token));boolean a = verify(token,1,"小鱼儿");System.out.println(a);}}

7.4.5.MD5

/*** 1.MD5加密字符串(32位大写)* 2.MD5加密字符串(32位小写)* <p>* MD5在线加密:https://md5jiami.51240.com/* 3.将二进制字节数组转换为十六进制字符串* 4.Unicode中文编码转换成字符串*/
public class MD5 {/*** 生成md5* @param message* @return*/public static String getMD5(String message) {String md5str = "";try {//1 创建一个提供信息摘要算法的对象,初始化为md5算法对象MessageDigest md = MessageDigest.getInstance("MD5");//2 将消息变成byte数组byte[] input = message.getBytes();//3 计算后获得字节数组,这就是那128位了byte[] buff = md.digest(input);//4 把数组每一字节(一个字节占八位)换成16进制连成md5字符串md5str = bytesToHex(buff);} catch (Exception e) {e.printStackTrace();}return md5str;}/*** MD5加密字符串(32位大写)** @param string 需要进行MD5加密的字符串* @return 加密后的字符串(大写)*/public static String md5Encrypt32Upper(String string) {byte[] hash;try {//创建一个MD5算法对象,并获得MD5字节数组,16*8=128位hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));} catch (NoSuchAlgorithmException e) {throw new RuntimeException("Huh, MD5 should be supported?", e);} catch (UnsupportedEncodingException e) {throw new RuntimeException("Huh, UTF-8 should be supported?", e);}//转换为十六进制字符串StringBuilder hex = new StringBuilder(hash.length * 2);for (byte b : hash) {if ((b & 0xFF) < 0x10) {hex.append("0");}hex.append(Integer.toHexString(b & 0xFF));}return hex.toString().toUpperCase();}/*** MD5加密字符串(32位小写)** @param string 需要进行MD5加密的字符串* @return 加密后的字符串(小写)*/public static String md5Encrypt32Lower(String string) {byte[] hash;try {//创建一个MD5算法对象,并获得MD5字节数组,16*8=128位hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));} catch (NoSuchAlgorithmException e) {throw new RuntimeException("Huh, MD5 should be supported?", e);} catch (UnsupportedEncodingException e) {throw new RuntimeException("Huh, UTF-8 should be supported?", e);}//转换为十六进制字符串StringBuilder hex = new StringBuilder(hash.length * 2);for (byte b : hash) {if ((b & 0xFF) < 0x10) {hex.append("0");}hex.append(Integer.toHexString(b & 0xFF));}return hex.toString().toLowerCase();}/*** 将二进制字节数组转换为十六进制字符串** @param bytes 二进制字节数组* @return 十六进制字符串*/public static String bytesToHex(byte[] bytes) {StringBuffer md5str = new StringBuffer();//把数组每一字节换成16进制连成md5字符串int digital;for (int i = 0; i < bytes.length; i++) {digital = bytes[i];if(digital < 0) {digital += 256;}if(digital < 16){md5str.append("0");}md5str.append(Integer.toHexString(digital));}return md5str.toString().toUpperCase();}/*** Unicode中文编码转换成字符串*/public static String unicodeToString(String str) {Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");Matcher matcher = pattern.matcher(str);char ch;while (matcher.find()) {ch = (char) Integer.parseInt(matcher.group(2), 16);str = str.replace(matcher.group(1), ch + "");}return str;}/*    @Testpublic void testMD5(){String message="123,123";String result=getMD5(message);System.out.println(result);}*/}

7.4.6.ShiroMD5

/*** MD5加密工具类**/
@Slf4j
public final class ShiroMD5 {/*** MD5对密码进行加密算法*/public static String getPwd(String email,String password){log.info("密码加盐,原密码为:"+password);Md5Hash md5 = new Md5Hash(password, email, 1024);String newMd5Password = md5.toHex();System.out.println("加盐后的密码是:" +newMd5Password);log.info("密码加密后,生成的新密码为:"+newMd5Password);return newMd5Password;}
}

7.5.Mapper层

7.5.1.AdminMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.orange.fastdfsjava.mapper.AdminMapper"><select id="selectByNamePwd" resultType="com.orange.fastdfsjava.pojo.Admin">select *from adminwhere name = #{name}and password = #{password}</select><select id="selectById" resultType="com.orange.fastdfsjava.pojo.Admin">select *from adminwhere id = #{id}</select><select id="selectCountByNamePwd" resultType="java.lang.Integer">select count(*)from adminwhere name = #{name}and password = #{password}</select>
</mapper>

7.5.2.MenuMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.orange.fastdfsjava.mapper.MenuMapper"><select id="selectById" resultType="com.orange.fastdfsjava.pojo.Menu">select *from menuwhere menu_id = #{menuId}</select>
</mapper>

7.5.3.RoleMenuMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.orange.fastdfsjava.mapper.RoleMenuMapper"><select id="selectByRoleId" resultType="com.orange.fastdfsjava.pojo.RoleMenu">select *from role_menuwhere role_id = #{roleId}</select>
</mapper>

7.5.4.AdminMapper

@Mapper
public interface AdminMapper {Admin selectByNamePwd(String name, String password);Admin selectById(Integer id);int selectCountByNamePwd(String name, String password);
}

7.5.5.MenuMapper

@Mapper
public interface MenuMapper {Menu selectById(Integer menuId);
}

7.5.6.RoleMenuMapper

@Mapper
public interface RoleMenuMapper {List<RoleMenu> selectByRoleId(Integer roleId);
}

7.6.Service层

7.6.1.AdminService

public interface AdminService {Admin selectAdminLogin(String name, String password);Admin getAdminById(Integer adminId);int selectCountAdminLogin(String name, String password);
}

7.6.2.MenuBeanService

public interface MenuBeanService {List<MenuBean> selectByRoleId(Integer roleId);
}

7.6.3.MenuService

public interface MenuService {Menu selectByMenuId(Integer menuId);
}

7.6.4.RoleMenuService

public interface RoleMenuService {List<RoleMenu> selectByRoleId(Integer roleId);
}

7.6.5.AdminServiceImpl

/*** 管理员表*/
@Service
public class AdminServiceImpl implements AdminService {@Resourceprivate AdminMapper adminMapper;@Overridepublic Admin selectAdminLogin(String name, String password) {return adminMapper.selectByNamePwd(name, password);}@Overridepublic Admin getAdminById(Integer id) {return adminMapper.selectById(id);}@Overridepublic int selectCountAdminLogin(String name, String password) {return adminMapper.selectCountByNamePwd(name, password);}
}

7.6.6.MenuBeanServiceImpl

@Service
public class MenuBeanServiceImpl implements MenuBeanService {@Resourceprivate RoleMenuMapper roleMenuMapper;@Resourceprivate MenuMapper menuMapper;@Overridepublic List<MenuBean> selectByRoleId(Integer roleId) {List<MenuBean> menuBeans = new ArrayList<>();List<RoleMenu> roleMenuList = roleMenuMapper.selectByRoleId(roleId);for (RoleMenu roleMenu : roleMenuList){Menu menu = menuMapper.selectById(roleMenu.getMenuId());if (menu.getParentId()==0){MenuBean menuBean = new MenuBean();menuBean.setMenuId(menu.getMenuId());menuBean.setMenuName(menu.getMenuName());menuBean.setIcon(menu.getIcon());menuBean.setUrl(menu.getUrl());menuBean.setParentId(menu.getParentId());menuBean.setMenus(menu.getMenus());menuBeans.add(menuBean);}}List<MenuBean> menuBeanList = new ArrayList<>();for (MenuBean menuBean : menuBeans){MenuBean menuBean1 = menuBean;List<Menu> menuList = new ArrayList<>();for (RoleMenu roleMenu : roleMenuList){Menu menu1 = menuMapper.selectById(roleMenu.getMenuId());if (menu1.getParentId().equals(menuBean.getMenuId())){menuList.add(menu1);}}menuBean1.setMenuList(menuList);menuBeanList.add(menuBean1);}return menuBeanList;}
}

7.6.7.MenuServiceImpl

/*** 菜单栏表*/
@Service
public class MenuServiceImpl implements MenuService {@Resourceprivate MenuMapper menuMapper;@Overridepublic Menu selectByMenuId(Integer menuId) {return menuMapper.selectById(menuId);}
}

7.6.8.RoleMenuServiceImpl

/*** 角色菜单中间表*/
@Service
public class RoleMenuServiceImpl implements RoleMenuService {@Resourceprivate RoleMenuMapper roleMenuMapper;@Overridepublic List<RoleMenu> selectByRoleId(Integer roleId) {return roleMenuMapper.selectByRoleId(roleId);}
}

7.7.controller层

7.7.1.AdminController

/*** 管理员表*/
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/admins")
public class AdminController {@Resourceprivate AdminService adminService;//管理员进行用户名密码登录@PostMapping("{name}/{password}")public R loginAdmin(@PathVariable String name, @PathVariable String password) {log.info("管理员进行用户名:===>{},密码登录:===>{}", name, password);int count = adminService.selectCountAdminLogin(name, password);if (count > 0) {Admin admin = adminService.selectAdminLogin(name, password);String adminName = admin.getName();String roleName = admin.getRoleName();if (StringUtils.isNotBlank(adminName)) {String token = JwtHelper.createToken(admin.getId(), admin.getName());return R.ok().setMessage("success").setCode(200).data("adminName", adminName).data("roleName", roleName).data("token", token);}}return R.error().setMessage("fail");}//根据id查询管理员@GetMapping()public R getAdminById(HttpServletRequest request) {Integer adminId = AuthContextHolder.getAdminId(request);Admin admin = adminService.getAdminById(adminId);log.info("根据id查询管理员:===>{}", admin);return R.ok().setMessage("success").setCode(200).data("admin", admin);}}

7.7.2.MenuController

/*** 菜单栏表 前端控制器*/
@Slf4j
@RestController
@RequestMapping("/menus")
public class MenuController {@Resourceprivate AdminService adminService;@Resourceprivate MenuBeanService menuBeanService;/*** 根据角色获取不同的菜单栏列表* @param request* @return* @throws Exception*/@GetMapping()public R getMenuByRoleId(HttpServletRequest request) throws Exception{try {int adminId = AuthContextHolder.getAdminId(request);Admin admin = adminService.getAdminById(adminId);Integer roleId = admin.getRoleId();List<MenuBean> menuBeanList = menuBeanService.selectByRoleId(roleId);return R.ok().setCode(200).setMessage("查询菜单列表success").data("menuBeanList",menuBeanList);}catch (Exception e){return R.error().setCode(208).setMessage("请求失败,请进行登录后操作");}}
}

7.8.前端vue改造

npm install js-cookie --save
npm install --save vue-qriously
npm install --save vuex

7.8.1.登录login.vue

<template><div class="login-wrap"><el-form label-position="left" :model="ruleForm" :rules="rules" ref="ruleForm" label-width="0px" class="demo-ruleForm login-container"><h3 class="title">用户登录</h3><el-form-item prop="username"><el-input type="text" v-model="ruleForm.username" auto-complete="off" placeholder="账号"></el-input></el-form-item><el-form-item prop="password"><el-input type="password" v-model="ruleForm.password" auto-complete="off" placeholder="密码"></el-input></el-form-item><el-row><el-col :span="12"><el-form-item prop="code"><el-input type="text" v-model="ruleForm.code" auto-complete="off" placeholder="图形验证码" @keyup.enter.native="submitForm('ruleForm')"></el-input></el-form-item></el-col><el-col :span="12" class="code-box"><img :src="ruleForm.codeimg" alt="" class="codeimg"><div @click="refreshCode" style="margin-right: 50px;margin-top: -18px"><SIdentify :identifyCode="identifyCode"></SIdentify></div></el-col></el-row><el-checkbox class="remember" v-model="rememberpwd">记住密码</el-checkbox><el-form-item style="width:100%;"><el-button type="primary" style="width:100%;" @click="submitForm('ruleForm')" :loading="logining">登录</el-button></el-form-item></el-form></div>
</template>
<script type="text/ecmascript-6">import cookie from "js-cookie";
import SIdentify from "@/view/code/identify";
import adminApi from "../api/fastdfs/admin";
export default {name: 'login',components: {SIdentify},data() {return {//定义loading默认为falselogining: false,// 记住密码rememberpwd: false,ruleForm: {//username和password默认为空username: '',password: '',code: '',randomStr: '',codeimg: ''},//rules前端验证rules: {username: [{ required: true, message: '请输入账号', trigger: 'blur' }],password: [{ required: true, message: '请输入密码', trigger: 'blur' }],code: [{ required: true, message: '请输入验证码', trigger: 'blur' }]},//验证码identifyCodes: "1234567890",identifyCode: ""}},// 创建完毕状态(里面是操作)created() {this.$message({message: '账号密码及验证码不为空即可',type: 'success'})},mounted() {const self = thisself.identifyCode = "";self.makeCode(this.identifyCodes, 4);self.ruleForm.codeimg = self.identifyCode//验证码输入框self.ruleForm.code = self.identifyCode},// 里面的函数只有调用才会执行methods: {//生成验证码工具randomNum(min, max) {return Math.floor(Math.random() * (max - min) + min);},//刷新验证码refreshCode() {this.identifyCode = "";this.makeCode(this.identifyCodes, 4);this.ruleForm.codeimg = this.identifyCode//验证码输入框this.ruleForm.code = this.identifyCode},//验证makeCode(o, l) {for (let i = 0; i < l; i++) {this.identifyCode += this.identifyCodes[this.randomNum(0, this.identifyCodes.length)];}},setCookies(adminName, token,roleName) {cookie.set('adminToken', token, { domain: 'localhost' })cookie.set('adminName', adminName, { domain: 'localhost' })cookie.set('roleName', roleName, { domain: 'localhost' })},//获取info列表submitForm(formName) {this.$refs[formName].validate(valid => {if (valid) {if (this.ruleForm.code===this.ruleForm.codeimg){adminApi.loginAdmin(this.ruleForm.username,this.ruleForm.password).then(response=>{if (response.code == 200){this.$message.success("登录成功")// 登录成功 设置cookiethis.setCookies(response.data.adminName,response.data.token,response.data.roleName)this.$router.push('main')}else {this.$message.error("用户名或者密码错误...")}})}else {// 获取图形验证码this.$message.error('验证码输入密码!')}} else {this.logining = falsereturn false}})},}
}
</script><style scoped>
.login-wrap {box-sizing: border-box;width: 100%;height: 100%;padding-top: 10%;background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmcgd2lkdGg9IjEzNjFweCIgaGVpZ2h0PSI2MDlweCIgdmlld0JveD0iMCAwIDEzNjEgNjA5IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPCEtLSBHZW5lcmF0b3I6IFNrZXRjaCA0Ni4yICg0NDQ5NikgLSBodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2ggLS0+CiAgICA8dGl0bGU+R3JvdXAgMjE8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZGVmcz48L2RlZnM+CiAgICA8ZyBpZD0iQW50LURlc2lnbi1Qcm8tMy4wIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0i6LSm5oi35a+G56CB55m75b2VLeagoemqjCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTc5LjAwMDAwMCwgLTgyLjAwMDAwMCkiPgogICAgICAgICAgICA8ZyBpZD0iR3JvdXAtMjEiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDc3LjAwMDAwMCwgNzMuMDAwMDAwKSI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iR3JvdXAtMTgiIG9wYWNpdHk9IjAuOCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNzQuOTAxNDE2LCA1NjkuNjk5MTU4KSByb3RhdGUoLTcuMDAwMDAwKSB0cmFuc2xhdGUoLTc0LjkwMTQxNiwgLTU2OS42OTkxNTgpIHRyYW5zbGF0ZSg0LjkwMTQxNiwgNTI1LjE5OTE1OCkiPgogICAgICAgICAgICAgICAgICAgIDxlbGxpcHNlIGlkPSJPdmFsLTExIiBmaWxsPSIjQ0ZEQUU2IiBvcGFjaXR5PSIwLjI1IiBjeD0iNjMuNTc0ODc5MiIgY3k9IjMyLjQ2ODM2NyIgcng9IjIxLjc4MzA0NzkiIHJ5PSIyMS43NjYwMDgiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0zIiBmaWxsPSIjQ0ZEQUU2IiBvcGFjaXR5PSIwLjU5OTk5OTk2NCIgY3g9IjUuOTg3NDY0NzkiIGN5PSIxMy44NjY4NjAxIiByeD0iNS4yMTczOTEzIiByeT0iNS4yMTMzMDk5NyI+PC9lbGxpcHNlPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0zOC4xMzU0NTE0LDg4LjM1MjAyMTUgQzQzLjg5ODQyMjcsODguMzUyMDIxNSA0OC41NzAyMzQsODMuNjgzODY0NyA0OC41NzAyMzQsNzcuOTI1NDAxNSBDNDguNTcwMjM0LDcyLjE2NjkzODMgNDMuODk4NDIyNyw2Ny40OTg3ODE2IDM4LjEzNTQ1MTQsNjcuNDk4NzgxNiBDMzIuMzcyNDgwMSw2Ny40OTg3ODE2IDI3LjcwMDY2ODgsNzIuMTY2OTM4MyAyNy43MDA2Njg4LDc3LjkyNTQwMTUgQzI3LjcwMDY2ODgsODMuNjgzODY0NyAzMi4zNzI0ODAxLDg4LjM1MjAyMTUgMzguMTM1NDUxNCw4OC4zNTIwMjE1IFoiIGlkPSJPdmFsLTMtQ29weSIgZmlsbD0iI0NGREFFNiIgb3BhY2l0eT0iMC40NSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02NC4yNzc1NTgyLDMzLjE3MDQ5NjMgTDExOS4xODU4MzYsMTYuNTY1NDkxNSIgaWQ9IlBhdGgtMTIiIHN0cm9rZT0iI0NGREFFNiIgc3Ryb2tlLXdpZHRoPSIxLjczOTEzMDQzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNDIuMTQzMTcwOCwyNi41MDAyNjgxIEw3LjcxMTkwMTYyLDE0LjU2NDA3MDIiIGlkPSJQYXRoLTE2IiBzdHJva2U9IiNFMEI0QjciIHN0cm9rZS13aWR0aD0iMC43MDI2Nzg5NjQiIG9wYWNpdHk9IjAuNyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtZGFzaGFycmF5PSIxLjQwNTM1Nzg5OTg3MzE1MywyLjEwODAzNjk1MzQ2OTk4MSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02My45MjYyMTg3LDMzLjUyMTU2MSBMNDMuNjcyMTMyNiw2OS4zMjUwOTUxIiBpZD0iUGF0aC0xNSIgc3Ryb2tlPSIjQkFDQUQ5IiBzdHJva2Utd2lkdGg9IjAuNzAyNjc4OTY0IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS1kYXNoYXJyYXk9IjEuNDA1MzU3ODk5ODczMTUzLDIuMTA4MDM2OTUzNDY5OTgxIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTE3IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMjYuODUwOTIyLCAxMy41NDM2NTQpIHJvdGF0ZSgzMC4wMDAwMDApIHRyYW5zbGF0ZSgtMTI2Ljg1MDkyMiwgLTEzLjU0MzY1NCkgdHJhbnNsYXRlKDExNy4yODU3MDUsIDQuMzgxODg5KSIgZmlsbD0iI0NGREFFNiI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxlbGxpcHNlIGlkPSJPdmFsLTQiIG9wYWNpdHk9IjAuNDUiIGN4PSI5LjEzNDgyNjUzIiBjeT0iOS4xMjc2ODA3NiIgcng9IjkuMTM0ODI2NTMiIHJ5PSI5LjEyNzY4MDc2Ij48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xOC4yNjk2NTMxLDE4LjI1NTM2MTUgQzE4LjI2OTY1MzEsMTMuMjE0MjgyNiAxNC4xNzk4NTE5LDkuMTI3NjgwNzYgOS4xMzQ4MjY1Myw5LjEyNzY4MDc2IEM0LjA4OTgwMTE0LDkuMTI3NjgwNzYgMCwxMy4yMTQyODI2IDAsMTguMjU1MzYxNSBMMTguMjY5NjUzMSwxOC4yNTUzNjE1IFoiIGlkPSJPdmFsLTQiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkuMTM0ODI3LCAxMy42OTE1MjEpIHNjYWxlKC0xLCAtMSkgdHJhbnNsYXRlKC05LjEzNDgyNywgLTEzLjY5MTUyMSkgIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTE0IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyMTYuMjk0NzAwLCAxMjMuNzI1NjAwKSByb3RhdGUoLTUuMDAwMDAwKSB0cmFuc2xhdGUoLTIxNi4yOTQ3MDAsIC0xMjMuNzI1NjAwKSB0cmFuc2xhdGUoMTA2LjI5NDcwMCwgMzUuMjI1NjAwKSI+CiAgICAgICAgICAgICAgICAgICAgPGVsbGlwc2UgaWQ9Ik92YWwtMiIgZmlsbD0iI0NGREFFNiIgb3BhY2l0eT0iMC4yNSIgY3g9IjI5LjExNzY0NzEiIGN5PSIyOS4xNDAyNDM5IiByeD0iMjkuMTE3NjQ3MSIgcnk9IjI5LjE0MDI0MzkiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0yIiBmaWxsPSIjQ0ZEQUU2IiBvcGFjaXR5PSIwLjMiIGN4PSIyOS4xMTc2NDcxIiBjeT0iMjkuMTQwMjQzOSIgcng9IjIxLjU2ODYyNzUiIHJ5PSIyMS41ODUzNjU5Ij48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICAgICAgPGVsbGlwc2UgaWQ9Ik92YWwtMi1Db3B5IiBzdHJva2U9IiNDRkRBRTYiIG9wYWNpdHk9IjAuNCIgY3g9IjE3OS4wMTk2MDgiIGN5PSIxMzguMTQ2MzQxIiByeD0iMjMuNzI1NDkwMiIgcnk9IjIzLjc0MzkwMjQiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0yIiBmaWxsPSIjQkFDQUQ5IiBvcGFjaXR5PSIwLjUiIGN4PSIyOS4xMTc2NDcxIiBjeT0iMjkuMTQwMjQzOSIgcng9IjEwLjc4NDMxMzciIHJ5PSIxMC43OTI2ODI5Ij48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTI5LjExNzY0NzEsMzkuOTMyOTI2OCBMMjkuMTE3NjQ3MSwxOC4zNDc1NjEgQzIzLjE2MTYzNTEsMTguMzQ3NTYxIDE4LjMzMzMzMzMsMjMuMTc5NjA5NyAxOC4zMzMzMzMzLDI5LjE0MDI0MzkgQzE4LjMzMzMzMzMsMzUuMTAwODc4MSAyMy4xNjE2MzUxLDM5LjkzMjkyNjggMjkuMTE3NjQ3MSwzOS45MzI5MjY4IFoiIGlkPSJPdmFsLTIiIGZpbGw9IiNCQUNBRDkiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8ZyBpZD0iR3JvdXAtOSIgb3BhY2l0eT0iMC40NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTcyLjAwMDAwMCwgMTMxLjAwMDAwMCkiIGZpbGw9IiNFNkExQTYiPgogICAgICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0yLUNvcHktMiIgY3g9IjcuMDE5NjA3ODQiIGN5PSI3LjE0NjM0MTQ2IiByeD0iNi40NzA1ODgyNCIgcnk9IjYuNDc1NjA5NzYiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTAuNTQ5MDE5NjA4LDEzLjYyMTk1MTIgQzQuMTIyNjI2ODEsMTMuNjIxOTUxMiA3LjAxOTYwNzg0LDEwLjcyMjcyMiA3LjAxOTYwNzg0LDcuMTQ2MzQxNDYgQzcuMDE5NjA3ODQsMy41Njk5NjA5NSA0LjEyMjYyNjgxLDAuNjcwNzMxNzA3IDAuNTQ5MDE5NjA4LDAuNjcwNzMxNzA3IEwwLjU0OTAxOTYwOCwxMy42MjE5NTEyIFoiIGlkPSJPdmFsLTItQ29weS0yIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzLjc4NDMxNCwgNy4xNDYzNDEpIHNjYWxlKC0xLCAxKSB0cmFuc2xhdGUoLTMuNzg0MzE0LCAtNy4xNDYzNDEpICI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0xMCIgZmlsbD0iI0NGREFFNiIgY3g9IjIxOC4zODIzNTMiIGN5PSIxMzguNjg1OTc2IiByeD0iMS42MTc2NDcwNiIgcnk9IjEuNjE4OTAyNDQiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0xMC1Db3B5LTIiIGZpbGw9IiNFMEI0QjciIG9wYWNpdHk9IjAuMzUiIGN4PSIxNzkuNTU4ODI0IiBjeT0iMTc1LjM4MTA5OCIgcng9IjEuNjE3NjQ3MDYiIHJ5PSIxLjYxODkwMjQ0Ij48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICAgICAgPGVsbGlwc2UgaWQ9Ik92YWwtMTAtQ29weSIgZmlsbD0iI0UwQjRCNyIgb3BhY2l0eT0iMC4zNSIgY3g9IjE4MC4wOTgwMzkiIGN5PSIxMDIuNTMwNDg4IiByeD0iMi4xNTY4NjI3NSIgcnk9IjIuMTU4NTM2NTkiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMjguOTk4NTM4MSwyOS45NjcxNTk4IEwxNzEuMTUxMDE4LDEzMi44NzYwMjQiIGlkPSJQYXRoLTExIiBzdHJva2U9IiNDRkRBRTYiIG9wYWNpdHk9IjAuOCI+PC9wYXRoPgogICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTEwIiBvcGFjaXR5PSIwLjc5OTk5OTk1MiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTA1NC4xMDA2MzUsIDM2LjY1OTMxNykgcm90YXRlKC0xMS4wMDAwMDApIHRyYW5zbGF0ZSgtMTA1NC4xMDA2MzUsIC0zNi42NTkzMTcpIHRyYW5zbGF0ZSgxMDI2LjYwMDYzNSwgNC42NTkzMTcpIj4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC03IiBzdHJva2U9IiNDRkRBRTYiIHN0cm9rZS13aWR0aD0iMC45NDExNzY0NzEiIGN4PSI0My44MTM1NTkzIiBjeT0iMzIiIHJ4PSIxMS4xODY0NDA3IiByeT0iMTEuMjk0MTE3NiI+PC9lbGxpcHNlPgogICAgICAgICAgICAgICAgICAgIDxnIGlkPSJHcm91cC0xMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzQuNTk2Nzc0LCAyMy4xMTExMTEpIiBmaWxsPSIjQkFDQUQ5Ij4KICAgICAgICAgICAgICAgICAgICAgICAgPGVsbGlwc2UgaWQ9Ik92YWwtNyIgb3BhY2l0eT0iMC40NSIgY3g9IjkuMTg1MzQ3MTgiIGN5PSI4Ljg4ODg4ODg5IiByeD0iOC40NzQ1NzYyNyIgcnk9IjguNTU2MTQ5NzMiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTkuMTg1MzQ3MTgsMTcuNDQ1MDM4NiBDMTMuODY1NzI2NCwxNy40NDUwMzg2IDE3LjY1OTkyMzUsMTMuNjE0MzE5OSAxNy42NTk5MjM1LDguODg4ODg4ODkgQzE3LjY1OTkyMzUsNC4xNjM0NTc4NyAxMy44NjU3MjY0LDAuMzMyNzM5MTU2IDkuMTg1MzQ3MTgsMC4zMzI3MzkxNTYgTDkuMTg1MzQ3MTgsMTcuNDQ1MDM4NiBaIiBpZD0iT3ZhbC03Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0zNC42NTk3Mzg1LDI0LjgwOTY5NCBMNS43MTY2NjA4NCw0Ljc2ODc4OTQ1IiBpZD0iUGF0aC0yIiBzdHJva2U9IiNDRkRBRTYiIHN0cm9rZS13aWR0aD0iMC45NDExNzY0NzEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbCIgc3Ryb2tlPSIjQ0ZEQUU2IiBzdHJva2Utd2lkdGg9IjAuOTQxMTc2NDcxIiBjeD0iMy4yNjI3MTE4NiIgY3k9IjMuMjk0MTE3NjUiIHJ4PSIzLjI2MjcxMTg2IiByeT0iMy4yOTQxMTc2NSI+PC9lbGxpcHNlPgogICAgICAgICAgICAgICAgICAgIDxlbGxpcHNlIGlkPSJPdmFsLUNvcHkiIGZpbGw9IiNGN0UxQUQiIGN4PSIyLjc5NjYxMDE3IiBjeT0iNjEuMTc2NDcwNiIgcng9IjIuNzk2NjEwMTciIHJ5PSIyLjgyMzUyOTQxIj48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTM0LjYzMTI0NDMsMzkuMjkyMjcxMiBMNS4wNjM2NjY2Myw1OS43ODUwODIiIGlkPSJQYXRoLTEwIiBzdHJva2U9IiNDRkRBRTYiIHN0cm9rZS13aWR0aD0iMC45NDExNzY0NzEiPjwvcGF0aD4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgIDxnIGlkPSJHcm91cC0xOSIgb3BhY2l0eT0iMC4zMyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTI4Mi41MzcyMTksIDQ0Ni41MDI4NjcpIHJvdGF0ZSgtMTAuMDAwMDAwKSB0cmFuc2xhdGUoLTEyODIuNTM3MjE5LCAtNDQ2LjUwMjg2NykgdHJhbnNsYXRlKDExNDIuNTM3MjE5LCAzMjcuNTAyODY3KSI+CiAgICAgICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTE3IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNDEuMzMzNTM5LCAxMDQuNTAyNzQyKSByb3RhdGUoMjc1LjAwMDAwMCkgdHJhbnNsYXRlKC0xNDEuMzMzNTM5LCAtMTA0LjUwMjc0MikgdHJhbnNsYXRlKDEyOS4zMzM1MzksIDkyLjUwMjc0MikiIGZpbGw9IiNCQUNBRDkiPgogICAgICAgICAgICAgICAgICAgICAgICA8Y2lyY2xlIGlkPSJPdmFsLTQiIG9wYWNpdHk9IjAuNDUiIGN4PSIxMS42NjY2NjY3IiBjeT0iMTEuNjY2NjY2NyIgcj0iMTEuNjY2NjY2NyI+PC9jaXJjbGU+CiAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMy4zMzMzMzMzLDIzLjMzMzMzMzMgQzIzLjMzMzMzMzMsMTYuODkwMDExMyAxOC4xMDk5ODg3LDExLjY2NjY2NjcgMTEuNjY2NjY2NywxMS42NjY2NjY3IEM1LjIyMzM0NDU5LDExLjY2NjY2NjcgMCwxNi44OTAwMTEzIDAsMjMuMzMzMzMzMyBMMjMuMzMzMzMzMywyMy4zMzMzMzMzIFoiIGlkPSJPdmFsLTQiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDExLjY2NjY2NywgMTcuNTAwMDAwKSBzY2FsZSgtMSwgLTEpIHRyYW5zbGF0ZSgtMTEuNjY2NjY3LCAtMTcuNTAwMDAwKSAiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICAgICAgPGNpcmNsZSBpZD0iT3ZhbC01LUNvcHktNiIgZmlsbD0iI0NGREFFNiIgY3g9IjIwMS44MzMzMzMiIGN5PSI4Ny41IiByPSI1LjgzMzMzMzMzIj48L2NpcmNsZT4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQzLjUsODguODEyNjY4NSBMMTU1LjA3MDUwMSwxNy42MDM4NTQ0IiBpZD0iUGF0aC0xNyIgc3Ryb2tlPSIjQkFDQUQ5IiBzdHJva2Utd2lkdGg9IjEuMTY2NjY2NjciPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTcuNSwzNy4zMzMzMzMzIEwxMjcuNDY2MjUyLDk3LjY0NDk3MzUiIGlkPSJQYXRoLTE4IiBzdHJva2U9IiNCQUNBRDkiIHN0cm9rZS13aWR0aD0iMS4xNjY2NjY2NyI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwb2x5bGluZSBpZD0iUGF0aC0xOSIgc3Ryb2tlPSIjQ0ZEQUU2IiBzdHJva2Utd2lkdGg9IjEuMTY2NjY2NjciIHBvaW50cz0iMTQzLjkwMjU5NyAxMjAuMzAyMjgxIDE3NC45MzU0NTUgMjMxLjU3MTM0MiAzOC41IDE0Ny41MTA4NDcgMTI2LjM2Njk0MSAxMTAuODMzMzMzIj48L3BvbHlsaW5lPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNTkuODMzMzMzLDk5Ljc0NTM4NDIgTDE5NS40MTY2NjcsODkuMjUiIGlkPSJQYXRoLTIwIiBzdHJva2U9IiNFMEI0QjciIHN0cm9rZS13aWR0aD0iMS4xNjY2NjY2NyIgb3BhY2l0eT0iMC42Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTIwNS4zMzMzMzMsODIuMTM3MjEwNSBMMjM4LjcxOTQwNiwzNi4xNjY2NjY3IiBpZD0iUGF0aC0yNCIgc3Ryb2tlPSIjQkFDQUQ5IiBzdHJva2Utd2lkdGg9IjEuMTY2NjY2NjciPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMjY2LjcyMzQyNCwxMzIuMjMxOTg4IEwyMDcuMDgzMzMzLDkwLjQxNjY2NjciIGlkPSJQYXRoLTI1IiBzdHJva2U9IiNDRkRBRTYiIHN0cm9rZS13aWR0aD0iMS4xNjY2NjY2NyI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxjaXJjbGUgaWQ9Ik92YWwtNSIgZmlsbD0iI0MxRDFFMCIgY3g9IjE1Ni45MTY2NjciIGN5PSI4Ljc1IiByPSI4Ljc1Ij48L2NpcmNsZT4KICAgICAgICAgICAgICAgICAgICA8Y2lyY2xlIGlkPSJPdmFsLTUtQ29weS0zIiBmaWxsPSIjQzFEMUUwIiBjeD0iMzkuMDgzMzMzMyIgY3k9IjE0OC43NSIgcj0iNS4yNSI+PC9jaXJjbGU+CiAgICAgICAgICAgICAgICAgICAgPGNpcmNsZSBpZD0iT3ZhbC01LUNvcHktMiIgZmlsbC1vcGFjaXR5PSIwLjYiIGZpbGw9IiNEMURFRUQiIGN4PSI4Ljc1IiBjeT0iMzMuMjUiIHI9IjguNzUiPjwvY2lyY2xlPgogICAgICAgICAgICAgICAgICAgIDxjaXJjbGUgaWQ9Ik92YWwtNS1Db3B5LTQiIGZpbGwtb3BhY2l0eT0iMC42IiBmaWxsPSIjRDFERUVEIiBjeD0iMjQzLjgzMzMzMyIgY3k9IjMwLjMzMzMzMzMiIHI9IjUuODMzMzMzMzMiPjwvY2lyY2xlPgogICAgICAgICAgICAgICAgICAgIDxjaXJjbGUgaWQ9Ik92YWwtNS1Db3B5LTUiIGZpbGw9IiNFMEI0QjciIGN4PSIxNzUuNTgzMzMzIiBjeT0iMjMyLjc1IiByPSI1LjI1Ij48L2NpcmNsZT4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+);/* background-color: #112346; */background-repeat: no-repeat;background-position: center right;background-size: 100%;
}
.login-container {border-radius: 10px;margin: 0px auto;width: 350px;padding: 30px 35px 15px 35px;background: #fff;border: 1px solid #eaeaea;text-align: left;box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.1);
}
.title {margin: 0px auto 40px auto;text-align: center;color: #505458;
}
.remember {margin: 0px 0px 35px 0px;
}
.code-box {text-align: right;
}
.codeimg {height: 40px;
}
</style>

7.8.2.后台页面admin.vue

<template><el-container class="index-con"><el-aside :class="showclass"><leftnav></leftnav></el-aside><el-container class="main-con"><el-header class="index-header"><navcon></navcon></el-header><el-main clss="index-main"><router-view></router-view></el-main></el-container></el-container>
</template>
<script>
// 导入组件
import navcon from '../components/navcon.vue'
import leftnav from '../components/leftnav.vue'
export default {name: 'admin',data() {return {showclass: 'asideshow',showtype: false}},// 注册组件components: {navcon,leftnav},methods: {},created() {// 监听this.$root.Bus.$on('toggle', value => {if (value) {this.showclass = 'asideshow'} else {setTimeout(() => {this.showclass = 'aside'}, 300)}})},beforeUpdate() {},// 挂载前状态(里面是操作)beforeMount() {// 弹出登录成功/*this.$message({message: '登录成功',type: 'success'})*/}
}
</script>
<style >
.index-con {height: 100%;width: 100%;box-sizing: border-box;
}.aside {width: 64px !important;height: 100%;background-color: #334157;margin: 0px;
}
.asideshow {width: 240px !important;height: 100%;background-color: #334157;margin: 0px;
}
.index-header,
.index-main {padding: 0px;border-left: 2px solid #333;
}
</style>

7.8.2.后台顶部页面navcon.vue

/**
* 头部菜单
*/
<template><el-menu class="el-menu-demo" mode="horizontal" background-color="#334157" text-color="#fff" active-text-color="#fff"><el-button class="buttonimg"><img class="showimg" :src="collapsed?imgsq:imgshow" @click="toggle(collapsed)"></el-button><el-submenu index="2" class="submenu"><template slot="title">{{adminName}}</template><el-menu-item>设置</el-menu-item><el-menu-item>个人中心</el-menu-item><el-menu-item @click="exit()" index="2-3">退出</el-menu-item></el-submenu></el-menu>
</template>
<script>import cookie from "js-cookie";
export default {name: 'navcon',data() {return {collapsed: true,imgshow: require('../assets/img/show.png'),imgsq: require('../assets/img/sq.png'),adminName: ''}},// 创建完毕状态(里面是操作)created() {this.adminName = cookie.get('adminName')},methods: {// 退出登录exit() {this.$confirm('退出登录, 是否继续?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {setTimeout(() => {this.$router.push({ path: '/' })cookie.set('adminToken', '', {domain: 'localhost'})cookie.set('adminName', '', {domain: 'localhost'})this.$message({type: 'success',message: '已退出登录!'})}, 1000)}).catch(() => {this.$message({type: 'info',message: '已取消'})})},// 切换显示toggle(showtype) {this.collapsed = !showtypethis.$root.Bus.$emit('toggle', this.collapsed)}}
}
</script>
<style scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {border: none;
}
.submenu {float: right;position: absolute;right: 0;top: 0px;
}
.buttonimg {height: 60px;background-color: transparent;border: none;
}
.showimg {width: 26px;height: 26px;position: absolute;top: 17px;left: 17px;
}
.showimg:active {border: none;
}
</style>

7.8.2.后台左侧页面leftnav.vue

/**
* 左边菜单
*/
<template><el-menu :collapse="collapsed" collapse-transition router unique-opened class="el-menu-vertical-demo" background-color="#334157" text-color="#fff" active-text-color="#ffd04b"><div class="logobox"><img class="logoimg" src="../assets/img/logo.png" alt=""></div><router-link to="/main"><el-menu-item index="Index"><template slot="title"><i class="el-icon-s-home"></i><span slot="title">首页</span></template></el-menu-item></router-link><el-submenu v-for="menu in menuBeanList" :key="menu.menuid" :index="menu.menuName"><template slot="title"><i class="iconfont" :class="menu.icon"></i>&nbsp;<span>{{menu.menuName}}</span></template><el-menu-item-group v-if="menu.menuList != null"><el-menu-item v-for="chmenu in menu.menuList" :index="'/'+chmenu.url" :key="chmenu.menuId"><i class="iconfont" :class="chmenu.icon"></i>&nbsp;<span>{{chmenu.menuName}}</span></el-menu-item></el-menu-item-group></el-submenu></el-menu>
</template><script>
import menuApi from "../api/fastdfs/menu";
export default {name: 'leftnav',data() {return {collapsed: false,allmenu: [],menuBeanList:[],}},// 创建完毕状态(里面是操作)created() {this.$root.Bus.$on('toggle', value => {this.collapsed = !value})menuApi.getMenuByRoleId().then(response=>{this.menuBeanList = response.data.menuBeanList})}
}
</script>
<style>
.el-menu-vertical-demo:not(.el-menu--collapse) {width: 240px;min-height: 400px;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {border: none;text-align: left;
}
.el-menu-item-group__title {padding: 0px;
}
.el-menu-bg {background-color: #1f2d3d !important;
}
.el-menu {border: none;
}
.logobox {height: 40px;line-height: 40px;color: #9d9d9d;font-size: 20px;text-align: center;padding: 20px 0px;
}
.logoimg {height: 40px;
}
</style>

7.8.2.主界面main.vue

<template><div><div class="body" style="z-index:1"><div class="stars" ref="starsRef"><div class="star" v-for="(item, index) in starsCount" :key="index"></div><div style="z-index: 10;font-size: 50px;color: #a0cfff"><span>欢迎登录后台管理系统=>{{ adminName }}</span></div></div><div style="z-index: 10;font-size: 50px;color: #a0cfff;margin-top: 200px;margin-left: 200px"><span>欢迎登录后台管理系统=>{{ adminName }}</span></div></div></div></template><script>
import cookie from "js-cookie";export default {name: "main",data() {return {adminName: '',num: 5,starsCount: 1000, //星星数量distance: 900, //间距}},// 创建完毕状态(里面是操作)created() {this.adminName = cookie.get('adminName')},mounted() {console.log(this.$refs.starsRef.children);let starNodes = Array.from(this.$refs.starsRef.children);starNodes.forEach((item) => {let speed = 0.2 + Math.random() * 1;let thisDistance = this.distance + Math.random() * 300;item.style.transformOrigin = `0 0 ${thisDistance}px`;item.style.transform =`translate3d(0,0,-${thisDistance}px)rotateY(${Math.random() * 360}deg)rotateX(${Math.random() * -50}deg)scale(${speed},${speed})`;});}}
</script><style scoped>
.body {position: absolute;width: 86%;height: 90%;margin: 0;padding: 0;background: radial-gradient(200% 100% at bottom center,#f7f7b6,#e96f92,#1b2947);background: radial-gradient(200% 105% at top center,#1b2947 10%,#75517d 40%,#e96f92 65%,#f7f7b6);background-attachment: fixed;overflow: hidden;
}@keyframes rotate {0% {transform: perspective(400px) rotateZ(20deg) rotateX(-40deg) rotateY(0);}100% {transform: perspective(400px) rotateZ(20deg) rotateX(-40deg) rotateY(-360deg);}
}.stars {transform: perspective(500px);transform-style: preserve-3d;position: absolute;perspective-origin: 50% 100%;left: 45%;animation: rotate 90s infinite linear;bottom: 0;
}.star {width: 2px;height: 2px;background: #f7f7b6;position: absolute;left: 0;top: 0;backface-visibility: hidden;
}
</style>

7.8.3.identify.vue

<template><div class="s-canvas"><canvas id="s-canvas" :width="contentWidth" :height="contentHeight"></canvas></div>
</template>
<script>
export default{name: 'SIdentify',props: {identifyCode: {type: String,default: '1234'},fontSizeMin: {type: Number,default: 16},fontSizeMax: {type: Number,default: 40},backgroundColorMin: {type: Number,default: 180},backgroundColorMax: {type: Number,default: 240},colorMin: {type: Number,default: 50},colorMax: {type: Number,default: 160},lineColorMin: {type: Number,default: 40},lineColorMax: {type: Number,default: 180},dotColorMin: {type: Number,default: 0},dotColorMax: {type: Number,default: 255},contentWidth: {type: Number,default: 112},contentHeight: {type: Number,default: 38}},methods: {// 生成一个随机数randomNum (min, max) {return Math.floor(Math.random() * (max - min) + min)},// 生成一个随机的颜色randomColor (min, max) {let r = this.randomNum(min, max)let g = this.randomNum(min, max)let b = this.randomNum(min, max)return 'rgb(' + r + ',' + g + ',' + b + ')'},drawPic () {let canvas = document.getElementById('s-canvas')let ctx = canvas.getContext('2d')ctx.textBaseline = 'bottom'// 绘制背景ctx.fillStyle = this.randomColor(this.backgroundColorMin, this.backgroundColorMax)ctx.fillRect(0, 0, this.contentWidth, this.contentHeight)// 绘制文字for (let i = 0; i < this.identifyCode.length; i++) {this.drawText(ctx, this.identifyCode[i], i)}this.drawLine(ctx)this.drawDot(ctx)},drawText (ctx, txt, i) {ctx.fillStyle = this.randomColor(this.colorMin, this.colorMax)ctx.font = this.randomNum(this.fontSizeMin, this.fontSizeMax) + 'px SimHei'let x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1))let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5)var deg = this.randomNum(-45, 45)// 修改坐标原点和旋转角度ctx.translate(x, y)ctx.rotate(deg * Math.PI / 180)ctx.fillText(txt, 0, 0)// 恢复坐标原点和旋转角度ctx.rotate(-deg * Math.PI / 180)ctx.translate(-x, -y)},drawLine (ctx) {// 绘制干扰线for (let i = 0; i < 8; i++) {ctx.strokeStyle = this.randomColor(this.lineColorMin, this.lineColorMax)ctx.beginPath()ctx.moveTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight))ctx.lineTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight))ctx.stroke()}},drawDot (ctx) {// 绘制干扰点for (let i = 0; i < 100; i++) {ctx.fillStyle = this.randomColor(0, 255)ctx.beginPath()ctx.arc(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight), 1, 0, 2 * Math.PI)ctx.fill()}}},watch: {identifyCode () {this.drawPic()}},mounted () {this.drawPic()}
}
</script>

7.8.4.request.js

import axios from 'axios'
import {Message} from 'element-ui'
import cookie from 'js-cookie'// 创建axios实例
const service = axios.create({baseURL: 'http://localhost:9090', // api 的 base_urltimeout: 1000000 // 请求超时时间
})// http request 拦截器
// 请求拦截器
service.interceptors.request.use(config => {// 可以在这里添加请求头等信息// token 先不处理,后续使用时在完善if (cookie.get('adminToken')) {config.headers['token'] = cookie.get('adminToken')}return config;},err => {// 请求错误处理console.log(err);return Promise.reject(err);}
);// http response 拦截器
// 响应拦截器
service.interceptors.response.use(response => {// 对响应数据做处理,例如只返回data部分//const data = response.data;//return data;if (response.code === 208) {this.$message.warning(response.message)router.push('login')return} else {if (response.data.code === 200) {return response.data} else {Message({message: response.data.message,type: 'error',duration: 5 * 1000})return Promise.reject(response.data)}}},error => {// 响应错误处理console.log('err' + error); // for debug//return Promise.reject(error);return Promise.reject(error.response);}
);export default service;

7.8.5.store.js

import Vue from 'vue';
import Vuex from 'vuex';Vue.use(Vuex);
// 登录验证
export default new Vuex.Store({state: {user: false},mutations: {// 登录login(state, adminName) {state.adminName = adminName;localStorage.setItem("adminName", adminName);},// 退出logout(state, adminName) {state.adminName = "";localStorage.setItem("adminName", "");}}
})

7.8.6.util.js

/*** 时间戳* @param {*} timestamp  时间戳*/const timestampToTime = (timestamp) => {let date = new Date(timestamp) //时间戳为10位需*1000,时间戳为13位的话不需乘1000let Y = date.getFullYear() + '-'let M =(date.getMonth() + 1 < 10 ?'0' + (date.getMonth() + 1) :date.getMonth() + 1) + '-'let D =(date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' 'let h =(date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':'let m =(date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) +':'let s =date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()return Y + M + D + h + m + s
};
/*** 存储localStorage*/
const setStore = (name, content) => {if (!name) return;if (typeof content !== 'string') {content = JSON.stringify(content);}window.localStorage.setItem(name, content);
}/*** 获取localStorage*/
const getStore = name => {if (!name) return;return window.localStorage.getItem(name);
}/*** 删除localStorage*/
const removeStore = name => {if (!name) return;window.localStorage.removeItem(name);
}/*** 设置cookie**/
function setCookie(name, value, day) {let date = new Date();date.setDate(date.getDate() + day);document.cookie = name + '=' + value + ';expires=' + date;
};/*** 获取cookie**/
function getCookie(name) {let reg = RegExp(name + '=([^;]+)');let arr = document.cookie.match(reg);if (arr) {return arr[1];} else {return '';}
};/*** 删除cookie**/
function delCookie(name) {setCookie(name, null, -1);
};/*** 导出 **/
export default{timestampToTime,setStore,getStore,removeStore,setCookie,getCookie,delCookie
}

7.8.7.index.js

//在路由文件router/index.js中配置
// 该文件专门用于创建整个应用的路由器
// 创建应用程序的路由器
import Vue from 'vue'
import VueRouter from 'vue-router'
// 此时就可以在Vue实例中配置路由器了
Vue.use(VueRouter)// 创建并暴露一个路由器
export default new VueRouter({routes:[{path:'/',name:'login',meta:{title:"登录页"},//redirect:'front/login',component:() => import('../view/login'),/*hidden: true,meta: {requireAuth: false //登录权限实现(登录拦截)}*/},{path:'/admin',name:'admin',meta:{title:"首页"},component:() => import('../view/admin'),children:[{path:'/main',name:'main',meta:{title:"首页"},component:() => import('../view/main')},//用户管理{path:'/user',name:'user',meta:{title:"用户管理:超级管理员:用户"},component:() => import('../view/user/user')},],},{path:'/admin',name:'admin',meta:{title:"文件管理"},component:() => import('../view/admin'),children:[{path:'/main',name:'main',meta:{title:"首页"},component:() => import('../view/main')},//用户管理{path:'/user',name:'user',meta:{title:"用户管理:超级管理员:用户"},component:() => import('../view/user/user')},//文件管理{path:'/upload',name:'upload',meta:{title:"文件管理:上传文件"},component:() => import('../view/fastdfs/fastdfsuploadimg')},{path:'/file',name:'file',meta:{title:"文件管理:文件"},component:() => import('../view/fastdfs/fastdfsimg')},],},],mode:'history', //去除#号base: process.env.BASE_URL,
})

7.8.8.admin.js

import request from "@/utils/request";const api_name = '/admins'export default {//登录loginAdmin(name,password){return request({url: `${api_name}/${name}/${password}`,method:'post'})},//获取当前用户信息getAdminById(){return request({url: `${api_name}`,method:'get'})}}

7.8.9.menu.js

import request from "@/utils/request";const api_name = '/menus'export default {//获取菜单列表getMenuByRoleId(){return request({url: `${api_name}`,method:'get'})},}

7.8.10.main.js

// 引入App
import App from './App.vue'
//引入Vue
import Vue from 'vue'
//引入axios
import axios from 'axios'
//引入VueAxios
//安装VueAxios模块后,不需要在每个组件中单独导入axios,只需将axios请求改为this.axios
import VueAxios from 'vue-axios'
//引入VueRouter
import VueRouter from 'vue-router'
//完整引入
//引入ElementUI组件库
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
//新建一个router文件夹,在文件夹下新建一个index.js文件
//引入路由器
import router from './router/index'
// 引入状态管理
import store from './utils/store'//引入qs模块发送post
import qs from 'qs'Vue.prototype.$qs = qsimport SIdentify from "@/view/code/identify";Vue.use(SIdentify)
// 过滤器
import * as custom from './utils/util'// 二维码生成器
import VueQriously from 'vue-qriously'Vue.use(VueQriously)
Vue.config.silent = true// 设置全局变量
Vue.prototype.$baseImagePath = 'http://192.168.229.141'
//this.$baseImagePath直接引用
//把axios挂载到vue上
Vue.prototype.$axios = axios;
//使用Vue.use来注册安装插件
Vue.use(VueRouter)
Vue.use(router)
Vue.use(VueAxios, axios)
//使用ElementUI组件库
Vue.use(ElementUI)
//关闭Vue的生产提示
Vue.config.productionTip = falseObject.keys(custom).forEach(key => {Vue.filter(key, custom[key])
})// 创建和挂载根实例
new Vue({store, //使用store vuex状态管理router, //将路由器注入到new Vue实例中,建立关联render: h => h(App), //将App组件放入容器中data: {// 空的实例放到根组件下,所有的子组件都能调用Bus: new Vue()}
}).$mount('#app');

7.9.效果展示

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

endl

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/686456.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《Go 简易速速上手小册》第7章:包管理与模块(2024 最新版)

文章目录 7.1 使用 Go Modules 管理依赖 - 掌舵向未来7.1.1 基础知识讲解7.1.2 重点案例&#xff1a;Web 服务功能描述实现步骤扩展功能 7.1.3 拓展案例 1&#xff1a;使用数据库功能描述实现步骤扩展功能 7.1.4 拓展案例 2&#xff1a;集成 Redis 缓存功能描述实现步骤扩展功能…

Sora 和之前 Runway 那些在架构上有啥区别呢?

问&#xff1a;Sora 和之前 Runway 那些在架构上有啥区别呢&#xff1f; 答&#xff1a;简单来说 Runway 是基于扩散模型&#xff08;Diffusion Model&#xff09;的&#xff0c;而 Sora 是基于 Diffusion Transformer。 Runway、Stable Diffusion 是基于扩散模型&#xff08…

MySQL 插入10万条数据性能分析

MySQL 插入10万条数据性能分析 一、背景 笔者想复现一个索引失效的场景&#xff0c;故需要一定规模的数据作支撑&#xff0c;所以需要向数据库中插入大约一百万条数据。那问题就来了&#xff0c;我们应该怎样插入才能使插入的速度最快呢&#xff1f; 为了更加贴合实际&#…

cool Node后端 中实现中间件的书写

1.需求 在node后端中&#xff0c;想实现一个专门鉴权的文件配置&#xff0c;可以这样来解释 就是 有些接口需要token调用接口&#xff0c;有些接口不需要使用token 调用 这期来详细说明一下 什么是中间件中间件顾名思义是指在请求和响应中间,进行请求数据的拦截处理&#xf…

如何用AI绘画工具最好最省时省事的方法制作个性化头像框?

原文章链接&#xff1a;如何根据游戏素材制作主题头像框&#xff1f;实战教程来了&#xff01; - 优设网 - 学设计上优设 教程专区&#xff1a;AI绘画&#xff0c;AI视频&#xff0c;AI写作等软件类型AI教程&#xff0c; AI工具专区&#xff1a;AI工具-喜好儿aigc 在 APP 的…

「算法」二分查找1:理论细节

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;算法详解 &#x1f387;欢迎点赞收藏加关注哦&#xff01; 二分查找算法简介 这个算法的特点就是&#xff1a;细节多&#xff0c;出错率高&#xff0c;很容易就写成死循环有模板&#xff0c;但…

如何在UI自动化测试中加入REST API的操作

1、问题 当我们描述一个“好的自动化测试用例”时&#xff0c;经常出现标准是&#xff1a; 精确 自动化测试用例应该测试一件事&#xff0c;只有一件事。与测试用例无关的应用程序的某个部分中的错误不应导致测试用例失败。 独立 自动化测试用例不应该受测试套件中任何其他…

PyTorch-线性回归

已经进入大模微调的时代&#xff0c;但是学习pytorch&#xff0c;对后续学习rasa框架有一定帮助吧。 <!-- 给出一系列的点作为线性回归的数据&#xff0c;使用numpy来存储这些点。 --> x_train np.array([[3.3], [4.4], [5.5], [6.71], [6.93], [4.168],[9.779], [6.1…

win32汇编获取系统信息

.data fmt db "页尺寸&#xff1a;%d",0 db "" lpsystem SYSTEM_INFO <?> szbuf db 200 dup(0) .const szCaption db 系统信息,0 .code start: invoke GetSystemInfo,addr lpsystem …

Java编程在工资信息管理中的最佳实践

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

用Java实现简单的图书管理系统

目录 1.总体框架 2.book包 Books类 booklist类 3.operation包 IO接口&#xff1a; addbooks类&#xff1a; borrowbooks类&#xff1a; delbooks类&#xff1a; returnbooks类&#xff1a; exit类&#xff1a; 4.user包 user类 Adminuser类&#xff08;难点&#…

嵌入式linux驱动开发篇之设备树

什么是设备树&#xff1f; 设备树&#xff08;Device Tree&#xff09;是一种用于描述嵌入式系统硬件组件及其连接关系的数据结构。它被广泛用于嵌入式 Linux 系统&#xff0c;尤其是针对使用多种不同架构和平台的嵌入式系统。它是一种与硬件描述相关的中间表示形式&#xff0c…

如何生成狗血短剧

如何生成狗血短剧 狗血短剧剧本将上述剧本转成对话 狗血短剧剧本 标题&#xff1a;《爱的轮回》 类型&#xff1a;现代都市爱情短剧 角色&#xff1a; 1. 林晓雪 - 女&#xff0c;25岁&#xff0c;职场小白&#xff0c;善良单纯 2. 陆子轩 - 男&#xff0c;28岁&#xff0c;公…

WINCC如何新增下单菜单,切换显示页面

杭州工控赖工 首先我们先看一下&#xff0c;显示的效果&#xff0c;通过下拉菜单&#xff0c;切换主显示页面。如图一&#xff1a; 图1 显示效果 第一步&#xff1a; 通过元件新增一个组合框&#xff0c;见图2&#xff1b; 组合框的设置&#xff0c;设置下拉框的长宽及组合数…

Rust 数据结构与算法:1算法分析之乱序字符串检查

Rust 数据结构与算法 一、算法分析 算法是通用的旨在解决某种问题的指令列表。 算法分析是基于算法使用的资源量来进行比较的。之所以说一个算法比另一个算法好,原因就在于前者在使用资源方面更有效率,或者说前者使用了更少的资源。 ●算法使用的空间指的是内存消耗。算法…

基于springboot智慧外贸平台源码和论文

网络的广泛应用给生活带来了十分的便利。所以把智慧外贸管理与现在网络相结合&#xff0c;利用java技术建设智慧外贸平台&#xff0c;实现智慧外贸的信息化。则对于进一步提高智慧外贸管理发展&#xff0c;丰富智慧外贸管理经验能起到不少的促进作用。 智慧外贸平台能够通过互…

神经网络算法原理

目录 得分函数 数学表示 计算方法 损失函数 ​编辑 前向传播 反向传播 ​编辑 整体架构 正则化的作用 数据预处理 ​过拟合解决方法 得分函数 得分函数是在机器学习和自然语言处理中常用的一种函数&#xff0c;用于评估模型对输入数据的预测结果的准确性或匹配程度。…

【Python---六大数据结构】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;Python &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; Python---六大数据结构 往期内容前言概述一下可变与不可变 Number四种不同的数值类型Number类型的创建i…

2024年【天津市安全员B证】新版试题及天津市安全员B证复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 天津市安全员B证新版试题参考答案及天津市安全员B证考试试题解析是安全生产模拟考试一点通题库老师及天津市安全员B证操作证已考过的学员汇总&#xff0c;相对有效帮助天津市安全员B证复审考试学员顺利通过考试。 1、…

人工智能学习与实训笔记(七):神经网络之模型压缩与知识蒸馏

人工智能专栏文章汇总&#xff1a;人工智能学习专栏文章汇总-CSDN博客 本篇目录 七、模型压缩与知识蒸馏 7.1 模型压缩 7.2 知识蒸馏 7.2.1 知识蒸馏的原理 7.2.2 知识蒸馏的种类 7.2.3 知识蒸馏的作用 七、模型压缩与知识蒸馏 出于对响应速度&#xff0c;存储大小和能…