# zhty **Repository Path**: lumingbao/zhty ## Basic Information - **Project Name**: zhty - **Description**: 智慧体育 - **Primary Language**: NodeJS - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 13 - **Forks**: 7 - **Created**: 2019-08-06 - **Last Updated**: 2025-02-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # zhty #### 介绍 1. 智慧体育小程序。 2. 主要实现了跑步过程中对时间、跑步路径、跑步路程、消耗卡路里的计算。 3. 使用了加速度计传感器,简单的判断了手机处于静止还是运动状态。 4. 界面参考了Keep等跑步软件。 5. 实现了微信小程序对微信运动步数的读取,读取微信运动步数的java后端代码贴在了最后。 6. 实现了主要功能,细节上可能存在不足,代码也写得比较乱,请谅解。 #### 软件架构 1. VUE 2. [uni-app](https://uniapp.dcloud.io/) 3. [ColorUI](https://www.color-ui.com/) #### 使用说明 1. 使用HBuilderX做为开发工具。 #### 最终效果 **首页** ![输入图片说明](https://images.gitee.com/uploads/images/2019/0806/145730_146a93a9_537008.jpeg "首页.jpg") **个人中心未登录** ![输入图片说明](https://images.gitee.com/uploads/images/2019/0806/145847_45d452e9_537008.jpeg "个人中心未登录.jpg") **个人中心已登陆** ![输入图片说明](https://images.gitee.com/uploads/images/2019/0806/150015_776c26be_537008.jpeg "个人中心已登陆.jpg") **登陆引导** ![输入图片说明](https://images.gitee.com/uploads/images/2019/0806/150039_8fe55fdf_537008.jpeg "登陆引导.jpg") **授权** ![输入图片说明](https://images.gitee.com/uploads/images/2019/0806/150103_3aabf503_537008.jpeg "登陆.jpg") **跑步中** ![输入图片说明](https://images.gitee.com/uploads/images/2019/0806/150133_2c81737b_537008.jpeg "跑步中.jpg") **跑步暂停** ![输入图片说明](https://images.gitee.com/uploads/images/2019/0806/150214_bfbc22ee_537008.jpeg "跑步暂停.jpg") **跑步结束** ![输入图片说明](https://images.gitee.com/uploads/images/2019/0806/150231_35c125ba_537008.jpeg "跑步结束.jpg") **跑步记录** ![输入图片说明](https://images.gitee.com/uploads/images/2019/0806/150252_7197cee8_537008.jpeg "跑步记录.jpg") #### 微信运动后端JAVA代码 ``` package com.fsd.api; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.fsd.context.Request; import com.fsd.context.ResBody; import com.fsd.context.annotation.Authentication; import com.fsd.util.crypto.AES; import com.fsd.weixin.common.HttpClient; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletResponse; import java.util.List; import java.util.Map; /** * @Description * @Author 芦明宝 * @Date 2019-07-26 9:03 * @Version 1.0 */ @Controller @RequestMapping public class ZhtyApiController { /** * 获得微信openid * @param request * @param response * @param code * @return */ @Authentication(anonymous = true) @ResponseBody @RequestMapping("/zhty/api/console/getOpenId.htm") public ResBody getOpenId(Request request, HttpServletResponse response, String code) { String url = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code="+ code +"&grant_type=authorization_code"; url = url.replace("APPID", "***"); url = url.replace("SECRET", "***"); String returnJson = HttpClient.httpsRequest(url, HttpClient.POST, null); JSONObject json = JSON.parseObject(returnJson); return ResBody.success(json); } /** * 微信运动解密 * @param request * @param response * @param openid * @param session_key * @param encryptedData * @param iv * @return */ @Authentication(anonymous = true) @ResponseBody @RequestMapping("/zhty/api/console/decrypt.htm") public ResBody decrypt(Request request, HttpServletResponse response, String openid, String session_key, String encryptedData, String iv) { List> list = null; try { AES aes = new AES(); byte[] resultByte = aes.decrypt(encryptedData, session_key, iv); if(null != resultByte && resultByte.length > 0){ String userInfo = new String(resultByte, "UTF8"); //将微信运动的数据,转换为list JSONObject userinfo = JSONObject.parseObject(userInfo); String stepInfoList = userinfo.getString("stepInfoList"); Gson gson = new Gson(); list = gson.fromJson(stepInfoList, new TypeToken>>() {}.getType()); } } catch (Exception e) { e.printStackTrace(); } return ResBody.success(list); } } package com.fsd.util.crypto; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.Security; import java.util.Arrays; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; import org.bouncycastle.jce.provider.BouncyCastleProvider; /** * AES加密 */ public class AES { // 算法名称 final String KEY_ALGORITHM = "AES"; // 加解密算法/模式/填充方式 final String algorithmStr = "AES/CBC/PKCS7Padding"; // private Key key; private Cipher cipher; public void init(byte[] keyBytes) { // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要 int base = 16; if (keyBytes.length % base != 0) { int groups = keyBytes.length / base + (keyBytes.length % base != 0 ? 1 : 0); byte[] temp = new byte[groups * base]; Arrays.fill(temp, (byte) 0); System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length); keyBytes = temp; } // 初始化 Security.addProvider(new BouncyCastleProvider()); // 转化成JAVA的密钥格式 key = new SecretKeySpec(keyBytes, KEY_ALGORITHM); try { // 初始化cipher cipher = Cipher.getInstance(algorithmStr); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchPaddingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public byte[] decrypt(String encryptedDataStr, String keyBytesStr, String ivStr) { byte[] encryptedText = null; byte[] encryptedData = null; byte[] sessionkey = null; byte[] iv = null; try { sessionkey = Base64.decodeBase64(keyBytesStr); encryptedData = Base64.decodeBase64(encryptedDataStr); iv = Base64.decodeBase64(ivStr); init(sessionkey); cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); encryptedText = cipher.doFinal(encryptedData); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return encryptedText; } } ```