系统展示
主页
登录页面
登录成功之后
发布博客
发布成功
点击编辑还可以对自己的文章进行编辑
前端核心代码
主页
1. <template> 2. <div class="mcontaner"> 3. <Header></Header> 4. 5. <div class="block"> 6. <el-timeline> 7. 8. <el-timeline-item :timestamp="blog.created" placement="top" v-for="blog in blogs"> 9. <el-card> 10. <h4> 11. <router-link :to="{name: 'BlogDetail', params: {blogId: blog.id}}"> 12. {{blog.title}} 13. </router-link> 14. </h4> 15. <p>{{blog.description}}</p> 16. </el-card> 17. </el-timeline-item> 18. 19. </el-timeline> 20. 21. <el-pagination class="mpage" 22. background 23. layout="prev, pager, next" 24. :current-page="currentPage" 25. :page-size="pageSize" 26. :total="total" 27. @current-change=page> 28. </el-pagination> 29. 30. </div> 31. 32. </div> 33. </template> 34. 35. <script> 36. import Header from "../components/Header"; 37. 38. export default { 39. name: "Blogs.vue", 40. components: {Header}, 41. data() { 42. return { 43. blogs: {}, 44. currentPage: 1, 45. total: 0, 46. pageSize: 5 47. } 48. }, 49. methods: { 50. page(currentPage) { 51. const _this = this 52. _this.$axios.get("/blogs?currentPage=" + currentPage).then(res => { 53. console.log(res) 54. _this.blogs = res.data.data.records 55. _this.currentPage = res.data.data.current 56. _this.total = res.data.data.total 57. _this.pageSize = res.data.data.size 58. 59. }) 60. } 61. }, 62. created() { 63. this.page(1) 64. } 65. } 66. </script> 67. 68. <style scoped> 69. 70. .mpage { 71. margin: 0 auto; 72. text-align: center; 73. } 74. 75. </style>
博客编辑页
1. <template> 2. <div> 3. <Header></Header> 4. 5. <div class="m-content"> 6. 7. <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm"> 8. <el-form-item label="标题" prop="title"> 9. <el-input v-model="ruleForm.title"></el-input> 10. </el-form-item> 11. 12. <el-form-item label="摘要" prop="description"> 13. <el-input type="textarea" v-model="ruleForm.description"></el-input> 14. </el-form-item> 15. 16. <el-form-item label="内容" prop="content"> 17. <mavon-editor v-model="ruleForm.content"></mavon-editor> 18. </el-form-item> 19. 20. <el-form-item> 21. <el-button type="primary" @click="submitForm('ruleForm')">立即创建</el-button> 22. <el-button @click="resetForm('ruleForm')">重置</el-button> 23. </el-form-item> 24. </el-form> 25. 26. </div> 27. 28. 29. 30. </div> 31. </template> 32. 33. <script> 34. import Header from "../components/Header"; 35. export default { 36. name: "BlogEdit.vue", 37. components: {Header}, 38. data() { 39. return { 40. ruleForm: { 41. id: '', 42. title: '', 43. description: '', 44. content: '' 45. }, 46. rules: { 47. title: [ 48. { required: true, message: '请输入标题', trigger: 'blur' }, 49. { min: 3, max: 25, message: '长度在 3 到 25 个字符', trigger: 'blur' } 50. ], 51. description: [ 52. { required: true, message: '请输入摘要', trigger: 'blur' } 53. ], 54. content: [ 55. { trequired: true, message: '请输入内容', trigger: 'blur' } 56. ] 57. } 58. }; 59. }, 60. methods: { 61. submitForm(formName) { 62. this.$refs[formName].validate((valid) => { 63. if (valid) { 64. 65. const _this = this 66. this.$axios.post('/blog/edit', this.ruleForm, { 67. headers: { 68. "Authorization": localStorage.getItem("token") 69. } 70. }).then(res => { 71. console.log(res) 72. _this.$alert('操作成功', '提示', { 73. confirmButtonText: '确定', 74. callback: action => { 75. _this.$router.push("/blogs") 76. } 77. }); 78. 79. }) 80. 81. } else { 82. console.log('error submit!!'); 83. return false; 84. } 85. }); 86. }, 87. resetForm(formName) { 88. this.$refs[formName].resetFields(); 89. } 90. }, 91. created() { 92. const blogId = this.$route.params.blogId 93. console.log(blogId) 94. const _this = this 95. if(blogId) { 96. this.$axios.get('/blog/' + blogId).then(res => { 97. const blog = res.data.data 98. _this.ruleForm.id = blog.id 99. _this.ruleForm.title = blog.title 100. _this.ruleForm.description = blog.description 101. _this.ruleForm.content = blog.content 102. }) 103. } 104. 105. } 106. } 107. </script> 108. 109. <style scoped> 110. .m-content { 111. text-align: center; 112. } 113. </style>
登录页面
1. <template> 2. <div> 3. 4. <el-container> 5. <el-header> 6. <img class="mlogo" src="https://www.markerhub.com/dist/images/logo/markerhub-logo.png" alt=""> 7. </el-header> 8. <el-main> 9. 10. <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm"> 11. <el-form-item label="用户名" prop="username"> 12. <el-input v-model="ruleForm.username"></el-input> 13. </el-form-item> 14. <el-form-item label="密码" prop="password"> 15. <el-input type="password" v-model="ruleForm.password"></el-input> 16. </el-form-item> 17. 18. <el-form-item> 19. <el-button type="primary" @click="submitForm('ruleForm')">登录</el-button> 20. <el-button @click="resetForm('ruleForm')">重置</el-button> 21. <el-button ><el-link href="/blogs">主页</el-link></el-button> 22. 23. </el-form-item> 24. </el-form> 25. 26. </el-main> 27. </el-container> 28. 29. </div> 30. </template> 31. 32. <script> 33. export default { 34. name: "Login", 35. data() { 36. return { 37. ruleForm: { 38. username: 'sy', 39. password: '111111' 40. }, 41. rules: { 42. username: [ 43. { required: true, message: '请输入用户名', trigger: 'blur' }, 44. { min: 0, max: 15, message: '长度在 3 到 15 个字符', trigger: 'blur' } 45. ], 46. password: [ 47. { required: true, message: '请选择密码', trigger: 'change' } 48. ] 49. } 50. }; 51. }, 52. methods: { 53. submitForm(formName) { 54. this.$refs[formName].validate((valid) => { 55. if (valid) { 56. const _this = this 57. this.$axios.post('/login', this.ruleForm).then(res => { 58. 59. console.log(res.data) 60. const jwt = res.headers['authorization'] 61. const userInfo = res.data.data 62. 63. // 把数据共享出去 64. _this.$store.commit("SET_TOKEN", jwt) 65. _this.$store.commit("SET_USERINFO", userInfo) 66. 67. // 获取 68. console.log(_this.$store.getters.getUser) 69. 70. _this.$router.push("/blogs") 71. }) 72. 73. } else { 74. console.log('error submit!!'); 75. return false; 76. } 77. }); 78. }, 79. resetForm(formName) { 80. this.$refs[formName].resetFields(); 81. } 82. } 83. } 84. </script> 85. 86. <style scoped> 87. .el-header, .el-footer { 88. background-color: #B3C0D1; 89. color: #333; 90. text-align: center; 91. line-height: 60px; 92. } 93. 94. .el-aside { 95. background-color: #D3DCE6; 96. color: #333; 97. text-align: center; 98. line-height: 200px; 99. } 100. 101. .el-main { 102. /*background-color: #E9EEF3;*/ 103. color: #333; 104. text-align: center; 105. line-height: 160px; 106. } 107. 108. body > .el-container { 109. margin-bottom: 40px; 110. } 111. 112. .el-container:nth-child(5) .el-aside, 113. .el-container:nth-child(6) .el-aside { 114. line-height: 260px; 115. } 116. 117. .el-container:nth-child(7) .el-aside { 118. line-height: 320px; 119. } 120. 121. .mlogo { 122. height: 60%; 123. margin-top: 10px; 124. } 125. 126. .demo-ruleForm { 127. max-width: 500px; 128. margin: 0 auto; 129. } 130. 131. </style>
博客详情页
1. <template> 2. <div> 3. <Header></Header> 4. 5. <div class="mblog"> 6. <h2> {{ blog.title }}</h2> 7. <el-link icon="el-icon-edit" v-if="ownBlog"> 8. <router-link :to="{name: 'BlogEdit', params: {blogId: blog.id}}" > 9. 编辑 10. </router-link> 11. </el-link> 12. <el-divider></el-divider> 13. <div class="markdown-body" v-html="blog.content"></div> 14. 15. </div> 16. 17. </div> 18. </template> 19. 20. <script> 21. import 'github-markdown-css' 22. import Header from "../components/Header"; 23. 24. export default { 25. name: "BlogDetail.vue", 26. components: {Header}, 27. data() { 28. return { 29. blog: { 30. id: "", 31. title: "", 32. content: "" 33. }, 34. ownBlog: false 35. } 36. }, 37. created() { 38. const blogId = this.$route.params.blogId 39. console.log(blogId) 40. const _this = this 41. this.$axios.get('/blog/' + blogId).then(res => { 42. const blog = res.data.data 43. _this.blog.id = blog.id 44. _this.blog.title = blog.title 45. 46. var MardownIt = require("markdown-it") 47. var md = new MardownIt() 48. 49. var result = md.render(blog.content) 50. _this.blog.content = result 51. _this.ownBlog = (blog.userId === _this.$store.getters.getUser.id) 52. 53. }) 54. } 55. } 56. </script> 57. 58. <style scoped> 59. .mblog { 60. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); 61. width: 100%; 62. min-height: 700px; 63. padding: 20px 15px; 64. } 65. 66. </style>
后端代码
博客接口
1. @RestController 2. public class BlogController { 3. 4. @Autowired 5. BlogService blogService; 6. 7. // 列表 8. @GetMapping("/blogs") 9. public Result list(@RequestParam(defaultValue = "1") Integer currentPage) { 10. 11. Page page = new Page(currentPage, 5); 12. IPage pageData = blogService.page(page, new QueryWrapper<Blog>().orderByDesc("created")); 13. 14. return Result.succ(pageData); 15. } 16. 17. 18. 19. // 详情 20. @GetMapping("/blog/{id}") 21. public Result detail(@PathVariable(name = "id") Long id) { 22. Blog blog = blogService.getById(id); 23. Assert.notNull(blog, "该博客已被删除"); 24. 25. return Result.succ(blog); 26. } 27. 28. // 编辑 29. @RequiresAuthentication 30. @PostMapping("/blog/edit") 31. public Result edit(@Validated @RequestBody Blog blog) { 32. 33. // Assert.isTrue(false, "公开版不能任意编辑!"); 34. 35. Blog temp = null; 36. if(blog.getId() != null) { 37. temp = blogService.getById(blog.getId()); 38. // 只能编辑自己的文章 39. System.out.println(ShiroUtil.getProfile().getId()); 40. Assert.isTrue(temp.getUserId().longValue() == ShiroUtil.getProfile().getId().longValue(), "没有权限编辑"); 41. 42. } else { 43. 44. temp = new Blog(); 45. temp.setUserId(ShiroUtil.getProfile().getId()); 46. temp.setCreated(LocalDateTime.now()); 47. temp.setStatus(0); 48. } 49. 50. BeanUtil.copyProperties(blog, temp, "id", "userId", "created", "status"); 51. blogService.saveOrUpdate(temp); 52. 53. return Result.succ(null); 54. } 55. 56. }
用户校验接口
1. @RestController 2. public class AccountController { 3. 4. @Autowired 5. UserService userService; 6. 7. @Autowired 8. JwtUtils jwtUtils; 9. 10. @PostMapping("/login") 11. public Result login(@Validated @RequestBody LoginDto loginDto, HttpServletResponse response) { 12. 13. System.out.println(loginDto.getUsername()); 14. User user = userService.getOne(new QueryWrapper<User>().eq("username", loginDto.getUsername())); 15. 16. System.out.println(2222); 17. Assert.notNull(user, "用户不存在"); 18. 19. if(!user.getPassword().equals(SecureUtil.md5(loginDto.getPassword()))){ 20. return Result.fail("密码不正确"); 21. } 22. String jwt = jwtUtils.generateToken(user.getId()); 23. 24. response.setHeader("Authorization", jwt); 25. response.setHeader("Access-control-Expose-Headers", "Authorization"); 26. 27. return Result.succ(MapUtil.builder() 28. .put("id", user.getId()) 29. .put("username", user.getUsername()) 30. .put("avatar", user.getAvatar()) 31. .put("email", user.getEmail()) 32. .map() 33. ); 34. } 35. 36. @RequiresAuthentication 37. @GetMapping("/logout") 38. public Result logout() { 39. SecurityUtils.getSubject().logout(); 40. return Result.succ(null); 41. } 42. 43. }
spring整合shiro
1. @Component 2. public class JwtFilter extends AuthenticatingFilter { 3. @Autowired 4. JwtUtils jwtUtils; 5. 6. @Override 7. protected AuthenticationToken createToken(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception { 8. HttpServletRequest request = (HttpServletRequest) servletRequest; 9. String jwt = request.getHeader("Authorization"); 10. if(StringUtils.isEmpty(jwt)) { 11. return null; 12. } 13. 14. return new JwtToken(jwt); 15. } 16. 17. @Override 18. protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception { 19. HttpServletRequest request = (HttpServletRequest) servletRequest; 20. String jwt = request.getHeader("Authorization"); 21. if(StringUtils.isEmpty(jwt)) { 22. return true; 23. } else { 24. // 校验jwt 25. Claims claim = jwtUtils.getClaimByToken(jwt); 26. if(claim == null || jwtUtils.isTokenExpired(claim.getExpiration())) { 27. throw new ExpiredCredentialsException("token已失效,请重新登录"); 28. } 29. 30. // 执行登录 31. return executeLogin(servletRequest, servletResponse); 32. } 33. } 34. 35. @Override 36. protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) { 37. 38. HttpServletResponse httpServletResponse = (HttpServletResponse) response; 39. 40. Throwable throwable = e.getCause() == null ? e : e.getCause(); 41. Result result = Result.fail(throwable.getMessage()); 42. String json = JSONUtil.toJsonStr(result); 43. 44. try { 45. httpServletResponse.getWriter().print(json); 46. } catch (IOException ioException) { 47. 48. } 49. return false; 50. } 51. 52. @Override 53. protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { 54. 55. HttpServletRequest httpServletRequest = WebUtils.toHttp(request); 56. HttpServletResponse httpServletResponse = WebUtils.toHttp(response); 57. httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin")); 58. httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE"); 59. httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers")); 60. // 跨域时会首先发送一个OPTIONS请求,这里我们给OPTIONS请求直接返回正常状态 61. if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) { 62. httpServletResponse.setStatus(org.springframework.http.HttpStatus.OK.value()); 63. return false; 64. } 65. 66. return super.preHandle(request, response); 67. } 68. 69. }
1. @Configuration 2. public class ShiroConfig { 3. 4. @Autowired 5. JwtFilter jwtFilter; 6. 7. @Bean 8. public SessionManager sessionManager(RedisSessionDAO redisSessionDAO) { 9. DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); 10. 11. // inject redisSessionDAO 12. sessionManager.setSessionDAO(redisSessionDAO); 13. return sessionManager; 14. } 15. 16. @Bean 17. public DefaultWebSecurityManager securityManager(AccountRealm accountRealm, 18. SessionManager sessionManager, 19. RedisCacheManager redisCacheManager) { 20. 21. DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(accountRealm); 22. 23. //inject sessionManager 24. securityManager.setSessionManager(sessionManager); 25. 26. // inject redisCacheManager 27. securityManager.setCacheManager(redisCacheManager); 28. return securityManager; 29. } 30. 31. @Bean 32. public ShiroFilterChainDefinition shiroFilterChainDefinition() { 33. DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition(); 34. 35. Map<String, String> filterMap = new LinkedHashMap<>(); 36. 37. 38. filterMap.put("/**", "jwt"); 39. chainDefinition.addPathDefinitions(filterMap); 40. return chainDefinition; 41. } 42. 43. @Bean("shiroFilterFactoryBean") 44. public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager, 45. ShiroFilterChainDefinition shiroFilterChainDefinition) { 46. ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); 47. shiroFilter.setSecurityManager(securityManager); 48. 49. Map<String, Filter> filters = new HashMap<>(); 50. filters.put("jwt", jwtFilter); 51. 52. 53. shiroFilter.setFilters(filters); 54. 55. Map<String, String> filterMap = shiroFilterChainDefinition.getFilterChainMap(); 56. 57. shiroFilter.setFilterChainDefinitionMap(filterMap); 58. return shiroFilter; 59. } 60. 61. 62. }
数据库设计
1. SET NAMES utf8mb4; 2. SET FOREIGN_KEY_CHECKS = 0; 3. 4. -- ---------------------------- 5. -- Table structure for m_blog 6. -- ---------------------------- 7. DROP TABLE IF EXISTS `m_blog`; 8. CREATE TABLE `m_blog` ( 9. `id` bigint(20) NOT NULL AUTO_INCREMENT, 10. `user_id` bigint(20) NOT NULL, 11. `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, 12. `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, 13. `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, 14. `created` datetime NOT NULL, 15. `status` tinyint(4) NULL DEFAULT NULL, 16. PRIMARY KEY (`id`) USING BTREE 17. ) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact; 18. 19. -- ---------------------------- 20. -- Records of m_blog 21. -- ---------------------------- 22. INSERT INTO `m_blog` VALUES (6, 2, '123', '321', '123213', '2022-12-20 12:14:56', 0); 23. INSERT INTO `m_blog` VALUES (7, 1, 'syy', '23', '12321321321', '2022-12-20 12:52:00', 0); 24. INSERT INTO `m_blog` VALUES (8, 1, '123213', '123213', 'ceshi', '2022-12-21 07:46:34', 0); 25. INSERT INTO `m_blog` VALUES (9, 1, '测试1', '测试二', '测试', '2022-12-29 04:20:06', 0); 26. 27. -- ---------------------------- 28. -- Table structure for m_discussion 29. -- ---------------------------- 30. DROP TABLE IF EXISTS `m_discussion`; 31. CREATE TABLE `m_discussion` ( 32. `id` bigint(20) NOT NULL AUTO_INCREMENT, 33. `user_id` bigint(20) NOT NULL, 34. `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, 35. `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, 36. `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, 37. `created` datetime NOT NULL, 38. `status` tinyint(4) NULL DEFAULT NULL, 39. PRIMARY KEY (`id`) USING BTREE 40. ) ENGINE = InnoDB AUTO_INCREMENT = 19 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact; 41. 42. -- ---------------------------- 43. -- Records of m_discussion 44. -- ---------------------------- 45. INSERT INTO `m_discussion` VALUES (1, 1, '小明', '五行学习法很不错', '五行学习法很好', '2020-10-13 21:05:31', 0); 46. INSERT INTO `m_discussion` VALUES (6, 1, '小李', 'nice', '内容', '2022-11-21 15:25:15', 0); 47. INSERT INTO `m_discussion` VALUES (7, 1, '小张', '不错', '', '2022-11-21 16:15:57', 0); 48. INSERT INTO `m_discussion` VALUES (8, 1, '小伤', '挺好的', '', '2022-11-21 16:25:36', 0); 49. INSERT INTO `m_discussion` VALUES (9, 1, 'shangyi', '挺不错的', '', '2022-11-21 16:27:00', 0); 50. INSERT INTO `m_discussion` VALUES (10, 1, '小商', '很好', '', '2022-11-21 16:31:49', 0); 51. INSERT INTO `m_discussion` VALUES (11, 1, '小诗', '挺好的', '', '2022-11-21 16:34:11', 0); 52. INSERT INTO `m_discussion` VALUES (12, 1, '尚艺', '很好', '', '2022-11-25 16:55:35', 0); 53. INSERT INTO `m_discussion` VALUES (13, 1, '11', '11', '', '2022-12-09 14:19:00', 0); 54. INSERT INTO `m_discussion` VALUES (14, 1, '111', '111112', '', '2022-12-09 15:31:43', 0); 55. INSERT INTO `m_discussion` VALUES (15, 1, '小诺', '12三大', '', '2022-12-09 15:33:04', 0); 56. INSERT INTO `m_discussion` VALUES (16, 1, '12', '123', '', '2022-12-09 15:34:20', 0); 57. INSERT INTO `m_discussion` VALUES (17, 1, '111', '111', '', '2022-12-09 16:25:59', 0); 58. INSERT INTO `m_discussion` VALUES (18, 1, 'xiao', '123', '', '2022-12-09 16:59:00', 0); 59. 60. -- ---------------------------- 61. -- Table structure for m_user 62. -- ---------------------------- 63. DROP TABLE IF EXISTS `m_user`; 64. CREATE TABLE `m_user` ( 65. `id` bigint(20) NOT NULL AUTO_INCREMENT, 66. `username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, 67. `avatar` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, 68. `email` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, 69. `password` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, 70. `status` int(5) NOT NULL, 71. `created` datetime NULL DEFAULT NULL, 72. `last_login` datetime NULL DEFAULT NULL, 73. `like` int(23) NULL DEFAULT NULL, 74. `collection` int(11) NULL DEFAULT NULL, 75. `visit` int(11) NULL DEFAULT NULL, 76. PRIMARY KEY (`id`) USING BTREE, 77. INDEX `UK_USERNAME`(`username`) USING BTREE 78. ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; 79. 80. -- ---------------------------- 81. -- Records of m_user 82. -- ---------------------------- 83. INSERT INTO `m_user` VALUES (1, 'sy', 'https://image-1300566513.cos.ap-guangzhou.myqcloud.com/upload/images/5a9f48118166308daba8b6da7e466aab.jpg', NULL, '96e79218965eb72c92a549dd5a330112', 0, '2020-04-20 10:44:01', NULL, NULL, NULL, NULL); 84. INSERT INTO `m_user` VALUES (2, 'xia', NULL, NULL, '96e79218965eb72c92a549dd5a330112', 0, NULL, NULL, NULL, NULL, NULL); 85. 86. SET FOREIGN_KEY_CHECKS = 1;
代码地址