基于金蝶云星空后台的微信小程序-登录功能原创
金蝶云社区-比邻星
比邻星
0人赞赏了该文章 104次浏览 未经作者许可,禁止转载编辑于2024年10月08日 19:55:30
summary-icon摘要由AI智能服务提供

本文档描述了一个基于手机号和密码登录的供应商小程序项目的设计思路、后台代码实现以及前端配置。设计思路部分指出,项目通过手机号和密码登录,并在金蝶云星空的供应商基础资料中添加相应字段以验证登录信息。后台代码部分展示了WebApi中用于处理登录请求的SupplierWebApi类,包括根据手机号和密码查询供应商ID的逻辑。前端代码部分则涉及全局配置和请求处理,包括设置请求头、处理响应以及错误处理等。整体而言,该项目通过前后端协作实现了基于手机号和密码的供应商登录功能。

1.png

一、设计思路

本项目登录采用手机号和密码的方式进行登录,由于此小程序是给供应商使用,故在金蝶云星空的供应商基础资料上添加两个字段【微信小程序登录手机号】【微信小程序登录密码】,通过验证小程序填的手机号和密码是否正确,如果正确则返回供应商Id,用于后续查询数据的依据。

二、后台代码

2.1WebApi

namespace ZF.Kingdee.ServicePlugIn.WebApi.WeChart
{
    public class SupplierWebApi : AbstractWebApiBusinessService
    {
        Context _ctx;
        public SupplierWebApi(KDServiceContext context) : base(context)
        {
            _ctx = this.KDContext.Session.AppContext;
        }
        /// <summary>
        /// 根据供应商微信小程序手机号和微信小程序密码获取供应商ID
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public string Login(string param)
        {
            CommonOutPut outPut = new CommonOutPut();
            try
            {
                SupplierLoginInPut rec = JsonHelper.JsonToT<SupplierLoginInPut>(param);
                string sql = string.Format(@"SELECT ISNULL(SUP.FSUPPLIERID,0) '供应商ID' FROM 
                t_BD_Supplier SUP WHERE SUP.F_T_PhoneNumber = '{0}' AND SUP.F_T_PassWord = '{1}' 
                AND  SUP.FDocumentStatus = 'C' AND SUP.FForbidStatus = 'A'", rec.phoneNumber,rec.password);
                int supplierId = DBServiceHelper.ExecuteScalar(_ctx, sql, 0);
                if (supplierId != 0)
                {
                    outPut.isSuccess = true;
                    outPut.msg = "登录成功!";
                    outPut.data = supplierId;
                }
                else
                {
                    outPut.isSuccess = false;
                    outPut.msg = "手机号或密码错误!";
                }
            }
            catch(Exception ex)
            {
                outPut.isSuccess = false;
                outPut.msg = ex.Message.ToString();
            }
            return JsonHelper.TToJson<CommonOutPut>(outPut);
        }
    }
}

2.2CommonOutPut

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ZF.Kingdee.Model.WeChart
{
    public class CommonOutPut
    {
        public bool isSuccess { get; set; }
        public string msg { get; set; }
        public object data { get; set; }
    }
}

三、前端代码

3.1config.js

// 应用全局配置
module.exports = {
  baseUrl: 'https://erp.xxx.com/K3cloud',
  // 应用信息
  appInfo: {
    // 应用名称
    name: "xxxApp",
    // 应用版本
    version: "1.0.0",
    // 应用logo
    logo: "/static/logo.png",
    // 官方网站
    site_url: "http://xxx.vip",
    // 政策协议
    agreements: [{
        title: "隐私政策",
        url: "https://xxx.vip/protocol.html"
      },
      {
        title: "用户服务协议",
        url: "https://xxx.vip/protocol.html"
      }
    ]
  }
}

3.2request.js

import store from '@/store'
import config from '@/config'
import {
	getToken,
	removeCookie,
	getCookies,
	setCookies
} from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import {
	toast,
	showConfirm,
	tansParams
} from '@/utils/common'

let timeout = 10000
const baseUrl = config.baseUrl

const request = config => {
	// 是否需要设置 token
	const isToken = (config.headers || {}).isToken === false
	if (getToken() && !isToken) {
		config.header = config.header || {};
		config.header['Authorization'] = 'Bearer ' + getToken()
		console.log(getToken())
	}
	// get请求映射params参数
	if (config.params) {
		let url = config.url + '?' + tansParams(config.params)
		url = url.slice(0, -1)
		config.url = url
	}
	return new Promise((resolve, reject) => {
		const cookieHeader= getCookies()?{'Cookie': getCookies()}:{}
		uni.request({
				method: config.method || 'get',
				timeout: config.timeout || timeout,
				url: config.baseUrl || baseUrl + config.url,
				data: config.data,
				header: Object.assign({}, config.header, cookieHeader),
				withCredentials: true,
				dataType: 'json'
			}).then(response => {
				let [error, res] = response
				if (error) {
					toast('后端接口连接异常')
					// reject('后端接口连接异常')
					resolve({
						"isSuccess": false,
						"msg": '后端接口连接异常',
						"data": null
					})
					return
				}
				const code = res.data.code || 200
				const msg = errorCode[code] || res.data.msg || errorCode['default']
				if (code === 401) {
					removeCookie();
					showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => {
						if (res.confirm) {
							store.dispatch('LogOut').then(res => {
								uni.reLaunch({
									url: '/pages/login'
								})
							})
						}
					})
					// reject('无效的会话,或者会话已过期,请重新登录。')
					resolve({
						"isSuccess": false,
						"msg": '无效的会话,或者会话已过期,请重新登录。',
						"data": null
					})
				} else if (code === 500) {
					toast(msg)
					// reject('500')
					resolve({
						"isSuccess": false,
						"msg": message,
						"data": null
					});
					return;
				} else if (code !== 200) {
					toast(msg)
					// reject(code)
					resolve({
						"isSuccess": false,
						"msg": message,
						"data": null
					})
					return;
				} else if (code == 200 && msg == "{ctx == null}") {
					removeCookie();
					showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => {
						if (res.confirm) {
							store.dispatch('LogOut').then(res => {
								uni.reLaunch({
									url: '/pages/login'
								})
							})
						}
					})
					return;
				}
				setCookies(res.cookies)
				resolve(res.data)
			})
			.catch(error => {
				let {
					message
				} = error
				if (message === 'Network Error') {
					message = '后端接口连接异常'
				} else if (message.includes('timeout')) {
					message = '系统接口请求超时'
				} else if (message.includes('Request failed with status code')) {
					message = '系统接口' + message.substr(message.length - 3) + '异常'
				}
				toast(message)
				resolve({
					"isSuccess": false,
					"msg": message,
					"data": null
				})
			})
	})
}

export default request

3.3base.js

export const body= (data) => {
	return {
		format: 1,
		useragent: "ApiClient",
		rid: "22222222222",
		timestamp: "111111111",
		v: "1.0",
		parameters:Array.isArray(data)?data: [data]
	}
}

3.4login.js

import request from '@/utils/request'
import {body} from "@/api/base.js"
// 金蝶登录
export function loginByAppSecret(){
        // 第三方授权登录维护的信息
	var ps=body(['账套Id','集成用户','应用Id','应用密钥','2052']);
	return request({
		'url': '/Kingdee.BOS.WebApi.ServicesStub.AuthService.LoginByAppSecret.common.kdsvc',
		headers: {
			isToken: false
		},
		'method': 'post',
		'data': ps
	})
}

// 登录方法
export function login({phoneNumber, password}) {
	const data = body({
		phoneNumber,
		password
	})
	return request({
		'url': '/ZF.Kingdee.ServicePlugIn.WebApi.WeChart.SupplierWebApi.Login,ZF.Kingdee.common.kdsvc',
		headers: {
			isToken: false
		},
		'method': 'post',
		'data': data
	})
}

3.5login.vue

<template>
<view>
<view class="logo-content align-center justify-center flex">
<image style="width: 100rpx;height: 100rpx;" :src="globalConfig.appInfo.logo" mode="widthFix">
</image>
<text>XXX供应商协同</text>
</view>
<view>
<view class="input-item flex align-center">
<view class="iconfont icon-user icon"></view>
<input v-model="loginForm.phoneNumber" type="text" placeholder="请输入账号" maxlength="30" />
</view>
<view class="input-item flex align-center">
<view class="iconfont icon-password icon"></view>
<input v-model="loginForm.password" type="password" placeholder="请输入密码" maxlength="20" />
</view>
<view class="flex align-center">
<checkbox-group @change="onRememberMe">
<label>
<checkbox value="1" :checked="remember=='1'" style="transform:scale(0.7)"/>记住账号
</label> 
</checkbox-group>
</view>
<view class="input-item flex align-center" v-if="captchaEnabled">
<view class="iconfont icon-code icon"></view>
<input v-model="loginForm.code" type="number" placeholder="请输入验证码" maxlength="4" />
<image :src="codeUrl" @click="getCode"></image>
</view>
<view>
<button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">登录</button>
</view>
</view>

<!-- <view class="xieyi text-center">
<text>登录即代表同意</text>
<text @click="handleUserAgrement">《用户协议》</text>
<text @click="handlePrivacy">《隐私协议》</text>
</view> -->
</view>
</template>

<script>
import {
getCodeImg,
loginByAppSecret,
login
} from '@/api/login'

import {
setToken
} from "@/utils/auth.js"

export default {
data() {
return {
remember: false,
codeUrl: "",
captchaEnabled: false,
globalConfig: getApp().globalData.config,
loginForm: {
phoneNumber: "",
password: ""
}
}
},
created() {
this.getCode();
this.remember=uni.getStorageSync("remember");
if(this.remember=='1'){
this.loginForm.phoneNumber=uni.getStorageSync("phoneNumber");
this.loginForm.password=uni.getStorageSync("password");
}

},
methods: {
// app授权
async appAuth() {
await loginByAppSecret();
},
// 隐私协议
handlePrivacy() {
let site = this.globalConfig.appInfo.agreements[0]
this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`)
},
// 用户协议
handleUserAgrement() {
let site = this.globalConfig.appInfo.agreements[1]
this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`)
},
// 获取图形验证码
getCode() {
// getCodeImg().then(res => {
//   this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled
//   if (this.captchaEnabled) {
//     this.codeUrl = 'data:image/gif;base64,' + res.img
//     this.loginForm.uuid = res.uuid
//   }
// })
},
// 登录方法
async handleLogin() {
if (this.loginForm.phoneNumber === "") {
this.$modal.msgError("请输入您的账号")
} else if (this.loginForm.password === "") {
this.$modal.msgError("请输入您的密码")
} else {
this.$modal.loading("登录中,请耐心等待...") 
this.pwdLogin()
}
},
// 密码登录
async pwdLogin() {
await this.appAuth();
const res = await login(this.loginForm);
this.$modal.closeLoading()
if (res.isSuccess) {
this.$store.commit('SET_SUPPLIERID', res.data)
setToken(res.data)
uni.setStorageSync("remember",this.remember)
if(this.remember=="1"){
uni.setStorageSync("phoneNumber",this.loginForm.phoneNumber)
uni.setStorageSync("password",this.loginForm.password)
}
this.loginSuccess()
} else {
this.$modal.msgError(res.msg || "登录失败")
}
},
// 登录成功后,处理函数
loginSuccess(result) {
// 设置用户信息
this.$tab.reLaunch('/pages/work/index')
// this.$store.dispatch('GetInfo').then(res => {
//   this.$tab.reLaunch('/pages/index')
// })
},
onRememberMe(e){ 
this.remember=e.detail.value[0]||'0';
}
}
}
</script>

<style>
page {
background-color: #FFFFFF;
}

.normal-login-container {
width: 100%;

.logo-content {
width: 100%;
font-size: 21px;
text-align: center;
padding-top: 15%;

image {
border-radius: 4px;
}

.title {
margin-left: 10px;
}
}

.login-form-content {
text-align: center;
margin: 20px auto;
margin-top: 15%;
width: 80%;

.input-item {
margin: 20px auto;
background-color: #f5f6f7;
height: 45px;
border-radius: 20px;

.icon {
font-size: 38rpx;
margin-left: 10px;
color: #999;
}

.input {
width: 100%;
font-size: 14px;
line-height: 20px;
text-align: left;
padding-left: 15px;
}

}

.login-btn {
margin-top: 40px;
height: 45px;
}

.xieyi {
color: #333;
margin-top: 20px;
}
}

.easyinput {
width: 100%;
}
}

.login-code-img {
height: 45px;
}
</style>


图标赞 0
0人点赞
还没有人点赞,快来当第一个点赞的人吧!
图标打赏
0人打赏
还没有人打赏,快来当第一个打赏的人吧!