feat: 1. 数脉api鉴别身份证。 2. 后台+微信登陆优化

This commit is contained in:
李琦
2026-08-04 13:56:14 +08:00
parent effaee6229
commit fe841e772a
5 changed files with 86 additions and 49 deletions

View File

@@ -29,10 +29,11 @@ export function sendDoctorWxCode(phone, password) {
} }
export function doctorWxLogin(payload) { export function doctorWxLogin(payload) {
// client_type=mobile医生/药师/诊所管理员等统一按手机端会话管理
return req.request({ return req.request({
url: `${AUTH_PREFIX}/login`, url: `${AUTH_PREFIX}/login`,
method: 'POST', method: 'POST',
data: payload, data: { ...(payload || {}), client_type: 'mobile' },
header: { isToken: false }, header: { isToken: false },
}); });
} }
@@ -45,10 +46,11 @@ export function getDoctorWxSiblingAccounts() {
} }
export function switchDoctorWxAccount(payload) { export function switchDoctorWxAccount(payload) {
// client_type=mobile切换账号按手机端会话管理
return doctorAuthRequest({ return doctorAuthRequest({
url: '/switch-account', url: '/switch-account',
method: 'POST', method: 'POST',
data: payload, data: { ...(payload || {}), client_type: 'mobile' },
}); });
} }
@@ -61,10 +63,11 @@ export function getDoctorWxAuthConfig() {
} }
export function doctorWxLoginByWechat(payload) { export function doctorWxLoginByWechat(payload) {
// 微信登录同样标记为手机端会话
return req.request({ return req.request({
url: `${AUTH_PREFIX}/wx-login`, url: `${AUTH_PREFIX}/wx-login`,
method: 'POST', method: 'POST',
data: payload, data: { ...(payload || {}), client_type: 'mobile' },
header: { isToken: false }, header: { isToken: false },
}); });
} }

View File

@@ -89,46 +89,21 @@ const reqInterceptor = async (options) => {
} }
/** /**
* 响应拦截器 * 登录失效统一处理:弹窗提示并按 loginMode 清理 token 后跳转登录页
* @param {string} tipMsg 提示文案
* @param {*} response 原始响应
* @param {object} conf 请求配置(供 _responseLog 使用)
*/ */
const resInterceptor = (response, conf = {}) => { const handleAuthExpired = (tipMsg, response, conf) => {
// 网络状态码 // 防重复弹窗:并发 401 只提示一次
const statusCode = response.statusCode|| response.errcode; if (!uni.__xkAuthModalShowing) {
// 响应拦截器 uni.__xkAuthModalShowing = true
if (statusCode >= 200 && statusCode < 300) { uni.showModal({
_responseLog(response, conf, "response 200-299") title: '登录失效',
// 解密Yii业务在 dataLaravel jok业务在 result content: tipMsg,
let res = response.data showCancel: false,
if (res == null || typeof res !== 'object') { confirmText: '重新登录',
return res success() {
}
if (res.data != null) {
res.data = getRes(res.data)
}
if (res.result != null) {
res.result = getRes(res.result)
}
return res
} else if (statusCode === 500) {
uni.showToast({
icon: 'error',
title: response['msg'] || errorCode[statusCode]
})
_responseLog(response, conf, "response 500")
// 增加一个控制字段wakaryReqToReject 使 reject的内容更加可控
return {
// 根据当前字段来判断是否reject
wakaryReqToReject: true,
// 下面可以配置其他返回信息方便统一处理reject
// 以下内容作为reject的返回根据需求处理返回具体错误信息
msg: "服务器错误",
res: response
}
} else if (statusCode === 401) {
uni.showToast({
icon: 'error',
title: response['msg'] || response['message'] || errorCode[statusCode]
})
const loginMode = uni.getStorageSync('loginMode') const loginMode = uni.getStorageSync('loginMode')
if (loginMode === 'platform_admin') { if (loginMode === 'platform_admin') {
uni.removeStorageSync('platform_admin_token') uni.removeStorageSync('platform_admin_token')
@@ -151,19 +126,65 @@ const resInterceptor = (response, conf = {}) => {
uni.removeStorageSync('loginInfo') uni.removeStorageSync('loginInfo')
uni.removeStorageSync('identity') uni.removeStorageSync('identity')
} }
setTimeout(() => { uni.__xkAuthModalShowing = false
uni.reLaunch({ url: '/pages/login/index' }) uni.reLaunch({ url: '/pages/login/index' })
}, 1000) },
fail() {
uni.__xkAuthModalShowing = false
}
})
}
_responseLog(response, conf, "response 401") _responseLog(response, conf, "response 401")
return {
wakaryReqToReject: true,
msg: tipMsg,
res: response
}
}
/**
* 响应拦截器
*/
const resInterceptor = (response, conf = {}) => {
// 网络状态码
const statusCode = response.statusCode|| response.errcode;
// 响应拦截器
if (statusCode >= 200 && statusCode < 300) {
_responseLog(response, conf, "response 200-299")
// 解密Yii业务在 dataLaravel jok业务在 result
let res = response.data
if (res == null || typeof res !== 'object') {
return res
}
if (res.data != null) {
res.data = getRes(res.data)
}
if (res.result != null) {
res.result = getRes(res.result)
}
// Laravel notAuth 返回 HTTP 200 + 业务码 401需与 HTTP 401 走同一套登录失效处理
const bizCode = Number(res.code != null ? res.code : res.errcode)
if (bizCode === 401) {
return handleAuthExpired(res.msg || res.message || '账号需重新登录', response, conf)
}
return res
} else if (statusCode === 500) {
uni.showToast({
icon: 'error',
title: response['msg'] || errorCode[statusCode]
})
_responseLog(response, conf, "response 500")
// 增加一个控制字段wakaryReqToReject 使 reject的内容更加可控 // 增加一个控制字段wakaryReqToReject 使 reject的内容更加可控
return { return {
// 根据当前字段来判断是否reject // 根据当前字段来判断是否reject
wakaryReqToReject: true, wakaryReqToReject: true,
// 下面可以配置其他返回信息方便统一处理reject // 下面可以配置其他返回信息方便统一处理reject
// 以下内容作为reject的返回根据需求处理返回具体错误信息 // 以下内容作为reject的返回根据需求处理返回具体错误信息
msg: response['msg'] || errorCode[statusCode], msg: "服务器错误",
res: response res: response
} }
} else if (statusCode === 401) {
return handleAuthExpired(response['msg'] || response['message'] || errorCode[statusCode] || '账号需重新登录', response, conf)
} else { } else {
uni.showToast({ uni.showToast({
icon: 'error', icon: 'error',

View File

@@ -169,12 +169,17 @@ export default {
uni.showLoading({ title: '正在获取验证码' }); uni.showLoading({ title: '正在获取验证码' });
sendDoctorWxCode(this.form.mobile, this.form.password) sendDoctorWxCode(this.form.mobile, this.form.password)
.then((res) => { .then((res) => {
if (res.code === 0) { // HTTP 200 但业务 code 非 0 时 reject统一走 catch 弹 toast
if (res.code !== 0) {
return Promise.reject(new Error(res.message || res.msg || '获取验证码失败'));
}
this.$refs.uCode.start(); this.$refs.uCode.start();
if (res.result && res.result.code) { if (res.result && res.result.code) {
this.smsCode = res.result.code; this.smsCode = res.result.code;
} }
} })
.catch((err) => {
this.$toast(err.message || err.msg || '获取验证码失败');
}) })
.finally(() => { .finally(() => {
uni.hideLoading(); uni.hideLoading();

View File

@@ -126,7 +126,9 @@
<view class="info"> <view class="info">
<text>医师</text> <text>医师</text>
<image v-if="view.doctorSignImage" :src="checkImageUrl(view.doctorSignImage)" mode="aspectFit"></image> <image v-if="view.doctorSignImage" :src="checkImageUrl(view.doctorSignImage)" mode="aspectFit"></image>
<text v-else class="name">{{ view.doctorName }}</text> <!-- 二次签名与处方详情页一致doctor_second_sign=1 时再展示一张 -->
<image v-if="view.doctorSecondSign == 1 && view.doctorSignImage" :src="checkImageUrl(view.doctorSignImage)" mode="aspectFit"></image>
<text v-else-if="!view.doctorSignImage" class="name">{{ view.doctorName }}</text>
</view> </view>
<view class="info"> <view class="info">
<text>审核药师</text> <text>审核药师</text>
@@ -214,6 +216,8 @@ export default {
|| (w.data.doctor_info && w.data.doctor_info.identity_info && w.data.doctor_info.identity_info.sign_image) || (w.data.doctor_info && w.data.doctor_info.identity_info && w.data.doctor_info.identity_info.sign_image)
|| (w.data.doctorInfo && w.data.doctorInfo.identityInfo && w.data.doctorInfo.identityInfo.sign_image) || (w.data.doctorInfo && w.data.doctorInfo.identityInfo && w.data.doctorInfo.identityInfo.sign_image)
|| '' || ''
// 透传二次签名标记,供医师签名区双图展示
mapped.doctorSecondSign = w.data.doctor_second_sign
mapped.pharmacistSignImage = mapped.pharmacistSignImage =
w.data.Pharmacist_sign_image w.data.Pharmacist_sign_image
|| (w.data.pharmacist_info && w.data.pharmacist_info.identity && w.data.pharmacist_info.identity.sign_image) || (w.data.pharmacist_info && w.data.pharmacist_info.identity && w.data.pharmacist_info.identity.sign_image)

View File

@@ -118,7 +118,9 @@
<view class="info"> <view class="info">
<text>医师</text> <text>医师</text>
<image v-if="view.doctorSignImage" :src="checkImageUrl(view.doctorSignImage)" mode="aspectFit"></image> <image v-if="view.doctorSignImage" :src="checkImageUrl(view.doctorSignImage)" mode="aspectFit"></image>
<text v-else class="name">{{ view.doctorName }}</text> <!-- 二次签名与处方详情页一致doctor_second_sign=1 时再展示一张 -->
<image v-if="view.doctorSecondSign == 1 && view.doctorSignImage" :src="checkImageUrl(view.doctorSignImage)" mode="aspectFit"></image>
<text v-else-if="!view.doctorSignImage" class="name">{{ view.doctorName }}</text>
</view> </view>
<view class="info"> <view class="info">
<text>审核药师</text> <text>审核药师</text>
@@ -203,6 +205,8 @@ export default {
|| (w.data.doctor_info && w.data.doctor_info.identity_info && w.data.doctor_info.identity_info.sign_image) || (w.data.doctor_info && w.data.doctor_info.identity_info && w.data.doctor_info.identity_info.sign_image)
|| (w.data.doctorInfo && w.data.doctorInfo.identityInfo && w.data.doctorInfo.identityInfo.sign_image) || (w.data.doctorInfo && w.data.doctorInfo.identityInfo && w.data.doctorInfo.identityInfo.sign_image)
|| '' || ''
// 透传二次签名标记,供医师签名区双图展示
mapped.doctorSecondSign = w.data.doctor_second_sign
mapped.pharmacistSignImage = mapped.pharmacistSignImage =
w.data.Pharmacist_sign_image w.data.Pharmacist_sign_image
|| (w.data.pharmacist_info && w.data.pharmacist_info.identity && w.data.pharmacist_info.identity.sign_image) || (w.data.pharmacist_info && w.data.pharmacist_info.identity && w.data.pharmacist_info.identity.sign_image)