Merge branch 'dev' of codeup.aliyun.com:61c14a7efa282c88e103c23f/oak-general-business into dev

This commit is contained in:
wenjiarui 2024-01-05 17:14:28 +08:00
commit 8d13b1b119
42 changed files with 1409 additions and 378 deletions

View File

@ -21,39 +21,32 @@ export async function getApplication(params, context) {
}, {});
//微信小程序环境下 没有就报错
if (type === 'wechatMp') {
assert(
application,
'微信小程序环境下 application必须存在小程序相关配置'
);
} else if (type === 'native') {
assert(application, '微信小程序环境下 application必须存在小程序相关配置');
}
else if (type === 'native') {
assert(application, 'APP环境下 application必须存在APP相关配置');
} else {
}
else {
//web 或 wechatPublic
if (type === 'wechatPublic') {
// 如果微信公众号环境下 application不存在公众号配置但又在公众号访问这时可以使用web的application
if (!application) {
const [application2] = await context.select(
'application',
{
data: cloneDeep(applicationProjection),
filter: {
type: 'web',
system: {
domain$system: {
url: domain,
},
const [application2] = await context.select('application', {
data: cloneDeep(applicationProjection),
filter: {
type: 'web',
system: {
domain$system: {
url: domain,
},
},
},
{}
);
assert(
application2,
'微信公众号环境下 application不存在公众号配置但必须存在web相关配置'
);
}, {});
assert(application2, '微信公众号环境下 application不存在公众号配置但必须存在web相关配置');
return application2.id;
}
} else {
}
else {
assert(application, 'web环境下 application必须存在web相关配置');
}
}

View File

@ -1148,24 +1148,18 @@ export async function sendCaptcha({ mobile, env, type: type2, }, context) {
}, {
dontCollect: true,
});
if (process.env.NODE_ENV === 'development' || mockSend) {
closeRootMode();
return `验证码[${code}]已创建`;
} else {
}
else {
//发送短信
const result = await sendSms(
{
origin: 'tencent',
templateName: '登录',
mobile,
templateParam: {
code,
duration: duration.toString(),
},
},
context
);
const result = await sendSms({
origin: 'tencent',
templateName: '登录',
mobile,
templateParam: { code, duration: duration.toString() },
}, context);
closeRootMode();
if (result.success) {
return '验证码已发送';

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: "application" | "platform" | "system";
entity: "application" | "system" | "platform";
entityId: string;
name: string;
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;

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;
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;

View File

@ -14,17 +14,17 @@ declare const _default: <ED2 extends EntityDict & BaseEntityDict, T2 extends key
buttonProps?: (ButtonProps & {
color?: "success" | "default" | "warning" | "primary" | "danger" | undefined;
fill?: "none" | "solid" | "outline" | undefined;
size?: "small" | "middle" | "large" | "mini" | undefined;
size?: "small" | "large" | "middle" | "mini" | undefined;
block?: boolean | undefined;
loading?: boolean | "auto" | undefined;
loadingText?: string | undefined;
loadingIcon?: import("react").ReactNode;
disabled?: boolean | undefined;
onClick?: ((event: import("react").MouseEvent<HTMLButtonElement, MouseEvent>) => unknown) | undefined;
type?: "button" | "reset" | "submit" | undefined;
type?: "button" | "submit" | "reset" | undefined;
shape?: "default" | "rounded" | "rectangular" | undefined;
children?: import("react").ReactNode;
} & Pick<import("react").ClassAttributes<HTMLButtonElement> & import("react").ButtonHTMLAttributes<HTMLButtonElement>, "id" | "onMouseDown" | "onMouseUp" | "onTouchStart" | "onTouchEnd"> & {
} & Pick<import("react").ClassAttributes<HTMLButtonElement> & import("react").ButtonHTMLAttributes<HTMLButtonElement>, "id" | "onMouseDown" | "onMouseUp" | "onTouchEnd" | "onTouchStart"> & {
className?: string | undefined;
style?: (import("react").CSSProperties & Partial<Record<"--text-color" | "--background-color" | "--border-radius" | "--border-width" | "--border-style" | "--border-color", string>>) | undefined;
tabIndex?: number | undefined;

View File

@ -26,6 +26,7 @@ export default OakComponent({
}
return {
id: 1,
$$createAt$$: 1,
name: 1,
nickname: 1,
mobile$user: {
@ -91,6 +92,18 @@ export default OakComponent({
},
};
},
sorters: [
{
sorter() {
return {
$attr: {
$$createAt$$: 1,
},
$direction: 'desc'
};
},
}
],
filters: [
{
filter() {

View File

@ -5,5 +5,6 @@ declare const _default: <ED2 extends EntityDict & BaseEntityDict, T2 extends key
entity: keyof ED2;
entityId: string;
relations: EntityDict['relation']['OpSchema'][];
passwordRequire: boolean;
}>) => React.ReactElement;
export default _default;

View File

@ -10,7 +10,8 @@ export default OakComponent({
isList: false,
formData({ data: mobile }) {
const { oakFullpath } = this.state;
const userRelations = oakFullpath && this.features.runningTree.getOperations(`${oakFullpath}.user.userRelation$user`);
const userRelations = oakFullpath &&
this.features.runningTree.getOperations(`${oakFullpath}.user.userRelation$user`);
return {
userId: mobile?.userId,
legal: userRelations && userRelations.length > 0,
@ -20,6 +21,7 @@ export default OakComponent({
entity: '',
entityId: '',
relations: [],
passwordRequire: false,
},
data: {
mobileValue: '',
@ -40,7 +42,7 @@ export default OakComponent({
filter: {
mobile: value,
ableState: 'enabled',
}
},
});
if (data.length > 0) {
this.clean();
@ -102,6 +104,6 @@ export default OakComponent({
},
searchCancelMp() {
this.onReset();
}
},
},
});

View File

@ -8,6 +8,7 @@ export default function Render(props: WebComponentProps<EntityDict, 'mobile', fa
mobileValue: string;
mobileValueReady: boolean;
userId: string;
passwordRequire: boolean;
}, {
onMobileChange: (value: string) => Promise<void>;
onConfirm: () => Promise<void>;

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 } = props.data;
const { mobileValue, mobileValueReady, relations, entity, entityId, userId, oakFullpath, oakExecutable, oakDirty, passwordRequire, } = props.data;
const { onConfirm, onMobileChange, onReset, t } = props.methods;
return (<Form footer={<div className={Style.btnContainer}>
<Button color="primary" style={{ flex: 2 }} onClick={() => {

View File

@ -10,6 +10,7 @@ export default function Render(props: WebComponentProps<EntityDict, 'mobile', fa
userId: string;
legal: boolean;
isNew: boolean;
passwordRequire: boolean;
}, {
onMobileChange: (value: string) => Promise<void>;
onConfirm: () => 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 } = props.data;
const { mobileValue, mobileValueReady, relations, entity, entityId, userId, oakFullpath, oakExecutable, legal, isNew, passwordRequire, } = props.data;
const { onConfirm, onMobileChange, onReset, t } = props.methods;
const [passwordConfirm, setPasswordConfirm] = useState(true);
return (<div className={Style.container}>

View File

@ -7,5 +7,6 @@ declare const _default: <ED2 extends EntityDict & BaseEntityDict, T2 extends key
redirectToAfterConfirm: ED2["userEntityGrant"]["Schema"]["redirectTo"];
claimUrl: string;
qrCodeType: string;
passwordRequire: boolean;
}>) => React.ReactElement;
export default _default;

View File

@ -60,6 +60,7 @@ export default OakComponent({
qrCodeType: '',
rule: 'single',
ruleOnRow: 'single',
passwordRequire: false,
},
lifetimes: {
ready() {

View File

@ -6,5 +6,6 @@ declare const _default: (props: import("oak-frontend-base").ReactComponentProps<
mobile: string;
isComponent: boolean;
setPasswordConfirm: (value: boolean) => void;
passwordRequire: boolean;
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
export default _default;

View File

@ -72,6 +72,7 @@ export default OakComponent({
relations: [],
mobile: '',
isComponent: false,
setPasswordConfirm: (value) => { }
setPasswordConfirm: (value) => { },
passwordRequire: false,
},
});

View File

@ -12,6 +12,7 @@ export default function Render(props: WebComponentProps<EntityDict, 'user', fals
entity: keyof EntityDict;
entityId: string;
isNew: boolean;
passwordRequire: boolean;
}, {
onMobileChange: (value: string) => Promise<void>;
onConfirm: () => Promise<void>;

View File

@ -2,7 +2,7 @@ import React from 'react';
import { Form, Input } from 'antd-mobile';
import UserRelation from './userRelation';
export default function Render(props) {
const { name, isNew, nickname, password, relations, oakFullpath, entity, entityId } = props.data;
const { name, isNew, nickname, password, relations, oakFullpath, entity, entityId, passwordRequire, } = props.data;
const { t, update } = props.methods;
return (<>
<Form.Item style={{ marginBottom: 0 }} label={!isNew ? t('existedUser') : t('newUser')}/>
@ -29,7 +29,7 @@ export default function Render(props) {
</>
</Form.Item>) : (<Form.Item label={t('user:attr.password')} name="password" rules={[
{
required: true,
required: passwordRequire,
},
]}>
<>

View File

@ -14,4 +14,5 @@ export default function Render(props: WebComponentProps<EntityDict, 'user', fals
qrCodeType?: QrCodeType;
rule: EntityDict['userEntityGrant']['OpSchema']['rule'];
ruleOnRow: EntityDict['userEntityGrant']['OpSchema']['ruleOnRow'];
passwordRequire: boolean;
}, {}>): JSX.Element;

View File

@ -5,7 +5,7 @@ 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, } = props.data;
const { entity, entityId, relations, grantByUserEntityGrant, grantByEmail, grantByMobile, grantMethodCount, oakFullpath, redirectToAfterConfirm, qrCodeType, claimUrl, rule, ruleOnRow, passwordRequire, } = props.data;
let SubPart = <></>;
if (grantMethodCount === 0) {
SubPart = (<div className={Style.container}>
@ -17,7 +17,7 @@ export default function Render(props) {
SubPart = <div className={Style.container}>尚未实现</div>;
}
else if (grantByMobile) {
SubPart = (<ByMobile entity={entity} entityId={entityId} relations={relations} oakPath="$userRelation-upsert-by-mobile" oakAutoUnmount={true}/>);
SubPart = (<ByMobile passwordRequire={passwordRequire} entity={entity} entityId={entityId} relations={relations} oakPath="$userRelation-upsert-by-mobile" oakAutoUnmount={true}/>);
}
else {
assert(grantByUserEntityGrant === true);
@ -53,9 +53,9 @@ export default function Render(props) {
items2.push(items[2]);
}
SubPart = (<Tabs className={Style.tab}>
{items2.map(ele => (<Tabs.Tab title={ele.label} key={ele.key}>
{ele.children}
</Tabs.Tab>))}
{items2.map((ele) => (<Tabs.Tab title={ele.label} key={ele.key}>
{ele.children}
</Tabs.Tab>))}
</Tabs>);
}
return SubPart;

View File

@ -14,4 +14,5 @@ export default function Render(props: WebComponentProps<EntityDict, 'relation',
qrCodeType?: QrCodeType;
rule: EntityDict['userEntityGrant']['OpSchema']['rule'];
ruleOnRow: EntityDict['userEntityGrant']['OpSchema']['ruleOnRow'];
passwordRequire: boolean;
}, {}>): JSX.Element;

View File

@ -5,7 +5,7 @@ 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, } = props.data;
const { entity, entityId, relations, grantByUserEntityGrant, grantByEmail, grantByMobile, grantMethodCount, oakFullpath, redirectToAfterConfirm, qrCodeType, claimUrl, rule, ruleOnRow, passwordRequire, } = props.data;
let SubPart = <></>;
if (grantMethodCount === 0) {
SubPart = (<div className={Style.container}>
@ -17,7 +17,7 @@ export default function Render(props) {
SubPart = <div className={Style.container}>尚未实现</div>;
}
else if (grantByMobile) {
SubPart = (<ByMobile entity={entity} entityId={entityId} relations={relations} oakPath="$userRelation-upsert-by-mobile" oakAutoUnmount={true}/>);
SubPart = (<ByMobile passwordRequire={passwordRequire} entity={entity} entityId={entityId} relations={relations} oakPath="$userRelation-upsert-by-mobile" oakAutoUnmount={true}/>);
}
else {
assert(grantByUserEntityGrant === true);

View File

@ -20,7 +20,7 @@ export interface Schema extends EntityShape {
codes: Array<WechatQrCode>;
isRoot?: Boolean;
addresses?: Address[];
accounts: Account[];
accounts?: Account[];
}
type IdAction = 'verify' | 'accept' | 'reject';
type IdState = 'unverified' | 'verified' | 'verifying';

View File

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

View File

@ -88,6 +88,7 @@ export async function completeToDo(entity, filter, action, context) {
targetEntity: entity,
targetFilter: filter,
action,
iState: 'active',
}
}, {});
assert(toDos.length > 0, `${entity}相关的todo进行完成操作时找不到对应的数据。filter是${JSON.stringify(filter)}`);

View File

@ -25,48 +25,33 @@ async function getApplication(params, context) {
}, {});
//微信小程序环境下 没有就报错
if (type === 'wechatMp') {
(0, assert_1.assert)(
application,
'微信小程序环境下 application必须存在小程序相关配置'
);
} else if (type === 'native') {
(0, assert_1.assert)(
application,
'APP环境下 application必须存在APP相关配置'
);
} else {
(0, assert_1.assert)(application, '微信小程序环境下 application必须存在小程序相关配置');
}
else if (type === 'native') {
(0, assert_1.assert)(application, 'APP环境下 application必须存在APP相关配置');
}
else {
//web 或 wechatPublic
if (type === 'wechatPublic') {
// 如果微信公众号环境下 application不存在公众号配置但又在公众号访问这时可以使用web的application
if (!application) {
const [application2] = await context.select(
'application',
{
data: (0, lodash_1.cloneDeep)(
Projection_1.applicationProjection
),
filter: {
type: 'web',
system: {
domain$system: {
url: domain,
},
const [application2] = await context.select('application', {
data: (0, lodash_1.cloneDeep)(Projection_1.applicationProjection),
filter: {
type: 'web',
system: {
domain$system: {
url: domain,
},
},
},
{}
);
(0, assert_1.assert)(
application2,
'微信公众号环境下 application不存在公众号配置但必须存在web相关配置'
);
}, {});
(0, assert_1.assert)(application2, '微信公众号环境下 application不存在公众号配置但必须存在web相关配置');
return application2.id;
}
} else {
(0, assert_1.assert)(
application,
'web环境下 application必须存在web相关配置'
);
}
else {
(0, assert_1.assert)(application, 'web环境下 application必须存在web相关配置');
}
}
return application.id;

View File

@ -1157,21 +1157,18 @@ async function sendCaptcha({ mobile, env, type: type2, }, context) {
}, {
dontCollect: true,
});
if (process.env.NODE_ENV === 'development' || mockSend) {
closeRootMode();
return `验证码[${code}]已创建`;
} else {
}
else {
//发送短信
const result = await (0, sms_1.sendSms)(
{
origin: 'tencent',
templateName: '登录',
mobile,
templateParam: { code, duration: duration.toString() },
},
context
);
const result = await (0, sms_1.sendSms)({
origin: 'tencent',
templateName: '登录',
mobile,
templateParam: { code, duration: duration.toString() },
}, context);
closeRootMode();
if (result.success) {
return '验证码已发送';

View File

@ -20,7 +20,7 @@ export interface Schema extends EntityShape {
codes: Array<WechatQrCode>;
isRoot?: Boolean;
addresses?: Address[];
accounts: Account[];
accounts?: Account[];
}
type IdAction = 'verify' | 'accept' | 'reject';
type IdState = 'unverified' | 'verified' | 'verifying';

View File

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

View File

@ -94,6 +94,7 @@ async function completeToDo(entity, filter, action, context) {
targetFilter: filter,
iState: 'active',
action,
iState: 'active',
}
}, {});
(0, assert_1.default)(toDos.length > 0, `${entity}相关的todo进行完成操作时找不到对应的数据。filter是${JSON.stringify(filter)}`);

View File

@ -7,6 +7,7 @@ import {
Config,
QiniuCloudConfig,
TencentCloudConfig,
CTYunCloudConfig,
} from '../../../../types/Config';
@ -367,6 +368,138 @@ function QiniuAccount(props: {
);
}
function CTYunAccount(props: {
accounts: CTYunCloudConfig[];
setValue: (path: string, value: any) => void;
removeItem: (path: string, index: number) => void;
addItem: (path: string, index: number) => void;
}) {
const { accounts, setValue, removeItem, addItem } = props;
return (
<Col flex="auto">
<Divider orientation="left" className={Styles.title}>
</Divider>
<Tabs
tabPosition={'top'}
size={'middle'}
type="editable-card"
hideAdd={!(accounts.length > 0)}
onEdit={(targetKey: any, action: 'add' | 'remove') => {
if (action === 'add') {
addItem('', accounts.length);
} else {
removeItem('', parseInt(targetKey, 10));
}
}}
items={
accounts.length > 0
? accounts.map((ele, idx) => ({
key: `${idx}`,
label: `帐号${idx + 1}`,
children: (
<Form
colon={false}
labelAlign="left"
layout="vertical"
style={{ marginTop: 10 }}
>
<Form.Item
label="accessKey"
// name="accessKey"
>
<>
<Input
placeholder="请输入accessKey"
type="text"
value={ele.accessKey}
onChange={(e) =>
setValue(
`${idx}.accessKey`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="securityKey"
// name="securityKey"
>
<>
<Input
placeholder="请输入securityKey"
type="text"
value={ele.securityKey}
onChange={(e) =>
setValue(
`${idx}.securityKey`,
e.target.value
)
}
/>
</>
</Form.Item>
</Form>
),
}))
: [
{
label: '新建帐号',
key: '0',
children: (
<Form
colon={true}
labelAlign="left"
layout="vertical"
style={{ marginTop: 10 }}
>
<Form.Item
label="accessKey"
// name="accessKey"
>
<>
<Input
placeholder="请输入accessKey"
type="text"
value=""
onChange={(e) =>
setValue(
`0.accessKey`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="securityKey"
// name="securityKey"
>
<>
<Input
placeholder="请输入securityKey"
type="text"
value=""
onChange={(e) =>
setValue(
`0.securityKey`,
e.target.value
)
}
/>
</>
</Form.Item>
</Form>
),
},
]
}
></Tabs>
</Col>
);
}
function AliAccount(props: {
accounts: AliCloudConfig[];
setValue: (path: string, value: any) => void;
@ -749,7 +882,7 @@ export default function Account(props: {
removeItem: (path: string, index: number) => void;
}) {
const { account, setValue, removeItem } = props;
const { tencent, qiniu, ali, amap } = account;
const { tencent, qiniu, ali, amap, ctyun } = account;
return (
<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
<Row>
@ -769,6 +902,12 @@ export default function Account(props: {
removeItem={(path, index) => removeItem(`qiniu`, index)}
addItem={(path, index) => setValue(`qiniu.${index}`, {})}
/>
<CTYunAccount
accounts={ctyun || []}
setValue={(path, value) => setValue(`ctyun.${path}`, value)}
removeItem={(path, index) => removeItem(`ctyun`, index)}
addItem={(path, index) => setValue(`ctyun.${index}`, {})}
/>
<AliAccount
accounts={ali || []}
setValue={(path, value) => setValue(`ali.${path}`, value)}

View File

@ -11,8 +11,8 @@ import {
Select,
} from 'antd';
import Styles from './web.module.less';
import { QiniuZone } from 'oak-external-sdk';
import { Config, QiniuCosConfig } from '../../../../types/Config';
import { QiniuZone, CTYunZone } from 'oak-external-sdk';
import { Config, QiniuCosConfig, CTYunCosConfig } from '../../../../types/Config';
// https://developer.qiniu.com/kodo/1671/region-endpoint-fq
const QiniuZoneArray: Array<{ label: string; value: QiniuZone }> = [
@ -250,13 +250,328 @@ function QiniuCos(props: {
);
}
const CTYunZoneArray: Array<{ label: string; value: CTYunZone }> = [
{
label: '郑州',
value: 'hazz',
},
{
label: '沈阳',
value: 'lnsy',
},
{
label: '四川成都',
value: 'sccd',
},
{
label: '乌鲁木齐',
value: 'xjwlmq',
},
{
label: '甘肃兰州',
value: 'gslz',
},
{
label: '山东青岛',
value: 'sdqd',
},
{
label: '贵州贵阳',
value: 'gzgy',
},
{
label: '湖北武汉',
value: 'hbwh',
},
{
label: '西藏拉萨',
value: 'xzls',
},
{
label: '安徽芜湖',
value: 'ahwh',
},
{
label: '广东深圳',
value: 'gdsz',
},
{
label: '江苏苏州',
value: 'jssz',
},
{
label: '上海2',
value: 'sh2',
},
];
function CTYunCos(props: {
cos: CTYunCosConfig;
setValue: (path: string, value: any) => void;
removeItem: (path: string, index: number) => void;
}) {
const { cos, setValue, removeItem } = props;
return (
<Col flex="auto">
<Divider orientation="left" className={Styles.title}>
</Divider>
<Tabs
tabPosition={'top'}
size={'middle'}
type="card"
items={[
{
key: '0',
label: '配置项',
children: (
<Form
colon={true}
labelAlign="left"
layout="vertical"
style={{ marginTop: 10 }}
>
<Form.Item
label="accessKey"
//name="accessKey"
>
<>
<Input
placeholder="请输入accessKey"
type="text"
value={cos?.accessKey}
onChange={(e) =>
setValue(
`accessKey`,
e.target.value
)
}
/>
</>
</Form.Item>
{/* <Form.Item
label="bucket"
//name="bucket"
>
<>
<Input
placeholder="请输入bucket"
type="text"
value={cos?.bucket}
onChange={(e) =>
setValue(
`bucket`,
e.target.value
)
}
/>
</>
</Form.Item> */}
<Divider
orientation="left"
className={Styles.title}
>
bucket配置
</Divider>
<Tabs
tabPosition={'top'}
size={'middle'}
type="editable-card"
// hideAdd={!(sms.length > 0)}
onEdit={(
targetKey: any,
action: 'add' | 'remove'
) => {
if (action === 'add') {
setValue(
`buckets.${
cos?.buckets?.length || 0
}`,
{}
);
} else {
removeItem(
'buckets',
parseInt(targetKey, 10)
);
}
}}
items={
cos?.buckets?.length > 0
? cos.buckets.map((ele, idx) => ({
key: `${idx}`,
label: `bucket:${idx + 1}`,
children: (
<Form
colon={false}
labelAlign="left"
layout="vertical"
style={{
marginTop: 10,
}}
>
<Form.Item
label="name"
// name="name"
>
<>
<Input
placeholder="请输入name"
type="text"
value={
ele.name
}
onChange={(
e
) =>
setValue(
`buckets.${idx}.name`,
e
.target
.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="zone"
//name="uploadHost"
>
<>
<Select
style={{
width: '100%',
}}
placeholder="请选择存储区域"
value={
ele.zone
}
onChange={(
value: string
) => {
setValue(
`buckets.${idx}.zone`,
value
);
}}
options={
CTYunZoneArray
}
/>
</>
</Form.Item>
<Form.Item
label="domain"
// name="domain"
>
<>
<Input
placeholder="请输入domain"
type="text"
value={
ele.domain
}
onChange={(
e
) =>
setValue(
`buckets.${idx}.domain`,
e
.target
.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="protocol"
// name="protocol"
>
<>
<Select
mode="multiple"
allowClear
style={{
width: '100%',
}}
placeholder="请选择协议"
value={
ele?.protocol as string[]
}
onChange={(
value: string[]
) => {
setValue(
`buckets.${idx}.protocol`,
value
);
}}
options={[
{
label: 'http',
value: 'http',
},
{
label: 'https',
value: 'https',
},
]}
/>
</>
</Form.Item>
</Form>
),
}))
: []
}
/>
{cos?.buckets?.length > 0 && (
<Form.Item
label="defaultBucket"
//name="uploadHost"
>
<>
<Select
allowClear
style={{ width: '100%' }}
placeholder="请选择默认bucket"
value={cos.defaultBucket}
onChange={(value: string) => {
setValue(
`defaultBucket`,
value
);
}}
options={cos.buckets.map(
(ele) => ({
label: ele.name,
value: ele.name,
})
)}
/>
</>
</Form.Item>
)}
</Form>
),
},
]}
></Tabs>
</Col>
);
}
export default function Cos(props: {
cos: Required<Config>['Cos'];
setValue: (path: string, value: any) => void;
removeItem: (path: string, index: number) => void;
}) {
const { cos, setValue, removeItem } = props;
const { qiniu } = cos;
const { qiniu, ctyun } = cos;
return (
<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
<Row>
@ -269,6 +584,11 @@ export default function Cos(props: {
setValue={(path, value) => setValue(`qiniu.${path}`, value)}
removeItem={(path, index) => removeItem(`qiniu.${path}`, index)}
/>
<CTYunCos
cos={ctyun!}
setValue={(path, value) => setValue(`ctyun.${path}`, value)}
removeItem={(path, index) => removeItem(`ctyun.${path}`, index)}
/>
</Space>
);
}

View File

@ -15,7 +15,7 @@ import {
} from 'antd';
import { get } from 'oak-domain/lib/utils/lodash';
import Styles from './web.module.less';
import { Config, AliSmsConfig, TencentSmsConfig } from '../../../../types/Config';
import { Config, AliSmsConfig, TencentSmsConfig, CTYunSmsConfig } from '../../../../types/Config';
function Ali(props: {
@ -50,52 +50,106 @@ function Ali(props: {
items={
sms.length > 0
? sms.map((ele, idx) => ({
key: `${idx}`,
label: `短信${idx + 1}`,
children: (
<Form
colon={false}
labelAlign="left"
layout="vertical"
style={{ marginTop: 10 }}
>
<Form.Item
label="accessKeyId"
name="accessKeyId"
>
<>
<Input
placeholder="请输入accessKeyId"
type="text"
value={ele.accessKeyId}
onChange={(e) =>
setValue(
`${idx}.accessKeyId`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="defaultSignName"
name="defaultSignName"
>
<>
<Input
placeholder="请输入defaultSignName"
type="text"
value={ele.defaultSignName}
onChange={(e) =>
setValue(
`${idx}.defaultSignName`,
e.target.value
)
}
/>
</>
</Form.Item>
{/* <Form.Item
key: `${idx}`,
label: `短信${idx + 1}`,
children: (
<Form
colon={false}
labelAlign="left"
layout="vertical"
style={{ marginTop: 10 }}
>
<Form.Item
label="accessKeyId"
name="accessKeyId"
>
<>
<Input
placeholder="请输入accessKeyId"
type="text"
value={ele.accessKeyId}
onChange={(e) =>
setValue(
`${idx}.accessKeyId`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="accessKeySecret"
name="accessKeySecret"
>
<>
<Input
placeholder="请输入accessKeySecret"
type="text"
value={ele.accessKeySecret}
onChange={(e) =>
setValue(
`${idx}.accessKeySecret`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="endpoint"
name="endpoint"
>
<>
<Input
placeholder="请输入endpoint"
type="text"
value={ele.endpoint}
onChange={(e) =>
setValue(
`${idx}.endpoint`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="apiVersion"
name="apiVersion"
>
<>
<Input
placeholder="请输入apiVersion"
type="text"
value={ele.apiVersion}
onChange={(e) =>
setValue(
`${idx}.defaultSignName`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="defaultSignName"
name="defaultSignName"
>
<>
<Input
placeholder="请输入defaultSignName"
type="text"
value={ele.defaultSignName}
onChange={(e) =>
setValue(
`${idx}.defaultSignName`,
e.target.value
)
}
/>
</>
</Form.Item>
{/* <Form.Item
label="templates"
name="templates"
>
@ -199,9 +253,9 @@ function Ali(props: {
}
></Tabs>
</Form.Item> */}
</Form>
),
}))
</Form>
),
}))
: []
}
></Tabs>
@ -297,176 +351,513 @@ function Tencent(props: {
items={
sms.length > 0
? sms.map((ele, idx) => ({
key: `${idx}`,
label: `短信${idx + 1}`,
children: (
<Form
colon={false}
labelAlign="left"
layout="vertical"
style={{ marginTop: 10 }}
>
<Form.Item
label="secretId"
//name="secretId"
>
<>
<Input
placeholder="请输入secretId"
type="text"
value={ele.secretId}
onChange={(e) =>
setValue(
`${idx}.secretId`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="smsSdkAppId"
//name="smsSdkAppId"
>
<>
<Input
placeholder="请输入smsSdkAppId"
type="text"
value={ele.smsSdkAppId}
onChange={(e) =>
setValue(
`${idx}.smsSdkAppId`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="defaultSignName"
//name="defaultSignName"
>
<>
<Input
placeholder="请输入defaultSignName"
type="text"
value={ele.defaultSignName}
onChange={(e) =>
setValue(
`${idx}.defaultSignName`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="templates"
//name="templates"
>
<Tabs
tabPosition={'top'}
size={'middle'}
type="editable-card"
// hideAdd={!(Object.keys(ele.templates).length > 0)}
onEdit={(
targetKey: any,
action: 'add' | 'remove'
) => {
if (action === 'add') {
setSmsIndex(`${idx}`);
setModal(true);
} else {
cleanKey(
`${idx}.templates`,
targetKey
);
}
}}
items={
Object.keys(
ele.templates || {}
).length > 0
? Object.keys(
ele.templates
).map((name, idx) => {
const template =
ele.templates[
name
];
return {
key: `${name}`,
label: `${name}`,
children: (
<Form
colon={
true
}
labelAlign="left"
layout="vertical"
style={{
marginTop: 10,
}}
>
<Form.Item
label="signName"
//name="signName"
key: `${idx}`,
label: `短信${idx + 1}`,
children: (
<Form
colon={false}
labelAlign="left"
layout="vertical"
style={{ marginTop: 10 }}
>
<Form.Item
label="secretId"
//name="secretId"
>
<>
<Input
placeholder="请输入secretId"
type="text"
value={ele.secretId}
onChange={(e) =>
setValue(
`${idx}.secretId`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="secretKey"
//name="secretId"
>
<>
<Input
placeholder="请输入secretKey"
type="text"
value={ele.secretKey}
onChange={(e) =>
setValue(
`${idx}.secretKey`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="smsSdkAppId"
//name="smsSdkAppId"
>
<>
<Input
placeholder="请输入smsSdkAppId"
type="text"
value={ele.smsSdkAppId}
onChange={(e) =>
setValue(
`${idx}.smsSdkAppId`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="region"
//name="region"
>
<>
<Input
placeholder="请输入region"
type="text"
value={ele.region}
onChange={(e) =>
setValue(
`${idx}.region`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="endpoint"
//name="endpoint"
>
<>
<Input
placeholder="请输入endpoint"
type="text"
value={ele.endpoint}
onChange={(e) =>
setValue(
`${idx}.endpoint`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="defaultSignName"
//name="defaultSignName"
>
<>
<Input
placeholder="请输入defaultSignName"
type="text"
value={ele.defaultSignName}
onChange={(e) =>
setValue(
`${idx}.defaultSignName`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="templates"
//name="templates"
>
<Tabs
tabPosition={'top'}
size={'middle'}
type="editable-card"
// hideAdd={!(Object.keys(ele.templates).length > 0)}
onEdit={(
targetKey: any,
action: 'add' | 'remove'
) => {
if (action === 'add') {
setSmsIndex(`${idx}`);
setModal(true);
} else {
cleanKey(
`${idx}.templates`,
targetKey
);
}
}}
items={
Object.keys(
ele.templates || {}
).length > 0
? Object.keys(
ele.templates
).map((name, idx) => {
const template =
ele.templates[
name
];
return {
key: `${name}`,
label: `${name}`,
children: (
<Form
colon={
true
}
labelAlign="left"
layout="vertical"
style={{
marginTop: 10,
}}
>
<>
<Input
placeholder="请输入signName"
type="text"
value={
template.signName
}
onChange={(
e
) =>
setValue(
`${idx}.templates.${name}.signName`,
<Form.Item
label="signName"
//name="signName"
>
<>
<Input
placeholder="请输入signName"
type="text"
value={
template.signName
}
onChange={(
e
.target
.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="code"
//name="code"
) =>
setValue(
`${idx}.templates.${name}.signName`,
e
.target
.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="code"
//name="code"
>
<>
<Input
placeholder="请输入code"
type="text"
value={
template.code
}
onChange={(
e
) =>
setValue(
`${idx}.templates.${name}.code`,
e
.target
.value
)
}
/>
</>
</Form.Item>
</Form>
),
};
})
: []
}
></Tabs>
</Form.Item>
</Form>
),
}))
: []
}
></Tabs>
<Modal
title="新建模版标签"
onCancel={() => {
setModal(false);
setLabelType('');
}}
onOk={() => {
if (!labelType) {
message.error({
content: '请输入标签名称',
});
return;
}
const templates = get(sms, `${smsIndex}.templates`) || {};
if (Object.keys(templates).includes(labelType)) {
message.error({
content: '已存在相同的标签名,请重新输入',
});
return;
}
setValue(`${smsIndex}.templates.${labelType}`, {});
setModal(false);
setLabelType('');
setSmsIndex('');
}}
open={open}
cancelText="取消"
okText="确定"
destroyOnClose={true}
>
<Form
colon={true}
labelAlign="left"
layout="vertical"
style={{ marginTop: 10 }}
>
<Form.Item
label="标签名称"
//name="messageType"
help="只能输入英文和中文"
>
<>
<Input
placeholder="请输入标签名称"
type="text"
value={labelType}
onChange={(e) =>
setLabelType(
e.target.value.replace(/[0-9-.]/g, '')
)
}
/>
</>
</Form.Item>
</Form>
</Modal>
</Col>
);
}
function CTYun(props: {
sms: CTYunSmsConfig[];
setValue: (path: string, value: any) => void;
removeItem: (path: string, index: number) => void;
addItem: (path: string, index: number) => void;
cleanKey: (path: string, key: string) => void;
}) {
const [open, setModal] = useState(false);
const [smsIndex, setSmsIndex] = useState('');
const [labelType, setLabelType] = useState('');
const { sms, setValue, addItem, removeItem, cleanKey } = props;
return (
<Col flex="auto">
<Divider orientation="left" className={Styles.title}>
</Divider>
<Tabs
tabPosition={'top'}
size={'middle'}
type="editable-card"
// hideAdd={!(sms.length > 0)}
onEdit={(targetKey: any, action: 'add' | 'remove') => {
if (action === 'add') {
addItem('', sms.length);
} else {
removeItem('', parseInt(targetKey, 10));
}
}}
items={
sms.length > 0
? sms.map((ele, idx) => ({
key: `${idx}`,
label: `短信${idx + 1}`,
children: (
<Form
colon={false}
labelAlign="left"
layout="vertical"
style={{ marginTop: 10 }}
>
<Form.Item
label="accessKey"
name="accessKey"
>
<>
<Input
placeholder="请输入accessKey"
type="text"
value={ele.accessKey}
onChange={(e) =>
setValue(
`${idx}.accessKey`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="securityKey"
name="securityKey"
>
<>
<Input
placeholder="请输入securityKey"
type="text"
value={ele.securityKey}
onChange={(e) =>
setValue(
`${idx}.securityKey`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="endpoint"
name="endpoint"
>
<>
<Input
placeholder="请输入endpoint"
type="text"
value={ele.endpoint}
onChange={(e) =>
setValue(
`${idx}.endpoint`,
e.target.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="defaultSignName"
name="defaultSignName"
>
<>
<Input
placeholder="请输入defaultSignName"
type="text"
value={ele.defaultSignName}
onChange={(e) =>
setValue(
`${idx}.defaultSignName`,
e.target.value
)
}
/>
</>
</Form.Item>
{/* <Form.Item
label="templates"
name="templates"
>
<Tabs
tabPosition={'top'}
size={'middle'}
type="editable-card"
// hideAdd={!(Object.keys(ele.templates).length > 0)}
onEdit={(
targetKey: any,
action: 'add' | 'remove'
) => {
if (action === 'add') {
setSmsIndex(`${idx}`);
setModal(true);
} else {
cleanKey(
`${idx}.templates`,
targetKey
);
}
}}
items={
Object.keys(
ele.templates || {}
).length > 0
? Object.keys(
ele.templates
).map((name, idx) => {
const template =
ele.templates[
name
];
return {
key: `${name}`,
label: `${name}`,
children: (
<Form
colon={
true
}
labelAlign="left"
layout="vertical"
style={{
marginTop: 10,
}}
>
<>
<Input
placeholder="请输入code"
type="text"
value={
template.code
}
onChange={(
e
) =>
setValue(
`${idx}.templates.${name}.code`,
<Form.Item
label="signName"
name="signName"
>
<>
<Input
placeholder="请输入signName"
type="text"
value={
template.signName
}
onChange={(
e
.target
.value
)
}
/>
</>
</Form.Item>
</Form>
),
};
})
: []
}
></Tabs>
</Form.Item>
</Form>
),
}))
) =>
setValue(
`${idx}.templates.${name}.signName`,
e
.target
.value
)
}
/>
</>
</Form.Item>
<Form.Item
label="code"
name="code"
>
<>
<Input
placeholder="请输入code"
type="text"
value={
template.code
}
onChange={(
e
) =>
setValue(
`${idx}.templates.${name}.code`,
e
.target
.value
)
}
/>
</>
</Form.Item>
</Form>
),
};
})
: []
}
></Tabs>
</Form.Item> */}
</Form>
),
}))
: []
}
></Tabs>
@ -537,7 +928,7 @@ export default function Sms(props: {
cleanKey: (path: string, key: string) => void;
}) {
const { sms, setValue, removeItem, cleanKey } = props;
const { ali, tencent, mockSend } = sms;
const { ali, tencent, mockSend, ctyun } = sms;
return (
<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
<Row>
@ -582,6 +973,13 @@ export default function Sms(props: {
addItem={(path, index) => setValue(`ali.${index}`, {})}
cleanKey={(path, key) => cleanKey(`ali.${path}`, key)}
/>
<CTYun
sms={ctyun || []}
setValue={(path, value) => setValue(`ctyun.${path}`, value)}
removeItem={(path, index) => removeItem(`ctyun`, index)}
addItem={(path, index) => setValue(`ctyun.${index}`, {})}
cleanKey={(path, key) => cleanKey(`ctyun.${path}`, key)}
/>
</Space>
);
}

View File

@ -15,8 +15,8 @@ export default OakComponent({
printRunningTree() {
console.log(this.features.runningTree.getRoot());
},
resetInitialData() {
this.features.localStorage.clear();
async resetInitialData() {
await this.features.localStorage.clear();
this.features.token.logout();
},
setVisible(visible: boolean) {
@ -58,12 +58,12 @@ export default OakComponent({
dialogVisible: false,
});
},
downloadEnv() {
const data = this.features.localStorage.loadAll();
async downloadEnv() {
const data = await this.features.localStorage.loadAll();
return data;
},
resetEnv(data: Record<string, any>) {
this.features.localStorage.resetAll(data);
async resetEnv(data: Record<string, any>) {
await this.features.localStorage.resetAll(data);
},
},
});

View File

@ -13,9 +13,9 @@ export default function render(props: WebComponentProps<EntityDict, 'address', t
printDebugStore: () => void;
printCachedStore: () =>void;
printRunningTree: () => void;
resetInitialData: () => void;
downloadEnv: () => void;
resetEnv: (data: Record<string, any>) => void;
resetInitialData: () => Promise<void>;
downloadEnv: () => Promise<void>;
resetEnv: (data: Record<string, any>) => Promise<void>;
}>) {
const { placement = 'bottom', style = {} } = props.data;
const { printCachedStore, printDebugStore, printRunningTree, resetInitialData, downloadEnv, resetEnv } = props.methods;
@ -64,12 +64,12 @@ export default function render(props: WebComponentProps<EntityDict, 'address', t
} else {
const reader = new FileReader();
reader.readAsText(file);
reader.onload = function () {
reader.onload = async function () {
try {
const data = JSON.parse(
this.result as string
);
resetEnv(data);
await resetEnv(data);
window.location.reload();
} catch (err) {
console.error(err);
@ -115,8 +115,8 @@ export default function render(props: WebComponentProps<EntityDict, 'address', t
size="large"
type="primary"
shape="circle"
onClick={() => {
const data = downloadEnv();
onClick={async () => {
const data = await downloadEnv();
const element = document.createElement('a');
element.setAttribute(
'href',
@ -163,8 +163,8 @@ export default function render(props: WebComponentProps<EntityDict, 'address', t
content: '重置后,原来的数据不可恢复',
okText: '确定',
cancelText: '取消',
onOk: (e) => {
resetInitialData();
onOk: async (e) => {
await resetInitialData();
modal.destroy!();
window.location.reload();
},

View File

@ -21,7 +21,7 @@ export interface Schema extends EntityShape {
codes: Array<WechatQrCode>;
isRoot?: Boolean;
addresses?: Address[];
accounts: Account[];
accounts?: Account[];
};
type IdAction = 'verify' | 'accept' | 'reject';

View File

@ -116,6 +116,7 @@ export async function completeToDo<ED extends EntityDict & BaseEntityDict, T ext
targetEntity: entity as string,
targetFilter: filter,
action,
iState: 'active',
}
}, {});
assert(toDos.length > 0, `${entity as string}相关的todo进行完成操作时找不到对应的数据。filter是${JSON.stringify(filter)}`);

View File

@ -5,11 +5,6 @@ export type QiniuCloudConfig = {
secretKey: string;
};
export type CTYunConfig = {
accessKey: string;
secretKey: string;
}
export type QiniuLiveConfig = {
accessKey: string;
liveHost: string; // 七牛直播云接口域名
@ -65,6 +60,12 @@ export type TencentCloudConfig = {
smsEndpoint: string;
};
export type CTYunCloudConfig = {
accessKey: string;
securityKey: string;
smsEndpoint: string;
};
export type AmapCloudConfig = {
webApiKey: string;
}
@ -73,6 +74,14 @@ export type AliSmsConfig = {
accessKeyId: string;
accessKeySecret: string;
defaultSignName: string;
apiVersion: string;
endpoint: string;
};
export type CTYunSmsConfig = {
accessKey: string;
securityKey: string;
defaultSignName: string;
endpoint: string;
};
@ -117,13 +126,14 @@ export type Config = {
mockSend?: boolean;
ali?: AliSmsConfig[];
tencent?: TencentSmsConfig[];
ctyun?: CTYunSmsConfig[];
};
App: {
qrCodeType?: QrCodeType; // 生成二维码时,优先生成的类型
qrCodeApplicationId?: string; // 生成二维码时优先使用的appId
qrCodePublicForMpId?: string; // 如果qrCodeType是wechatPublicForMp在此指明关联的小程序appId
mpShareImageUrl?: string; // 小程序分享时的imageUrl使用网络图片54
mergeUserDirectly?: boolean; // 当发现用户具有相同的特征时直接合并
qrCodeType?: QrCodeType; // 生成二维码时,优先生成的类型
qrCodeApplicationId?: string; // 生成二维码时优先使用的appId
qrCodePublicForMpId?: string; // 如果qrCodeType是wechatPublicForMp在此指明关联的小程序appId
mpShareImageUrl?: string; // 小程序分享时的imageUrl使用网络图片54
mergeUserDirectly?: boolean; // 当发现用户具有相同的特征时直接合并
};
};

View File

@ -11,46 +11,96 @@ import { AliSmsConfig } from '../../types/Config';
export default class Ali implements Sms<ED, BackendRuntimeContext<ED>> {
name = 'ali';
getConfig(context: BackendRuntimeContext<ED>) {
const { system } = context.getApplication()!;
const { config: systemConfig } = system as EntityDict['system']['Schema'];
async getConfig(context: BackendRuntimeContext<ED>, systemId?: string) {
let system;
if (systemId) {
[system] = await context.select(
'system',
{
data: {
id: 1,
config: 1,
},
filter: {
id: systemId,
},
},
{
dontCollect: true,
}
);
} else {
system = context.getApplication()!.system;
}
const { config: systemConfig } =
system as EntityDict['system']['Schema'];
const aliConfig = get(systemConfig, 'Sms.ali.0', {}) as AliSmsConfig;
const { accessKeyId,
accessKeySecret,
defaultSignName,
endpoint } = aliConfig;
const { accessKeyId, accessKeySecret, defaultSignName, endpoint } =
aliConfig;
assert(accessKeyId, 'accessKeyId未配置');
assert(accessKeySecret, 'accessKeySecret未配置');
assert(defaultSignName, 'defaultSignName未配置');
assert(endpoint, 'endpoint未配置');
return aliConfig;
}
async syncTemplate(systemId: string) {
// todo
return [];
}
async sendSms(params: {
mobile: string,
templateParam?: Record<string, any>,
smsTemplate: Partial<EntityDict['smsTemplate']['Schema']>
}, context: BackendRuntimeContext<ED>): Promise<{ success: boolean, res: any }> {
const { mobile, templateParam, smsTemplate } = params;
const { templateCode } = smsTemplate;
const { accessKeyId, accessKeySecret, defaultSignName, endpoint } = this.getConfig(context);
async syncTemplate(systemId: string, context: BackendRuntimeContext<ED>) {
const { accessKeyId, accessKeySecret, endpoint, apiVersion } = await this.getConfig(
context,
systemId
);
const aliInstance = SDK.getInstance(
'ali',
accessKeyId,
accessKeySecret,
endpoint,
undefined,
apiVersion
) as AliSmsInstance;
const result = await aliInstance.syncTemplate({
PageIndex: 1,
PageSize: 100,
});
// // todo templateName: string,
// templateCode: string,
// templateContent: string
const { smsTemplateList } = result;
if (smsTemplateList) {
return smsTemplateList.map((ele) => {
return {
templateCode: ele.templateCode!,
templateName: ele.templateName!,
templateContent: ele.templateContent!,
};
});
}
return [];
}
async sendSms(
params: {
mobile: string;
templateParam?: Record<string, any>;
smsTemplate: Partial<EntityDict['smsTemplate']['Schema']>;
},
context: BackendRuntimeContext<ED>
): Promise<{ success: boolean; res: any }> {
const { mobile, templateParam, smsTemplate } = params;
const { templateCode } = smsTemplate;
const { accessKeyId, accessKeySecret, defaultSignName, endpoint } =
await this.getConfig(context);
const aliInstance = SDK.getInstance(
'ali',
accessKeyId,
accessKeySecret,
endpoint
) as AliSmsInstance;
const result = await aliInstance.sendSms({
phoneNumbers: [mobile],
templateCode: templateCode!,
templateParam: templateParam,
signName: defaultSignName,
})
});
const { code, message, requestId } = result;
if (code === 'Ok') {
if (code === 'OK') {
return {
success: true,
res: result,

117
src/utils/sms/ctyun.ts Normal file
View File

@ -0,0 +1,117 @@
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain'
import { BackendRuntimeContext } from '../../context/BackendRuntimeContext';
import { assert } from 'oak-domain/lib/utils/assert';
import Sms from "../../types/Sms";
import { ED } from '../../types/RuntimeCxt';
import { EntityDict } from '../../oak-app-domain';
import { get } from 'oak-domain/lib/utils/lodash';
import SDK, { CTYunSmsInstance } from 'oak-external-sdk/lib/SmsSdk';
import { CTYunSmsConfig } from '../../types/Config';
export default class CTYun implements Sms<ED, BackendRuntimeContext<ED>> {
name = 'ctyun';
async getConfig(context: BackendRuntimeContext<ED>, systemId?: string) {
let system;
if (systemId) {
[system] = await context.select(
'system',
{
data: {
id: 1,
config: 1,
},
filter: {
id: systemId,
},
},
{
dontCollect: true,
}
);
} else {
system = context.getApplication()!.system;
}
const { config: systemConfig } =
system as EntityDict['system']['Schema'];
const ctyunConfig = get(
systemConfig,
'Sms.ctyun.0',
{}
) as CTYunSmsConfig;
const { accessKey, securityKey, endpoint } =
ctyunConfig;
assert(accessKey, 'accessKey未配置');
assert(securityKey, 'securityKey未配置');
return ctyunConfig;
}
async syncTemplate(systemId: string, context: BackendRuntimeContext<ED>) {
const { accessKey, securityKey, endpoint } =
await this.getConfig(context, systemId);
const ctyunInstance = SDK.getInstance(
'ctyun',
accessKey,
securityKey,
endpoint
) as CTYunSmsInstance;
const result = await ctyunInstance.syncTemplate({
pageIndex: 1,
pageSize: 50, // pageSize必须小于或等于50
});
// // todo templateName: string,
// templateCode: string,
// templateContent: string
const { data } = result;
if (data) {
return data.map((ele) => {
return {
templateCode: ele.templateCode!,
templateName: ele.templateName!,
templateContent: ele.templateContent!,
};
});
}
return [];
}
async sendSms(
params: {
mobile: string;
templateParam?: Record<string, string>;
smsTemplate: Partial<EntityDict['smsTemplate']['Schema']>;
},
context: BackendRuntimeContext<ED>
): Promise<{ success: boolean; res: any }> {
const { mobile, templateParam, smsTemplate } = params;
const { templateCode } = smsTemplate;
const {
accessKey,
securityKey,
endpoint,
defaultSignName,
} = await this.getConfig(context);
const ctyunInstance = SDK.getInstance(
'ctyun',
accessKey,
securityKey,
endpoint
) as CTYunSmsInstance;
const result = await ctyunInstance.sendSms({
phoneNumber: mobile,
templateParam,
templateCode: templateCode!,
signName: defaultSignName,
});
const code = result?.code || '';
if (code === 'OK') {
return {
success: true,
res: result,
};
}
return {
success: false,
res: result,
};
}
};

View File

@ -10,13 +10,16 @@ import Sms from '../../types/Sms';
import Ali from './ali';
import Tencent from './tencent';
import CTYun from './ctyun';
const ali = new Ali();
const tencent = new Tencent();
const ctyun = new CTYun();
const SmsDict: Record<string, any> = {
[ali.name]: ali,
[tencent.name]: tencent,
[ctyun.name]: ctyun,
};

View File

@ -38,11 +38,8 @@ export default class Tencent implements Sms<ED, BackendRuntimeContext<ED>> {
'Sms.tencent.0',
{}
) as TencentSmsConfig;
const { secretId,
secretKey,
region,
endpoint,
smsSdkAppId } = tencentConfig;
const { secretId, secretKey, region, endpoint, smsSdkAppId } =
tencentConfig;
assert(secretId, 'secretId未配置');
assert(secretKey, 'secretKey未配置');
assert(region, 'region未配置');