message和notification的逻辑(未测试)
This commit is contained in:
parent
0f8d42573d
commit
73a818b7df
|
|
@ -1,18 +1,17 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var filter_1 = require("oak-domain/lib/store/filter");
|
||||
var tslib_1 = require("tslib");
|
||||
var assert_1 = tslib_1.__importDefault(require("assert"));
|
||||
var validator_1 = require("oak-domain/lib/utils/validator");
|
||||
var checkers = [
|
||||
{
|
||||
type: 'logical',
|
||||
action: 'select',
|
||||
type: 'data',
|
||||
action: 'create',
|
||||
entity: 'messageTypeTemplateId',
|
||||
checker: function (operation, context) {
|
||||
var applicationId = context.getApplicationId();
|
||||
var filter = {
|
||||
applicationId: applicationId,
|
||||
};
|
||||
operation.filter = operation.filter ? (0, filter_1.combineFilters)([operation.filter, filter]) : filter;
|
||||
},
|
||||
checker: function (data, context) {
|
||||
(0, assert_1.default)(!(data instanceof Array));
|
||||
(0, validator_1.checkAttributesNotNull)('messageTypeTemplateId', data, ['type', 'templateId', 'applicationId']);
|
||||
}
|
||||
}
|
||||
];
|
||||
exports.default = checkers;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ exports.default = OakComponent({
|
|||
id: 1,
|
||||
name: 1,
|
||||
},
|
||||
params: 1,
|
||||
router: 1,
|
||||
},
|
||||
formData: function (_a) {
|
||||
var message = _a.data, features = _a.features, props = _a.props;
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ import { EntityDict } from '../../../general-app-domain';
|
|||
export default function Render(props: WebComponentProps<EntityDict, 'message', false, {
|
||||
onItemClicked: (item: {
|
||||
id: string;
|
||||
params: EntityDict['message']['Schema']['params'];
|
||||
router: EntityDict['message']['Schema']['router'];
|
||||
}) => void;
|
||||
$$createAt$$: number;
|
||||
type: string;
|
||||
title: string;
|
||||
params: EntityDict['message']['Schema']['params'];
|
||||
router: EntityDict['message']['Schema']['router'];
|
||||
visitState: EntityDict['message']['Schema']['visitState'];
|
||||
id: string;
|
||||
}, {}>): JSX.Element;
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@ var MessageTypeToColor = {
|
|||
};
|
||||
function Render(props) {
|
||||
var data = props.data, methods = props.methods;
|
||||
var id = data.id, params = data.params, title = data.title, type = data.type, $$createAt$$ = data.$$createAt$$, visitState = data.visitState, _a = data.oakLegalActions, oakLegalActions = _a === void 0 ? [] : _a, onItemClicked = data.onItemClicked;
|
||||
var id = data.id, router = data.router, title = data.title, type = data.type, $$createAt$$ = data.$$createAt$$, visitState = data.visitState, _a = data.oakLegalActions, oakLegalActions = _a === void 0 ? [] : _a, onItemClicked = data.onItemClicked;
|
||||
var navigateTo = methods.navigateTo, execute = methods.execute;
|
||||
return ((0, jsx_runtime_1.jsxs)("div", tslib_1.__assign({ className: web_module_less_1.default.list, onClick: onItemClicked
|
||||
? function () {
|
||||
onItemClicked({
|
||||
id: id,
|
||||
params: params,
|
||||
params: router,
|
||||
});
|
||||
}
|
||||
: undefined }, { children: [(0, jsx_runtime_1.jsxs)("div", tslib_1.__assign({ className: web_module_less_1.default.list__notify }, { children: [visitState === 'unvisited' && ((0, jsx_runtime_1.jsx)(antd_1.Badge, { style: { marginRight: 5 }, status: "processing" })), (0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ className: web_module_less_1.default.notify_deadline }, { children: title })), oakLegalActions.includes('visit') && ((0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ className: web_module_less_1.default.notify_mask, onClick: function (event) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { String, Text } from 'oak-domain/lib/types/DataType';
|
|||
import { Schema as User } from './User';
|
||||
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
||||
import { Channel, Weight } from '../types/Message';
|
||||
declare type MessageParams = {
|
||||
declare type Router = {
|
||||
pathname: string;
|
||||
props?: Record<string, any>;
|
||||
state?: Record<string, any>;
|
||||
|
|
@ -21,6 +21,6 @@ export interface Schema extends EntityShape {
|
|||
title: String<256>;
|
||||
content: Text;
|
||||
data?: Object;
|
||||
params?: MessageParams;
|
||||
router?: Router;
|
||||
}
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ var locale = {
|
|||
weight: '优先级',
|
||||
iState: '发送状态',
|
||||
visitState: '访问状态',
|
||||
params: '渠道定制参数',
|
||||
router: '目标路由',
|
||||
data: '透传数据',
|
||||
},
|
||||
action: {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { Action, ParticularAction, IState, VisitState } from "./Action";
|
|||
import { Channel, Weight } from "../../types/Message";
|
||||
import * as User from "../User/Schema";
|
||||
import * as MessageSystem from "../MessageSystem/Schema";
|
||||
declare type MessageParams = {
|
||||
declare type Router = {
|
||||
pathname: string;
|
||||
props?: Record<string, any>;
|
||||
state?: Record<string, any>;
|
||||
|
|
@ -26,7 +26,7 @@ export declare type OpSchema = EntityShape & {
|
|||
title: String<256>;
|
||||
content: Text;
|
||||
data?: Object | null;
|
||||
params?: MessageParams | null;
|
||||
router?: Router | null;
|
||||
iState?: IState | null;
|
||||
visitState?: VisitState | null;
|
||||
};
|
||||
|
|
@ -41,7 +41,7 @@ export declare type Schema = EntityShape & {
|
|||
title: String<256>;
|
||||
content: Text;
|
||||
data?: Object | null;
|
||||
params?: MessageParams | null;
|
||||
router?: Router | null;
|
||||
iState?: IState | null;
|
||||
visitState?: VisitState | null;
|
||||
user: User.Schema;
|
||||
|
|
@ -65,7 +65,7 @@ declare type AttrFilter = {
|
|||
title: Q_StringValue;
|
||||
content: Q_StringValue;
|
||||
data: Object;
|
||||
params: Q_EnumValue<MessageParams>;
|
||||
router: Q_EnumValue<Router>;
|
||||
iState: Q_EnumValue<IState>;
|
||||
visitState: Q_EnumValue<VisitState>;
|
||||
};
|
||||
|
|
@ -87,7 +87,7 @@ export declare type Projection = {
|
|||
title?: number;
|
||||
content?: number;
|
||||
data?: number;
|
||||
params?: number;
|
||||
router?: number;
|
||||
iState?: number;
|
||||
visitState?: number;
|
||||
messageSystem$message?: MessageSystem.Selection & {
|
||||
|
|
@ -130,7 +130,7 @@ export declare type SortAttr = {
|
|||
} | {
|
||||
content: number;
|
||||
} | {
|
||||
params: number;
|
||||
router: number;
|
||||
} | {
|
||||
iState: number;
|
||||
} | {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ exports.desc = {
|
|||
data: {
|
||||
type: "object"
|
||||
},
|
||||
params: {
|
||||
router: {
|
||||
type: "object"
|
||||
},
|
||||
iState: {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{ "attr": { "entity": "关联对象", "entityId": "关联对象ID", "restriction": "限制", "title": "标题", "content": "内容", "user": "关联用户", "type": "消息类型", "weight": "优先级", "iState": "发送状态", "visitState": "访问状态", "params": "渠道定制参数", "data": "透传数据" }, "action": { "succeed": "成功", "fail": "失败", "visit": "阅读" }, "v": { "iState": { "sending": "发送中", "success": "发送成功", "failure": "发送失败" }, "visitState": { "unvisited": "未读", "visited": "已读" }, "weight": { "high": "高", "medium": "中", "low": "低" } } }
|
||||
{ "attr": { "entity": "关联对象", "entityId": "关联对象ID", "restriction": "限制", "title": "标题", "content": "内容", "user": "关联用户", "type": "消息类型", "weight": "优先级", "iState": "发送状态", "visitState": "访问状态", "router": "目标路由", "data": "透传数据" }, "action": { "succeed": "成功", "fail": "失败", "visit": "阅读" }, "v": { "iState": { "sending": "发送中", "success": "发送成功", "failure": "发送失败" }, "visitState": { "unvisited": "未读", "visited": "已读" }, "weight": { "high": "高", "medium": "中", "low": "低" } } }
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ function createComponent(option, features) {
|
|||
});
|
||||
} }, methods), lifetimes: tslib_1.__assign({ ready: function () {
|
||||
if (relatedMessageTypes) {
|
||||
var applicationId = this.features.application.getApplicationId();
|
||||
this.features.cache.refresh('messageTypeTemplateId', {
|
||||
data: {
|
||||
id: 1,
|
||||
|
|
@ -87,6 +88,7 @@ function createComponent(option, features) {
|
|||
type: {
|
||||
$in: relatedMessageTypes,
|
||||
},
|
||||
applicationId: applicationId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ var jsx_runtime_1 = require("react/jsx-runtime");
|
|||
var antd_1 = require("antd");
|
||||
var pageHeader_1 = tslib_1.__importDefault(require("../../../components/common/pageHeader"));
|
||||
var web_module_less_1 = tslib_1.__importDefault(require("./web.module.less"));
|
||||
var list_1 = tslib_1.__importDefault(require("../../../components/messageTypeTemplateId/list"));
|
||||
function Render(props) {
|
||||
var _a = props.data, oakId = _a.oakId, tabValue = _a.tabValue, config = _a.config, name = _a.name, description = _a.description, type = _a.type, system = _a.system;
|
||||
var _b = props.methods, t = _b.t, navigateBack = _b.navigateBack, onTabClick = _b.onTabClick, goWechatPublicTagList = _b.goWechatPublicTagList;
|
||||
|
|
@ -12,13 +13,21 @@ function Render(props) {
|
|||
if (type === 'wechatPublic') {
|
||||
Actions.push((0, jsx_runtime_1.jsx)(antd_1.Button, tslib_1.__assign({ onClick: function () { return goWechatPublicTagList(); } }, { children: "\u516C\u4F17\u53F7Tag\u7BA1\u7406" })));
|
||||
}
|
||||
return ((0, jsx_runtime_1.jsx)(pageHeader_1.default, tslib_1.__assign({ showBack: true, title: "\u5E94\u7528\u6982\u89C8" }, { children: (0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ className: web_module_less_1.default.container }, { children: (0, jsx_runtime_1.jsx)(antd_1.Card, tslib_1.__assign({ title: name, bordered: false, actions: Actions }, { children: (0, jsx_runtime_1.jsx)(antd_1.Tabs, { items: [
|
||||
{
|
||||
label: '应用概览',
|
||||
key: 'detail',
|
||||
children: ((0, jsx_runtime_1.jsxs)(antd_1.Descriptions, tslib_1.__assign({ column: 1, bordered: true }, { children: [(0, jsx_runtime_1.jsx)(antd_1.Descriptions.Item, tslib_1.__assign({ label: "id" }, { children: (0, jsx_runtime_1.jsx)(antd_1.Typography.Paragraph, tslib_1.__assign({ copyable: true }, { children: oakId })) })), (0, jsx_runtime_1.jsx)(antd_1.Descriptions.Item, tslib_1.__assign({ label: t('application:attr.name') }, { children: name })), (0, jsx_runtime_1.jsx)(antd_1.Descriptions.Item, tslib_1.__assign({ label: t('application:attr.description') }, { children: description })), (0, jsx_runtime_1.jsx)(antd_1.Descriptions.Item, tslib_1.__assign({ label: t('application:attr.type') }, { children: t("application:v.type.".concat(type)) })), (0, jsx_runtime_1.jsx)(antd_1.Descriptions.Item, tslib_1.__assign({ label: t('application:attr.system') +
|
||||
t('system:attr.name') }, { children: system === null || system === void 0 ? void 0 : system.name }))] }))),
|
||||
},
|
||||
] }) })) })) })));
|
||||
var items = [
|
||||
{
|
||||
label: '应用概览',
|
||||
key: 'detail',
|
||||
children: ((0, jsx_runtime_1.jsxs)(antd_1.Descriptions, tslib_1.__assign({ column: 1, bordered: true }, { children: [(0, jsx_runtime_1.jsx)(antd_1.Descriptions.Item, tslib_1.__assign({ label: "id" }, { children: (0, jsx_runtime_1.jsx)(antd_1.Typography.Paragraph, tslib_1.__assign({ copyable: true }, { children: oakId })) })), (0, jsx_runtime_1.jsx)(antd_1.Descriptions.Item, tslib_1.__assign({ label: t('application:attr.name') }, { children: name })), (0, jsx_runtime_1.jsx)(antd_1.Descriptions.Item, tslib_1.__assign({ label: t('application:attr.description') }, { children: description })), (0, jsx_runtime_1.jsx)(antd_1.Descriptions.Item, tslib_1.__assign({ label: t('application:attr.type') }, { children: t("application:v.type.".concat(type)) })), (0, jsx_runtime_1.jsx)(antd_1.Descriptions.Item, tslib_1.__assign({ label: t('application:attr.system') +
|
||||
t('system:attr.name') }, { children: system === null || system === void 0 ? void 0 : system.name }))] }))),
|
||||
},
|
||||
];
|
||||
if (['wechatPublic', 'wechatMp'].includes(type)) {
|
||||
items.push({
|
||||
label: '模板消息管理',
|
||||
key: 'mttId',
|
||||
children: (0, jsx_runtime_1.jsx)(list_1.default, { applicationId: oakId, oakPath: "$application-detail-mttId" })
|
||||
});
|
||||
}
|
||||
return ((0, jsx_runtime_1.jsx)(pageHeader_1.default, tslib_1.__assign({ showBack: true, title: "\u5E94\u7528\u6982\u89C8" }, { children: (0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ className: web_module_less_1.default.container }, { children: (0, jsx_runtime_1.jsx)(antd_1.Card, tslib_1.__assign({ title: name, bordered: false, actions: Actions }, { children: (0, jsx_runtime_1.jsx)(antd_1.Tabs, { items: items }) })) })) })));
|
||||
}
|
||||
exports.default = Render;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ exports.default = OakComponent({
|
|||
id: 1,
|
||||
name: 1,
|
||||
},
|
||||
params: 1,
|
||||
router: 1,
|
||||
},
|
||||
isList: false,
|
||||
formData: function (_a) {
|
||||
|
|
@ -34,10 +34,10 @@ exports.default = OakComponent({
|
|||
},
|
||||
methods: {
|
||||
goPage: function () {
|
||||
var params = this.state.params;
|
||||
var pathname = params === null || params === void 0 ? void 0 : params.pathname;
|
||||
var props = (params === null || params === void 0 ? void 0 : params.props) || {};
|
||||
var state = params === null || params === void 0 ? void 0 : params.state;
|
||||
var router = this.state.router;
|
||||
var pathname = router === null || router === void 0 ? void 0 : router.pathname;
|
||||
var props = (router === null || router === void 0 ? void 0 : router.props) || {};
|
||||
var state = router === null || router === void 0 ? void 0 : router.state;
|
||||
if (!pathname) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export default function Render(props: WebComponentProps<EntityDict, 'message', f
|
|||
$$createAt$$: number;
|
||||
type: string;
|
||||
visitState: EntityDict['message']['Schema']['visitState'];
|
||||
params: EntityDict['message']['Schema']['params'];
|
||||
router: EntityDict['message']['Schema']['router'];
|
||||
}, {
|
||||
goPage: () => void;
|
||||
}>): JSX.Element;
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ var antd_1 = require("antd");
|
|||
var mobile_module_less_1 = tslib_1.__importDefault(require("./mobile.module.less"));
|
||||
function Render(props) {
|
||||
var data = props.data, methods = props.methods;
|
||||
var title = data.title, content = data.content, params = data.params;
|
||||
var title = data.title, content = data.content, router = data.router;
|
||||
var t = methods.t, goPage = methods.goPage;
|
||||
var pathname = params === null || params === void 0 ? void 0 : params.pathname;
|
||||
var pathname = router === null || router === void 0 ? void 0 : router.pathname;
|
||||
return ((0, jsx_runtime_1.jsxs)("div", tslib_1.__assign({ className: mobile_module_less_1.default.container }, { children: [(0, jsx_runtime_1.jsx)("h1", tslib_1.__assign({ className: mobile_module_less_1.default.title }, { children: title })), (0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ className: mobile_module_less_1.default.content }, { children: content })), pathname && ((0, jsx_runtime_1.jsx)(antd_1.Button, tslib_1.__assign({ className: mobile_module_less_1.default.btn, block: true, type: "primary", onClick: function () {
|
||||
goPage();
|
||||
} }, { children: "\u524D\u5F80" })))] })));
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export default function Render(props: WebComponentProps<EntityDict, 'message', f
|
|||
$$createAt$$: number;
|
||||
type: string;
|
||||
visitState: EntityDict['message']['Schema']['visitState'];
|
||||
params: EntityDict['message']['Schema']['params'];
|
||||
router: EntityDict['message']['Schema']['router'];
|
||||
}, {
|
||||
goPage: () => void;
|
||||
}>): JSX.Element;
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ var pageHeader_1 = tslib_1.__importDefault(require("../../../components/common/p
|
|||
var web_module_less_1 = tslib_1.__importDefault(require("./web.module.less"));
|
||||
function Render(props) {
|
||||
var data = props.data, methods = props.methods;
|
||||
var title = data.title, content = data.content, params = data.params;
|
||||
var title = data.title, content = data.content, router = data.router;
|
||||
var t = methods.t, goPage = methods.goPage;
|
||||
var pathname = params === null || params === void 0 ? void 0 : params.pathname;
|
||||
var pathname = router === null || router === void 0 ? void 0 : router.pathname;
|
||||
return ((0, jsx_runtime_1.jsx)(pageHeader_1.default, tslib_1.__assign({ title: "\u6D88\u606F\u8BE6\u60C5", showBack: true }, { children: (0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ className: web_module_less_1.default.container }, { children: (0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ className: web_module_less_1.default.warp }, { children: (0, jsx_runtime_1.jsxs)("div", tslib_1.__assign({ className: web_module_less_1.default.inner }, { children: [(0, jsx_runtime_1.jsx)("h1", tslib_1.__assign({ className: web_module_less_1.default.title }, { children: title })), (0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ className: web_module_less_1.default.content }, { children: content })), pathname && ((0, jsx_runtime_1.jsx)(antd_1.Button, tslib_1.__assign({ className: web_module_less_1.default.btn, block: true, type: "primary", onClick: function () {
|
||||
goPage();
|
||||
} }, { children: "\u524D\u5F80" })))] })) })) })) })));
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ exports.default = OakComponent({
|
|||
id: 1,
|
||||
name: 1,
|
||||
},
|
||||
params: 1,
|
||||
router: 1,
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ function Render(props) {
|
|||
}, destroyOnClose: true }, { children: (0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ className: web_module_less_1.default.container }, { children: (messages === null || messages === void 0 ? void 0 : messages.length) > 0 ? ((0, jsx_runtime_1.jsx)("div", { children: messages === null || messages === void 0 ? void 0 : messages.map(function (message, index) { return ((0, jsx_runtime_1.jsx)(cell_1.default, { oakId: message.id, oakPath: oakFullpath
|
||||
? "".concat(oakFullpath, ".").concat(message.id)
|
||||
: '', onItemClicked: function (item) {
|
||||
var params = item.params, id = item.id;
|
||||
var id = item.id;
|
||||
onClose && onClose();
|
||||
goDetailById(id);
|
||||
} }, message.id)); }) })) : ((0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ className: web_module_less_1.default.noData }, { children: (0, jsx_runtime_1.jsx)(empty_1.default, { description: "\u6682\u65E0\u6D88\u606F", image: empty_1.default.PRESENTED_IMAGE_SIMPLE }) }))) })) })));
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ exports.default = OakComponent({
|
|||
id: 1,
|
||||
name: 1,
|
||||
},
|
||||
params: 1,
|
||||
router: 1,
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,20 +7,21 @@ var types_1 = require("oak-domain/lib/types");
|
|||
var assert_1 = tslib_1.__importDefault(require("assert"));
|
||||
function rewriteFilter(schema, entity, filter) {
|
||||
var e_1, _a, _b, _c, _d, _e;
|
||||
var _f;
|
||||
for (var attr in filter) {
|
||||
if (attr === '#id' || attr === '$text' || attr.toLowerCase().startsWith(types_1.EXPRESSION_PREFIX)) {
|
||||
}
|
||||
else if (['$and', '$or'].includes(attr)) {
|
||||
try {
|
||||
for (var _f = (e_1 = void 0, tslib_1.__values(filter[attr])), _g = _f.next(); !_g.done; _g = _f.next()) {
|
||||
var node = _g.value;
|
||||
for (var _g = (e_1 = void 0, tslib_1.__values(filter[attr])), _h = _g.next(); !_h.done; _h = _g.next()) {
|
||||
var node = _h.value;
|
||||
rewriteFilter(schema, entity, node);
|
||||
}
|
||||
}
|
||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (_g && !_g.done && (_a = _f.return)) _a.call(_f);
|
||||
if (_h && !_h.done && (_a = _g.return)) _a.call(_g);
|
||||
}
|
||||
finally { if (e_1) throw e_1.error; }
|
||||
}
|
||||
|
|
@ -33,7 +34,7 @@ function rewriteFilter(schema, entity, filter) {
|
|||
* 这里要处理的就是把userId受到的约束扩展到存在merge的case
|
||||
* 大部分这类约束都来自relation类型的checker(auth)。来自auth的由系统创建的checker一定是{ userId: xxx }的形式,但用户手写的有可能是{ user: { id: xxxx }}的形式
|
||||
*/
|
||||
if (attr.endsWith('Id') && attr !== 'entityId') {
|
||||
if (attr.endsWith('Id') && attr !== 'entityId' && ((_f = schema[entity].attributes[attr]) === null || _f === void 0 ? void 0 : _f.type) === 'ref') {
|
||||
// 只要是指向user的ref都要处理
|
||||
var rel = (0, relation_1.judgeRelation)(schema, entity, attr.slice(0, attr.length - 2));
|
||||
if (rel === 'user') {
|
||||
|
|
@ -107,7 +108,7 @@ function rewriteFilter(schema, entity, filter) {
|
|||
rewriteFilter(schema, rel, filter[attr]);
|
||||
}
|
||||
else if (rel instanceof Array) {
|
||||
var _h = tslib_1.__read(rel, 1), e = _h[0];
|
||||
var _j = tslib_1.__read(rel, 1), e = _j[0];
|
||||
var f = filter[attr].filter;
|
||||
if (f) {
|
||||
rewriteFilter(schema, e, f);
|
||||
|
|
@ -115,7 +116,7 @@ function rewriteFilter(schema, entity, filter) {
|
|||
}
|
||||
else if (typeof filter[attr] === 'object') {
|
||||
// 还要处理子查询
|
||||
var _j = filter[attr], $in = _j.$in, $nin = _j.$nin;
|
||||
var _k = filter[attr], $in = _k.$in, $nin = _k.$nin;
|
||||
if ($in && !($in instanceof Array)) {
|
||||
var e = $in.entity, f = $in.filter;
|
||||
rewriteFilter(schema, e, f);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Trigger } from 'oak-domain/lib/types/Trigger';
|
||||
import { EntityDict } from '../general-app-domain/EntityDict';
|
||||
import { RuntimeCxt } from '../types/RuntimeCxt';
|
||||
declare const triggers: Trigger<EntityDict, 'notification', RuntimeCxt>[];
|
||||
import { BackendRuntimeContext } from '../context/BackendRuntimeContext';
|
||||
declare const triggers: Trigger<EntityDict, 'notification', BackendRuntimeContext<EntityDict>>[];
|
||||
export default triggers;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,61 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tslib_1 = require("tslib");
|
||||
var assert_1 = require("oak-domain/lib/utils/assert");
|
||||
function sendMessage(messageSentData, context) {
|
||||
var oak_external_sdk_1 = require("oak-external-sdk");
|
||||
function sendMessage(notification, context) {
|
||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||
return tslib_1.__generator(this, function (_a) {
|
||||
return [2 /*return*/];
|
||||
var data, templateId, channel, messageSystemId, _a, messageSystem, system, applications, _b, app, config, _c, appId, appSecret, instance;
|
||||
return tslib_1.__generator(this, function (_d) {
|
||||
switch (_d.label) {
|
||||
case 0:
|
||||
data = notification.data, templateId = notification.templateId, channel = notification.channel, messageSystemId = notification.messageSystemId;
|
||||
return [4 /*yield*/, context.select('messageSystem', {
|
||||
data: {
|
||||
id: 1,
|
||||
messageId: 1,
|
||||
message: {
|
||||
id: 1,
|
||||
userId: 1,
|
||||
},
|
||||
system: {
|
||||
id: 1,
|
||||
application$system: {
|
||||
$entity: 'application',
|
||||
data: {
|
||||
id: 1,
|
||||
type: 1,
|
||||
config: 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
filter: {
|
||||
id: messageSystemId,
|
||||
}
|
||||
}, { dontCollect: true })];
|
||||
case 1:
|
||||
_a = tslib_1.__read.apply(void 0, [_d.sent(), 1]), messageSystem = _a[0];
|
||||
system = messageSystem.system;
|
||||
applications = system.application$system;
|
||||
_b = channel;
|
||||
switch (_b) {
|
||||
case 'mp': return [3 /*break*/, 2];
|
||||
}
|
||||
return [3 /*break*/, 4];
|
||||
case 2:
|
||||
app = applications.find(function (ele) { return ele.type === 'wechatMp'; });
|
||||
config = app.config;
|
||||
_c = config, appId = _c.appId, appSecret = _c.appSecret;
|
||||
instance = oak_external_sdk_1.WechatSDK.getInstance(appId, 'wechatMp', appSecret);
|
||||
return [4 /*yield*/, instance.sendSubscribedMessage({
|
||||
templateId: templateId,
|
||||
data: data,
|
||||
})];
|
||||
case 3:
|
||||
_d.sent();
|
||||
_d.label = 4;
|
||||
case 4: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -19,29 +69,45 @@ var triggers = [
|
|||
fn: function (_a, context, params) {
|
||||
var operation = _a.operation;
|
||||
return tslib_1.__awaiter(void 0, void 0, void 0, function () {
|
||||
var data, filter, fn;
|
||||
return tslib_1.__generator(this, function (_b) {
|
||||
switch (_b.label) {
|
||||
var data, data_1, data_1_1, d, e_1_1;
|
||||
var e_1, _b;
|
||||
return tslib_1.__generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
data = operation.data, filter = operation.filter;
|
||||
fn = function (messageSentData) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
|
||||
return tslib_1.__generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, sendMessage(messageSentData, context)];
|
||||
case 1:
|
||||
_a.sent();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); };
|
||||
if (!(data instanceof Array)) return [3 /*break*/, 1];
|
||||
(0, assert_1.assert)('不存在一对多的情况');
|
||||
return [3 /*break*/, 3];
|
||||
case 1: return [4 /*yield*/, fn(data)];
|
||||
data = operation.data;
|
||||
if (!(data instanceof Array)) return [3 /*break*/, 9];
|
||||
_c.label = 1;
|
||||
case 1:
|
||||
_c.trys.push([1, 6, 7, 8]);
|
||||
data_1 = tslib_1.__values(data), data_1_1 = data_1.next();
|
||||
_c.label = 2;
|
||||
case 2:
|
||||
_b.sent();
|
||||
_b.label = 3;
|
||||
case 3: return [2 /*return*/, 0];
|
||||
if (!!data_1_1.done) return [3 /*break*/, 5];
|
||||
d = data_1_1.value;
|
||||
return [4 /*yield*/, sendMessage(d, context)];
|
||||
case 3:
|
||||
_c.sent();
|
||||
_c.label = 4;
|
||||
case 4:
|
||||
data_1_1 = data_1.next();
|
||||
return [3 /*break*/, 2];
|
||||
case 5: return [3 /*break*/, 8];
|
||||
case 6:
|
||||
e_1_1 = _c.sent();
|
||||
e_1 = { error: e_1_1 };
|
||||
return [3 /*break*/, 8];
|
||||
case 7:
|
||||
try {
|
||||
if (data_1_1 && !data_1_1.done && (_b = data_1.return)) _b.call(data_1);
|
||||
}
|
||||
finally { if (e_1) throw e_1.error; }
|
||||
return [7 /*endfinally*/];
|
||||
case 8: return [3 /*break*/, 11];
|
||||
case 9: return [4 /*yield*/, sendMessage(data, context)];
|
||||
case 10:
|
||||
_c.sent();
|
||||
_c.label = 11;
|
||||
case 11: return [2 /*return*/, 0];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -988,7 +988,7 @@ export async function sendCaptcha<ED extends EntityDict, Cxt extends BackendRunt
|
|||
});
|
||||
if (captcha) {
|
||||
const code = captcha.code!;
|
||||
if (process.env.NODE_ENV === 'development' || mockSend) {
|
||||
if (process.env.NODE_ENV !== 'production' || mockSend) {
|
||||
return `验证码[${code}]已创建`;
|
||||
}
|
||||
else if (captcha.$$createAt$$! as number - now < 60000) {
|
||||
|
|
@ -1001,22 +1001,10 @@ export async function sendCaptcha<ED extends EntityDict, Cxt extends BackendRunt
|
|||
origin: 'tencent',
|
||||
templateName: '登录',
|
||||
mobile,
|
||||
templateParamSet: {
|
||||
templateParamSet: [
|
||||
code,
|
||||
duration: duration.toString(),
|
||||
},
|
||||
templateParamSetFn: (origin, templateParamSet) => {
|
||||
if (!templateParamSet) {
|
||||
return templateParamSet;
|
||||
}
|
||||
if (origin === 'tencent') {
|
||||
return [
|
||||
templateParamSet.code,
|
||||
templateParamSet.duration,
|
||||
];
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
duration.toString(),
|
||||
],
|
||||
},
|
||||
context
|
||||
);
|
||||
|
|
@ -1064,22 +1052,10 @@ export async function sendCaptcha<ED extends EntityDict, Cxt extends BackendRunt
|
|||
origin: 'tencent',
|
||||
templateName: '登录',
|
||||
mobile,
|
||||
templateParamSet: {
|
||||
templateParamSet: [
|
||||
code,
|
||||
duration: duration.toString(),
|
||||
},
|
||||
templateParamSetFn: (origin, templateParamSet) => {
|
||||
if (!templateParamSet) {
|
||||
return templateParamSet;
|
||||
}
|
||||
if (origin === 'tencent') {
|
||||
return [
|
||||
templateParamSet.code,
|
||||
templateParamSet.duration,
|
||||
];
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
duration.toString(),
|
||||
],
|
||||
},
|
||||
context
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,19 +2,18 @@ import { Checker } from "oak-domain/lib/types";
|
|||
import { EntityDict } from '../general-app-domain';
|
||||
import { RuntimeCxt } from '../types/RuntimeCxt';
|
||||
import { combineFilters } from 'oak-domain/lib/store/filter';
|
||||
import assert from "assert";
|
||||
import { checkAttributesNotNull } from "oak-domain/lib/utils/validator";
|
||||
|
||||
const checkers: Checker<EntityDict, 'messageTypeTemplateId', RuntimeCxt> [] = [
|
||||
{
|
||||
type: 'logical',
|
||||
action: 'select',
|
||||
type: 'data',
|
||||
action: 'create',
|
||||
entity: 'messageTypeTemplateId',
|
||||
checker: (operation, context) => {
|
||||
const applicationId = context.getApplicationId();
|
||||
const filter: EntityDict['messageTypeTemplateId']['Selection']['filter'] = {
|
||||
applicationId,
|
||||
};
|
||||
operation.filter = operation.filter ? combineFilters([operation.filter, filter]): filter;
|
||||
},
|
||||
checker: (data, context) => {
|
||||
assert(!(data instanceof Array));
|
||||
checkAttributesNotNull('messageTypeTemplateId', data, ['type', 'templateId', 'applicationId']);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export default OakComponent({
|
|||
id: 1,
|
||||
name: 1,
|
||||
},
|
||||
params: 1,
|
||||
router: 1,
|
||||
},
|
||||
formData: function ({ data: message, features, props }) {
|
||||
return message || {};
|
||||
|
|
|
|||
|
|
@ -26,12 +26,12 @@ export default function Render(
|
|||
{
|
||||
onItemClicked: (item: {
|
||||
id: string;
|
||||
params: EntityDict['message']['Schema']['params'];
|
||||
router: EntityDict['message']['Schema']['router'];
|
||||
}) => void;
|
||||
$$createAt$$: number;
|
||||
type: string;
|
||||
title: string;
|
||||
params: EntityDict['message']['Schema']['params'];
|
||||
router: EntityDict['message']['Schema']['router'];
|
||||
visitState: EntityDict['message']['Schema']['visitState'];
|
||||
id: string;
|
||||
},
|
||||
|
|
@ -41,7 +41,7 @@ export default function Render(
|
|||
const { data, methods } = props;
|
||||
const {
|
||||
id,
|
||||
params,
|
||||
router,
|
||||
title,
|
||||
type,
|
||||
$$createAt$$,
|
||||
|
|
@ -59,7 +59,7 @@ export default function Render(
|
|||
? () => {
|
||||
onItemClicked({
|
||||
id,
|
||||
params,
|
||||
router,
|
||||
});
|
||||
}
|
||||
: undefined
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { LocaleDef } from 'oak-domain/lib/types/Locale';
|
|||
import { Index, ActionDef } from 'oak-domain/lib/types';
|
||||
import { Channel, Weight } from '../types/Message';
|
||||
|
||||
type MessageParams = {
|
||||
type Router = {
|
||||
pathname: string;
|
||||
props?: Record<string, any>;
|
||||
state?: Record<string, any>;
|
||||
|
|
@ -27,7 +27,7 @@ export interface Schema extends EntityShape {
|
|||
title: String<256>;
|
||||
content: Text;
|
||||
data?: Object; // 透传到前台的数据(OpRecords)
|
||||
params?: MessageParams; // 通知前端需要到达的路由
|
||||
router?: Router; // 通知前端需要到达的路由
|
||||
};
|
||||
|
||||
type IAction = 'succeed' | 'fail';
|
||||
|
|
@ -74,7 +74,7 @@ const locale: LocaleDef<
|
|||
weight: '优先级',
|
||||
iState: '发送状态',
|
||||
visitState: '访问状态',
|
||||
params: '渠道定制参数',
|
||||
router: '目标路由',
|
||||
data: '透传数据',
|
||||
},
|
||||
action: {
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ const locale: LocaleDef<Schema, Action, '', {
|
|||
wechatPublic: '公众号',
|
||||
jPush: '极光推送',
|
||||
jim: '极光消息',
|
||||
mp: '小程序',
|
||||
wechatMp: '小程序',
|
||||
sms: '短信',
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ export function createComponent<
|
|||
lifetimes: {
|
||||
ready() {
|
||||
if (relatedMessageTypes) {
|
||||
const applicationId = this.features.application.getApplicationId();
|
||||
this.features.cache.refresh('messageTypeTemplateId', {
|
||||
data: {
|
||||
id: 1,
|
||||
|
|
@ -136,6 +137,7 @@ export function createComponent<
|
|||
type: {
|
||||
$in: relatedMessageTypes,
|
||||
},
|
||||
applicationId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { ReactNode } from 'react';
|
||||
import { Tabs, Card, Descriptions, Typography, Button } from 'antd';
|
||||
import { Tabs, Card, Descriptions, Typography, Button, TabsProps } from 'antd';
|
||||
import PageHeader from '../../../components/common/pageHeader';
|
||||
import Style from './web.module.less';
|
||||
|
||||
|
|
@ -12,6 +12,7 @@ import {
|
|||
|
||||
import { EntityDict } from '../../../general-app-domain';
|
||||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import MessageTypeTemplateIdList from '../../../components/messageTypeTemplateId/list';
|
||||
|
||||
type Config = WebConfig | WechatPublicConfig | WechatMpConfig;
|
||||
|
||||
|
|
@ -50,53 +51,61 @@ export default function Render(
|
|||
</Button>
|
||||
);
|
||||
}
|
||||
const items: TabsProps['items'] = [
|
||||
{
|
||||
label: '应用概览',
|
||||
key: 'detail',
|
||||
children: (
|
||||
<Descriptions column={1} bordered>
|
||||
<Descriptions.Item label="id">
|
||||
<Typography.Paragraph copyable>
|
||||
{oakId}
|
||||
</Typography.Paragraph>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item
|
||||
label={t('application:attr.name')}
|
||||
>
|
||||
{name}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item
|
||||
label={t(
|
||||
'application:attr.description'
|
||||
)}
|
||||
>
|
||||
{description}
|
||||
</Descriptions.Item>
|
||||
|
||||
<Descriptions.Item
|
||||
label={t('application:attr.type')}
|
||||
>
|
||||
{t(`application:v.type.${type}`)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item
|
||||
label={
|
||||
t('application:attr.system') +
|
||||
t('system:attr.name')
|
||||
}
|
||||
>
|
||||
{system?.name}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
),
|
||||
},
|
||||
];
|
||||
if (['wechatPublic', 'wechatMp'].includes(type)) {
|
||||
items.push({
|
||||
label: '模板消息管理',
|
||||
key: 'mttId',
|
||||
children: <MessageTypeTemplateIdList applicationId={oakId} oakPath="$application-detail-mttId"/>
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<PageHeader showBack={true} title="应用概览">
|
||||
<div className={Style.container}>
|
||||
<Card title={name} bordered={false} actions={Actions}>
|
||||
<Tabs
|
||||
items={[
|
||||
{
|
||||
label: '应用概览',
|
||||
key: 'detail',
|
||||
children: (
|
||||
<Descriptions column={1} bordered>
|
||||
<Descriptions.Item label="id">
|
||||
<Typography.Paragraph copyable>
|
||||
{oakId}
|
||||
</Typography.Paragraph>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item
|
||||
label={t('application:attr.name')}
|
||||
>
|
||||
{name}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item
|
||||
label={t(
|
||||
'application:attr.description'
|
||||
)}
|
||||
>
|
||||
{description}
|
||||
</Descriptions.Item>
|
||||
|
||||
<Descriptions.Item
|
||||
label={t('application:attr.type')}
|
||||
>
|
||||
{t(`application:v.type.${type}`)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item
|
||||
label={
|
||||
t('application:attr.system') +
|
||||
t('system:attr.name')
|
||||
}
|
||||
>
|
||||
{system?.name}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
),
|
||||
},
|
||||
]}
|
||||
items={items}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export default OakComponent({
|
|||
id: 1,
|
||||
name: 1,
|
||||
},
|
||||
params: 1,
|
||||
router: 1,
|
||||
},
|
||||
isList: false,
|
||||
formData: ({ data: message }) => {
|
||||
|
|
@ -31,10 +31,10 @@ export default OakComponent({
|
|||
},
|
||||
methods: {
|
||||
goPage() {
|
||||
const { params } = this.state;
|
||||
const pathname = params?.pathname;
|
||||
const props = params?.props || {};
|
||||
const state = params?.state;
|
||||
const { router } = this.state;
|
||||
const pathname = router?.pathname;
|
||||
const props = router?.props || {};
|
||||
const state = router?.state;
|
||||
if (!pathname) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export default function Render(
|
|||
$$createAt$$: number;
|
||||
type: string;
|
||||
visitState: EntityDict['message']['Schema']['visitState'];
|
||||
params: EntityDict['message']['Schema']['params'];
|
||||
router: EntityDict['message']['Schema']['router'];
|
||||
},
|
||||
{
|
||||
goPage: () => void;
|
||||
|
|
@ -28,9 +28,9 @@ export default function Render(
|
|||
>
|
||||
) {
|
||||
const { data, methods } = props;
|
||||
const { title, content, params } = data;
|
||||
const { title, content, router } = data;
|
||||
const { t, goPage } = methods;
|
||||
const pathname = params?.pathname;
|
||||
const pathname = router?.pathname;
|
||||
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export default function Render(
|
|||
$$createAt$$: number;
|
||||
type: string;
|
||||
visitState: EntityDict['message']['Schema']['visitState'];
|
||||
params: EntityDict['message']['Schema']['params'];
|
||||
router: EntityDict['message']['Schema']['router'];
|
||||
},
|
||||
{
|
||||
goPage: () => void;
|
||||
|
|
@ -28,9 +28,9 @@ export default function Render(
|
|||
>
|
||||
) {
|
||||
const { data, methods } = props;
|
||||
const { title, content, params } = data;
|
||||
const { title, content, router } = data;
|
||||
const { t, goPage } = methods;
|
||||
const pathname = params?.pathname;
|
||||
const pathname = router?.pathname;
|
||||
|
||||
return (
|
||||
<div className={Style.container}>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export default OakComponent({
|
|||
id: 1,
|
||||
name: 1,
|
||||
},
|
||||
params: 1,
|
||||
router: 1,
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -69,9 +69,8 @@ export default function Render(
|
|||
}
|
||||
onItemClicked={(item: {
|
||||
id: string;
|
||||
params: EntityDict['message']['Schema']['params'];
|
||||
}) => {
|
||||
const { params, id } = item;
|
||||
const { id } = item;
|
||||
onClose && onClose();
|
||||
goDetailById(id);
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export default OakComponent({
|
|||
id: 1,
|
||||
name: 1,
|
||||
},
|
||||
params: 1,
|
||||
router: 1,
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ function rewriteFilter<ED extends EntityDict & BaseEntityDict, T extends keyof E
|
|||
* 这里要处理的就是把userId受到的约束扩展到存在merge的case
|
||||
* 大部分这类约束都来自relation类型的checker(auth)。来自auth的由系统创建的checker一定是{ userId: xxx }的形式,但用户手写的有可能是{ user: { id: xxxx }}的形式
|
||||
*/
|
||||
if (attr.endsWith('Id') && attr !== 'entityId') {
|
||||
if (attr.endsWith('Id') && attr !== 'entityId' && schema[entity].attributes[attr as string]?.type === 'ref') {
|
||||
// 只要是指向user的ref都要处理
|
||||
const rel = judgeRelation(schema, entity, attr.slice(0, attr.length - 2));
|
||||
if (rel === 'user') {
|
||||
|
|
|
|||
|
|
@ -20,11 +20,42 @@ export function registerMessageNotificationConverters<ED extends EntityDict, Cxt
|
|||
|
||||
|
||||
const InitialChannalByWeightMatrix: Record<Weight, Channel[]> = {
|
||||
high: ['mp', 'wechatPublic', 'sms'],
|
||||
medium: ['mp', 'wechatPublic'],
|
||||
low: ['mp', 'wechatPublic'],
|
||||
high: ['wechatMp', 'wechatPublic', 'sms'],
|
||||
medium: ['wechatMp', 'wechatPublic'],
|
||||
low: ['wechatMp', 'wechatPublic'],
|
||||
};
|
||||
|
||||
async function tryCreateSmsNotification(message: EntityDict['message']['Schema'], context: BackendRuntimeContext<EntityDict>) {
|
||||
const { userId, type, entity, entityId } = message;
|
||||
const [mobile] = await context.select('mobile', {
|
||||
data: {
|
||||
id: 1,
|
||||
mobile: 1,
|
||||
},
|
||||
filter: {
|
||||
userId,
|
||||
},
|
||||
indexFrom: 0,
|
||||
count: 1,
|
||||
}, { dontCollect: true });
|
||||
if (mobile) {
|
||||
const converter = ConverterDict[type!] && ConverterDict[type!].toSms;
|
||||
if (converter) {
|
||||
const dispersedData = await converter(entity!, entityId!, context);
|
||||
if (dispersedData) {
|
||||
return {
|
||||
id: await generateNewIdAsync(),
|
||||
data: dispersedData,
|
||||
channel: 'sms',
|
||||
data1: {
|
||||
mobile,
|
||||
},
|
||||
} as Omit<EntityDict['notification']['CreateSingle']['data'], 'messageSystemId'>;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function createNotification(message: CreateMessageData, context: BRC) {
|
||||
const { restriction, userId, weight, type, entity, entityId } = message;
|
||||
assert(userId);
|
||||
|
|
@ -100,7 +131,7 @@ async function createNotification(message: CreateMessageData, context: BRC) {
|
|||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
if (channels.length === 0) {
|
||||
console.warn(`类型为${type}的消息在生成时,尝试为之生成通知,找不到可推送的channel`);
|
||||
return 0;
|
||||
|
|
@ -114,21 +145,39 @@ async function createNotification(message: CreateMessageData, context: BRC) {
|
|||
async (system) => {
|
||||
const { application$system: applications, config } = system;
|
||||
const notificationDatas: Omit<EntityDict['notification']['CreateSingle']['data'], 'messageSystemId'>[] = [];
|
||||
|
||||
await Promise.all(
|
||||
channels.map(
|
||||
async (channel) => {
|
||||
switch (channel) {
|
||||
case 'mp': {
|
||||
const app = applications?.find(
|
||||
case 'wechatMp': {
|
||||
const apps = applications!.filter(
|
||||
ele => ele.type === 'wechatMp',
|
||||
);
|
||||
if (app) {
|
||||
const wechatUsers = await context.select('wechatUser', {
|
||||
data: {
|
||||
id: 1,
|
||||
applicationId: 1,
|
||||
openId: 1,
|
||||
},
|
||||
filter: {
|
||||
applicationId: {
|
||||
$in: apps.map(ele => ele.id!),
|
||||
},
|
||||
userId,
|
||||
}
|
||||
}, { dontCollect: true });
|
||||
for (const app of apps) {
|
||||
// 如果是wechatMp或者wechat,还要保证用户已经有openId
|
||||
const wechatUser = wechatUsers.find(
|
||||
ele => ele.applicationId === app.id
|
||||
);
|
||||
const messageTypeTemplateId = messageTypeTemplateIds.find(
|
||||
ele => ele.applicationId === app.id && ele.type === type
|
||||
);
|
||||
if (messageTypeTemplateId) {
|
||||
if (messageTypeTemplateId && wechatUser) {
|
||||
const converter = ConverterDict[type!] && ConverterDict[type!]!.toWechatMp;
|
||||
const dispersedData = converter && await converter(entity!, entityId!, context);
|
||||
const dispersedData = converter && await converter(entity!, entityId!, apps, app, context);
|
||||
if (dispersedData) {
|
||||
notificationDatas.push({
|
||||
id: await generateNewIdAsync(),
|
||||
|
|
@ -136,6 +185,9 @@ async function createNotification(message: CreateMessageData, context: BRC) {
|
|||
channel,
|
||||
applicationId: app.id,
|
||||
templateId: messageTypeTemplateId.templateId!,
|
||||
data1: {
|
||||
openId: wechatUser.openId!,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -143,23 +195,45 @@ async function createNotification(message: CreateMessageData, context: BRC) {
|
|||
break;
|
||||
}
|
||||
case 'wechatPublic': {
|
||||
const app = applications?.find(
|
||||
const apps = applications!.filter(
|
||||
ele => ele.type === 'wechatPublic',
|
||||
);
|
||||
if (app) {
|
||||
const wechatUsers = await context.select('wechatUser', {
|
||||
data: {
|
||||
id: 1,
|
||||
applicationId: 1,
|
||||
openId: 1,
|
||||
},
|
||||
filter: {
|
||||
applicationId: {
|
||||
$in: apps.map(ele => ele.id!),
|
||||
},
|
||||
userId,
|
||||
}
|
||||
}, { dontCollect: true });
|
||||
for (const app of apps) {
|
||||
// 如果是wechatMp或者wechat,还要保证用户已经有openId
|
||||
const wechatUser = wechatUsers.find(
|
||||
ele => ele.applicationId === app.id
|
||||
);
|
||||
const messageTypeTemplateId = messageTypeTemplateIds.find(
|
||||
ele => ele.applicationId === app.id && ele.type === type
|
||||
);
|
||||
if (messageTypeTemplateId) {
|
||||
if (messageTypeTemplateId && wechatUser) {
|
||||
const converter = ConverterDict[type!] && ConverterDict[type!]!.toWechatPublic;
|
||||
const dispersedData = converter && await converter(entity!, entityId!, context);
|
||||
if (dispersedData) {
|
||||
const disperseResult = converter && await converter(entity!, entityId!, apps, app, context);
|
||||
if (disperseResult) {
|
||||
const { data, wechatMpAppId } = disperseResult;
|
||||
notificationDatas.push({
|
||||
id: await generateNewIdAsync(),
|
||||
data: dispersedData,
|
||||
data,
|
||||
channel,
|
||||
applicationId: app.id,
|
||||
templateId: messageTypeTemplateId.templateId!,
|
||||
data1: {
|
||||
openId: wechatUser.openId!,
|
||||
wechatMpAppId,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -167,7 +241,7 @@ async function createNotification(message: CreateMessageData, context: BRC) {
|
|||
break;
|
||||
}
|
||||
default: {
|
||||
assert (channel === 'sms'); // 目前只支持三种
|
||||
assert(channel === 'sms'); // 目前只支持三种
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -175,19 +249,12 @@ async function createNotification(message: CreateMessageData, context: BRC) {
|
|||
)
|
||||
);
|
||||
if (channels.includes('sms')) {
|
||||
const converter = ConverterDict[type!] && ConverterDict[type!].toSms;
|
||||
if (converter) {
|
||||
const dispersedData = await converter(entity!, entityId!, context);
|
||||
if (dispersedData) {
|
||||
notificationDatas.push({
|
||||
id: await generateNewIdAsync(),
|
||||
data: dispersedData,
|
||||
channel: 'sms',
|
||||
});
|
||||
}
|
||||
const smsNotification = await tryCreateSmsNotification(message as EntityDict['message']['Schema'], context);
|
||||
if (smsNotification) {
|
||||
notificationDatas.push(smsNotification);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const messageSystemData: EntityDict['messageSystem']['CreateSingle']['data'] = {
|
||||
id: await generateNewIdAsync(),
|
||||
messageId: message.id,
|
||||
|
|
|
|||
|
|
@ -1,35 +1,329 @@
|
|||
import { Trigger, CreateTrigger, UpdateTrigger } from 'oak-domain/lib/types/Trigger';
|
||||
import { Trigger, CreateTrigger, UpdateTrigger, UpdateTriggerInTxn } from 'oak-domain/lib/types/Trigger';
|
||||
import { EntityDict } from '../general-app-domain/EntityDict';
|
||||
import { CreateOperationData as CreateNotificationData } from '../general-app-domain/Notification/Schema';
|
||||
import { assert } from 'oak-domain/lib/utils/assert';
|
||||
import { RuntimeCxt } from '../types/RuntimeCxt';
|
||||
import { BackendRuntimeContext } from '../context/BackendRuntimeContext';
|
||||
import { WechatMpConfig, WechatPublicConfig, WebConfig } from '../general-app-domain/Application/Schema';
|
||||
import { WechatSDK } from 'oak-external-sdk';
|
||||
import { WechatMpInstance, WechatPublicInstance, WechatSDK } from 'oak-external-sdk';
|
||||
import { composeUrl } from 'oak-domain/lib/utils/url';
|
||||
import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
|
||||
import { sendSms } from '../utils/sms';
|
||||
import { tryMakeSmsNotification } from './message';
|
||||
|
||||
async function sendMessage(messageSentData: CreateNotificationData, context: BackendRuntimeContext<EntityDict>) {
|
||||
async function sendMessage(notification: CreateNotificationData, context: BackendRuntimeContext<EntityDict>) {
|
||||
const { data, templateId, channel, messageSystemId, data1, id } = notification;
|
||||
const [messageSystem] = await context.select('messageSystem', {
|
||||
data: {
|
||||
id: 1,
|
||||
messageId: 1,
|
||||
message: {
|
||||
id: 1,
|
||||
userId: 1,
|
||||
router: 1,
|
||||
type: 1,
|
||||
},
|
||||
system: {
|
||||
id: 1,
|
||||
application$system: {
|
||||
$entity: 'application',
|
||||
data: {
|
||||
id: 1,
|
||||
type: 1,
|
||||
config: 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
filter: {
|
||||
id: messageSystemId,
|
||||
}
|
||||
}, { dontCollect: true });
|
||||
const { system, message } = messageSystem!;
|
||||
const { router, userId, type } = message!;
|
||||
const { application$system: applications, config } = system!;
|
||||
switch (channel) {
|
||||
case 'wechatMp': {
|
||||
const app = applications!.find(
|
||||
ele => ele.type === 'wechatMp'
|
||||
);
|
||||
const { config } = app!;
|
||||
const { appId, appSecret } = config as WechatMpConfig;
|
||||
const instance = WechatSDK.getInstance(appId!, 'wechatMp', appSecret) as WechatMpInstance;
|
||||
const page = `/pages/${composeUrl(router!.pathname!, Object.assign({}, router!.props!, router!.state!))}`;
|
||||
|
||||
// 根据当前环境决定消息推哪个版本
|
||||
const StateDict = {
|
||||
'development': 'developer',
|
||||
'staging': 'trial',
|
||||
'production': 'former',
|
||||
}
|
||||
try {
|
||||
await instance.sendSubscribedMessage({
|
||||
templateId: templateId!,
|
||||
data: data!,
|
||||
openId: (data1 as { openId: string }).openId, // 在notification创建时就赋值了
|
||||
page,
|
||||
state: StateDict[process.env.NODE_ENV as 'development'] as 'developer',
|
||||
});
|
||||
await context.operate('notification', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'succeed',
|
||||
data: {},
|
||||
filter: {
|
||||
id,
|
||||
}
|
||||
}, { dontCollect: true });
|
||||
return 1;
|
||||
}
|
||||
catch (err) {
|
||||
console.warn('发微信小程序消息失败', err);
|
||||
await context.operate('notification', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'fail',
|
||||
data: {
|
||||
},
|
||||
filter: {
|
||||
id,
|
||||
}
|
||||
}, { dontCollect: true });
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
case 'wechatPublic': {
|
||||
const app = applications!.find(
|
||||
ele => ele.type === 'wechatPublic'
|
||||
);
|
||||
const { config } = app!;
|
||||
const { appId, appSecret } = config as WechatPublicConfig;
|
||||
const instance = WechatSDK.getInstance(appId!, 'wechatPublic', appSecret) as WechatPublicInstance;
|
||||
const page = composeUrl(router!.pathname!, Object.assign({}, router!.props!, router!.state!));
|
||||
const { openId, wechatMpAppId } = data1 as {
|
||||
openId: string,
|
||||
wechatMpAppId?: string,
|
||||
};
|
||||
|
||||
try {
|
||||
await instance.sendTemplateMessage({
|
||||
openId,
|
||||
templateId: templateId!,
|
||||
url: !wechatMpAppId ? page : undefined,
|
||||
data: data!,
|
||||
miniProgram: wechatMpAppId ? {
|
||||
appid: wechatMpAppId,
|
||||
pagepath: `/pages/${page}`,
|
||||
} : undefined,
|
||||
clientMsgId: id,
|
||||
});
|
||||
await context.operate('notification', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'succeed',
|
||||
data: {},
|
||||
filter: {
|
||||
id,
|
||||
}
|
||||
}, { dontCollect: true });
|
||||
return 1;
|
||||
}
|
||||
catch (err) {
|
||||
console.warn('发微信公众号消息失败', err);
|
||||
await context.operate('notification', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'fail',
|
||||
data: {
|
||||
},
|
||||
filter: {
|
||||
id,
|
||||
}
|
||||
}, { dontCollect: true });
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
default: {
|
||||
assert(channel === 'sms');
|
||||
|
||||
try {
|
||||
await sendSms({
|
||||
origin: 'ali',
|
||||
templateName: type,
|
||||
templateParamSet: (data as { params: any }).params!,
|
||||
mobile: (data1 as { mobile: string }).mobile,
|
||||
}, context);
|
||||
await context.operate('notification', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'succeed',
|
||||
data: {},
|
||||
filter: {
|
||||
id,
|
||||
}
|
||||
}, { dontCollect: true });
|
||||
return 1;
|
||||
}
|
||||
catch (err) {
|
||||
console.warn('发tencent sms消息失败', err);
|
||||
try {
|
||||
await sendSms({
|
||||
origin: 'tencent',
|
||||
templateName: type,
|
||||
templateParamSet: (data as { paramsArray: any }).paramsArray!,
|
||||
mobile: (data1 as { mobile: string }).mobile,
|
||||
}, context);
|
||||
await context.operate('notification', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'succeed',
|
||||
data: {},
|
||||
filter: {
|
||||
id,
|
||||
}
|
||||
}, { dontCollect: true });
|
||||
return 1;
|
||||
}
|
||||
catch (err2) {
|
||||
console.warn('发aliyun sms消息失败', err2);
|
||||
await context.operate('notification', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'fail',
|
||||
data: {
|
||||
},
|
||||
filter: {
|
||||
id,
|
||||
}
|
||||
}, { dontCollect: true });
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const triggers: Trigger<EntityDict, 'notification', RuntimeCxt>[] = [
|
||||
async function tryCreateSmsNotification(message: EntityDict['message']['Schema'], context: BackendRuntimeContext<EntityDict>) {
|
||||
const smsNotification = await tryMakeSmsNotification(message, context);
|
||||
if (smsNotification) {
|
||||
const { messageSystem$message } = message;
|
||||
for (const ms of messageSystem$message!) {
|
||||
const { id } = ms;
|
||||
await context.operate('notification', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'create',
|
||||
data: Object.assign(smsNotification, {
|
||||
messageSystemId: id,
|
||||
}),
|
||||
}, { dontCollect: true });
|
||||
}
|
||||
return messageSystem$message!.length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const triggers: Trigger<EntityDict, 'notification', BackendRuntimeContext<EntityDict>>[] = [
|
||||
{
|
||||
name: '当创建notification后,业务提交后再进行推送',
|
||||
entity: 'notification',
|
||||
action: 'create',
|
||||
when: 'commit',
|
||||
strict: 'makeSure',
|
||||
fn: async ({ operation }, context, params) => {
|
||||
const { data, filter } = operation;
|
||||
const fn = async (messageSentData: CreateNotificationData) => {
|
||||
await sendMessage(messageSentData, context as BackendRuntimeContext<EntityDict>);
|
||||
}
|
||||
strict: 'takeEasy',
|
||||
fn: async ({ operation }, context) => {
|
||||
const { data } = operation;
|
||||
if (data instanceof Array) {
|
||||
assert('不存在一对多的情况')
|
||||
for (const d of data) {
|
||||
await sendMessage(d, context);
|
||||
}
|
||||
}
|
||||
else {
|
||||
await fn(data);
|
||||
await sendMessage(data, context);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} as CreateTrigger<EntityDict, 'notification', RuntimeCxt>,
|
||||
} as CreateTrigger<EntityDict, 'notification', BackendRuntimeContext<EntityDict>>,
|
||||
{
|
||||
name: '当notification完成时,根据情况去更新message',
|
||||
entity: 'notification',
|
||||
when: 'after',
|
||||
action: ['fail', 'succeed'],
|
||||
fn: async ({ operation }, context) => {
|
||||
const { filter } = operation;
|
||||
assert(filter!.id);
|
||||
const [message] = await context.select('message', {
|
||||
data: {
|
||||
id: 1,
|
||||
weight: 1,
|
||||
iState: 1,
|
||||
type: 1,
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
userId: 1,
|
||||
messageSystem$message: {
|
||||
$entity: 'messageSystem',
|
||||
data: {
|
||||
id: 1,
|
||||
notification$messageSystem: {
|
||||
$entity: 'notification',
|
||||
data: {
|
||||
id: 1,
|
||||
iState: 1,
|
||||
channel: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}, { dontCollect: true });
|
||||
assert(message);
|
||||
if (message.iState === 'success') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 查看所有的notification状态,只要有一个完成就已经完成了
|
||||
let success = false;
|
||||
let allFailed = true;
|
||||
let smsTried = false;
|
||||
for (const ms of message.messageSystem$message!) {
|
||||
for (const n of ms.notification$messageSystem!) {
|
||||
if (n.iState === 'success') {
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
if (n.iState !== 'failure') {
|
||||
allFailed = false;
|
||||
}
|
||||
if (n.channel === 'sms') {
|
||||
smsTried = true;
|
||||
}
|
||||
}
|
||||
if (success === true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
// 有一个完成就算完成
|
||||
await context.operate('message', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'succeed',
|
||||
data: {},
|
||||
filter: {
|
||||
id: message.id,
|
||||
},
|
||||
}, { dontCollect: true });
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (message.weight === 'medium' && !smsTried && allFailed) {
|
||||
// 中级的消息,在其它途径都失败的情况下再发短信
|
||||
const result = await tryCreateSmsNotification(message as EntityDict['message']['Schema'], context);
|
||||
return result;
|
||||
}
|
||||
// 标识消息发送失败
|
||||
await context.operate('message', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'fail',
|
||||
data: {},
|
||||
filter: {
|
||||
id: message.id,
|
||||
},
|
||||
}, { dontCollect: true });
|
||||
return 1;
|
||||
}
|
||||
} as UpdateTriggerInTxn<EntityDict, 'notification', BackendRuntimeContext<EntityDict>>
|
||||
];
|
||||
export default triggers;
|
||||
|
|
@ -2,35 +2,42 @@ import { BRC } from './RuntimeCxt';
|
|||
import { EntityDict } from '../general-app-domain';
|
||||
import { BackendRuntimeContext } from '../context/BackendRuntimeContext';
|
||||
|
||||
type WechatPublicTemplateMsgKeyword = 'keyword1' | 'keyword2' | 'keyword3'| 'keyword4'| 'keyword5'| 'keyword6'| 'keyword7';
|
||||
export type Channel = 'wechatPublic' | 'jPush' | 'jim' | 'mp' | 'sms';
|
||||
type WechatPublicTemplateMsgKeyword = 'keyword1' | 'keyword2' | 'keyword3' | 'keyword4' | 'keyword5' | 'keyword6' | 'keyword7';
|
||||
export type Channel = 'wechatPublic' | 'jPush' | 'jim' | 'wechatMp' | 'sms';
|
||||
export type Weight = 'high' | 'medium' | 'low';
|
||||
|
||||
export interface MessageNotificationConverter<ED extends EntityDict, Cxt extends BackendRuntimeContext<ED>> {
|
||||
type: string;
|
||||
toWechatMp?: (entity: ED['message']['OpSchema']['entity'], entityId: string, context: Cxt) => Promise<{
|
||||
[K : string]: {
|
||||
value: string;
|
||||
}
|
||||
}>;
|
||||
toWechatPublic?: (entity: ED['message']['OpSchema']['entity'], entityId: string, context: Cxt) => Promise<{
|
||||
first?: {
|
||||
value: string;
|
||||
color?: string;
|
||||
};
|
||||
remark?: {
|
||||
value: string;
|
||||
color?: string;
|
||||
};
|
||||
} & {
|
||||
[K in WechatPublicTemplateMsgKeyword]?: {
|
||||
value: string;
|
||||
color?: string;
|
||||
};
|
||||
}>;
|
||||
toWechatMp?: (entity: ED['message']['OpSchema']['entity'], entityId: string,
|
||||
applications: EntityDict['application']['Schema'][], application: EntityDict['application']['Schema'],
|
||||
context: Cxt) => Promise<{
|
||||
[K: string]: {
|
||||
value: string;
|
||||
}
|
||||
} | undefined>;
|
||||
toWechatPublic?: (entity: ED['message']['OpSchema']['entity'], entityId: string,
|
||||
applications: EntityDict['application']['Schema'][], application: EntityDict['application']['Schema'],
|
||||
context: Cxt) => Promise<{
|
||||
data: {
|
||||
first?: {
|
||||
value: string;
|
||||
color?: string;
|
||||
};
|
||||
remark?: {
|
||||
value: string;
|
||||
color?: string;
|
||||
};
|
||||
} & {
|
||||
[K in WechatPublicTemplateMsgKeyword]?: {
|
||||
value: string;
|
||||
color?: string;
|
||||
};
|
||||
},
|
||||
wechatMpAppId?: string,
|
||||
} | undefined>;
|
||||
toSms?: (entity: ED['message']['OpSchema']['entity'], entityId: string, context: Cxt) => Promise<{
|
||||
signName?: string; // 可能的签名
|
||||
params?: Record<string, string>; // 模板参数,需要替换的参数名和 value 的键值对
|
||||
paramsArray?: Array<string>; // 数组形式的模板参数,按序传入服务商接口
|
||||
}>;
|
||||
} | undefined>;
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import {
|
|||
AliCloudConfig,
|
||||
AliSmsConfig,
|
||||
} from '../types/Config';
|
||||
import { OakExternalException } from 'oak-domain/lib/types';
|
||||
|
||||
export async function sendSms<
|
||||
ED extends EntityDict,
|
||||
|
|
@ -18,11 +19,7 @@ export async function sendSms<
|
|||
origin: 'ali' | 'tencent';
|
||||
templateName: string;
|
||||
mobile: string;
|
||||
templateParamSet?: Record<string, string>;
|
||||
templateParamSetFn?: (
|
||||
origin: 'ali' | 'tencent',
|
||||
templateParamSet?: Record<string, string>
|
||||
) => string[] | Record<string, string> | undefined;
|
||||
templateParamSet?: Record<string, string> | string[];
|
||||
},
|
||||
context: Cxt
|
||||
) {
|
||||
|
|
@ -31,7 +28,6 @@ export async function sendSms<
|
|||
templateName,
|
||||
mobile,
|
||||
templateParamSet,
|
||||
templateParamSetFn,
|
||||
} = options;
|
||||
const application = context.getApplication();
|
||||
|
||||
|
|
@ -50,33 +46,36 @@ export async function sendSms<
|
|||
) {
|
||||
assert(false, `${origin}短信未配置`);
|
||||
}
|
||||
const templateParamSet2 = templateParamSetFn
|
||||
? templateParamSetFn(origin, templateParamSet)
|
||||
: templateParamSet;
|
||||
if (origin === 'tencent') {
|
||||
const accountConfig = accountConfigs[0] as TencentCloudConfig;
|
||||
const smsConfig = smsConfigs[0] as TencentSmsConfig;
|
||||
const template = smsConfig.templates?.[templateName];
|
||||
const SmsSdkInstance = SmsSdk.getInstance(
|
||||
origin,
|
||||
accountConfig.secretId,
|
||||
accountConfig.secretKey,
|
||||
accountConfig.region,
|
||||
accountConfig.endpoint
|
||||
) as TencentSmsInstance;
|
||||
const data = await SmsSdkInstance.sendSms({
|
||||
PhoneNumberSet: [mobile],
|
||||
SmsSdkAppId: smsConfig.smsSdkAppId,
|
||||
SignName: template.signName || smsConfig.defaultSignName,
|
||||
TemplateId: template.code,
|
||||
TemplateParamSet: templateParamSet2 as string[],
|
||||
});
|
||||
const sendStatus = data.SendStatusSet[0];
|
||||
if (sendStatus.Code === 'Ok') {
|
||||
return true;
|
||||
for (const smsConfig of smsConfigs) {
|
||||
const smsConfig = smsConfigs[0] as TencentSmsConfig;
|
||||
const accountConfig = (accountConfigs as TencentCloudConfig[]).find(
|
||||
ele => ele.secretId === smsConfig.secretId
|
||||
)!;
|
||||
const template = smsConfig.templates?.[templateName];
|
||||
const SmsSdkInstance = SmsSdk.getInstance(
|
||||
origin,
|
||||
accountConfig.secretId,
|
||||
accountConfig.secretKey,
|
||||
accountConfig.region,
|
||||
accountConfig.endpoint
|
||||
) as TencentSmsInstance;
|
||||
const data = await SmsSdkInstance.sendSms({
|
||||
PhoneNumberSet: [mobile],
|
||||
SmsSdkAppId: smsConfig.smsSdkAppId,
|
||||
SignName: template.signName || smsConfig.defaultSignName,
|
||||
TemplateId: template.code,
|
||||
TemplateParamSet: templateParamSet as string[],
|
||||
});
|
||||
const sendStatus = data.SendStatusSet[0];
|
||||
if (sendStatus.Code === 'Ok') {
|
||||
return true;
|
||||
}
|
||||
console.warn(`通过微信云发送sms失败,电话是${mobile},模板Id是${template.code}`, sendStatus);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
throw new Error('未实现');
|
||||
}
|
||||
|
||||
throw new OakExternalException('尝试发送sms短信失败');
|
||||
}
|
||||
Loading…
Reference in New Issue