feat: 支持小程序扫码授权登录网页
This commit is contained in:
parent
169562994b
commit
9751ee5e10
|
|
@ -134,11 +134,13 @@ export type AspectDict<ED extends EntityDict> = {
|
|||
* 微信小程序登录
|
||||
* @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<ED>) => Promise<string>;
|
||||
/**
|
||||
* 微信原生 APP 登录
|
||||
|
|
@ -297,6 +299,7 @@ export type AspectDict<ED extends EntityDict> = {
|
|||
createWechatLogin: (params: {
|
||||
type: EntityDict['wechatLogin']['Schema']['type'];
|
||||
interval: number;
|
||||
qrCodeType?: EntityDict['wechatLogin']['Schema']['qrCodeType'];
|
||||
}, context: BackendRuntimeContext<ED>) => Promise<string>;
|
||||
/**
|
||||
* 解绑微信用户
|
||||
|
|
|
|||
|
|
@ -77,9 +77,10 @@ export declare function loginWechat<ED extends EntityDict>({ code, env, wechatLo
|
|||
* @param context
|
||||
* @returns
|
||||
*/
|
||||
export declare function loginWechatMp<ED extends EntityDict>({ code, env, }: {
|
||||
export declare function loginWechatMp<ED extends EntityDict>({ code, env, wechatLoginId, }: {
|
||||
code: string;
|
||||
env: WechatMpEnv;
|
||||
wechatLoginId?: string;
|
||||
}, context: BRC<ED>): Promise<string>;
|
||||
/**
|
||||
* 同步从wx.getUserProfile拿到的用户信息
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@ import { BRC } from '../types/RuntimeCxt';
|
|||
export declare function createWechatLogin<ED extends EntityDict>(params: {
|
||||
type: EntityDict['wechatLogin']['Schema']['type'];
|
||||
interval: number;
|
||||
qrCodeType?: EntityDict['wechatLogin']['Schema']['qrCodeType'];
|
||||
}, context: BRC<ED>): Promise<string>;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ export default function render(props: WebComponentProps<EntityDict, 'passport',
|
|||
passports: (EntityDict['passport']['OpSchema'] & {
|
||||
appIdStr: string;
|
||||
stateColor: string;
|
||||
hasQrCodePrefix: boolean;
|
||||
})[];
|
||||
systemId: string;
|
||||
systemName: string;
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ export default function render(props) {
|
|||
}, passport.id);
|
||||
}} updateConfig={updateConfig}/>);
|
||||
case 'wechatMpForWeb':
|
||||
return (<WechatMpForWeb key={passport.id} passport={passport} appIdStr={passport?.appIdStr} t={t} changeEnabled={(enabled) => {
|
||||
return (<WechatMpForWeb key={passport.id} passport={passport} appIdStr={passport?.appIdStr} hasQrCodePrefix={passport?.hasQrCodePrefix} t={t} changeEnabled={(enabled) => {
|
||||
updateItem({
|
||||
enabled,
|
||||
}, passport.id);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 (<div className={Styles.item}>
|
||||
<div className={Styles.title}>
|
||||
<Tag color={stateColor}>{t(`passport:v.type.${type}`)}</Tag>
|
||||
{/* <Tooltip title={(mpAppIds && mpAppIds.length > 0) ? '' : '如需启用小程序授权登录,请先前往应用管理,创建小程序application,并完成基础配置'}> */}
|
||||
<Switch
|
||||
<Tooltip title={hasQrCodePrefix ? '' : '请先配置小程序普通链接二维码规则'}>
|
||||
<Switch
|
||||
// disabled={!(mpAppIds && mpAppIds.length > 0)}
|
||||
checkedChildren="开启" unCheckedChildren="关闭" checked={enabled} onChange={(checked) => {
|
||||
changeEnabled(checked);
|
||||
}}/>
|
||||
{/* </Tooltip> */}
|
||||
}} disabled={!hasQrCodePrefix}/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<Form labelCol={{ span: 4 }} wrapperCol={{ span: 20 }} style={{ maxWidth: 900, marginTop: 16 }}>
|
||||
<Form.Item label="appId">
|
||||
|
|
|
|||
|
|
@ -150,6 +150,10 @@ export default function Render(props) {
|
|||
<WechatLoginQrCodeForPublic type="login" oakPath="$login-wechatLogin/qrCode" oakAutoUnmount={true} url={state} size={180}/>
|
||||
{Tip}
|
||||
</div>}
|
||||
{loginMode === 'wechatMpForWeb' && <div className={Style['loginbox-qrcode']}>
|
||||
<WechatLoginQrCodeForPublic type="login" oakPath="$login-wechatLogin/qrCode" oakAutoUnmount={true} url={state} size={180} qrCodeType={'wechatMpDomainUrl'}/>
|
||||
{Tip}
|
||||
</div>}
|
||||
{(inputOptions?.length > 0 || oauthOptions?.length > 0) ? (<div className={Style['loginbox-methods']}>
|
||||
<Divider plain style={{ fontSize: 13, color: '#808080', }}>{t('otherMethods')}</Divider>
|
||||
<Space split={<Divider type="vertical"/>}>
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
&-qrcode {
|
||||
padding: 16px 32px;
|
||||
font-size: 14px;
|
||||
height: 268px;
|
||||
min-height: 268px;
|
||||
|
||||
&__sociallogin {
|
||||
text-align: center;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,2 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "wechatLogin", false, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1,4 +1,30 @@
|
|||
<!-- index.wxml -->
|
||||
<view class="page-body">
|
||||
绑定小程序尚未实现
|
||||
<block wx:if="{{expired}}">
|
||||
<view class="circle-view">
|
||||
<l-icon name="warning" size="120" />
|
||||
<text class="text">二维码已过期,请重新扫码</text>
|
||||
<text class="desc">抱歉,该码已过期</text>
|
||||
</view>
|
||||
</block>
|
||||
<block wx:if="{{type==='login'}}">
|
||||
<view wx:if="{{successed}}" class="circle-view">
|
||||
<l-icon name="success" size="120" />
|
||||
<text class="text">登录成功</text>
|
||||
</view>
|
||||
<block wx:else>
|
||||
<l-button
|
||||
type="default"
|
||||
size="long"
|
||||
disabled="{{oakExecuting || oakLoading}}"
|
||||
bind:lintap="loginByWechatMp"
|
||||
style="width:100%"
|
||||
>
|
||||
一键登录
|
||||
</l-button>
|
||||
</block>
|
||||
</block>
|
||||
<view wx:else>
|
||||
绑定小程序尚未实现
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
import { EntityDict } from '../../../oak-app-domain';
|
||||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, keyof EntityDict, false, {
|
||||
type: "login" | "bind";
|
||||
type: EntityDict["wechatLogin"]["Schema"]["type"];
|
||||
url: string;
|
||||
size: undefined;
|
||||
qrCodeType: EntityDict["wechatLogin"]["Schema"]["qrCodeType"];
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,2 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, keyof import("../../../oak-app-domain").EntityDict, false, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ export declare class Token<ED extends EntityDict> extends Feature {
|
|||
loginWechat(code: string, params?: {
|
||||
wechatLoginId?: string;
|
||||
}): Promise<void>;
|
||||
loginWechatMp(): Promise<void>;
|
||||
loginWechatMp(params?: {
|
||||
wechatLoginId?: string;
|
||||
}): Promise<void>;
|
||||
loginWechatNative(code: string): Promise<void>;
|
||||
syncUserInfoWechatMp(): Promise<void>;
|
||||
logout(dontPublish?: boolean): Promise<void>;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -134,11 +134,13 @@ export type AspectDict<ED extends EntityDict> = {
|
|||
* 微信小程序登录
|
||||
* @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<ED>) => Promise<string>;
|
||||
/**
|
||||
* 微信原生 APP 登录
|
||||
|
|
@ -297,6 +299,7 @@ export type AspectDict<ED extends EntityDict> = {
|
|||
createWechatLogin: (params: {
|
||||
type: EntityDict['wechatLogin']['Schema']['type'];
|
||||
interval: number;
|
||||
qrCodeType?: EntityDict['wechatLogin']['Schema']['qrCodeType'];
|
||||
}, context: BackendRuntimeContext<ED>) => Promise<string>;
|
||||
/**
|
||||
* 解绑微信用户
|
||||
|
|
|
|||
|
|
@ -77,9 +77,10 @@ export declare function loginWechat<ED extends EntityDict>({ code, env, wechatLo
|
|||
* @param context
|
||||
* @returns
|
||||
*/
|
||||
export declare function loginWechatMp<ED extends EntityDict>({ code, env, }: {
|
||||
export declare function loginWechatMp<ED extends EntityDict>({ code, env, wechatLoginId, }: {
|
||||
code: string;
|
||||
env: WechatMpEnv;
|
||||
wechatLoginId?: string;
|
||||
}, context: BRC<ED>): Promise<string>;
|
||||
/**
|
||||
* 同步从wx.getUserProfile拿到的用户信息
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@ import { BRC } from '../types/RuntimeCxt';
|
|||
export declare function createWechatLogin<ED extends EntityDict>(params: {
|
||||
type: EntityDict['wechatLogin']['Schema']['type'];
|
||||
interval: number;
|
||||
qrCodeType?: EntityDict['wechatLogin']['Schema']['qrCodeType'];
|
||||
}, context: BRC<ED>): Promise<string>;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -179,15 +179,18 @@ export type AspectDict<ED extends EntityDict> = {
|
|||
* 微信小程序登录
|
||||
* @param code 微信授权 code
|
||||
* @param env 小程序环境信息
|
||||
* @param wechatLoginId 可选的微信登录 ID(用于扫码登录场景)
|
||||
* @returns 返回登录 token
|
||||
*/
|
||||
loginWechatMp: (
|
||||
{
|
||||
code,
|
||||
env,
|
||||
wechatLoginId,
|
||||
}: {
|
||||
code: string;
|
||||
env: WechatMpEnv;
|
||||
wechatLoginId?: string;
|
||||
},
|
||||
context: BackendRuntimeContext<ED>
|
||||
) => Promise<string>;
|
||||
|
|
@ -411,6 +414,7 @@ export type AspectDict<ED extends EntityDict> = {
|
|||
params: {
|
||||
type: EntityDict['wechatLogin']['Schema']['type'];
|
||||
interval: number;
|
||||
qrCodeType?: EntityDict['wechatLogin']['Schema']['qrCodeType'];
|
||||
},
|
||||
context: BackendRuntimeContext<ED>
|
||||
) => Promise<string>;
|
||||
|
|
|
|||
|
|
@ -2573,14 +2573,16 @@ export async function loginWechatMp<ED extends EntityDict>(
|
|||
{
|
||||
code,
|
||||
env,
|
||||
wechatLoginId,
|
||||
}: {
|
||||
code: string;
|
||||
env: WechatMpEnv;
|
||||
wechatLoginId?: string;
|
||||
},
|
||||
context: BRC<ED>
|
||||
): Promise<string> {
|
||||
const closeRootMode = context.openRootMode();
|
||||
const tokenValue = await loginFromWechatEnv<ED>(code, env, context);
|
||||
const tokenValue = await loginFromWechatEnv<ED>(code, env, context, wechatLoginId);
|
||||
await loadTokenInfo<ED>(tokenValue, context);
|
||||
closeRootMode();
|
||||
return tokenValue;
|
||||
|
|
|
|||
|
|
@ -8,10 +8,11 @@ export async function createWechatLogin<ED extends EntityDict>(
|
|||
params: {
|
||||
type: EntityDict['wechatLogin']['Schema']['type'];
|
||||
interval: number;
|
||||
qrCodeType?:EntityDict['wechatLogin']['Schema']['qrCodeType'];
|
||||
},
|
||||
context: BRC<ED>
|
||||
) {
|
||||
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<ED extends EntityDict>(
|
|||
type,
|
||||
expiresAt: Date.now() + interval,
|
||||
expired: false,
|
||||
qrCodeType: 'wechatPublic',
|
||||
qrCodeType,
|
||||
successed: false,
|
||||
};
|
||||
if (userId) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
|
|
|
|||
|
|
@ -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: {
|
|||
<div className={Styles.item}>
|
||||
<div className={Styles.title}>
|
||||
<Tag color={stateColor}>{t(`passport:v.type.${type}`)}</Tag>
|
||||
{/* <Tooltip title={(mpAppIds && mpAppIds.length > 0) ? '' : '如需启用小程序授权登录,请先前往应用管理,创建小程序application,并完成基础配置'}> */}
|
||||
<Switch
|
||||
// disabled={!(mpAppIds && mpAppIds.length > 0)}
|
||||
checkedChildren="开启"
|
||||
unCheckedChildren="关闭"
|
||||
checked={enabled}
|
||||
onChange={(checked) => {
|
||||
changeEnabled(checked);
|
||||
}}
|
||||
/>
|
||||
{/* </Tooltip> */}
|
||||
<Tooltip title={hasQrCodePrefix ? '' : '请先配置小程序普通链接二维码规则'}>
|
||||
<Switch
|
||||
// disabled={!(mpAppIds && mpAppIds.length > 0)}
|
||||
checkedChildren="开启"
|
||||
unCheckedChildren="关闭"
|
||||
checked={enabled}
|
||||
onChange={(checked) => {
|
||||
changeEnabled(checked);
|
||||
}}
|
||||
disabled={!hasQrCodePrefix}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<Form
|
||||
labelCol={{ span: 4 }}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
&-qrcode {
|
||||
padding: 16px 32px;
|
||||
font-size: 14px;
|
||||
height: 268px;
|
||||
min-height: 268px;
|
||||
|
||||
&__sociallogin {
|
||||
text-align: center;
|
||||
|
|
|
|||
|
|
@ -335,6 +335,19 @@ export default function Render(
|
|||
/>
|
||||
{Tip}
|
||||
</div>}
|
||||
{loginMode === 'wechatMpForWeb' && <div
|
||||
className={Style['loginbox-qrcode']}
|
||||
>
|
||||
<WechatLoginQrCodeForPublic
|
||||
type="login"
|
||||
oakPath="$login-wechatLogin/qrCode"
|
||||
oakAutoUnmount={true}
|
||||
url={state}
|
||||
size={180}
|
||||
qrCodeType={'wechatMpDomainUrl'}
|
||||
/>
|
||||
{Tip}
|
||||
</div>}
|
||||
{(inputOptions?.length > 0 || oauthOptions?.length > 0) ? (
|
||||
<div className={Style['loginbox-methods']}>
|
||||
<Divider plain style={{ fontSize: 13, color: '#808080', }}>{t('otherMethods')}</Divider>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,30 @@
|
|||
<!-- index.wxml -->
|
||||
<view class="page-body">
|
||||
绑定小程序尚未实现
|
||||
<block wx:if="{{expired}}">
|
||||
<view class="circle-view">
|
||||
<l-icon name="warning" size="120" />
|
||||
<text class="text">二维码已过期,请重新扫码</text>
|
||||
<text class="desc">抱歉,该码已过期</text>
|
||||
</view>
|
||||
</block>
|
||||
<block wx:if="{{type==='login'}}">
|
||||
<view wx:if="{{successed}}" class="circle-view">
|
||||
<l-icon name="success" size="120" />
|
||||
<text class="text">登录成功</text>
|
||||
</view>
|
||||
<block wx:else>
|
||||
<l-button
|
||||
type="default"
|
||||
size="long"
|
||||
disabled="{{oakExecuting || oakLoading}}"
|
||||
bind:lintap="loginByWechatMp"
|
||||
style="width:100%"
|
||||
>
|
||||
一键登录
|
||||
</l-button>
|
||||
</block>
|
||||
</block>
|
||||
<view wx:else>
|
||||
绑定小程序尚未实现
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ export default OakComponent({
|
|||
},
|
||||
lifetimes: {
|
||||
attached() {
|
||||
if (process.env.OAK_PLATFORM === 'web') {
|
||||
// if (process.env.OAK_PLATFORM === 'web') {
|
||||
//处理微信授权登录
|
||||
this.login();
|
||||
}
|
||||
// }
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -280,13 +280,14 @@ export class Token<ED extends EntityDict> 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);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ const triggers: Trigger<EntityDict, 'application', BRC<EntityDict>>[] = [
|
|||
}
|
||||
} as RemoveTrigger<EntityDict, 'application', BRC<EntityDict>>,
|
||||
{
|
||||
name: 'web applicaiton清空微信网站配置时,将相应的applicationPassport删除',
|
||||
name: 'web applicaiton清空微信网站配置时,将相应的passport禁用',
|
||||
entity: 'application',
|
||||
action: 'update',
|
||||
when: 'before',
|
||||
|
|
@ -39,7 +39,7 @@ const triggers: Trigger<EntityDict, 'application', BRC<EntityDict>>[] = [
|
|||
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<EntityDict, 'application', BRC<EntityDict>>[] = [
|
|||
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<EntityDict, 'application', BRC<EntityDict>>[] = [
|
|||
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<EntityDict, 'application', BRC<EntityDict>>[] = [
|
|||
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<EntityDict, 'application', BRC<EntityDict>>[] = [
|
|||
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<EntityDict, 'application', BRC<EntityDict>>[] = [
|
|||
}
|
||||
} 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<EntityDict, 'application', BRC<EntityDict>>[] = [
|
|||
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<EntityDict, 'application', BRC<EntityDict>>[] = [
|
|||
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',
|
||||
|
|
|
|||
Loading…
Reference in New Issue