diff --git a/es/aspects/AspectDict.d.ts b/es/aspects/AspectDict.d.ts index de6d4cff8..3cb0bf636 100644 --- a/es/aspects/AspectDict.d.ts +++ b/es/aspects/AspectDict.d.ts @@ -134,11 +134,13 @@ export type AspectDict = { * 微信小程序登录 * @param code 微信授权 code * @param env 小程序环境信息 + * @param wechatLoginId 可选的微信登录 ID(用于扫码登录场景) * @returns 返回登录 token */ - loginWechatMp: ({ code, env, }: { + loginWechatMp: ({ code, env, wechatLoginId, }: { code: string; env: WechatMpEnv; + wechatLoginId?: string; }, context: BackendRuntimeContext) => Promise; /** * 微信原生 APP 登录 @@ -297,6 +299,7 @@ export type AspectDict = { createWechatLogin: (params: { type: EntityDict['wechatLogin']['Schema']['type']; interval: number; + qrCodeType?: EntityDict['wechatLogin']['Schema']['qrCodeType']; }, context: BackendRuntimeContext) => Promise; /** * 解绑微信用户 diff --git a/es/aspects/token.d.ts b/es/aspects/token.d.ts index e2b32e6d0..0fe2b56bd 100644 --- a/es/aspects/token.d.ts +++ b/es/aspects/token.d.ts @@ -77,9 +77,10 @@ export declare function loginWechat({ code, env, wechatLo * @param context * @returns */ -export declare function loginWechatMp({ code, env, }: { +export declare function loginWechatMp({ code, env, wechatLoginId, }: { code: string; env: WechatMpEnv; + wechatLoginId?: string; }, context: BRC): Promise; /** * 同步从wx.getUserProfile拿到的用户信息 diff --git a/es/aspects/token.js b/es/aspects/token.js index 13e01d139..b03b97717 100644 --- a/es/aspects/token.js +++ b/es/aspects/token.js @@ -1949,9 +1949,9 @@ export async function loginWechat({ code, env, wechatLoginId, }, context) { * @param context * @returns */ -export async function loginWechatMp({ code, env, }, context) { +export async function loginWechatMp({ code, env, wechatLoginId, }, context) { const closeRootMode = context.openRootMode(); - const tokenValue = await loginFromWechatEnv(code, env, context); + const tokenValue = await loginFromWechatEnv(code, env, context, wechatLoginId); await loadTokenInfo(tokenValue, context); closeRootMode(); return tokenValue; diff --git a/es/aspects/wechatLogin.d.ts b/es/aspects/wechatLogin.d.ts index 9c13e80d8..24f4c249b 100644 --- a/es/aspects/wechatLogin.d.ts +++ b/es/aspects/wechatLogin.d.ts @@ -3,4 +3,5 @@ import { BRC } from '../types/RuntimeCxt'; export declare function createWechatLogin(params: { type: EntityDict['wechatLogin']['Schema']['type']; interval: number; + qrCodeType?: EntityDict['wechatLogin']['Schema']['qrCodeType']; }, context: BRC): Promise; diff --git a/es/aspects/wechatLogin.js b/es/aspects/wechatLogin.js index 27f993f0c..efe9c372e 100644 --- a/es/aspects/wechatLogin.js +++ b/es/aspects/wechatLogin.js @@ -1,6 +1,6 @@ import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid'; export async function createWechatLogin(params, context) { - const { type, interval } = params; + const { type, interval, qrCodeType = "wechatPublic" } = params; let userId; if (type === 'bind') { userId = context.getCurrentUserId(); @@ -11,7 +11,7 @@ export async function createWechatLogin(params, context) { type, expiresAt: Date.now() + interval, expired: false, - qrCodeType: 'wechatPublic', + qrCodeType, successed: false, }; if (userId) { diff --git a/es/components/passport/index.js b/es/components/passport/index.js index 74d6d6146..8bb96048f 100644 --- a/es/components/passport/index.js +++ b/es/components/passport/index.js @@ -36,9 +36,10 @@ export default OakComponent({ formData({ data }) { const passports = data.map((ele) => { const stateColor = ele.type ? this.features.style.getColor('passport', 'type', ele.type) : '#00BFFF'; - let appIdStr; + let appIdStr, hasQrCodePrefix = false; if (ele.type === 'wechatMpForWeb') { appIdStr = this.getAppIdStr('wechatMp', ele.config?.appId); + hasQrCodePrefix = this.checkMpQrCodePrefix(ele.config?.appId); } else if (ele.type === 'wechatPublicForWeb') { appIdStr = this.getAppIdStr('wechatPublic', ele.config?.appId); @@ -47,6 +48,7 @@ export default OakComponent({ ...ele, appIdStr, stateColor, + hasQrCodePrefix, }; }); return { @@ -277,6 +279,24 @@ export default OakComponent({ } }); return application?.name ? appId + ' (applicationName:' + application.name + ')' : appId; + }, + checkMpQrCodePrefix(appId) { + const systemId = this.features.application.getApplication().systemId; + const [application] = this.features.cache.get('application', { + data: { + id: 1, + config: 1, + }, + filter: { + systemId, + config: { + appId, + }, + type: 'wechatMp', + } + }); + const config = application?.config; + return !!config?.qrCodePrefix; } }, }); diff --git a/es/components/passport/web.pc.d.ts b/es/components/passport/web.pc.d.ts index 8ca637487..1dc7bb2d1 100644 --- a/es/components/passport/web.pc.d.ts +++ b/es/components/passport/web.pc.d.ts @@ -6,6 +6,7 @@ export default function render(props: WebComponentProps); case 'wechatMpForWeb': - return ( { + return ( { updateItem({ enabled, }, passport.id); diff --git a/es/components/passport/wechatMpForWeb/index.d.ts b/es/components/passport/wechatMpForWeb/index.d.ts index d35c0d0df..d49e17353 100644 --- a/es/components/passport/wechatMpForWeb/index.d.ts +++ b/es/components/passport/wechatMpForWeb/index.d.ts @@ -6,6 +6,7 @@ export default function wechatMpForWeb(props: { stateColor: string; }; appIdStr: string; + hasQrCodePrefix: boolean; t: (k: string, params?: any) => string; changeEnabled: (enabled: boolean) => void; updateConfig: (id: string, config: SmsConfig | EmailConfig | PfwConfig | MfwConfig | PwdConfig | NameConfig | OAuthConfig, path: string, value: any, type?: string) => void; diff --git a/es/components/passport/wechatMpForWeb/index.js b/es/components/passport/wechatMpForWeb/index.js index 3457f8d6d..dde3d65f8 100644 --- a/es/components/passport/wechatMpForWeb/index.js +++ b/es/components/passport/wechatMpForWeb/index.js @@ -1,20 +1,20 @@ import React from "react"; -import { Switch, Form, Tag, Input } from 'antd'; +import { Switch, Form, Tooltip, Tag, Input } from 'antd'; import Styles from './web.module.less'; export default function wechatMpForWeb(props) { - const { passport, appIdStr, t, changeEnabled, updateConfig } = props; + const { passport, appIdStr, hasQrCodePrefix, t, changeEnabled, updateConfig } = props; const { id, type, enabled, stateColor } = passport; const config = passport.config || {}; return (
{t(`passport:v.type.${type}`)} - {/* 0) ? '' : '如需启用小程序授权登录,请先前往应用管理,创建小程序application,并完成基础配置'}> */} - + 0)} checkedChildren="开启" unCheckedChildren="关闭" checked={enabled} onChange={(checked) => { changeEnabled(checked); - }}/> - {/* */} + }} disabled={!hasQrCodePrefix}/> +
diff --git a/es/components/user/login/web.js b/es/components/user/login/web.js index 7287132ce..70152ee24 100644 --- a/es/components/user/login/web.js +++ b/es/components/user/login/web.js @@ -150,6 +150,10 @@ export default function Render(props) { {Tip}
} + {loginMode === 'wechatMpForWeb' &&
+ + {Tip} +
} {(inputOptions?.length > 0 || oauthOptions?.length > 0) ? (
{t('otherMethods')} }> diff --git a/es/components/user/login/web.module.less b/es/components/user/login/web.module.less index 0b82be5ca..02efe2e59 100644 --- a/es/components/user/login/web.module.less +++ b/es/components/user/login/web.module.less @@ -61,7 +61,7 @@ &-qrcode { padding: 16px 32px; font-size: 14px; - height: 268px; + min-height: 268px; &__sociallogin { text-align: center; diff --git a/es/components/wechatLogin/confirm/index.d.ts b/es/components/wechatLogin/confirm/index.d.ts index 7e6f4d539..ddbd0e992 100644 --- a/es/components/wechatLogin/confirm/index.d.ts +++ b/es/components/wechatLogin/confirm/index.d.ts @@ -1,3 +1,2 @@ -/// declare const _default: (props: import("oak-frontend-base").ReactComponentProps) => React.ReactElement; export default _default; diff --git a/es/components/wechatLogin/confirm/index.js b/es/components/wechatLogin/confirm/index.js index f6b0ccb28..5240fc899 100644 --- a/es/components/wechatLogin/confirm/index.js +++ b/es/components/wechatLogin/confirm/index.js @@ -44,6 +44,15 @@ export default OakComponent({ const redirectUrl = `https%3A%2F%2F${window.location.host}%2FwechatUser%2Flogin%3FwechatLoginId%3D${this.props.oakId}`; //网址转义 `https://${window.location.host}/wechatUser/login?wechatLoginId=${this.props.oakId}` window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUrl}&response_type=code&scope=snsapi_userinfo&state=${state}#wechat_redirect`; } + }, + async loginByWechatMp() { + const { loginUserId } = this.state; + if (!loginUserId) { + // 先小程序登录 + await this.features.token.loginWechatMp(); + } + await this.features.token.loginWechatMp({ wechatLoginId: this.props.oakId }); + this.refresh(); } }, }); diff --git a/es/components/wechatLogin/confirm/index.less b/es/components/wechatLogin/confirm/index.less index 5bb28b408..c388362d7 100644 --- a/es/components/wechatLogin/confirm/index.less +++ b/es/components/wechatLogin/confirm/index.less @@ -9,6 +9,8 @@ flex-direction: column; background-color: @oak-bg-color-container; box-sizing: border-box; + align-items: center; + justify-content: center; .safe-area-inset-bottom(); } @@ -19,19 +21,6 @@ margin-bottom: 60rpx; } -.circle-view { - margin-top: 30rpx; - padding: 10rpx; - width: 200rpx; - height: 200rpx; - border-radius: 50%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - background-color: #fff; -} - .title { font-size: 32rpx; color: @oak-text-color-primary; @@ -41,4 +30,23 @@ margin-top: 16rpx; font-size: 28rpx; color: @oak-text-color-secondary; +} + +.circle-view { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.text { + font-size: 36rpx; + color: @oak-text-color-primary; + margin-top: 16rpx; +} + +.desc { + font-size: 24rpx; + color: @oak-text-color-secondary; + margin-top: 16rpx; } \ No newline at end of file diff --git a/es/components/wechatLogin/confirm/index.xml b/es/components/wechatLogin/confirm/index.xml index 9eea2a130..4f415e633 100644 --- a/es/components/wechatLogin/confirm/index.xml +++ b/es/components/wechatLogin/confirm/index.xml @@ -1,4 +1,30 @@ - 绑定小程序尚未实现 + + + + 二维码已过期,请重新扫码 + 抱歉,该码已过期 + + + + + + 登录成功 + + + + 一键登录 + + + + + 绑定小程序尚未实现 + \ No newline at end of file diff --git a/es/components/wechatLogin/qrCode/index.d.ts b/es/components/wechatLogin/qrCode/index.d.ts index db7fcdc9b..be8275924 100644 --- a/es/components/wechatLogin/qrCode/index.d.ts +++ b/es/components/wechatLogin/qrCode/index.d.ts @@ -1,7 +1,8 @@ import { EntityDict } from '../../../oak-app-domain'; declare const _default: (props: import("oak-frontend-base").ReactComponentProps) => React.ReactElement; export default _default; diff --git a/es/components/wechatLogin/qrCode/index.js b/es/components/wechatLogin/qrCode/index.js index 79865982e..a7ef3a516 100644 --- a/es/components/wechatLogin/qrCode/index.js +++ b/es/components/wechatLogin/qrCode/index.js @@ -29,13 +29,15 @@ export default OakComponent({ type: 'bind', url: '', size: undefined, + qrCodeType: 'wechatPublic', }, methods: { async createWechatLogin() { - const { type = 'bind' } = this.props; + const { type = 'bind', qrCodeType = 'wechatPublic' } = this.props; const { result: wechatLoginId } = await this.features.cache.exec('createWechatLogin', { type, interval: Interval, + qrCodeType, }); this.setState({ wechatLoginId, @@ -64,7 +66,7 @@ export default OakComponent({ id: 1, entity: 1, entityId: 1, - type: 1, + type: 1, //类型 ticket: 1, url: 1, buffer: 1, diff --git a/es/components/wechatUser/login/index.d.ts b/es/components/wechatUser/login/index.d.ts index 4007eded7..fc416ef2a 100644 --- a/es/components/wechatUser/login/index.d.ts +++ b/es/components/wechatUser/login/index.d.ts @@ -1,3 +1,2 @@ -/// declare const _default: (props: import("oak-frontend-base").ReactComponentProps) => React.ReactElement; export default _default; diff --git a/es/components/wechatUser/login/index.js b/es/components/wechatUser/login/index.js index 811bbedba..0e5985fd5 100644 --- a/es/components/wechatUser/login/index.js +++ b/es/components/wechatUser/login/index.js @@ -6,10 +6,10 @@ export default OakComponent({ }, lifetimes: { attached() { - if (process.env.OAK_PLATFORM === 'web') { - //处理微信授权登录 - this.login(); - } + // if (process.env.OAK_PLATFORM === 'web') { + //处理微信授权登录 + this.login(); + // } }, }, methods: { diff --git a/es/features/token.d.ts b/es/features/token.d.ts index 50b2e5339..e17af7257 100644 --- a/es/features/token.d.ts +++ b/es/features/token.d.ts @@ -25,7 +25,9 @@ export declare class Token extends Feature { loginWechat(code: string, params?: { wechatLoginId?: string; }): Promise; - loginWechatMp(): Promise; + loginWechatMp(params?: { + wechatLoginId?: string; + }): Promise; loginWechatNative(code: string): Promise; syncUserInfoWechatMp(): Promise; logout(dontPublish?: boolean): Promise; diff --git a/es/features/token.js b/es/features/token.js index 0b2ae4e07..97936691e 100644 --- a/es/features/token.js +++ b/es/features/token.js @@ -188,12 +188,13 @@ export class Token extends Feature { this.publish(); this.checkNeedSetPassword(); } - async loginWechatMp() { + async loginWechatMp(params) { const { code } = await wx.login(); const env = await this.environment.getEnv(); const { result } = await this.cache.exec('loginWechatMp', { code, env: env, + wechatLoginId: params?.wechatLoginId, }); this.tokenValue = result; await this.storage.save(LOCAL_STORAGE_KEYS.token, result); diff --git a/es/triggers/application.js b/es/triggers/application.js index e5311d188..e58e4b692 100644 --- a/es/triggers/application.js +++ b/es/triggers/application.js @@ -21,7 +21,7 @@ const triggers = [ } }, { - name: 'web applicaiton清空微信网站配置时,将相应的applicationPassport删除', + name: 'web applicaiton清空微信网站配置时,将相应的passport禁用', entity: 'application', action: 'update', when: 'before', @@ -30,7 +30,7 @@ const triggers = [ return !!data.config; }, fn: async ({ operation }, context, option) => { - const { filter } = operation; + const { filter, data } = operation; const applications = await context.select('application', { data: { id: 1, @@ -43,9 +43,10 @@ const triggers = [ let count = 0; for (const application of applications) { if (application.type === 'web') { - const { wechat } = application.config || {}; - const { appId, appSecret } = wechat || {}; - if (!(appId && appId !== '' && appSecret && appSecret !== '')) { + // const { wechat } = application.config as WebConfig || {}; + // const { appId, appSecret } = wechat || {}; + const { appId: newAppId, appSecret: newAppSecret } = data?.config?.wechat || {}; + if (!newAppId || !newAppSecret) { const [passport] = await context.select('passport', { data: { id: 1, @@ -59,14 +60,16 @@ const triggers = [ indexFrom: 0, }, { forUpdate: true }); if (passport) { - await context.operate('applicationPassport', { + await context.operate('passport', { id: await generateNewIdAsync(), - action: 'remove', - data: {}, - filter: { - passportId: passport.id, - applicationId: application.id, + action: 'update', + data: { + enabled: false, + config: {}, }, + filter: { + id: passport.id, + } }, option); count++; } @@ -100,7 +103,7 @@ const triggers = [ for (const application of applications) { if (application.type === 'wechatPublic') { const { appId, appSecret, isService } = application.config || {}; - if (appId && appId !== '') { + if (appId) { const [passport] = await context.select('passport', { data: { id: 1, @@ -116,7 +119,7 @@ const triggers = [ count: 1, indexFrom: 0, }, { forUpdate: true }); - if (appSecret && appSecret !== '' && isService) { + if (appSecret && isService) { if (!passport) { await context.operate('passport', { id: await generateNewIdAsync(), @@ -154,7 +157,7 @@ const triggers = [ } else if (application.type === 'wechatMp') { const { appId, appSecret, } = application.config || {}; - if (appId && appId !== '') { + if (appId) { const [passport] = await context.select('passport', { data: { id: 1, @@ -169,7 +172,7 @@ const triggers = [ count: 1, indexFrom: 0, }, { forUpdate: true }); - if (appSecret && appSecret !== '') { + if (appSecret) { if (!passport) { await context.operate('passport', { id: await generateNewIdAsync(), @@ -265,6 +268,66 @@ const triggers = [ return count; } }, + { + name: 'wechatMp applicaiton清空普通链接二维码规则配置时,将相应的passport禁用', + entity: 'application', + action: 'update', + when: 'after', + check: (operation) => { + const { data } = operation; + return !!data.config; + }, + fn: async ({ operation }, context, option) => { + const { filter } = operation; + const applications = await context.select('application', { + data: { + id: 1, + config: 1, + type: 1, + systemId: 1, + }, + filter, + }, {}); + let count = 0; + for (const application of applications) { + if (application.type === 'wechatMp') { + const { qrCodePrefix, appId } = application.config || {}; + if (appId && !qrCodePrefix) { + const [passport] = await context.select('passport', { + data: { + id: 1, + }, + filter: { + enabled: true, + systemId: application.systemId, + type: 'wechatMpForWeb', + config: { + appId, + } + }, + count: 1, + indexFrom: 0, + }, { forUpdate: true }); + if (passport) { + await context.operate('passport', { + id: await generateNewIdAsync(), + action: 'update', + data: { + enabled: false, + config: {}, + }, + filter: { + id: passport.id, + } + }, option); + count++; + } + } + } + } + return count; + } + }, { name: '删除application前,将相关的passport删除', entity: 'application', diff --git a/lib/aspects/AspectDict.d.ts b/lib/aspects/AspectDict.d.ts index de6d4cff8..3cb0bf636 100644 --- a/lib/aspects/AspectDict.d.ts +++ b/lib/aspects/AspectDict.d.ts @@ -134,11 +134,13 @@ export type AspectDict = { * 微信小程序登录 * @param code 微信授权 code * @param env 小程序环境信息 + * @param wechatLoginId 可选的微信登录 ID(用于扫码登录场景) * @returns 返回登录 token */ - loginWechatMp: ({ code, env, }: { + loginWechatMp: ({ code, env, wechatLoginId, }: { code: string; env: WechatMpEnv; + wechatLoginId?: string; }, context: BackendRuntimeContext) => Promise; /** * 微信原生 APP 登录 @@ -297,6 +299,7 @@ export type AspectDict = { createWechatLogin: (params: { type: EntityDict['wechatLogin']['Schema']['type']; interval: number; + qrCodeType?: EntityDict['wechatLogin']['Schema']['qrCodeType']; }, context: BackendRuntimeContext) => Promise; /** * 解绑微信用户 diff --git a/lib/aspects/token.d.ts b/lib/aspects/token.d.ts index e2b32e6d0..0fe2b56bd 100644 --- a/lib/aspects/token.d.ts +++ b/lib/aspects/token.d.ts @@ -77,9 +77,10 @@ export declare function loginWechat({ code, env, wechatLo * @param context * @returns */ -export declare function loginWechatMp({ code, env, }: { +export declare function loginWechatMp({ code, env, wechatLoginId, }: { code: string; env: WechatMpEnv; + wechatLoginId?: string; }, context: BRC): Promise; /** * 同步从wx.getUserProfile拿到的用户信息 diff --git a/lib/aspects/token.js b/lib/aspects/token.js index 6a82a9d86..46088208d 100644 --- a/lib/aspects/token.js +++ b/lib/aspects/token.js @@ -1975,9 +1975,9 @@ async function loginWechat({ code, env, wechatLoginId, }, context) { * @param context * @returns */ -async function loginWechatMp({ code, env, }, context) { +async function loginWechatMp({ code, env, wechatLoginId, }, context) { const closeRootMode = context.openRootMode(); - const tokenValue = await loginFromWechatEnv(code, env, context); + const tokenValue = await loginFromWechatEnv(code, env, context, wechatLoginId); await loadTokenInfo(tokenValue, context); closeRootMode(); return tokenValue; diff --git a/lib/aspects/wechatLogin.d.ts b/lib/aspects/wechatLogin.d.ts index 9c13e80d8..24f4c249b 100644 --- a/lib/aspects/wechatLogin.d.ts +++ b/lib/aspects/wechatLogin.d.ts @@ -3,4 +3,5 @@ import { BRC } from '../types/RuntimeCxt'; export declare function createWechatLogin(params: { type: EntityDict['wechatLogin']['Schema']['type']; interval: number; + qrCodeType?: EntityDict['wechatLogin']['Schema']['qrCodeType']; }, context: BRC): Promise; diff --git a/lib/aspects/wechatLogin.js b/lib/aspects/wechatLogin.js index 240aa8f59..a70167fcd 100644 --- a/lib/aspects/wechatLogin.js +++ b/lib/aspects/wechatLogin.js @@ -1,9 +1,9 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.createWechatLogin = void 0; +exports.createWechatLogin = createWechatLogin; const uuid_1 = require("oak-domain/lib/utils/uuid"); async function createWechatLogin(params, context) { - const { type, interval } = params; + const { type, interval, qrCodeType = "wechatPublic" } = params; let userId; if (type === 'bind') { userId = context.getCurrentUserId(); @@ -14,7 +14,7 @@ async function createWechatLogin(params, context) { type, expiresAt: Date.now() + interval, expired: false, - qrCodeType: 'wechatPublic', + qrCodeType, successed: false, }; if (userId) { @@ -44,4 +44,3 @@ async function createWechatLogin(params, context) { } return id; } -exports.createWechatLogin = createWechatLogin; diff --git a/lib/features/token.js b/lib/features/token.js index e11ae3e40..bcad1ecdc 100644 --- a/lib/features/token.js +++ b/lib/features/token.js @@ -191,12 +191,13 @@ class Token extends Feature_1.Feature { this.publish(); this.checkNeedSetPassword(); } - async loginWechatMp() { + async loginWechatMp(params) { const { code } = await wx.login(); const env = await this.environment.getEnv(); const { result } = await this.cache.exec('loginWechatMp', { code, env: env, + wechatLoginId: params?.wechatLoginId, }); this.tokenValue = result; await this.storage.save(constants_1.LOCAL_STORAGE_KEYS.token, result); diff --git a/lib/triggers/application.js b/lib/triggers/application.js index f67287444..2b74aaf75 100644 --- a/lib/triggers/application.js +++ b/lib/triggers/application.js @@ -23,7 +23,7 @@ const triggers = [ } }, { - name: 'web applicaiton清空微信网站配置时,将相应的applicationPassport删除', + name: 'web applicaiton清空微信网站配置时,将相应的passport禁用', entity: 'application', action: 'update', when: 'before', @@ -32,7 +32,7 @@ const triggers = [ return !!data.config; }, fn: async ({ operation }, context, option) => { - const { filter } = operation; + const { filter, data } = operation; const applications = await context.select('application', { data: { id: 1, @@ -45,9 +45,10 @@ const triggers = [ let count = 0; for (const application of applications) { if (application.type === 'web') { - const { wechat } = application.config || {}; - const { appId, appSecret } = wechat || {}; - if (!(appId && appId !== '' && appSecret && appSecret !== '')) { + // const { wechat } = application.config as WebConfig || {}; + // const { appId, appSecret } = wechat || {}; + const { appId: newAppId, appSecret: newAppSecret } = data?.config?.wechat || {}; + if (!newAppId || !newAppSecret) { const [passport] = await context.select('passport', { data: { id: 1, @@ -61,14 +62,16 @@ const triggers = [ indexFrom: 0, }, { forUpdate: true }); if (passport) { - await context.operate('applicationPassport', { + await context.operate('passport', { id: await (0, uuid_1.generateNewIdAsync)(), - action: 'remove', - data: {}, - filter: { - passportId: passport.id, - applicationId: application.id, + action: 'update', + data: { + enabled: false, + config: {}, }, + filter: { + id: passport.id, + } }, option); count++; } @@ -102,7 +105,7 @@ const triggers = [ for (const application of applications) { if (application.type === 'wechatPublic') { const { appId, appSecret, isService } = application.config || {}; - if (appId && appId !== '') { + if (appId) { const [passport] = await context.select('passport', { data: { id: 1, @@ -118,7 +121,7 @@ const triggers = [ count: 1, indexFrom: 0, }, { forUpdate: true }); - if (appSecret && appSecret !== '' && isService) { + if (appSecret && isService) { if (!passport) { await context.operate('passport', { id: await (0, uuid_1.generateNewIdAsync)(), @@ -156,7 +159,7 @@ const triggers = [ } else if (application.type === 'wechatMp') { const { appId, appSecret, } = application.config || {}; - if (appId && appId !== '') { + if (appId) { const [passport] = await context.select('passport', { data: { id: 1, @@ -171,7 +174,7 @@ const triggers = [ count: 1, indexFrom: 0, }, { forUpdate: true }); - if (appSecret && appSecret !== '') { + if (appSecret) { if (!passport) { await context.operate('passport', { id: await (0, uuid_1.generateNewIdAsync)(), @@ -267,6 +270,66 @@ const triggers = [ return count; } }, + { + name: 'wechatMp applicaiton清空普通链接二维码规则配置时,将相应的passport禁用', + entity: 'application', + action: 'update', + when: 'after', + check: (operation) => { + const { data } = operation; + return !!data.config; + }, + fn: async ({ operation }, context, option) => { + const { filter } = operation; + const applications = await context.select('application', { + data: { + id: 1, + config: 1, + type: 1, + systemId: 1, + }, + filter, + }, {}); + let count = 0; + for (const application of applications) { + if (application.type === 'wechatMp') { + const { qrCodePrefix, appId } = application.config || {}; + if (appId && !qrCodePrefix) { + const [passport] = await context.select('passport', { + data: { + id: 1, + }, + filter: { + enabled: true, + systemId: application.systemId, + type: 'wechatMpForWeb', + config: { + appId, + } + }, + count: 1, + indexFrom: 0, + }, { forUpdate: true }); + if (passport) { + await context.operate('passport', { + id: await (0, uuid_1.generateNewIdAsync)(), + action: 'update', + data: { + enabled: false, + config: {}, + }, + filter: { + id: passport.id, + } + }, option); + count++; + } + } + } + } + return count; + } + }, { name: '删除application前,将相关的passport删除', entity: 'application', diff --git a/src/aspects/AspectDict.ts b/src/aspects/AspectDict.ts index eafe005ac..58357708f 100644 --- a/src/aspects/AspectDict.ts +++ b/src/aspects/AspectDict.ts @@ -179,15 +179,18 @@ export type AspectDict = { * 微信小程序登录 * @param code 微信授权 code * @param env 小程序环境信息 + * @param wechatLoginId 可选的微信登录 ID(用于扫码登录场景) * @returns 返回登录 token */ loginWechatMp: ( { code, env, + wechatLoginId, }: { code: string; env: WechatMpEnv; + wechatLoginId?: string; }, context: BackendRuntimeContext ) => Promise; @@ -411,6 +414,7 @@ export type AspectDict = { params: { type: EntityDict['wechatLogin']['Schema']['type']; interval: number; + qrCodeType?: EntityDict['wechatLogin']['Schema']['qrCodeType']; }, context: BackendRuntimeContext ) => Promise; diff --git a/src/aspects/token.ts b/src/aspects/token.ts index 8014e6804..80be22a68 100644 --- a/src/aspects/token.ts +++ b/src/aspects/token.ts @@ -2573,14 +2573,16 @@ export async function loginWechatMp( { code, env, + wechatLoginId, }: { code: string; env: WechatMpEnv; + wechatLoginId?: string; }, context: BRC ): Promise { const closeRootMode = context.openRootMode(); - const tokenValue = await loginFromWechatEnv(code, env, context); + const tokenValue = await loginFromWechatEnv(code, env, context, wechatLoginId); await loadTokenInfo(tokenValue, context); closeRootMode(); return tokenValue; diff --git a/src/aspects/wechatLogin.ts b/src/aspects/wechatLogin.ts index b8ecb8b1b..389a223d6 100644 --- a/src/aspects/wechatLogin.ts +++ b/src/aspects/wechatLogin.ts @@ -8,10 +8,11 @@ export async function createWechatLogin( params: { type: EntityDict['wechatLogin']['Schema']['type']; interval: number; + qrCodeType?:EntityDict['wechatLogin']['Schema']['qrCodeType']; }, context: BRC ) { - const { type, interval } = params; + const { type, interval, qrCodeType="wechatPublic" } = params; let userId; if (type === 'bind') { userId = context.getCurrentUserId(); @@ -22,7 +23,7 @@ export async function createWechatLogin( type, expiresAt: Date.now() + interval, expired: false, - qrCodeType: 'wechatPublic', + qrCodeType, successed: false, }; if (userId) { diff --git a/src/components/passport/index.ts b/src/components/passport/index.ts index 6262175a5..72cd93d34 100644 --- a/src/components/passport/index.ts +++ b/src/components/passport/index.ts @@ -1,6 +1,7 @@ import { cloneDeep, isEqual, set, } from "oak-domain/lib/utils/lodash"; import { EmailConfig, MfwConfig, PfwConfig, SmsConfig, NameConfig, OAuthConfig } from "../../entities/Passport"; import { EntityDict } from "../../oak-app-domain"; +import { WechatMpConfig } from "../../entities/Application"; export default OakComponent({ entity: 'passport', @@ -39,9 +40,10 @@ export default OakComponent({ formData({ data }) { const passports = data.map((ele) => { const stateColor = ele.type ? this.features.style.getColor('passport', 'type', ele.type) : '#00BFFF'; - let appIdStr; + let appIdStr, hasQrCodePrefix = false; if (ele.type === 'wechatMpForWeb') { appIdStr = this.getAppIdStr('wechatMp', (ele.config as MfwConfig)?.appId); + hasQrCodePrefix = this.checkMpQrCodePrefix((ele.config as MfwConfig)?.appId); } else if (ele.type === 'wechatPublicForWeb') { appIdStr = this.getAppIdStr('wechatPublic', (ele.config as PfwConfig)?.appId); } @@ -49,6 +51,7 @@ export default OakComponent({ ...ele, appIdStr, stateColor, + hasQrCodePrefix, } }) return { @@ -282,6 +285,26 @@ export default OakComponent({ } ) return application?.name ? appId + ' (applicationName:' + application.name + ')' : appId + }, + checkMpQrCodePrefix(appId: string) { + const systemId = this.features.application.getApplication().systemId; + const [application] = this.features.cache.get('application', + { + data: { + id: 1, + config: 1, + }, + filter: { + systemId, + config: { + appId, + }, + type: 'wechatMp', + } + } + ); + const config = application?.config as WechatMpConfig; + return !!config?.qrCodePrefix; } }, diff --git a/src/components/passport/web.pc.tsx b/src/components/passport/web.pc.tsx index 7592c6a1c..fbdb4492b 100644 --- a/src/components/passport/web.pc.tsx +++ b/src/components/passport/web.pc.tsx @@ -47,7 +47,7 @@ export default function render(props: WebComponentProps< 'passport', true, { - passports: (EntityDict['passport']['OpSchema'] & { appIdStr: string; stateColor: string })[]; + passports: (EntityDict['passport']['OpSchema'] & { appIdStr: string; stateColor: string; hasQrCodePrefix: boolean })[]; systemId: string; systemName: string; oauthOptions: { @@ -227,6 +227,7 @@ export default function render(props: WebComponentProps< key={passport.id} passport={passport} appIdStr={passport?.appIdStr} + hasQrCodePrefix={passport?.hasQrCodePrefix} t={t} changeEnabled={(enabled) => { updateItem({ diff --git a/src/components/passport/wechatMpForWeb/index.tsx b/src/components/passport/wechatMpForWeb/index.tsx index 63c8dca3c..af794c6e5 100644 --- a/src/components/passport/wechatMpForWeb/index.tsx +++ b/src/components/passport/wechatMpForWeb/index.tsx @@ -7,11 +7,12 @@ import Styles from './web.module.less'; export default function wechatMpForWeb(props: { passport: EntityDict['passport']['OpSchema'] & { stateColor: string }; appIdStr: string; + hasQrCodePrefix: boolean; t: (k: string, params?: any) => string; changeEnabled: (enabled: boolean) => void; updateConfig: (id: string, config: SmsConfig | EmailConfig | PfwConfig | MfwConfig | PwdConfig | NameConfig | OAuthConfig, path: string, value: any, type?: string) => void; }) { - const { passport, appIdStr, t, changeEnabled, updateConfig } = props; + const { passport, appIdStr, hasQrCodePrefix, t, changeEnabled, updateConfig } = props; const { id, type, enabled, stateColor } = passport; const config = passport.config as MfwConfig || {}; @@ -19,17 +20,18 @@ export default function wechatMpForWeb(props: {
{t(`passport:v.type.${type}`)} - {/* 0) ? '' : '如需启用小程序授权登录,请先前往应用管理,创建小程序application,并完成基础配置'}> */} - 0)} - checkedChildren="开启" - unCheckedChildren="关闭" - checked={enabled} - onChange={(checked) => { - changeEnabled(checked); - }} - /> - {/* */} + + 0)} + checkedChildren="开启" + unCheckedChildren="关闭" + checked={enabled} + onChange={(checked) => { + changeEnabled(checked); + }} + disabled={!hasQrCodePrefix} + /> +
{Tip}
} + {loginMode === 'wechatMpForWeb' &&
+ + {Tip} +
} {(inputOptions?.length > 0 || oauthOptions?.length > 0) ? (
{t('otherMethods')} diff --git a/src/components/wechatLogin/confirm/index.less b/src/components/wechatLogin/confirm/index.less index 5bb28b408..c388362d7 100644 --- a/src/components/wechatLogin/confirm/index.less +++ b/src/components/wechatLogin/confirm/index.less @@ -9,6 +9,8 @@ flex-direction: column; background-color: @oak-bg-color-container; box-sizing: border-box; + align-items: center; + justify-content: center; .safe-area-inset-bottom(); } @@ -19,19 +21,6 @@ margin-bottom: 60rpx; } -.circle-view { - margin-top: 30rpx; - padding: 10rpx; - width: 200rpx; - height: 200rpx; - border-radius: 50%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - background-color: #fff; -} - .title { font-size: 32rpx; color: @oak-text-color-primary; @@ -41,4 +30,23 @@ margin-top: 16rpx; font-size: 28rpx; color: @oak-text-color-secondary; +} + +.circle-view { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.text { + font-size: 36rpx; + color: @oak-text-color-primary; + margin-top: 16rpx; +} + +.desc { + font-size: 24rpx; + color: @oak-text-color-secondary; + margin-top: 16rpx; } \ No newline at end of file diff --git a/src/components/wechatLogin/confirm/index.ts b/src/components/wechatLogin/confirm/index.ts index dfa3d8e10..3628e3582 100644 --- a/src/components/wechatLogin/confirm/index.ts +++ b/src/components/wechatLogin/confirm/index.ts @@ -49,6 +49,16 @@ export default OakComponent({ const redirectUrl = `https%3A%2F%2F${window.location.host}%2FwechatUser%2Flogin%3FwechatLoginId%3D${this.props.oakId}`; //网址转义 `https://${window.location.host}/wechatUser/login?wechatLoginId=${this.props.oakId}` window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUrl}&response_type=code&scope=snsapi_userinfo&state=${state}#wechat_redirect` } + }, + async loginByWechatMp() { + const {loginUserId} = this.state; + if(!loginUserId){ + // 先小程序登录 + await this.features.token.loginWechatMp(); + } + await this.features.token.loginWechatMp({ wechatLoginId: this.props.oakId }); + this.refresh(); } + }, }); diff --git a/src/components/wechatLogin/confirm/index.xml b/src/components/wechatLogin/confirm/index.xml index 9eea2a130..4f415e633 100644 --- a/src/components/wechatLogin/confirm/index.xml +++ b/src/components/wechatLogin/confirm/index.xml @@ -1,4 +1,30 @@ - 绑定小程序尚未实现 + + + + 二维码已过期,请重新扫码 + 抱歉,该码已过期 + + + + + + 登录成功 + + + + 一键登录 + + + + + 绑定小程序尚未实现 + \ No newline at end of file diff --git a/src/components/wechatLogin/qrCode/index.ts b/src/components/wechatLogin/qrCode/index.ts index 9131480ef..10a76a19c 100644 --- a/src/components/wechatLogin/qrCode/index.ts +++ b/src/components/wechatLogin/qrCode/index.ts @@ -32,15 +32,17 @@ export default OakComponent({ type: 'bind' as EntityDict['wechatLogin']['Schema']['type'], url: '', size: undefined, + qrCodeType: 'wechatPublic' as EntityDict['wechatLogin']['Schema']['qrCodeType'], }, methods: { async createWechatLogin() { - const { type = 'bind' } = this.props; + const { type = 'bind', qrCodeType = 'wechatPublic' } = this.props; const { result: wechatLoginId } = await this.features.cache.exec( 'createWechatLogin', { type, interval: Interval, + qrCodeType, } ); this.setState( diff --git a/src/components/wechatUser/login/index.ts b/src/components/wechatUser/login/index.ts index b2c75da42..4bdd165c9 100644 --- a/src/components/wechatUser/login/index.ts +++ b/src/components/wechatUser/login/index.ts @@ -7,10 +7,10 @@ export default OakComponent({ }, lifetimes: { attached() { - if (process.env.OAK_PLATFORM === 'web') { + // if (process.env.OAK_PLATFORM === 'web') { //处理微信授权登录 this.login(); - } + // } }, }, methods: { diff --git a/src/features/token.ts b/src/features/token.ts index 7ee0eabd6..fe686e565 100644 --- a/src/features/token.ts +++ b/src/features/token.ts @@ -280,13 +280,14 @@ export class Token extends Feature { this.checkNeedSetPassword(); } - async loginWechatMp() { + async loginWechatMp(params?: { wechatLoginId?: string }) { const { code } = await wx.login(); const env = await this.environment.getEnv(); const { result } = await this.cache.exec('loginWechatMp', { code, env: env as WechatMpEnv, + wechatLoginId: params?.wechatLoginId, }); this.tokenValue = result; await this.storage.save(LOCAL_STORAGE_KEYS.token, result); diff --git a/src/triggers/application.ts b/src/triggers/application.ts index ecbf0e779..111ebf548 100644 --- a/src/triggers/application.ts +++ b/src/triggers/application.ts @@ -30,7 +30,7 @@ const triggers: Trigger>[] = [ } } as RemoveTrigger>, { - name: 'web applicaiton清空微信网站配置时,将相应的applicationPassport删除', + name: 'web applicaiton清空微信网站配置时,将相应的passport禁用', entity: 'application', action: 'update', when: 'before', @@ -39,7 +39,7 @@ const triggers: Trigger>[] = [ return !!data.config; }, fn: async ({ operation }, context, option) => { - const { filter } = operation; + const { filter, data } = operation; const applications = await context.select('application', { data: { id: 1, @@ -52,9 +52,10 @@ const triggers: Trigger>[] = [ let count = 0; for (const application of applications) { if (application.type === 'web') { - const { wechat } = application.config as WebConfig || {}; - const { appId, appSecret } = wechat || {}; - if (!(appId && appId !== '' && appSecret && appSecret !== '')) { + // const { wechat } = application.config as WebConfig || {}; + // const { appId, appSecret } = wechat || {}; + const { appId: newAppId, appSecret: newAppSecret } = (data?.config as WebConfig)?.wechat || {}; + if (!newAppId || !newAppSecret) { const [passport] = await context.select('passport', { data: { id: 1, @@ -68,14 +69,16 @@ const triggers: Trigger>[] = [ indexFrom: 0, }, { forUpdate: true }); if (passport) { - await context.operate('applicationPassport', { + await context.operate('passport', { id: await generateNewIdAsync(), - action: 'remove', - data: {}, - filter: { - passportId: passport.id, - applicationId: application.id, + action: 'update', + data: { + enabled: false, + config: {}, }, + filter: { + id: passport.id, + } }, option); count++; } @@ -109,7 +112,7 @@ const triggers: Trigger>[] = [ for (const application of applications) { if (application.type === 'wechatPublic') { const { appId, appSecret, isService } = application.config as WechatPublicConfig || {}; - if (appId && appId !== '') { + if (appId) { const [passport] = await context.select('passport', { data: { id: 1, @@ -125,7 +128,7 @@ const triggers: Trigger>[] = [ count: 1, indexFrom: 0, }, { forUpdate: true }); - if (appSecret && appSecret !== '' && isService) { + if (appSecret && isService) { if (!passport) { await context.operate('passport', { id: await generateNewIdAsync(), @@ -161,7 +164,7 @@ const triggers: Trigger>[] = [ } } else if (application.type === 'wechatMp') { const { appId, appSecret, } = application.config as WechatMpConfig || {}; - if (appId && appId !== '') { + if (appId) { const [passport] = await context.select('passport', { data: { id: 1, @@ -176,7 +179,7 @@ const triggers: Trigger>[] = [ count: 1, indexFrom: 0, }, { forUpdate: true }); - if (appSecret && appSecret !== '') { + if (appSecret) { if (!passport) { await context.operate('passport', { id: await generateNewIdAsync(), @@ -273,6 +276,66 @@ const triggers: Trigger>[] = [ return count; } }, + { + name: 'wechatMp applicaiton清空普通链接二维码规则配置时,将相应的passport禁用', + entity: 'application', + action: 'update', + when: 'after', + check: (operation) => { + const { data } = operation as EntityDict['application']['Update']; + return !!data.config; + }, + fn: async ({ operation }, context, option) => { + const { filter } = operation; + const applications = await context.select('application', { + data: { + id: 1, + config: 1, + type: 1, + systemId: 1, + }, + filter, + }, {}); + let count = 0; + for (const application of applications) { + if (application.type === 'wechatMp') { + const { qrCodePrefix, appId } = application.config as WechatMpConfig || {}; + if (appId && !qrCodePrefix) { + const [passport] = await context.select('passport', { + data: { + id: 1, + }, + filter: { + enabled: true, + systemId: application.systemId!, + type: 'wechatMpForWeb', + config: { + appId, + } + }, + count: 1, + indexFrom: 0, + }, { forUpdate: true }); + if (passport) { + await context.operate('passport', { + id: await generateNewIdAsync(), + action: 'update', + data: { + enabled: false, + config: {}, + }, + filter: { + id: passport.id, + } + }, option); + count++; + } + } + } + } + return count; + } + }, { name: '删除application前,将相关的passport删除', entity: 'application',