一、平台管理前端
步骤①:拷贝资料中提供的前端项目到没有中文的目录下
步骤②:在leadnews.conf文件夹下新增heima-leadnews-admin.conf配置文件
内容如下:根据自己的情况更改root地址
upstream heima-admin-gateway{
server localhost:51603;
}
server {
listen 8803;
location / {
root D:/IDEA/frontProject/admin-web/;
index index.html;
}
location ~/service_6001/(.*) {
proxy_pass http://heima-admin-gateway/$1;
proxy_set_header HOST $host; # 不改变源请求头的值
proxy_pass_request_body on; #开启获取请求体
proxy_pass_request_headers on; #开启获取请求头
proxy_set_header X-Real-IP $remote_addr; # 记录真实发出请求的客户端IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #记录代理信息
}
}
步骤③:重启nginx,访问 http://localhost:8803/#/login
二、登录及网关
1. 登录
步骤①:导入资料中的leadnews_admin.sql
/*
Navicat Premium Data Transfer
Source Server : localhost
Source Server Type : MySQL
Source Server Version : 50721
Source Host : localhost:3306
Source Schema : leadnews_admin
Target Server Type : MySQL
Target Server Version : 50721
File Encoding : 65001
Date: 26/07/2021 01:45:37
*/
DROP DATABASE IF EXISTS leadnews_admin;
CREATE DATABASE leadnews_admin;
USE leadnews_admin;
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for ad_article_statistics
-- ----------------------------
DROP TABLE IF EXISTS `ad_article_statistics`;
CREATE TABLE `ad_article_statistics` (
`id` int(11) UNSIGNED NOT NULL COMMENT '主键',
`article_we_media` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '主账号ID',
`article_crawlers` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '子账号ID',
`channel_id` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '频道ID',
`read_20` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '草读量',
`read_100` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '读完量',
`read_count` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '阅读量',
`comment` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '评论量',
`follow` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '关注量',
`collection` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '收藏量',
`forward` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '转发量',
`likes` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '点赞量',
`unlikes` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '不喜欢',
`unfollow` int(11) UNSIGNED NULL DEFAULT NULL COMMENT 'unfollow',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文章数据统计表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ad_article_statistics
-- ----------------------------
-- ----------------------------
-- Table structure for ad_channel_label
-- ----------------------------
DROP TABLE IF EXISTS `ad_channel_label`;
CREATE TABLE `ad_channel_label` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
`channel_id` int(11) UNSIGNED NULL DEFAULT NULL,
`label_id` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '标签ID',
`ord` int(5) UNSIGNED NULL DEFAULT NULL COMMENT '排序',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1118 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '频道标签信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ad_channel_label
-- ----------------------------
INSERT INTO `ad_channel_label` VALUES (1108, 1, 1, 0);
INSERT INTO `ad_channel_label` VALUES (1109, 1, 8, 0);
INSERT INTO `ad_channel_label` VALUES (1110, 7, 7, 0);
INSERT INTO `ad_channel_label` VALUES (1111, 7, 9, 0);
INSERT INTO `ad_channel_label` VALUES (1112, 3, 3, 0);
INSERT INTO `ad_channel_label` VALUES (1113, 7, 2, 0);
INSERT INTO `ad_channel_label` VALUES (1114, 3, 4, 0);
INSERT INTO `ad_channel_label` VALUES (1115, 5, 5, 0);
INSERT INTO `ad_channel_label` VALUES (1116, 4, 6, 0);
INSERT INTO `ad_channel_label` VALUES (1117, 6, 10, 0);
-- ----------------------------
-- Table structure for ad_function
-- ----------------------------
DROP TABLE IF EXISTS `ad_function`;
CREATE TABLE `ad_function` (
`id` int(11) UNSIGNED NOT NULL,
`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '功能名称',
`code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '功能代码',
`parent_id` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '父功能',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '登录时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '页面功能信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ad_function
-- ----------------------------
-- ----------------------------
-- Table structure for ad_label
-- ----------------------------
DROP TABLE IF EXISTS `ad_label`;
CREATE TABLE `ad_label` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '频道名称',
`type` tinyint(1) UNSIGNED NULL DEFAULT NULL COMMENT '0系统增加\r\n 1人工增加',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `idx_name`(`name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 24237 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '标签信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ad_label
-- ----------------------------
INSERT INTO `ad_label` VALUES (1, 'java', 0, '2019-08-22 16:30:16');
INSERT INTO `ad_label` VALUES (2, 'docker', 0, '2019-08-22 16:30:52');
INSERT INTO `ad_label` VALUES (3, 'mysql', 0, '2019-08-22 16:31:17');
INSERT INTO `ad_label` VALUES (4, 'vue', 0, '2019-08-22 16:35:39');
INSERT INTO `ad_label` VALUES (5, 'Weex', 0, '2019-08-22 16:36:08');
INSERT INTO `ad_label` VALUES (6, 'Python', 0, '2019-08-22 16:36:34');
INSERT INTO `ad_label` VALUES (7, '大数据', 0, '2019-08-22 16:36:48');
INSERT INTO `ad_label` VALUES (8, 'spring', 0, '2019-08-22 16:39:11');
INSERT INTO `ad_label` VALUES (9, 'hbase', 0, '2019-08-22 16:39:35');
INSERT INTO `ad_label` VALUES (10, 'hive', 0, '2019-08-22 16:43:44');
INSERT INTO `ad_label` VALUES (23858, '工具', 1, '2019-08-22 16:43:55');
INSERT INTO `ad_label` VALUES (23859, 'c', 1, '2019-08-22 16:44:01');
INSERT INTO `ad_label` VALUES (23860, '电话', 1, '2019-08-22 16:44:22');
INSERT INTO `ad_label` VALUES (23861, '照片', 1, '2019-08-22 16:44:22');
INSERT INTO `ad_label` VALUES (23862, '咨询', 1, '2019-08-22 16:44:22');
INSERT INTO `ad_label` VALUES (23863, '智能', 1, '2019-08-22 16:46:00');
INSERT INTO `ad_label` VALUES (23864, '人工智能', 1, '2019-08-22 16:46:00');
INSERT INTO `ad_label` VALUES (23865, 'AI', 1, '2019-08-22 16:46:00');
INSERT INTO `ad_label` VALUES (23866, '智能协会', 1, '2019-08-22 16:46:00');
INSERT INTO `ad_label` VALUES (23867, '人工智能协会', 1, '2019-08-22 16:46:00');
INSERT INTO `ad_label` VALUES (23868, '5G', 1, '2019-08-22 16:47:21');
INSERT INTO `ad_label` VALUES (23869, '高通', 1, '2019-08-22 16:47:21');
INSERT INTO `ad_label` VALUES (23870, '苹果', 1, '2019-08-22 16:47:21');
INSERT INTO `ad_label` VALUES (23871, '英特尔', 1, '2019-08-22 16:47:21');
INSERT INTO `ad_label` VALUES (23872, '智能手机', 1, '2019-08-22 16:47:21');
INSERT INTO `ad_label` VALUES (23873, 'google', 1, '2019-08-22 16:47:49');
INSERT INTO `ad_label` VALUES (23874, '芯片', 1, '2019-08-22 16:47:49');
INSERT INTO `ad_label` VALUES (23875, '交互', 1, '2019-08-22 16:47:49');
INSERT INTO `ad_label` VALUES (23876, '智能交互', 1, '2019-08-22 16:47:49');
INSERT INTO `ad_label` VALUES (23877, '手势交互', 1, '2019-08-22 16:47:49');
INSERT INTO `ad_label` VALUES (23878, '智慧酒店', 1, '2019-08-22 16:48:54');
INSERT INTO `ad_label` VALUES (23879, '人脸识别', 1, '2019-08-22 16:49:06');
INSERT INTO `ad_label` VALUES (23880, '软硬件开发流程', 1, '2019-08-22 16:49:26');
INSERT INTO `ad_label` VALUES (23881, '软硬件结合', 1, '2019-08-22 16:50:23');
INSERT INTO `ad_label` VALUES (23882, 'React', 1, '2019-08-22 17:18:59');
INSERT INTO `ad_label` VALUES (23883, '前端技术', 1, '2019-08-22 17:18:59');
INSERT INTO `ad_label` VALUES (23903, 'IDEA', 1, '2019-08-22 17:22:21');
INSERT INTO `ad_label` VALUES (23904, 'git', 1, '2019-08-22 17:32:54');
INSERT INTO `ad_label` VALUES (23905, 'java学习', 1, '2019-08-22 17:43:34');
INSERT INTO `ad_label` VALUES (23906, '机器学习', 1, '2019-08-22 17:46:40');
INSERT INTO `ad_label` VALUES (23907, '陆奇', 1, '2019-08-22 17:46:55');
INSERT INTO `ad_label` VALUES (23908, '设计模式', 1, '2019-08-22 17:47:40');
INSERT INTO `ad_label` VALUES (23909, '谷歌', 1, '2019-08-22 17:48:11');
INSERT INTO `ad_label` VALUES (23916, '工业数字化', 1, '2019-08-22 17:49:16');
INSERT INTO `ad_label` VALUES (23949, '个人生活', 1, '2019-08-22 17:57:38');
INSERT INTO `ad_label` VALUES (23950, '安徽', 1, '2019-08-22 17:57:38');
INSERT INTO `ad_label` VALUES (23951, '黄山', 1, '2019-08-22 17:57:38');
INSERT INTO `ad_label` VALUES (23952, 'SVN信息', 1, '2019-08-22 18:00:27');
INSERT INTO `ad_label` VALUES (23953, '清除', 1, '2019-08-22 18:00:27');
INSERT INTO `ad_label` VALUES (23954, '删除', 1, '2019-08-22 18:00:27');
INSERT INTO `ad_label` VALUES (23955, 'svn', 1, '2019-08-22 18:00:27');
INSERT INTO `ad_label` VALUES (23956, '排序', 1, '2019-08-22 18:01:27');
INSERT INTO `ad_label` VALUES (23957, '快排', 1, '2019-08-22 18:01:27');
INSERT INTO `ad_label` VALUES (23958, '归并排序', 1, '2019-08-22 18:01:27');
INSERT INTO `ad_label` VALUES (23959, '程序人生', 1, '2019-08-22 18:05:25');
INSERT INTO `ad_label` VALUES (23960, '毕业一年', 1, '2019-08-22 18:05:25');
INSERT INTO `ad_label` VALUES (23961, '毕业总结', 1, '2019-08-22 18:05:25');
INSERT INTO `ad_label` VALUES (23962, '毕业感想', 1, '2019-08-22 18:05:25');
INSERT INTO `ad_label` VALUES (23979, 'dom', 1, '2019-08-22 18:09:39');
INSERT INTO `ad_label` VALUES (23980, 'javascript', 1, '2019-08-22 18:09:39');
INSERT INTO `ad_label` VALUES (23981, 'web开发', 1, '2019-08-22 18:09:39');
INSERT INTO `ad_label` VALUES (23995, 'IT', 1, '2019-08-22 18:13:50');
INSERT INTO `ad_label` VALUES (23996, '科技', 1, '2019-08-22 18:13:50');
INSERT INTO `ad_label` VALUES (23998, '自动化', 1, '2019-08-22 18:16:20');
INSERT INTO `ad_label` VALUES (23999, '运维', 1, '2019-08-22 18:16:20');
INSERT INTO `ad_label` VALUES (24000, 'ansible', 1, '2019-08-22 18:16:20');
INSERT INTO `ad_label` VALUES (24001, '入门', 1, '2019-08-22 18:16:20');
INSERT INTO `ad_label` VALUES (24002, 'c#', 1, '2019-08-22 18:16:45');
INSERT INTO `ad_label` VALUES (24003, '正则', 1, '2019-08-22 18:16:45');
INSERT INTO `ad_label` VALUES (24004, 'regex', 1, '2019-08-22 18:16:45');
INSERT INTO `ad_label` VALUES (24005, '字符串', 1, '2019-08-22 18:16:45');
INSERT INTO `ad_label` VALUES (24015, 'openstack', 1, '2019-08-22 18:19:42');
INSERT INTO `ad_label` VALUES (24016, 'k8s', 1, '2019-08-22 18:20:47');
INSERT INTO `ad_label` VALUES (24017, 'kubernetes', 1, '2019-08-22 18:20:47');
INSERT INTO `ad_label` VALUES (24018, 'kubectl', 1, '2019-08-22 18:20:47');
INSERT INTO `ad_label` VALUES (24019, 'supervisor', 1, '2019-08-22 18:24:43');
INSERT INTO `ad_label` VALUES (24020, 'linux', 1, '2019-08-22 18:24:43');
INSERT INTO `ad_label` VALUES (24021, '进程管理', 1, '2019-08-22 18:24:43');
INSERT INTO `ad_label` VALUES (24109, '百度网盘', 1, '2019-08-22 19:14:19');
INSERT INTO `ad_label` VALUES (24110, '百度云', 1, '2019-08-22 19:14:19');
INSERT INTO `ad_label` VALUES (24111, '免费', 1, '2019-08-22 19:14:19');
INSERT INTO `ad_label` VALUES (24112, '不限速', 1, '2019-08-22 19:14:19');
INSERT INTO `ad_label` VALUES (24113, '破解', 1, '2019-08-22 19:14:19');
INSERT INTO `ad_label` VALUES (24123, '脚本', 1, '2019-08-22 19:14:26');
INSERT INTO `ad_label` VALUES (24124, '作业', 1, '2019-08-22 19:14:26');
INSERT INTO `ad_label` VALUES (24125, '自动化运维', 1, '2019-08-22 19:14:26');
INSERT INTO `ad_label` VALUES (24126, '极客头条', 1, '2019-08-22 20:34:33');
INSERT INTO `ad_label` VALUES (24198, '业界新闻', 1, '2019-08-23 07:28:27');
INSERT INTO `ad_label` VALUES (24206, '杂谈', 1, '2019-08-23 07:31:09');
INSERT INTO `ad_label` VALUES (24207, '零信任网络', 1, '2019-08-23 07:33:37');
INSERT INTO `ad_label` VALUES (24208, '网络安全', 1, '2019-08-23 07:33:37');
INSERT INTO `ad_label` VALUES (24209, 'Go语言', 1, '2019-08-23 07:33:54');
INSERT INTO `ad_label` VALUES (24210, '程序员', 1, '2019-08-23 07:33:54');
INSERT INTO `ad_label` VALUES (24223, 'Android', 1, '2019-08-23 07:35:42');
INSERT INTO `ad_label` VALUES (24224, '架构', 1, '2019-08-23 07:35:42');
INSERT INTO `ad_label` VALUES (24232, 'flume', 1, '2019-08-23 07:37:05');
INSERT INTO `ad_label` VALUES (24233, 'hive优化', 1, '2019-08-23 07:37:27');
INSERT INTO `ad_label` VALUES (24234, 'parquet', 1, '2019-08-23 07:37:27');
INSERT INTO `ad_label` VALUES (24235, 'orc', 1, '2019-08-23 07:37:27');
INSERT INTO `ad_label` VALUES (24236, 'snappy', 1, '2019-08-23 07:37:27');
-- ----------------------------
-- Table structure for ad_menu
-- ----------------------------
DROP TABLE IF EXISTS `ad_menu`;
CREATE TABLE `ad_menu` (
`id` int(11) UNSIGNED NOT NULL,
`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '菜单名称',
`code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '菜单代码',
`parent_id` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '父菜单',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '登录时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单资源信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ad_menu
-- ----------------------------
-- ----------------------------
-- Table structure for ad_recommend_strategy
-- ----------------------------
DROP TABLE IF EXISTS `ad_recommend_strategy`;
CREATE TABLE `ad_recommend_strategy` (
`id` int(5) UNSIGNED NOT NULL COMMENT '主键',
`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '策略名称',
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '策略描述',
`is_enable` tinyint(1) NULL DEFAULT NULL COMMENT '是否有效',
`group_id` int(5) UNSIGNED NULL DEFAULT NULL COMMENT '分组ID',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '推荐策略信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ad_recommend_strategy
-- ----------------------------
-- ----------------------------
-- Table structure for ad_role
-- ----------------------------
DROP TABLE IF EXISTS `ad_role`;
CREATE TABLE `ad_role` (
`id` int(11) UNSIGNED NOT NULL,
`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '角色名称',
`description` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '角色描述',
`is_enable` tinyint(1) UNSIGNED NULL DEFAULT NULL COMMENT '是否有效',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '登录时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '角色信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ad_role
-- ----------------------------
-- ----------------------------
-- Table structure for ad_role_auth
-- ----------------------------
DROP TABLE IF EXISTS `ad_role_auth`;
CREATE TABLE `ad_role_auth` (
`id` int(11) UNSIGNED NOT NULL,
`role_id` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '角色ID',
`type` tinyint(1) UNSIGNED NULL DEFAULT NULL COMMENT '资源类型\r\n 0 菜单\r\n 1 功能',
`entry_id` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '资源ID',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '登录时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '角色权限信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ad_role_auth
-- ----------------------------
-- ----------------------------
-- Table structure for ad_strategy_group
-- ----------------------------
DROP TABLE IF EXISTS `ad_strategy_group`;
CREATE TABLE `ad_strategy_group` (
`id` int(5) UNSIGNED NOT NULL COMMENT '主键',
`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '策略名称',
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '策略描述',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '推荐策略分组信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ad_strategy_group
-- ----------------------------
-- ----------------------------
-- Table structure for ad_user
-- ----------------------------
DROP TABLE IF EXISTS `ad_user`;
CREATE TABLE `ad_user` (
`id` int(11) UNSIGNED NOT NULL COMMENT '主键',
`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '登录用户名',
`password` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '登录密码',
`salt` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '盐',
`nickname` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '昵称',
`image` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '头像',
`phone` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '手机号',
`status` tinyint(11) UNSIGNED NULL DEFAULT NULL COMMENT '状态\r\n 0 暂时不可用\r\n 1 永久不可用\r\n 9 正常可用',
`email` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '邮箱',
`login_time` datetime(0) NULL DEFAULT NULL COMMENT '最后一次登录时间',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '管理员用户信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ad_user
-- ----------------------------
INSERT INTO `ad_user` VALUES (1, 'wukong', '123', NULL, 'mo', NULL, '13320325525', 1, 'wukong@qq.com', '2019-07-30 10:16:41', '2019-07-30 10:16:43');
INSERT INTO `ad_user` VALUES (2, 'admin', '5d4e1a406d4a9edbf7b4f10c2a390405', '123abc', 'ad', NULL, '13320325528', 1, 'admin@qq.com', '2020-03-04 17:07:37', '2020-03-04 17:07:40');
INSERT INTO `ad_user` VALUES (3, 'guest', '34e20b52f5bd120db806e57e27f47ed0', '123456', 'gu', NULL, '13412345676', 1, 'guest@qq.com', '2020-07-30 15:00:03', '2020-07-30 15:00:06');
-- ----------------------------
-- Table structure for ad_user_equipment
-- ----------------------------
DROP TABLE IF EXISTS `ad_user_equipment`;
CREATE TABLE `ad_user_equipment` (
`id` int(11) UNSIGNED NOT NULL,
`user_id` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '用户ID',
`type` tinyint(1) UNSIGNED NULL DEFAULT NULL COMMENT '0PC\r\n 1ANDROID\r\n 2IOS\r\n 3PAD\r\n 9 其他',
`version` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '设备版本',
`sys` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '设备系统',
`no` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '设备唯一号,MD5加密',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '登录时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '管理员设备信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ad_user_equipment
-- ----------------------------
-- ----------------------------
-- Table structure for ad_user_login
-- ----------------------------
DROP TABLE IF EXISTS `ad_user_login`;
CREATE TABLE `ad_user_login` (
`id` int(11) UNSIGNED NOT NULL,
`user_id` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '用户ID',
`equipment_id` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '登录设备ID',
`ip` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '登录IP',
`address` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '登录地址',
`longitude` decimal(5, 5) NULL DEFAULT NULL COMMENT '经度',
`latitude` decimal(5, 5) NULL DEFAULT NULL COMMENT '纬度',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '登录时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '管理员登录行为信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ad_user_login
-- ----------------------------
-- ----------------------------
-- Table structure for ad_user_opertion
-- ----------------------------
DROP TABLE IF EXISTS `ad_user_opertion`;
CREATE TABLE `ad_user_opertion` (
`id` int(11) UNSIGNED NOT NULL,
`user_id` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '用户ID',
`equipment_id` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '登录设备ID',
`ip` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '登录IP',
`address` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '登录地址',
`type` int(5) NULL DEFAULT NULL COMMENT '操作类型',
`description` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '操作描述',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '登录时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '管理员操作行为信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ad_user_opertion
-- ----------------------------
-- ----------------------------
-- Table structure for ad_user_role
-- ----------------------------
DROP TABLE IF EXISTS `ad_user_role`;
CREATE TABLE `ad_user_role` (
`id` int(11) UNSIGNED NOT NULL,
`role_id` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '角色ID',
`user_id` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '用户ID',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '登录时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '管理员角色信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ad_user_role
-- ----------------------------
-- ----------------------------
-- Table structure for ad_vistor_statistics
-- ----------------------------
DROP TABLE IF EXISTS `ad_vistor_statistics`;
CREATE TABLE `ad_vistor_statistics` (
`id` int(11) UNSIGNED NOT NULL COMMENT '主键',
`activity` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '日活',
`vistor` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '访问量',
`ip` int(11) UNSIGNED NULL DEFAULT NULL COMMENT 'IP量',
`register` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '注册量',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '访问数据统计表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ad_vistor_statistics
-- ----------------------------
SET FOREIGN_KEY_CHECKS = 1;
②从资料中拷贝AdUser类放到admin包下
package com.heima.model.admin.pojos;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 管理员用户信息表
* </p>
*
* @author itheima
*/
@Data
@TableName("ad_user")
public class AdUser implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
private Integer id;
/**
* 登录用户名
*/
@TableField("name")
private String name;
/**
* 登录密码
*/
@TableField("password")
private String password;
/**
* 盐
*/
@TableField("salt")
private String salt;
/**
* 昵称
*/
@TableField("nickname")
private String nickname;
/**
* 头像
*/
@TableField("image")
private String image;
/**
* 手机号
*/
@TableField("phone")
private String phone;
/**
* 状态
0 暂时不可用
1 永久不可用
9 正常可用
*/
@TableField("status")
private Integer status;
/**
* 邮箱
*/
@TableField("email")
private String email;
/**
* 最后一次登录时间
*/
@TableField("login_time")
private Date loginTime;
/**
* 创建时间
*/
@TableField("created_time")
private Date createdTime;
}
③在service模块下新建heima-leadnews-admin模块
④在admin模块新建如下
bootstrap.yml配置如下:
server:
port: 51809
spring:
application:
name: leadnews-admin
cloud:
nacos:
discovery:
server-addr: 192.168.200.130:8848
config:
server-addr: 192.168.200.130:8848
file-extension: yml
logback.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--定义日志文件的存储地址,使用绝对路径-->
<property name="LOG_HOME" value="e:/logs"/>
<!-- Console 输出设置 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>utf8</charset>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<fileNamePattern>${LOG_HOME}/leadnews.%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 异步输出 -->
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="FILE"/>
</appender>
<logger name="org.apache.ibatis.cache.decorators.LoggingCache" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>
<logger name="org.springframework.boot" level="debug"/>
<root level="info">
<!--<appender-ref ref="ASYNC"/>-->
<appender-ref ref="FILE"/>
<appender-ref ref="CONSOLE"/>
</root>
</configuration>
在nacos配置中心创建配置文件leadnews-admin.yml
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/leadnews_admin?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
username: root
password: 123456
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
mapper-locations: classpath*:mapper/*.xml
# 设置别名包扫描路径,通过该属性可以给包中的类注册别名
type-aliases-package: com.heima.model.admin.pojos
⑤接口定义
说明 | |
接口地址 | /login/in |
请求方式 | POST |
参数 | AdUserDto |
响应结果 | ResponseResult |
新增AdUserDto
package com.heima.model.admin.dtos;
import lombok.Data;
@Data
public class AdUserDto {
/**
* 用户名
*/
private String name;
/**
* 密码
*/
private String password;
}
⑥新建AdUserMapper
package com.heima.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.heima.model.admin.pojos.AdUser;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface AdUserMapper extends BaseMapper<AdUser> {
}
⑦新增LoginController
package com.heima.admin.controller.v1;
import com.heima.admin.service.AdUserService;
import com.heima.model.admin.dtos.AdUserDto;
import com.heima.model.common.dtos.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/login")
public class LoginController {
@Autowired
private AdUserService adUserService;
@PostMapping("/in")
public ResponseResult login(@RequestBody AdUserDto dto) {
return adUserService.login(dto);
}
}
⑧新增AdUserService
package com.heima.admin.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.heima.model.admin.dtos.AdUserDto;
import com.heima.model.admin.pojos.AdUser;
import com.heima.model.common.dtos.ResponseResult;
public interface AdUserService extends IService<AdUser> {
/**
* 登录
* @param dto
* @return
*/
public ResponseResult login(AdUserDto dto);
}
⑨新增实现类AdUserServiceImpl
package com.heima.admin.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.admin.mapper.AdUserMapper;
import com.heima.admin.service.AdUserService;
import com.heima.model.admin.dtos.AdUserDto;
import com.heima.model.admin.pojos.AdUser;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.utils.common.AppJwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import java.util.HashMap;
import java.util.Map;
@Service
@Slf4j
@Transactional
public class AdUserServiceImpl extends ServiceImpl<AdUserMapper, AdUser> implements AdUserService {
/**
* 登录
* @param dto
* @return
*/
@Override
public ResponseResult login(AdUserDto dto) {
// 1. 检查参数
if(StringUtils.isBlank(dto.getName()) || StringUtils.isBlank(dto.getPassword())) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "用户名或密码不能为空");
}
// 2. 查询用户
AdUser user = getOne(Wrappers.<AdUser>lambdaQuery().eq(AdUser::getName, dto.getName()));
if(user == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "用户不存在");
}
// 3. 比对密码
String salt = user.getSalt();
String password = dto.getPassword();
// md5加密
password = DigestUtils.md5DigestAsHex((password + salt).getBytes());
if(password.equals(user.getPassword())) {
// 4. 返回数据 - jwt
Map<String, Object> map = new HashMap<>();
map.put("token", AppJwtUtil.getToken(user.getId().longValue()));
user.setSalt("");
user.setPassword("");
map.put("user", user);
return ResponseResult.okResult(map);
} else {
// 密码错误
return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);
}
}
}
⑩新增引导类AdminApplication
package com.heima.admin;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@MapperScan("com.heima.admin.mapper")
@EnableDiscoveryClient
public class AdminApplication {
public static void main(String[] args) {
SpringApplication.run(AdminApplication.class, args);
}
}
2. 网关
步骤①:创建模块heima-leadnews-admin-gateway
②在heima-leadnews-admin-gateway的resources文件夹下新增bootstrap.yml
server:
port: 51603
spring:
application:
name: leadnews-admin-gateway
cloud:
nacos:
discovery:
server-addr: 192.168.200.130:8848
config:
server-addr: 192.168.200.130:8848
file-extension: yml
③新增引导类AdminGatewayApplication
package com.heima.admin.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class AdminGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(AdminGatewayApplication.class, args);
}
}
④在nacos配置中心添加leadnews-admin-gateway.yml
spring:
cloud:
gateway:
globalcors:
add-to-simple-url-handler-mapping: true
corsConfigurations:
'[/**]':
allowedHeaders: "*"
allowedOrigins: "*"
allowedMethods:
- GET
- POST
- DELETE
- PUT
- OPTION
routes:
# 平台管理微服务
- id: admin
uri: lb://leadnews-admin
predicates:
- Path=/admin/**
filters:
- StripPrefix= 1
# 用户微服务
- id: user
uri: lb://leadnews-user
predicates:
- Path=/user/**
filters:
- StripPrefix= 1
# 文章微服务
- id: article
uri: lb://leadnews-article
predicates:
- Path=/article/**
filters:
- StripPrefix= 1
# 频道微服务
- id: wemedia
uri: lb://leadnews-wemedia
predicates:
- Path=/wemedia/**
filters:
- StripPrefix= 1
# 敏感词微服务
- id: sensitive
uri: lb://leadnews-sensitive
predicates:
- Path=/sensitive/**
filters:
- StripPrefix= 1
#搜索微服务
- id: leadnews-search
uri: lb://leadnews-search
predicates:
- Path=/search/**
filters:
- StripPrefix= 1
⑤拷贝一份jwt解析工具类到AppJwtUtil到admin-gateway模块下
package com.heima.admin.gateway.util;
import io.jsonwebtoken.*;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.*;
public class AppJwtUtil {
// TOKEN的有效期一天(S)
private static final int TOKEN_TIME_OUT = 3_600;
// 加密KEY
private static final String TOKEN_ENCRY_KEY = "MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY";
// 最小刷新间隔(S)
private static final int REFRESH_TIME = 300;
// 生产ID
public static String getToken(Long id){
Map<String, Object> claimMaps = new HashMap<>();
claimMaps.put("id",id);
long currentTime = System.currentTimeMillis();
return Jwts.builder()
.setId(UUID.randomUUID().toString())
.setIssuedAt(new Date(currentTime)) //签发时间
.setSubject("system") //说明
.setIssuer("heima") //签发者信息
.setAudience("app") //接收用户
.compressWith(CompressionCodecs.GZIP) //数据压缩方式
.signWith(SignatureAlgorithm.HS512, generalKey()) //加密方式
.setExpiration(new Date(currentTime + TOKEN_TIME_OUT * 1000)) //过期时间戳
.addClaims(claimMaps) //cla信息
.compact();
}
/**
* 获取token中的claims信息
*
* @param token
* @return
*/
private static Jws<Claims> getJws(String token) {
return Jwts.parser()
.setSigningKey(generalKey())
.parseClaimsJws(token);
}
/**
* 获取payload body信息
*
* @param token
* @return
*/
public static Claims getClaimsBody(String token) {
try {
return getJws(token).getBody();
}catch (ExpiredJwtException e){
return null;
}
}
/**
* 获取hearder body信息
*
* @param token
* @return
*/
public static JwsHeader getHeaderBody(String token) {
return getJws(token).getHeader();
}
/**
* 是否过期
*
* @param claims
* @return -1:有效,0:有效,1:过期,2:过期
*/
public static int verifyToken(Claims claims) {
if(claims==null){
return 1;
}
try {
claims.getExpiration()
.before(new Date());
// 需要自动刷新TOKEN
if((claims.getExpiration().getTime()-System.currentTimeMillis())>REFRESH_TIME*1000){
return -1;
}else {
return 0;
}
} catch (ExpiredJwtException ex) {
return 1;
}catch (Exception e){
return 2;
}
}
/**
* 由字符串生成加密key
*
* @return
*/
public static SecretKey generalKey() {
byte[] encodedKey = Base64.getEncoder().encode(TOKEN_ENCRY_KEY.getBytes());
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
public static void main(String[] args) {
/* Map map = new HashMap();
map.put("id","11");*/
System.out.println(AppJwtUtil.getToken(1102L));
Jws<Claims> jws = AppJwtUtil.getJws("eyJhbGciOiJIUzUxMiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAAADWLQQqEMAwA_5KzhURNt_qb1KZYQSi0wi6Lf9942NsMw3zh6AVW2DYmDGl2WabkZgreCaM6VXzhFBfJMcMARTqsxIG9Z888QLui3e3Tup5Pb81013KKmVzJTGo11nf9n8v4nMUaEY73DzTabjmDAAAA.4SuqQ42IGqCgBai6qd4RaVpVxTlZIWC826QA9kLvt9d-yVUw82gU47HDaSfOzgAcloZedYNNpUcd18Ne8vvjQA");
Claims claims = jws.getBody();
System.out.println(claims.get("id"));
}
}
⑥在admin网关微服务中新建全局过滤器
package com.heima.admin.gateway.filter;
import com.heima.admin.gateway.util.AppJwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
@Slf4j
public class AuthorizeFilter implements Ordered, GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1. 获取request和response对象
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
// 2. 判断是否是登录
if(request.getURI().getPath().contains("/login")) {
// 放行
return chain.filter(exchange);
}
// 3. 获取token
String token = request.getHeaders().getFirst("token");
// 4. 判断token是否存在
if(StringUtils.isBlank(token)) {
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
// 5. 判断token是否有效
try {
Claims claimsBody = AppJwtUtil.getClaimsBody(token);
// 判断token是否过期
int result = AppJwtUtil.verifyToken(claimsBody);
if (result == 1 || result == 2) {
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
// 获取token解析后的用户信息
Object userId = claimsBody.get("id");
// 存入header中
ServerHttpRequest serverHttpRequest = request.mutate().headers(httpHeaders -> {
httpHeaders.add("userId", userId + "");
}).build();
// 重置请求
exchange.mutate().request(serverHttpRequest);
} catch (Exception e) {
e.printStackTrace();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
// 6. 放行
return chain.filter(exchange);
}
/**
* 优先级设置:值越小,优先级越高
* @return
*/
@Override
public int getOrder() {
return 0;
}
}
⑦启动AdminGatewayApplication和AdminApplication进行测试
三、频道管理
1. 新增频道
(1)需求分析
- 前台输入内容进行频道的保存
- 频道名称不能重复
(2)接口定义
说明 | |
接口地址 | /api/v1/channel/save |
请求方式 | POST |
参数 | WmChannel |
响应结果 | ResponseResult |
(3)实现步骤
wemedia模块
步骤①:新增接口 - WmChannelController
/**
* 新增频道
* @param adChannel
* @return
*/
@PostMapping("/save")
public ResponseResult insert(@RequestBody WmChannel adChannel) {
return wmChannelService.insert(adChannel);
}
②业务层 - WmChannelService
/**
* 新增保存频道
* @param adChannel
* @return
*/
ResponseResult insert(WmChannel adChannel);
③实现类 - WmChannelServiceImpl
/**
* 新增保存频道
* @param adChannel
* @return
*/
@Override
public ResponseResult insert(WmChannel adChannel) {
// 1. 检查参数
if(adChannel == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
// 检查是否存在频道名称相同的情况
WmChannel channel = getOne(Wrappers.<WmChannel>lambdaQuery().eq(WmChannel::getName, adChannel.getName()));
if(channel != null) {
return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST, "频道已存在");
}
// 2. 保存频道
adChannel.setCreatedTime(new Date());
save(adChannel);
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
2. 查询频道列表
(1)需求分析
- 查询需要按照创建时间倒序查询
- 按照频道名称模糊查询
- 可以按照状态进行精确查找(1:启用 true 0:禁用 false)
- 分页查询
(2)接口定义
说明 | |
接口地址 | /api/v1/channel/list |
请求方式 | POST |
参数 | ChannelDto |
响应结果 | ResponseResult |
(3)实现步骤
步骤①:新增实体类ChannelDto
package com.heima.model.wemedia.dtos;
import com.heima.model.common.dtos.PageRequestDto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ChannelDto extends PageRequestDto {
/**
* 频道名称
*/
@ApiModelProperty(value = "频道名称")
private String name;
}
②WmChannelController中新增接口
/**
* 根据频道名称模糊分页查询
* @param dto
* @return
*/
@PostMapping("/list")
public ResponseResult findByNameAndPage(@RequestBody ChannelDto dto) {
return wmChannelService.findByNameAndPage(dto);
}
③WmChannelService
/**
* 根据频道名称模糊分页查询
* @param dto
* @return
*/
ResponseResult findByNameAndPage(ChannelDto dto);
④WmChannelServiceImpl
/**
* 根据频道名称模糊分页查询
* @param dto
* @return
*/
@Override
public ResponseResult findByNameAndPage(ChannelDto dto) {
// 1. 检查参数
if(dto == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
// 2. 检查分页
dto.checkParam();
// 3. 模糊查询 + 分页
IPage page = new Page(dto.getPage(), dto.getSize());
// 频道名称模糊查询
LambdaQueryWrapper<WmChannel> lambdaQueryWrapper = new LambdaQueryWrapper<>();
if(StringUtils.isNotBlank(dto.getName())) {
lambdaQueryWrapper.like(WmChannel::getName, dto.getName());
}
page = page(page, lambdaQueryWrapper);
// 4. 结果返回
ResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int)page.getTotal());
responseResult.setData(page.getRecords());
return responseResult;
}
⑤启动以下服务进行测试
3. 修改频道
(1)需求分析
- 点击编辑后可以修改频道
- 如果频道被引用则不能禁用
(2)接口定义
说明 | |
接口地址 | /api/v1/channel/update |
请求方式 | POST |
参数 | WmChannel |
响应结果 | ResponseResult |
(3)实现步骤
步骤①:WmChannelController新增接口
/**
* 修改频道信息
* @param adChannel
* @return
*/
@PostMapping("/update")
public ResponseResult update(@RequestBody WmChannel adChannel) {
return wmChannelService.update(adChannel);
}
②WmChannelService新增业务
/**
* 修改频道信息
* @param adChannel
* @return
*/
ResponseResult update(WmChannel adChannel);
③WmChannelServiceImpl实现业务方法
/**
* 修改频道信息
* @param adChannel
* @return
*/
@Override
public ResponseResult update(WmChannel adChannel) {
// 1. 检查参数
if(adChannel == null || adChannel.getId() == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
// 2. 判断频道是否被已发布的文章引用
int count = wmNewsService.count(Wrappers
.<WmNews>lambdaQuery()
.eq(WmNews::getChannelId, adChannel.getId())
.eq(WmNews::getStatus, WmNews.Status.PUBLISHED.getCode()));
if(count > 0) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "频道被引用不能修改或禁用");
}
// 3. 修改
updateById(adChannel);
// 4. 返回结果
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
④测试
4. 删除频道
(1)需求分析
- 只有禁用的频道才能被删除
(2)接口定义
说明 | |
接口地址 | /api/v1/channel/del/{id} |
请求方式 | GET |
参数 | 频道id |
响应结果 | ResponseResult |
(3)实现步骤
步骤①:新增接口 - WmChannelController
/**
* 删除频道
* @param id
* @return
*/
@GetMapping("del/{id}")
public ResponseResult delete(@PathVariable("id") Integer id) {
return wmChannelService.delete(id);
}
②新增业务方法 - WmChannelService
/**
* 删除频道
* @param id
* @return
*/
ResponseResult delete(Integer id);
③实现 - WmChannelServiceImpl
/**
* 删除频道
* @param id
* @return
*/
@Override
public ResponseResult delete(Integer id) {
// 1. 检查参数
if(id == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
// 2. 查询频道
WmChannel wmChannel = getById(id);
if(wmChannel == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
}
// 3. 频道是否有效 -> 启动
if(wmChannel.getStatus()) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "频道有效,不能删除");
}
// 4. 判断频道是否被已发表的文章引用
int count = wmNewsService.count(Wrappers
.<WmNews>lambdaQuery()
.eq(WmNews::getChannelId, wmChannel.getId())
.eq(WmNews::getStatus, WmNews.Status.PUBLISHED.getCode()));
if(count > 0) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "频道被引用,不能删除");
}
// 5. 删除频道
removeById(id);
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
④测试
四、敏感词管理
1. 新增敏感词
(1)需求分析
- 弹出的输入框,输入敏感词可直接保存
- 已存在的敏感词则不能保存
(2)接口定义
说明 | |
接口地址 | /api/v1/sensitive/save |
请求方式 | POST |
参数 | WmSensitive |
响应结果 | ResponseResult |
(3)实现步骤
步骤①:在model模块的wemedia模块新增SentitiveDto
package com.heima.model.wemedia.dtos;
import com.heima.model.common.dtos.PageRequestDto;
import lombok.Data;
@Data
public class SensitiveDto extends PageRequestDto {
/**
* 敏感词名称
*/
private String name;
}
②wemedia模块mapper下新增WmSensitiveMapper
package com.heima.wemedia.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.heima.model.wemedia.pojos.WmSensitive;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface WmSensitiveMapper extends BaseMapper<WmSensitive> {
}
③WmSensitiveController
package com.heima.wemedia.controller.v1;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.wemedia.service.WmSensitiveService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/v1/sensitive")
public class WmSensitiveController {
@Autowired
private WmSensitiveService wmSensitiveService;
/**
* 新增敏感词
* @param wmSensitive
* @return
*/
@PostMapping("/save")
public ResponseResult insert(@RequestBody WmSensitive wmSensitive) {
return wmSensitiveService.insert(wmSensitive);
}
}
④WmSensitiveService
package com.heima.wemedia.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmSensitive;
public interface WmSensitiveService extends IService<WmSensitive> {
/**
* 新增敏感词
* @param wmSensitive
* @return
*/
ResponseResult insert(WmSensitive wmSensitive);
}
⑤WmSensitiveServiceImpl
package com.heima.wemedia.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import com.heima.wemedia.service.WmSensitiveService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
@Service
@Slf4j
@Transactional
public class WmSensitiveServiceImpl extends ServiceImpl<WmSensitiveMapper, WmSensitive> implements WmSensitiveService {
/**
* 新增敏感词
* @param wmSensitive
* @return
*/
@Override
public ResponseResult insert(WmSensitive wmSensitive) {
// 1. 检查参数
if(wmSensitive == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
// 2. 已存在的敏感词,不能保存
WmSensitive sensitive = getOne(Wrappers
.<WmSensitive>lambdaQuery()
.eq(WmSensitive::getSensitives, wmSensitive.getSensitives()));
if(sensitive != null) {
return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST, "敏感词已存在");
}
// 3. 保存敏感词
wmSensitive.setCreatedTime(new Date());
save(wmSensitive);
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
}
⑥测试
2. 查询敏感词列表
(1)需求分析
- 查询需要按照创建时间倒序查询
- 按照敏感词名称模糊查询
- 分页查询
(2)接口定义
说明 | |
接口地址 | /api/v1/sensitive/list |
请求方式 | POST |
参数 | SensitiveDto |
响应结果 | ResponseResult |
(3)实现步骤
步骤①:在WmSensitiveController新增接口
/**
* 查询敏感词列表
* @param dto
* @return
*/
@PostMapping("/list")
public ResponseResult list(@RequestBody SensitiveDto dto) {
return wmSensitiveService.list(dto);
}
②WmSensitiveService新增业务方法
/**
* 查询敏感词列表
* @param dto
* @return
*/
ResponseResult list( SensitiveDto dto);
③WmSenstiveServiceImpl实现业务方法
/**
* 查询敏感词列表
* @param dto
* @return
*/
@Override
public ResponseResult list(SensitiveDto dto) {
// 1. 检查参数
if(dto == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
// 2. 检查分页
dto.checkParam();
// 3. 模糊查询 + 分页
IPage page = new Page(dto.getPage(), dto.getSize());
LambdaQueryWrapper<WmSensitive> lambdaQueryWrapper = new LambdaQueryWrapper<>();
if(StringUtils.isNotBlank(dto.getName())) {
lambdaQueryWrapper.like(WmSensitive::getSensitives, dto.getName());
}
page = page(page, lambdaQueryWrapper);
// 4. 结果返回
ResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int)page.getTotal());
responseResult.setData(page.getRecords());
return responseResult;
}
④启动ScheduleApplication、AdminApplication、AdminGatewayApplication、WemediaGatewayApplication、WemediaApplication进行测试
3. 修改敏感词
(1)需求分析
(2)接口定义
说明 | |
接口地址 | /api/v1/sensitive/update |
请求方式 | POST |
参数 | WmSensitive |
响应结果 | ResponseResult |
(3)实现步骤
步骤①:WmSensitiveController
/**
* 修改敏感词信息
* @param wmSensitive
* @return
*/
@PostMapping("/update")
public ResponseResult update(@RequestBody WmSensitive wmSensitive) {
return wmSensitiveService.update(wmSensitive);
}
②WmSensitiveService
/**
* 修改名称信息
* @param wmSensitive
* @return
*/
ResponseResult update(WmSensitive wmSensitive);
③WmSensitiveServiceImpl
/**
* 修改敏感词信息
* @param wmSensitive
* @return
*/
@Override
public ResponseResult update(WmSensitive wmSensitive) {
// 1. 检查参数
if(wmSensitive == null || wmSensitive.getId() == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
// 2. 根据id查询敏感词信息
WmSensitive sensitive = getById(wmSensitive);
if(sensitive == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
}
// 3. 修改敏感词信息
updateById(wmSensitive);
// 4. 结果返回
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
④测试
4. 删除敏感词
(1)需求分析
- 直接根据敏感词id删除即可
(2)接口定义
说明 | |
接口地址 | /api/v1/sensitive/del{id} |
请求方式 | DELETE |
参数 | 敏感词id |
响应结果 | ResponseResult |
(3)实现步骤
步骤①:WmSensitiveController
/**
* 删除敏感词
* @param id
* @return
*/
@DeleteMapping("del/{id}")
public ResponseResult delete(@PathVariable("id") Integer id) {
return wmSensitiveService.delete(id);
}
②WmSensitiveService
/**
* 删除敏感词
* @param id
* @return
*/
ResponseResult delete(Integer id);
③WmSensitiveImpl
/**
* 删除敏感词
* @param id
* @return
*/
@Override
public ResponseResult delete(Integer id) {
// 1. 检查参数
if(id == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
// 2. 查询敏感词
WmSensitive wmSensitive = getById(id);
if(wmSensitive == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
}
// 3. 删除
removeById(id);
// 4. 结果返回
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
④测试
五、用户认证审核
- 在app端的个人中心用户可以实名认证,需要材料为:姓名、身份证号、身份证正面照、身份证反面照、手持照片、活体照片(通过微笑、眨眼、张嘴、摇头、点头等组合动作,确保操作的为真实活体人脸),当用户提交审核后就到了后端让运营人员进行审核
- 平台运营端查看用户认证信息,进行审核,其中审核包括了用户身份审核,需要对接公安系统校验身份证信息
- 用户通过审核后需要开通自媒体账号(该账户的用户名和密码与app端一致)
1. 分页查询认证查询列表
(1)需求分析
- 可根据审核状态条件查询
- 需要分页查询
(2)接口设计
说明 | |
接口地址 | /api/v1/auth/list |
请求方式 | POST |
参数 | AuthDto |
响应结果 | ResponseResult |
(3)实现步骤
步骤①:在leadnews-user模块新增Mapper - ApUserRealnameMapper
package com.heima.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.heima.model.user.pojos.ApUserRealname;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ApUserRealnameMapper extends BaseMapper<ApUserRealname> {
}
②在model模块的user模块下新增AuthDto实体类
package com.heima.model.user.dtos;
import com.heima.model.common.dtos.PageRequestDto;
import lombok.Data;
@Data
public class AuthDto extends PageRequestDto {
/**
* 状态
*/
private Short status;
private Integer id;
//驳回的信息
private String msg;
}
③在model模块的user模块下新增ApUserRealname实体类
package com.heima.model.user.pojos;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* APP实名认证信息表
* </p>
*
* @author itheima
*/
@Data
@TableName("ap_user_realname")
public class ApUserRealname implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 账号ID
*/
@TableField("user_id")
private Integer userId;
/**
* 用户名称
*/
@TableField("name")
private String name;
/**
* 资源名称
*/
@TableField("idno")
private String idno;
/**
* 正面照片
*/
@TableField("font_image")
private String fontImage;
/**
* 背面照片
*/
@TableField("back_image")
private String backImage;
/**
* 手持照片
*/
@TableField("hold_image")
private String holdImage;
/**
* 活体照片
*/
@TableField("live_image")
private String liveImage;
/**
* 状态
0 创建中
1 待审核
2 审核失败
9 审核通过
*/
@TableField("status")
private Short status;
/**
* 拒绝原因
*/
@TableField("reason")
private String reason;
/**
* 创建时间
*/
@TableField("created_time")
private Date createdTime;
/**
* 提交时间
*/
@TableField("submited_time")
private Date submitedTime;
/**
* 更新时间
*/
@TableField("updated_time")
private Date updatedTime;
}
④在leadnews-user模块下新增ApUserRealnameController
package com.heima.user.controller.v1;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.user.dtos.AuthDto;
import com.heima.user.service.ApUserRealnameService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/v1/auth")
public class ApUserRealnameController {
@Autowired
private ApUserRealnameService apUserRealnameService;
/**
* 查询用户列表
* @param dto
* @return
*/
@PostMapping("/list")
public ResponseResult list(@RequestBody AuthDto dto) {
return apUserRealnameService.list(dto);
}
}
⑤ApUserRealnameService
package com.heima.user.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.user.dtos.AuthDto;
import com.heima.model.user.pojos.ApUserRealname;
public interface ApUserRealnameService extends IService<ApUserRealname> {
/**
* 分页查询认证列表
* @param dto
* @return
*/
ResponseResult list(AuthDto dto);
}
⑥ApUserRealnameServiceImpl
package com.heima.user.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.dtos.AuthDto;
import com.heima.model.user.pojos.ApUserRealname;
import com.heima.user.mapper.ApUserRealnameMapper;
import com.heima.user.service.ApUserRealnameService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Slf4j
@Transactional
public class ApUserRealnameServiceImpl extends ServiceImpl<ApUserRealnameMapper, ApUserRealname> implements ApUserRealnameService {
/**
* 分页查询认证列表
* @param dto
* @return
*/
@Override
public ResponseResult list(AuthDto dto) {
// 1. 检查参数
if(dto == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
// 2. 分页条件查询
dto.checkParam();
// 3. 分页根据状态精确查询
IPage page = new Page(dto.getPage(), dto.getSize());
LambdaQueryWrapper<ApUserRealname> lambdaQueryWrapper = new LambdaQueryWrapper<>();
if (dto.getStatus() != null) {
lambdaQueryWrapper.eq(ApUserRealname::getStatus, dto.getStatus());
}
page = page(page, lambdaQueryWrapper);
// 4. 结果返回
ResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int)page.getTotal());
responseResult.setData(page.getRecords());
return responseResult;
}
}
⑦测试
2. 审核失败
(1)需求分析
- 审核不通过,拒绝注册为自媒体用户
(2)接口设计
说明 | |
接口地址 | /api/v1/auth/authFail |
请求方式 | POST |
参数 | AuthDto |
响应结果 | ResponseResult |
(3)实现步骤
步骤①:在common模块新增常量类 UserConstants
package com.heima.common.constants;
public class UserConstants {
public static final Short PASS_AUTH = 9;
public static final Short FAIL_AUTH = 2;
public static final Integer AUTH_TYPE = 2;
}
②ApUserRealnameController
/**
* 审核不通过
* @param dto
* @return
*/
@PostMapping("/authFail")
public ResponseResult authFail(@RequestBody AuthDto dto) {
return apUserRealnameService.updateByStatus(dto, UserConstants.FAIL_AUTH);
}
③ApUserRealnameService
/**
* 根据审核状态更新审核结果
* @param dto
* @param status 2审核失败 9审核成功
* @return
*/
ResponseResult updateByStatus(AuthDto dto, Short status);
④ApUserRealnameServiceImpl
/**
* 根据状态更新审核结果
* @param dto
* @param status 2审核失败 9审核成功
* @return
*/
@Override
public ResponseResult updateByStatus(AuthDto dto, Short status) {
// 1. 检查参数
if(dto == null || dto.getId() == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
// 2. 修改认证状态
ApUserRealname apUserRealname = new ApUserRealname();
apUserRealname.setId(dto.getId());
apUserRealname.setStatus(status);
apUserRealname.setUpdatedTime(new Date());
if(StringUtils.isNotBlank(dto.getMsg())) {
// 审核不通过原因
apUserRealname.setReason(dto.getMsg());
}
updateById(apUserRealname);
// 3. 如果审核状态为成功->9,需要创建自媒体账户
if(status.equals(UserConstants.PASS_AUTH)) {
// 通过审核
ResponseResult responseResult = createWmUserAndAuthor(dto);
if(responseResult != null) {
return responseResult;
}
}
// 4. 返回结果
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
/**
* 创建自媒体账户
* @param dto
* @return
*/
private ResponseResult createWmUserAndAuthor(AuthDto dto) {
Integer userRealnameId = dto.getId();
// 1. 查询用户认证信息
ApUserRealname apUserRealname = getById(userRealnameId);
if(apUserRealname == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
}
// 2. 查询app端用户信息
Integer userId = apUserRealname.getUserId();
ApUser apUser = apUserMapper.selectById(userId);
if(apUser == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
}
// 3. 创建自媒体用户
WmUser wmUser =wemediaClient.findWmUserByName(apUser.getName());
if(wmUser == null) {
wmUser = new WmUser();
wmUser.setApUserId(apUser.getId());
wmUser.setCreatedTime(new Date());
wmUser.setName(apUser.getName());
wmUser.setPassword(apUser.getPassword());
wmUser.setSalt(apUser.getSalt());
wmUser.setPhone(apUser.getPhone());
wmUser.setStatus(9);
wemediaClient.saveWmUser(wmUser);
}
apUser.setFlag((short) 1);
apUserMapper.updateById(apUser);
return null;
}
⑤在heima-leadnews-feign-api添加远程调用接口 - IWemediaClient
package com.heima.apis.wemedia;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmUser;
import org.springframework.cloud.openfeign.FeignClient;
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.RequestBody;
@FeignClient("leadnews-wemedia")
public interface IWemediaClient {
@GetMapping("/api/v1/user/findByName/{name}")
WmUser findWmUserByName(@PathVariable("name") String name);
@PostMapping("/api/v1/wm_user/save")
ResponseResult saveWmUser(@RequestBody WmUser wmUser);
@GetMapping("/api/v1/channel/list")
public ResponseResult getChannels();
}
⑥在heima-leadnews-wemedia新增feign包,新增WemediaClient类
package com.heima.wemedia.feign;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.apis.wemedia.IWemediaClient;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.wemedia.service.WmChannelService;
import com.heima.wemedia.service.WmUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
public class WemediaClient implements IWemediaClient {
@Autowired
private WmUserService wmUserService;
@Override
@GetMapping("/api/v1/user/findByName/{name}")
public WmUser findWmUserByName(@PathVariable("name") String name) {
return wmUserService.getOne(Wrappers.<WmUser>lambdaQuery().eq(WmUser::getName, name));
}
@Override
@PostMapping("/api/v1/wm_user/save")
public ResponseResult saveWmUser(@RequestBody WmUser wmUser) {
wmUserService.save(wmUser);
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
@Autowired
private WmChannelService wmChannelService;
@GetMapping("/api/v1/channel/list")
@Override
public ResponseResult getChannels() {
return wmChannelService.findAll();
}
}
⑦在user模块开启远程调用
package com.heima.user;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.heima.user.mapper")
@EnableFeignClients(basePackages = "com.heima.apis")
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
3. 审核成功
(1)需求分析
- 实名认证通过后,为用户新建自媒体用户账户
(2)接口设计
说明 | |
接口地址 | /api/v1/auth/authPass |
请求方式 | POST |
参数 | AuthDto |
响应结果 | ResponseResult |
(3)实现步骤
①ApUserRealnameController
/**
* 审核成功
* @param dto
* @return
*/
@PostMapping("/authPass")
public ResponseResult authPass(@RequestBody AuthDto dto) {
return apUserRealnameService.updateByStatus(dto, UserConstants.PASS_AUTH);
}
②重启服务进行测试
ap_user_realname表
wm_user表
六、自媒体文章人工审核
自媒体文章如果没有自动审核成功,而是到了人工审核(自媒体文章状态为3),需要在admin端人工处理文章的审核:
- 平台管理员可以查看待人工审核的文章信息,如果存在违规内容则驳回(状态修改为2,文章审核失败)
- 平台管理员可以查看待人工审核的文章信息,如果不存在违规,则需要创建app端的文章信息,并更新自媒体文章的状态
- 也可以通过点击查看按钮,查看文章详细信息,查看详情后可以根据内容判断是否需要通过审核
1. 查询文章列表
1)需求分析
- 分页查询自媒体文章
- 可以按照标题模糊查询
- 可以按照审核状态ji进行精确检索
- 文章查询按照创建时间倒序查询
- 注意:需要展示作者名称
(2)接口设计
说明 | |
接口地址 | /api/v1/news/list_vo |
请求方式 | POST |
参数 | NewsAuthDto |
响应结果 | ResponseResult |
(3)实现步骤
步骤①:在model模块下的wemedia新增实体类WmNewsVo
package com.heima.model.wemedia.vo;
import com.heima.model.wemedia.pojos.WmNews;
import lombok.Data;
@Data
public class WmNewsVo extends WmNews {
/**
* 作者名称
*/
private String authorName;
}
②在heima-leadnews-wemedia模块新增WmNewsMapper
package com.heima.wemedia.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.heima.model.wemedia.dtos.NewsAuthDto;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.vo.WmNewsVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface WmNewsMapper extends BaseMapper<WmNews> {
List<WmNewsVo> findListAndPage(@Param("dto") NewsAuthDto dto);
int findListCount(@Param("dto") NewsAuthDto dto);
}
③在resources/mapper下新建对应的映射文件 - WmNewsMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.heima.wemedia.mapper.WmNewsMapper">
<select id="findListAndPage" parameterType="com.heima.model.wemedia.dtos.NewsAuthDto"
resultType="com.heima.model.wemedia.vo.WmNewsVo">
SELECT
wn.*,wu.`name` authorName
FROM
wm_news wn
LEFT JOIN
wm_user wu
ON wn.user_id = wu.id
<where>
<if test="dto.title!=null and dto.title!=''">
and wn.title like concat('%',#{dto.title},'%')
</if>
<if test="dto.status!=null">
and wn.status = #{dto.status}
</if>
</where>
limit #{dto.page},#{dto.size}
</select>
<select id="findListCount" parameterType="com.heima.model.wemedia.dtos.NewsAuthDto"
resultType="int">
SELECT
count(1)
FROM
wm_news wn
LEFT JOIN
wm_user wu
ON wn.user_id = wu.id
<where>
<if test="dto.title!=null and dto.title!=''">
and wn.title like concat('%',#{dto.title},'%')
</if>
<if test="dto.status!=null">
and wn.status = #{dto.status}
</if>
</where>
</select>
</mapper>
④WmNewsController新增接口
/**
* 查询(待审核)文章列表
* @param dto
* @return
*/
@PostMapping("/list_vo")
public ResponseResult findList(@RequestBody NewsAuthDto dto) {
return wmNewsService.findList(dto);
}
⑤WmNewsService新增业务方法
/**
* 查询文章列表
* @param dto
* @return
*/
ResponseResult findList(NewsAuthDto dto);
⑥WmNewsServiceImpl实现业务方法
@Autowired
private WmNewsMapper wmNewsMapper;
/**
* 查询(待审核)文章列表
* @param dto
* @return
*/
@Override
public ResponseResult findList(NewsAuthDto dto) {
// 1. 参数检查
dto.checkParam();
// 2. 记录当前页
int currentPage = dto.getPage();
// 3. 分页查询 + count查询
dto.setPage((dto.getPage() - 1) * dto.getSize());
List<WmNewsVo> wmNewsVoList = wmNewsMapper.findListAndPage(dto);
int count = wmNewsMapper.findListCount(dto);
// 4. 结果返回
ResponseResult responseResult = new PageResponseResult(currentPage, dto.getSize(), count);
responseResult.setData(wmNewsVoList);
return responseResult;
}
⑦测试
2. 查询文章详情
1)需求分析
- 可以查看文章详细内容
- 注意:需要展示作者名称
(2)接口设计
说明 | |
接口地址 | /api/v1/news/one_vo/{id} |
请求方式 | GET |
参数 | 文章id |
响应结果 | ResponseResult |
(3)实现步骤
步骤①:WmNewsController
/**
* 查看文章详情
* @param id
* @return
*/
@GetMapping("/one_vo/{id}")
public ResponseResult findWmNewsVo(@PathVariable("id") Integer id) {
return wmNewsService.findWmNewsVo(id);
}
②WmNewsService
/**
* 查看文章详情
* @param id
* @return
*/
ResponseResult findWmNewsVo(Integer id);
③WmNewsServiceImpl
@Autowired
private WmUserMapper wmUserMapper;
/**
* 查看文章详情
* @param id
* @return
*/
@Override
public ResponseResult findWmNewsVo(Integer id) {
// 1. 检查参数
if(id == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
// 2. 查询文章信息
WmNews wmNews = getById(id);
if(wmNews == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
}
// 3. 查询用户信息
WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
// 4. 封装vo返回
WmNewsVo vo = new WmNewsVo();
// 属性拷贝
BeanUtils.copyProperties(wmNews, vo);
if(wmUser != null) {
vo.setAuthorName(wmUser.getName());
}
// 5. 结果返回
ResponseResult responseResult = new ResponseResult<>().ok(vo);
return responseResult;
}
⑦测试
3. 审核失败
1)需求分析
- 拒绝以后需要给出原因,并修改文章的状态为2
(2)接口设计
说明 | |
接口地址 | /api/v1/news/auth_fail |
请求方式 | POST |
参数 | NewsAuthDto |
响应结果 | ResponseResult |
(3)实现步骤
步骤①:在WemediaConstants添加两个常量
public static final Short WM_NEWS_AUTH_PASS = 4;
public static final Short WM_NEWS_AUTH_FAIL = 2;
②WmNewsController
/**
* 审核失败
* @param dto
* @return
*/
@PostMapping("/auth_fail")
public ResponseResult authFail(@RequestBody NewsAuthDto dto) {
return wmNewsService.updateByStatus(WemediaConstants.WM_NEWS_AUTH_FAIL, dto);
}
③WmNewsService
/**
* 文章审核,修改状态
* @param status 2审核失败 4审核成功
* @param dto
* @return
*/
ResponseResult updateByStatus(Short status, NewsAuthDto dto);
④WmNewsServiceImpl
@Override
public ResponseResult updateByStatus(Short status, NewsAuthDto dto) {
// 1. 检查参数
if(dto == null || dto.getId() == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
// 2. 查询文章信息
WmNews wmNews = getById(dto.getId());
if(wmNews == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
}
// 3. 修改文章的状态
wmNews.setStatus(status);
if(StringUtils.isNotBlank(dto.getMsg())) {
wmNews.setReason(dto.getMsg());
}
updateById(wmNews);
// 4. 审核成功,则要创建app端文章数据,并修改自媒体文章
if(status.equals(WemediaConstants.WM_NEWS_AUTH_PASS)) {
// 创建app端文章数据
ResponseResult responseResult = wmNewsAutoScanService.saveAppArticle(wmNews);
if(responseResult.getCode().equals(200)) {
wmNews.setArticleId((Long) responseResult.getData());
wmNews.setStatus(WmNews.Status.PUBLISHED.getCode());
updateById(wmNews);
}
}
// 5. 结果返回
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
⑤WmNewsAutoScanService
/**
* 保存app端文章数据
* @param wmNews
* @return
*/
ResponseResult saveAppArticle(WmNews wmNews);
⑥测试
4. 审核成功
1)需求分析
- 需要创建app端的文章信息,并更新自媒体文章的状态
(2)接口设计
说明 | |
接口地址 | /api/v1/news/auth_pass |
请求方式 | POST |
参数 | NewsAuthDto |
响应结果 | ResponseResult |
(3)实现步骤
①WmNewsController
/**
* 审核成功
* @param dto
* @return
*/
@PostMapping("/auth_pass")
public ResponseResult authPass(@RequestBody NewsAuthDto dto) {
return wmNewsService.updateByStatus(WemediaConstants.WM_NEWS_AUTH_PASS, dto);
}
②测试
可能有不对或遗漏的地方,多多谅解!!!