├── .gitignore ├── README.md ├── wechat-api ├── .gitignore ├── db.sql ├── pom.xml └── src │ ├── main │ ├── java │ │ └── cn │ │ │ └── tycoding │ │ │ ├── Application.java │ │ │ ├── biz │ │ │ ├── controller │ │ │ │ ├── LoginController.java │ │ │ │ └── UserController.java │ │ │ ├── entity │ │ │ │ └── SysUser.java │ │ │ ├── mapper │ │ │ │ └── UserMapper.java │ │ │ └── service │ │ │ │ ├── UserService.java │ │ │ │ └── impl │ │ │ │ └── UserServiceImpl.java │ │ │ └── common │ │ │ ├── auth │ │ │ ├── AuthRealm.java │ │ │ ├── AuthSessionManager.java │ │ │ ├── ShiroConfig.java │ │ │ └── ShiroSessionListener.java │ │ │ ├── config │ │ │ ├── CorsConfig.java │ │ │ └── MybatisPlusConfig.java │ │ │ ├── constants │ │ │ ├── CommonConstant.java │ │ │ └── enums │ │ │ │ └── CommonEnum.java │ │ │ ├── controller │ │ │ └── BaseController.java │ │ │ ├── exception │ │ │ └── GlobalException.java │ │ │ ├── handler │ │ │ └── GlobalExceptionHandler.java │ │ │ ├── properties │ │ │ ├── AppProperties.java │ │ │ └── ShiroProperties.java │ │ │ └── utils │ │ │ ├── MD5Util.java │ │ │ ├── QueryPage.java │ │ │ └── R.java │ └── resources │ │ ├── application-dev.yml │ │ ├── application-prod.yml │ │ ├── application.yml │ │ ├── banner.txt │ │ ├── logback-spring.xml │ │ ├── mapper │ │ └── UserMapper.xml │ │ └── tycoding.properties │ └── test │ └── java │ └── cn │ └── tycoding │ └── common │ └── utils │ └── MD5UtilTest.java └── wechat-app ├── .gitignore ├── App.vue ├── README.md ├── api └── user.js ├── common └── app.css ├── components ├── common │ ├── tui-clipboard │ │ ├── clipboard.min.js │ │ └── tui-clipboard.js │ └── tui-validation │ │ └── tui-validation.js ├── luch-request │ ├── adapters │ │ └── index.js │ ├── core │ │ ├── InterceptorManager.js │ │ ├── Request.js │ │ ├── buildFullPath.js │ │ ├── defaults.js │ │ ├── dispatchRequest.js │ │ ├── mergeConfig.js │ │ └── settle.js │ ├── helpers │ │ ├── buildURL.js │ │ ├── combineURLs.js │ │ └── isAbsoluteURL.js │ ├── index.js │ └── utils.js ├── thorui-nvue │ ├── thor-circular-progress │ │ ├── gcanvas │ │ │ ├── bridge │ │ │ │ └── bridge-weex.js │ │ │ ├── context-2d │ │ │ │ ├── FillStyleLinearGradient.js │ │ │ │ ├── FillStylePattern.js │ │ │ │ ├── FillStyleRadialGradient.js │ │ │ │ └── RenderingContext.js │ │ │ ├── context-webgl │ │ │ │ ├── ActiveInfo.js │ │ │ │ ├── Buffer.js │ │ │ │ ├── Framebuffer.js │ │ │ │ ├── GLenum.js │ │ │ │ ├── GLmethod.js │ │ │ │ ├── GLtype.js │ │ │ │ ├── Program.js │ │ │ │ ├── Renderbuffer.js │ │ │ │ ├── RenderingContext.js │ │ │ │ ├── Shader.js │ │ │ │ ├── ShaderPrecisionFormat.js │ │ │ │ ├── Texture.js │ │ │ │ ├── UniformLocation.js │ │ │ │ └── classUtils.js │ │ │ ├── env │ │ │ │ ├── canvas.js │ │ │ │ ├── image.js │ │ │ │ └── tool.js │ │ │ └── index.js │ │ └── thor-circular-progress.nvue │ └── thor-icon │ │ ├── icons.js │ │ └── thor-icon.vue ├── thorui │ ├── tui-actionsheet │ │ └── tui-actionsheet.vue │ ├── tui-alert │ │ └── tui-alert.vue │ ├── tui-badge │ │ └── tui-badge.vue │ ├── tui-bottom-navigation │ │ └── tui-bottom-navigation.vue │ ├── tui-bottom-popup │ │ └── tui-bottom-popup.vue │ ├── tui-bubble-popup │ │ └── tui-bubble-popup.vue │ ├── tui-button │ │ └── tui-button.vue │ ├── tui-calendar │ │ └── tui-calendar.vue │ ├── tui-card │ │ └── tui-card.vue │ ├── tui-cascade-selection │ │ └── tui-cascade-selection.vue │ ├── tui-circular-progress │ │ └── tui-circular-progress.vue │ ├── tui-collapse │ │ └── tui-collapse.vue │ ├── tui-countdown │ │ └── tui-countdown.vue │ ├── tui-datetime │ │ └── tui-datetime.vue │ ├── tui-divider │ │ └── tui-divider.vue │ ├── tui-drawer │ │ └── tui-drawer.vue │ ├── tui-dropdown-list │ │ └── tui-dropdown-list.vue │ ├── tui-fab │ │ └── tui-fab.vue │ ├── tui-footer │ │ └── tui-footer.vue │ ├── tui-grid-item │ │ └── tui-grid-item.vue │ ├── tui-grid │ │ └── tui-grid.vue │ ├── tui-icon │ │ └── tui-icon.vue │ ├── tui-image-cropper │ │ └── tui-image-cropper.vue │ ├── tui-image-group │ │ └── tui-image-group.vue │ ├── tui-keyboard-input │ │ └── tui-keyboard-input.vue │ ├── tui-keyboard │ │ └── tui-keyboard.vue │ ├── tui-list-cell │ │ └── tui-list-cell.vue │ ├── tui-list-view │ │ └── tui-list-view.vue │ ├── tui-loading │ │ └── tui-loading.vue │ ├── tui-loadmore │ │ └── tui-loadmore.vue │ ├── tui-modal │ │ └── tui-modal.vue │ ├── tui-navigation-bar │ │ └── tui-navigation-bar.vue │ ├── tui-no-data │ │ └── tui-no-data.vue │ ├── tui-nomore │ │ └── tui-nomore.vue │ ├── tui-numberbox │ │ └── tui-numberbox.vue │ ├── tui-rate │ │ └── tui-rate.vue │ ├── tui-scroll-top │ │ └── tui-scroll-top.vue │ ├── tui-skeleton │ │ └── tui-skeleton.vue │ ├── tui-steps │ │ └── tui-steps.vue │ ├── tui-sticky │ │ └── tui-sticky.vue │ ├── tui-swipe-action │ │ └── tui-swipe-action.vue │ ├── tui-tabbar │ │ └── tui-tabbar.vue │ ├── tui-tabs │ │ └── tui-tabs.vue │ ├── tui-tag │ │ └── tui-tag.vue │ ├── tui-time-axis │ │ └── tui-time-axis.vue │ ├── tui-timeaxis-item │ │ └── tui-timeaxis-item.vue │ ├── tui-tips │ │ └── tui-tips.vue │ ├── tui-toast │ │ └── tui-toast.vue │ ├── tui-top-dropdown │ │ └── tui-top-dropdown.vue │ └── tui-upload │ │ └── tui-upload.vue ├── uni-simple-router │ ├── README.md │ ├── appRouter │ │ ├── hooks.js │ │ ├── init.js │ │ ├── uniNav.js │ │ └── util.js │ ├── appletsRouter │ │ ├── appletsNav.js │ │ ├── hooks.js │ │ ├── init.js │ │ └── util.js │ ├── component │ │ ├── h5-dom.js │ │ └── router-link.vue │ ├── helpers │ │ ├── compile.js │ │ ├── config.js │ │ ├── mixins.js │ │ ├── navJump.js │ │ ├── urlQuery.js │ │ ├── util.js │ │ └── warn.js │ ├── index.js │ ├── lifeCycle │ │ └── hooks.js │ ├── package.json │ ├── patch │ │ ├── app-patch.js │ │ ├── applets-patch.js │ │ └── h5-patch.js │ ├── types │ │ ├── index.d.ts │ │ └── options.d.ts │ └── vueRouter │ │ ├── base.js │ │ ├── concat.js │ │ ├── extends │ │ └── myArray.js │ │ ├── init.js │ │ ├── proxy │ │ └── proxy.js │ │ ├── routerNav.js │ │ └── util.js ├── uni │ └── uParse │ │ └── src │ │ ├── components │ │ ├── wxParseAudio.vue │ │ ├── wxParseImg.vue │ │ ├── wxParseTable.vue │ │ ├── wxParseTemplate0.vue │ │ ├── wxParseTemplate1.vue │ │ ├── wxParseTemplate10.vue │ │ ├── wxParseTemplate11.vue │ │ ├── wxParseTemplate2.vue │ │ ├── wxParseTemplate3.vue │ │ ├── wxParseTemplate4.vue │ │ ├── wxParseTemplate5.vue │ │ ├── wxParseTemplate6.vue │ │ ├── wxParseTemplate7.vue │ │ ├── wxParseTemplate8.vue │ │ ├── wxParseTemplate9.vue │ │ └── wxParseVideo.vue │ │ ├── editor.css │ │ ├── libs │ │ ├── html2json.js │ │ ├── htmlparser.js │ │ └── wxDiscode.js │ │ ├── wxParse.css │ │ └── wxParse.vue └── views │ ├── app-plus │ └── tui-share │ │ └── tui-share.nvue │ ├── t-chat-bar │ └── t-chat-bar.vue │ ├── t-linkage │ └── t-linkage.vue │ ├── t-news-item │ └── t-news-item.nvue │ ├── t-pay-way │ └── ti-pay-way.vue │ └── t-rt-popup │ └── t-rt-popup.vue ├── config.js ├── main.js ├── manifest.json ├── pages.json ├── pages ├── common │ ├── about │ │ └── about.vue │ ├── github │ │ └── github.vue │ ├── info │ │ └── info.vue │ └── login │ │ └── login.vue └── tabbar │ ├── extend │ └── extend.vue │ ├── index │ └── index.vue │ └── my │ └── my.vue ├── permission.js ├── router └── index.js ├── static ├── fonts │ └── thorui.ttf ├── images │ ├── fab │ │ ├── fab_about.png │ │ ├── fab_reward.png │ │ └── fab_share.png │ ├── index │ │ ├── basic.png │ │ ├── cancle.png │ │ ├── canvas.png │ │ ├── class.png │ │ ├── drawer.png │ │ ├── home_icon_choose_3x.png │ │ ├── icon_down.png │ │ ├── icon_next_3x.png │ │ ├── icon_right.png │ │ ├── index.png │ │ ├── map.png │ │ ├── nav.png │ │ ├── refresh.png │ │ ├── search.png │ │ ├── swipe.png │ │ └── template.png │ ├── my │ │ ├── call.png │ │ ├── feedback.png │ │ ├── github.png │ │ ├── go.png │ │ ├── icon_out_3x.png │ │ ├── log.png │ │ ├── mine_bg_3x.png │ │ ├── mine_def_touxiang_3x.png │ │ ├── mine_icon_bianji_3x.png │ │ ├── mine_icon_chongdian_3x.png │ │ ├── mine_icon_jiayouzhan_3x.png │ │ ├── mine_icon_tingche_3x.png │ │ └── reward.png │ ├── share │ │ ├── icon_moments.png │ │ ├── icon_qq.png │ │ ├── icon_sina.png │ │ └── icon_wechat.png │ ├── tabbar │ │ ├── code_active.png │ │ ├── code_gray.png │ │ ├── extend_active.png │ │ ├── extend_gray.png │ │ ├── home.png │ │ ├── home_fill.png │ │ ├── people.png │ │ ├── people_fill.png │ │ └── release.png │ └── toast │ │ ├── check-circle.png │ │ ├── fail-circle.png │ │ ├── img_nodata.png │ │ ├── img_noorder_3x.png │ │ └── info-circle.png └── style │ └── thorui.css ├── store ├── getters.js ├── index.js └── modules │ └── user.js └── utils ├── auth.js ├── request.js └── util.js /.gitignore: -------------------------------------------------------------------------------- 1 | ### gradle ### 2 | .gradle 3 | /build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | 6 | ### STS ### 7 | .settings/ 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | bin/ 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | rebel.xml 22 | 23 | ### NetBeans ### 24 | nbproject/private/ 25 | build/ 26 | nbbuild/ 27 | dist/ 28 | nbdist/ 29 | .nb-gradle/ 30 | 31 | ### maven ### 32 | target/ 33 | *.war 34 | *.ear 35 | *.zip 36 | *.tar 37 | *.tar.gz 38 | 39 | ### logs #### 40 | /logs/ 41 | *.log 42 | 43 | ### temp ignore ### 44 | *.cache 45 | *.diff 46 | *.patch 47 | *.tmp 48 | *.java~ 49 | *.properties~ 50 | *.xml~ 51 | 52 | ### system ignore ### 53 | .DS_Store 54 | Thumbs.db 55 | Servers 56 | .metadata 57 | upload 58 | gen_code 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Wechat Template 2 | 3 | 本仓库中包含了两个项目: 4 | 5 | `wechat-api`: 基于SpringBoot2.x、Shiro构建的仅提供Restful api的后端项目 6 | 7 | `wechat-app`: 基于Uni-app构建的微信小程序 8 | 9 | **你能学到什么** 10 | 11 | 1. Uni-app与Java Web项目结合的最佳实践 12 | 2. SpringBoot与Shiro的集成,以及身份校验、Token交互的实现 13 | 3. 如何优雅的封装一套Uni-app(微信小程序)脚手架,包括:request api封装、vuex存储、router页面路由、与Java后端数据交互 14 | 4. 如何优雅的封装一套SpringBoot&Shiro权限项目脚手架,如何处理前后端分离Token交互 15 | 5. 如何处理小程序端Request请求,后续将从Login请求展开逐步分析前后端交互流程 16 | 17 | ## 文档 18 | 19 | 文档正在编写中... 20 | 21 | 22 | 23 | 后续将在我的公众号 **程序员涂陌** 中陆续发布,请持续关注! 24 | 25 | | 程序员涂陌 | 26 | | ----------------------------------------------------------- | 27 | | ![qrcode_for_gh](http://cdn.tycoding.cn/20200610184737.jpg) | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ## 捐赠 35 | 36 | | Alipay | WechatPay | 37 | | ---------------------------------------------------------- | ---------------------------------------------------------- | 38 | | ![alipay_258px](http://cdn.tycoding.cn/20200610132929.png) | ![wechat_258px](http://cdn.tycoding.cn/20200610132940.png) | 39 | 40 | 41 | 42 | ## 预览 43 | 44 | | Login | Index | My | 45 | | ------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------ | 46 | | ![IMG_0701](http://cdn.tycoding.cn/20200610182506.PNG) | ![IMG_0696](http://cdn.tycoding.cn/20200610182520.PNG) | ![IMG_0697](http://cdn.tycoding.cn/20200610182533.PNG) | 47 | 48 | | Update | About | Github | 49 | | ------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------ | 50 | | ![IMG_0700](http://cdn.tycoding.cn/20200610182651.PNG) | ![IMG_0698](http://cdn.tycoding.cn/20200610182613.PNG) | ![IMG_0699](http://cdn.tycoding.cn/20200610182628.PNG) | 51 | 52 | 53 | 54 | ## 联系我 55 | 56 | - [Blog@TyCoding's blog](http://www.tycoding.cn) 57 | 58 | - [GitHub@TyCoding](https://github.com/TyCoding) 59 | 60 | - [ZhiHu@TyCoding](https://www.zhihu.com/people/tomo-83-82/activities) 61 | 62 | - QQ Group: 671017003 63 | 64 | -------------------------------------------------------------------------------- /wechat-api/.gitignore: -------------------------------------------------------------------------------- 1 | ### gradle ### 2 | .gradle 3 | /build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | 6 | ### STS ### 7 | .settings/ 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | bin/ 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | rebel.xml 22 | 23 | ### NetBeans ### 24 | nbproject/private/ 25 | build/ 26 | nbbuild/ 27 | dist/ 28 | nbdist/ 29 | .nb-gradle/ 30 | 31 | ### maven ### 32 | target/ 33 | *.war 34 | *.ear 35 | *.zip 36 | *.tar 37 | *.tar.gz 38 | 39 | ### logs #### 40 | /logs/ 41 | *.log 42 | 43 | ### temp ignore ### 44 | *.cache 45 | *.diff 46 | *.patch 47 | *.tmp 48 | *.java~ 49 | *.properties~ 50 | *.xml~ 51 | 52 | ### system ignore ### 53 | .DS_Store 54 | Thumbs.db 55 | Servers 56 | .metadata 57 | upload 58 | gen_code 59 | -------------------------------------------------------------------------------- /wechat-api/db.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat Premium Data Transfer 3 | Source Server : localhost_3306 4 | Source Server Type : MySQL 5 | Source Server Version : 50729 6 | Source Host : localhost:3306 7 | Source Schema : wechat_api 8 | Target Server Type : MySQL 9 | Target Server Version : 50729 10 | File Encoding : 65001 11 | Date: 09/06/2020 10:57:29 12 | */ 13 | 14 | SET NAMES utf8mb4; 15 | SET FOREIGN_KEY_CHECKS = 0; 16 | 17 | -- ---------------------------- 18 | -- Table structure for tb_user 19 | -- ---------------------------- 20 | DROP TABLE IF EXISTS `tb_user`; 21 | CREATE TABLE `tb_user` ( 22 | `id` int(11) NOT NULL AUTO_INCREMENT, 23 | `username` varchar(255) DEFAULT NULL, 24 | `password` varchar(255) DEFAULT NULL, 25 | `avatar` varchar(255) DEFAULT NULL, 26 | PRIMARY KEY (`id`) 27 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; 28 | 29 | -- ---------------------------- 30 | -- Records of tb_user 31 | -- ---------------------------- 32 | BEGIN; 33 | INSERT INTO `tb_user` VALUES (1, 'tycoding', '250b8460be2cf5c3d93938074b63f8e0', 'http://cdn.tycoding.cn/20200609171249.png'); 34 | COMMIT; 35 | 36 | SET FOREIGN_KEY_CHECKS = 1; -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/Application.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | /** 8 | * @author tycoding 9 | * @date 2020/6/9 10 | */ 11 | @SpringBootApplication 12 | @MapperScan("cn.tycoding.biz.mapper") 13 | public class Application { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(Application.class, args); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/biz/controller/LoginController.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.biz.controller; 2 | 3 | import cn.tycoding.common.constants.enums.CommonEnum; 4 | import cn.tycoding.common.controller.BaseController; 5 | import cn.tycoding.common.exception.GlobalException; 6 | import cn.tycoding.common.utils.MD5Util; 7 | import cn.tycoding.common.utils.R; 8 | import org.apache.shiro.authc.UsernamePasswordToken; 9 | import org.apache.shiro.subject.Subject; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | /** 16 | * @author tycoding 17 | * @date 2020/6/9 18 | */ 19 | @RestController 20 | public class LoginController extends BaseController { 21 | 22 | /** 23 | * 登录接口 24 | * 25 | * @param username 26 | * @param password 27 | * @return 28 | */ 29 | @GetMapping("/login") 30 | public R login(@RequestParam(value = "username", required = false) String username, 31 | @RequestParam(value = "password", required = false) String password) { 32 | if (username == null || password == null) { 33 | throw new GlobalException(CommonEnum.LOGIN_ERROR.getMsg()); 34 | } 35 | Subject subject = getSubject(); 36 | String encrypt_password = MD5Util.encryptPassword(username, password); 37 | UsernamePasswordToken token = new UsernamePasswordToken(username, encrypt_password); 38 | try { 39 | subject.login(token); 40 | 41 | Map map = new HashMap<>(); 42 | map.put("token", subject.getSession().getId()); 43 | map.put("user", this.getCurrentUser()); 44 | return new R<>(map); 45 | } catch (Exception e) { 46 | e.printStackTrace(); 47 | return new R<>(e); 48 | } 49 | } 50 | 51 | /** 52 | * 注销接口 53 | * 54 | * @return 55 | */ 56 | @DeleteMapping(value = "/logout") 57 | public R logout() { 58 | Subject subject = getSubject(); 59 | subject.logout(); 60 | return new R(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/biz/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.biz.controller; 2 | 3 | import cn.tycoding.common.controller.BaseController; 4 | import cn.tycoding.common.exception.GlobalException; 5 | import cn.tycoding.common.utils.QueryPage; 6 | import cn.tycoding.common.utils.R; 7 | import cn.tycoding.biz.entity.SysUser; 8 | import cn.tycoding.biz.service.UserService; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | /** 16 | * @author tycoding 17 | * @date 2020/6/9 18 | */ 19 | @RestController 20 | @RequestMapping("/user") 21 | public class UserController extends BaseController { 22 | 23 | @Autowired 24 | private UserService userService; 25 | 26 | @GetMapping("/info") 27 | public R getInfo() { 28 | Map map = new HashMap<>(); 29 | map.put("token", this.getSession().getId()); 30 | map.put("user", this.getCurrentUser()); 31 | return new R<>(map); 32 | } 33 | 34 | @GetMapping("/{id}") 35 | public R findById(@PathVariable Long id) { 36 | return new R<>(userService.getById(id)); 37 | } 38 | 39 | @PostMapping("/list") 40 | public R findByPage(@RequestBody SysUser sysUser, QueryPage queryPage) { 41 | return new R<>(super.getData(userService.list(sysUser, queryPage))); 42 | } 43 | 44 | @GetMapping("/findByName") 45 | public R findByName(String name) { 46 | return new R<>(userService.findByName(name)); 47 | } 48 | 49 | @PostMapping("/filter/list") 50 | public R list(@RequestBody SysUser sysUser) { 51 | return new R<>(userService.list(sysUser)); 52 | } 53 | 54 | @PostMapping 55 | public R save(@RequestBody SysUser sysUser) { 56 | try { 57 | userService.add(sysUser); 58 | return new R(); 59 | } catch (Exception e) { 60 | throw new GlobalException(e.getMessage()); 61 | } 62 | } 63 | 64 | @PutMapping 65 | public R update(@RequestBody SysUser sysUser) { 66 | try { 67 | userService.update(sysUser); 68 | return new R(); 69 | } catch (Exception e) { 70 | throw new GlobalException(e.getMessage()); 71 | } 72 | } 73 | 74 | @DeleteMapping("/{id}") 75 | public R delete(@PathVariable Long id) { 76 | try { 77 | userService.delete(id); 78 | return new R(); 79 | } catch (Exception e) { 80 | e.printStackTrace(); 81 | throw new GlobalException(e.getMessage()); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/biz/entity/SysUser.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.biz.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | import lombok.experimental.Accessors; 9 | 10 | import java.io.Serializable; 11 | import java.util.Date; 12 | 13 | /** 14 | * @author tycoding 15 | * @date 2020/6/9 16 | */ 17 | @Data 18 | @Accessors(chain = true) 19 | @TableName(value = "tb_user") 20 | public class SysUser implements Serializable { 21 | 22 | @TableId(type = IdType.AUTO) 23 | private Long id; 24 | 25 | private String username; 26 | private String password; 27 | private String avatar; 28 | } 29 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/biz/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.biz.mapper; 2 | 3 | import cn.tycoding.biz.entity.SysUser; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | * @author tycoding 8 | * @date 2020/6/9 9 | */ 10 | public interface UserMapper extends BaseMapper { 11 | } 12 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/biz/service/UserService.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.biz.service; 2 | 3 | import cn.tycoding.common.utils.QueryPage; 4 | import cn.tycoding.biz.entity.SysUser; 5 | import com.baomidou.mybatisplus.core.metadata.IPage; 6 | import com.baomidou.mybatisplus.extension.service.IService; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author tycoding 12 | * @date 2020/6/9 13 | */ 14 | public interface UserService extends IService { 15 | 16 | SysUser findByName(String username); 17 | 18 | IPage list(SysUser sysUser, QueryPage queryPage); 19 | 20 | List list(SysUser sysUser); 21 | 22 | void add(SysUser sysUser); 23 | 24 | void update(SysUser sysUser); 25 | 26 | void delete(Long id); 27 | } 28 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/common/auth/AuthRealm.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.auth; 2 | 3 | import cn.tycoding.common.constants.enums.CommonEnum; 4 | import cn.tycoding.biz.entity.SysUser; 5 | import cn.tycoding.biz.service.UserService; 6 | import org.apache.shiro.authc.*; 7 | import org.apache.shiro.authz.AuthorizationInfo; 8 | import org.apache.shiro.realm.AuthorizingRealm; 9 | import org.apache.shiro.subject.PrincipalCollection; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Component; 12 | 13 | /** 14 | * @author tycoding 15 | * @date 2020/6/9 16 | */ 17 | @Component 18 | public class AuthRealm extends AuthorizingRealm { 19 | 20 | @Autowired 21 | private UserService userService; 22 | 23 | /** 24 | * 身份校验 25 | * 26 | * @param authenticationToken 27 | * @return 28 | * @throws AuthenticationException 29 | */ 30 | @Override 31 | protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { 32 | String username = (String) authenticationToken.getPrincipal(); 33 | if (username == null) { 34 | throw new AuthenticationException(CommonEnum.TOKEN_ERROR.getMsg()); 35 | } 36 | String password = new String((char[]) authenticationToken.getCredentials()); 37 | SysUser sysUser = userService.findByName(username); 38 | 39 | if (sysUser == null || !sysUser.getPassword().equals(password)) { 40 | throw new IncorrectCredentialsException(CommonEnum.LOGIN_ERROR.getMsg()); 41 | } 42 | 43 | return new SimpleAuthenticationInfo( 44 | sysUser, 45 | password, 46 | getName() 47 | ); 48 | } 49 | 50 | /** 51 | * 权限校验 52 | * 53 | * @param principalCollection 54 | * @return 55 | */ 56 | @Override 57 | protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { 58 | return null; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/common/auth/AuthSessionManager.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.auth; 2 | 3 | import cn.tycoding.common.constants.CommonConstant; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.apache.shiro.session.mgt.DefaultSessionManager; 6 | import org.apache.shiro.session.mgt.SessionKey; 7 | import org.apache.shiro.web.servlet.ShiroHttpServletRequest; 8 | import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; 9 | import org.apache.shiro.web.util.WebUtils; 10 | 11 | import javax.servlet.ServletRequest; 12 | import javax.servlet.ServletResponse; 13 | import java.io.Serializable; 14 | 15 | /** 16 | * @author tycoding 17 | * @date 2020/6/9 18 | */ 19 | public class AuthSessionManager extends DefaultWebSessionManager { 20 | 21 | public AuthSessionManager() { 22 | super(); 23 | } 24 | 25 | @Override 26 | protected Serializable getSessionId(ServletRequest request, ServletResponse response) { 27 | // 获取请求头Header中的Token,登录时定义了Token = SessionID 28 | String token = WebUtils.toHttp(request).getHeader(CommonConstant.AUTHORIZATION); 29 | if (!StringUtils.isEmpty(token)) { 30 | request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, token); 31 | request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE); 32 | return token; 33 | } else { 34 | // 否则按默认从Cookie中获取JSESSIONID 35 | return super.getSessionId(request, response); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/common/auth/ShiroSessionListener.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.auth; 2 | 3 | import org.apache.shiro.session.Session; 4 | import org.apache.shiro.session.SessionListener; 5 | 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | /** 9 | * @author tycoding 10 | * @date 2020/6/9 11 | */ 12 | public class ShiroSessionListener implements SessionListener { 13 | 14 | private final AtomicInteger sessionCount = new AtomicInteger(0); 15 | 16 | @Override 17 | public void onStart(Session session) { 18 | sessionCount.incrementAndGet(); 19 | } 20 | 21 | @Override 22 | public void onStop(Session session) { 23 | sessionCount.decrementAndGet(); 24 | } 25 | 26 | @Override 27 | public void onExpiration(Session session) { 28 | sessionCount.decrementAndGet(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/common/config/CorsConfig.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.cors.CorsConfiguration; 6 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 7 | import org.springframework.web.filter.CorsFilter; 8 | 9 | /** 10 | * 解决跨域 11 | * 12 | * @author tycoding 13 | * @date 2020/6/9 14 | */ 15 | @Configuration 16 | public class CorsConfig { 17 | private CorsConfiguration buildConfig() { 18 | CorsConfiguration corsConfiguration = new CorsConfiguration(); 19 | corsConfiguration.addAllowedOrigin("*"); 20 | corsConfiguration.addAllowedHeader("*"); 21 | corsConfiguration.addAllowedMethod("*"); 22 | return corsConfiguration; 23 | } 24 | 25 | @Bean 26 | public CorsFilter corsFilter() { 27 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 28 | source.registerCorsConfiguration("/**", buildConfig()); 29 | return new CorsFilter(source); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/common/config/MybatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.config; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; 4 | import org.mybatis.spring.annotation.MapperScan; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | /** 9 | * @author tycoding 10 | * @date 2020/6/9 11 | */ 12 | @Configuration 13 | public class MybatisPlusConfig { 14 | 15 | /** 16 | * Mybatis-Plus 分页插件 17 | */ 18 | @Bean 19 | public PaginationInterceptor paginationInterceptor() { 20 | return new PaginationInterceptor(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/common/constants/CommonConstant.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.constants; 2 | 3 | /** 4 | * 项目公共常量 5 | * 6 | * @author tycoding 7 | * @date 2020/6/9 8 | */ 9 | public interface CommonConstant { 10 | 11 | /** 12 | * 成功标记 13 | */ 14 | int SUCCESS = 200; 15 | 16 | /** 17 | * 错误标记 18 | */ 19 | int ERROR = 500; 20 | 21 | /** 22 | * UTF-8编码 23 | */ 24 | String UTF8 = "UTF-8"; 25 | 26 | /** 27 | * User-Agent 28 | */ 29 | String USER_AGENT = "User-Agent"; 30 | 31 | /** 32 | * 前端Token Key 33 | */ 34 | String AUTHORIZATION = "Authorization"; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/common/constants/enums/CommonEnum.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.constants.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | /** 7 | * @author tycoding 8 | * @date 2020/6/9 9 | */ 10 | @Getter 11 | @AllArgsConstructor 12 | public enum CommonEnum { 13 | 14 | LOGIN_ERROR(500, "用户名或密码错误"), 15 | TOKEN_ERROR(401, "Token已失效,请重新登录"), 16 | PARAM_ERROR(401, "参数错误"), 17 | USER_ERROR(500, "获取用户信息失败"), 18 | LOGOUT_ERROR(500, "退出失败"), 19 | SYSTEM_ERROR(500, "系统内部错误"), 20 | COMMON_ERROR(500, "系统内部错误"), 21 | FILE_ERROR(400, "上传的文件为空"), 22 | COMMON_SUCCESS(200, "成功"), 23 | RESET_SUCCESS(200, "重置密码成功"); 24 | 25 | private final int code; 26 | private final String msg; 27 | } 28 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/common/controller/BaseController.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.controller; 2 | 3 | import cn.tycoding.biz.entity.SysUser; 4 | import com.baomidou.mybatisplus.core.metadata.IPage; 5 | import org.apache.shiro.SecurityUtils; 6 | import org.apache.shiro.authc.AuthenticationToken; 7 | import org.apache.shiro.session.Session; 8 | import org.apache.shiro.subject.Subject; 9 | 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | /** 14 | * Controller公共层方法提取 15 | * 16 | * @author tycoding 17 | * @date 2020/6/9 18 | */ 19 | public class BaseController { 20 | 21 | protected static Subject getSubject() { 22 | return SecurityUtils.getSubject(); 23 | } 24 | 25 | protected SysUser getCurrentUser() { 26 | return (SysUser) getSubject().getPrincipal(); 27 | } 28 | 29 | protected Session getSession() { 30 | return getSubject().getSession(); 31 | } 32 | 33 | protected Session getSession(Boolean flag) { 34 | return getSubject().getSession(flag); 35 | } 36 | 37 | protected void login(AuthenticationToken token) { 38 | getSubject().login(token); 39 | } 40 | 41 | public Map getData(IPage page) { 42 | Map data = new HashMap<>(); 43 | data.put("rows", page.getRecords()); 44 | data.put("total", page.getTotal()); 45 | return data; 46 | } 47 | 48 | public Map getToken() { 49 | Map map = new HashMap<>(); 50 | map.put("token", getSession().getId()); 51 | return map; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/common/exception/GlobalException.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.exception; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * @author tycoding 8 | * @date 2020/6/9 9 | */ 10 | public class GlobalException extends RuntimeException { 11 | 12 | @Getter 13 | @Setter 14 | private String msg; 15 | 16 | public GlobalException(String message) { 17 | super(message); 18 | this.msg = message; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/common/handler/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.handler; 2 | 3 | import cn.tycoding.common.constants.CommonConstant; 4 | import cn.tycoding.common.exception.GlobalException; 5 | import cn.tycoding.common.utils.R; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.apache.shiro.authc.AuthenticationException; 8 | import org.apache.shiro.authz.AuthorizationException; 9 | import org.apache.shiro.authz.UnauthorizedException; 10 | import org.springframework.core.Ordered; 11 | import org.springframework.core.annotation.Order; 12 | import org.springframework.http.HttpStatus; 13 | import org.springframework.web.bind.annotation.ExceptionHandler; 14 | import org.springframework.web.bind.annotation.RestControllerAdvice; 15 | 16 | /** 17 | * 全局异常处理器 18 | * 19 | * @author tycoding 20 | * @date 2020/6/9 21 | */ 22 | @Slf4j 23 | @RestControllerAdvice 24 | @Order(value = Ordered.HIGHEST_PRECEDENCE) 25 | public class GlobalExceptionHandler { 26 | 27 | @ExceptionHandler(value = Exception.class) 28 | public R exception(Exception e) { 29 | log.error("内部错误, {}", e.getMessage()); 30 | e.printStackTrace(); 31 | return new R(e); 32 | } 33 | 34 | @ExceptionHandler(value = GlobalException.class) 35 | public R globalExceptionHandle(GlobalException e) { 36 | log.error("全局异常, {}", e.getMessage()); 37 | e.printStackTrace(); 38 | return new R<>(CommonConstant.ERROR, e.getMsg()); 39 | } 40 | 41 | @ExceptionHandler(value = UnauthorizedException.class) 42 | public R handleUnauthorizedException(UnauthorizedException e) { 43 | log.error("UnauthorizedException, {}", e.getMessage()); 44 | return new R(HttpStatus.FORBIDDEN, e.getMessage()); 45 | } 46 | 47 | @ExceptionHandler(value = AuthenticationException.class) 48 | public R handleAuthenticationException(AuthenticationException e) { 49 | log.error("AuthenticationException, {}", e.getMessage()); 50 | return new R(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage()); 51 | } 52 | 53 | @ExceptionHandler(value = AuthorizationException.class) 54 | public R handleAuthorizationException(AuthorizationException e) { 55 | log.error("AuthorizationException, {}", e.getMessage()); 56 | return new R<>(HttpStatus.UNAUTHORIZED, e.getMessage()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/common/properties/AppProperties.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.properties; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.SpringBootConfiguration; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.annotation.PropertySource; 7 | 8 | /** 9 | * @author tycoding 10 | * @date 2020/6/9 11 | */ 12 | @Data 13 | @SpringBootConfiguration 14 | @PropertySource(value = {"classpath:tycoding.properties"}) 15 | @ConfigurationProperties(prefix = "tycoding") 16 | public class AppProperties { 17 | 18 | private ShiroProperties shiro = new ShiroProperties(); 19 | } 20 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/common/properties/ShiroProperties.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.properties; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author tycoding 7 | * @date 2020/6/9 8 | */ 9 | @Data 10 | public class ShiroProperties { 11 | 12 | private long sessionTimeout; 13 | private int cookieTimeout; 14 | private String anonUrl; 15 | private String loginUrl; 16 | private String successUrl; 17 | private String logoutUrl; 18 | private String cipherKey; 19 | } 20 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/common/utils/MD5Util.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.utils; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.apache.shiro.crypto.hash.SimpleHash; 5 | import org.apache.shiro.util.ByteSource; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * Shiro MD5 加密 10 | * 11 | * @author tycoding 12 | * @date 2020/6/9 13 | */ 14 | @Component 15 | public class MD5Util { 16 | 17 | // 算法名称 18 | private static final String ALGORITH_NAME = "MD5"; 19 | // 迭代次数 20 | private static final int HASH_ITERATIONS = 2; 21 | 22 | //加密算法 23 | public static String encryptPassword(String username, String password) { 24 | if (username == null || password == null) { 25 | return null; 26 | } 27 | return new SimpleHash( 28 | ALGORITH_NAME, 29 | StringUtils.lowerCase(StringUtils.lowerCase(password)), 30 | ByteSource.Util.bytes(StringUtils.lowerCase(username)), 31 | HASH_ITERATIONS).toHex(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/common/utils/QueryPage.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.utils; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * @author tycoding 11 | * @date 2020/6/9 12 | */ 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class QueryPage implements Serializable { 17 | 18 | /** 19 | * 当前页 20 | */ 21 | private int page; 22 | 23 | /** 24 | * 每页的记录数 25 | */ 26 | private int limit; 27 | } 28 | -------------------------------------------------------------------------------- /wechat-api/src/main/java/cn/tycoding/common/utils/R.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.utils; 2 | 3 | import cn.tycoding.common.constants.CommonConstant; 4 | import cn.tycoding.common.constants.enums.CommonEnum; 5 | import lombok.*; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * @author tycoding 11 | * @date 2020/6/9 12 | */ 13 | @Builder 14 | @ToString 15 | @AllArgsConstructor 16 | public class R implements Serializable { 17 | 18 | @Getter 19 | @Setter 20 | private int code = CommonConstant.SUCCESS; 21 | 22 | @Getter 23 | @Setter 24 | private Object msg = "success"; 25 | 26 | @Getter 27 | @Setter 28 | private T data; 29 | 30 | public R() { 31 | super(); 32 | } 33 | 34 | public R(T data) { 35 | super(); 36 | this.data = data; 37 | } 38 | 39 | public R(int code, String msg) { 40 | this.code = code; 41 | this.msg = msg; 42 | } 43 | 44 | public R(T data, String msg) { 45 | super(); 46 | this.data = data; 47 | this.msg = msg; 48 | } 49 | 50 | public R(CommonEnum enums) { 51 | super(); 52 | this.code = enums.getCode(); 53 | this.msg = enums.getMsg(); 54 | } 55 | 56 | public R(Throwable e) { 57 | super(); 58 | this.code = CommonConstant.ERROR; 59 | this.msg = e.getMessage(); 60 | } 61 | 62 | public R(String message, Throwable e) { 63 | super(); 64 | this.msg = message; 65 | this.code = CommonConstant.ERROR; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /wechat-api/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | type: com.zaxxer.hikari.HikariDataSource 4 | driver-class-name: com.mysql.cj.jdbc.Driver 5 | username: root 6 | password: root 7 | url: jdbc:mysql://localhost:3306/wechat_api?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai 8 | 9 | # 打印sql 10 | #logging: 11 | # level: 12 | # cn.tycoding.biz.mapper: DEBUG 13 | -------------------------------------------------------------------------------- /wechat-api/src/main/resources/application-prod.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | type: com.zaxxer.hikari.HikariDataSource 4 | driver-class-name: com.mysql.cj.jdbc.Driver 5 | username: root 6 | password: root 7 | url: jdbc:mysql://localhost:3306/wechat_api?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai -------------------------------------------------------------------------------- /wechat-api/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | tomcat: 4 | uri-encoding: utf-8 5 | 6 | spring: 7 | profiles: 8 | #开发环境:dev 生产环境:prod 9 | active: dev 10 | 11 | #文件上传相关设置 12 | servlet: 13 | multipart: 14 | max-file-size: 10MB 15 | max-request-size: 100MB 16 | 17 | mybatis-plus: 18 | type-aliases-package: cn.tycoding.biz.entity 19 | mapper-locations: classpath:mapper/*.xml 20 | configuration: 21 | jdbc-type-for-null: null 22 | global-config: 23 | banner: false 24 | -------------------------------------------------------------------------------- /wechat-api/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _ __ __ __ ___ ______ __ __ 2 | | | / /__ _____/ /_ ____ _/ /_ / | ____ ____ /_ __/__ ____ ___ ____ / /___ _/ /____ 3 | | | /| / / _ \/ ___/ __ \/ __ `/ __/ / /| | / __ \/ __ \ / / / _ \/ __ `__ \/ __ \/ / __ `/ __/ _ \ 4 | | |/ |/ / __/ /__/ / / / /_/ / /_ / ___ |/ /_/ / /_/ / / / / __/ / / / / / /_/ / / /_/ / /_/ __/ 5 | |__/|__/\___/\___/_/ /_/\__,_/\__/ /_/ |_/ .___/ .___/ /_/ \___/_/ /_/ /_/ .___/_/\__,_/\__/\___/ 6 | /_/ /_/ /_/ 7 | 8 | Author: TyCoding 9 | Blog: http://tycoding.cn 10 | Github: https://github.com/tycoding 11 | QQ group: 671017003 -------------------------------------------------------------------------------- /wechat-api/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 12 | 14 | 15 | 16 | 17 | ${CONSOLE_LOG_PATTERN} 18 | 19 | 20 | 21 | 22 | 23 | ${log.path}/debug.log 24 | 25 | ${log.path}/%d{yyyy-MM, aux}/debug.%d{yyyy-MM-dd}.%i.log.gz 26 | 50MB 27 | 30 28 | 29 | 30 | %date [%thread] %-5level [%logger{50}] %file:%line - %msg%n 31 | 32 | 33 | 34 | 35 | 36 | ${log.path}/error.log 37 | 38 | ${log.path}/%d{yyyy-MM}/error.%d{yyyy-MM-dd}.%i.log.gz 39 | 50MB 40 | 30 41 | 42 | 43 | %date [%thread] %-5level [%logger{50}] %file:%line - %msg%n 44 | 45 | 46 | ERROR 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /wechat-api/src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /wechat-api/src/main/resources/tycoding.properties: -------------------------------------------------------------------------------- 1 | # Shiro配置 2 | tycoding.shiro.session_timeout=3600 3 | tycoding.shiro.cookie_timeout=86400 4 | tycoding.shiro.anon_url=/login,/logout 5 | tycoding.shiro.login_url=/login 6 | tycoding.shiro.success_url=/index 7 | tycoding.shiro.logout_url=/logout 8 | tycoding.shiro.cipher_key=tycoding 9 | -------------------------------------------------------------------------------- /wechat-api/src/test/java/cn/tycoding/common/utils/MD5UtilTest.java: -------------------------------------------------------------------------------- 1 | package cn.tycoding.common.utils; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | /** 9 | * @author tycoding 10 | * @date 2020/6/1 11 | */ 12 | @RunWith(SpringRunner.class) 13 | @SpringBootTest 14 | public class MD5UtilTest { 15 | 16 | @Test 17 | public void encryptPassword() { 18 | String encryptPassword = MD5Util.encryptPassword("tycoding", "123456"); 19 | System.out.println(encryptPassword); // 250b8460be2cf5c3d93938074b63f8e0 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /wechat-app/.gitignore: -------------------------------------------------------------------------------- 1 | /unpackage 2 | 3 | ### gradle ### 4 | .gradle 5 | /build/ 6 | !gradle/wrapper/gradle-wrapper.jar 7 | 8 | ### STS ### 9 | .settings/ 10 | .apt_generated 11 | .classpath 12 | .factorypath 13 | .project 14 | .settings 15 | .springBeans 16 | bin/ 17 | 18 | ### IntelliJ IDEA ### 19 | .idea 20 | *.iws 21 | *.iml 22 | *.ipr 23 | rebel.xml 24 | 25 | ### NetBeans ### 26 | nbproject/private/ 27 | build/ 28 | nbbuild/ 29 | dist/ 30 | nbdist/ 31 | .nb-gradle/ 32 | 33 | ### maven ### 34 | target/ 35 | *.war 36 | *.ear 37 | *.zip 38 | *.tar 39 | *.tar.gz 40 | 41 | ### logs #### 42 | /logs/ 43 | *.log 44 | 45 | ### temp ignore ### 46 | *.cache 47 | *.diff 48 | *.patch 49 | *.tmp 50 | *.java~ 51 | *.properties~ 52 | *.xml~ 53 | 54 | ### system ignore ### 55 | .DS_Store 56 | Thumbs.db 57 | Servers 58 | .metadata 59 | upload 60 | gen_code 61 | -------------------------------------------------------------------------------- /wechat-app/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 16 | -------------------------------------------------------------------------------- /wechat-app/README.md: -------------------------------------------------------------------------------- 1 | # Component 2 | 3 | | name | version | 4 | | -- | -- | 5 | | uni-app | 2.7.9 | 6 | | thorui | 1.5.0 | 7 | | luch-request | 3.0.2 | 8 | | uni-simple-route | 1.8.4 | -------------------------------------------------------------------------------- /wechat-app/api/user.js: -------------------------------------------------------------------------------- 1 | import http from '@/utils/request' 2 | 3 | export function login(data) { 4 | return http.request({ 5 | url: '/login', 6 | method: 'get', 7 | params: { 8 | username: data.username, 9 | password: data.password 10 | } 11 | }) 12 | } 13 | 14 | export function getInfo() { 15 | return http.request({ 16 | url: '/user/info', 17 | method: 'get' 18 | }) 19 | } 20 | 21 | export function logout() { 22 | return http.request({ 23 | url: '/logout', 24 | method: 'delete' 25 | }) 26 | } 27 | 28 | export function getList(query, data) { 29 | return http.request({ 30 | url: `/user/list?page=${query.page}&limit=${query.limit}`, 31 | method: 'post', 32 | data 33 | }) 34 | } 35 | 36 | export function findById(id) { 37 | return http.request({ 38 | url: '/user/' + id, 39 | method: 'get' 40 | }) 41 | } 42 | 43 | export function findByName(name) { 44 | return http.request({ 45 | url: `/user/findByName?name=${name}`, 46 | method: 'get' 47 | }) 48 | } 49 | 50 | export function save(data) { 51 | return http.request({ 52 | url: '/user', 53 | method: 'post', 54 | data 55 | }) 56 | } 57 | 58 | export function del(id) { 59 | return http.request({ 60 | url: '/user/' + id, 61 | method: 'delete' 62 | }) 63 | } 64 | 65 | export function update(data) { 66 | return http.request({ 67 | url: '/user', 68 | method: 'put', 69 | data 70 | }) 71 | } 72 | 73 | export function changePass(data) { 74 | return http.request({ 75 | url: '/user/changePass', 76 | method: 'post', 77 | data 78 | }) 79 | } 80 | -------------------------------------------------------------------------------- /wechat-app/common/app.css: -------------------------------------------------------------------------------- 1 | /*app.wxss*/ 2 | /* #ifndef APP-NVUE */ 3 | page { 4 | background-color: #fafafa; 5 | font-size: 32rpx; 6 | } 7 | 8 | text { 9 | /* 自动换行 */ 10 | word-break:break-all; 11 | } 12 | 13 | ::-webkit-scrollbar { 14 | width: 0; 15 | height: 0; 16 | color: transparent; 17 | } 18 | 19 | button::after { 20 | border: none; 21 | } 22 | 23 | .container { 24 | display: flex; 25 | box-sizing: border-box; 26 | flex-direction: column; 27 | } 28 | 29 | .tui-phcolor { 30 | color: #ccc; 31 | font-size: 32rpx; 32 | overflow: visible; 33 | } 34 | 35 | 36 | 37 | .tui-opcity { 38 | opacity: 0.5; 39 | } 40 | 41 | .tui-hover { 42 | background-color: #f7f7f9 !important; 43 | } 44 | 45 | .tui-ellipsis { 46 | overflow: hidden; 47 | white-space: nowrap; 48 | text-overflow: ellipsis; 49 | } 50 | 51 | 52 | 53 | /*按钮样式*/ 54 | 55 | /*列表统一样式 */ 56 | .tui-list-item { 57 | position: relative; 58 | } 59 | 60 | .tui-list-item::after { 61 | content: ''; 62 | position: absolute; 63 | border-bottom: 1rpx solid #eaeef1; 64 | -webkit-transform: scaleY(0.5); 65 | transform: scaleY(0.5); 66 | bottom: 0; 67 | right: 0; 68 | left: 30rpx; 69 | } 70 | 71 | .tui-last::after { 72 | border-bottom: 0 !important; 73 | } 74 | 75 | .tui-button-primary { 76 | width: 100%; 77 | height: 90rpx; 78 | line-height: 90rpx; 79 | background: linear-gradient(-90deg, #5677fc, #5c8dff); 80 | border-radius: 45rpx; 81 | color: #fff; 82 | font-size: 36rpx; 83 | } 84 | 85 | .tui-button-hover { 86 | color: #d5d4d9; 87 | background: linear-gradient(-90deg, #4a67d6, #4e77d9); 88 | } 89 | 90 | .tui-button-gray { 91 | background: #ededed; 92 | color: #999 !important; 93 | } 94 | 95 | .tui-button-gray_hover { 96 | background: #d5d5d5 !important; 97 | color: #898989; 98 | } 99 | 100 | .tui-button-white { 101 | background: #fff; 102 | color: #333 !important; 103 | } 104 | 105 | .tui-button-white_hover { 106 | background: #e5e5e5 !important; 107 | color: #2e2e2e !important; 108 | } 109 | 110 | /* #endif */ 111 | -------------------------------------------------------------------------------- /wechat-app/components/common/tui-clipboard/tui-clipboard.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 复制文本 兼容H5 3 | * 来自 ThorUI www.thorui.cn | 文档地址: www.donarui.com 4 | * @author echo. 5 | * @version 1.0.0 6 | **/ 7 | // #ifdef H5 8 | import ClipboardJS from "./clipboard.min.js" 9 | // #endif 10 | const thorui = { 11 | getClipboardData: function(data, callback) { 12 | // #ifdef APP-PLUS || MP 13 | uni.setClipboardData({ 14 | data: data, 15 | success(res) { 16 | ("function" == typeof callback) && callback(true) 17 | }, 18 | fail(res) { 19 | ("function" == typeof callback) && callback(false) 20 | } 21 | }) 22 | // #endif 23 | 24 | // #ifdef H5 25 | let event = window.event || {} 26 | let clipboard = new ClipboardJS("", { 27 | text: () => data 28 | }) 29 | clipboard.on('success', (e) => { 30 | ("function" == typeof callback) && callback(true) 31 | clipboard.off('success') 32 | clipboard.off('error') 33 | clipboard.destroy() 34 | }); 35 | clipboard.on('error', (e) => { 36 | ("function" == typeof callback) && callback(false) 37 | clipboard.off('success') 38 | clipboard.off('error') 39 | clipboard.destroy() 40 | }); 41 | clipboard.onClick(event) 42 | // #endif 43 | } 44 | }; 45 | 46 | module.exports = { 47 | getClipboardData: thorui.getClipboardData 48 | }; 49 | -------------------------------------------------------------------------------- /wechat-app/components/luch-request/adapters/index.js: -------------------------------------------------------------------------------- 1 | import buildURL from '../helpers/buildURL' 2 | import buildFullPath from '../core/buildFullPath' 3 | import settle from '../core/settle' 4 | 5 | /** 6 | * 返回可选值存在的配置 7 | * @param {Array} keys - 可选值数组 8 | * @param {Object} config2 - 配置 9 | * @return {{}} - 存在的配置项 10 | */ 11 | const mergeKeys = (keys, config2) => { 12 | let config = {} 13 | keys.forEach(prop => { 14 | if (typeof config2[prop] !== 'undefined') { 15 | config[prop] = config2[prop] 16 | } 17 | }) 18 | return config 19 | } 20 | export default (config) => { 21 | return new Promise((resolve, reject) => { 22 | const _config = { 23 | url: buildURL(buildFullPath(config.baseURL, config.url), config.params), 24 | header: config.header, 25 | complete: (response) => { 26 | response.config = config 27 | try { 28 | // 对可能字符串不是json 的情况容错 29 | if (typeof response.data === 'string') { 30 | response.data = JSON.parse(response.data) 31 | } 32 | // eslint-disable-next-line no-empty 33 | } catch (e) { 34 | } 35 | settle(resolve, reject, response) 36 | } 37 | } 38 | let requestTask 39 | if (config.method === 'UPLOAD') { 40 | let otherConfig = { 41 | // #ifdef MP-ALIPAY 42 | fileType: config.fileType, 43 | // #endif 44 | filePath: config.filePath, 45 | name: config.name 46 | } 47 | const optionalKeys = [ 48 | // #ifdef APP-PLUS || H5 49 | 'files', 50 | // #endif 51 | // #ifdef H5 52 | 'file', 53 | // #endif 54 | 'formData' 55 | ] 56 | requestTask = uni.uploadFile({..._config, ...otherConfig, ...mergeKeys(optionalKeys, config)}) 57 | } else if (config.method === 'DOWNLOAD') { 58 | requestTask = uni.downloadFile(_config) 59 | } else { 60 | const optionalKeys = [ 61 | 'data', 62 | 'method', 63 | // #ifdef MP-ALIPAY || MP-WEIXIN 64 | 'timeout', 65 | // #endif 66 | 'dataType', 67 | // #ifndef MP-ALIPAY || APP-PLUS 68 | 'responseType', 69 | // #endif 70 | // #ifdef APP-PLUS 71 | 'sslVerify', 72 | // #endif 73 | // #ifdef H5 74 | 'withCredentials' 75 | // #endif 76 | ] 77 | requestTask = uni.request({..._config,...mergeKeys(optionalKeys, config)}) 78 | } 79 | if (config.getTask) { 80 | config.getTask(requestTask, config) 81 | } 82 | }) 83 | } 84 | -------------------------------------------------------------------------------- /wechat-app/components/luch-request/core/InterceptorManager.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | 4 | function InterceptorManager() { 5 | this.handlers = [] 6 | } 7 | 8 | /** 9 | * Add a new interceptor to the stack 10 | * 11 | * @param {Function} fulfilled The function to handle `then` for a `Promise` 12 | * @param {Function} rejected The function to handle `reject` for a `Promise` 13 | * 14 | * @return {Number} An ID used to remove interceptor later 15 | */ 16 | InterceptorManager.prototype.use = function use(fulfilled, rejected) { 17 | this.handlers.push({ 18 | fulfilled: fulfilled, 19 | rejected: rejected 20 | }) 21 | return this.handlers.length - 1 22 | } 23 | 24 | /** 25 | * Remove an interceptor from the stack 26 | * 27 | * @param {Number} id The ID that was returned by `use` 28 | */ 29 | InterceptorManager.prototype.eject = function eject(id) { 30 | if (this.handlers[id]) { 31 | this.handlers[id] = null 32 | } 33 | } 34 | 35 | /** 36 | * Iterate over all the registered interceptors 37 | * 38 | * This method is particularly useful for skipping over any 39 | * interceptors that may have become `null` calling `eject`. 40 | * 41 | * @param {Function} fn The function to call for each interceptor 42 | */ 43 | InterceptorManager.prototype.forEach = function forEach(fn) { 44 | this.handlers.forEach(h => { 45 | if (h !== null) { 46 | fn(h) 47 | } 48 | }) 49 | } 50 | 51 | export default InterceptorManager 52 | -------------------------------------------------------------------------------- /wechat-app/components/luch-request/core/buildFullPath.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | import isAbsoluteURL from '../helpers/isAbsoluteURL' 4 | import combineURLs from '../helpers/combineURLs' 5 | 6 | /** 7 | * Creates a new URL by combining the baseURL with the requestedURL, 8 | * only when the requestedURL is not already an absolute URL. 9 | * If the requestURL is absolute, this function returns the requestedURL untouched. 10 | * 11 | * @param {string} baseURL The base URL 12 | * @param {string} requestedURL Absolute or relative URL to combine 13 | * @returns {string} The combined full path 14 | */ 15 | export default function buildFullPath(baseURL, requestedURL) { 16 | if (baseURL && !isAbsoluteURL(requestedURL)) { 17 | return combineURLs(baseURL, requestedURL) 18 | } 19 | return requestedURL 20 | } 21 | -------------------------------------------------------------------------------- /wechat-app/components/luch-request/core/defaults.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 默认的全局配置 3 | */ 4 | 5 | 6 | export default { 7 | baseURL: '', 8 | header: {}, 9 | method: 'GET', 10 | dataType: 'json', 11 | // #ifndef MP-ALIPAY || APP-PLUS 12 | responseType: 'text', 13 | // #endif 14 | custom: {}, 15 | // #ifdef MP-ALIPAY || MP-WEIXIN 16 | timeout: 30000, 17 | // #endif 18 | // #ifdef APP-PLUS 19 | sslVerify: true, 20 | // #endif 21 | // #ifdef H5 22 | withCredentials: false, 23 | // #endif 24 | validateStatus: function validateStatus(status) { 25 | return status >= 200 && status < 300 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /wechat-app/components/luch-request/core/dispatchRequest.js: -------------------------------------------------------------------------------- 1 | import adapter from '../adapters/index' 2 | 3 | 4 | export default (config) => { 5 | config.header = config.header || {} 6 | return adapter(config) 7 | } 8 | -------------------------------------------------------------------------------- /wechat-app/components/luch-request/core/mergeConfig.js: -------------------------------------------------------------------------------- 1 | import {deepMerge, isObject} from '../utils' 2 | 3 | /** 4 | * 合并局部配置优先的配置,如果局部有该配置项则用局部,如果全局有该配置项则用全局 5 | * @param {Array} keys - 配置项 6 | * @param {Object} globalsConfig - 当前的全局配置 7 | * @param {Object} config2 - 局部配置 8 | * @return {{}} 9 | */ 10 | const mergeKeys = (keys, globalsConfig, config2) => { 11 | let config = {} 12 | keys.forEach(prop => { 13 | if (typeof config2[prop] !== 'undefined') { 14 | config[prop] = config2[prop] 15 | } else if (typeof globalsConfig[prop] !== 'undefined') { 16 | config[prop] = globalsConfig[prop] 17 | } 18 | }) 19 | return config 20 | } 21 | /** 22 | * 23 | * @param globalsConfig - 当前实例的全局配置 24 | * @param config2 - 当前的局部配置 25 | * @return - 合并后的配置 26 | */ 27 | export default (globalsConfig, config2 = {}) => { 28 | const method = config2.method || globalsConfig.method || 'GET' 29 | let config = { 30 | baseURL: globalsConfig.baseURL || '', 31 | method: method, 32 | url: config2.url || '' 33 | } 34 | const mergeDeepPropertiesKeys = ['header', 'params', 'custom'] 35 | const defaultToConfig2Keys = ['getTask', 'validateStatus'] 36 | mergeDeepPropertiesKeys.forEach(prop => { 37 | if (isObject(config2[prop])) { 38 | config[prop] = deepMerge(globalsConfig[prop], config2[prop]) 39 | } else if (typeof config2[prop] !== 'undefined') { 40 | config[prop] = config2[prop] 41 | } else if (isObject(globalsConfig[prop])) { 42 | config[prop] = deepMerge(globalsConfig[prop]) 43 | } else if (typeof globalsConfig[prop] !== 'undefined') { 44 | config[prop] = globalsConfig[prop] 45 | } 46 | }) 47 | config = {...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2)} 48 | 49 | // eslint-disable-next-line no-empty 50 | if (method === 'DOWNLOAD') { 51 | 52 | } else if (method === 'UPLOAD') { 53 | if (isObject(config.header)) { 54 | delete config.header['content-type'] 55 | delete config.header['Content-Type'] 56 | } 57 | const uploadKeys = [ 58 | // #ifdef APP-PLUS || H5 59 | 'files', 60 | // #endif 61 | // #ifdef MP-ALIPAY 62 | 'fileType', 63 | // #endif 64 | // #ifdef H5 65 | 'file', 66 | // #endif 67 | 'filePath', 68 | 'name', 69 | 'formData', 70 | ] 71 | uploadKeys.forEach(prop => { 72 | if (typeof config2[prop] !== 'undefined') { 73 | config[prop] = config2[prop] 74 | } 75 | }) 76 | } else { 77 | const defaultsKeys = [ 78 | 'data', 79 | // #ifdef MP-ALIPAY || MP-WEIXIN 80 | 'timeout', 81 | // #endif 82 | 'dataType', 83 | // #ifndef MP-ALIPAY || APP-PLUS 84 | 'responseType', 85 | // #endif 86 | // #ifdef APP-PLUS 87 | 'sslVerify', 88 | // #endif 89 | // #ifdef H5 90 | 'withCredentials' 91 | // #endif 92 | ] 93 | config = {...config, ...mergeKeys(defaultsKeys, globalsConfig, config2)} 94 | } 95 | 96 | return config 97 | } 98 | -------------------------------------------------------------------------------- /wechat-app/components/luch-request/core/settle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Resolve or reject a Promise based on response status. 3 | * 4 | * @param {Function} resolve A function that resolves the promise. 5 | * @param {Function} reject A function that rejects the promise. 6 | * @param {object} response The response. 7 | */ 8 | export default function settle(resolve, reject, response) { 9 | const validateStatus = response.config.validateStatus 10 | const status = response.statusCode 11 | if (status && (!validateStatus || validateStatus(status))) { 12 | resolve(response) 13 | } else { 14 | reject(response) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /wechat-app/components/luch-request/helpers/buildURL.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | import * as utils from './../utils' 4 | 5 | function encode(val) { 6 | return encodeURIComponent(val). 7 | replace(/%40/gi, '@'). 8 | replace(/%3A/gi, ':'). 9 | replace(/%24/g, '$'). 10 | replace(/%2C/gi, ','). 11 | replace(/%20/g, '+'). 12 | replace(/%5B/gi, '['). 13 | replace(/%5D/gi, ']') 14 | } 15 | 16 | /** 17 | * Build a URL by appending params to the end 18 | * 19 | * @param {string} url The base of the url (e.g., http://www.google.com) 20 | * @param {object} [params] The params to be appended 21 | * @returns {string} The formatted url 22 | */ 23 | export default function buildURL(url, params) { 24 | /*eslint no-param-reassign:0*/ 25 | if (!params) { 26 | return url 27 | } 28 | 29 | var serializedParams 30 | if (utils.isURLSearchParams(params)) { 31 | serializedParams = params.toString() 32 | } else { 33 | var parts = [] 34 | 35 | utils.forEach(params, function serialize(val, key) { 36 | if (val === null || typeof val === 'undefined') { 37 | return 38 | } 39 | 40 | if (utils.isArray(val)) { 41 | key = key + '[]' 42 | } else { 43 | val = [val] 44 | } 45 | 46 | utils.forEach(val, function parseValue(v) { 47 | if (utils.isDate(v)) { 48 | v = v.toISOString() 49 | } else if (utils.isObject(v)) { 50 | v = JSON.stringify(v) 51 | } 52 | parts.push(encode(key) + '=' + encode(v)) 53 | }) 54 | }) 55 | 56 | serializedParams = parts.join('&') 57 | } 58 | 59 | if (serializedParams) { 60 | var hashmarkIndex = url.indexOf('#') 61 | if (hashmarkIndex !== -1) { 62 | url = url.slice(0, hashmarkIndex) 63 | } 64 | 65 | url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams 66 | } 67 | 68 | return url 69 | } 70 | -------------------------------------------------------------------------------- /wechat-app/components/luch-request/helpers/combineURLs.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * Creates a new URL by combining the specified URLs 5 | * 6 | * @param {string} baseURL The base URL 7 | * @param {string} relativeURL The relative URL 8 | * @returns {string} The combined URL 9 | */ 10 | export default function combineURLs(baseURL, relativeURL) { 11 | return relativeURL 12 | ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') 13 | : baseURL 14 | } 15 | -------------------------------------------------------------------------------- /wechat-app/components/luch-request/helpers/isAbsoluteURL.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * Determines whether the specified URL is absolute 5 | * 6 | * @param {string} url The URL to test 7 | * @returns {boolean} True if the specified URL is absolute, otherwise false 8 | */ 9 | export default function isAbsoluteURL(url) { 10 | // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL). 11 | // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed 12 | // by any combination of letters, digits, plus, period, or hyphen. 13 | return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url) 14 | } 15 | -------------------------------------------------------------------------------- /wechat-app/components/luch-request/index.js: -------------------------------------------------------------------------------- 1 | import Request from './core/Request' 2 | export default Request 3 | -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/context-2d/FillStyleLinearGradient.js: -------------------------------------------------------------------------------- 1 | class FillStyleLinearGradient { 2 | 3 | constructor(x0, y0, x1, y1) { 4 | this._start_pos = { _x: x0, _y: y0 }; 5 | this._end_pos = { _x: x1, _y: y1 }; 6 | this._stop_count = 0; 7 | this._stops = [0, 0, 0, 0, 0]; 8 | } 9 | 10 | addColorStop = function (pos, color) { 11 | if (this._stop_count < 5 && 0.0 <= pos && pos <= 1.0) { 12 | this._stops[this._stop_count] = { _pos: pos, _color: color }; 13 | this._stop_count++; 14 | } 15 | } 16 | } 17 | 18 | export default FillStyleLinearGradient; -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/context-2d/FillStylePattern.js: -------------------------------------------------------------------------------- 1 | class FillStylePattern { 2 | constructor(img, pattern) { 3 | this._style = pattern; 4 | this._img = img; 5 | } 6 | } 7 | 8 | export default FillStylePattern; -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/context-2d/FillStyleRadialGradient.js: -------------------------------------------------------------------------------- 1 | class FillStyleRadialGradient { 2 | constructor(x0, y0, r0, x1, y1, r1) { 3 | this._start_pos = { _x: x0, _y: y0, _r: r0 }; 4 | this._end_pos = { _x: x1, _y: y1, _r: r1 }; 5 | this._stop_count = 0; 6 | this._stops = [0, 0, 0, 0, 0]; 7 | } 8 | 9 | addColorStop(pos, color) { 10 | if (this._stop_count < 5 && 0.0 <= pos && pos <= 1.0) { 11 | this._stops[this._stop_count] = { _pos: pos, _color: color }; 12 | this._stop_count++; 13 | } 14 | } 15 | } 16 | 17 | export default FillStyleRadialGradient; -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/context-webgl/ActiveInfo.js: -------------------------------------------------------------------------------- 1 | export default class WebGLActiveInfo { 2 | className = 'WebGLActiveInfo'; 3 | 4 | constructor({ 5 | type, name, size 6 | }) { 7 | this.type = type; 8 | this.name = name; 9 | this.size = size; 10 | } 11 | } -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/context-webgl/Buffer.js: -------------------------------------------------------------------------------- 1 | import {getTransferedObjectUUID} from './classUtils'; 2 | 3 | const name = 'WebGLBuffer'; 4 | 5 | function uuid(id) { 6 | return getTransferedObjectUUID(name, id); 7 | } 8 | 9 | export default class WebGLBuffer { 10 | className = name; 11 | 12 | constructor(id) { 13 | this.id = id; 14 | } 15 | 16 | static uuid = uuid; 17 | 18 | uuid() { 19 | return uuid(this.id); 20 | } 21 | } -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/context-webgl/Framebuffer.js: -------------------------------------------------------------------------------- 1 | import {getTransferedObjectUUID} from './classUtils'; 2 | 3 | const name = 'WebGLFrameBuffer'; 4 | 5 | function uuid(id) { 6 | return getTransferedObjectUUID(name, id); 7 | } 8 | 9 | export default class WebGLFramebuffer { 10 | className = name; 11 | 12 | constructor(id) { 13 | this.id = id; 14 | } 15 | 16 | static uuid = uuid; 17 | 18 | uuid() { 19 | return uuid(this.id); 20 | } 21 | } -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/context-webgl/GLtype.js: -------------------------------------------------------------------------------- 1 | const GLtype = {}; 2 | 3 | [ 4 | "GLbitfield", 5 | "GLboolean", 6 | "GLbyte", 7 | "GLclampf", 8 | "GLenum", 9 | "GLfloat", 10 | "GLint", 11 | "GLintptr", 12 | "GLsizei", 13 | "GLsizeiptr", 14 | "GLshort", 15 | "GLubyte", 16 | "GLuint", 17 | "GLushort" 18 | ].sort().map((typeName, i) => GLtype[typeName] = 1 >> (i + 1)); 19 | 20 | export default GLtype; 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/context-webgl/Program.js: -------------------------------------------------------------------------------- 1 | import {getTransferedObjectUUID} from './classUtils'; 2 | 3 | const name = 'WebGLProgram'; 4 | 5 | function uuid(id) { 6 | return getTransferedObjectUUID(name, id); 7 | } 8 | 9 | export default class WebGLProgram { 10 | className = name; 11 | 12 | constructor(id) { 13 | this.id = id; 14 | } 15 | 16 | static uuid = uuid; 17 | 18 | uuid() { 19 | return uuid(this.id); 20 | } 21 | } -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/context-webgl/Renderbuffer.js: -------------------------------------------------------------------------------- 1 | import {getTransferedObjectUUID} from './classUtils'; 2 | 3 | const name = 'WebGLRenderBuffer'; 4 | 5 | function uuid(id) { 6 | return getTransferedObjectUUID(name, id); 7 | } 8 | 9 | export default class WebGLRenderbuffer { 10 | className = name; 11 | 12 | constructor(id) { 13 | this.id = id; 14 | } 15 | 16 | static uuid = uuid; 17 | 18 | uuid() { 19 | return uuid(this.id); 20 | } 21 | } -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/context-webgl/Shader.js: -------------------------------------------------------------------------------- 1 | import {getTransferedObjectUUID} from './classUtils'; 2 | 3 | const name = 'WebGLShader'; 4 | 5 | function uuid(id) { 6 | return getTransferedObjectUUID(name, id); 7 | } 8 | 9 | export default class WebGLShader { 10 | className = name; 11 | 12 | constructor(id, type) { 13 | this.id = id; 14 | this.type = type; 15 | } 16 | 17 | static uuid = uuid; 18 | 19 | uuid() { 20 | return uuid(this.id); 21 | } 22 | } -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/context-webgl/ShaderPrecisionFormat.js: -------------------------------------------------------------------------------- 1 | export default class WebGLShaderPrecisionFormat { 2 | className = 'WebGLShaderPrecisionFormat'; 3 | 4 | constructor({ 5 | rangeMin, rangeMax, precision 6 | }) { 7 | this.rangeMin = rangeMin; 8 | this.rangeMax = rangeMax; 9 | this.precision = precision; 10 | } 11 | } -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/context-webgl/Texture.js: -------------------------------------------------------------------------------- 1 | import {getTransferedObjectUUID} from './classUtils'; 2 | 3 | const name = 'WebGLTexture'; 4 | 5 | function uuid(id) { 6 | return getTransferedObjectUUID(name, id); 7 | } 8 | 9 | export default class WebGLTexture { 10 | className = name; 11 | 12 | constructor(id, type) { 13 | this.id = id; 14 | this.type = type; 15 | } 16 | 17 | static uuid = uuid; 18 | 19 | uuid() { 20 | return uuid(this.id); 21 | } 22 | } -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/context-webgl/UniformLocation.js: -------------------------------------------------------------------------------- 1 | import {getTransferedObjectUUID} from './classUtils'; 2 | 3 | const name = 'WebGLUniformLocation'; 4 | 5 | function uuid(id) { 6 | return getTransferedObjectUUID(name, id); 7 | } 8 | 9 | export default class WebGLUniformLocation { 10 | className = name; 11 | 12 | constructor(id, type) { 13 | this.id = id; 14 | this.type = type; 15 | } 16 | 17 | static uuid = uuid; 18 | 19 | uuid() { 20 | return uuid(this.id); 21 | } 22 | } -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/context-webgl/classUtils.js: -------------------------------------------------------------------------------- 1 | export function getTransferedObjectUUID(name, id) { 2 | return `${name.toLowerCase()}-${id}`; 3 | } -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/env/canvas.js: -------------------------------------------------------------------------------- 1 | import GContext2D from '../context-2d/RenderingContext'; 2 | import GContextWebGL from '../context-webgl/RenderingContext'; 3 | 4 | export default class GCanvas { 5 | 6 | // static GBridge = null; 7 | 8 | id = null; 9 | 10 | _needRender = true; 11 | 12 | constructor(id, { disableAutoSwap }) { 13 | this.id = id; 14 | 15 | this._disableAutoSwap = disableAutoSwap; 16 | if (disableAutoSwap) { 17 | this._swapBuffers = () => { 18 | GCanvas.GBridge.render(this.id); 19 | } 20 | } 21 | } 22 | 23 | getContext(type) { 24 | 25 | let context = null; 26 | 27 | if (type.match(/webgl/i)) { 28 | context = new GContextWebGL(this); 29 | 30 | context.componentId = this.id; 31 | 32 | if (!this._disableAutoSwap) { 33 | const render = () => { 34 | if (this._needRender) { 35 | GCanvas.GBridge.render(this.id); 36 | this._needRender = false; 37 | } 38 | } 39 | setInterval(render, 16); 40 | } 41 | 42 | GCanvas.GBridge.callSetContextType(this.id, 1); // 0 for 2d; 1 for webgl 43 | } else if (type.match(/2d/i)) { 44 | context = new GContext2D(this); 45 | 46 | context.componentId = this.id; 47 | 48 | // const render = ( callback ) => { 49 | // 50 | // const commands = context._drawCommands; 51 | // context._drawCommands = ''; 52 | // 53 | // GCanvas.GBridge.render2d(this.id, commands, callback); 54 | // this._needRender = false; 55 | // } 56 | // //draw方法触发 57 | // context._flush = render; 58 | // //setInterval(render, 16); 59 | 60 | GCanvas.GBridge.callSetContextType(this.id, 0); 61 | } else { 62 | throw new Error('not supported context ' + type); 63 | } 64 | 65 | return context; 66 | 67 | } 68 | 69 | reset() { 70 | GCanvas.GBridge.callReset(this.id); 71 | } 72 | 73 | 74 | } -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/env/image.js: -------------------------------------------------------------------------------- 1 | let incId = 1; 2 | 3 | const noop = function () { }; 4 | 5 | class GImage { 6 | 7 | static GBridge = null; 8 | 9 | constructor() { 10 | this._id = incId++; 11 | this._width = 0; 12 | this._height = 0; 13 | this._src = undefined; 14 | this._onload = noop; 15 | this._onerror = noop; 16 | this.complete = false; 17 | } 18 | 19 | get width() { 20 | return this._width; 21 | } 22 | set width(v) { 23 | this._width = v; 24 | } 25 | 26 | get height() { 27 | return this._height; 28 | } 29 | 30 | set height(v) { 31 | this._height = v; 32 | } 33 | 34 | get src() { 35 | return this._src; 36 | } 37 | 38 | set src(v) { 39 | 40 | if (v.startsWith('//')) { 41 | v = 'http:' + v; 42 | } 43 | 44 | this._src = v; 45 | 46 | GImage.GBridge.perloadImage([this._src, this._id], (data) => { 47 | if (typeof data === 'string') { 48 | data = JSON.parse(data); 49 | } 50 | if (data.error) { 51 | var evt = { type: 'error', target: this }; 52 | this.onerror(evt); 53 | } else { 54 | this.complete = true; 55 | this.width = typeof data.width === 'number' ? data.width : 0; 56 | this.height = typeof data.height === 'number' ? data.height : 0; 57 | var evt = { type: 'load', target: this }; 58 | this.onload(evt); 59 | } 60 | }); 61 | } 62 | 63 | addEventListener(name, listener) { 64 | if (name === 'load') { 65 | this.onload = listener; 66 | } else if (name === 'error') { 67 | this.onerror = listener; 68 | } 69 | } 70 | 71 | removeEventListener(name, listener) { 72 | if (name === 'load') { 73 | this.onload = noop; 74 | } else if (name === 'error') { 75 | this.onerror = noop; 76 | } 77 | } 78 | 79 | get onload() { 80 | return this._onload; 81 | } 82 | 83 | set onload(v) { 84 | this._onload = v; 85 | } 86 | 87 | get onerror() { 88 | return this._onerror; 89 | } 90 | 91 | set onerror(v) { 92 | this._onerror = v; 93 | } 94 | } 95 | 96 | export default GImage; -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/env/tool.js: -------------------------------------------------------------------------------- 1 | 2 | export function ArrayBufferToBase64 (buffer) { 3 | var binary = ''; 4 | var bytes = new Uint8ClampedArray(buffer); 5 | for (var len = bytes.byteLength, i = 0; i < len; i++) { 6 | binary += String.fromCharCode(bytes[i]); 7 | } 8 | return btoa(binary); 9 | } 10 | 11 | export function Base64ToUint8ClampedArray(base64String) { 12 | const padding = '='.repeat((4 - base64String.length % 4) % 4); 13 | const base64 = (base64String + padding) 14 | .replace(/\-/g, '+') 15 | .replace(/_/g, '/'); 16 | 17 | const rawData = atob(base64); 18 | const outputArray = new Uint8ClampedArray(rawData.length); 19 | 20 | for (let i = 0; i < rawData.length; ++i) { 21 | outputArray[i] = rawData.charCodeAt(i); 22 | } 23 | return outputArray; 24 | } -------------------------------------------------------------------------------- /wechat-app/components/thorui-nvue/thor-circular-progress/gcanvas/index.js: -------------------------------------------------------------------------------- 1 | import GCanvas from './env/canvas'; 2 | import GImage from './env/image'; 3 | 4 | import GWebGLRenderingContext from './context-webgl/RenderingContext'; 5 | import GContext2D from './context-2d/RenderingContext'; 6 | 7 | import GBridgeWeex from './bridge/bridge-weex'; 8 | 9 | export let Image = GImage; 10 | 11 | export let WeexBridge = GBridgeWeex; 12 | 13 | export function enable(el, { 14 | bridge, 15 | debug, 16 | disableAutoSwap, 17 | disableComboCommands 18 | } = {}) { 19 | 20 | const GBridge = GImage.GBridge = GCanvas.GBridge = GWebGLRenderingContext.GBridge = GContext2D.GBridge = bridge; 21 | 22 | GBridge.callEnable(el.ref, [ 23 | 0, // renderMode: 0--RENDERMODE_WHEN_DIRTY, 1--RENDERMODE_CONTINUOUSLY 24 | -1, // hybridLayerType: 0--LAYER_TYPE_NONE 1--LAYER_TYPE_SOFTWARE 2--LAYER_TYPE_HARDWARE 25 | false, // supportScroll 26 | false, // newCanvasMode 27 | 1, // compatible 28 | 'white', // clearColor 29 | false // sameLevel: newCanvasMode = true && true => GCanvasView and Webview is same level 30 | ]); 31 | 32 | if (debug === true) { 33 | GBridge.callEnableDebug(); 34 | } 35 | if (disableComboCommands) { 36 | GBridge.callEnableDisableCombo(); 37 | } 38 | 39 | var canvas = new GCanvas(el.ref, { 40 | disableAutoSwap 41 | }); 42 | let pixelRatio = uni.getSystemInfoSync().pixelRatio; 43 | canvas.width = el.style.width * pixelRatio; 44 | canvas.height = el.style.height * pixelRatio; 45 | 46 | return canvas; 47 | }; 48 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-alert/tui-alert.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 60 | 61 | 135 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-badge/tui-badge.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 65 | 66 | 154 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-bottom-popup/tui-bottom-popup.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 50 | 51 | 97 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-divider/tui-divider.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 75 | 76 | 104 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-drawer/tui-drawer.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 45 | 46 | 99 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-dropdown-list/tui-dropdown-list.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 44 | 45 | 67 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-footer/tui-footer.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 58 | 59 | 122 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-grid-item/tui-grid-item.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 46 | 47 | 138 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-grid/tui-grid.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 19 | 20 | 45 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-image-group/tui-image-group.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 132 | 133 | 150 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-keyboard-input/tui-keyboard-input.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 40 | 41 | 74 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-list-view/tui-list-view.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 29 | 30 | 88 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-loading/tui-loading.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 19 | 20 | 79 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-no-data/tui-no-data.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 53 | 54 | 104 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-nomore/tui-nomore.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 36 | 37 | 115 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-time-axis/tui-time-axis.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 | 39 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-timeaxis-item/tui-timeaxis-item.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 27 | 28 | 51 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-toast/tui-toast.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 58 | 59 | 119 | -------------------------------------------------------------------------------- /wechat-app/components/thorui/tui-top-dropdown/tui-top-dropdown.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 58 | 59 | 96 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/README.md: -------------------------------------------------------------------------------- 1 | # uni-simple-router 2 | 3 | > 一个更为简洁的[Vue-router](https://router.vuejs.org/zh/),专为 [uni-app](https://uniapp.dcloud.io/) 量身打造 4 | 5 | ## 介绍 6 | 7 | `uni-simple-router` 是专为 [uni-app](https://uniapp.dcloud.io/) 打造的路由器。它与 [uni-app](https://uniapp.dcloud.io/) 核心深度集成,使使用 [uni-app](https://uniapp.dcloud.io/) 轻松构建单页应用程序变得轻而易举。功能包括: 8 | 9 | * `H5端` 能完全使用 `vue-router` 进行开发。 10 | 11 | * 模块化,基于组件的路由器配置。 12 | 13 | * 路由参数,查询,通配符。 14 | 15 | * `H5端` 查看由 `uni-simple-router` 过渡系统提供动力的过渡效果。 16 | 17 | * 更细粒度的导航控制。 18 | 19 | * `H端`自动控制活动的CSS类链接。 20 | 21 | * 通配小程序端、APP端、H5端。 22 | 23 | 24 | 开始使用 [查看文档](http://hhyang.cn),或 [使用示例](https://github.com/SilurianYang/uni-simple-router/tree/master/examples)(请参见下面的示例)。 25 | 26 | ## 问题 27 | 在提交问题的之前,请确保阅读 [“问题报告清单”](https://github.com/SilurianYang/uni-simple-router/issues/new?assignees=&labels=&template=bug_report.md&title=) 。不符合准则的问题可能会立即被解决。 28 | 29 | ## 贡献 30 | 提出拉取请求之前,请务必先阅读 [查看文档](http://hhyang.cn)(请参见下面的示例)。。 31 | 32 | ## 变更日志 33 | [发行说明](https://github.com/SilurianYang/uni-simple-router/releases) 中记录了每个发行版的详细信息更改。 34 | 35 | ## 特别感谢 36 | 37 | 特别感谢 [markrgba](https://github.com/markrgba) 一直以来对文档和相关测试的维护。 38 | 39 | ## 技术交流 40 | 41 | uni-app  插件 42 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/appRouter/uniNav.js: -------------------------------------------------------------------------------- 1 | import { methods, baseConfig, Global } from '../helpers/config'; 2 | import { noop, formatURLQuery } from '../helpers/util'; 3 | 4 | let stop = null; 5 | 6 | /** 7 | * @param {Object} finalRoute 格式化后的路由跳转规则 8 | * @param {Object} NAVTYPE 需要调用的跳转方法 9 | */ 10 | const uniPushTo = function (finalRoute, NAVTYPE) { 11 | return new Promise((resolve) => { 12 | const query = formatURLQuery(`?${finalRoute.uniRoute.query}`); 13 | const { APP } = baseConfig; 14 | const { url } = finalRoute.uniRoute; 15 | stop = setTimeout(() => { 16 | resolve(url); 17 | resolve = noop; // 执行完了就没了 确保不会被下一次执行 18 | Global.LockStatus = false; // 跳转完成解锁状态 19 | }, APP.switchPageOutTime); 20 | 21 | uni[methods[NAVTYPE]]({ 22 | url: url + query, 23 | ...finalRoute.route.animation, 24 | complete: () => { 25 | clearTimeout(stop); 26 | resolve(url); 27 | resolve = noop; // 执行完了就没了 确保不会被下一次执行 28 | Global.LockStatus = false; // 跳转完成解锁状态 29 | }, 30 | }, true); // 这里传递true 主要是兼容重写 uni.switchTab 31 | }); 32 | }; 33 | 34 | export default uniPushTo; 35 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/appletsRouter/appletsNav.js: -------------------------------------------------------------------------------- 1 | 2 | import { methods, Global } from '../helpers/config'; 3 | import { formatURLQuery } from '../helpers/util'; 4 | 5 | 6 | /** 7 | * @param {Object} finalRoute 格式化后的路由跳转规则 8 | * @param {Object} NAVTYPE 需要调用的跳转方法 9 | */ 10 | const appletsUniPushTo = function (finalRoute, NAVTYPE) { 11 | return new Promise((resolve) => { 12 | const query = formatURLQuery(`?${finalRoute.uniRoute.query}`); 13 | const { url } = finalRoute.uniRoute; 14 | uni[methods[NAVTYPE]]({ 15 | url: url + query, 16 | complete: () => { 17 | resolve(url); 18 | Global.LockStatus = false; // 跳转完成解锁状态 19 | }, 20 | }); 21 | }); 22 | }; 23 | export default appletsUniPushTo; 24 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/appletsRouter/init.js: -------------------------------------------------------------------------------- 1 | import { proxyLaunchHook } from './hooks'; 2 | 3 | /** 4 | * 开始初始化app端路由配置 5 | * 6 | * @param {Object} Router 当前Router对象 7 | * 8 | * this 为当前 page 对象 9 | */ 10 | const appletsInit = function () { 11 | proxyLaunchHook.call(this); 12 | }; 13 | export default appletsInit; 14 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/component/h5-dom.js: -------------------------------------------------------------------------------- 1 | const render = function (node) { 2 | if (typeof node == 'string') { // 是一个文本节点 3 | return document.createTextNode(node); 4 | } 5 | if (node instanceof HTMLElement) { 6 | return node; 7 | } 8 | // eslint-disable-next-line 9 | return createElement(node); 10 | }; 11 | /** 12 | * 根据标签及属性创建一个dom 13 | */ 14 | const createElement = function ({ 15 | tag, 16 | attrs, 17 | children, 18 | } = {}) { 19 | const $el = document.createElement(tag); 20 | // eslint-disable-next-line 21 | for (const [k, v] of Object.entries(attrs)) { 22 | $el.setAttribute(k, v); 23 | } 24 | // eslint-disable-next-line 25 | for (const item of children) { 26 | $el.appendChild(render(item)); 27 | } 28 | return $el; 29 | }; 30 | 31 | const html = createElement({ 32 | tag: 'div', 33 | attrs: { 34 | id: 'router-loadding', 35 | }, 36 | children: [ 37 | createElement({ 38 | tag: 'div', 39 | attrs: { 40 | class: 'loadding', 41 | }, 42 | children: [], 43 | }), 44 | ], 45 | }); 46 | /* eslint-disable */ 47 | const style = createElement({ 48 | tag: 'style', 49 | attrs: { 50 | id: 'HHYANG_style', 51 | }, 52 | children: [ 53 | ` 54 | body{padding:0;margin:0}#router-loadding{position:fixed;width:100%;height:3px;transition:all .05s;top:0;z-index:9999999999999999;}#router-loadding .loadding{position:fixed;top:0;height:3px;background-color:#47b14b;width:0;box-shadow:0 0 15px #4CAF50;transition:all .8s;border-top-right-radius:3px;border-bottom-right-radius:3px} 55 | `, 56 | ], 57 | }); 58 | 59 | const script = createElement({ 60 | tag: 'script', 61 | attrs: { 62 | id: 'HHYANG_script', 63 | }, 64 | children: [ 65 | ` 66 | var HHYANG_El=document.querySelector("#router-loadding .loadding"),HHYANG_Pel=document.querySelector("#router-loadding"),w=0,stop=null,WH=window.innerWidth,loop=function(){w=w>=WH-35?w+parseInt(5*Math.random()):w+parseInt(35*Math.random());HHYANG_El.style.cssText="width:"+w+"px";w>=WH&&clearInterval(stop)};window.startLodding=function(a){a=void 0===a?500:a;HHYANG_Pel.style.cssText="display: block;";HHYANG_El.style.cssText="transition: all 0.8s;";w=0;clearInterval(stop);stop=setInterval(function(){loop()},a)};window.stopLodding=function(a){a=void 0===a?200:a;clearInterval(stop);HHYANG_El.style.cssText="width:"+WH+"px;transition: all "+a/1E3+"s;";HHYANG_Pel.style.cssText="opacity: 0;transition: all "+a/1E3+"s;";setTimeout(function(){HHYANG_Pel.style.cssText="display: none;";HHYANG_El.style.cssText="width:0px";w=0},a)}; 67 | `, 68 | ], 69 | }); 70 | export const DOM = { 71 | style, 72 | html, 73 | script, 74 | }; 75 | /* eslint-enable */ 76 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/component/router-link.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/helpers/compile.js: -------------------------------------------------------------------------------- 1 | export const H5 = function (fn) { 2 | // #ifdef H5 3 | fn(); 4 | // #endif 5 | }; 6 | export const APP = function (fn) { 7 | // #ifdef APP-PLUS 8 | fn(); 9 | // #endif 10 | }; 11 | export const applets = function (fn) { 12 | // #ifdef MP 13 | fn(); 14 | // #endif 15 | }; 16 | export const notH5 = function (fn) { 17 | // #ifndef H5 18 | fn(); 19 | // #endif 20 | }; 21 | export const baiduApple = function (fn) { 22 | // #ifdef MP-BAIDU 23 | fn(); 24 | // #endif 25 | }; 26 | export const touTiao = function (fn) { 27 | // #ifdef MP-TOUTIAO 28 | fn(); 29 | // #endif 30 | }; 31 | export const mp = function (fn) { 32 | // #ifdef MP 33 | fn(); 34 | // #endif 35 | }; 36 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/helpers/mixins.js: -------------------------------------------------------------------------------- 1 | import { uniAppHook } from './config'; 2 | import H5init from '../vueRouter/init'; 3 | import { appInit, removeBackPressEvent, pageIsHeadBack } from '../appRouter/init'; 4 | import appletsInit from '../appletsRouter/init'; 5 | import { appPlatform } from './util'; 6 | import { proxyIndexHook } from '../appRouter/hooks'; 7 | import { appletsProxyIndexHook } from '../appletsRouter/hooks'; 8 | 9 | /** 10 | * 获取一些需要在各个平台混入的事件 11 | * @param {Object} Router 当前原始路由对象 12 | */ 13 | const getMixins = function (Router) { 14 | return { 15 | H5: { 16 | beforeCreate() { 17 | if (this.$options.router) { 18 | H5init(Router.$root, this.$options.router, this); 19 | } 20 | }, 21 | }, 22 | APP: { 23 | onLaunch() { 24 | uniAppHook.onLaunched = true; // 标志已经触发了 onLaunch 事件 25 | appInit.call(this, Router.$root); 26 | }, 27 | onLoad() { 28 | // 第一个页面 拦截所有生命周期 29 | if (uniAppHook.onLaunched && !uniAppHook.pageReady) { 30 | uniAppHook.onLaunched = false; 31 | proxyIndexHook.call(this, Router.$root); 32 | } 33 | removeBackPressEvent(this.$mp.page, this.$options); // 移除页面的onBackPress事件 34 | }, 35 | onBackPress(...args) { 36 | return pageIsHeadBack.call(Router.$root, this.$mp.page, this.$options, args); 37 | }, 38 | }, 39 | APPLETS: { 40 | onLaunch() { 41 | uniAppHook.onLaunched = true; // 标志已经触发了 onLaunch 事件 42 | appletsInit.call(this, Router.$root); 43 | }, 44 | onLoad() { 45 | if (uniAppHook.onLaunched && !uniAppHook.pageReady) { // 必须是第一个页面 46 | uniAppHook.onLaunched = false; 47 | appletsProxyIndexHook.call(this, Router.$root); 48 | } 49 | }, 50 | }, 51 | }; 52 | }; 53 | 54 | const initMixins = function (Vue, Router) { 55 | Vue.mixin({ 56 | ...getMixins(Router)[appPlatform(true)], 57 | }); 58 | }; 59 | 60 | export default initMixins; 61 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/helpers/warn.js: -------------------------------------------------------------------------------- 1 | import { Global } from './config'; 2 | 3 | 4 | const isLog = function (type, errText, enforce) { 5 | if (!enforce) { 6 | const dev = Global.Router.CONFIG.debugger; 7 | const isObject = dev.toString() === '[object Object]'; 8 | if (dev === false) { 9 | return false; 10 | } if (dev === false) { 11 | return false; 12 | } if (isObject) { 13 | if (dev[type] === false) { 14 | return false; 15 | } 16 | } 17 | } 18 | /* eslint no-console:"off" */ 19 | console[type](errText); 20 | }; 21 | export const err = function (errInfo, enforce = false) { 22 | isLog('error', errInfo, enforce); 23 | }; 24 | 25 | export const warn = function (errInfo, enforce = false) { 26 | isLog('warn', errInfo, enforce); 27 | }; 28 | 29 | export const log = function (errInfo, enforce = false) { 30 | isLog('log', errInfo, enforce); 31 | }; 32 | export const warnLock = function (errInfo) { 33 | console.warn(errInfo); 34 | }; 35 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/lifeCycle/hooks.js: -------------------------------------------------------------------------------- 1 | import { appPlatform, isH5 } from '../helpers/util'; 2 | 3 | // #ifdef H5 4 | import H5 from '../patch/h5-patch'; 5 | 6 | const H5PATCH = new H5(isH5()); 7 | // #endif 8 | 9 | export const registerHook = function (list, fn) { 10 | list.push(fn); 11 | return () => { 12 | const i = list.indexOf(fn); 13 | if (i > -1) list.splice(i, 1); 14 | }; 15 | }; 16 | /** 17 | * 注册全局Router生命钩子 18 | */ 19 | export const registerRouterHooks = function () { 20 | registerHook(this.lifeCycle.routerbeforeHooks, function () { 21 | return new Promise(async (resolve) => { 22 | this.CONFIG.routerBeforeEach(); // 触发暴露给开发者的生命钩子 23 | if (appPlatform(true) === 'H5') { 24 | H5PATCH.on('toogle', 'startLodding'); 25 | } 26 | return resolve(true); 27 | }); 28 | }); 29 | registerHook(this.lifeCycle.routerAfterHooks, function (res = {}) { 30 | if (res.H5Intercept !== true) { 31 | this.CONFIG.routerAfterEach(); // 触发暴露给开发者的生命钩子 32 | } 33 | if (appPlatform(true) === 'H5') { 34 | H5PATCH.on('toogle', 'stopLodding'); 35 | } 36 | return true; 37 | }); 38 | }; 39 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "uni-simple-router", 3 | "version": "1.5.5", 4 | "description": "> 一个更为简洁的[Vue-router](https://router.vuejs.org/zh/),专为 [uni-app](https://uniapp.dcloud.io/) 量身打造", 5 | "main": "index.js", 6 | "directories": { 7 | "example": "examples" 8 | }, 9 | "scripts": { 10 | "postinstall": "node -e \"console.log('\\x1B[32m \\x1B[1m','\\n 欢迎下载 uni-simple-router ↓↓↓↓ \\n\\n 注意事项:\\n 1: 编译为app端如果开启V3,请关闭fast启动模式 \\n 2: 多看文档,特别是‘快速上手’栏目。文档地址:http://hhyang.cn/ \\n 3: 不要再问路由表是否可以不配置两遍。问就是文档有!\\n 4: 有啥问题解决不了的加群:769241495 \\n 5: 任何时候你都可以在github上提出你的想法及问题,相信我很快会得到回应 \\n\\n showTime:\\n 1:开源不易,需要鼓励。去给 uni-simple-router 项目 点个 star 吧 \\n')\"" 11 | }, 12 | "dependencies": { 13 | "query-string": "^6.12.1" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/SilurianYang/uni-simple-router.git" 18 | }, 19 | "keywords": [ 20 | "router", 21 | "uni-app-router", 22 | "interceptor", 23 | "uni-app", 24 | "uniapp" 25 | ], 26 | "author": "hhyang", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/SilurianYang/uni-simple-router/issues" 30 | }, 31 | "homepage": "https://github.com/SilurianYang/uni-simple-router#readme", 32 | "types": "./types/index.d.ts" 33 | } -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/patch/app-patch.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 截止 1.3.5 版本 不做任何操作 3 | * @param {element} el dom节点 4 | */ 5 | const appMount = function (Vim) { 6 | Vim.$mount(); 7 | }; 8 | export default appMount; 9 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/patch/applets-patch.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * 截止 1.3.5 版本 不做任何操作 4 | * @param {element} el dom节点 5 | */ 6 | const appletsMount = function (Vim) { 7 | Vim.$mount(); 8 | }; 9 | 10 | export default appletsMount; 11 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/types/index.d.ts: -------------------------------------------------------------------------------- 1 | import {Component,PluginFunction,Location,Route,Animation,H5,APP,RouteConfig,RouterOptions} from './options' 2 | 3 | /** 4 | * 路由挂载点 5 | * @param {VueComponent } Vim vue实例对象 6 | * @param {dom} el dom节点选择器 7 | */ 8 | declare const RouterMount: (Vim: any, el: string | Element) => void; 9 | 10 | declare class Router { 11 | constructor(options:RouterOptions) 12 | /** 13 | * 当前的 Route 14 | */ 15 | get $Route():Route; 16 | /** 17 | * 获取 url 参数帮助类实例 18 | */ 19 | get $parseQuery():object; 20 | /** 21 | * 获取当前是否处于正在跳转的状态 22 | * H5 状态下始终为false 23 | */ 24 | get $lockStatus():boolean; 25 | 26 | /** 27 | * 动态设置拦截状态 28 | */ 29 | set $lockStatus(status:boolean); 30 | 31 | /**动态的导航到一个新 URL 保留浏览历史 32 | * navigateTo 33 | * @param {Object} rule 34 | */ 35 | push(rule: Location | string): void; 36 | 37 | /**动态的导航到一个新 URL 关闭当前页面,跳转到的某个页面。 38 | * redirectTo 39 | * @param {Object} rule 40 | */ 41 | replace(rule:Location | string):void; 42 | 43 | /**动态的导航到一个新 URL 关闭所有页面,打开到应用内的某个页面 44 | * reLaunch 45 | * @param {Object} rule 46 | */ 47 | replaceAll(rule:Location | string):void; 48 | 49 | /**动态的导航到一个新 url 关闭所有页面,打开到应用内的某个tab 50 | * @param {Object} rule 51 | */ 52 | pushTab(rule:Location | string) :void; 53 | 54 | /** 55 | * 返回到指定层级页面上 56 | */ 57 | back(backLayer?:number,delta?:Object):void 58 | 59 | /** 60 | * 获取当前页面下的 Route 信息 61 | * @param {Object} Vim 当前开发者可以传递一个 vue 组件对象 来获取当前下的 Route 信息 62 | */ 63 | getPageRoute(Vim?:Component) : Route 64 | 65 | /** 66 | * 注册的全局前置生命周期 67 | * @param hooks 注册的全局前置生命周期函数 68 | */ 69 | beforeEach(hooks:Function) : Function 70 | 71 | /** 72 | * 注册的全局后置生命周期 73 | * @param hooks 注册的全局后置生命周期函数 74 | */ 75 | afterEach(hooks:Function) : Function 76 | 77 | static install:PluginFunction 78 | } 79 | 80 | declare module "vue/types/vue" { 81 | interface Vue { 82 | $Router: Router; 83 | $Route: Route; 84 | } 85 | } 86 | 87 | export default Router; 88 | 89 | export { 90 | RouterMount, 91 | Location, 92 | Route, 93 | Animation, 94 | H5, 95 | APP, 96 | RouteConfig, 97 | RouterOptions 98 | } -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/vueRouter/base.js: -------------------------------------------------------------------------------- 1 | export const builtIn = [{ 2 | path: '/preview-image', 3 | name: 'previewImage', 4 | component: { 5 | render: () => {}, 6 | }, 7 | }, { 8 | path: '/choose-location', 9 | name: 'chooseLocation', 10 | component: { 11 | render: () => {}, 12 | }, 13 | }, { 14 | path: '/open-location', 15 | name: 'openLocation', 16 | component: { 17 | render: () => {}, 18 | }, 19 | }]; // uni-app内置路由 20 | export const vuelifeHooks = { // vueRouter的原始生命周期 21 | beforeHooks: [], 22 | afterHooks: [], 23 | }; 24 | export const vueMount = [];// 使用内部对象保留实例化下的appVue,并使用Router进行挂载触发第一次路由钩子 25 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/vueRouter/extends/myArray.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 实现一个继承的 数组类 代理掉 vue-router 生命钩子的数据 3 | */ 4 | class MyArray extends Array { 5 | constructor(Router, vueOldHooks, hookFun) { 6 | super(); 7 | this.Router = Router; 8 | this.vueOldHooks = vueOldHooks; 9 | this.hookFun = hookFun; 10 | } 11 | 12 | push(v) { 13 | this.vueOldHooks.splice(0, 1, v);// 把vue-router路由生命钩子保存起来 14 | this[this.length] = (to, from, next) => { 15 | this.hookFun(to, from, next, this.Router); 16 | }; 17 | } 18 | } 19 | 20 | export default MyArray; 21 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/vueRouter/init.js: -------------------------------------------------------------------------------- 1 | import { afterHooks, beforeHooks, registerRouter } from './concat'; 2 | import { fromatRoutes } from './util'; 3 | import { err, warn } from '../helpers/warn'; 4 | import { proxyEachHooks } from './proxy/proxy'; 5 | /** 6 | * 重写掉H5端 uni-app原始存在的bug 7 | * 8 | * @param {Object} Router 9 | */ 10 | const rewriteUniFun = function (Router) { 11 | if (Router.CONFIG.h5.rewriteFun === false) { // 不需要重写 12 | return false; 13 | } 14 | uni.reLaunch = function ({ 15 | url, 16 | }) { 17 | if (url === '/') { 18 | warn('H5端 uni.reLaunch(\'/\')时 默认被重写了! 你可以使用 this.$Router.replaceAll() 或者 uni.reLaunch(\'/\'?xxx)'); 19 | // eslint-disable-next-line 20 | if (history.length > 1) { // 只有在有历史记录的时候才返回 不然直接返回首页 21 | return Router.back(); 22 | } 23 | return Router.replaceAll('/'); 24 | } 25 | const path = url.match(/^[^?]+|(\/)/)[0]; 26 | try { 27 | const query = {}; 28 | url.replace(/([^?&]+)=([^?&]+)/g, (s, v, k) => { 29 | query[v] = decodeURIComponent(k); 30 | return `${k}=${v}`; 31 | }); 32 | Router.replaceAll({ 33 | path, 34 | query, 35 | }); 36 | } catch (e) { 37 | err(`${url}解析失败了.... 试试 this.$Router.replaceAll() 吧`); 38 | } 39 | }; 40 | uni.navigateBack = function (delta) { 41 | let backLayer = delta; 42 | if (delta.constructor === Object) { // 这种可能就只是uni-app自带的返回按钮,还有种可能就是开发者另类传递的 43 | backLayer = 1; 44 | } 45 | Router.back(backLayer, delta); 46 | }; 47 | }; 48 | /** 49 | * 拦截并注册vueRouter中的生命钩子,路由表解析 50 | * @param {Object} Router 51 | * @param {vueRouter} vueRouter 52 | */ 53 | const init = function (Router, vueRouter) { 54 | const CONFIG = Router.CONFIG.h5; 55 | vueRouter.afterHooks = proxyEachHooks(Router, 'afterHooks', afterHooks); 56 | vueRouter.beforeHooks = proxyEachHooks(Router, 'beforeHooks', beforeHooks); 57 | const objVueRoutes = fromatRoutes(vueRouter.options.routes, false, {}); // 返回一个格式化好的routes 键值对的形式 58 | const objSelfRoutes = fromatRoutes(Router.CONFIG.routes, true, CONFIG); 59 | Router.vueRoutes = objVueRoutes; // 挂载vue-routes到当前的路由下 60 | Router.selfRoutes = { 61 | ...Router.selfRoutes || {}, 62 | ...objSelfRoutes, 63 | }; // 挂载self-routes到当前路由下 64 | Router.$route = vueRouter; // 挂载vue-router到$route 65 | rewriteUniFun(Router); // 重新掉uniapp上的一些有异常的方法 66 | registerRouter(Router, vueRouter, CONFIG.vueRouterDev); 67 | }; 68 | export default init; 69 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/vueRouter/proxy/proxy.js: -------------------------------------------------------------------------------- 1 | import { beforeEnterHooks } from '../concat'; 2 | import { vuelifeHooks } from '../base'; 3 | import MyArray from '../extends/myArray'; 4 | 5 | /** 6 | * 通过 Object.defineProperty 代理一个对象主要是拦截beforeEnter 生命钩子 7 | * @param {Router} Router 路由实例对象 8 | * @param {Object} BeProxy 需要代理的路由表 9 | */ 10 | export const proxyBeforeEnter = function (Router, BeProxy) { 11 | const proxyDc = Object.create(null);// 创建没有继承的属性 12 | const BeProxyKeys = Object.keys(BeProxy); 13 | for (let i = 0; i < BeProxyKeys.length; i += 1) { 14 | const key = BeProxyKeys[i]; 15 | Object.defineProperty(proxyDc, key, { 16 | enumerable: true, 17 | configurable: true, 18 | get() { 19 | const value = BeProxy[key]; 20 | if (key == 'beforeEnter' && value !== undefined) { 21 | return (to, from, next) => { 22 | beforeEnterHooks(to, from, next, value, Router); 23 | }; 24 | } 25 | return value; 26 | }, 27 | set(v) { 28 | BeProxy[key] = v; 29 | }, 30 | }); 31 | } 32 | return proxyDc; 33 | }; 34 | 35 | /** 36 | * 在uni-app没有注入生命周期时先直接代理相关生命周期数组 37 | * @param {Object} Router 38 | * @param {Object} key 39 | * @param {Funtion} hookFun 40 | */ 41 | export const proxyEachHooks = function (Router, key, hookFun) { 42 | const vueOldHooks = vuelifeHooks[key]; 43 | return new MyArray(Router, vueOldHooks, hookFun); 44 | }; 45 | -------------------------------------------------------------------------------- /wechat-app/components/uni-simple-router/vueRouter/routerNav.js: -------------------------------------------------------------------------------- 1 | import { err } from '../helpers/warn'; 2 | import { formatUserRule, strPathToObjPath } from './util'; 3 | 4 | /** 5 | * @param {Object} replace vue-router的跳转方式 6 | * @param {Object} rule 需要跳转到的路由匹配规则 7 | * @param {Object} type 对应的官方跳转模式 8 | * 9 | * this 为当前 Router 实例 10 | */ 11 | const H5PushTo = function (replace, rule, type) { 12 | if (this.$route == null) { 13 | return err('h5端路由为就绪,请检查调用代码'); 14 | } 15 | rule = formatUserRule(rule, this.selfRoutes, this.CONFIG); 16 | const objPath = strPathToObjPath(rule); 17 | objPath.type = type; 18 | this.$route[replace](objPath); 19 | }; 20 | 21 | export default H5PushTo; 22 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseAudio.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 27 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseImg.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 95 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseTable.vue: -------------------------------------------------------------------------------- 1 | 6 | 53 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseTemplate0.vue: -------------------------------------------------------------------------------- 1 | 56 | 57 | 104 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseTemplate1.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 89 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseTemplate10.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 89 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseTemplate11.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 87 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseTemplate2.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 89 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseTemplate3.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 89 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseTemplate4.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 89 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseTemplate5.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 89 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseTemplate6.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 89 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseTemplate7.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 89 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseTemplate8.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 89 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseTemplate9.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 89 | -------------------------------------------------------------------------------- /wechat-app/components/uni/uParse/src/components/wxParseVideo.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 16 | -------------------------------------------------------------------------------- /wechat-app/components/views/app-plus/tui-share/tui-share.nvue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 52 | 53 | 131 | -------------------------------------------------------------------------------- /wechat-app/components/views/t-linkage/t-linkage.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 98 | 99 | -------------------------------------------------------------------------------- /wechat-app/components/views/t-rt-popup/t-rt-popup.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 82 | 83 | 124 | -------------------------------------------------------------------------------- /wechat-app/config.js: -------------------------------------------------------------------------------- 1 | // 判断开发环境和生产环境 2 | let BASE_URL = '' 3 | let BURY_URL = '' 4 | if (process.env.NODE_ENV === 'development') { 5 | BASE_URL = 'http://127.0.0.1:8080' //dev 6 | BURY_URL = 'http://39.105.46.235:8080' //测试使用服务地址 7 | } else { 8 | // 生产环境,这里用我自己的服务器做演示 9 | BASE_URL = 'http://39.105.46.235:8080' //prod 10 | BURY_URL = 'http://127.0.0.1:8080' 11 | } 12 | 13 | const config = { 14 | BASE_URL: BASE_URL, 15 | BURY_URL: BURY_URL 16 | } 17 | 18 | export { 19 | config 20 | } 21 | -------------------------------------------------------------------------------- /wechat-app/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App' 3 | import store from './store' 4 | import router from './router' 5 | import '@/permission.js' 6 | 7 | Vue.config.productionTip = false 8 | 9 | Vue.prototype.$eventHub = Vue.prototype.$eventHub || new Vue() 10 | Vue.prototype.$store = store 11 | App.mpType = 'app' 12 | 13 | const app = new Vue({ 14 | store, 15 | router, 16 | ...App 17 | }) 18 | app.$mount() -------------------------------------------------------------------------------- /wechat-app/pages/common/about/about.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 48 | 49 | 76 | -------------------------------------------------------------------------------- /wechat-app/pages/common/github/github.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 20 | 21 | 24 | -------------------------------------------------------------------------------- /wechat-app/pages/tabbar/extend/extend.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 16 | 17 | 32 | -------------------------------------------------------------------------------- /wechat-app/permission.js: -------------------------------------------------------------------------------- 1 | import router from './router' 2 | import store from './store' 3 | import { 4 | getToken 5 | } from '@/utils/auth.js' 6 | 7 | 8 | // 白名单 9 | const whiteList = ['login'] 10 | 11 | /** 12 | * 路由守卫 13 | */ 14 | router.beforeEach(async (to, from, next) => { 15 | const hasToken = getToken() 16 | if (hasToken) { 17 | if (to.name === 'login') { 18 | next({ 19 | name: 'login' 20 | }) 21 | } else { 22 | try { 23 | await store.dispatch('user/getInfo') 24 | next() 25 | } catch (error) { 26 | await store.dispatch('user/resetToken') 27 | next({ 28 | name: 'login' 29 | }) 30 | } 31 | } 32 | next({ 33 | name: 'login' 34 | }) 35 | } else { 36 | /** 37 | * 实现强制登录 38 | */ 39 | 40 | // has no token 41 | if (whiteList.indexOf(to.name) !== -1) { 42 | next() 43 | } else { 44 | // 如果无Token访问whiteList之外的页面都强制路由到login页面 45 | next({ 46 | name: 'login', 47 | NAVTYPE: 'replaceAll' 48 | }) 49 | } 50 | } 51 | }) 52 | -------------------------------------------------------------------------------- /wechat-app/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from '@/components/uni-simple-router/index.js' 3 | Vue.use(Router) 4 | 5 | const router = new Router({ 6 | routes: [{ 7 | //注意:path必须跟pages.json中的地址对应,最前面别忘了加'/'哦 8 | path: '/pages/tabbar/index/index', 9 | name: 'index', 10 | meta: { 11 | title: '首页', 12 | }, 13 | }, 14 | { 15 | path: '/pages/tabbar/extend/extend', 16 | name: 'extend', 17 | meta: { 18 | title: '教学', 19 | }, 20 | }, 21 | { 22 | path: '/pages/tabbar/my/my', 23 | name: 'my', 24 | meta: { 25 | title: '我的', 26 | }, 27 | }, 28 | { 29 | path: '/pages/common/info/info', 30 | name: 'info', 31 | meta: { 32 | title: '账户信息', 33 | }, 34 | }, 35 | { 36 | path: '/pages/common/github/github', 37 | name: 'github', 38 | meta: { 39 | title: '账户信息', 40 | }, 41 | }, 42 | { 43 | path: '/pages/common/login/login', 44 | name: 'login', 45 | meta: { 46 | title: '登录', 47 | }, 48 | }, 49 | { 50 | path: '/pages/common/about/about', 51 | name: 'about', 52 | meta: { 53 | title: '关于', 54 | }, 55 | }, 56 | ] 57 | }); 58 | export default router 59 | -------------------------------------------------------------------------------- /wechat-app/static/fonts/thorui.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/fonts/thorui.ttf -------------------------------------------------------------------------------- /wechat-app/static/images/fab/fab_about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/fab/fab_about.png -------------------------------------------------------------------------------- /wechat-app/static/images/fab/fab_reward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/fab/fab_reward.png -------------------------------------------------------------------------------- /wechat-app/static/images/fab/fab_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/fab/fab_share.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/basic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/basic.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/cancle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/cancle.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/canvas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/canvas.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/class.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/drawer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/drawer.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/home_icon_choose_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/home_icon_choose_3x.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/icon_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/icon_down.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/icon_next_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/icon_next_3x.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/icon_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/icon_right.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/index.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/map.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/nav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/nav.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/refresh.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/search.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/swipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/swipe.png -------------------------------------------------------------------------------- /wechat-app/static/images/index/template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/index/template.png -------------------------------------------------------------------------------- /wechat-app/static/images/my/call.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/my/call.png -------------------------------------------------------------------------------- /wechat-app/static/images/my/feedback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/my/feedback.png -------------------------------------------------------------------------------- /wechat-app/static/images/my/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/my/github.png -------------------------------------------------------------------------------- /wechat-app/static/images/my/go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/my/go.png -------------------------------------------------------------------------------- /wechat-app/static/images/my/icon_out_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/my/icon_out_3x.png -------------------------------------------------------------------------------- /wechat-app/static/images/my/log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/my/log.png -------------------------------------------------------------------------------- /wechat-app/static/images/my/mine_bg_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/my/mine_bg_3x.png -------------------------------------------------------------------------------- /wechat-app/static/images/my/mine_def_touxiang_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/my/mine_def_touxiang_3x.png -------------------------------------------------------------------------------- /wechat-app/static/images/my/mine_icon_bianji_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/my/mine_icon_bianji_3x.png -------------------------------------------------------------------------------- /wechat-app/static/images/my/mine_icon_chongdian_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/my/mine_icon_chongdian_3x.png -------------------------------------------------------------------------------- /wechat-app/static/images/my/mine_icon_jiayouzhan_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/my/mine_icon_jiayouzhan_3x.png -------------------------------------------------------------------------------- /wechat-app/static/images/my/mine_icon_tingche_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/my/mine_icon_tingche_3x.png -------------------------------------------------------------------------------- /wechat-app/static/images/my/reward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/my/reward.png -------------------------------------------------------------------------------- /wechat-app/static/images/share/icon_moments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/share/icon_moments.png -------------------------------------------------------------------------------- /wechat-app/static/images/share/icon_qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/share/icon_qq.png -------------------------------------------------------------------------------- /wechat-app/static/images/share/icon_sina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/share/icon_sina.png -------------------------------------------------------------------------------- /wechat-app/static/images/share/icon_wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/share/icon_wechat.png -------------------------------------------------------------------------------- /wechat-app/static/images/tabbar/code_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/tabbar/code_active.png -------------------------------------------------------------------------------- /wechat-app/static/images/tabbar/code_gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/tabbar/code_gray.png -------------------------------------------------------------------------------- /wechat-app/static/images/tabbar/extend_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/tabbar/extend_active.png -------------------------------------------------------------------------------- /wechat-app/static/images/tabbar/extend_gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/tabbar/extend_gray.png -------------------------------------------------------------------------------- /wechat-app/static/images/tabbar/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/tabbar/home.png -------------------------------------------------------------------------------- /wechat-app/static/images/tabbar/home_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/tabbar/home_fill.png -------------------------------------------------------------------------------- /wechat-app/static/images/tabbar/people.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/tabbar/people.png -------------------------------------------------------------------------------- /wechat-app/static/images/tabbar/people_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/tabbar/people_fill.png -------------------------------------------------------------------------------- /wechat-app/static/images/tabbar/release.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/tabbar/release.png -------------------------------------------------------------------------------- /wechat-app/static/images/toast/check-circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/toast/check-circle.png -------------------------------------------------------------------------------- /wechat-app/static/images/toast/fail-circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/toast/fail-circle.png -------------------------------------------------------------------------------- /wechat-app/static/images/toast/img_nodata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/toast/img_nodata.png -------------------------------------------------------------------------------- /wechat-app/static/images/toast/img_noorder_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/toast/img_noorder_3x.png -------------------------------------------------------------------------------- /wechat-app/static/images/toast/info-circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TyCoding/wechat-template/ab99cbfe9acae7f86de1aef5b2af69cfc792a62f/wechat-app/static/images/toast/info-circle.png -------------------------------------------------------------------------------- /wechat-app/store/getters.js: -------------------------------------------------------------------------------- 1 | const getters = { 2 | token: state => state.user.token, 3 | avatar: state => state.user.avatar, 4 | name: state => state.user.name 5 | } 6 | export default getters -------------------------------------------------------------------------------- /wechat-app/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import getters from './getters' 4 | import user from './modules/user' 5 | 6 | Vue.use(Vuex) 7 | 8 | const store = new Vuex.Store({ 9 | modules: { 10 | user 11 | }, 12 | getters 13 | }) 14 | 15 | export default store -------------------------------------------------------------------------------- /wechat-app/store/modules/user.js: -------------------------------------------------------------------------------- 1 | import { 2 | login, 3 | logout, 4 | getInfo 5 | } from '@/api/user.js' 6 | import { 7 | getToken, 8 | setToken, 9 | removeToken 10 | } from '@/utils/auth' 11 | 12 | const state = { 13 | token: getToken(), 14 | name: '', 15 | avatar: '' 16 | } 17 | 18 | const mutations = { 19 | SET_TOKEN: (state, token) => { 20 | state.token = token 21 | }, 22 | SET_NAME: (state, name) => { 23 | state.name = name 24 | }, 25 | SET_AVATAR: (state, avatar) => { 26 | state.avatar = avatar 27 | } 28 | } 29 | 30 | const actions = { 31 | // user login 32 | login({ 33 | commit 34 | }, userInfo) { 35 | const { 36 | username, 37 | password 38 | } = userInfo 39 | return new Promise((resolve, reject) => { 40 | login({ 41 | username: username, 42 | password: password 43 | }).then(res => { 44 | if (res.code == 200 && res.data != null) { 45 | 46 | } 47 | commit('SET_TOKEN', res.data.token) 48 | commit('SET_NAME', res.data.user.username) 49 | commit('SET_AVATAR', res.data.user.avatar) 50 | setToken(res.data.token) 51 | resolve() 52 | }).catch(error => { 53 | reject(error) 54 | }) 55 | }) 56 | }, 57 | 58 | // get user info 59 | getInfo({ 60 | commit, 61 | state 62 | }) { 63 | return new Promise((resolve, reject) => { 64 | getInfo().then(response => { 65 | const { 66 | data 67 | } = response 68 | 69 | if (!data) { 70 | reject('Verification failed, please Login again.') 71 | } 72 | 73 | commit('SET_NAME', data.user.username) 74 | commit('SET_AVATAR', data.user.avatar) 75 | resolve(data) 76 | }).catch(error => { 77 | reject(error) 78 | }) 79 | }) 80 | }, 81 | 82 | // user logout 83 | logout({ 84 | commit, 85 | state 86 | }) { 87 | return new Promise((resolve, reject) => { 88 | logout().then(() => { 89 | commit('SET_TOKEN', '') 90 | commit('SET_NAME', '') 91 | commit('SET_AVATAR', '') 92 | removeToken() 93 | resolve() 94 | }).catch(error => { 95 | reject(error) 96 | }) 97 | }) 98 | }, 99 | 100 | // remove token 101 | resetToken({ 102 | commit 103 | }) { 104 | return new Promise(resolve => { 105 | commit('SET_TOKEN', '') 106 | removeToken() 107 | resolve() 108 | }) 109 | } 110 | } 111 | 112 | export default { 113 | namespaced: true, 114 | state, 115 | mutations, 116 | actions 117 | } 118 | -------------------------------------------------------------------------------- /wechat-app/utils/auth.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 操作Token 3 | */ 4 | 5 | const TokenKey = "app_key" 6 | 7 | export function getToken() { 8 | return uni.getStorageSync(TokenKey) 9 | } 10 | 11 | export function setToken(token) { 12 | return uni.setStorageSync(TokenKey, token) 13 | } 14 | 15 | export function removeToken() { 16 | return uni.removeStorageSync(TokenKey) 17 | } 18 | -------------------------------------------------------------------------------- /wechat-app/utils/request.js: -------------------------------------------------------------------------------- 1 | import { 2 | config 3 | } from '@/config.js' 4 | import { 5 | getToken 6 | } from '@/utils/auth.js' 7 | import store from '@/store' 8 | import Request from '@/components/luch-request/index.js' 9 | const http = new Request(); 10 | 11 | // 全局配置 12 | // http.config.baseURL = config.BASE_URL 13 | http.config.baseURL = config.BURY_URL //测试使用服务地址 14 | 15 | // request interceptor 16 | http.interceptors.request.use(config => { 17 | uni.showLoading({ 18 | mask: true, 19 | title: 'Loading...' 20 | }) 21 | if (store.getters.token) { 22 | // if store has token 23 | // set request header 24 | config.header['Authorization'] = getToken() 25 | } 26 | 27 | return config; 28 | }, error => { 29 | console.log(error) 30 | uni.hideLoading() 31 | tui.toast("网络不给力,请稍后再试~") 32 | return Promise.reject(error) 33 | }) 34 | 35 | // response interceptor 36 | http.interceptors.response.use(response => { 37 | let res = response.data 38 | uni.hideLoading() 39 | if (res.code == 401) { 40 | uni.clearStorageSync() 41 | uni.showModal({ 42 | title: '提示', 43 | content: "登录信息已失效,请重新登录", 44 | showCancel: true, 45 | cancelColor: "#555", 46 | confirmColor: "#5677fc", 47 | confirmText: "登录", 48 | success(res) { 49 | if (res.confirm) { 50 | uni.redirectTo({ 51 | url: '/pages/common/login/login' 52 | }) 53 | } else { 54 | callback(false) 55 | } 56 | } 57 | }) 58 | 59 | } else if (res.code != 200) { 60 | uni.showToast({ 61 | title: res.msg, 62 | icon: 'none', 63 | duration: 2000 64 | }) 65 | } 66 | return res 67 | }, error => { 68 | console.log(error) 69 | uni.hideLoading() 70 | uni.showToast({ 71 | title: '网络连接异常,请稍后再试~', 72 | icon: 'none', 73 | duration: 2000 74 | }) 75 | return Promise.reject(error) 76 | }) 77 | 78 | export default http 79 | -------------------------------------------------------------------------------- /wechat-app/utils/util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 数据处理 3 | * @author echo. 4 | * @version 1.5.0 5 | **/ 6 | const utils = { 7 | //去空格 8 | trim: function(value) { 9 | return value.replace(/(^\s*)|(\s*$)/g, ""); 10 | }, 11 | //内容替换 12 | replaceAll: function(text, repstr, newstr) { 13 | return text.replace(new RegExp(repstr, "gm"), newstr); 14 | }, 15 | //格式化手机号码 16 | formatNumber: function(num) { 17 | return num.length === 11 ? num.replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2') : num; 18 | }, 19 | //金额格式化 20 | rmoney: function(money) { 21 | return parseFloat(money).toFixed(2).toString().split('').reverse().join('').replace(/(\d{3})/g, '$1,').replace( 22 | /\,$/, '').split('').reverse().join(''); 23 | }, 24 | //日期格式化 25 | formatDate: function(formatStr, fdate) { 26 | if (fdate) { 27 | if (~fdate.indexOf('.')) { 28 | fdate = fdate.substring(0, fdate.indexOf('.')); 29 | } 30 | fdate = fdate.toString().replace('T', ' ').replace(/\-/g, '/'); 31 | var fTime, fStr = 'ymdhis'; 32 | if (!formatStr) 33 | formatStr = "y-m-d h:i:s"; 34 | if (fdate) 35 | fTime = new Date(fdate); 36 | else 37 | fTime = new Date(); 38 | var month = fTime.getMonth() + 1; 39 | var day = fTime.getDate(); 40 | var hours = fTime.getHours(); 41 | var minu = fTime.getMinutes(); 42 | var second = fTime.getSeconds(); 43 | month = month < 10 ? '0' + month : month; 44 | day = day < 10 ? '0' + day : day; 45 | hours = hours < 10 ? ('0' + hours) : hours; 46 | minu = minu < 10 ? '0' + minu : minu; 47 | second = second < 10 ? '0' + second : second; 48 | var formatArr = [ 49 | fTime.getFullYear().toString(), 50 | month.toString(), 51 | day.toString(), 52 | hours.toString(), 53 | minu.toString(), 54 | second.toString() 55 | ] 56 | for (var i = 0; i < formatArr.length; i++) { 57 | formatStr = formatStr.replace(fStr.charAt(i), formatArr[i]); 58 | } 59 | return formatStr; 60 | } else { 61 | return ""; 62 | } 63 | } 64 | } 65 | 66 | module.exports = { 67 | trim: utils.trim, 68 | replaceAll: utils.replaceAll, 69 | formatNumber: utils.formatNumber, 70 | rmoney: utils.rmoney, 71 | formatDate: utils.formatDate 72 | } 73 | --------------------------------------------------------------------------------