重构了userRelation/upsert

This commit is contained in:
Xu Chang 2025-10-09 14:56:45 +08:00
commit d8be2d5323
66 changed files with 524 additions and 598 deletions

View File

@ -168,8 +168,10 @@ export function TocView(props) {
rootMargin: '0px 0px -75% 0px',
});
// 开始观察所有内容区块
sections.forEach(section => {
observer.observe(section);
sections?.forEach(section => {
if (section) {
observer.observe(section);
}
});
return () => {
if (tocContainer) {

View File

@ -19,7 +19,7 @@ export default OakComponent({
breadcrumbItems: [],
showAddArticle: false,
showAddMenu: true,
parentId: undefined,
parentId: '',
articleMenuId: '',
unsub: undefined,
},

View File

@ -19,7 +19,7 @@ export default function Render(props) {
<div className={Styles.header}>
<Breadcrumb items={breadcrumbItems} itemRender={itemRender} separator=">"/>
<Space>
{!!showAddArticle && (<Button key="article" type="primary" icon={<PlusOutlined />} onClick={() => onAddArticle()}>{t('addArticle')}</Button>)}
{(!!showAddArticle && !(parentId === '' && articleMenuId === '')) && (<Button key="article" type="primary" icon={<PlusOutlined />} onClick={() => onAddArticle()}>{t('addArticle')}</Button>)}
{!!showAddMenu && (<Button key="menu" type="primary" icon={<PlusOutlined />} onClick={() => setAddMenuOpen(true)}>{t('addMenu')}</Button>)}
</Space>
</div>

View File

@ -1,4 +1,5 @@
/// <reference types="react" />
import { GenerateUrlFn } from "../../../types/Article";
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "articleMenu", true, {
entity: string;
entityId: string;
@ -8,6 +9,6 @@ declare const _default: (props: import("oak-frontend-base").ReactComponentProps<
onArticleClick: (atricleId: string) => void;
empty: import("react").ReactNode;
changeAddArticle: (show: boolean) => void;
generateUrl: (mode: 'article' | 'menu', type: 'detail' | 'editor' | 'preview' | 'create', id: string) => string;
generateUrl: GenerateUrlFn;
}>) => React.ReactElement;
export default _default;

View File

@ -98,7 +98,7 @@ export default OakComponent({
onArticleClick: (atricleId) => undefined,
empty: undefined,
changeAddArticle: (show) => undefined,
generateUrl: (mode, type, id) => undefined,
generateUrl: ((mode, type, id) => { }),
},
listeners: {
'entity,entityId,parentId'(prev, next) {

View File

@ -1,7 +1,7 @@
import { Style } from '../../../../types/Style';
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../../oak-app-domain").EntityDict, keyof import("../../../../oak-app-domain").EntityDict, false, {
style: Style;
entity: "platform" | "system" | "application";
entity: "system" | "platform" | "application";
entityId: string;
name: string;
}>) => React.ReactElement;

View File

@ -1,7 +1,7 @@
import { Config } from '../../../types/Config';
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, keyof import("../../../oak-app-domain").EntityDict, false, {
config: Config;
entity: "platform" | "system";
entity: "system" | "platform";
name: string;
entityId: string;
}>) => React.ReactElement;

View File

@ -15,7 +15,7 @@ declare const _default: <ED2 extends EntityDict & BaseEntityDict, T2 extends key
type?: ButtonProps['type'] | AmButtonProps['type'];
executeText?: string | undefined;
buttonProps?: (ButtonProps & {
color?: "default" | "primary" | "success" | "warning" | "danger" | undefined;
color?: "default" | "success" | "warning" | "primary" | "danger" | undefined;
fill?: "none" | "solid" | "outline" | undefined;
size?: "small" | "large" | "middle" | "mini" | undefined;
block?: boolean | undefined;

View File

@ -5,7 +5,7 @@ declare const _default: <ED2 extends EntityDict & BaseEntityDict, T2 extends key
entity: keyof ED2;
entityId: string;
relations: EntityDict['relation']['OpSchema'][];
passwordRequire?: boolean | undefined;
passwordRequired?: boolean | undefined;
allowUpdateName?: boolean | undefined;
allowUpdateNickname?: boolean | undefined;
}>) => React.ReactElement;

View File

@ -22,9 +22,7 @@ export default OakComponent({
entity: '',
entityId: '',
relations: [],
passwordRequire: false,
allowUpdateName: false,
allowUpdateNickname: false,
passwordRequired: false,
},
data: {
mobileValue: '',

View File

@ -28,6 +28,7 @@
entity="{{entity}}"
entityId="{{entityId}}"
relations="{{relations}}"
passwordRequired="{{passwordRequired}}"
isComponent="{{true}}"
/>
</block>

View File

@ -8,9 +8,7 @@ export default function Render(props: WebComponentProps<EntityDict, 'mobile', fa
mobileValue: string;
mobileValueReady: boolean;
userId: string;
passwordRequire: boolean;
allowUpdateName?: boolean;
allowUpdateNickname?: boolean;
passwordRequired: boolean;
isNew: boolean;
oakExecutable: boolean;
}, {

View File

@ -3,7 +3,7 @@ import { Form, Input, Button } from 'antd-mobile';
import Style from './web.module.less';
import OnUser from '../onUser/index';
export default function Render(props) {
const { mobileValue, mobileValueReady, relations, entity, entityId, userId, oakFullpath, oakExecutable, oakDirty, passwordRequire, allowUpdateName, allowUpdateNickname, isNew, } = props.data;
const { mobileValue, mobileValueReady, relations, entity, entityId, userId, oakFullpath, oakExecutable, oakDirty, passwordRequired, isNew, } = props.data;
const { onConfirm, onMobileChange, onReset, t } = props.methods;
return (<Form footer={<div className={Style.btnContainer}>
<Button color="primary" style={{ flex: 2 }} onClick={() => {
@ -35,6 +35,6 @@ export default function Render(props) {
}} placeholder={t('inputMobile')} type="tel" clearable/>
</>
</Form.Item>
{mobileValueReady && (<OnUser oakAutoUnmount={true} oakPath={`${oakFullpath}.user`} entity={entity} entityId={entityId} relations={relations} passwordRequire={passwordRequire} allowUpdateName={allowUpdateName} allowUpdateNickname={allowUpdateNickname} isNew={isNew}/>)}
{mobileValueReady && (<OnUser oakAutoUnmount={true} oakPath={`${oakFullpath}.user`} entity={entity} entityId={entityId} relations={relations} passwordRequired={passwordRequired} isNew={isNew}/>)}
</Form>);
}

View File

@ -10,9 +10,7 @@ export default function Render(props: WebComponentProps<EntityDict, 'mobile', fa
userId: string;
legal: boolean;
isNew: boolean;
passwordRequire: boolean;
allowUpdateName?: boolean;
allowUpdateNickname?: boolean;
passwordRequired: boolean;
oakExecutable: boolean;
}, {
onMobileChange: (value: string) => Promise<void>;

View File

@ -3,7 +3,7 @@ import { Form, Input, Button, Space } from 'antd';
import Style from './web.pc.module.less';
import OnUser from '../onUser/index';
export default function Render(props) {
const { mobileValue, mobileValueReady, relations, entity, entityId, userId, oakFullpath, oakExecutable, legal, isNew, passwordRequire, allowUpdateName, allowUpdateNickname, } = props.data;
const { mobileValue, mobileValueReady, relations, entity, entityId, userId, oakFullpath, oakExecutable, legal, isNew, passwordRequired, } = props.data;
const { onConfirm, onMobileChange, onReset, t } = props.methods;
const [passwordConfirm, setPasswordConfirm] = useState(true);
return (<div className={Style.container}>
@ -29,7 +29,7 @@ export default function Render(props) {
}} placeholder="请输入手机号码" type="tel"/>
</Form.Item>
</Form>
{mobileValueReady && (<OnUser oakAutoUnmount={true} oakPath={`${oakFullpath}.user`} oakId={userId} entity={entity} entityId={entityId} relations={relations} setPasswordConfirm={setPasswordConfirm} passwordRequire={passwordRequire} allowUpdateName={allowUpdateName} allowUpdateNickname={allowUpdateNickname} isNew={isNew}/>)}
{mobileValueReady && (<OnUser oakAutoUnmount={true} oakPath={`${oakFullpath}.user`} oakId={userId} entity={entity} entityId={entityId} relations={relations} setPasswordConfirm={setPasswordConfirm} passwordRequired={passwordRequired} isNew={isNew}/>)}
<Form colon labelCol={{ span: 4 }} wrapperCol={{ span: 8 }}>
<Form.Item wrapperCol={{ offset: 4 }}>
<Space>

View File

@ -31,7 +31,6 @@ export default OakComponent({
qrCodeType: '',
multiple: false,
rule: 'single',
ruleOnRow: 'single',
},
data: {
period: 15,
@ -81,7 +80,7 @@ export default OakComponent({
},
setInit() {
const userId = this.features.token.getUserId();
const { entity, entityId, type, redirectToAfterConfirm, qrCodeType, claimUrl, multiple, rule, ruleOnRow, } = this.props;
const { entity, entityId, type, redirectToAfterConfirm, qrCodeType, claimUrl, multiple, rule, } = this.props;
// if (this.isCreation()) {
this.update({
entity,
@ -93,7 +92,7 @@ export default OakComponent({
type: type || 'grant',
multiple,
rule: rule || 'single',
ruleOnRow: ruleOnRow || 'single',
ruleOnRow: 'single',
granterId: userId,
redirectTo: redirectToAfterConfirm,
qrCodeType: qrCodeType,

View File

@ -7,8 +7,7 @@ declare const _default: <ED2 extends EntityDict & BaseEntityDict, T2 extends key
redirectToAfterConfirm: ED2["userEntityGrant"]["Schema"]["redirectTo"];
claimUrl: string;
qrCodeType: string;
passwordRequire?: boolean | undefined;
allowUpdateName?: boolean | undefined;
allowUpdateNickname?: boolean | undefined;
passwordRequired?: boolean | undefined;
disabledMethods: Array<'email' | 'mobile' | 'userEntityGrant'>;
}>) => React.ReactElement;
export default _default;

View File

@ -1,4 +1,3 @@
import { assert } from 'oak-domain/lib/utils/assert';
export default OakComponent({
isList: true,
entity: 'relation',
@ -10,10 +9,7 @@ export default OakComponent({
display: 1,
},
data: {
grantByUserEntityGrant: false,
grantByEmail: false,
grantByMobile: false,
grantMethodCount: 0,
enabled: ['email', 'mobile', 'userEntityGrant'],
},
filters: [
{
@ -59,44 +55,31 @@ export default OakComponent({
claimUrl: '',
qrCodeType: '',
rule: 'single',
ruleOnRow: 'single',
passwordRequire: false,
allowUpdateName: false,
allowUpdateNickname: false,
passwordRequired: false,
disabledMethods: [],
},
lifetimes: {
ready() {
const isRoot = this.features.token.isRoot();
const application = this.features.application.getApplication();
const { type, config } = application; // 这个页面总不可能是第一个页面吧application肯定初始化完成了
let grantByUserEntityGrant = false, grantByMobile = false, grantByEmail = false;
if (type.startsWith('wechat')) {
grantByUserEntityGrant = true;
}
else {
assert(type === 'web');
const passport = config.passport || [];
grantByEmail = passport.includes('email');
// 是超级管理员 不需要根据配置手机号来判断 by wkj
grantByMobile = isRoot || passport.includes('mobile');
grantByUserEntityGrant = passport.includes('wechat');
}
let grantMethodCount = 0;
if (grantByEmail) {
grantMethodCount++;
}
if (grantByMobile) {
grantMethodCount++;
}
if (grantByUserEntityGrant) {
grantMethodCount++;
}
this.setState({
grantMethodCount,
grantByUserEntityGrant,
grantByEmail,
grantByMobile,
async ready() {
const { disabledMethods } = this.props;
const { systemId } = this.features.application.getApplication();
const { data: passports } = await this.features.cache.refresh('passport', {
data: {
id: 1,
type: 1,
},
filter: {
systemId,
},
});
const passportTypes = passports.map(ele => ele.type);
const enabled = ['userEntityGrant'];
if (passportTypes.includes('sms') && !disabledMethods?.includes('mobile')) {
enabled.push('mobile');
}
if (passportTypes.includes('email') && !disabledMethods?.includes('email')) {
enabled.push('email');
}
this.setState({ enabled });
},
},
});

View File

@ -1,4 +1,9 @@
{
"navigationBarTitleText": "添加权限",
"usingComponents": {}
"usingComponents": {
"l-tabs": "@oak-frontend-base/miniprogram_npm/lin-ui/tabs/index",
"l-tabpanel": "@oak-frontend-base/miniprogram_npm/lin-ui/tabpanel/index",
"byMobile": "./byMobile/index",
"byUserEntityGrant": "./byUserEntityGrant/index"
}
}

View File

@ -2,27 +2,11 @@
@import "../../../config/styles/mp/index.less";
@import "../../../config/styles/mp/mixins.less";
page {
.container {
height: 100%;
background-color: @bg-color;
}
.page-body {
height: 100%;
display: flex;
flex: 1;
flex-direction: column;
box-sizing: border-box;
align-items: stretch;
padding: 0;
.safe-area-inset-bottom();
}
.col {
width: 100%;
display: flex;
flex-direction: column;
}
.btn-view {
display: flex;
margin: 0rpx @spacer-2;
align-items: center;
justify-content: center;
}

View File

@ -1,4 +1,66 @@
<!-- index.wxml -->
<view class="page-body">
</view>
<block wx:if="{{enabled.length === 0}}">
<view class="container">
{{t('noMethods')}}
</view>
</block>
<block wx:elif="{{enabled.length === 1}}">
<block wx:if="{{enabled[0] === 'email'}}">
<view class="container">
{{t('not-implemented')}}
</view>
</block>
<block wx:elif="{{enabled[0] === 'mobile'}}">
<byMobile
passwordRequired="{{passwordRequired}}"
entity="{{entity}}"
entityId="{{entityId}}"
relations="{{relations}}"
oakPath="$userRelation-upsert-by-mobile"
/>
</block>
<block wx:else>
<byUserEntityGrant
qrCodeType="{{qrCodeType}}"
entity="{{entity}}"
entityId="{{entityId}}"
relations="{{relations}}"
claimUrl="{{claimUrl}}"
rule="{{rule}}"
oakPath="$userRelation-upsert-by-userEntityGrant"
redirectToAfterConfirm="{{redirectToAfterConfirm}}"
/>
</block>
</block>
<block wx:else>
<l-tabs>
<l-tabpanel wx:for="{{enabled}}" wx:key="index" tab="{{t('methods.' + item)}}" key="{{item}}" slot="{{item}}">
<block wx:if="{{item === 'email'}}">
<view class="container">
{{t('not-implemented')}}
</view>
</block>
<block wx:elif="{{item === 'mobile'}}">
<byMobile
passwordRequired="{{passwordRequired}}"
entity="{{entity}}"
entityId="{{entityId}}"
relations="{{relations}}"
oakPath="$userRelation-upsert-by-mobile"
/>
</block>
<block wx:else>
<byUserEntityGrant
qrCodeType="{{qrCodeType}}"
entity="{{entity}}"
entityId="{{entityId}}"
relations="{{relations}}"
claimUrl="{{claimUrl}}"
rule="{{rule}}"
oakPath="$userRelation-upsert-by-userEntityGrant"
redirectToAfterConfirm="{{redirectToAfterConfirm}}"
/>
</block>
</l-tabpanel>
<l-tabs>
</block>

View File

@ -0,0 +1,9 @@
{
"noMethods": "没有有效的授权途径(手机号、邮箱、用户自领),请检查配置",
"methods": {
"mobile": "手机号",
"email": "电子邮箱",
"userEntityGrant": "用户自领"
},
"not-implemented": "尚未实现"
}

View File

@ -5,9 +5,7 @@ declare const _default: (props: import("oak-frontend-base").ReactComponentProps<
relations: import("../../../../oak-app-domain/Relation/_baseSchema").OpSchema[];
mobile: string;
setPasswordConfirm: (value: boolean) => void;
passwordRequire: boolean;
allowUpdateName: boolean;
allowUpdateNickname: boolean;
passwordRequired: boolean;
isNew: boolean;
}>) => React.ReactElement;
export default _default;

View File

@ -72,9 +72,7 @@ export default OakComponent({
relations: [],
mobile: '',
setPasswordConfirm: (value) => { },
passwordRequire: false,
allowUpdateName: false,
allowUpdateNickname: false,
passwordRequired: false,
isNew: false,
},
});

View File

@ -13,9 +13,7 @@ export default function Render(props: WebComponentProps<EntityDict, 'user', fals
entityId: string;
isNew: boolean;
setPasswordConfirm: (value: boolean) => void;
passwordRequire: boolean;
allowUpdateName?: boolean;
allowUpdateNickname?: boolean;
passwordRequired: boolean;
}, {
onMobileChange: (value: string) => Promise<void>;
onConfirm: () => Promise<void>;

View File

@ -4,7 +4,7 @@ import UserRelation from './userRelation';
import { EyeInvisibleOutlined, EyeTwoTone } from '@ant-design/icons';
import { encryptPasswordSha1 } from '../../../../utils/password';
export default function Render(props) {
const { name, isNew, nickname, password, relations, oakFullpath, entity, entityId, setPasswordConfirm, passwordRequire, allowUpdateName, allowUpdateNickname, } = props.data;
const { name, isNew, nickname, password, relations, oakFullpath, entity, entityId, setPasswordConfirm, passwordRequired, } = props.data;
const { t, update } = props.methods;
const [form] = Form.useForm();
const [password2, setPassword2] = useState('');
@ -30,9 +30,9 @@ export default function Render(props) {
},
]}>
<>
<Input disabled={!isNew && !allowUpdateName} onChange={(e) => {
<Input disabled={!isNew} onChange={(e) => {
const strValue = e.target.value;
if (isNew || allowUpdateName) {
if (isNew) {
update({
name: strValue,
});
@ -42,9 +42,9 @@ export default function Render(props) {
</Form.Item>
<Form.Item label={t('user:attr.nickname')} name="nickname">
<>
<Input disabled={!isNew && !allowUpdateNickname} value={nickname} onChange={(e) => {
<Input disabled={!isNew} value={nickname} onChange={(e) => {
const strValue = e.target.value;
if (isNew || allowUpdateNickname) {
if (isNew) {
update({
nickname: strValue,
});
@ -55,7 +55,7 @@ export default function Render(props) {
{isNew ? (<>
<Form.Item label={t('user:attr.password')} name="password" help={validateHelp1} rules={[
{
required: passwordRequire,
required: passwordRequired,
message: '请输入密码',
validator: (_, value) => {
if (!value && !password2) {
@ -97,7 +97,7 @@ export default function Render(props) {
</Form.Item>
<Form.Item label={'确认密码'} name="confirmPassword" rules={[
{
required: passwordRequire,
required: passwordRequired,
validator: (_, value) => {
if (!value && !password) {
setValidateHelp('');

View File

@ -1,12 +1,8 @@
/// <reference types="react" />
import React from 'react';
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
import { QrCodeType } from '../../../types/Config';
export default function Render(props: WebComponentProps<EntityDict, 'user', false, {
grantByUserEntityGrant: boolean;
grantByEmail: boolean;
grantByMobile: boolean;
grantMethodCount: number;
redirectToAfterConfirm: EntityDict['userEntityGrant']['Schema']['redirectTo'];
claimUrl: string;
entity: keyof EntityDict;
@ -14,8 +10,6 @@ export default function Render(props: WebComponentProps<EntityDict, 'user', fals
relations: EntityDict['relation']['OpSchema'][];
qrCodeType?: QrCodeType;
rule: EntityDict['userEntityGrant']['OpSchema']['rule'];
ruleOnRow: EntityDict['userEntityGrant']['OpSchema']['ruleOnRow'];
passwordRequire: boolean;
allowUpdateName?: boolean;
allowUpdateNickname?: boolean;
}, {}>): JSX.Element;
passwordRequired: boolean;
enabled: Array<'email' | 'mobile' | 'userEntityGrant'>;
}, {}>): React.JSX.Element;

View File

@ -3,60 +3,33 @@ import { Tabs } from 'antd-mobile';
import Style from './mobile.module.less';
import ByMobile from './byMobile/index';
import ByUserEntityGrant from './byUserEntityGrant';
import { assert } from 'oak-domain/lib/utils/assert';
export default function Render(props) {
const { entity, entityId, relations, grantByUserEntityGrant, grantByEmail, grantByMobile, grantMethodCount, oakFullpath, redirectToAfterConfirm, qrCodeType, claimUrl, rule, ruleOnRow, passwordRequire, allowUpdateName, allowUpdateNickname, } = props.data;
let SubPart = <></>;
if (grantMethodCount === 0) {
SubPart = (<div className={Style.container}>
应用没有定义授权方式请管理员在控制台中定义
const { entity, entityId, relations, redirectToAfterConfirm, qrCodeType, claimUrl, rule, passwordRequired, enabled, } = props.data;
const { t } = props.methods;
if (enabled.length === 0) {
return (<div className={Style.container}>
{t('noMethods')}
</div>);
}
else if (grantMethodCount === 1) {
if (grantByEmail) {
SubPart = <div className={Style.container}>尚未实现</div>;
}
else if (grantByMobile) {
SubPart = (<ByMobile allowUpdateName={allowUpdateName} allowUpdateNickname={allowUpdateNickname} passwordRequire={passwordRequire} entity={entity} entityId={entityId} relations={relations} oakPath="$userRelation-upsert-by-mobile" oakAutoUnmount={true}/>);
}
else {
assert(grantByUserEntityGrant === true);
SubPart = (<ByUserEntityGrant qrCodeType={qrCodeType} entity={entity} entityId={entityId} relations={relations} oakPath="$userRelation-upsert-by-userEntityGrant" oakAutoUnmount={true} redirectToAfterConfirm={redirectToAfterConfirm} claimUrl={claimUrl}/>);
const SubParts = enabled.map((ele) => {
switch (ele) {
case 'email': {
return <div className={Style.container}>{t('not-implemented')}</div>;
}
case 'mobile': {
return (<ByMobile passwordRequired={passwordRequired} entity={entity} entityId={entityId} relations={relations} oakPath="$userRelation-upsert-by-mobile" oakAutoUnmount={true}/>);
}
case 'userEntityGrant': {
return (<ByUserEntityGrant qrCodeType={qrCodeType} entity={entity} entityId={entityId} relations={relations} claimUrl={claimUrl} rule={rule} oakPath="$userRelation-upsert-by-userEntityGrant" oakAutoUnmount={true} redirectToAfterConfirm={redirectToAfterConfirm}/>);
}
}
});
if (SubParts.length === 1) {
return SubParts[0];
}
else {
const items = [
{
label: 'Email',
key: 'item-1',
children: <div className={Style.container}>尚未实现</div>,
},
{
label: '二维码',
key: 'item-2',
children: (<ByUserEntityGrant entity={entity} entityId={entityId} relations={relations} qrCodeType={qrCodeType} oakPath="$userRelation-upsert-by-userEntityGrant" oakAutoUnmount={true} redirectToAfterConfirm={redirectToAfterConfirm} claimUrl={claimUrl} rule={rule} ruleOnRow={ruleOnRow}/>),
},
{
label: '手机号',
key: 'item-3',
children: (<ByMobile allowUpdateName={allowUpdateName} allowUpdateNickname={allowUpdateNickname} passwordRequire={passwordRequire} entity={entity} entityId={entityId} relations={relations} oakPath="$userRelation-upsert-by-mobile" oakAutoUnmount={true}/>),
},
];
const items2 = [];
if (grantByEmail) {
items2.push(items[0]);
}
if (grantByUserEntityGrant) {
items2.push(items[1]);
}
if (grantByMobile) {
items2.push(items[2]);
}
SubPart = (<Tabs className={Style.tab}>
{items2.map((ele) => (<Tabs.Tab title={ele.label} key={ele.key}>
{ele.children}
</Tabs.Tab>))}
</Tabs>);
}
return SubPart;
return (<Tabs className={Style.tab}>
{enabled.map((ele, idx) => (<Tabs.Tab title={t(`methods.${ele}`)} key={`item-${idx}`}>
{SubParts[idx]}
</Tabs.Tab>))}
</Tabs>);
}

View File

@ -1,12 +1,8 @@
/// <reference types="react" />
import React from 'react';
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
import { QrCodeType } from '../../../types/Config';
export default function Render(props: WebComponentProps<EntityDict, 'relation', true, {
grantByUserEntityGrant: boolean;
grantByEmail: boolean;
grantByMobile: boolean;
grantMethodCount: number;
redirectToAfterConfirm: EntityDict['userEntityGrant']['Schema']['redirectTo'];
claimUrl: string;
entity: keyof EntityDict;
@ -14,8 +10,6 @@ export default function Render(props: WebComponentProps<EntityDict, 'relation',
relations: EntityDict['relation']['OpSchema'][];
qrCodeType?: QrCodeType;
rule: EntityDict['userEntityGrant']['OpSchema']['rule'];
ruleOnRow: EntityDict['userEntityGrant']['OpSchema']['ruleOnRow'];
passwordRequire: boolean;
allowUpdateName?: boolean;
allowUpdateNickname?: boolean;
}, {}>): JSX.Element;
passwordRequired: boolean;
enabled: Array<'email' | 'mobile' | 'userEntityGrant'>;
}, {}>): React.JSX.Element;

View File

@ -3,56 +3,33 @@ import { Tabs } from 'antd';
import Style from './web.module.less';
import ByMobile from './byMobile/index';
import ByUserEntityGrant from './byUserEntityGrant';
import { assert } from 'oak-domain/lib/utils/assert';
export default function Render(props) {
const { entity, entityId, relations, grantByUserEntityGrant, grantByEmail, grantByMobile, grantMethodCount, oakFullpath, redirectToAfterConfirm, qrCodeType, claimUrl, rule, ruleOnRow, passwordRequire, allowUpdateName, allowUpdateNickname, } = props.data;
let SubPart = <></>;
if (grantMethodCount === 0) {
SubPart = (<div className={Style.container}>
应用没有定义授权方式请管理员在控制台中定义
const { entity, entityId, relations, enabled, redirectToAfterConfirm, qrCodeType, claimUrl, rule, passwordRequired, } = props.data;
const { t } = props.methods;
if (enabled.length === 0) {
return (<div className={Style.container}>
{t('noMethods')}
</div>);
}
else if (grantMethodCount === 1) {
if (grantByEmail) {
SubPart = <div className={Style.container}>尚未实现</div>;
}
else if (grantByMobile) {
SubPart = (<ByMobile allowUpdateName={allowUpdateName} allowUpdateNickname={allowUpdateNickname} passwordRequire={passwordRequire} entity={entity} entityId={entityId} relations={relations} oakPath="$userRelation-upsert-by-mobile" oakAutoUnmount={true}/>);
}
else {
assert(grantByUserEntityGrant === true);
SubPart = (<ByUserEntityGrant qrCodeType={qrCodeType} entity={entity} entityId={entityId} relations={relations} claimUrl={claimUrl} oakPath="$userRelation-upsert-by-userEntityGrant" oakAutoUnmount={true} redirectToAfterConfirm={redirectToAfterConfirm}/>);
const SubParts = enabled.map((ele) => {
switch (ele) {
case 'email': {
return <div className={Style.container}>{t('not-implemented')}</div>;
}
case 'mobile': {
return (<ByMobile passwordRequired={passwordRequired} entity={entity} entityId={entityId} relations={relations} oakPath="$userRelation-upsert-by-mobile" oakAutoUnmount={true}/>);
}
case 'userEntityGrant': {
return (<ByUserEntityGrant qrCodeType={qrCodeType} entity={entity} entityId={entityId} relations={relations} claimUrl={claimUrl} rule={rule} oakPath="$userRelation-upsert-by-userEntityGrant" oakAutoUnmount={true} redirectToAfterConfirm={redirectToAfterConfirm}/>);
}
}
});
if (SubParts.length === 1) {
return SubParts[0];
}
else {
const items = [
{
label: 'Email',
key: 'item-1',
children: <div className={Style.container}>尚未实现</div>,
},
{
label: '二维码',
key: 'item-2',
children: (<ByUserEntityGrant entity={entity} entityId={entityId} relations={relations} qrCodeType={qrCodeType} oakPath="$userRelation-upsert-by-userEntityGrant" oakAutoUnmount={true} redirectToAfterConfirm={redirectToAfterConfirm} claimUrl={claimUrl} rule={rule} ruleOnRow={ruleOnRow}/>),
},
{
label: '手机号',
key: 'item-3',
children: (<ByMobile allowUpdateName={allowUpdateName} allowUpdateNickname={allowUpdateNickname} passwordRequire={passwordRequire} entity={entity} entityId={entityId} relations={relations} oakPath="$userRelation-upsert-by-mobile" oakAutoUnmount={true}/>),
},
];
const items2 = [];
if (grantByEmail) {
items2.push(items[0]);
}
if (grantByUserEntityGrant) {
items2.push(items[1]);
}
if (grantByMobile) {
items2.push(items[2]);
}
SubPart = <Tabs items={items2}/>;
}
return SubPart;
return (<Tabs items={enabled.map((ele, idx) => ({
label: t(`methods.${ele}`),
key: `item-${idx}`,
children: SubParts[idx]
}))}/>);
}

View File

@ -1,6 +1,6 @@
import { EntityDict } from '../../../oak-app-domain';
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, keyof EntityDict, false, {
type: "login" | "bind";
type: "bind" | "login";
url: string;
size: undefined;
}>) => React.ReactElement;

View File

@ -632,6 +632,22 @@ const i18ns = [
}
}
},
{
id: "5ce54ef75387e766a33bd2b74709d32a",
namespace: "oak-general-business-c-userRelation-upsert",
language: "zh-CN",
module: "oak-general-business",
position: "src/components/userRelation/upsert",
data: {
"noMethods": "没有有效的授权途径(手机号、邮箱、用户自领),请检查配置",
"methods": {
"mobile": "手机号",
"email": "电子邮箱",
"userEntityGrant": "用户自领"
},
"not-implemented": "尚未实现"
}
},
{
id: "724a46f659f9bfa42239b79e59761f0e",
namespace: "oak-general-business-c-userRelation-upsert-onUser",

View File

@ -4,7 +4,6 @@ import { Schema as System } from './System';
import { Schema as Session } from './Session';
import { Schema as Domain } from './Domain';
import { Style } from '../types/Style';
export type Passport = 'email' | 'mobile' | 'wechat' | 'wechatPublic' | 'wechatNative';
export type AppType = 'web' | 'wechatMp' | 'wechatPublic' | 'native';
export type WechatMpConfig = {
type: 'wechatMp';
@ -19,7 +18,6 @@ export type WechatMpConfig = {
mode: 'clear' | 'compatible' | 'safe';
dataFormat: 'json' | 'xml';
};
passport?: Passport[];
};
export type WebConfig = {
type: 'web';
@ -33,7 +31,6 @@ export type WebConfig = {
appId: string;
appSecret: string;
};
passport?: Passport[];
location: {
protocol: 'http:' | 'https:';
hostname: string;
@ -56,7 +53,6 @@ export type WechatPublicConfig = {
appId: string;
originalId: string;
};
passport?: Passport[];
location: {
protocol: 'http:' | 'https:';
hostname: string;
@ -65,7 +61,6 @@ export type WechatPublicConfig = {
};
export type NativeConfig = {
type: 'native';
passport?: Passport[];
wechatNative?: {
appId: string;
appSecret: string;

View File

@ -4,7 +4,6 @@ import { MakeAction as OakMakeAction, EntityShape } from "oak-domain/lib/types/E
import { GenericAction } from "oak-domain/lib/actions/action";
import { String, Text } from "oak-domain/lib/types/DataType";
import { Style } from "../../types/Style";
export type Passport = "email" | "mobile" | "wechat" | "wechatPublic" | "wechatNative";
export type AppType = "web" | "wechatMp" | "wechatPublic" | "native";
export type WechatMpConfig = {
type: "wechatMp";
@ -19,7 +18,6 @@ export type WechatMpConfig = {
mode: "clear" | "compatible" | "safe";
dataFormat: "json" | "xml";
};
passport?: Passport[];
};
export type WebConfig = {
type: "web";
@ -33,7 +31,6 @@ export type WebConfig = {
appId: string;
appSecret: string;
};
passport?: Passport[];
location: {
protocol: "http:" | "https:";
hostname: string;
@ -56,7 +53,6 @@ export type WechatPublicConfig = {
appId: string;
originalId: string;
};
passport?: Passport[];
location: {
protocol: "http:" | "https:";
hostname: string;
@ -65,7 +61,6 @@ export type WechatPublicConfig = {
};
export type NativeConfig = {
type: "native";
passport?: Passport[];
wechatNative?: {
appId: string;
appSecret: string;

View File

@ -141,6 +141,8 @@ const triggers = [
id: 1,
name: 1,
parentId: 1,
entity: 1,
entityId: 1,
},
filter,
}, {});
@ -152,6 +154,8 @@ const triggers = [
parentId: 1,
},
filter: {
entity: articleMenu.entity,
entityId: articleMenu.entityId,
name: data.name,
parentId: articleMenu.parentId
? articleMenu.parentId

View File

@ -1,2 +1,2 @@
declare const _default: (import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "message", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "address", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "application", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "article", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "articleMenu", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "extraFile", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "user", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "userEntityGrant", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatQrCode", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "notification", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatLogin", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "parasite", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "sessionMessage", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatMenu", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatPublicTag", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatMpJump", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "system", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "passport", import("..").BRC<import("../oak-app-domain").EntityDict>>)[];
declare const _default: (import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "sessionMessage", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "application", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "message", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "address", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "article", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "articleMenu", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "extraFile", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "user", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "userEntityGrant", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatQrCode", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "notification", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatLogin", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "parasite", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatMenu", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatPublicTag", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatMpJump", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "system", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "passport", import("..").BRC<import("../oak-app-domain").EntityDict>>)[];
export default _default;

View File

@ -14,7 +14,7 @@ export declare function createToDo<ED extends EntityDict & BaseEntityDict, T ext
redirectTo: EntityDict['toDo']['OpSchema']['redirectTo'];
entity: any;
entityId: string;
}, userIds?: string[]): Promise<0 | 1>;
}, userIds?: string[]): Promise<1 | 0>;
/**
* todo例程entity对象上进行action操作时filtertodo完成
* entity的action的后trigger中调用

View File

@ -634,6 +634,22 @@ const i18ns = [
}
}
},
{
id: "5ce54ef75387e766a33bd2b74709d32a",
namespace: "oak-general-business-c-userRelation-upsert",
language: "zh-CN",
module: "oak-general-business",
position: "src/components/userRelation/upsert",
data: {
"noMethods": "没有有效的授权途径(手机号、邮箱、用户自领),请检查配置",
"methods": {
"mobile": "手机号",
"email": "电子邮箱",
"userEntityGrant": "用户自领"
},
"not-implemented": "尚未实现"
}
},
{
id: "724a46f659f9bfa42239b79e59761f0e",
namespace: "oak-general-business-c-userRelation-upsert-onUser",

View File

@ -4,7 +4,6 @@ import { Schema as System } from './System';
import { Schema as Session } from './Session';
import { Schema as Domain } from './Domain';
import { Style } from '../types/Style';
export type Passport = 'email' | 'mobile' | 'wechat' | 'wechatPublic' | 'wechatNative';
export type AppType = 'web' | 'wechatMp' | 'wechatPublic' | 'native';
export type WechatMpConfig = {
type: 'wechatMp';
@ -19,7 +18,6 @@ export type WechatMpConfig = {
mode: 'clear' | 'compatible' | 'safe';
dataFormat: 'json' | 'xml';
};
passport?: Passport[];
};
export type WebConfig = {
type: 'web';
@ -33,7 +31,6 @@ export type WebConfig = {
appId: string;
appSecret: string;
};
passport?: Passport[];
location: {
protocol: 'http:' | 'https:';
hostname: string;
@ -56,7 +53,6 @@ export type WechatPublicConfig = {
appId: string;
originalId: string;
};
passport?: Passport[];
location: {
protocol: 'http:' | 'https:';
hostname: string;
@ -65,7 +61,6 @@ export type WechatPublicConfig = {
};
export type NativeConfig = {
type: 'native';
passport?: Passport[];
wechatNative?: {
appId: string;
appSecret: string;

View File

@ -4,7 +4,6 @@ import { MakeAction as OakMakeAction, EntityShape } from "oak-domain/lib/types/E
import { GenericAction } from "oak-domain/lib/actions/action";
import { String, Text } from "oak-domain/lib/types/DataType";
import { Style } from "../../types/Style";
export type Passport = "email" | "mobile" | "wechat" | "wechatPublic" | "wechatNative";
export type AppType = "web" | "wechatMp" | "wechatPublic" | "native";
export type WechatMpConfig = {
type: "wechatMp";
@ -19,7 +18,6 @@ export type WechatMpConfig = {
mode: "clear" | "compatible" | "safe";
dataFormat: "json" | "xml";
};
passport?: Passport[];
};
export type WebConfig = {
type: "web";
@ -33,7 +31,6 @@ export type WebConfig = {
appId: string;
appSecret: string;
};
passport?: Passport[];
location: {
protocol: "http:" | "https:";
hostname: string;
@ -56,7 +53,6 @@ export type WechatPublicConfig = {
appId: string;
originalId: string;
};
passport?: Passport[];
location: {
protocol: "http:" | "https:";
hostname: string;
@ -65,7 +61,6 @@ export type WechatPublicConfig = {
};
export type NativeConfig = {
type: "native";
passport?: Passport[];
wechatNative?: {
appId: string;
appSecret: string;

View File

@ -143,6 +143,8 @@ const triggers = [
id: 1,
name: 1,
parentId: 1,
entity: 1,
entityId: 1,
},
filter,
}, {});
@ -154,6 +156,8 @@ const triggers = [
parentId: 1,
},
filter: {
entity: articleMenu.entity,
entityId: articleMenu.entityId,
name: data.name,
parentId: articleMenu.parentId
? articleMenu.parentId

View File

@ -1,2 +1,2 @@
declare const _default: (import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "message", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "address", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "application", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "article", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "articleMenu", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "extraFile", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "user", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "userEntityGrant", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatQrCode", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "notification", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatLogin", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "parasite", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "sessionMessage", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatMenu", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatPublicTag", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatMpJump", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "system", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "passport", import("..").BRC<import("../oak-app-domain").EntityDict>>)[];
declare const _default: (import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "sessionMessage", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "application", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "message", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "address", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "article", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "articleMenu", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "extraFile", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "user", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "userEntityGrant", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatQrCode", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "notification", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatLogin", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "parasite", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatMenu", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatPublicTag", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "wechatMpJump", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "system", import("..").BRC<import("../oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Trigger<import("../oak-app-domain").EntityDict, "passport", import("..").BRC<import("../oak-app-domain").EntityDict>>)[];
export default _default;

View File

@ -14,7 +14,7 @@ export declare function createToDo<ED extends EntityDict & BaseEntityDict, T ext
redirectTo: EntityDict['toDo']['OpSchema']['redirectTo'];
entity: any;
entityId: string;
}, userIds?: string[]): Promise<0 | 1>;
}, userIds?: string[]): Promise<1 | 0>;
/**
* todo例程entity对象上进行action操作时filtertodo完成
* entity的action的后trigger中调用

View File

@ -248,8 +248,10 @@ export function TocView(
});
// 开始观察所有内容区块
sections.forEach(section => {
observer.observe(section);
sections?.forEach(section => {
if (section) {
observer.observe(section);
}
});
return () => {

View File

@ -28,7 +28,7 @@ export default OakComponent({
}[],
showAddArticle: false,
showAddMenu: true,
parentId: undefined as string | undefined,
parentId: '',
articleMenuId: '', //非空时展示atricle表格
unsub: undefined as undefined | (() => void),
},

View File

@ -36,7 +36,7 @@ export default function Render(
onAddMenu: (menuName: string) => Promise<boolean>;
changeAddArticle: (show: boolean) => void;
onAddArticle: () => void;
menuCheck:(isArticle: boolean) =>void;
menuCheck: (isArticle: boolean) => void;
}
>
) {
@ -44,7 +44,7 @@ export default function Render(
const { oakFullpath, oakLoading, oakExecuting, entity, entityId, title, breadcrumbItems, origin = 'qiniu', menuEmpty, articleEmpty, parentId, articleMenuId, showAddArticle, showAddMenu,
generateUrl,
} = data;
const { t, onBreadcrumItemClick, onMenuClick, onAddMenu, changeAddArticle, onAddArticle, menuCheck } = methods;
const { t, onBreadcrumItemClick, onMenuClick, onAddMenu, changeAddArticle, onAddArticle, menuCheck } = methods;
const [addMenuOpen, setAddMenuOpen] = useState(false);
@ -66,7 +66,7 @@ export default function Render(
separator=">"
/>
<Space>
{!!showAddArticle && (
{(!!showAddArticle && !(parentId === '' && articleMenuId === '')) && (
<Button key="article" type="primary" icon={<PlusOutlined />} onClick={() => onAddArticle()}>{t('addArticle')}</Button>
)}
{!!showAddMenu && (

View File

@ -2,6 +2,7 @@
import dayjs from "dayjs";
import copy from 'copy-to-clipboard';
import { DATA_SUBSCRIBER_KEYS } from "../../../config/constants";
import { GenerateUrlFn, Mode, Action } from "../../../types/Article";
export default OakComponent({
entity: 'articleMenu',
@ -101,7 +102,7 @@ export default OakComponent({
onArticleClick: (atricleId: string) => undefined as void,
empty: undefined as React.ReactNode | undefined,
changeAddArticle: (show: boolean) => undefined as void,
generateUrl: (mode: 'article' | 'menu', type: 'detail' | 'editor' | 'preview' | 'create', id: string) => undefined as unknown as string,
generateUrl: ((mode: Mode, type: Action, id: string) => {}) as GenerateUrlFn,
},
listeners: {
'entity,entityId,parentId'(prev, next) {

View File

@ -16,7 +16,6 @@ import Styles from './web.module.less';
import {
AppType,
WebConfig,
Passport,
} from '../../../../oak-app-domain/Application/Schema';
export default function Web(props: {

View File

@ -18,7 +18,6 @@ import Styles from './web.module.less';
import {
AppType,
WechatPublicConfig,
Passport,
} from '../../../../oak-app-domain/Application/Schema';

View File

@ -32,9 +32,7 @@ export default OakComponent({
entity: '' as keyof EntityDict,
entityId: '',
relations: [] as EntityDict['relation']['OpSchema'][],
passwordRequire: false,
allowUpdateName: false,
allowUpdateNickname: false,
passwordRequired: false,
},
data: {
mobileValue: '',
@ -130,7 +128,7 @@ export default OakComponent({
entity: keyof ED2;
entityId: string;
relations: EntityDict['relation']['OpSchema'][];
passwordRequire?: boolean;
passwordRequired?: boolean;
allowUpdateName?: boolean;
allowUpdateNickname?: boolean;
}

View File

@ -28,6 +28,7 @@
entity="{{entity}}"
entityId="{{entityId}}"
relations="{{relations}}"
passwordRequired="{{passwordRequired}}"
isComponent="{{true}}"
/>
</block>

View File

@ -19,9 +19,7 @@ export default function Render(
userId: string;
legal: boolean;
isNew: boolean;
passwordRequire: boolean;
allowUpdateName?: boolean;
allowUpdateNickname?: boolean;
passwordRequired: boolean;
oakExecutable: boolean;
},
{
@ -42,9 +40,7 @@ export default function Render(
oakExecutable,
legal,
isNew,
passwordRequire,
allowUpdateName,
allowUpdateNickname,
passwordRequired,
} = props.data;
const { onConfirm, onMobileChange, onReset, t } = props.methods;
const [passwordConfirm, setPasswordConfirm] = useState(true);
@ -90,9 +86,7 @@ export default function Render(
entityId={entityId}
relations={relations}
setPasswordConfirm={setPasswordConfirm}
passwordRequire={passwordRequire}
allowUpdateName={allowUpdateName}
allowUpdateNickname={allowUpdateNickname}
passwordRequired={passwordRequired}
isNew={isNew}
/>
)}

View File

@ -17,9 +17,7 @@ export default function Render(
mobileValue: string;
mobileValueReady: boolean;
userId: string;
passwordRequire: boolean;
allowUpdateName?: boolean;
allowUpdateNickname?: boolean;
passwordRequired: boolean;
isNew: boolean;
oakExecutable: boolean;
},
@ -40,9 +38,7 @@ export default function Render(
oakFullpath,
oakExecutable,
oakDirty,
passwordRequire,
allowUpdateName,
allowUpdateNickname,
passwordRequired,
isNew,
} = props.data;
const { onConfirm, onMobileChange, onReset, t } = props.methods;
@ -104,9 +100,7 @@ export default function Render(
entity={entity}
entityId={entityId}
relations={relations}
passwordRequire={passwordRequire}
allowUpdateName={allowUpdateName}
allowUpdateNickname={allowUpdateNickname}
passwordRequired={passwordRequired}
isNew={isNew}
/>
)}

View File

@ -39,8 +39,6 @@ export default OakComponent({
qrCodeType: '' as QrCodeType,
multiple: false,
rule: 'single' as EntityDict['userEntityGrant']['OpSchema']['rule'],
ruleOnRow:
'single' as EntityDict['userEntityGrant']['OpSchema']['ruleOnRow'],
},
data: {
period: 15,
@ -100,7 +98,6 @@ export default OakComponent({
claimUrl,
multiple,
rule,
ruleOnRow,
} = this.props;
// if (this.isCreation()) {
this.update({
@ -113,7 +110,7 @@ export default OakComponent({
type: type || 'grant',
multiple,
rule: rule || 'single',
ruleOnRow: ruleOnRow || 'single',
ruleOnRow: 'single',
granterId: userId,
redirectTo:
redirectToAfterConfirm as EntityDict['userEntityGrant']['Schema']['redirectTo'],

View File

@ -1,4 +1,9 @@
{
"navigationBarTitleText": "添加权限",
"usingComponents": {}
"navigationBarTitleText": "添加权限",
"usingComponents": {
"l-tabs": "@oak-frontend-base/miniprogram_npm/lin-ui/tabs/index",
"l-tabpanel": "@oak-frontend-base/miniprogram_npm/lin-ui/tabpanel/index",
"byMobile": "./byMobile/index",
"byUserEntityGrant": "./byUserEntityGrant/index"
}
}

View File

@ -2,27 +2,11 @@
@import "../../../config/styles/mp/index.less";
@import "../../../config/styles/mp/mixins.less";
page {
.container {
height: 100%;
background-color: @bg-color;
}
.page-body {
height: 100%;
display: flex;
flex: 1;
flex-direction: column;
box-sizing: border-box;
align-items: stretch;
padding: 0;
.safe-area-inset-bottom();
}
.col {
width: 100%;
display: flex;
flex-direction: column;
}
.btn-view {
display: flex;
margin: 0rpx @spacer-2;
align-items: center;
justify-content: center;
}

View File

@ -16,10 +16,7 @@ export default OakComponent({
display: 1,
},
data: {
grantByUserEntityGrant: false,
grantByEmail: false,
grantByMobile: false,
grantMethodCount: 0,
enabled: ['email', 'mobile', 'userEntityGrant'] as Array<'email' | 'mobile' | 'userEntityGrant'>,
},
filters: [
{
@ -66,46 +63,34 @@ export default OakComponent({
claimUrl: '',
qrCodeType: '' as QrCodeType,
rule: 'single' as EntityDict['userEntityGrant']['OpSchema']['rule'],
ruleOnRow:
'single' as EntityDict['userEntityGrant']['OpSchema']['ruleOnRow'],
passwordRequire: false,
allowUpdateName: false,
allowUpdateNickname: false,
passwordRequired: false,
disabledMethods: [] as Array<'email' | 'mobile' | 'userEntityGrant'>,
},
lifetimes: {
ready() {
const isRoot = this.features.token.isRoot();
const application = this.features.application.getApplication();
const { type, config } = application!; // 这个页面总不可能是第一个页面吧application肯定初始化完成了
let grantByUserEntityGrant = false,
grantByMobile = false,
grantByEmail = false;
if (type!.startsWith('wechat')) {
grantByUserEntityGrant = true;
} else {
assert(type === 'web');
const passport = (config as WebConfig).passport || [];
grantByEmail = passport.includes('email');
// 是超级管理员 不需要根据配置手机号来判断 by wkj
grantByMobile = isRoot || passport.includes('mobile');
grantByUserEntityGrant = passport.includes('wechat');
}
let grantMethodCount = 0;
if (grantByEmail) {
grantMethodCount++;
}
if (grantByMobile) {
grantMethodCount++;
}
if (grantByUserEntityGrant) {
grantMethodCount++;
}
this.setState({
grantMethodCount,
grantByUserEntityGrant,
grantByEmail,
grantByMobile,
async ready() {
const { disabledMethods } = this.props;
const { systemId } = this.features.application.getApplication()!;
const { data: passports } = await this.features.cache.refresh('passport', {
data: {
id: 1,
type: 1,
},
filter: {
systemId,
},
});
const passportTypes = passports.map(
ele => ele.type!
);
const enabled = ['userEntityGrant'] as Array<'email' | 'mobile' | 'userEntityGrant'>
if (passportTypes.includes('sms') && !disabledMethods?.includes('mobile')) {
enabled.push('mobile');
}
if (passportTypes.includes('email') && !disabledMethods?.includes('email')) {
enabled.push('email');
}
this.setState({ enabled });
},
},
}) as <ED2 extends EntityDict & BaseEntityDict, T2 extends keyof ED2>(
@ -119,9 +104,8 @@ export default OakComponent({
redirectToAfterConfirm: ED2['userEntityGrant']['Schema']['redirectTo'];
claimUrl: string;
qrCodeType: string;
passwordRequire?: boolean;
allowUpdateName?: boolean;
allowUpdateNickname?: boolean;
passwordRequired?: boolean;
disabledMethods: Array<'email' | 'mobile' | 'userEntityGrant'>;
}
>
) => React.ReactElement;

View File

@ -1,4 +1,66 @@
<!-- index.wxml -->
<view class="page-body">
</view>
<block wx:if="{{enabled.length === 0}}">
<view class="container">
{{t('noMethods')}}
</view>
</block>
<block wx:elif="{{enabled.length === 1}}">
<block wx:if="{{enabled[0] === 'email'}}">
<view class="container">
{{t('not-implemented')}}
</view>
</block>
<block wx:elif="{{enabled[0] === 'mobile'}}">
<byMobile
passwordRequired="{{passwordRequired}}"
entity="{{entity}}"
entityId="{{entityId}}"
relations="{{relations}}"
oakPath="$userRelation-upsert-by-mobile"
/>
</block>
<block wx:else>
<byUserEntityGrant
qrCodeType="{{qrCodeType}}"
entity="{{entity}}"
entityId="{{entityId}}"
relations="{{relations}}"
claimUrl="{{claimUrl}}"
rule="{{rule}}"
oakPath="$userRelation-upsert-by-userEntityGrant"
redirectToAfterConfirm="{{redirectToAfterConfirm}}"
/>
</block>
</block>
<block wx:else>
<l-tabs>
<l-tabpanel wx:for="{{enabled}}" wx:key="index" tab="{{t('methods.' + item)}}" key="{{item}}" slot="{{item}}">
<block wx:if="{{item === 'email'}}">
<view class="container">
{{t('not-implemented')}}
</view>
</block>
<block wx:elif="{{item === 'mobile'}}">
<byMobile
passwordRequired="{{passwordRequired}}"
entity="{{entity}}"
entityId="{{entityId}}"
relations="{{relations}}"
oakPath="$userRelation-upsert-by-mobile"
/>
</block>
<block wx:else>
<byUserEntityGrant
qrCodeType="{{qrCodeType}}"
entity="{{entity}}"
entityId="{{entityId}}"
relations="{{relations}}"
claimUrl="{{claimUrl}}"
rule="{{rule}}"
oakPath="$userRelation-upsert-by-userEntityGrant"
redirectToAfterConfirm="{{redirectToAfterConfirm}}"
/>
</block>
</l-tabpanel>
<l-tabs>
</block>

View File

@ -0,0 +1,9 @@
{
"noMethods": "没有有效的授权途径(手机号、邮箱、用户自领),请检查配置",
"methods": {
"mobile": "手机号",
"email": "电子邮箱",
"userEntityGrant": "用户自领"
},
"not-implemented": "尚未实现"
}

View File

@ -77,9 +77,7 @@ export default OakComponent({
relations: [] as EntityDict['relation']['OpSchema'][],
mobile: '',
setPasswordConfirm: (value: boolean) => { },
passwordRequire: false,
allowUpdateName: false,
allowUpdateNickname: false,
passwordRequired: false,
isNew: false,
},
});

View File

@ -23,9 +23,7 @@ export default function Render(
entityId: string;
isNew: boolean;
setPasswordConfirm: (value: boolean) => void;
passwordRequire: boolean;
allowUpdateName?: boolean;
allowUpdateNickname?: boolean;
passwordRequired: boolean;
},
{
onMobileChange: (value: string) => Promise<void>;
@ -44,9 +42,7 @@ export default function Render(
entity,
entityId,
setPasswordConfirm,
passwordRequire,
allowUpdateName,
allowUpdateNickname,
passwordRequired,
} = props.data;
const { t, update } = props.methods;
const [form] = Form.useForm();
@ -93,10 +89,10 @@ export default function Render(
>
<>
<Input
disabled={!isNew && !allowUpdateName}
disabled={!isNew}
onChange={(e) => {
const strValue = e.target.value;
if (isNew || allowUpdateName) {
if (isNew) {
update({
name: strValue,
});
@ -110,11 +106,11 @@ export default function Render(
<Form.Item label={t('user:attr.nickname')} name="nickname">
<>
<Input
disabled={!isNew && !allowUpdateNickname}
disabled={!isNew}
value={nickname}
onChange={(e) => {
const strValue = e.target.value;
if (isNew || allowUpdateNickname) {
if (isNew) {
update({
nickname: strValue,
});
@ -132,7 +128,7 @@ export default function Render(
help={validateHelp1}
rules={[
{
required: passwordRequire,
required: passwordRequired,
message: '请输入密码',
validator: (_, value) => {
if (!value && !password2) {
@ -199,7 +195,7 @@ export default function Render(
name="confirmPassword"
rules={[
{
required: passwordRequire,
required: passwordRequired,
validator: (_, value) => {
if (!value && !password) {
setValidateHelp('');

View File

@ -3,7 +3,6 @@ import { Tabs } from 'antd';
import Style from './web.module.less';
import ByMobile from './byMobile/index';
import ByUserEntityGrant from './byUserEntityGrant';
import { assert } from 'oak-domain/lib/utils/assert';
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
import { QrCodeType } from '../../../types/Config';
@ -14,10 +13,6 @@ export default function Render(
'relation',
true,
{
grantByUserEntityGrant: boolean;
grantByEmail: boolean;
grantByMobile: boolean;
grantMethodCount: number;
redirectToAfterConfirm: EntityDict['userEntityGrant']['Schema']['redirectTo'];
claimUrl: string;
entity: keyof EntityDict;
@ -25,10 +20,8 @@ export default function Render(
relations: EntityDict['relation']['OpSchema'][];
qrCodeType?: QrCodeType;
rule: EntityDict['userEntityGrant']['OpSchema']['rule'];
ruleOnRow: EntityDict['userEntityGrant']['OpSchema']['ruleOnRow'];
passwordRequire: boolean;
allowUpdateName?: boolean;
allowUpdateNickname?: boolean;
passwordRequired: boolean;
enabled: Array<'email' | 'mobile' | 'userEntityGrant'>;
},
{}
>
@ -37,111 +30,71 @@ export default function Render(
entity,
entityId,
relations,
grantByUserEntityGrant,
grantByEmail,
grantByMobile,
grantMethodCount,
oakFullpath,
enabled,
redirectToAfterConfirm,
qrCodeType,
claimUrl,
rule,
ruleOnRow,
passwordRequire,
allowUpdateName,
allowUpdateNickname,
passwordRequired,
} = props.data;
let SubPart: JSX.Element = <></>;
if (grantMethodCount === 0) {
SubPart = (
const { t } = props.methods;
if (enabled.length === 0) {
return (
<div className={Style.container}>
{t('noMethods')}
</div>
);
} else if (grantMethodCount === 1) {
if (grantByEmail) {
SubPart = <div className={Style.container}></div>;
} else if (grantByMobile) {
SubPart = (
<ByMobile
allowUpdateName={allowUpdateName}
allowUpdateNickname={allowUpdateNickname}
passwordRequire={passwordRequire}
entity={entity}
entityId={entityId}
relations={relations}
oakPath="$userRelation-upsert-by-mobile"
oakAutoUnmount={true}
/>
);
} else {
assert(grantByUserEntityGrant === true);
SubPart = (
<ByUserEntityGrant
qrCodeType={qrCodeType}
entity={entity}
entityId={entityId}
relations={relations}
claimUrl={claimUrl}
oakPath="$userRelation-upsert-by-userEntityGrant"
oakAutoUnmount={true}
redirectToAfterConfirm={redirectToAfterConfirm}
/>
);
}
} else {
const items = [
{
label: 'Email',
key: 'item-1',
children: <div className={Style.container}></div>,
},
{
label: '二维码',
key: 'item-2',
children: (
<ByUserEntityGrant
entity={entity}
entityId={entityId}
relations={relations}
qrCodeType={qrCodeType}
oakPath="$userRelation-upsert-by-userEntityGrant"
oakAutoUnmount={true}
redirectToAfterConfirm={redirectToAfterConfirm}
claimUrl={claimUrl}
rule={rule}
ruleOnRow={ruleOnRow}
/>
),
},
{
label: '手机号',
key: 'item-3',
children: (
<ByMobile
allowUpdateName={allowUpdateName}
allowUpdateNickname={allowUpdateNickname}
passwordRequire={passwordRequire}
entity={entity}
entityId={entityId}
relations={relations}
oakPath="$userRelation-upsert-by-mobile"
oakAutoUnmount={true}
/>
),
},
];
const items2: typeof items = [];
if (grantByEmail) {
items2.push(items[0]);
}
if (grantByUserEntityGrant) {
items2.push(items[1]);
}
if (grantByMobile) {
items2.push(items[2]);
}
SubPart = <Tabs items={items2} />;
}
return SubPart;
const SubParts = enabled.map(
(ele) => {
switch (ele) {
case 'email': {
return <div className={Style.container}>{t('not-implemented')}</div>;
}
case 'mobile': {
return (
<ByMobile
passwordRequired={passwordRequired}
entity={entity}
entityId={entityId}
relations={relations}
oakPath="$userRelation-upsert-by-mobile"
oakAutoUnmount={true}
/>
);
}
case 'userEntityGrant': {
return (
<ByUserEntityGrant
qrCodeType={qrCodeType}
entity={entity}
entityId={entityId}
relations={relations}
claimUrl={claimUrl}
rule={rule}
oakPath="$userRelation-upsert-by-userEntityGrant"
oakAutoUnmount={true}
redirectToAfterConfirm={redirectToAfterConfirm}
/>
);
}
}
}
);
if (SubParts.length === 1) {
return SubParts[0];
}
return (
<Tabs items={
enabled.map(
(ele, idx) => ({
label: t(`methods.${ele}`),
key: `item-${idx}`,
children: SubParts[idx]
}))
} />
);
}

View File

@ -3,7 +3,6 @@ import { Tabs } from 'antd-mobile';
import Style from './mobile.module.less';
import ByMobile from './byMobile/index';
import ByUserEntityGrant from './byUserEntityGrant';
import { assert } from 'oak-domain/lib/utils/assert';
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
import { QrCodeType } from '../../../types/Config';
@ -14,10 +13,6 @@ export default function Render(
'user',
false,
{
grantByUserEntityGrant: boolean;
grantByEmail: boolean;
grantByMobile: boolean;
grantMethodCount: number;
redirectToAfterConfirm: EntityDict['userEntityGrant']['Schema']['redirectTo'];
claimUrl: string;
entity: keyof EntityDict;
@ -25,10 +20,8 @@ export default function Render(
relations: EntityDict['relation']['OpSchema'][];
qrCodeType?: QrCodeType;
rule: EntityDict['userEntityGrant']['OpSchema']['rule'];
ruleOnRow: EntityDict['userEntityGrant']['OpSchema']['ruleOnRow'];
passwordRequire: boolean;
allowUpdateName?: boolean;
allowUpdateNickname?: boolean;
passwordRequired: boolean;
enabled: Array<'email' | 'mobile' | 'userEntityGrant'>;
},
{}
>
@ -37,119 +30,70 @@ export default function Render(
entity,
entityId,
relations,
grantByUserEntityGrant,
grantByEmail,
grantByMobile,
grantMethodCount,
oakFullpath,
redirectToAfterConfirm,
qrCodeType,
claimUrl,
rule,
ruleOnRow,
passwordRequire,
allowUpdateName,
allowUpdateNickname,
passwordRequired,
enabled,
} = props.data;
let SubPart: JSX.Element = <></>;
if (grantMethodCount === 0) {
SubPart = (
const { t } = props.methods;
if (enabled.length === 0) {
return (
<div className={Style.container}>
{t('noMethods')}
</div>
);
} else if (grantMethodCount === 1) {
if (grantByEmail) {
SubPart = <div className={Style.container}></div>;
} else if (grantByMobile) {
SubPart = (
<ByMobile
allowUpdateName={allowUpdateName}
allowUpdateNickname={allowUpdateNickname}
passwordRequire={passwordRequire}
entity={entity}
entityId={entityId}
relations={relations}
oakPath="$userRelation-upsert-by-mobile"
oakAutoUnmount={true}
/>
);
} else {
assert(grantByUserEntityGrant === true);
SubPart = (
<ByUserEntityGrant
qrCodeType={qrCodeType}
entity={entity}
entityId={entityId}
relations={relations}
oakPath="$userRelation-upsert-by-userEntityGrant"
oakAutoUnmount={true}
redirectToAfterConfirm={redirectToAfterConfirm}
claimUrl={claimUrl}
/>
);
}
} else {
const items = [
{
label: 'Email',
key: 'item-1',
children: <div className={Style.container}></div>,
},
{
label: '二维码',
key: 'item-2',
children: (
<ByUserEntityGrant
entity={entity}
entityId={entityId}
relations={relations}
qrCodeType={qrCodeType}
oakPath="$userRelation-upsert-by-userEntityGrant"
oakAutoUnmount={true}
redirectToAfterConfirm={redirectToAfterConfirm}
claimUrl={claimUrl}
rule={rule}
ruleOnRow={ruleOnRow}
/>
),
},
{
label: '手机号',
key: 'item-3',
children: (
<ByMobile
allowUpdateName={allowUpdateName}
allowUpdateNickname={allowUpdateNickname}
passwordRequire={passwordRequire}
entity={entity}
entityId={entityId}
relations={relations}
oakPath="$userRelation-upsert-by-mobile"
oakAutoUnmount={true}
/>
),
},
];
const items2: typeof items = [];
if (grantByEmail) {
items2.push(items[0]);
}
if (grantByUserEntityGrant) {
items2.push(items[1]);
}
if (grantByMobile) {
items2.push(items[2]);
}
SubPart = (
<Tabs className={Style.tab}>
{items2.map((ele) => (
<Tabs.Tab title={ele.label} key={ele.key}>
{ele.children}
</Tabs.Tab>
))}
</Tabs>
);
}
return SubPart;
const SubParts = enabled.map(
(ele) => {
switch (ele) {
case 'email': {
return <div className={Style.container}>{t('not-implemented')}</div>;
}
case 'mobile': {
return (
<ByMobile
passwordRequired={passwordRequired}
entity={entity}
entityId={entityId}
relations={relations}
oakPath="$userRelation-upsert-by-mobile"
oakAutoUnmount={true}
/>
);
}
case 'userEntityGrant': {
return (
<ByUserEntityGrant
qrCodeType={qrCodeType}
entity={entity}
entityId={entityId}
relations={relations}
claimUrl={claimUrl}
rule={rule}
oakPath="$userRelation-upsert-by-userEntityGrant"
oakAutoUnmount={true}
redirectToAfterConfirm={redirectToAfterConfirm}
/>
);
}
}
}
);
if (SubParts.length === 1) {
return SubParts[0];
}
return (
<Tabs className={Style.tab}>
{enabled.map((ele, idx) => (
<Tabs.Tab title={t(`methods.${ele}`)} key={`item-${idx}`}>
{SubParts[idx]}
</Tabs.Tab>
))}
</Tabs>
);
}

View File

@ -634,6 +634,22 @@ const i18ns: I18n[] = [
}
}
},
{
id: "5ce54ef75387e766a33bd2b74709d32a",
namespace: "oak-general-business-c-userRelation-upsert",
language: "zh-CN",
module: "oak-general-business",
position: "src/components/userRelation/upsert",
data: {
"noMethods": "没有有效的授权途径(手机号、邮箱、用户自领),请检查配置",
"methods": {
"mobile": "手机号",
"email": "电子邮箱",
"userEntityGrant": "用户自领"
},
"not-implemented": "尚未实现"
}
},
{
id: "724a46f659f9bfa42239b79e59761f0e",
namespace: "oak-general-business-c-userRelation-upsert-onUser",

View File

@ -7,7 +7,6 @@ import { Schema as Domain } from './Domain';
import { Style } from '../types/Style';
import { EntityDesc } from 'oak-domain/lib/types/EntityDesc';
export type Passport = 'email' | 'mobile' | 'wechat' | 'wechatPublic' | 'wechatNative';
export type AppType = 'web' | 'wechatMp' | 'wechatPublic' | 'native';
export type WechatMpConfig = {
type: 'wechatMp';
@ -22,7 +21,6 @@ export type WechatMpConfig = {
mode: 'clear' | 'compatible' | 'safe'; //消息加解密方式 明文模式 兼容模式 安全模式
dataFormat: 'json' | 'xml';
};
passport?: Passport[];
};
export type WebConfig = {
@ -37,7 +35,6 @@ export type WebConfig = {
appId: string;
appSecret: string; //微信支付
};
passport?: Passport[];
location: {
protocol: 'http:' | 'https:';
hostname: string;
@ -63,7 +60,6 @@ export type WechatPublicConfig = {
appId: string;
originalId: string; //原始id
};
passport?: Passport[];
location: {
protocol: 'http:' | 'https:';
hostname: string;
@ -73,7 +69,6 @@ export type WechatPublicConfig = {
export type NativeConfig = {
type: 'native';
passport?: Passport[];
wechatNative?: {
appId: string;
appSecret: string; //微信App授权登录

View File

@ -192,6 +192,8 @@ const triggers: Trigger<
id: 1,
name: 1,
parentId: 1,
entity: 1,
entityId :1,
},
filter,
},
@ -207,6 +209,8 @@ const triggers: Trigger<
parentId: 1,
},
filter: {
entity: articleMenu.entity!,
entityId: articleMenu.entityId!,
name: (data as any).name,
parentId: articleMenu.parentId
? articleMenu.parentId