地磅无人值守项目 系列文章目录


文章目录

  • 前言
  • 一、开发微信页面
  • 二、2.Abp vNext 开放登录接口
    • 1.Abp vNext 开放登录接口
    • 2.微信端登录示例
      • utils/config.js
      • utils/auth.js
      • utils/http.js
      • utils/business/login.js
  • 总结

前言

客户提出新需求:车辆驾人员能在手机上查看自己车辆过磅记录。开搞…
人手一个微信,那就用微信小程序。

之前搞过vue,有很多相似的地方。


一、开发微信页面

页面及代码示例:

index.wxml


<!--index.wxml-->
<view class="page"><view class="page-body"><swiper class="swiper" indicator-dots="{{indicatorDots}}"autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" circular="true"><block wx:for="{{background}}" wx:key="*this"><swiper-item><image src="{{imgPath + item}}" class="slide-image" mode="aspectFill" /></swiper-item></block></swiper></view><view class="weui-grids"><navigator class="weui-grid" aria-role="button" url="/pages/records/list"><view class="weui-grid__icon"><icon class="iconfont icon-dingdan" /></view><view class="weui-grid__label">历史单据</view></navigator><navigator class="weui-grid" aria-role="button" url="/pages/cars/create/create"><view class="weui-grid__icon"><icon class="iconfont icon-wuliu" /></view><view class="weui-grid__label">车辆录入</view></navigator><navigator class="weui-grid" aria-role="button" url="#"><view class="weui-grid__icon"><icon class="iconfont icon-bingtutubiao" /></view><view class="weui-grid__label">单据统计<text style="font-style:italic;font-size: 26rpx;">待开放</text></view></navigator><navigator class="weui-grid" aria-role="button" url="/pages/cars/list"><view class="weui-grid__icon"><icon class="iconfont icon-auto" /></view><view class="weui-grid__label">车辆管理</view></navigator></view>
</view>

index.js

const {urlList} = require('../../utils/config.js');Page({data: {imgPath: urlList.advertPicListUrl,background: ['/banner01.png', '/banner02.png'],indicatorDots: true,vertical: false,autoplay: true,circular: false,interval: 5000,duration: 500,previousMargin: 0,nextMargin: 0},onShareAppMessage: function(){return{title: "转发给好友",path: "/pages/index/index"}},changeProperty: function (e) {var propertyName = e.currentTarget.dataset.propertyNamevar newData = {}newData[propertyName] = e.detail.valuethis.setData(newData)},changeIndicatorDots: function (e) {this.setData({indicatorDots: !this.data.indicatorDots})},changeAutoplay: function (e) {this.setData({autoplay: !this.data.autoplay})},intervalChange: function (e) {this.setData({interval: e.detail.value})},durationChange: function (e) {this.setData({duration: e.detail.value})}
})

二、2.Abp vNext 开放登录接口

1.Abp vNext 开放登录接口

using FloorScale.Base.Cars;
using FloorScale.Base.CarTypes;
using FloorScale.Base.MaterialFormats;
using FloorScale.Base.Materials;
using FloorScale.Base.MaterialTypes;
using FloorScale.Base.ReceivingUnits;
using FloorScale.Base.Shippers;
using FloorScale.Base.WeightRecords;
using FloorScale.Base.WeightTypes;
using FloorScale.Base.WeightUnits;
using FloorScale.Tenants;
using FloorScale.ThirdParty.WechatMinis.Dtos;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Data;
using Volo.Abp.Identity;
using Volo.Abp.Uow;namespace FloorScale.ThirdParty.WechatMinis
{/// <summary>/// 微信小程序/// </summary>[ApiExplorerSettings(GroupName = FloorScaleAppService.SwaggerDocWechatMiniApi)][Authorize]public partial class WechatMiniService : FloorScaleAppService{private const string ProviderName = "WeChatMiniProgram";private const string FixedPassword = ".*_0W@";private readonly IConfiguration _configuration;private readonly IdentityUserManager _userManager;private readonly IWechatMiniRepository _wechatRepository;private readonly IUnitOfWorkManager _unitOfWorkManager;private readonly IDataFilter _dataFilter;//private readonly ITenantRepository _tenantsRepository;private readonly IEfCoreTenantRepository _tenantRepository;private readonly ICarRepository _carRepository;private readonly ICarTypeRepository _typeRepository;private readonly IShipperRepository _shipperRepository;private readonly IReceivingUnitRepository _receivingUnitRepository;private readonly IMaterialTypeRepository _materialTypeRepository;private readonly IMaterialRepository _materialRepository;private readonly IMaterialFormatRepository _formatRepository;private readonly IWeightTypeRepository _weightTypeRepository;private readonly IWeightRecordRepository _weightRecordRepository;private readonly IWeightUnitRepository _weightUnitRepository;public WechatMiniService(IConfiguration configuration,IdentityUserManager userManager,IWechatMiniRepository wechatRepository,IUnitOfWorkManager unitOfWorkManager,IDataFilter dataFilter,IEfCoreTenantRepository tenantRepository,ICarRepository carRepository,ICarTypeRepository typeRepository,IShipperRepository shipperRepository,IReceivingUnitRepository receivingUnitRepository,IMaterialTypeRepository materialTypeRepository,IMaterialRepository materialRepository,IMaterialFormatRepository formatRepository,IWeightTypeRepository weightTypeRepository,IWeightRecordRepository weightRecordRepository,IWeightUnitRepository weightUnitRepository){_configuration = configuration;_userManager = userManager;_wechatRepository = wechatRepository;_unitOfWorkManager = unitOfWorkManager;_dataFilter = dataFilter;_tenantRepository = tenantRepository;_carRepository = carRepository;_typeRepository = typeRepository;_shipperRepository = shipperRepository;_receivingUnitRepository = receivingUnitRepository;_materialTypeRepository = materialTypeRepository;_materialRepository = materialRepository;_formatRepository = formatRepository;_weightTypeRepository = weightTypeRepository;_weightRecordRepository = weightRecordRepository;_weightUnitRepository = weightUnitRepository;}/// <summary>/// 登录/// </summary>/// <param name="login"></param>/// <returns></returns>[AllowAnonymous]public async Task<WeChatToken> GetLoginAsync(GetWechatLoginDto login){var result = new WeChatToken();// 调用第三方服务通过小程序内部登录后的Code获取微信Session信息//var wechatSession = await GetWechatSession(login.Code);//if (wechatSession == null)//{//    throw new BusinessException("wechatFail", "获取Openid失败");//}login.ClientId = "FloorScale_App";login.ClientSecret = "****";WechatCode2Session wechatSession = new WechatCode2Session(){Openid = "abcef06",};var tenantId = Guid.Parse(_configuration["WeChatMini:tenantId"]);using (CurrentTenant.Change(tenantId)){// 通过Provider和Openid获取用户的登录信息var wechatLogin = await _userManager.FindByLoginAsync(ProviderName, wechatSession.Openid);var userId = Guid.Empty;// 首次微信登陆if (wechatLogin == null){var idUserLoginInfo = new Microsoft.AspNetCore.Identity.UserLoginInfo(ProviderName,wechatSession.Openid,"微信小程序");if (!CurrentUser.Id.HasValue){userId = GuidGenerator.Create();// 注册用户登录var iduser = new IdentityUser(userId,wechatSession.Openid,email: $"{wechatSession.Openid}@qq.com",tenantId: tenantId);iduser.ExtraProperties.Add(nameof(wechatSession.Openid), wechatSession.Openid);iduser.AddLogin(idUserLoginInfo);// 添加用户信息await _userManager.CreateAsync(iduser, $"{wechatSession.Openid}{FixedPassword}");var wechatUser = new WechatMini(){UserId = iduser.Id,OpenId = wechatSession.Openid,Phone = string.Empty,Email = string.Empty,NickName = string.Empty,Address = string.Empty,AvatarUrl = string.Empty,Birthday = null,Gender = 0,Status = true,TenantId = tenantId};result.NeedUpdate = true;await _wechatRepository.InsertAsync(wechatUser);}else{userId = CurrentUser.Id.Value;var user = await _userManager.GetByIdAsync(CurrentUser.Id.Value);await _userManager.AddLoginAsync(user, idUserLoginInfo);}}else{userId = wechatLogin.Id;}var tokenResponse = await GetTokenByOpenIdAsync(wechatSession.Openid,wechatSession.Openid,login);result.UserId = userId;result.AccessToken = tokenResponse.AccessToken;result.ExpiresIn = tokenResponse.ExpiresIn;result.TokenType = tokenResponse.TokenType;result.Scope = tokenResponse.Scope;result.RefreshToken = tokenResponse.RefreshToken;return result;}}private async Task<TokenResponse> GetTokenByOpenIdAsync(string userName, string password, GetWechatLoginDto login){var disco = await new HttpClient().GetDiscoveryDocumentAsync(_configuration["AuthServer:Authority"]);using (var tokenClient = new HttpClient()){tokenClient.DefaultRequestHeaders.Add("__tenant", _configuration["WeChatMini:tenantId"]);var tokenResponse = await tokenClient.RequestPasswordTokenAsync(new PasswordTokenRequest{Address = disco.TokenEndpoint,ClientId = login.ClientId,ClientSecret = login.ClientSecret,UserName = userName,Password = $"{password}{FixedPassword}"});tokenClient.SetBearerToken(tokenResponse.AccessToken);return tokenResponse;}}private async Task<WechatCode2Session> GetWechatSession(string code){WechatCode2Session result = null;var appid = _configuration["WeChatMini:appid"];var secret = _configuration["WeChatMini:secret"];var httpClient = new HttpClient();var urlWeixin = string.Format(_configuration["WeChatMini:WeixinSessionUri"],appid,secret,code);try{var token = await httpClient.GetStringAsync(urlWeixin);result = JsonConvert.DeserializeObject<WechatCode2Session>(token);}catch { }return result;}/// <summary>/// 获取用户信息/// </summary>/// <param name="uid"></param>/// <returns></returns>public async Task<WechatMiniDto> GetUserInfoAsync(Guid uid){using (CurrentTenant.Change(Guid.Parse(_configuration["WeChatMini:tenantId"]))){var model = await _wechatRepository.GetAsync(p => p.UserId == uid);return ObjectMapper.Map<WechatMini, WechatMiniDto>(model);}}/// <summary>/// 更新用户信息/// </summary>/// <param name="uid"></param>/// <param name="input"></param>/// <returns></returns>public async Task UpdateUserInfoAsync(Guid uid, [FromBody] UpdateWechatMiniDto input){using (CurrentTenant.Change(Guid.Parse(_configuration["WeChatMini:tenantId"]))){var modelUser = await _wechatRepository.GetAsync(p => p.UserId == uid);modelUser.Phone = input.Phone;modelUser.NickName = input.NickName;if (!string.IsNullOrWhiteSpace(input.AvatarUrl))modelUser.AvatarUrl = input.AvatarUrl;modelUser.Address = input.Address;modelUser.Birthday = input.Birthday;modelUser.Gender = input.Gender;var result = await _wechatRepository.UpdateAsync(modelUser);}}/// <summary>/// 删除实体/// </summary>/// <param name="id">编号</param>/// <returns></returns>public async Task DeleteAsync(Guid id){await _wechatRepository.DeleteAsync(id);}}
}

2.微信端登录示例

utils/config.js

// const basePath = 'https://localhost:44385';
const basePath = 'https://scaleapi.caishiben.com';
const urlList = {basePath: basePath,// 刷新tokenrefreshTokeUrl: basePath + '/refreshToke',//token// 登录和首页轮播loginUrl: basePath + '/wxappLogin',//登录advertPicListUrl: basePath + '/wechat',//轮播列表
}
const globalConfig = {clientId: 'FloorScale_App',clientSecret: '********'
}module.exports = {urlList,globalConfig
}

utils/auth.js


import http from './business/login'
import userApi from './business/user'
const {globalConfig} = require('config.js')async function checkSession(){return new Promise((resolve, reject) => {wx.checkSession({success() {return resolve(true)},fail() {return resolve(false)}})})
}// 检测登录状态,返回 true / false
async function checkHasLogined() {const token = wx.getStorageSync('token')if (!token) {return false}const loggined = await checkSession()if (!loggined) {wx.removeStorageSync('token')wx.removeStorageSync('userInfo')wx.removeStorageSync('uid')wx.removeStorageSync('rememberTenant')return false}return true
}async function register(page) {let _this = this;return new Promise((resolve, reject) => {wx.getUserProfile({desc: '用于完善会员资料',fail: () => {resolve(false)},success: (resUser) => {wx.login({fail: () => {resolve(false)},success: resLogin => {http.getLoginToken({data: {code: resLogin.code,clientId: globalConfig.clientId,clientSecret: globalConfig.clientSecret},success: function (resToken) {wx.setStorageSync('token', resToken.access_token)wx.setStorageSync('uid', resToken.uid)if (resToken.needUpdate) {updateUser(resUser.userInfo)}if(page) {page.onShow()}resolve(true)},complete : function(resToken){},fail: function (resToken) {resolve(false)}})}})}})})
}function updateUser(data) {let _this = this;let passData = {"userId": wx.getStorageSync('uid'),"phone": "","nickName": data.nickName,"address": "","avatarUrl": data.avatarUrl,"birthday": null,"gender": data.gender,"remark": ""}userApi.updateUserInfo({data: passData,success: function (res) {},complete : function(res){},fail: function (res) {}})
}module.exports = {checkHasLogined: checkHasLogined,register: register
}

utils/http.js


module.exports = {http(url, method, params) {let requestHeader = {'content-type': 'application/json'}// 获取tokenlet token = wx.getStorageSync('token')if (token){requestHeader.authorization = 'Bearer ' + token}// 在这里判断一下data是否存在,params表示前端需要传递的数据,params是一个对象,有三组键值对,// data:表示请求要发送的数据,success:成功的回调,fail:失败的回调,这三个字段可缺可无,其余字段会忽略if(params.data){for (let key in params.data) { // 在这里判断传过来的参数值为null,就删除这个属性if (params.data[key] == null || params.data[key] == 'null') {delete params.data[key]}}}wx.request({url: urlList.basePath + url,method: method === '' ? 'get' : method,data: params.data,header: requestHeader,success(res) {params.success && params.success(res.data)},fail(err) {params.fail && params.fail(err)},complete(err) {params.complete && params.complete(err)}})}
}

utils/business/login.js


function getSession(params){http('/api/app/wechat-mini/session', 'get', params)
}function getLoginToken(params){http('/api/app/wechat-mini/login', 'get', params)
}export default {getLoginToken,getSession
}

总结

Abp vNext 开放登录接口调通后,剩下的工作就是功能叠加。这个工作有点枯燥。

微信上打开小程序:#小程序://尧安称重/NxgTDIoRdkAWE7g
前端:https://dibang.caishiben.com
接口服务:https://scaleapi.caishiben.com
接口文档:https://scaleapi.caishiben.com/swagger/index.html

5.Abp vNext 地磅无人值守 微信小程序相关推荐

  1. abp Vnext OpenIddect 扩展微信小程序授权登录

    abp vnext6.0之后官方替换了原来的ids4,采用了openIddict的oauth认证框架.使用之前的方法已经不行,以下是OpenIddect 使用ITokenExtensionGrant接 ...

  2. Abp vNext 地磅无人值守项目目录

    地磅无人值守项目目录 第一章 项目概况 第二章 项目后台搭建 2.1.0 abp vnext 接口服务搭建 2.1.1 abp vnext初始化项目 2.1.2 SQL Server数据库 2.1.3 ...

  3. 2.1.1 Abp vNext 地磅无人值守 接口服务创建

    地磅无人值守项目 系列文章目录 文章目录 前言 一.Abp vNext手脚架 二.创建Abp vNext项目 1.创建项目 2.初始化数据库 3.试运行 3.1 查看数据库连接 3.2 浏览器查看 3 ...

  4. 2.1.0 Abp vNext 地磅无人值守 接口服务搭建

    地磅无人值守项目 系列文章目录 文章目录 前言 一.Domain项目创建实体类 1.创建实体类(该类对应 数据库字段) 2.创建表接口类 二.EntityFrameworkCore项目 1.创建表实现 ...

  5. 2.1.3 Abp vNext 地磅无人值守 业务实现

    地磅无人值守项目 系列文章目录 文章目录 前言 一.AbpHelper简介 二.AbpHelper使用 1.创建CarType实体类 2.AbpHelper打开解决方案 3.为CarType实体类生成 ...

  6. 3.Abp vNext 地磅无人值守 vue 前端搭建

    地磅无人值守项目 系列文章目录 文章目录 前言 一.Vue概要 二.文件夹简单说明 api示例 views示例 router示例 1.router/modules文件夹下加入cars.js,代码如下: ...

  7. 2.1.4 Abp vNext 地磅无人值守 车辆物料实现接口

    地磅无人值守项目 系列文章目录 文章目录 前言 一.获取实体数据 二.创建实体数据 三.获取翻页数据 四.更新实体数据 五.删除实体数据 六.CarTypeAppService全部代码 总结 前言 提 ...

  8. 4.Abp vNext 地磅无人值守 Winform 客户端搭建

    地磅无人值守项目 系列文章目录 文章目录 前言 一.基础功能 1. 一台电脑启动一次客户端 2. 日志记录 3. 自动升级功能 二.对接硬件设备 1.对接摄像头 总结 前言 客户端主要是管控车辆进出场 ...

  9. 1.Abp vNext 地磅无人值守项目

    地磅无人值守项目 系列文章目录 文章目录 前言 一.过磅方式 二.系统作业流程 三.系统构成模块 总结 前言 传统的衡称重由于设备.人为因素及流程等问题,导致作弊现象层出不穷.称重过磅效率也得不到有效 ...

最新文章

  1. 了解关于Hadoop的12个事实
  2. js字符串与数组的处理
  3. python面向对象有什么用_Python 中的面向对象没有意义
  4. Java数据结构和算法(二):数组
  5. 我的考研~~~3-4月份总结
  6. Codepen 每日精选(2018-4-21)
  7. 罗永浩:比起悲剧英雄 我更喜欢被当成失败的小丑
  8. 刘强东深夜写信诉苦;华为不排斥卖给苹果 5G 芯片;Facebook 再宕机 | 极客头条...
  9. Java基础篇:如何使用instanceof
  10. 【工作日志】2013-02-01
  11. SHAP模型:可解释机器学习模型
  12. 好用的在线PS编辑器
  13. DIY回音壁多媒体音箱
  14. 正整数分解使得乘积最大问题
  15. 电路设计之--钽电容选取
  16. 二叉树的结构特点及性质
  17. win10多显示器设置只有主显示屏显示任务栏
  18. html 表格排列,html表格如何排序?表格排序详解!
  19. python爬取网易云音乐排行榜数据
  20. Python 运用GeoIP2离线数据库定位

热门文章

  1. 主流实时流处理计算框架Flink初体验
  2. 【仿真设计】仿真技术在智能制造中的作用;智能制造难点在模型,焦点在仿真;汽车行业CAE研究
  3. 【mac 实现ai绘画自由安装指南】
  4. 怎样把word转换成excel表格格式
  5. Leetcode DAY6: 有效的字母异位词 and 两个数组的交集 and 快乐数 and 两数之和
  6. mac上优秀的键盘改键神器:Karabiner Elements完美支持m1芯片详细教程解析
  7. 3ds Max 材质贴图
  8. Error response from daemon: Container 2c6d35b44a9862c63a6caf11a5622a33fe27979e12e51f9bd96f8dad98521c
  9. 物理工程建模和AI量化建模的时空跳跃
  10. 基于labview开发平台的声音信号采集及处理系统设计(任务书+lunwen+翻译及原文+vi源文件+查重报告)