uni-quick-login.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. <template>
  2. <view class="quick-login-box">
  3. <view class="item" v-for="(item,index) in servicesList" :key="index"
  4. @click="item.path?to(item.path):login_before(item.id,false)">
  5. <image class="logo" :src="item.logo" mode="widthFix"></image>
  6. <text class="login-title">{{item.text}}</text>
  7. </view>
  8. </view>
  9. </template>
  10. <script>
  11. import {
  12. mapGetters,
  13. mapMutations
  14. } from 'vuex';
  15. //前一个窗口的页面地址。控制点击切换快捷登录方式是创建还是返回
  16. import loginSuccess from '@/pages/ucenter/login-page/common/loginSuccess.js';
  17. export default {
  18. computed: {
  19. loginConfig() {
  20. return getApp().globalData.config.router.login
  21. },
  22. agreements() {
  23. return getApp().globalData.config.about.agreements || []
  24. }
  25. },
  26. data() {
  27. return {
  28. servicesList: [{
  29. "id": "username",
  30. "text": "账号登录",
  31. "logo": "/static/uni-quick-login/user.png",
  32. "path": "/pages/ucenter/login-page/pwd-login/pwd-login"
  33. },
  34. {
  35. "id": "smsCode",
  36. "text": "短信验证码",
  37. "logo": "/static/uni-quick-login/sms.png",
  38. "path": "/pages/ucenter/login-page/index/index"
  39. }
  40. ],
  41. oauthServices: [],
  42. config: {
  43. "weixin": {
  44. "text": "微信登录",
  45. "logo": "/static/uni-quick-login/wechat.png",
  46. },
  47. "apple": {
  48. "text": "苹果登录",
  49. "logo": "/static/uni-quick-login/apple.png",
  50. },
  51. "univerify": {
  52. "text": "一键登录",
  53. "logo": "/static/uni-quick-login/univerify.png",
  54. },
  55. "qq": {
  56. "text": "QQ登录",//暂未提供该登录方式的接口示例
  57. "logo": "/static/uni-quick-login/univerify.png",
  58. },
  59. "xiaomi": {
  60. "text": "小米登录",//暂未提供该登录方式的接口示例
  61. "logo": "/static/uni-quick-login/univerify.png",
  62. },
  63. "sinaweibo": {
  64. "text": "微博登录",//暂未提供该登录方式的接口示例
  65. "logo": "/static/uni-quick-login/univerify.png",
  66. }
  67. },
  68. univerifyStyle:{ //一键登录弹出窗的样式配置参数
  69. "fullScreen": true, // 是否全屏显示,true表示全屏模式,false表示非全屏模式,默认值为false。
  70. "backgroundColor": "#ffffff", // 授权页面背景颜色,默认值:#ffffff
  71. "buttons": { // 自定义登陆按钮
  72. "iconWidth": "45px", // 图标宽度(高度等比例缩放) 默认值:45px
  73. "list": []
  74. },
  75. "privacyTerms": {
  76. "defaultCheckBoxState": false, // 条款勾选框初始状态 默认值: true
  77. "textColor": "#BBBBBB", // 文字颜色 默认值:#BBBBBB
  78. "termsColor": "#5496E3", // 协议文字颜色 默认值: #5496E3
  79. "prefix": "我已阅读并同意", // 条款前的文案 默认值:“我已阅读并同意”
  80. "suffix": "并使用本机号码登录", // 条款后的文案 默认值:“并使用本机号码登录”
  81. "privacyItems": []
  82. }
  83. }
  84. }
  85. },
  86. watch: {
  87. agree(agree) {
  88. this.univerifyStyle.privacyTerms.defaultCheckBoxState = agree
  89. }
  90. },
  91. props: {
  92. agree: {
  93. type: Boolean,
  94. default () {
  95. return false
  96. }
  97. }
  98. },
  99. async created() {
  100. this.univerifyStyle.privacyTerms.privacyItems = this.agreements
  101. let servicesList = this.servicesList
  102. //获取当前环境能用的快捷登录方式
  103. // #ifdef MP-WEIXIN
  104. let id = 'weixin'
  105. if (this.loginConfig.includes(id)) {
  106. servicesList.push({
  107. ...this.config[id],
  108. id
  109. })
  110. }
  111. // #endif
  112. // #ifdef APP-PLUS
  113. this.oauthServices = await new Promise((callBack)=>{
  114. plus.oauth.getServices(oauthServices => {
  115. callBack(oauthServices.filter(({nativeClient,id})=>nativeClient&&this.loginConfig.includes(id)))
  116. //只返回1.应用支持 && 2.手机已安装对应客户端 && 3.uni-card.config.js配置项中存在的快捷登录方式
  117. }, err => {
  118. callBack([])
  119. uni.hideLoading()
  120. uni.showModal({
  121. title: '获取服务供应商失败:' + JSON.stringify(err),
  122. showCancel: false,
  123. confirmText: '知道了'
  124. });
  125. console.error('获取服务供应商失败:' + JSON.stringify(err));
  126. })
  127. })
  128. // #endif
  129. //添加已配置且可用的第三方快捷登陆项
  130. servicesList = servicesList.concat(this.oauthServices.map( ({id})=>{
  131. return {...this.config[id],id}
  132. }))
  133. //设置一键登录功能底下的快捷登陆按钮
  134. servicesList.forEach(({id,logo})=>{
  135. if(id != 'univerify'){
  136. this.univerifyStyle.buttons.list.push({"iconPath":logo,"provider":id})
  137. }
  138. })
  139. //去掉当前页面对应的登录选项
  140. this.servicesList = servicesList.filter(item=>{
  141. return item.path != this.getRoute(1)
  142. })
  143. // console.log('servicesList',servicesList,this.servicesList);
  144. },
  145. methods: {
  146. ...mapMutations({
  147. setUserInfo: 'user/login'
  148. }),
  149. getRoute(n = 0) {
  150. let pages = getCurrentPages();
  151. // console.log('route-pages-length', pages.length);
  152. if (n > pages.length) {
  153. return ''
  154. }
  155. return '/' + pages[pages.length - n].route
  156. },
  157. to(path) {
  158. // console.log('比较', this.getRoute(2), path)
  159. if (this.getRoute(2) == path) { // 控制路由是重新打开还是返回,避免重复打开页面
  160. uni.navigateBack();
  161. } else {
  162. uni.navigateTo({
  163. url: path
  164. })
  165. }
  166. },
  167. login_before(type, navigateBack = true) {
  168. if (!this.agree&&type!='univerify') {
  169. return uni.showToast({
  170. title: '你未同意隐私政策协议',
  171. icon: 'none'
  172. });
  173. }
  174. uni.showLoading({
  175. mask: true
  176. })
  177. // console.log(arguments);
  178. let oauthService = this.oauthServices.find((service) => service.id == type)
  179. // console.log(type);
  180. // #ifdef APP-PLUS
  181. //请勿直接使用前端获取的unionid或openid直接用于登录,前端的数据都是不可靠的
  182. if (type == 'weixin') {
  183. return oauthService.authorize(({
  184. code
  185. }) => {
  186. // console.log(code);
  187. this.login({
  188. code
  189. }, type)
  190. },
  191. err => {
  192. uni.hideLoading()
  193. console.log(err);
  194. uni.showModal({
  195. content: JSON.stringify(err),
  196. showCancel: false
  197. });
  198. })
  199. }
  200. // #endif
  201. uni.login({
  202. "provider": type,
  203. "univerifyStyle": this.univerifyStyle,
  204. complete: (e) => {
  205. console.log(e);
  206. },
  207. success: async e => {
  208. console.log(e);
  209. if (type == 'apple') {
  210. let res = await this.getUserInfo({
  211. provider: "apple"
  212. })
  213. uni.hideLoading()
  214. Object.assign(e.authResult, res.userInfo)
  215. }
  216. // #ifdef MP-WEIXIN
  217. if (type == 'weixin') {
  218. return this.login({
  219. code: e.code
  220. }, type)
  221. }
  222. // #endif
  223. this.login(e.authResult, type)
  224. },
  225. fail: (err) => {
  226. uni.hideLoading()
  227. console.log(err);
  228. if (type == 'univerify') {
  229. if (err.metadata && err.metadata.error_data) {
  230. uni.showToast({
  231. title: "一键登录:" + err.metadata.error_data,
  232. icon: 'none'
  233. });
  234. }
  235. if (err.errMsg) {
  236. uni.showToast({
  237. title: "一键登录:" + err.errMsg,
  238. icon: 'none'
  239. });
  240. }
  241. switch (err.errCode) {
  242. case 30002:
  243. console.log('在一键登录界面,点击其他登录方式');
  244. break;
  245. case 30003:
  246. console.log('关闭了登录');
  247. if (navigateBack) {
  248. uni.navigateBack()
  249. }
  250. break;
  251. case 30006:
  252. uni.showModal({
  253. title: "登录服务初始化错误",
  254. content: err.metadata.error_data,
  255. showCancel: false,
  256. confirmText: '知道了',
  257. });
  258. break;
  259. case "30008":
  260. uni.showToast({
  261. title: '点击了第三方登陆',
  262. icon: 'none'
  263. });
  264. console.log('点击了第三方登陆,provider:',err.provider);
  265. let {path} = this.servicesList.find(item=>item.id==err.provider)||{}
  266. console.log('path',path);
  267. if(path&&path!=this.getRoute(1)){ //存在路径,且并不是当前已经打开的路径
  268. this.to(path)
  269. }else{
  270. this.login_before(err.provider)
  271. }
  272. break;
  273. default:
  274. console.log(9527, err);
  275. break;
  276. }
  277. }
  278. }
  279. })
  280. },
  281. login(params, type) { //联网验证登录
  282. console.log({
  283. params,
  284. type
  285. });
  286. let action = 'loginBy' + type.trim().toLowerCase().replace(type[0], type[0].toUpperCase())
  287. uniCloud.callFunction({
  288. name: 'uni-id-cf',
  289. data: {
  290. action,
  291. params
  292. },
  293. success: ({
  294. result
  295. }) => {
  296. console.log(result);
  297. if (result.code === 0) {
  298. if (type == 'univerify') {
  299. uni.closeAuthView()
  300. }
  301. uni.hideLoading()
  302. loginSuccess(result)
  303. delete result.userInfo.token
  304. this.setUserInfo(result.userInfo)
  305. } else {
  306. uni.showModal({
  307. content: result.msg,
  308. showCancel: false
  309. });
  310. }
  311. },
  312. complete: () => {
  313. uni.hideLoading()
  314. }
  315. })
  316. },
  317. async getUserInfo(e) {
  318. return new Promise((resolve, reject) => {
  319. uni.getUserInfo({
  320. ...e,
  321. success: (res) => {
  322. resolve(res);
  323. },
  324. fail: (err) => {
  325. uni.showModal({
  326. content: JSON.stringify(err),
  327. showCancel: false
  328. });
  329. reject(err);
  330. }
  331. })
  332. })
  333. }
  334. }
  335. }
  336. </script>
  337. <style scoped>
  338. .quick-login-box {
  339. flex-direction: row;
  340. width: 750rpx;
  341. justify-content: space-around;
  342. position: fixed;
  343. bottom: 10rpx;
  344. left: 0;
  345. }
  346. .item {
  347. flex-direction: column;
  348. justify-content: center;
  349. align-items: center;
  350. height: 200rpx;
  351. }
  352. .logo {
  353. width: 60rpx;
  354. height: 60rpx;
  355. }
  356. .login-title {
  357. margin-top: 4px;
  358. font-size: 26rpx;
  359. }
  360. </style>