在我们很多前端业务开发中,往往为了方便,都需要自定义一些用户组件,一个是减少单一页面的代码,提高维护效率;二个也是方便重用。本篇随笔介绍在任务管理操作中,使用自定义Vue&Element组件,实现系统用户选择和显示。

1、系统用户的选择需求

在我们一些业务系统中,可能需要选中系统用户进行一些业务处理,如本篇介绍的任务系统中,如在新增或者编辑界面中,需要选择任务的执行人、参与人等人员操作。

而在查看详细数据的时候,可能需要展示相关的人员名称,如下界面所示。

前者需要弹出界面中选择用户,可以设置多选、单选、过滤用户数据的操作;后者则需要根据用户的ID显示正常的名称。

一般来说,我们用户隶属于某个部门、角色、或者岗位的,我们可以根据这些条件进行开始展示,同时也可以输入一定的条件进行查询定位用户。

选择用户的弹出界面如下所示,其中可以根据部门分类、岗位分类进行快速的查询,同时也可以根据用户名进行查询。

我们可以通过定义用户组件,允许开启/禁用限制用户多选的操作,如果选择多个,则自动添加在列表中,如下界面所示。

确认后,界面的人员进行更新显示即可。

以上就是大概的用户组件的界面效果和逻辑处理。

2、实现用户选择和显示的组件开发

我们先定义一个用户组件,命名为selectPostUser.vue其中HTML模板代码的结构如下所示。

主要就是一个标签显示、按钮、和一个弹出对话框。

在编辑状态下,显示按钮,并可以触发弹出对话框的展示,对话框主要就是显示系统系统的内容。

而这个组件,我们定义了几个prop属性,用来配置显示不同的界面效果,是否可以选择,是否可以移除标签、是否可以多选人员等设置。

export default{
props: {
value: {
//接受外部v-model传入的值 type: [String],default: ''},
closable: {
//是否可以关闭标签 type: Boolean,default: () => { return true}
},
selectable: {
//是否可选人员 type: Boolean,default: () => { return true}
},
multiple: {
//是否多选,默认可以多选 type: Boolean,default: true}
},

我们定义了几个data变量,以及对几个变量进行watch监控,以便控制它的值的更新和返回,如下代码所示。

这里注意,如果我们需要使用.sync的方式来更新属性的值,那么需要使用update:value的格式进行处理,如下所示。

则代码更新这个visible则如下

this.$emit('update:isVisible', val)

而如果我们这个组件通过v-modal绑定的值,如下界面代码所示

<select-post-userv-if="isEdit"ref="editForm.participant"v-model="editForm.participant" />

如果更新返回,则使用下面方式

this.$emit('input', val)

使用自定义的用户组件,需要在父页面中引入相关的对象组件,如下代码所示。

import selectPostUser from './components/selectPostUser'

然后加入父页面的组件列表中

import selectPostUserfrom './components/selectPostUser'import tasklog from'./components/tasklog'let that;
export
default{
components: { selectPostUser, tasklog },
//导入组件

这样我们才能在界面上正常使用了

  <el-col:span="12">
    <el-form-itemlabel="执行人"prop="executor">
      <select-post-userref="add_executor"v-model="addForm.executor":multiple="false" />
    </el-form-item>
  </el-col>
  <el-col:span="12">
    <el-form-itemlabel="参与人"prop="participant">
      <select-post-userref="add_participant"v-model="addForm.participant" />
    </el-form-item>
  </el-col>
  <el-col:span="12">
    <el-form-itemlabel="验收人"prop="accepter">
      <select-post-userref="add_accepter"v-model="addForm.accepter" />
    </el-form-item>
  </el-col>

如果我们需要在限制不能多加超过一个用户的,那么设置 :multiple="false" 即可限制即可,

用户组件中对该变量进行处理,限制添加多于一个人员的情况即可。

通过,选择确认内容后,我们更新对应的值,并触发一个change事件给父页面使用即可。

    async handleSubmit () { //表单提交
      this.isVisible = false
      this.change() //触发值变化

      this.$emit('submit', this.tags)
},
change (data) {if (this.tags) {this.dataValue = this.tags.map(e => e.id).join(',')
console.log(
this.dataValue)this.$emit('change', this.dataValue)
}
},

如果我们是查看明细状态下,不允许用户编辑或者修改人员,那么可以通过修改其他两个属性进行控制显示,如下代码所示。

<el-col:span="12">
  <el-form-itemlabel="执行人">
    <select-post-userref="viewForm.executor"v-model="viewForm.executor":closable="false":selectable="false" />
  </el-form-item>
</el-col>
<el-col:span="12">
  <el-form-itemlabel="参与人">
    <select-post-userref="viewForm.participant"v-model="viewForm.participant":closable="false":selectable="false" />
  </el-form-item>
</el-col>
<el-col:span="12">
  <el-form-itemlabel="验收人">
    <select-post-userref="viewForm.accepter"v-model="viewForm.accepter":closable="false":selectable="false" />
  </el-form-item>
</el-col>

通过设置 :
closable
="false"和  :
selectable
="false" 两个属性变量,就可以控制不出现移除标签人员和选择按钮的出现了。

以上就是自定义用户组件的主要逻辑和处理操作,我们自定义用户组件后,在各个页面需要的地方,引入使用即可,可以非常方便的重用,且可以减少单一页面的代码,非常方便。

学会如何自定义用户组件的处理过程,是我们前端开发所必须掌握的基本技能之一,熟练拆分各种重复模块变为自定义组件的过程,可以使得我们的代码更方便维护开发,增强可读性。

在前面随笔的介绍中,我们已经为各种框架,已经准备了Web API、Winform端、Bootstrap-Vue的公司动态网站前端、Vue&Element的管理前端等内容,基本都是基于Web API基础的。完成这些基础准备和布局后,我们继续将技术的触角放到使用Vue语言开发小程序的场景中,本篇随笔介绍使用uView UI+UniApp开发微信小程序,介绍使用准备过程中的一些注意点和经验总结。

1、小程序的开发准备工作

我们在开发小程序之前,需要了解一些基本的知识,以及掌握一些常规的开发工具,相关知识最好能够在着手开始前有所掌握,然后在开发过程中逐步加强巩固即可。

1)Vue语言掌握

我们通过Vue官网
https://cn.vuejs.org/v2/guide/index.html
,了解相关的语言基础只是,这个部分我们利用Vue开发小程序的基础,必须先有所掌握相关基础知识,以及开发组件中涉及到的知识点。

Vue可以是我们后续前端开发的强力助手,如果我们掌握的好,对很多相关的处理会一目了然,否则可能不明所以,如Mixin混入、以及组件的事件属性的通讯关系、Vuex的存取处理、常用的JS模块、ES6的函数定义及Promise的处理等等。

随着我们对Vue开发的逐步熟悉,各种特性我们会一一记在脑中并能够熟练运用。

2)UniApp官网

我们需要了解UniApp的基础,包括它的相关理念,下面介绍的uViewUI本身也是基于它的进一步封装,使用UniApp和HbuliderX 工具可以开发各种不同的小程序,APP、H5等场景,不过我们这里着重考虑微信小程序。

3)uView UI官网

通过官网
https://www.uviewui.com/components/intro.html
,了解组件的使用,以及一些基础的知识,如easycom的约定、全局变量特别是Vuex的混入及使用过程、JS类库等处理。

我们本次开发小程序,需要利用uView UI的组件代码下载下来进行项目的整合使用,或者利用HBuilder X的工具,直接下载使用UniApp官网的uView UI插件模块。

uView UI提供了各种界面上用到的组件,几乎封装了我们常见到的各种界面元素,极大的方便了我们小程序界面的开发工作,如果有些特殊的功能界面,也可以从UniApp官网的插件列表中寻找进行整合。

4)官方小程序网站

通过官网
https://developers.weixin.qq.com/miniprogram/dev/framework/
了解微信小程序的基础知识,我们利用uView UI+UniApp开发微信小程序,本身还是对官方小程序接口的封装处理,我们有时候还是需要对其中的相关生命周期,底层函数等有一定的了解,才能更好的理解微信小程序的各种机制和处理方式。

5)开发工具

我们这里开发UniApp程序,推荐还是使用HBuilderX来开发,相对通用的前端开发工具VS Code来说,它的有些处理更特性化,然后熟悉配合《微信开发者工具》进行小程序的调试和部署即可。

2、uView UI的使用

以Web API为业务数据的接口基石,我们可以扩展很多业务管理端,包括Winform端、Vue&Element业务管理端、动态门户网站、微信小程序等等。

我们循例介绍一下uView UI的基础使用步骤,首先在项目中main.js引入对应的组件-引入uView主JS库。

//main.js
import uView from "uview-ui";
Vue.use(uView);

检查uni.scss中已经加入了uView UI的样式,引入uView的全局SCSS主题文件

/*uni.scss*/@import'uview-ui/theme.scss';

检查app.vue中加入了对应的样式,在
App.vue
中首行的位置引入

<stylelang="scss">@import "uview-ui/index.scss";
@import "common/demo.scss";
</style>

一般来说,我们创建示例项目,都有这些基础的设置了,我这里只是循例介绍一下,让我们有所了解它的工作原理。

我这里还是主要介绍uView的this.$u的相关对象处理,它是通过Vue.prototype进行挂载进去的,也就是我们使用这些,都是uView加入的,如下main.js部分内容所示。

//引入uView提供的对vuex的简写法文件
let vuexStore = require('@/store/$u.mixin.js')
Vue.mixin(vuexStore)
//引入后自动将Vuex里面的键作为Computed的属性 //引入uView对小程序分享的mixin封装 let mpShare = require('uview-ui/libs/mixin/mpShare.js')
Vue.mixin(mpShare)

在项目中,我们可以找到对应项目的store实现,以及uview对象Mixin混入的部分

它把登录信息相关的用户和令牌信息,通过storage的方式进行存储起来,并处理好相关的逻辑,这样混入后我们可以方便的通过混入的Computed属性获取到对应的值,或者快速的设置存储起来。

这里的SaveStateKeys就是设置存储到storage中的键,只要存在这两个键的内容,都可以快速的使用Vuex的处理,如下是获取内容。

<viewclass="u-flex-1">
    <viewclass="u-font-16 u-p-b-20">用户名称:{{vuex_user.fullName}}</view>
    <viewclass="u-font-12 u-p-b-20">手机号:{{vuex_user.mobilePhone}}</view>
    <viewclass="u-font-12 ">邮箱:{{vuex_user.email}}</view>
</view>

由于是页面对象的自动混入,我们甚至在JS代码里面都没有定义这两个对象,只需要记得这个键是我们的全局存储的对象即可。

例如我们在JS的模块里面,通过VM获得this的参数

即可直接调用对象存储处理,如下代码所示。

//缓存其他信息
vm.$u.vuex('vuex_user.name', name)
vm.$u.vuex(
'vuex_user.fullName', fullName)
vm.$u.vuex(
'vuex_user.mobilePhone', mobilePhone)
vm.$u.vuex(
'vuex_user.email', email)
vm.$u.vuex(
'vuex_user.roles', roles)
vm.$u.vuex(
'vuex_user.roles', roleNames)

如果是在页面组件中,我们则使用this代替vm的变量进行调用

this.$u.vuex('vuex_user.name', name)

storage的信息,可以通过小程序的调试工具进行查看到,如下截图所示。

3、小程序的登录状态判断及跳转

在业务系统中,我们需要根据登录用户的身份获取对应的数据,如果用户没有登录,这些信息是无法获到的,那么我们可以在app.vue中判断用户是否登录,然后调准到对应的页面,如下所示。

跳转判断在app.vue的程序启动逻辑中进行处理,如下代码所示。

<script>exportdefault{
globalData: {
username:
''},
onLaunch() {
//如果用户没有登录或令牌失效,跳转到登录界面 //console.log(this.vuex_token) if(!this.vuex_token) {this.$u.route({
url:
'pages/template/login/password'});
}
else{
uni.switchTab({
url:
'/pages/example/myinfo'});
}
},
}
</script> <stylelang="scss">@import "uview-ui/index.scss";
@import "common/demo.scss";
</style>

其中 uni.switchTab 是跳转到首页的某个tab页面,如果我们的页面有tabbar页面的话。

用户登录的时候,需要输入用户名,密码,构建相关的参数后,进行登录处理

submit() {this.$refs.uForm.validate(valid =>{if(valid) {this.$u.api.User.login(this.model).then(data =>{//登陆成功跳转到Tab页面
uni.switchTab({
url:
'/pages/example/myinfo'});
});
}
else{
console.log(
'验证失败');
}
});
},

其中
this.$u.api.User
是用户API接口的统一调用方式

我们在main.js代码里面看到安装了两个不同的JS模块,如下代码所示。

//http拦截器,将此部分放在new Vue()和app.$mount()之间,才能App.vue中正常使用
import httpInterceptor from '@/common/http.interceptor.js'Vue.use(httpInterceptor, app)//http接口API抽离,免于写url或者一些固定的参数
import httpApi from '@/common/http.api.js'Vue.use(httpApi, app)

其中第一个是统一http调用的设置,第二个这是引入一个api对象,方便调用api对应的接口,如下:
this.$u.api.User

以及统一整合各个API对象

import User from '../api/user.js'

//此处第二个参数vm,就是我们在页面使用的this,你可以通过vm获取vuex等操作,更多内容详见uView对拦截器的介绍部分://https://uviewui.com/js/http.html#%E4%BD%95%E8%B0%93%E8%AF%B7%E6%B1%82%E6%8B%A6%E6%88%AA%EF%BC%9F
const install = (Vue, vm) =>{//将各个定义的接口名称,统一放进对象挂载到vm.$u.api(因为vm就是this,也即this.$u.api)下
    vm.$u.api = { //将 vm 对象传递到模块中
User: User(vm)
}
}

export
default { install }

其中在http.interceptor.js里面,统一设置了api的Url的baseUrl,这样可以不用配置反向代理的转义,就可以简化API中URL的定义了。

const install = (Vue, vm) =>{
Vue.prototype.$u.http.setConfig({
baseUrl:
'http://localhost:27206/', //接口访问基础路径 showLoading: true, //是否显示请求中的loading loadingText: '请求中...', //请求loading中的文字提示 loadingTime: 800, //在此时间内,请求还没回来的话,就显示加载中动画,单位ms //如果将此值设置为true,拦截回调中将会返回服务端返回的所有数据response,而不是response.data //设置为true后,就需要在this.$u.http.interceptor.response进行多一次的判断,请打印查看具体值 //originalData: true, //设置自定义头部content-type //header: { //'content-type': 'application/json;charset=UTF-8' //} })

另外我们返回的Response对象里面,有统一定义对象的,相关的数据可以参考随笔《
利用过滤器Filter和特性Attribute实现对Web API返回结果的封装和统一异常处理
》了解。

一旦程序处理过程中,有错误抛出,都会统一到这里进行处理,有异常的返回JSON如下所示。

其中结果result是用于检查是否执行成功的标识,这里用来判断是否有错误即可,有错误,则显示自定义错误信息

    //响应拦截,判断状态码是否通过
    Vue.prototype.$u.http.interceptor.response = res =>{//console.log(res)
        //如果把originalData设置为了true,这里得到将会是服务器返回的所有的原始数据
        //判断可能变成了res.statueCode,或者res.data.code之类的,请打印查看结果
        if (!vm.$u.test.isEmpty(res.success)) {//res为服务端返回值,可能有code,result等字段
            //这里对res.result进行返回,将会在this.$u.post(url).then(res => {})的then回调中的res的到
            //如果配置了originalData为true,请留意这里的返回值
            returnres.result
}
else{var msg = '' var data =res.resultif (data && data.error &&data.error.message) {
msg
=data.error.message
vm.$u.toast(msg)
}
//如果返回false,则会调用Promise的reject回调, //并将进入this.$u.post(url).then().catch(res=>{})的catch回调中,res为服务端的返回值 return false}
}

上面的拦截默认是基于状态码200的,如果我们自定义一些异常,指定了状态码的也需要拦截,需改uview-ui/libs/request/index.js 根据状态码自己去加入,如下代码所示。

用户完成登录,并成功获取身份信息后,切换到指定的页面,如下界面效果所示

在《
使用uView UI+UniApp开发微信小程序
》的随笔中,介绍了基于uView UI+UniApp开发微信小程序的一些基础知识和准备工作,其中也大概介绍了一下基本的登录过程,本篇随笔详细介绍一下微信小程序的相关登录处理以及登录后设置用户身份信息,并跳转到相应页面的处理过程。

1、令牌判断和登录方式

在之前介绍过,在业务系统中,我们需要根据登录用户的身份获取对应的数据,如果用户没有登录,这些信息是无法获到的,那么我们可以在app.vue中判断用户是否登录,然后跳转到对应的页面,如下所示。

也就是系统启动的进入的时候,我们需要对系统用户的身份做一次判断,判断token是否存在,并且是否有效(因为token是有时效的)。

我们先来介绍下如何如何判断token是否存在的处理过程,由于token本身在登陆的时候,设置了存储,因此只需要通过uView的token获取操作即可读取出来,并进行判断即可。

我们只需要简单判断this.vuex_token 是否存在值即可,因为this.vuex_token是由于uView在加载Mixin的时候,已经自动映射了存储的键值,因此我们可以通过this.vuex_token访问到对应的值。

如果是简单的判断,我们在app.vue的如下代码即可处理

<script>exportdefault{
globalData: {
username:
''},
onLaunch() {
//如果用户没有登录或令牌失效,跳转到登录界面//console.log(this.vuex_token) if(!this.vuex_token) {this.$u.route({
url:
'pages/template/login/password'});
}
else{
uni.switchTab({
url:
'/pages/example/myinfo'});
}
},
}
</script>

不过我们需要通过判断它的时限有效性,那么通过判断失效日期进行处理,如下代码所示。

<script>exportdefault{
onLaunch() {
//如果用户没有登录或令牌失效,跳转到登录界面//console.log(this.vuex_token) console.log(this.$u.http.config.baseUrl)var authed = this.checkToken()if(!authed) {this.$u.route({
url:
'/pages/task/login/index'});
}
else{this.$u.route({
type:
'tab',
url:
'pages/task/login/myinfo'})
}
},
methods: {
checkToken() {
if(this.vuex_token && this.vuex_user) {var expired = new Date(this.vuex_user.expired) //token过期时间
const now =Date.now()if(expired - now > 0) {return true}
}
return false}
}
}
</script>

其中expired是我们获取到token的时间,并加上token的失效时间的。

我们这里使用了一个checkToken的函数,用来判断是否正常登录并且有效的,如果令牌无效,那么跳转到登陆界面,否则直接跳到个人信息页面下。

我们先来看看登录界面,我们这里提供了几种登录方式,账号密码登录、短信验证码登陆、微信授权登录几种方式。

这几种不同的登录方式,都是在验证成功后,需要获取用户的身份信息,并设置到Storage存储中去,逻辑上有相同之处。

2、登录的处理逻辑

用户登录的时候,需要输入用户名,密码,构建相关的参数后,进行登录处理,处理过程代码如下所示。

submit() {this.$refs.uForm.validate(valid =>{if(valid) {this.$u.api.User.login(this.model).then(data =>{//登陆成功跳转到Tab页面
uni.switchTab({
url:
'/pages/task/login/myinfo'});
});
}
else{
console.log(
'验证失败');
}
});
},

其中 this.$u.api.User 是用户API接口的统一调用方式,其中http.api.js的代码如下所示。

import User from '../api/user.js'import Taskfrom '../api/task.js'

const install = (Vue, vm) =>{//将各个定义的接口名称,统一放进对象挂载到vm.$u.api(因为vm就是this,也即this.$u.api)下
    vm.$u.api = { //将 vm 对象传递到模块中
User: User(vm),
Task: Task(vm)
}
}

export
default { install }

其中api/user.js里面定义了访问远程WebAPI的操作,同时也是我们封装一些处理逻辑的操作函数,我们可以通过ES6的Promise进行封装一个简单的登录函数。

由于我们这里登录过程,除了用户名密码外,还需要appid、时间戳以及签名参数等信息组合,因此构建参数比较多一点。

登录成功后,我们就调用resolve的执行即可,如果失败,调用reject的处理。

这样我们就可以直接通过Promise的操作处理登录成功后的操作了,如下代码所示。

this.$u.api.User.login(this.model).then(data =>{
uni.switchTab({
url:
'/pages/task/login/myinfo'});
});

而其中setUserToken函数,主要是便于重用的目的抽取出来,因为设置令牌和用户信息,是其他两个登录方式(短信登陆、微信登陆)所通用的操作。

短信验证码的登录方式也是类似,需要后端配合判断短信的有效性即可,前端先调用后端的发送短信操作,如下代码所示

//发送短信验证码
var params = { PhoneNumber: this.tel }this.$u.api.User.SendPhoneLoginSmsCode(params).then(res =>{if(res.success) {this.$u.toast(`验证码已发送至手机 ${this.tel},请注意查收!`)this.$u.route({
url:
'pages/task/login/code',params: {
mobile:
this.tel
}
});
}
else{this.$u.toast('发送出现错误:' +res.errorMessage)
}
})

而前端调用的函数也就是在api/user.js中简单封装一下对API的调用即可。

SendPhoneLoginSmsCode(data) { //发送登录动态码
    return vm.$u.post('/api/framework/User/SendPhoneLoginSmsCode', data)
},

发送的后端代码如下所示,主要就是放在缓存中一段时间供验证即可。

        /// <summary>
        /// 发送登录动态码
        /// </summary>
        /// <returns></returns>
[AllowAnonymous]
public CommonResult SendPhoneLoginSmsCode(PhoneCaptchaModel model)
{
//获取随机6位数字动态验证码 var code = RandomChinese.GetRandomNumber(6);//使用自定义模板处理短信发送 string message =string.Format(ConfigData.MySmsCodeTemplate, code);var smsSender = newMySmsSender();var result =smsSender.Send(model.PhoneNumber, message);if(result.Success)
{
var cacheKey = model.PhoneNumber;//以手机号码作为键存储验证码缓存 var cacheItem = new SmsLoginCodeCacheItem { Code = code, PhoneNumber =model.PhoneNumber };var cache = CacheManagerHelper.GetCacheItem(cacheKey, () =>{returncacheItem;
}, TimeSpan.FromMinutes(ConfigData.SmsCodeExpiredMinutes));
}returnresult;
}

验证的时候,只需要判断缓存里面是否存在记录和对应验证码是否匹配即可,如果顺利通过,那么构建用户的token信息返回给前端就是。

如果前端发送验证码成功,那么登陆界面跳转到等待输入验证码的界面,如下所示。

输入正确的验证码即可顺利登陆,否则过期则要求重新发送短信验证码。

submit() {var params = { mobile: this.mobile, smscode: this.smscode };
console.log(params);
this.$u.api.User.dynamiclogin(params)
.then(res
=>{this.$u.toast('验证成功');

uni.switchTab({
url:
'/pages/task/login/myinfo'});
})
.
catch(error =>{
console.log(
'验证失败' +error);this.$u.toast(error);
});
},

如果顺利登陆,则跳转到我的页面里面去,展示一些常用的信息汇总,以及常见处理操作。

这里面涉及一个退出登录的操作,主要就是注销当前用户的身份,只要清空身份信息,并跳转到登录首页即可。

logout() {this.$u.vuex('vuex_token', null) //重置
    this.$u.vuex('vuex_user', null) //重置
    this.$u.toast('退出成功,请重新登录!')this.second = 0setTimeout(()=>{this.$u.route({ url: '/pages/task/login/index'})
},
1500)
},

鉴于篇幅原因,先介绍到这里,关于微信授权登陆及绑定的操作过程,后续再介绍。

ABP框架介绍地址:
http://www.iqidi.com/Framework/AbpIndex.htm

ABP框架文档下载地址:
http://www.iqidi.com/Framework/Abpdoc.htm

1、基于Winform的ABP快速开发架特点:

1、基于ABP框架底层基础上,完善了用户管理、组织机构管理、角色管理、菜单管理、功能管理及权限分配,日志管理、字典管理、产品管理等管理功能,可实现用户的功能及数据权限进行控制管理。
2、集成通用字典管理模块,方便对字典大类及对应字典项目数据的管理。
3、集成菜单权限控制及全局菜单的显示及禁用。
4、和我们的Winform框架一样,提供封装良好的框架组件模块,包括权限系统、字典模块、附件管理模块、自动升级、分页控件、公用类库及界面基类模块等模块。
5、通过代码生成工具Database2sharp配套工具实现业务模块的快速开发,可以快速生成框架底层代码,以及界面代码,后续进行一定的布局调整即可。
6、生成的Winform界面, 包括业务数据的分页查询,数据的Excel导入和导出的功能,操作功能的权限控制等,以及编辑查看界面的数据展示、保存和更新数据操作等功能。
7、底层基于.net core进行构建,并具有.net core 技术带来的相关优点,具有ABP框架所具有的一切优点,如基于领域驱动的开发、依赖注入、仓储模式、异常处理、日志记录、动态Web API等。

2、基于Vue + Element 的ABP快速开发架特点:

1、和基于Winform的ABP框架一样,使用同一个API后端,模块包括用户管理、组织机构管理、角色管理、菜单管理、功能管理及权限分配,日志管理、字典管理、产品管理等管理功能,可实现用户的功能及数据权限进行控制管理。
2、集成通用字典管理模块,方便对字典大类及对应字典项目数据的管理。
3、集成菜单权限控制及全局菜单的显示及禁用,系统以后端配置的动态菜单实现路由过滤,实现严格的界面权限判断处理。
4、基于Vue + Element 的ABP框架,整合了众多前端流行组件,以Element界面组件为基础,拓展很多相关组件,界面设计模块化处理。
5、框架界面美观,整合树列表、表格数据展示,以及增加、编辑、查看、删除等常规功能的功能,首页以图表等多种综合控件展示。
6、基于Vue + Element 的ABP框架,前后端严格分离,后端使用最新流行的.net core 的ABP框架作为API支撑,前端界面以模块化为指导进行开发,API封装类以类的抽象封装解决共同部分接口内容。
7、整个系统除了包括权限系统模块、字典管理模块等内核模块外,提供众多前端展示案例代码参考,框架快速开发提供高效技术支持。

ABP框架的Winform端试用地址:
http://www.iqidi.com/download/abpsetup.rar

ABP框架的动态网站地址:
http://www.iqidi.com:8000

ABP框架的Vue&Element管理后端:
http://www.iqidi.com:8000/#/login

在前面随笔《
使用uView UI+UniApp开发微信小程序
》和《
使用uView UI+UniApp开发微信小程序--判断用户是否登录并跳转
》介绍了微信小程序的常规登录处理和验证码登录处理的一些经验,本篇随笔继续介绍第三种登录方式,微信授权登录。微信授权登录是系统用户表绑定了微信小程序OpenID后,通过前端发起微信的登录授权,顺利获得微信授权后获得code,并在我们自己的服务后台接口通过code解析出用户的OpenId,然后获得对应用户的身份token信息返回给前端,前端完成登录后的跳转处理。

1、微信授权登录界面

我们前面介绍过常规的账号密码登录处理和验证码登录处理,第三种登录方式微信授权登录也是很常见的,因此整合在系统中方便使用,界面效果如下所示。

这个界面很简单,只需要提供一个按钮触发授权登录即可。

不过,授权登录需要用户登录系统后绑定微信才能进行一键登录,否则是无法识别用户的openid,也就无法一键登录了。

一旦绑定微信,也就是建立了用户和小程序OpenId 之间的关联,也就可以实现微信授权登录了。授权绑定需要获取用户信息,因此需要发起用户授权的确认操作,如下界面所示。

如果需要取消,那么随时取消授权也可以,系统提供入口处理即可,一般在同一界面中根据状态绑定或者解绑。

以上就是大概的界面处理流程,剩下的就是我们需要编码实现相应的逻辑即可。

2、微信授权绑定和一键登录系统处理

用户授权绑定或者解绑,我们通过状态来识别提供相关的功能即可,如下界面代码所示。

<viewclass="bottom">
    <u-buttonv-if="!vuex_user.openid"shape="circle"type="success"@click="authLogin">授权绑定</u-button>
    <u-buttonv-else shape="circle"type="error"@click="cancelBind">取消绑定</u-button>
    <u-gapheight="20"></u-gap>
    <u-buttonshape="circle"@click="gotoMyInfo">返回我的页面</u-button>
</view>

微信授权登录的绑定微信操作代码如下所示。

首先先通过uni.getUserProfile获得用户信息,返回的信息,不包括openid信息,只是一些基础的昵称,头像等信息,如下所示

不过它本身的加密信息,是我们可以通过它来在服务器后端解析出来openid的。注意,前端在正式发布后,腾信API是不在授权名单中,因此不能通过纯前端的方式解析openid,除非通过定义云函数方式调用(也就是离不开服务器)。

我们这里通过服务器端进行解析,因此服务端的域名是在授权Https列表中的

一般服务器端的接口顺利获取openid等数据,就直接resolve执行成功的回调操作

服务端直接通过jscode2session的处理即可获取对应的数据了

        public JSCode2SessionResult JSCode2Session(string appid, string secret, string js_code, string grant_type = "authorization_code")
{
var url = string.Format("https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type={3}", appid, secret, js_code, grant_type);var result = WeJsonHelper<JSCode2SessionResult>.ConvertJson(url);returnresult;
}

如果前端通过下面代码测试非正式的环境,也可以获得openid,正式环境下,小程序不接受https://api.weixin.qq.com的域名的。

uni.request({
url:
'https://api.weixin.qq.com/sns/jscode2session?appid=' +data.appid+ '&secret=' +data.secret+ '&js_code=' +loginRes.code+ '&grant_type=authorization_code',
success: codeRes
=>{//console.log(codeRes) resolve(codeRes.data)
},
fail: ()
=>{var tips = '获取 SesssionKey OpenId 失败'vm.$u.toast(tips)
reject(tips)
},
})

一般我们获得用户的openid等详细信息,我们可以把这些信息写入服务器的相关表中,并更新用户的openid即可

服务端接口接受用户数据,并写入或者更新小程序用户表信息,同时更新系统用户的openid即可。

一般前端顺利获得结果,就跳转用户页面即可。

	setTimeout(() => {
		uni.switchTab({ url: '/pages/task/login/myinfo' });
	}, 3000);

而取消用户绑定,只需要置空服务器端用户表对应记录的openId,并置空本地用户的openid信息即可。

cancelBind() { //取消绑定微信
    var param = {id: this.vuex_user.id}this.$u.api.User.CancelBindWechat(param).then(res=>{
console.log(res)
if(res.success){this.$u.toast('已取消绑定')this.$u.vuex('vuex_user.openid', '')this.$u.vuex('vuex_user.wechatInfo', null) //重置微信信息 this.headimg = '/static/images/wx_ico.png'}else{this.$u.toast('取消绑定失败')
}
})
},

至此,我们就完成了用户绑定和解绑微信的相关操作了。剩下的就是我们需要处理登录界面上一键登录的处理了。

登录的方法代码如下所示。

login() {
let _self
= this;//0. 显示加载的效果 uni.showLoading({ title: '登录中...'});var data ={}
_self.$u.api.User.wechatlogin(data)
//微信登陆授权 .then(res =>{
console.log(res);
uni.hideLoading();
_self.$u.toast(
'登录成功');
uni.switchTab({
url:
'/pages/task/login/myinfo'});
})
.
catch(error =>{
console.log(error);
_self.error
=error;
});
}

也就是我们封装了一个微信授权登录的逻辑,一旦成功返回,就跳转到指定页面上去即可。

其中封装的Promise函数逻辑代码如下所示

先在前端发起登录处理,获得code提交给服务器进行处理验证即可。

大概的步骤分为:

1)通过code 换取 session_key

2)从系统中判断是否存在用户

3)根据用户身份生成tokenresult

代码逻辑如下所示

以上就是微信授权绑定和一键登录系统的相关处理逻辑及代码,其实无论常规的账号密码登陆、短信验证码登陆、微信一键登录,大致的处理过程都大同小异,就是先通过直接或者间接的方式确认用户身份的有效性,然后获得用户的信息,构建返回的token令牌信息给前端使用即可。前端则负责处理结果逻辑,是提示用户还是顺利跳转到默认用户页面即可。

相关文章:

使用uView UI+UniApp开发微信小程序

使用uView UI+UniApp开发微信小程序--判断用户是否登录并跳转