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

This commit is contained in:
Xu Chang 2023-09-29 20:24:35 +08:00
commit d4a6422297
341 changed files with 13211 additions and 384 deletions

View File

@ -4,6 +4,7 @@ import { EntityDict } from '../oak-app-domain';
import { Config } from '../types/Config';
import { MenuType } from '../types/WeChat';
import { BackendRuntimeContext } from '../context/BackendRuntimeContext';
import { WechatPublicEventData, WechatMpEventData } from 'oak-external-sdk';
export type GeneralAspectDict<ED extends EntityDict, Cxt extends BackendRuntimeContext<ED>> = {
mergeUser: (params: {
from: string;
@ -151,6 +152,12 @@ export type GeneralAspectDict<ED extends EntityDict, Cxt extends BackendRuntimeC
type: MenuType;
mediaId: string;
}, context: Cxt) => Promise<any>;
createSession: (params: {
data?: WechatPublicEventData | WechatMpEventData;
type: AppType;
entity?: string;
entityId?: string;
}, context: Cxt) => Promise<string>;
createTag: (params: {
applicationId: string;
name: string;

View File

@ -7,6 +7,7 @@ import { createWechatLogin } from './wechatLogin';
import { unbindingWechat } from './wechatUser';
import { getMpUnlimitWxaCode } from './wechatQrCode';
import { confirmUserEntityGrant } from './userEntityGrant';
import { createSession } from './session';
import { getCurrentMenu, getMenu, createMenu, createConditionalMenu, deleteConditionalMenu, deleteMenu, batchGetArticle, getArticle, batchGetMaterialList, getMaterial } from './wechatMenu';
import { createTag, getTags, editTag, deleteTag } from './wechatPublicTag';
declare const aspectDict: {
@ -44,6 +45,7 @@ declare const aspectDict: {
getArticle: typeof getArticle;
batchGetMaterialList: typeof batchGetMaterialList;
getMaterial: typeof getMaterial;
createSession: typeof createSession;
createTag: typeof createTag;
getTags: typeof getTags;
editTag: typeof editTag;

View File

@ -7,6 +7,7 @@ import { createWechatLogin } from './wechatLogin';
import { unbindingWechat } from './wechatUser';
import { getMpUnlimitWxaCode } from './wechatQrCode';
import { confirmUserEntityGrant } from './userEntityGrant';
import { createSession } from './session';
import { getCurrentMenu, getMenu, createMenu, createConditionalMenu, deleteConditionalMenu, deleteMenu, batchGetArticle, getArticle, batchGetMaterialList, getMaterial, } from './wechatMenu';
import { createTag, getTags, editTag, deleteTag, } from './wechatPublicTag';
const aspectDict = {
@ -44,6 +45,7 @@ const aspectDict = {
getArticle,
batchGetMaterialList,
getMaterial,
createSession,
createTag,
getTags,
editTag,

10
es/aspects/session.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
import { EntityDict } from "../oak-app-domain";
import { AppType } from "../oak-app-domain/Application/Schema";
import { BackendRuntimeContext } from "../context/BackendRuntimeContext";
import { WechatPublicEventData, WechatMpEventData } from 'oak-external-sdk';
export declare function createSession<ED extends EntityDict, Cxt extends BackendRuntimeContext<ED>>(params: {
data?: WechatPublicEventData | WechatMpEventData;
type: AppType;
entity?: string;
entityId?: string;
}, context: Cxt): Promise<string | undefined>;

157
es/aspects/session.js Normal file
View File

@ -0,0 +1,157 @@
import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
import assert from "assert";
// export async function transformData<
// ED extends EntityDict,
// Cxt extends BackendRuntimeContext<ED>
// >(
// params: {
// data: WechatPublicEventData | WechatMpEventData;
// type: AppType,
// entity: string,
// entityId: string,
// },
// context: Cxt
// ) {
// const { data, type, entity, entityId } = params;
// const {
// ToUserName,
// FromUserName,
// CreateTime,
// MsgType,
// // Event,
// Content,
// // EventKey,
// } = data;
// if (entity !== 'web') {
// const sessionMessageData = {
// createTime: CreateTime,
// type: MsgType,
// text: Content,
// // news: ,
// aaoe: false,
// isRead: false,
// }
// return sessionMessageData
// } else {
// const sessionMessageData = {
// createTime: CreateTime,
// type: MsgType,
// text: Content,
// // news: ,
// aaoe: false,
// isRead: false,
// }
// return sessionMessageData
// }
// }
export async function createSession(params, context) {
const { data, type, entity, entityId } = params;
const userId = context.getCurrentUserId(true);
let session;
let sessionMessage$session;
switch (type) {
case 'web': {
const systemId = context.getSystemId();
const [application] = await context.select('application', {
data: {
id: 1,
systemId: 1,
type: 1,
},
filter: {
systemId,
type: 'web'
}
}, {});
const result = await context.select('session', {
data: {
id: 1,
entity: 1,
entityId: 1,
userId: 1,
lmts: 1,
},
filter: {
entity: entity || 'application',
entityId: entityId || application?.id,
userId,
}
}, {});
session = result[0];
break;
}
case 'wechatMp':
case 'wechatPublic': {
assert(data, '');
const { ToUserName, FromUserName, CreateTime, MsgType,
// Event,
Content,
// EventKey,
} = data;
const [wechatUser] = await context.select('wechatUser', {
data: {
id: 1,
openId: 1,
applicationId: 1,
},
filter: {
openId: FromUserName,
}
}, {});
sessionMessage$session = [
{
id: await generateNewIdAsync(),
action: 'create',
data: {
id: await generateNewIdAsync(),
applicationId: wechatUser?.applicationId,
// sessionId: session[0]?.id,
wechatUser: wechatUser?.id,
createTime: CreateTime,
type: MsgType,
text: Content,
// news: ,
aaoe: false,
},
}
];
break;
}
default: {
assert(false, '');
}
}
const sessionId = await generateNewIdAsync();
if (session) {
if (!data) {
return session.id;
}
await context.operate('session', {
id: await generateNewIdAsync(),
action: 'update',
data: Object.assign({}, sessionMessage$session && { sessionMessage$session }),
filter: {
id: session.id,
}
}, {
dontCollect: true,
});
return session.id;
}
else {
await context.operate('session', {
id: await generateNewIdAsync(),
action: 'create',
data: Object.assign({
id: sessionId,
entity,
entityId,
userId,
lmts: Date.now(),
}, sessionMessage$session && { sessionMessage$session }),
}, {
dontCollect: true,
});
return sessionId;
}
}

10
es/aspects/sessionMessage.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
import { EntityDict } from "../oak-app-domain";
import { AppType } from "../oak-app-domain/Application/Schema";
import { BackendRuntimeContext } from "../context/BackendRuntimeContext";
import { WechatPublicEventData, WechatMpEventData } from 'oak-external-sdk';
export declare function createSessionMessage<ED extends EntityDict, Cxt extends BackendRuntimeContext<ED>>(params: {
data?: WechatPublicEventData | WechatMpEventData;
type: AppType;
entity?: string;
entityId?: string;
}, context: Cxt): Promise<void>;

View File

@ -0,0 +1,14 @@
export async function createSessionMessage(params, context) {
const { data, type, entity, entityId } = params;
// const [application] = await context.select('application', {
// data: {
// id: 1,
// systemId: 1,
// type: 1,
// },
// filter: {
// systemId,
// type: 'web'
// }
// }, {});
}

View File

@ -1189,14 +1189,22 @@ export async function getWechatMpUserPhoneNumber({ code, env }, context) {
export async function logout({}, context) {
const tokenId = context.getTokenValue();
if (tokenId) {
await context.operate('token', {
id: await generateNewIdAsync(),
action: 'disable',
data: {},
filter: {
id: tokenId,
},
}, { dontCollect: true });
const closeRootMode = context.openRootMode();
try {
await context.operate('token', {
id: await generateNewIdAsync(),
action: 'disable',
data: {},
filter: {
id: tokenId,
},
}, { dontCollect: true });
}
catch (err) {
closeRootMode();
throw err;
}
closeRootMode();
}
}
/**

8
es/components/session/cell/index.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
/// <reference types="react" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "session", false, {
selectedId: string;
onSelect: (id: string) => void;
key: string;
entityFilter: {};
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
export default _default;

View File

@ -0,0 +1,159 @@
export default OakComponent({
entity: 'session',
projection: {
id: 1,
userId: 1,
entity: 1,
entityId: 1,
lmts: 1,
user: {
id: 1,
name: 1,
nickname: 1,
mobile$user: {
$entity: 'mobile',
data: {
id: 1,
mobile: 1,
userId: 1,
},
},
extraFile$entity: {
$entity: 'extraFile',
data: {
id: 1,
tag1: 1,
origin: 1,
bucket: 1,
objectId: 1,
filename: 1,
extra1: 1,
extension: 1,
type: 1,
entity: 1,
},
filter: {
tag1: {
$in: ['avatar'],
},
},
},
},
},
isList: false,
formData({ data, features }) {
const session = Object.assign({}, data);
Object.assign(session, {
userUrl: features.extraFile.getUrl(session?.user?.extraFile$entity &&
session?.user?.extraFile$entity[0]),
});
if (session?.sessionMessage$session) {
Object.assign(session, {
wechatMessages: session?.sessionMessage$session,
// unreadLength: session?.sessionMessage$session?.filter(
// (ele: any) => ele.isRead === false
// )?.length,
});
}
return session;
},
lifetimes: {
async detached() {
const { oakId } = this.props;
const { session } = this.state;
const userId = this.features.token.getUserId(true);
const { data: readRemark } = await this.features.cache.refresh('readRemark', {
data: {
id: 1,
sessionId: 1,
userId: 1,
$$createAt$$: 1,
},
filter: {
session: {
id: oakId
},
userId,
},
sorter: [
{
$attr: {
$$createAt$$: 1,
},
$direction: 'desc',
},
],
count: 1,
});
const { data: sessionMessage } = await this.features.cache.refresh('sessionMessage', {
data: {
id: 1,
sessionId: 1,
userId: 1,
$$createAt$$: 1,
},
filter: {
session: {
id: oakId
},
},
sorter: [
{
$attr: {
$$createAt$$: 1,
},
$direction: 'desc',
},
],
count: 1,
});
if (readRemark && readRemark?.length > 0) {
if (session?.lmst > readRemark && sessionMessage[0]?.userId !== userId) {
}
}
else {
if (sessionMessage[0]?.userId !== userId) {
}
}
},
},
properties: {
selectedId: '',
onSelect: (id) => { },
key: '',
entityFilter: {},
},
methods: {
getAvatarUrl() {
const { userUrl, entity } = this.state;
const { entityFilter } = this.props;
const defaultUrl = 'http://qiniu.gecomebox.com/static/defaultAvatar.png';
if (entityFilter) {
return userUrl || defaultUrl;
}
else {
return defaultUrl;
}
},
getName() {
const { user, entity } = this.state;
const { entityFilter } = this.props;
if (entityFilter) {
const userName = user?.name;
const userNickname = user?.name || user?.nickname;
const userMobile = user?.mobile$user &&
user?.mobile$user[0]?.mobile;
if (userName) {
return userName;
}
if (userMobile) {
return '用户' + userMobile;
}
return userNickname;
}
else {
return '未知';
}
},
},
});

13
es/components/session/cell/web.d.ts vendored Normal file
View File

@ -0,0 +1,13 @@
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
export default function render(props: WebComponentProps<EntityDict, 'session', false, {
id: string;
unreadLength: number;
sessiontMessages: EntityDict['sessionMessage']['Schema'][];
userType: string;
selectedId: string;
onSelect: (id: string) => void;
}, {
getName: () => string;
getAvatarUrl: () => string;
}>): import("react/jsx-runtime").JSX.Element;

View File

@ -0,0 +1,27 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Image, Badge } from 'antd';
import dayjs from 'dayjs';
import classNames from 'classnames';
import Style from './web.module.less';
export default function render(props) {
const { methods, data } = props;
const { selectedId, onSelect, userType, id, unreadLength, sessiontMessages = [], } = data;
const { t, getName, getAvatarUrl } = methods;
const sessiontMessage = sessiontMessages && sessiontMessages[0];
const createAt = sessiontMessage?.$$createAt$$;
const type = sessiontMessage?.type;
const text = sessiontMessage?.text;
const today = dayjs().startOf('day').valueOf();
const createAt2 = createAt && dayjs(createAt).startOf('day').valueOf();
return (_jsxs("div", { className: classNames(Style.cell, {
[Style.cell_selected]: id === selectedId,
}), onClick: () => {
onSelect(id);
}, children: [_jsx(Badge, { dot: id === selectedId ? false : true, count: unreadLength || 0, children: _jsx(Image, { className: Style.avatar, src: getAvatarUrl(), preview: false }) }), _jsxs("div", { className: Style.inner, children: [_jsxs("div", { className: Style.top, children: [_jsx("div", { className: Style.title, children: getName() }), _jsx("div", { className: Style.date, children: sessiontMessage &&
(today === createAt2
? dayjs(createAt).format('HH:mm')
: dayjs(createAt).format('YYYY-MM-DD')) })] }), _jsx("div", { className: Style.message, children: type &&
(type === 'text'
? `${text}`
: `[${t(`sessiontMessage:v.type.${type}`)}消息]`) })] })] }));
}

View File

@ -0,0 +1,58 @@
.cell {
display: flex;
flex-direction: row;
border-bottom: 1px solid var(--oak-border-color);
padding: 10px;
cursor: pointer;
.avatar {
height: 50px !important;
width: 50px !important;
}
.inner {
display: flex;
flex-direction: column;
flex: 1;
margin-left: 10px;
.top {
display: flex;
flex-direction: row;
justify-content: space-between;
.title {
font-size: 16px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
width: 140px;
color: var(--oak-text-color-primary);
}
.date {
font-size: 10px;
color: var(--oak-text-color-secondary);
}
}
.message {
display: inline-block;
font-size: 12px;
color: var(--oak-text-color-secondary);
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: 180px;
margin-top: 10px;
}
}
}
.cell_selected {
background: #d4e3fc;
}

View File

@ -0,0 +1,7 @@
type HeaderProps = {
showBack: boolean;
sessionId: string;
userId: string;
};
declare function Header(props: HeaderProps): import("react/jsx-runtime").JSX.Element;
export default Header;

View File

@ -0,0 +1,102 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useEffect } from 'react';
import { Button, Image } from 'antd';
import { LeftOutlined } from '@ant-design/icons';
import useFeatures from '../../..//hooks/useFeatures';
import classNames from 'classnames';
import Style from './index.module.less';
import { useWidth } from 'oak-frontend-base/es/platforms/web';
function Header(props) {
const features = useFeatures();
const width = useWidth();
const { showBack = true, sessionId, userId } = props;
const [name, setName] = useState('');
const [url, setUrl] = useState('');
useEffect(() => {
if (sessionId) {
const [session] = features.cache?.get('session', {
data: {
id: 1,
uerId: 1,
user: {
id: 1,
name: 1,
nickname: 1,
mobile$user: {
$entity: 'mobile',
data: {
id: 1,
mobile: 1,
userId: 1,
},
},
extraFile$entity: {
$entity: 'extraFile',
data: {
id: 1,
tag1: 1,
origin: 1,
bucket: 1,
objectId: 1,
filename: 1,
extra1: 1,
extension: 1,
type: 1,
entity: 1,
entityId: 1,
},
filter: {
tag1: {
$in: ['avatar'],
},
},
},
},
},
filter: {
id: sessionId,
},
});
if (session) {
const url2 = getAvatarUrl(session);
setUrl(url2);
const name2 = getName(session);
setName(name2);
}
}
}, [sessionId, userId]);
const getAvatarUrl = (session) => {
const { entity, user } = session || {};
const defaultUrl = 'http://qiniu.gecomebox.com/static/defaultAvatar.png';
if (user) {
const userAvatar = features.extraFile.getUrl(session?.user?.extraFile$entity &&
session?.user?.extraFile$entity[0]);
return userAvatar || defaultUrl;
}
return defaultUrl;
};
const getName = (session) => {
const { user } = session || {};
if (user) {
const userName = user?.name || '';
const userNickname = user?.name || user?.nickname || '';
const userMobile = (user?.mobile$user &&
user?.mobile$user[0]?.mobile) ||
'';
if (userName) {
return userName;
}
if (userMobile) {
return '用户' + userMobile;
}
return userNickname;
}
return '未知';
};
return (_jsxs("div", { className: classNames(Style.header, {
[Style.header_mobile]: width === 'xs'
}), children: [showBack && (_jsx(Button, { type: "text", onClick: () => {
features.navigator.navigateBack();
}, children: _jsx(LeftOutlined, { className: Style.backIcon }) })), _jsxs("div", { className: Style.middle, children: [_jsx(Image, { src: url, className: Style.icon, preview: false }), _jsx("div", { className: Style.name, children: name })] })] }));
}
export default Header;

View File

@ -0,0 +1,44 @@
.header {
display: flex;
background: #eee;
flex-direction: row;
align-items: center;
position: fixed;
width: 100%;
z-index: 20;
height: 50px;
position: absolute;
.middle {
display: flex;
flex-direction: row;
flex: 1;
align-items: center;
.icon {
height: 30px;
width: 30px;
align-items: center;
display: flex;
justify-content: center;
margin: 10px;
}
.name {
font-size: 16px;
}
}
}
.header_mobile {
background: var(--oak-color-primary);
.backIcon {
color: #fff;
}
.name {
font-size: 16px;
color: #fff;
}
}

View File

@ -0,0 +1,4 @@
/// <reference types="wechat-miniprogram" />
/// <reference types="react" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, keyof import("../../../oak-app-domain").EntityDict, false, WechatMiniprogram.Component.DataOption>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
export default _default;

View File

@ -0,0 +1,16 @@
export default OakComponent({
isList: false,
formData({ data, features }) {
const userInfo = features.token.getUserInfo();
const mobile = userInfo?.mobile$user && userInfo?.mobile$user[0]?.mobile;
const extraFile = userInfo?.extraFile$entity?.find((ele) => ele.tag1 === 'avatar');
const avatarUrl = features.extraFile.getUrl(extraFile);
return {
mobile,
avatarUrl,
nickname: userInfo?.nickname,
name: userInfo?.name,
};
},
methods: {},
});

6
es/components/session/header/web.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
export default function render(props: WebComponentProps<EntityDict, 'session', false, {
avatarUrl: string;
nickname: string;
}, {}>): import("react/jsx-runtime").JSX.Element;

View File

@ -0,0 +1,10 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Avatar } from 'antd';
// import { UserOutlined } from '@ant-design/icons';
import Style from './web.module.less';
export default function render(props) {
const { methods, data } = props;
const { nickname, avatarUrl } = data;
const defaultUrl = 'http://qiniu.gecomebox.com/static/defaultAvatar.png';
return (_jsxs("div", { className: Style.header, children: [_jsx(Avatar, { shape: "square", className: Style.avatar, src: avatarUrl || defaultUrl }), _jsx("div", { className: Style.nickname, children: nickname })] }));
}

View File

@ -0,0 +1,28 @@
.header {
display: flex;
flex-direction: row;
background: var(--oak-color-primary);
align-items: center;
height: 100px;
.avatar {
width: 50px;
height: 50px;
line-height: 60px;
background-color: var(--oak-bg-color-page);
margin: 0 20px;
.icon {
color: var(--oak-text-color-placeholder);
font-size: 30px;
}
}
.nickname {
color: #fff;
text-overflow: ellipsis;
white-space: nowrap;
overflow:hidden;
}
}

10
es/components/session/list/index.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
/// <reference types="react" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "session", true, {
entity: string;
entityFilter: any;
entityDisplay: (entity: string, entityId: string) => "";
entityProjection: any;
sessionId: string;
dialog: boolean;
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
export default _default;

View File

@ -0,0 +1,216 @@
export default OakComponent({
entity: 'session',
projection: {
id: 1,
entity: 1,
entityId: 1,
userId: 1,
user: {
id: 1,
name: 1,
nickname: 1,
mobile$user: {
$entity: 'mobile',
data: {
id: 1,
mobile: 1,
userId: 1,
},
},
extraFile$entity: {
$entity: 'extraFile',
data: {
id: 1,
tag1: 1,
origin: 1,
bucket: 1,
objectId: 1,
filename: 1,
extra1: 1,
extension: 1,
type: 1,
entity: 1,
entityId: 1,
},
filter: {
tag1: {
$in: ['avatar'],
},
},
},
},
sessionMessage$session: {
$entity: 'sessionMessage',
data: {
id: 1,
text: 1,
type: 1,
userId: 1,
wechatUserId: 1,
createTime: 1,
$$createAt$$: 1,
aaoe: 1,
},
sorter: [
{
$attr: {
$$createAt$$: 1,
},
$direction: 'desc',
},
],
indexFrom: 0,
count: 1,
},
$$createAt$$: 1,
},
isList: true,
formData: function ({ data: sessions, features, props }) {
// const unReadLength = wechatSessions?.filter(
// (ele) => ele.isRead
// )
return {
sessions,
};
},
lifetimes: {
async attached() {
const userId = this.features.token.getUserId(true);
// if (!userId) {
// this.redirectTo(
// {
// url: '/login',
// backUrl: encodeURIComponent(window.location.href),
// },
// undefined,
// true
// );
// return;
// }
const { sessionId } = this.props;
// 父层传入conversationId 默认聊天
if (sessionId) {
this.setSelectedSessionId(sessionId);
}
},
},
data: {
unReadLength: 0,
selectedSessionId: '',
},
properties: {
entity: '',
entityFilter: {},
entityDisplay: (entity, entityId) => '',
entityProjection: {},
sessionId: '',
dialog: false,
},
filters: [
{
filter() {
const { entityFilter, sessionId } = this.props;
if (entityFilter) {
// 说明来源于entity
return {
...entityFilter,
/* $or: [
{
userId: {
$exists: false,
},
},
{
'#id': 'node-1',
user: {
session$user: {
'#sqp': 'not in',
'$expr1': {
$ne: [
{
'#refAttr': 'id',
},
{
'#refId': 'node-1',
'#refAttr': 'id',
}
]
},
$expr2: {
$eq: [
{
'#refAttr': 'userId',
'#refId': 'node-1',
},
{
'#refAttr': 'userId',
}
]
}
}
}
}
], */
};
}
const userId = this.features.token.getUserId();
return {
userId,
};
},
'#name': 'propsQuery',
},
],
sorters: [
{
sorter: {
$attr: {
$$updateAt$$: 1,
},
$direction: 'desc',
},
},
],
methods: {
setSelectedSessionId(sessionId) {
this.setState({
selectedSessionId: sessionId,
});
},
getFilter() {
const { entity, sessionId } = this.props;
// 当外层upsert传入id时走这里
if (sessionId) {
return {
id: sessionId,
};
}
// bypark,byCompany,byplatform走这里
const userId = this.features.token.getUserId();
},
async clearUnRead() {
// =框架支持
// const filter = getFilter();
// await this.execute({
// action: 'update',
// data:
// this.props.userType === 'employer'
// ? {
// isEmployerRead: true,
// }
// : {
// isEntityRead: true,
// },
// filter,
// });
// await this.refresh();
},
// mobile独有
navigateToMessage(sessionId) {
this.navigateTo({
url: '/sessionMessage/list',
sessionId,
}, undefined, true);
},
},
});

View File

@ -0,0 +1,4 @@
{
"navigationBarTitleText": "会话列表",
"usingComponents": {}
}

View File

@ -0,0 +1,39 @@
/** index.wxss **/
.container {
display: flex;
flex-direction: row;
background: var(--oak-bg-color-page);
}
.conversationContainer {
display: flex;
flex-direction: column;
width: 100%;
.messageNumberBox {
display: flex;
flex-direction: row;
align-items: center;
padding: 0 10px;
height: 40px;
justify-content: space-between;
border-top: 1px solid var(--oak-border-color);
border-bottom: 1px solid var(--oak-border-color);
.messageText {
font-size: 16px;
color: var(--oak-text-color-primary);
}
.numberText {
font-size: 16px;
color: var(--oak-text-color-primary);
}
.clearIcon {
font-size: 16px;
color: var(--oak-text-color-secondary);
}
}
}

0
es/components/session/list/web.d.ts vendored Normal file
View File

View File

@ -0,0 +1,69 @@
"use strict";
// import React from 'react';
// import Style from './mobile.module.less';
// import ConversationHeader from '@project/components/conversation/header';
// import ConversationCell from '@project/components/conversation/cell';
// import ConversationMessageNumber from '@project/components/conversation/messageNumber';
// import { WebComponentProps } from 'oak-frontend-base';
// import { EntityDict } from '@oak-app-domain';
// export default function Render(
// props: WebComponentProps<
// EntityDict,
// 'conversation',
// false,
// {
// conversations: EntityDict['conversation']['Schema'][];
// selectedConversationId: string;
// unReadConversation: number;
// userType: string;
// },
// {
// clearUnRead: () => void;
// setSelectedConversationId: (conversationId: string) => void;
// navigateToConversationMessage: (conversationId: string) => void;
// }
// >
// ) {
// const { data, methods } = props;
// const {
// conversations,
// selectedConversationId,
// oakFullpath,
// unReadConversation,
// userType,
// } = data;
// const {
// clearUnRead,
// setSelectedConversationId,
// navigateToConversationMessage,
// } = methods;
// return (
// <div className={Style.container}>
// <div className={Style.conversationContainer}>
// <ConversationHeader />
// <ConversationMessageNumber
// number={unReadConversation}
// clear={clearUnRead}
// />
// {conversations?.map((conversation: any, index: number) => {
// return (
// <ConversationCell
// userType={userType}
// selectedId={selectedConversationId}
// onSelect={(id: string) => {
// navigateToConversationMessage(conversation.id);
// }}
// oakId={conversation.id}
// key={conversation.id}
// oakPath={
// oakFullpath
// ? `${oakFullpath}.${conversation.id}`
// : ''
// }
// />
// );
// })}
// </div>
// </div>
// );
// }

View File

@ -0,0 +1,66 @@
/** index.wxss **/
.container {
overflow: hidden;
height: 100%;
}
.bothContainer {
margin: 0 auto;
margin-top: 5vh;
width: 90%;
min-width: 600px;
height: 80vh;
display: flex;
flex-direction: row;
background-color: #fff;
box-shadow: 0 11px 20px 0 rgb(0 0 0 / 30%);
}
.dialogContainer {
margin-top: unset;
width: 100%;
height: 80vh;
}
.inner {
display: flex;
overflow: scroll;
flex-direction: column;
// margin-top: 50px;
overflow-x: hidden;
height: 100%;
}
.conversationContainer {
display: flex;
flex-direction: column;
width: 300px;
border-right: 1px solid var(--oak-border-color);
.messageNumberBox {
display: flex;
flex-direction: row;
align-items: center;
padding: 0 10px;
height: 40px;
justify-content: space-between;
border-top: 1px solid var(--oak-border-color);
border-bottom: 1px solid var(--oak-border-color);
.messageText {
font-size: 16px;
color: var(--oak-text-color-primary);
}
.numberText {
font-size: 16px;
color: var(--oak-text-color-primary);
}
.clearIcon {
font-size: 16px;
color: var(--oak-text-color-secondary);
}
}
}

11
es/components/session/list/web.pc.d.ts vendored Normal file
View File

@ -0,0 +1,11 @@
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
export default function Render(props: WebComponentProps<EntityDict, 'session', false, {
sessions: EntityDict['session']['Schema'][];
selectedSessionId: string;
className: string;
dialog: boolean;
entityFilter: object;
}, {
setSelectedSessionId: (conversationId: string) => void;
}>): import("react/jsx-runtime").JSX.Element;

View File

@ -0,0 +1,26 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import MessageList from '../../sessionMessage/list';
import Header from '../../../components/session/header';
import SessionCell from '../../../components/session/cell';
import classNames from 'classnames';
import Style from './web.module.less';
export default function Render(props) {
const { data, methods } = props;
const { sessions, selectedSessionId, oakFullpath,
// unReadConversation = 0,
entityFilter, dialog = false, className, } = data;
const { setSelectedSessionId } = methods;
return (_jsx("div", { className: Style.container, children: _jsxs("div", { className: classNames(Style.bothContainer, className, {
[Style.dialogContainer]: dialog,
}), children: [_jsxs("div", { className: Style.conversationContainer, children: [_jsx(Header, {}), _jsx("div", { className: Style.inner, children: sessions?.map((session, index) => {
return (_jsx(SessionCell, { entityFilter: entityFilter, selectedId: selectedSessionId, onSelect: (id) => {
setSelectedSessionId(id);
}, oakId: session.id, oakPath: oakFullpath
? `${oakFullpath}.${session.id}`
: '' }, session.id));
}) })] }), selectedSessionId && (_jsx(MessageList, { sessionId: selectedSessionId,
// isCombine={true}
isEntity: !!entityFilter, oakAutoUnmount: true, oakPath: oakFullpath
? `$$sessionMessage/list`
: undefined }))] }) }));
}

View File

@ -0,0 +1,6 @@
type MessageNumberProps = {
number: number;
clear: () => void;
};
declare function MessageNumber(props: MessageNumberProps): import("react/jsx-runtime").JSX.Element;
export default MessageNumber;

View File

@ -0,0 +1,10 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import Style from './index.module.less';
import { ClearOutlined } from '@ant-design/icons';
function MessageNumber(props) {
const { number = 0, clear } = props;
return (_jsxs("div", { className: Style.messageNumberBox, children: [_jsxs("div", { className: Style.messageNumber, children: [_jsx("span", { className: Style.messageText, children: "\u6D88\u606F" }), _jsxs("span", { className: Style.numberText, children: ["(", number, ")"] })] }), _jsx("div", { onClick: () => {
clear();
}, children: _jsx(ClearOutlined, { className: Style.clearIcon }) })] }));
}
export default MessageNumber;

View File

@ -0,0 +1,26 @@
.messageNumberBox {
display: flex;
flex-direction: row;
align-items: center;
padding: 0 10px;
height: 40px;
justify-content: space-between;
border-top: 1px solid var(--oak-border-color);
border-bottom: 1px solid var(--oak-border-color);
.messageText {
font-size: 16px;
color: var(--oak-text-color-primary);
}
.numberText {
font-size: 16px;
color: var(--oak-text-color-primary);
}
.clearIcon {
font-size: 16px;
color: var(--oak-text-color-secondary);
}
}

View File

@ -0,0 +1,6 @@
/// <reference types="react" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "sessionMessage", false, {
key: string;
isEntity: boolean;
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
export default _default;

View File

@ -0,0 +1,98 @@
// import { Schema as ExtraFile } from '../../../
export default OakComponent({
entity: 'sessionMessage',
isList: false,
projection: {
id: 1,
text: 1,
type: 1,
createTime: 1,
userId: 1,
wechatUserId: 1,
// isRead: 1,
$$createAt$$: 1,
sessionId: 1,
session: {
id: 1,
entity: 1,
entityId: 1,
},
aaoe: 1,
extraFile$entity: {
$entity: 'extraFile',
data: {
id: 1,
tag1: 1,
tag2: 1,
origin: 1,
bucket: 1,
objectId: 1,
filename: 1,
extra1: 1,
extension: 1,
type: 1,
entity: 1,
},
filter: {
tag1: {
$in: ['image'],
},
},
},
},
formData({ data: sessionMessage, features }) {
const type = sessionMessage?.type;
// const data = wechatMessage?.data;
// const session = sessionMessage?.session;
const newSessionMessage = {
type,
aaoe: sessionMessage?.aaoe,
// data,
text: sessionMessage?.text,
id: sessionMessage?.id,
$$createAt$$: sessionMessage?.$$createAt$$,
sessionId: sessionMessage?.sessionId,
// employerId: conversation?.employerId,
// employerMobile:
// conversation?.employer?.mobile$user &&
// conversation?.employer?.mobile$user[0]?.mobile,
// companyName: conversation?.company?.name,
// employerAvatar: this.features.extraFile.getUrl(
// conversation?.employer?.extraFile$entity &&
// conversation?.employer?.extraFile$entity[0]
// ),
};
// if (type === 'image') {
// const extraFile$entity =
// wechatMessage?.extraFile$entity as ExtraFile[];
// Object.assign(newWechatMessage, {
// picUrl: features.extraFile.getUrl(extraFile$entity[0]),
// });
// }
return newSessionMessage;
},
properties: {
key: '',
isEntity: false,
},
methods: {
getAvatarUrl(type) {
const defaultUrl = 'http://qiniu.gecomebox.com/static/defaultAvatar.png';
const { companyLogoUrl, employerAvatar, parkLogoUrl } = this.state;
switch (type) {
case 'company': {
return companyLogoUrl || defaultUrl;
}
case 'employer': {
return employerAvatar || defaultUrl;
}
case 'platformProvider': {
return process.env.PUBLIC_URL + '/logo192.png';
}
case 'park': {
return parkLogoUrl || defaultUrl;
}
}
},
},
});

View File

@ -0,0 +1,14 @@
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
export default function render(props: WebComponentProps<EntityDict, 'sessionMessage', false, {
isEntity: boolean;
$$createAt$$: number;
text: string;
type: string;
aaoe: boolean;
picUrl: string;
sessionId: string;
id: string;
}, {
getAvatarUrl: (type: string) => string;
}>): import("react/jsx-runtime").JSX.Element;

View File

@ -0,0 +1,36 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Image } from 'antd';
import dayjs from 'dayjs';
import classNames from 'classnames';
import Style from './web.module.less';
export default function render(props) {
const { data, methods } = props;
const { $$createAt$$, text, type, picUrl, isEntity, aaoe, sessionId, } = data;
const { t, getAvatarUrl } = methods;
return (_jsx(ICell, { time: $$createAt$$, children: _jsxs("div", { className: classNames(Style.myMessage, {
[Style.notMyMessage]: isEntity !== aaoe,
}), children: [_jsx(Image, { preview: false, className: Style.avatar, src: getAvatarUrl(type) }), _jsxs("div", { className: classNames({
[Style.messageType_text]: type === 'text',
[Style.messageType_text_no]: isEntity !== aaoe,
}), children: [type === 'text' && _jsx(IText, { value: text }), type === 'image' && _jsx(IImage, { url: picUrl })] })] }) }));
}
function ICell(props) {
const { children, time } = props;
const time2 = dayjs(time).startOf('day').valueOf();
return (_jsxs("div", { className: Style.cell, children: [_jsx("div", { className: Style.date, children: time2 === dayjs().startOf('day').valueOf()
? dayjs(time).format('HH:mm:ss')
: dayjs(time).format('YYYY-MM-DD HH:mm:ss') }), children] }));
}
function IText(props) {
const { value } = props;
return _jsx("div", { children: value });
}
function IImage(props) {
const { url } = props;
return (_jsx(Image, { src: url, style: {
width: 120,
// height: 240,
borderRadius: 4,
backgroundColor: '#fff',
} }));
}

View File

@ -0,0 +1,130 @@
.cell {
display: flex;
flex-direction: column;
.date {
font-size: 12px;
color: var(--oak-text-color-secondary);
display: flex;
justify-content: center;
align-items: center;
margin: 10px 0px 10px 0px;
}
}
.background {
display: flex;
flex-direction: column;
}
.skuBackground {
background: var(--oak-container-color-page);
display: flex;
flex-direction: row;
margin: 5px;
}
.skuInfo {
background: var(--oak-container-color-page);
display: flex;
flex-direction: column;
}
.button {
display: flex;
flex-direction: row-reverse;
margin: 5px;
}
.tradeId {
font-size: 12px;
line-height: 25px;
margin: 5px;
width: 200px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.avatar {
margin: 10px;
height: 30px !important;
width: 30px !important;
padding: 0 !important;
}
.messageType_text {
display: flex;
border-radius: 4px;
background: linear-gradient(
var(--oak-color-primary),
var(--oak-color-primary)
);
border-radius: 4px;
font-size: 14px;
line-height: 18px;
word-wrap: break-word;
word-break: break-all;
max-width: 60%;
color: #fff;
padding: 10px;
}
.messageType_text_no {
color: #333;
background: var(--oak-bg-color-container);
}
.messageType_trade {
border-radius: 8px;
color: #333;
background: var(--oak-bg-color-container);
}
.messageType_sku {
border-radius: 8px;
color: #333;
background: var(--oak-bg-color-container);
}
.myMessage {
display: flex;
flex-direction: row-reverse;
justify-content: flex-start;
align-items: baseline;
}
.notMyMessage {
flex-direction: row;
}
.messageType_system {
color: var(--oak-text-color-secondary);
overflow: hidden;
text-overflow: ellipsis;
text-align: center;
line-height: 25px;
display: flex;
justify-content: center;
-webkit-line-clamp: 2;
margin: 0px 10px;
}
.name {
font-size: 14px;
margin: 5px;
width: 200px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.text {
font-size: 10px;
margin: 5px;
color: #777;
}

View File

@ -0,0 +1,10 @@
/// <reference types="react" />
import { EntityDict } from '../../../oak-app-domain';
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "sessionMessage", true, {
sessionId: string;
isEntity: boolean;
dialog: boolean;
entity: string;
entityId: string;
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
export default _default;

View File

@ -0,0 +1,299 @@
import { generateNewId } from 'oak-domain/lib/utils/uuid';
import { DATA_SUBSCRIBER_KEYS } from '../../../config/constants';
export default OakComponent({
entity: 'sessionMessage',
projection: {
id: 1,
text: 1,
type: 1,
userId: 1,
wechatUserId: 1,
createTime: 1,
$$createAt$$: 1,
aaoe: 1,
extraFile$entity: {
$entity: 'extraFile',
data: {
id: 1,
tag1: 1,
origin: 1,
bucket: 1,
objectId: 1,
filename: 1,
extra1: 1,
extension: 1,
type: 1,
entity: 1,
entityId: 1,
},
// filter: {
// tag1: {
// $in: ['image'],
// },
// },
},
sessionId: 1,
session: {
id: 1,
entity: 1,
entityId: 1,
},
},
isList: true,
lifetimes: {
async ready() {
const { sessionId } = this.props;
this.subData([
{
entity: 'sessionMessage',
filter: {
sessionId: sessionId,
},
id: `${DATA_SUBSCRIBER_KEYS.sessionMessageList}-${sessionId}`,
}
]);
// const userId = this.features.token.getUserId(true);
// const applicationId = this.features.application.getApplicationId();
// if (!sessionId) {
// const entity = 'application';
// const entityId = applicationId;
// const type = 'web';
// const { result: newSessionId } = await this.features.cache.exec('createSession', { type, entity, entityId });
// this.setState({
// newSessionId,
// })
// }
// if (!userId) {
// this.redirectTo(
// {
// url: '/login',
// backUrl: encodeURIComponent(window.location.href),
// },
// undefined,
// true
// );
// return;
// }
// (this as any).timer = setInterval(() => {
// this.refresh();
// }, 2000);
this.getConversationInfo();
},
detached() {
if (this.timer) {
clearInterval(this.timer);
}
const { sessionId } = this.props;
this.unSubData([
`${DATA_SUBSCRIBER_KEYS.sessionMessageList}-${sessionId}`
]);
},
},
listeners: {
num(prev, next) {
if (prev.num !== next.num) {
if (next.num > 0 && next.num <= 20) {
this.pageScroll('comment');
}
}
},
sessionId(prev, next) {
if (this.state.oakFullpath) {
if (prev.sessionId !== next.sessionId) {
if (next.sessionId) {
this.getConversationInfo();
// 如果sessionId变了需要重新刷新下
this.refresh();
}
}
}
},
},
formData({ data: sessionMessageList = [], features }) {
return {
sessionMessageList,
num: sessionMessageList?.length,
};
},
properties: {
sessionId: '',
isEntity: false,
dialog: false,
entity: '',
entityId: '',
},
filters: [
{
filter() {
const { sessionId } = this.props;
return {
sessionId,
// type: {
// $exists: true,
// },
};
},
},
],
sorters: [
{
sorter: {
$attr: {
$$createAt$$: 1,
},
$direction: 'desc',
},
},
],
data: {
content: '',
buttonHidden: true,
selectedTradeId: '',
newSessionId: '',
},
methods: {
setContent(text) {
this.setState({
text,
});
},
setButtonHidden(isHidden) {
this.setState({
buttonHidden: isHidden,
});
},
async getConversationInfo() {
const { sessionId } = this.props;
if (!sessionId) {
return;
}
const { data: [session], } = await this.features.cache.refresh('session', {
data: {
id: 1,
entity: 1,
entityId: 1,
userId: 1,
user: {
id: 1,
name: 1,
nickname: 1,
mobile$user: {
$entity: 'mobile',
data: {
id: 1,
mobile: 1,
userId: 1,
},
},
extraFile$entity: {
$entity: 'extraFile',
data: {
id: 1,
tag1: 1,
origin: 1,
bucket: 1,
objectId: 1,
filename: 1,
extra1: 1,
extension: 1,
type: 1,
entity: 1,
entityId: 1,
},
filter: {
tag1: {
$in: ['avatar'],
},
},
},
},
},
filter: {
id: sessionId,
},
});
this.setState({
entity: session?.entity,
entityId: session?.entityId,
});
},
pageScroll(id) {
const doc = window.document.getElementById(id);
setTimeout(() => doc.scrollTo(0, 10000), 500);
},
async createMessage() {
const { text, wechatUserId, newSessionId } = this.state;
const { sessionId, isEntity } = this.props;
const userId = this.features.token.getUserId();
const applicationId = this.features.application.getApplicationId();
if (!this.state.text) {
this.setMessage({
type: 'warning',
content: '请输入内容',
});
return;
}
this.addItem({
applicationId,
text,
userId,
wechatUserId,
sessionId: sessionId || newSessionId,
type: 'text',
createTime: Date.now(),
aaoe: isEntity,
});
await this.execute(undefined, false);
this.setState({
text: '',
});
this.pageScroll('comment');
},
async customUpload(file) {
const { sessionId } = this.props;
// TS 语法
// file 即选中的文件
const { name, size, type, originFileObj } = file;
const extension = name.substring(name.lastIndexOf('.') + 1);
const filename = name.substring(0, name.lastIndexOf('.'));
const extraFile = {
extra1: originFileObj,
origin: 'qiniu',
type: 'image',
tag1: 'image',
objectId: generateNewId(),
filename,
fileType: type,
size,
extension,
entity: 'wechatMessage',
bucket: '',
id: generateNewId(),
};
// try {
// // 自己实现上传,并得到图片 url alt href
// const { url, bucket } = await this.features.extraFile.upload(
// extraFile
// );
// extraFile.bucket = bucket;
// extraFile.extra1 = null;
// const userId = this.features.token.getUserId();
// this.addItem({
// id: generateNewId(),
// sessionId,
// type: 'image',
// extraFile$entity: [
// {
// id: generateNewId(),
// action: 'create',
// data: extraFile,
// },
// ],
// } as EntityDict['sessionMessage']['CreateSingle']['data']);
// await this.execute(undefined, false);
// } catch (err) {
// throw err;
// }
},
},
});

View File

@ -0,0 +1,5 @@
{
"navigationBarTitleText": "消息",
"enablePullDownRefresh": false,
"usingComponents": {}
}

View File

@ -0,0 +1,114 @@
/** index.wxss **/
.container {
display: flex;
flex-direction: column;
height: 100vh;
width: 100%;
position: relative;
background: var(--oak-bg-color-page);
.inner {
display: flex;
overflow: scroll;
flex-direction: column;
margin-top: 50px;
overflow-x: hidden;
}
.bottom {
background: var(--oak-bg-color-page);
display: flex;
width: 100%;
flex-direction: column;
position: fixed;
bottom: 0;
margin: 0px;
position: absolute;
z-index: 100;
.textareaBox {
border-top: 1px solid var(--oak-border-color);
border-bottom: 1px solid var(--oak-border-color);
display: flex;
// background: var(--oak-bg-color-container);
flex-direction: row;
align-items: center;
min-height: 45px;
.plusIcon {
font-size: 24px;
}
.textarea {
margin: 5px;
border: none;
outline: none;
}
.textarea:focus {
border: none;
box-shadow: none;
}
.action {
display: flex;
flex-direction: row-reverse;
margin: 5px;
}
}
.toolbar {
display: flex;
flex-direction: row;
align-items: center;
padding: 10px;
.button {
display: flex;
flex-direction: column;
align-items: center;
margin: 5px;
.iconBox {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #fff;
border-radius: 4px;
height: 50px;
width: 50px;
.icon {
font-size: 24px;
color: var(--oak-text-color-primary);
}
}
.text {
margin-top: 4px;
font-size: 12px;
color: var(--oak-text-color-primary);
}
}
}
}
}
.popup_title {
height: 50px;
display: flex;
flex-direction: column;
padding: 0 10px;
justify-content: center;
.title {
font-size: 16px;
}
}

View File

View File

@ -0,0 +1,288 @@
"use strict";
// import React, { useState, useEffect } from 'react';
// import { Button, Image, Popup } from 'antd-mobile';
// import { Input, Upload, Popover, Tag } from 'antd';
// import {
// PlusCircleOutlined,
// PictureFilled,
// BookFilled,
// CloseOutlined,
// } from '@ant-design/icons';
// import ConversationMessageCell from '@project/components/conversationMessage/cell';
// import ConversationHeader from '@project/components/conversation/forConversationMessage';
// import SendTradeCard from '@project/components/trade/detail/sendCard';
// import SendSkuCard from '@project/components/sku/sendSkuCard';
// import TradeList from '@project/pages/trade/byConversation/list';
// import Style from './mobile.module.less';
// import { WebComponentProps } from 'oak-frontend-base';
// import { EntityDict } from '@oak-app-domain';
// interface CustomFile {
// name: string;
// size: number;
// type: string;
// originFileObj: File;
// }
// export default function Render(
// props: WebComponentProps<
// EntityDict,
// 'conversationMessage',
// true,
// {
// conversationMessageList: EntityDict['conversationMessage']['Schema'][];
// content: string;
// buttonHidden: boolean;
// selectedTradeId: string;
// conversationId: string;
// userType: string;
// isCombine: boolean;
// companyId: string;
// employerId: string;
// tradeId: string;
// skuId: string;
// },
// {
// setButtonHidden: (isHidden: boolean) => void;
// customUpload: (file: CustomFile) => void;
// createTradeMessage: (id: string) => void;
// createSkuMessage: (id: string) => void;
// setContent: (content: string) => void;
// pageScroll: (id: string) => void;
// createMessage: () => void;
// }
// >
// ) {
// const { data, methods } = props;
// const {
// oakFullpath,
// oakPagination,
// oakLoading,
// oakExecuting,
// conversationId,
// userType,
// conversationMessageList,
// selectedTradeId,
// content,
// isCombine,
// buttonHidden,
// companyId,
// employerId,
// tradeId,
// skuId,
// } = data;
// const {
// setButtonHidden,
// customUpload,
// createTradeMessage,
// createSkuMessage,
// setContent,
// pageScroll,
// createMessage,
// } = methods;
// const { pageSize, total, currentPage } = oakPagination || {};
// const [bottomHeight, setBottomHeight] = useState(0);
// const [tradeListVisible, setTradeListVisible] = useState(false);
// const [sendTdOpen, setSendTdOpen] = useState(true);
// const [showCard, setShowCard] = useState(true);
// const [showCard1, setShowCard1] = useState(true);
// useEffect(() => {
// if (buttonHidden) {
// const dom = window.document.getElementById('bottom');
// const newBottomHeight = dom && dom.offsetHeight || 0;
// setBottomHeight(newBottomHeight);
// } else {
// setBottomHeight(0);
// }
// }, [buttonHidden]);
// return conversationId ? (
// <div className={Style.container}>
// <ConversationHeader
// showBack={!isCombine}
// userType={userType}
// conversationId={conversationId}
// userId={employerId}
// />
// <div
// className={Style.inner}
// style={{
// marginBottom: bottomHeight ? `${bottomHeight}px` : '45px',
// }}
// id="comment"
// onClick={() => setButtonHidden(true)}
// >
// {conversationMessageList
// ?.sort(
// (a, b) =>
// (a.$$createAt$$ as number) -
// (b.$$createAt$$ as number)
// )
// .map((conversationMessage, index: number) => {
// return (
// <ConversationMessageCell
// key={conversationMessage.id}
// oakId={conversationMessage.id}
// oakPath={
// oakFullpath
// ? `${oakFullpath}.${conversationMessage.id}`
// : undefined
// }
// userType={userType}
// />
// );
// })}
// </div>
// <div className={Style.bottom} id="bottom">
// {tradeId && showCard && (
// <SendTradeCard
// conversationId={conversationId}
// userType={userType}
// setShowCard={() => {
// setShowCard(false);
// }}
// setBottomHeight={() => {
// setBottomHeight(0);
// }}
// oakId={tradeId}
// oakAutoUnmount={true}
// oakPath={
// data.oakFullpath
// ? `conversationMessage/list/trade/detail/sendCard`
// : undefined
// }
// createTradeMessage={() => {
// createTradeMessage(tradeId);
// }}
// />
// )}
// {skuId && showCard1 && (
// <SendSkuCard
// conversationId={conversationId}
// userType={userType}
// setShowCard1={() => {
// setShowCard1(false);
// }}
// setBottomHeight={() => {
// setBottomHeight(0);
// }}
// oakId={skuId}
// oakAutoUnmount={true}
// oakPath={
// data.oakFullpath
// ? `conversationMessage/list/sku/sendSkuCard`
// : undefined
// }
// createSkuMessage={() => {
// createSkuMessage(skuId);
// }}
// />
// )}
// <div className={Style.textareaBox}>
// <Input.TextArea
// className={Style.textarea}
// rows={1}
// onChange={({ target: { value } }) => {
// setContent(value);
// }}
// onFocus={() => {
// setButtonHidden(true);
// setShowCard(false);
// setBottomHeight(0);
// }}
// value={content}
// />
// <div className={Style.action}>
// {content && (
// <Button
// color="primary"
// fill="solid"
// size="middle"
// disabled={!content}
// onClick={() => {
// createMessage();
// pageScroll('comment');
// }}
// style={{ width: '56px', fontSize: '14px' }}
// >
// 发送
// </Button>
// )}
// {!content && (
// <PlusCircleOutlined
// className={Style.plusIcon}
// onClick={() => {
// setButtonHidden(false);
// setShowCard(false);
// }}
// />
// )}
// </div>
// </div>
// {!buttonHidden && (
// <div className={Style.toolbar}>
// <div className={Style.button}>
// <Upload
// accept={'image/*'}
// multiple={false}
// showUploadList={false}
// onChange={({ file }) => {
// customUpload(file as CustomFile);
// }}
// >
// <div className={Style.iconBox}>
// <PictureFilled className={Style.icon} />
// </div>
// </Upload>
// <div className={Style.text}>图片</div>
// </div>
// {['company', 'employer'].includes(userType) && (
// <>
// <div
// className={Style.button}
// onClick={() => {
// setTradeListVisible(true);
// }}
// >
// <div className={Style.iconBox}>
// <BookFilled className={Style.icon} />
// </div>
// <div className={Style.text}>订单</div>
// </div>
// <Popup
// visible={tradeListVisible}
// showCloseButton={true}
// onMaskClick={() => {
// setTradeListVisible(false);
// }}
// onClose={() => {
// setTradeListVisible(false);
// }}
// >
// <div className={Style.popup_title}>
// <span className={Style.title}>
// 选择订单
// </span>
// </div>
// <TradeList
// companyId={companyId}
// userId={employerId}
// oakAutoUnmount={true}
// oakPath={
// oakFullpath
// ? '$$conversation-message/trade'
// : ''
// }
// setTradeId={(id: string) => {
// setTradeListVisible(false);
// createTradeMessage(id);
// }}
// />
// </Popup>
// </>
// )}
// </div>
// )}
// </div>
// </div>
// ) : (
// <div className={Style.background}></div>
// );
// }

View File

@ -0,0 +1,77 @@
/** index.wxss **/
.container {
display: flex;
flex: 1;
height: 100%;
// width: 100%;
flex-direction: column;
position: relative;
background: var(--oak-bg-color-page);
.inner {
display: flex;
overflow: scroll;
flex-direction: column;
// margin-top: 50px;
overflow-x: hidden;
height: 100%;
}
.bottomSku {
width: calc(100% - 16px);
// position: fixed;
bottom: 176px;
z-index: 1000;
position: absolute;
}
.bottom {
border-top: 1px solid var(--oak-border-color);
background: var(--oak-bg-color-container);
display: flex;
width: 100%;
flex-direction: column;
position: fixed;
bottom: 0;
margin: 0px;
position: absolute;
z-index: 100;
.toolbar {
display: flex;
flex-direction: row;
align-items: center;
height: 30px;
.icon {
margin: 0 6px;
font-size: 20px;
color: var(--oak-text-color-secondary);
}
}
.textareaBox {
display: flex;
flex-direction: column;
padding: 0 10px;
.textarea {
border: none;
outline: none;
}
.textarea:focus {
border: none;
box-shadow: none;
}
.btn {
display: flex;
flex-direction: row;
justify-content: flex-end;
margin: 5px 0;
}
}
}
}

View File

@ -0,0 +1,23 @@
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
interface customFile {
name: string;
size: number;
type: string;
originFileObj: File;
}
export default function Render(props: WebComponentProps<EntityDict, 'sessionMessage', true, {
sessionMessageList: EntityDict['sessionMessage']['Schema'][];
text: string;
buttonHidden: boolean;
sessionId: string;
isEntity: boolean;
employerId: string;
}, {
setButtonHidden: (isHidden: boolean) => void;
customUpload: (file: customFile) => void;
setContent: (text: string) => void;
pageScroll: (id: string) => void;
createMessage: () => void;
}>): import("react/jsx-runtime").JSX.Element;
export {};

View File

@ -0,0 +1,44 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useEffect } from 'react';
import { Button, Input, Upload } from 'antd';
import { PictureOutlined } from '@ant-design/icons';
import MessageCell from '../../../components/sessionMessage/cell';
import Style from './web.module.less';
export default function Render(props) {
const { data, methods } = props;
const { sessionId, isEntity, sessionMessageList, oakFullpath, text, employerId, buttonHidden, } = data;
const { setButtonHidden, customUpload, setContent, pageScroll, createMessage, } = methods;
const [bottomHeight, setBottomHeight] = useState(0);
useEffect(() => {
if (buttonHidden) {
const newBottomHeight = window.document.getElementById('bottom')?.offsetHeight;
setBottomHeight(newBottomHeight);
}
else {
setBottomHeight(0);
}
}, [buttonHidden]);
return (_jsxs("div", { className: Style.container, children: [_jsx("div", { className: Style.inner, style: {
marginBottom: bottomHeight ? `${bottomHeight}px` : '168px',
}, id: "comment", onClick: () => setButtonHidden(true), children: sessionMessageList
?.sort((a, b) => a.$$createAt$$ -
b.$$createAt$$)
.map((sessionMessage, index) => {
return (_jsx(MessageCell, { oakId: sessionMessage.id, oakPath: oakFullpath
? `${oakFullpath}.${sessionMessage.id}`
: '', isEntity: isEntity }, sessionMessage.id));
}) }), _jsxs("div", { className: Style.bottom, id: "bottom", children: [_jsx("div", { className: Style.toolbar, children: _jsx(Upload, { accept: 'image/*', multiple: false, showUploadList: false, customRequest: () => { }, onChange: ({ file }) => {
customUpload(file);
}, children: _jsx(PictureOutlined, { className: Style.icon }) }) }), _jsxs("div", { className: Style.textareaBox, children: [_jsx(Input.TextArea, { className: Style.textarea, rows: 5, onChange: (e) => {
setContent(e.target.value);
}, onFocus: () => {
setButtonHidden(true);
}, onPressEnter: (e) => {
e.preventDefault();
createMessage();
pageScroll('comment');
}, value: text }), _jsx("div", { className: Style.btn, children: _jsx(Button, { type: "primary", disabled: text ? false : true, onClick: () => {
createMessage();
pageScroll('comment');
}, children: "\u53D1\u9001" }) })] })] })] }));
}

View File

@ -9,3 +9,6 @@ export declare const LOCAL_STORAGE_KEYS: {
appId: string;
token: string;
};
export declare const DATA_SUBSCRIBER_KEYS: {
sessionMessageList: string;
};

View File

@ -13,3 +13,6 @@ export const LOCAL_STORAGE_KEYS = {
appId: 'ogb:f-application-id',
token: 'ogb:f-token-token',
};
export const DATA_SUBSCRIBER_KEYS = {
sessionMessageList: 'sessionM-l',
};

View File

@ -21,7 +21,7 @@ export const SelectFreeEntities = [
'mobile',
'wechatQrCode',
'wechatLogin',
'messageTypeTemplateId',
'messageTypeTemplate',
'articleMenu',
'article',
];

View File

@ -3,9 +3,10 @@ import URL from 'url';
import sha1 from 'sha1';
import x2js from 'x2js';
import { WechatSDK, } from 'oak-external-sdk';
import { expandUuidTo36Bytes, generateNewIdAsync, } from 'oak-domain/lib/utils/uuid';
import { expandUuidTo36Bytes, generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
import { composeDomainUrl } from '../utils/domain';
import { composeUrl } from 'oak-domain/lib/utils/url';
import { createSession } from '../aspects/session';
const X2Js = new x2js();
function assertFromWeChat(query, config) {
const { signature, nonce, timestamp } = query;
@ -540,6 +541,12 @@ function onWeChatPublicEvent(data, context) {
contentType: 'application/xml',
};
}
function onWeChatMpEvent(data, context) {
const content = createSession({ data, type: 'wechatMp' }, context);
return {
content: 'success'
};
}
const endpoints = {
wechatPublicEvent: [
{
@ -597,5 +604,70 @@ const endpoints = {
},
},
],
wechatMpEvent: [{
name: '微信小程序回调接口',
method: 'post',
params: ['appId'],
fn: async (context, params, headers, req, body) => {
const { appId } = params;
if (!appId || appId === '20230210') {
console.error('applicationId参数不存在');
console.log(JSON.stringify(body));
return '';
}
await context.setApplication(appId);
const application = context.getApplication();
const { config } = application;
const { server } = config;
if (!server) {
throw new Error(`请配置:“微信小程序-服务器配置”`);
}
if (server?.dataFormat === 'json') {
const { content } = onWeChatMpEvent(body, context);
return content;
}
else {
const { xml: data } = X2Js.xml2js(body);
const { content } = onWeChatMpEvent(data, context);
return content;
}
},
}, {
name: '微信小程序验证接口',
method: 'get',
params: ['appId'],
fn: async (context, params, body, req, headers) => {
const { searchParams } = new URL.URL(`http://${req.headers.host}${req.url}`);
const { appId } = params;
if (!appId || appId === '20230210') {
console.error('applicationId参数不存在');
const echostr = searchParams.get('echostr');
return echostr;
}
const [application] = await context.select('application', {
data: {
id: 1,
config: 1,
},
filter: {
id: appId,
},
}, {});
if (!application) {
throw new Error(`未找到${appId}对应的app`);
}
const signature = searchParams.get('signature');
const timestamp = searchParams.get('timestamp');
const nonce = searchParams.get('nonce');
const isWeChat = assertFromWeChat({ signature, timestamp, nonce }, application.config);
if (isWeChat) {
const echostr = searchParams.get('echostr');
return echostr;
}
else {
throw new Error('Verify Failed');
}
},
}],
};
export default endpoints;

7
es/entities/ReadRemark.d.ts vendored Normal file
View File

@ -0,0 +1,7 @@
import { EntityShape } from 'oak-domain/lib/types/Entity';
import { Schema as Session } from './Session';
import { Schema as User } from './User';
export interface Schema extends EntityShape {
user: User;
session: Session;
}

13
es/entities/ReadRemark.js Normal file
View File

@ -0,0 +1,13 @@
;
const entityDesc = {
locales: {
zh_CN: {
name: '会话',
attr: {
user: '当前用户',
session: '会话',
},
},
}
};
export {};

View File

@ -1,7 +1,10 @@
import { String } from 'oak-domain/lib/types/DataType';
import { String, Datetime } from 'oak-domain/lib/types/DataType';
import { EntityShape } from 'oak-domain/lib/types/Entity';
import { Schema as User } from './User';
export interface Schema extends EntityShape {
entity: String<32>;
entityId: String<64>;
user?: User;
lmts?: Datetime;
}
export type Relation = 'owner';
export type Relation = 'partner';

View File

@ -6,9 +6,11 @@ const entityDesc = {
attr: {
entity: '关联对象',
entityId: '关联对象id',
user: '发送者',
lmts: '最后一条消息的发送时间',
},
r: {
owner: '所有者',
partner: '所有者',
}
},
}

View File

@ -14,6 +14,7 @@ const entityDesc = {
files: '文件',
news: '文章',
aaoe: '作为实体的发起者',
// isRead: '是否已读'
},
v: {
type: {

View File

@ -4,14 +4,19 @@ export default function useMyInfo() {
const features = useFeatures();
const getMyInfo = () => {
const userInfo = features.token.getUserInfo();
const mobile = userInfo?.mobile$user && userInfo?.mobile$user[0]?.mobile || '';
const { mobile } = (userInfo?.mobile$user && userInfo?.mobile$user[0]) ||
(userInfo?.user$ref &&
userInfo?.user$ref[0] &&
userInfo?.user$ref[0].mobile$user &&
userInfo?.user$ref[0].mobile$user[0]) ||
{};
const extraFile = userInfo?.extraFile$entity?.find((ele) => ele.tag1 === 'avatar');
const avatarUrl = features.extraFile.getUrl(extraFile);
return {
avatarUrl,
name: userInfo?.name || '',
nickname: userInfo?.nickname || '',
mobile,
mobile: mobile || '',
};
};
const myInfo = getMyInfo();

View File

@ -28,12 +28,12 @@ export const desc = {
name: 'index_entity_relation',
attributes: [
{
name: 'destEntity',
name: 'destEntity'
},
{
name: "relationId",
name: "relationId"
},
],
]
}
]
};

View File

@ -2,9 +2,9 @@ const IActionDef = {
stm: {
send: ['unsent', 'sending'],
success: ['sending', 'sent'],
fail: ['sending', 'failure'],
fail: ['sending', 'failure']
},
is: 'unsent',
is: 'unsent'
};
export const actions = ["count", "stat", "download", "select", "aggregate", "create", "remove", "update", "send", "success", "fail"];
export const ActionDefDict = {

View File

@ -52,17 +52,17 @@ export const desc = {
attributes: [
{
name: 'mobile',
direction: 'ASC',
direction: 'ASC'
},
{
name: 'code',
direction: 'ASC',
direction: 'ASC'
},
{
name: '$$createAt$$',
direction: 'DESC',
direction: 'DESC'
}
],
]
}
]
};

View File

@ -26,13 +26,13 @@ export const desc = {
attributes: [
{
name: 'email',
direction: 'ASC',
direction: 'ASC'
},
{
name: 'ableState',
direction: 'ASC',
direction: 'ASC'
}
],
]
}
]
};

View File

@ -28,6 +28,7 @@ import { EntityDef as Mobile } from "./Mobile/Schema";
import { EntityDef as Notification } from "./Notification/Schema";
import { EntityDef as Parasite } from "./Parasite/Schema";
import { EntityDef as Platform } from "./Platform/Schema";
import { EntityDef as ReadRemark } from "./ReadRemark/Schema";
import { EntityDef as Session } from "./Session/Schema";
import { EntityDef as SessionMessage } from "./SessionMessage/Schema";
import { EntityDef as Station } from "./Station/Schema";
@ -76,6 +77,7 @@ export type EntityDict = {
notification: Notification;
parasite: Parasite;
platform: Platform;
readRemark: ReadRemark;
session: Session;
sessionMessage: SessionMessage;
station: Station;

View File

@ -42,15 +42,15 @@ export const desc = {
name: 'namespace_language',
attributes: [
{
name: 'namespace',
name: 'namespace'
},
{
name: 'language',
name: 'language'
}
],
config: {
unique: true,
},
unique: true
}
}
]
};

View File

@ -2,14 +2,14 @@ export const actions = ["count", "stat", "download", "select", "aggregate", "cre
const IActionDef = {
stm: {
succeed: ['sending', 'success'],
fail: ['sending', 'failure'],
},
fail: ['sending', 'failure']
}
};
const VisitActionDef = {
stm: {
visit: ['unvisited', 'visited'],
visit: ['unvisited', 'visited']
},
is: 'unvisited',
is: 'unvisited'
};
export const ActionDefDict = {
iState: IActionDef,

View File

@ -25,13 +25,13 @@ export const desc = {
attributes: [
{
name: 'mobile',
direction: 'ASC',
direction: 'ASC'
},
{
name: 'ableState',
direction: 'ASC',
direction: 'ASC'
}
],
]
}
]
};

View File

@ -1,9 +1,9 @@
const IActionDef = {
stm: {
apply: ['active', 'applied'],
abandon: ['active', 'abandoned'],
abandon: ['active', 'abandoned']
},
is: 'active',
is: 'active'
};
export const actions = ["count", "stat", "download", "select", "aggregate", "create", "remove", "update", "apply", "abandon"];
export const ActionDefDict = {

View File

@ -52,9 +52,9 @@ export const desc = {
attributes: [
{
name: 'iState',
direction: 'ASC',
direction: 'ASC'
}
],
]
}
]
};

View File

@ -2,9 +2,9 @@ export const actions = ["count", "stat", "download", "select", "aggregate", "cre
const IActionDef = {
stm: {
succeed: ['sending', 'success'],
fail: ['sending', 'failure'],
fail: ['sending', 'failure']
},
is: 'sending',
is: 'sending'
};
export const ActionDefDict = {
iState: IActionDef

View File

@ -361,7 +361,7 @@ export type UpdateOperationData = FormUpdateData<Omit<OpSchema, "entity" | "enti
entity?: never;
} | {
entity?: ("user" | "userEntityGrant" | "userSystem" | "userWechatPublicTag" | "wechatLogin" | "wechatMenu" | "wechatPublicAutoReply" | "wechatPublicTag" | "wechatPublicTemplate" | "wechatQrCode" | "wechatUser" | string) | null;
entityId?: ForeignKey<"User" | "UserEntityGrant" | "UserSystem" | "UserWechatPublicTag" | "WechatLogin" | "WechatMenu" | "wechatPublicAutoReply" | "WechatPublicTag" | "wechatPublicTemplate" | "WechatQrCode" | "WechatUser"> | null;
entityId?: ForeignKey<"User" | "UserEntityGrant" | "UserSystem" | "UserWechatPublicTag" | "WechatLogin" | "WechatMenu" | "wechatPublicAutoReply" | "WechatPublicTag" | "WechatPublicTemplate" | "WechatQrCode" | "WechatUser"> | null;
}) & {
[k: string]: any;
};

152
es/oak-app-domain/ReadRemark/Schema.d.ts vendored Normal file
View File

@ -0,0 +1,152 @@
import { ForeignKey } from "oak-domain/lib/types/DataType";
import { Q_DateValue, Q_StringValue, NodeId, MakeFilter, ExprOp, ExpressionKey } from "oak-domain/lib/types/Demand";
import { OneOf } from "oak-domain/lib/types/Polyfill";
import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOperation, Selection as OakSelection, MakeAction as OakMakeAction } from "oak-domain/lib/types/Entity";
import { GenericAction } from "oak-domain/lib/actions/action";
import { EntityShape } from "oak-domain/lib/types/Entity";
import * as User from "../User/Schema";
import * as Session from "../Session/Schema";
export type OpSchema = EntityShape & {
userId: ForeignKey<"user">;
sessionId: ForeignKey<"session">;
};
export type OpAttr = keyof OpSchema;
export type Schema = EntityShape & {
userId: ForeignKey<"user">;
sessionId: ForeignKey<"session">;
user: User.Schema;
session: Session.Schema;
} & {
[A in ExpressionKey]?: any;
};
type AttrFilter = {
id: Q_StringValue;
$$createAt$$: Q_DateValue;
$$seq$$: Q_StringValue;
$$updateAt$$: Q_DateValue;
userId: Q_StringValue;
user: User.Filter;
sessionId: Q_StringValue;
session: Session.Filter;
};
export type Filter = MakeFilter<AttrFilter & ExprOp<OpAttr | string>>;
export type Projection = {
"#id"?: NodeId;
[k: string]: any;
id?: number;
$$createAt$$?: number;
$$updateAt$$?: number;
$$seq$$?: number;
userId?: number;
user?: User.Projection;
sessionId?: number;
session?: Session.Projection;
} & Partial<ExprOp<OpAttr | string>>;
type ReadRemarkIdProjection = OneOf<{
id: number;
}>;
type UserIdProjection = OneOf<{
userId: number;
}>;
type SessionIdProjection = OneOf<{
sessionId: number;
}>;
export type SortAttr = {
id: number;
} | {
$$createAt$$: number;
} | {
$$seq$$: number;
} | {
$$updateAt$$: number;
} | {
userId: number;
} | {
user: User.SortAttr;
} | {
sessionId: number;
} | {
session: Session.SortAttr;
} | {
[k: string]: any;
} | OneOf<ExprOp<OpAttr | string>>;
export type SortNode = {
$attr: SortAttr;
$direction?: "asc" | "desc";
};
export type Sorter = SortNode[];
export type SelectOperation<P extends Object = Projection> = OakSelection<"select", P, Filter, Sorter>;
export type Selection<P extends Object = Projection> = SelectOperation<P>;
export type Aggregation = DeduceAggregation<Projection, Filter, Sorter>;
export type CreateOperationData = FormCreateData<Omit<OpSchema, "userId" | "sessionId">> & (({
userId?: never;
user: User.CreateSingleOperation;
} | {
userId: ForeignKey<"user">;
user?: User.UpdateOperation;
} | {
userId: ForeignKey<"user">;
}) & ({
sessionId?: never;
session: Session.CreateSingleOperation;
} | {
sessionId: ForeignKey<"session">;
session?: Session.UpdateOperation;
} | {
sessionId: ForeignKey<"session">;
}));
export type CreateSingleOperation = OakOperation<"create", CreateOperationData>;
export type CreateMultipleOperation = OakOperation<"create", Array<CreateOperationData>>;
export type CreateOperation = CreateSingleOperation | CreateMultipleOperation;
export type UpdateOperationData = FormUpdateData<Omit<OpSchema, "userId" | "sessionId">> & (({
user: User.CreateSingleOperation;
userId?: never;
} | {
user: User.UpdateOperation;
userId?: never;
} | {
user: User.RemoveOperation;
userId?: never;
} | {
user?: never;
userId?: ForeignKey<"user"> | null;
}) & ({
session: Session.CreateSingleOperation;
sessionId?: never;
} | {
session: Session.UpdateOperation;
sessionId?: never;
} | {
session: Session.RemoveOperation;
sessionId?: never;
} | {
session?: never;
sessionId?: ForeignKey<"session"> | null;
})) & {
[k: string]: any;
};
export type UpdateOperation = OakOperation<"update" | string, UpdateOperationData, Filter, Sorter>;
export type RemoveOperationData = {} & (({
user?: User.UpdateOperation | User.RemoveOperation;
}) & ({
session?: Session.UpdateOperation | Session.RemoveOperation;
}));
export type RemoveOperation = OakOperation<"remove", RemoveOperationData, Filter, Sorter>;
export type Operation = CreateOperation | UpdateOperation | RemoveOperation;
export type UserIdSubQuery = Selection<UserIdProjection>;
export type SessionIdSubQuery = Selection<SessionIdProjection>;
export type ReadRemarkIdSubQuery = Selection<ReadRemarkIdProjection>;
export type EntityDef = {
Schema: Schema;
OpSchema: OpSchema;
Action: OakMakeAction<GenericAction> | string;
Selection: Selection;
Aggregation: Aggregation;
Operation: Operation;
Create: CreateOperation;
Update: UpdateOperation;
Remove: RemoveOperation;
CreateSingle: CreateSingleOperation;
CreateMulti: CreateMultipleOperation;
};
export {};

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,3 @@
import { StorageDesc } from "oak-domain/lib/types/Storage";
import { OpSchema } from "./Schema";
export declare const desc: StorageDesc<OpSchema>;

View File

@ -0,0 +1,17 @@
import { genericActions as actions } from "oak-domain/lib/actions/action";
export const desc = {
attributes: {
userId: {
notNull: true,
type: "ref",
ref: "user"
},
sessionId: {
notNull: true,
type: "ref",
ref: "session"
}
},
actionType: "crud",
actions
};

View File

@ -0,0 +1 @@
{ "name": "会话", "attr": { "user": "当前用户", "session": "会话" } }

View File

@ -3,6 +3,7 @@ export const ActionCascadePathGraph = [
["email", "user", "email", false],
["extraFile", "user", "extraFile", false],
["extraFile", "sessionMessage.session", "session", true],
["extraFile", "sessionMessage.session.user", "session", false],
["extraFile", "sessionMessage.user", "sessionMessage", false],
["extraFile", "sessionMessage.wechatUser.user", "wechatUser", false],
["message", "user", "message", false],
@ -10,8 +11,13 @@ export const ActionCascadePathGraph = [
["mobile", "user", "mobile", false],
["notification", "messageSystem.message.user", "message", false],
["parasite", "user", "parasite", false],
["readRemark", "user", "readRemark", false],
["readRemark", "session", "session", true],
["readRemark", "session.user", "session", false],
["session", "", "session", true],
["session", "user", "session", false],
["sessionMessage", "session", "session", true],
["sessionMessage", "session.user", "session", false],
["sessionMessage", "user", "sessionMessage", false],
["sessionMessage", "wechatUser.user", "wechatUser", false],
["token", "email.user", "email", false],
@ -21,12 +27,14 @@ export const ActionCascadePathGraph = [
["token", "player", "token", false],
["token", "wechatUser.user", "wechatUser", false],
["userEntityGrant", "session", "session", true],
["userEntityGrant", "session.user", "session", false],
["userEntityGrant", "granter", "userEntityGrant", false],
["userEntityGrant", "grantee", "userEntityGrant", false],
["userSystem", "user", "userSystem", false],
["userWechatPublicTag", "wechatUser.user", "wechatUser", false],
["wechatLogin", "user", "wechatLogin", false],
["wechatQrCode", "userEntityGrant.session", "session", true],
["wechatQrCode", "userEntityGrant.session.user", "session", false],
["wechatQrCode", "userEntityGrant.granter", "userEntityGrant", false],
["wechatQrCode", "userEntityGrant.grantee", "userEntityGrant", false],
["wechatQrCode", "wechatLogin.user", "wechatLogin", false],
@ -34,13 +42,14 @@ export const ActionCascadePathGraph = [
["wechatUser", "user", "wechatUser", false]
];
export const RelationCascadePathGraph = [
["session", "user", "session", false],
["session", "", "session", true]
];
export const relations = [
{
id: "session-owner",
id: "session-partner",
entity: "session",
name: "owner"
name: "partner"
}
];
export const deducedRelationMap = {};

View File

@ -35,18 +35,18 @@ export const desc = {
name: 'index_targetEntity_entityId_name',
attributes: [
{
name: 'entity',
name: 'entity'
},
{
name: 'entityId',
name: 'entityId'
},
{
name: 'name',
name: 'name'
}
],
config: {
unique: true,
},
unique: true
}
}
]
};

View File

@ -26,18 +26,18 @@ export const desc = {
name: 'index_entity_relation_path',
attributes: [
{
name: "sourceRelationId",
name: "sourceRelationId"
},
{
name: 'path',
name: 'path'
},
{
name: "destRelationId",
name: "destRelationId"
},
],
config: {
unique: true,
},
unique: true
}
}
]
};

View File

@ -3,9 +3,11 @@ import { Q_DateValue, Q_StringValue, Q_EnumValue, NodeId, MakeFilter, ExprOp, Ex
import { OneOf } from "oak-domain/lib/types/Polyfill";
import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOperation, Selection as OakSelection, MakeAction as OakMakeAction, AggregationResult } from "oak-domain/lib/types/Entity";
import { GenericAction, RelationAction } from "oak-domain/lib/actions/action";
import { String } from "oak-domain/lib/types/DataType";
import { String, Datetime } from "oak-domain/lib/types/DataType";
import { EntityShape } from "oak-domain/lib/types/Entity";
import * as User from "../User/Schema";
import * as Application from "../Application/Schema";
import * as ReadRemark from "../ReadRemark/Schema";
import * as SessionMessage from "../SessionMessage/Schema";
import * as UserEntityGrant from "../UserEntityGrant/Schema";
import * as Relation from "../Relation/Schema";
@ -13,12 +15,19 @@ import * as UserRelation from "../UserRelation/Schema";
export type OpSchema = EntityShape & {
entity: "application" | string;
entityId: String<64>;
userId?: ForeignKey<"user"> | null;
lmts?: Datetime | null;
};
export type OpAttr = keyof OpSchema;
export type Schema = EntityShape & {
entity: "application" | string;
entityId: String<64>;
userId?: ForeignKey<"user"> | null;
lmts?: Datetime | null;
user?: User.Schema | null;
application?: Application.Schema;
readRemark$session?: Array<ReadRemark.Schema>;
readRemark$session$$aggr?: AggregationResult<ReadRemark.Schema>;
sessionMessage$session?: Array<SessionMessage.Schema>;
sessionMessage$session$$aggr?: AggregationResult<SessionMessage.Schema>;
userEntityGrant$entity?: Array<UserEntityGrant.Schema>;
@ -37,7 +46,11 @@ type AttrFilter = {
$$updateAt$$: Q_DateValue;
entity: Q_EnumValue<"application" | string>;
entityId: Q_StringValue;
userId: Q_StringValue;
user: User.Filter;
lmts: Q_DateValue;
application: Application.Filter;
readRemark$session: ReadRemark.Filter & SubQueryPredicateMetadata;
sessionMessage$session: SessionMessage.Filter & SubQueryPredicateMetadata;
userEntityGrant$entity: UserEntityGrant.Filter & SubQueryPredicateMetadata;
relation$entity: Relation.Filter & SubQueryPredicateMetadata;
@ -53,7 +66,16 @@ export type Projection = {
$$seq$$?: number;
entity?: number;
entityId?: number;
userId?: number;
user?: User.Projection;
lmts?: number;
application?: Application.Projection;
readRemark$session?: ReadRemark.Selection & {
$entity: "readRemark";
};
readRemark$session$$aggr?: ReadRemark.Aggregation & {
$entity: "readRemark";
};
sessionMessage$session?: SessionMessage.Selection & {
$entity: "sessionMessage";
};
@ -82,6 +104,9 @@ export type Projection = {
type SessionIdProjection = OneOf<{
id: number;
}>;
type UserIdProjection = OneOf<{
userId: number;
}>;
type ApplicationIdProjection = OneOf<{
entityId: number;
}>;
@ -97,6 +122,12 @@ export type SortAttr = {
entity: number;
} | {
entityId: number;
} | {
userId: number;
} | {
user: User.SortAttr;
} | {
lmts: number;
} | {
application: Application.SortAttr;
} | {
@ -110,7 +141,15 @@ export type Sorter = SortNode[];
export type SelectOperation<P extends Object = Projection> = OakSelection<"select", P, Filter, Sorter>;
export type Selection<P extends Object = Projection> = SelectOperation<P>;
export type Aggregation = DeduceAggregation<Projection, Filter, Sorter>;
export type CreateOperationData = FormCreateData<Omit<OpSchema, "entity" | "entityId">> & ({
export type CreateOperationData = FormCreateData<Omit<OpSchema, "entity" | "entityId" | "userId">> & (({
userId?: never;
user?: User.CreateSingleOperation;
} | {
userId: ForeignKey<"user">;
user?: User.UpdateOperation;
} | {
userId?: ForeignKey<"user">;
})) & ({
entity?: never;
entityId?: never;
application: Application.CreateSingleOperation;
@ -126,6 +165,7 @@ export type CreateOperationData = FormCreateData<Omit<OpSchema, "entity" | "enti
entityId?: string;
[K: string]: any;
}) & {
readRemark$session?: OakOperation<ReadRemark.UpdateOperation["action"], Omit<ReadRemark.UpdateOperationData, "session" | "sessionId">, Omit<ReadRemark.Filter, "session" | "sessionId">> | OakOperation<"create", Omit<ReadRemark.CreateOperationData, "session" | "sessionId">[]> | Array<OakOperation<"create", Omit<ReadRemark.CreateOperationData, "session" | "sessionId">> | OakOperation<ReadRemark.UpdateOperation["action"], Omit<ReadRemark.UpdateOperationData, "session" | "sessionId">, Omit<ReadRemark.Filter, "session" | "sessionId">>>;
sessionMessage$session?: OakOperation<SessionMessage.UpdateOperation["action"], Omit<SessionMessage.UpdateOperationData, "session" | "sessionId">, Omit<SessionMessage.Filter, "session" | "sessionId">> | OakOperation<"create", Omit<SessionMessage.CreateOperationData, "session" | "sessionId">[]> | Array<OakOperation<"create", Omit<SessionMessage.CreateOperationData, "session" | "sessionId">> | OakOperation<SessionMessage.UpdateOperation["action"], Omit<SessionMessage.UpdateOperationData, "session" | "sessionId">, Omit<SessionMessage.Filter, "session" | "sessionId">>>;
userEntityGrant$entity?: OakOperation<UserEntityGrant.UpdateOperation["action"], Omit<UserEntityGrant.UpdateOperationData, "entity" | "entityId">, Omit<UserEntityGrant.Filter, "entity" | "entityId">> | OakOperation<"create", Omit<UserEntityGrant.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<UserEntityGrant.CreateOperationData, "entity" | "entityId">> | OakOperation<UserEntityGrant.UpdateOperation["action"], Omit<UserEntityGrant.UpdateOperationData, "entity" | "entityId">, Omit<UserEntityGrant.Filter, "entity" | "entityId">>>;
relation$entity?: OakOperation<Relation.UpdateOperation["action"], Omit<Relation.UpdateOperationData, "entity" | "entityId">, Omit<Relation.Filter, "entity" | "entityId">> | OakOperation<"create", Omit<Relation.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<Relation.CreateOperationData, "entity" | "entityId">> | OakOperation<Relation.UpdateOperation["action"], Omit<Relation.UpdateOperationData, "entity" | "entityId">, Omit<Relation.Filter, "entity" | "entityId">>>;
@ -134,7 +174,19 @@ export type CreateOperationData = FormCreateData<Omit<OpSchema, "entity" | "enti
export type CreateSingleOperation = OakOperation<"create", CreateOperationData>;
export type CreateMultipleOperation = OakOperation<"create", Array<CreateOperationData>>;
export type CreateOperation = CreateSingleOperation | CreateMultipleOperation;
export type UpdateOperationData = FormUpdateData<Omit<OpSchema, "entity" | "entityId">> & ({
export type UpdateOperationData = FormUpdateData<Omit<OpSchema, "entity" | "entityId" | "userId">> & (({
user: User.CreateSingleOperation;
userId?: never;
} | {
user: User.UpdateOperation;
userId?: never;
} | {
user: User.RemoveOperation;
userId?: never;
} | {
user?: never;
userId?: ForeignKey<"user"> | null;
})) & ({
application?: Application.CreateSingleOperation | Application.UpdateOperation | Application.RemoveOperation;
entityId?: never;
entity?: never;
@ -143,19 +195,23 @@ export type UpdateOperationData = FormUpdateData<Omit<OpSchema, "entity" | "enti
entityId?: ForeignKey<"Application"> | null;
}) & {
[k: string]: any;
readRemark$session?: OakOperation<ReadRemark.UpdateOperation["action"], Omit<ReadRemark.UpdateOperationData, "session" | "sessionId">, Omit<ReadRemark.Filter, "session" | "sessionId">> | OakOperation<ReadRemark.RemoveOperation["action"], Omit<ReadRemark.RemoveOperationData, "session" | "sessionId">, Omit<ReadRemark.Filter, "session" | "sessionId">> | OakOperation<"create", Omit<ReadRemark.CreateOperationData, "session" | "sessionId">[]> | Array<OakOperation<"create", Omit<ReadRemark.CreateOperationData, "session" | "sessionId">> | OakOperation<ReadRemark.UpdateOperation["action"], Omit<ReadRemark.UpdateOperationData, "session" | "sessionId">, Omit<ReadRemark.Filter, "session" | "sessionId">> | OakOperation<ReadRemark.RemoveOperation["action"], Omit<ReadRemark.RemoveOperationData, "session" | "sessionId">, Omit<ReadRemark.Filter, "session" | "sessionId">>>;
sessionMessage$session?: OakOperation<SessionMessage.UpdateOperation["action"], Omit<SessionMessage.UpdateOperationData, "session" | "sessionId">, Omit<SessionMessage.Filter, "session" | "sessionId">> | OakOperation<SessionMessage.RemoveOperation["action"], Omit<SessionMessage.RemoveOperationData, "session" | "sessionId">, Omit<SessionMessage.Filter, "session" | "sessionId">> | OakOperation<"create", Omit<SessionMessage.CreateOperationData, "session" | "sessionId">[]> | Array<OakOperation<"create", Omit<SessionMessage.CreateOperationData, "session" | "sessionId">> | OakOperation<SessionMessage.UpdateOperation["action"], Omit<SessionMessage.UpdateOperationData, "session" | "sessionId">, Omit<SessionMessage.Filter, "session" | "sessionId">> | OakOperation<SessionMessage.RemoveOperation["action"], Omit<SessionMessage.RemoveOperationData, "session" | "sessionId">, Omit<SessionMessage.Filter, "session" | "sessionId">>>;
userEntityGrant$entity?: OakOperation<UserEntityGrant.UpdateOperation["action"], Omit<UserEntityGrant.UpdateOperationData, "entity" | "entityId">, Omit<UserEntityGrant.Filter, "entity" | "entityId">> | OakOperation<UserEntityGrant.RemoveOperation["action"], Omit<UserEntityGrant.RemoveOperationData, "entity" | "entityId">, Omit<UserEntityGrant.Filter, "entity" | "entityId">> | OakOperation<"create", Omit<UserEntityGrant.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<UserEntityGrant.CreateOperationData, "entity" | "entityId">> | OakOperation<UserEntityGrant.UpdateOperation["action"], Omit<UserEntityGrant.UpdateOperationData, "entity" | "entityId">, Omit<UserEntityGrant.Filter, "entity" | "entityId">> | OakOperation<UserEntityGrant.RemoveOperation["action"], Omit<UserEntityGrant.RemoveOperationData, "entity" | "entityId">, Omit<UserEntityGrant.Filter, "entity" | "entityId">>>;
relation$entity?: OakOperation<Relation.UpdateOperation["action"], Omit<Relation.UpdateOperationData, "entity" | "entityId">, Omit<Relation.Filter, "entity" | "entityId">> | OakOperation<Relation.RemoveOperation["action"], Omit<Relation.RemoveOperationData, "entity" | "entityId">, Omit<Relation.Filter, "entity" | "entityId">> | OakOperation<"create", Omit<Relation.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<Relation.CreateOperationData, "entity" | "entityId">> | OakOperation<Relation.UpdateOperation["action"], Omit<Relation.UpdateOperationData, "entity" | "entityId">, Omit<Relation.Filter, "entity" | "entityId">> | OakOperation<Relation.RemoveOperation["action"], Omit<Relation.RemoveOperationData, "entity" | "entityId">, Omit<Relation.Filter, "entity" | "entityId">>>;
userRelation$entity?: OakOperation<UserRelation.UpdateOperation["action"], Omit<UserRelation.UpdateOperationData, "entity" | "entityId">, Omit<UserRelation.Filter, "entity" | "entityId">> | OakOperation<UserRelation.RemoveOperation["action"], Omit<UserRelation.RemoveOperationData, "entity" | "entityId">, Omit<UserRelation.Filter, "entity" | "entityId">> | OakOperation<"create", Omit<UserRelation.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<UserRelation.CreateOperationData, "entity" | "entityId">> | OakOperation<UserRelation.UpdateOperation["action"], Omit<UserRelation.UpdateOperationData, "entity" | "entityId">, Omit<UserRelation.Filter, "entity" | "entityId">> | OakOperation<UserRelation.RemoveOperation["action"], Omit<UserRelation.RemoveOperationData, "entity" | "entityId">, Omit<UserRelation.Filter, "entity" | "entityId">>>;
};
export type UpdateOperation = OakOperation<"update" | RelationAction | string, UpdateOperationData, Filter, Sorter>;
export type RemoveOperationData = {} & ({
export type RemoveOperationData = {} & (({
user?: User.UpdateOperation | User.RemoveOperation;
})) & ({
application?: Application.UpdateOperation | Application.RemoveOperation;
} | {
[k: string]: any;
});
export type RemoveOperation = OakOperation<"remove", RemoveOperationData, Filter, Sorter>;
export type Operation = CreateOperation | UpdateOperation | RemoveOperation;
export type UserIdSubQuery = Selection<UserIdProjection>;
export type ApplicationIdSubQuery = Selection<ApplicationIdProjection>;
export type SessionIdSubQuery = Selection<SessionIdProjection>;
export type EntityDef = {

View File

@ -15,9 +15,16 @@ export const desc = {
params: {
length: 64
}
},
userId: {
type: "ref",
ref: "user"
},
lmts: {
type: "datetime"
}
},
actionType: "crud",
actions,
relation: ['owner']
relation: ['partner']
};

View File

@ -1 +1 @@
{ "name": "会话", "attr": { "entity": "关联对象", "entityId": "关联对象id" }, "r": { "owner": "所有者" } }
{ "name": "会话", "attr": { "entity": "关联对象", "entityId": "关联对象id", "user": "发送者", "lmts": "最后一条消息的发送时间" }, "r": { "partner": "所有者" } }

View File

@ -28,6 +28,7 @@ import { desc as mobileDesc } from "./Mobile/Storage";
import { desc as notificationDesc } from "./Notification/Storage";
import { desc as parasiteDesc } from "./Parasite/Storage";
import { desc as platformDesc } from "./Platform/Storage";
import { desc as readRemarkDesc } from "./ReadRemark/Storage";
import { desc as sessionDesc } from "./Session/Storage";
import { desc as sessionMessageDesc } from "./SessionMessage/Storage";
import { desc as stationDesc } from "./Station/Storage";
@ -76,6 +77,7 @@ export const storageSchema = {
notification: notificationDesc,
parasite: parasiteDesc,
platform: platformDesc,
readRemark: readRemarkDesc,
session: sessionDesc,
sessionMessage: sessionMessageDesc,
station: stationDesc,

View File

@ -44,20 +44,20 @@ export const desc = {
name: 'index_name',
attributes: [
{
name: 'name',
name: 'name'
},
],
]
},
{
name: 'index_entity',
attributes: [
{
name: 'entity',
name: 'entity'
},
{
name: 'entityId',
name: 'entityId'
}
],
]
}
]
};

View File

@ -2,9 +2,9 @@ const IdActionDef = {
stm: {
verify: ['unverified', 'verifying'],
accept: [['unverified', 'verifying'], 'verified'],
reject: [['verifying', 'verified'], 'unverified'],
reject: [['verifying', 'verified'], 'unverified']
},
is: 'unverified',
is: 'unverified'
};
const UserActionDef = {
stm: {
@ -12,8 +12,8 @@ const UserActionDef = {
disable: [['normal', 'shadow'], 'disabled'],
enable: ['disabled', 'normal'],
mergeTo: [['normal', 'shadow'], 'merged'],
mergeFrom: ['normal', 'normal'],
},
mergeFrom: ['normal', 'normal']
}
};
export const actions = ["count", "stat", "download", "select", "aggregate", "create", "remove", "update", "grant", "revoke", "activate", "disable", "enable", "mergeTo", "mergeFrom", "verify", "accept", "reject"];
export const ActionDefDict = {

View File

@ -13,6 +13,8 @@ import * as Email from "../Email/Schema";
import * as Message from "../Message/Schema";
import * as Mobile from "../Mobile/Schema";
import * as Parasite from "../Parasite/Schema";
import * as ReadRemark from "../ReadRemark/Schema";
import * as Session from "../Session/Schema";
import * as SessionMessage from "../SessionMessage/Schema";
import * as Token from "../Token/Schema";
import * as UserEntityGrant from "../UserEntityGrant/Schema";
@ -68,6 +70,10 @@ export type Schema = EntityShape & {
mobile$user$$aggr?: AggregationResult<Mobile.Schema>;
parasite$user?: Array<Parasite.Schema>;
parasite$user$$aggr?: AggregationResult<Parasite.Schema>;
readRemark$user?: Array<ReadRemark.Schema>;
readRemark$user$$aggr?: AggregationResult<ReadRemark.Schema>;
session$user?: Array<Session.Schema>;
session$user$$aggr?: AggregationResult<Session.Schema>;
sessionMessage$user?: Array<SessionMessage.Schema>;
sessionMessage$user$$aggr?: AggregationResult<SessionMessage.Schema>;
token$user?: Array<Token.Schema>;
@ -121,6 +127,8 @@ type AttrFilter = {
message$user: Message.Filter & SubQueryPredicateMetadata;
mobile$user: Mobile.Filter & SubQueryPredicateMetadata;
parasite$user: Parasite.Filter & SubQueryPredicateMetadata;
readRemark$user: ReadRemark.Filter & SubQueryPredicateMetadata;
session$user: Session.Filter & SubQueryPredicateMetadata;
sessionMessage$user: SessionMessage.Filter & SubQueryPredicateMetadata;
token$user: Token.Filter & SubQueryPredicateMetadata;
token$player: Token.Filter & SubQueryPredicateMetadata;
@ -203,6 +211,18 @@ export type Projection = {
parasite$user$$aggr?: Parasite.Aggregation & {
$entity: "parasite";
};
readRemark$user?: ReadRemark.Selection & {
$entity: "readRemark";
};
readRemark$user$$aggr?: ReadRemark.Aggregation & {
$entity: "readRemark";
};
session$user?: Session.Selection & {
$entity: "session";
};
session$user$$aggr?: Session.Aggregation & {
$entity: "session";
};
sessionMessage$user?: SessionMessage.Selection & {
$entity: "sessionMessage";
};
@ -342,6 +362,8 @@ export type CreateOperationData = FormCreateData<Omit<OpSchema, "refId">> & (({
message$user?: OakOperation<Message.UpdateOperation["action"], Omit<Message.UpdateOperationData, "user" | "userId">, Omit<Message.Filter, "user" | "userId">> | OakOperation<"create", Omit<Message.CreateOperationData, "user" | "userId">[]> | Array<OakOperation<"create", Omit<Message.CreateOperationData, "user" | "userId">> | OakOperation<Message.UpdateOperation["action"], Omit<Message.UpdateOperationData, "user" | "userId">, Omit<Message.Filter, "user" | "userId">>>;
mobile$user?: OakOperation<Mobile.UpdateOperation["action"], Omit<Mobile.UpdateOperationData, "user" | "userId">, Omit<Mobile.Filter, "user" | "userId">> | OakOperation<"create", Omit<Mobile.CreateOperationData, "user" | "userId">[]> | Array<OakOperation<"create", Omit<Mobile.CreateOperationData, "user" | "userId">> | OakOperation<Mobile.UpdateOperation["action"], Omit<Mobile.UpdateOperationData, "user" | "userId">, Omit<Mobile.Filter, "user" | "userId">>>;
parasite$user?: OakOperation<Parasite.UpdateOperation["action"], Omit<Parasite.UpdateOperationData, "user" | "userId">, Omit<Parasite.Filter, "user" | "userId">> | OakOperation<"create", Omit<Parasite.CreateOperationData, "user" | "userId">[]> | Array<OakOperation<"create", Omit<Parasite.CreateOperationData, "user" | "userId">> | OakOperation<Parasite.UpdateOperation["action"], Omit<Parasite.UpdateOperationData, "user" | "userId">, Omit<Parasite.Filter, "user" | "userId">>>;
readRemark$user?: OakOperation<ReadRemark.UpdateOperation["action"], Omit<ReadRemark.UpdateOperationData, "user" | "userId">, Omit<ReadRemark.Filter, "user" | "userId">> | OakOperation<"create", Omit<ReadRemark.CreateOperationData, "user" | "userId">[]> | Array<OakOperation<"create", Omit<ReadRemark.CreateOperationData, "user" | "userId">> | OakOperation<ReadRemark.UpdateOperation["action"], Omit<ReadRemark.UpdateOperationData, "user" | "userId">, Omit<ReadRemark.Filter, "user" | "userId">>>;
session$user?: OakOperation<Session.UpdateOperation["action"], Omit<Session.UpdateOperationData, "user" | "userId">, Omit<Session.Filter, "user" | "userId">> | OakOperation<"create", Omit<Session.CreateOperationData, "user" | "userId">[]> | Array<OakOperation<"create", Omit<Session.CreateOperationData, "user" | "userId">> | OakOperation<Session.UpdateOperation["action"], Omit<Session.UpdateOperationData, "user" | "userId">, Omit<Session.Filter, "user" | "userId">>>;
sessionMessage$user?: OakOperation<SessionMessage.UpdateOperation["action"], Omit<SessionMessage.UpdateOperationData, "user" | "userId">, Omit<SessionMessage.Filter, "user" | "userId">> | OakOperation<"create", Omit<SessionMessage.CreateOperationData, "user" | "userId">[]> | Array<OakOperation<"create", Omit<SessionMessage.CreateOperationData, "user" | "userId">> | OakOperation<SessionMessage.UpdateOperation["action"], Omit<SessionMessage.UpdateOperationData, "user" | "userId">, Omit<SessionMessage.Filter, "user" | "userId">>>;
token$user?: OakOperation<Token.UpdateOperation["action"], Omit<Token.UpdateOperationData, "user" | "userId">, Omit<Token.Filter, "user" | "userId">> | OakOperation<"create", Omit<Token.CreateOperationData, "user" | "userId">[]> | Array<OakOperation<"create", Omit<Token.CreateOperationData, "user" | "userId">> | OakOperation<Token.UpdateOperation["action"], Omit<Token.UpdateOperationData, "user" | "userId">, Omit<Token.Filter, "user" | "userId">>>;
token$player?: OakOperation<Token.UpdateOperation["action"], Omit<Token.UpdateOperationData, "player" | "playerId">, Omit<Token.Filter, "player" | "playerId">> | OakOperation<"create", Omit<Token.CreateOperationData, "player" | "playerId">[]> | Array<OakOperation<"create", Omit<Token.CreateOperationData, "player" | "playerId">> | OakOperation<Token.UpdateOperation["action"], Omit<Token.UpdateOperationData, "player" | "playerId">, Omit<Token.Filter, "player" | "playerId">>>;
@ -380,6 +402,8 @@ export type UpdateOperationData = FormUpdateData<Omit<OpSchema, "refId">> & (({
message$user?: OakOperation<Message.UpdateOperation["action"], Omit<Message.UpdateOperationData, "user" | "userId">, Omit<Message.Filter, "user" | "userId">> | OakOperation<Message.RemoveOperation["action"], Omit<Message.RemoveOperationData, "user" | "userId">, Omit<Message.Filter, "user" | "userId">> | OakOperation<"create", Omit<Message.CreateOperationData, "user" | "userId">[]> | Array<OakOperation<"create", Omit<Message.CreateOperationData, "user" | "userId">> | OakOperation<Message.UpdateOperation["action"], Omit<Message.UpdateOperationData, "user" | "userId">, Omit<Message.Filter, "user" | "userId">> | OakOperation<Message.RemoveOperation["action"], Omit<Message.RemoveOperationData, "user" | "userId">, Omit<Message.Filter, "user" | "userId">>>;
mobile$user?: OakOperation<Mobile.UpdateOperation["action"], Omit<Mobile.UpdateOperationData, "user" | "userId">, Omit<Mobile.Filter, "user" | "userId">> | OakOperation<Mobile.RemoveOperation["action"], Omit<Mobile.RemoveOperationData, "user" | "userId">, Omit<Mobile.Filter, "user" | "userId">> | OakOperation<"create", Omit<Mobile.CreateOperationData, "user" | "userId">[]> | Array<OakOperation<"create", Omit<Mobile.CreateOperationData, "user" | "userId">> | OakOperation<Mobile.UpdateOperation["action"], Omit<Mobile.UpdateOperationData, "user" | "userId">, Omit<Mobile.Filter, "user" | "userId">> | OakOperation<Mobile.RemoveOperation["action"], Omit<Mobile.RemoveOperationData, "user" | "userId">, Omit<Mobile.Filter, "user" | "userId">>>;
parasite$user?: OakOperation<Parasite.UpdateOperation["action"], Omit<Parasite.UpdateOperationData, "user" | "userId">, Omit<Parasite.Filter, "user" | "userId">> | OakOperation<Parasite.RemoveOperation["action"], Omit<Parasite.RemoveOperationData, "user" | "userId">, Omit<Parasite.Filter, "user" | "userId">> | OakOperation<"create", Omit<Parasite.CreateOperationData, "user" | "userId">[]> | Array<OakOperation<"create", Omit<Parasite.CreateOperationData, "user" | "userId">> | OakOperation<Parasite.UpdateOperation["action"], Omit<Parasite.UpdateOperationData, "user" | "userId">, Omit<Parasite.Filter, "user" | "userId">> | OakOperation<Parasite.RemoveOperation["action"], Omit<Parasite.RemoveOperationData, "user" | "userId">, Omit<Parasite.Filter, "user" | "userId">>>;
readRemark$user?: OakOperation<ReadRemark.UpdateOperation["action"], Omit<ReadRemark.UpdateOperationData, "user" | "userId">, Omit<ReadRemark.Filter, "user" | "userId">> | OakOperation<ReadRemark.RemoveOperation["action"], Omit<ReadRemark.RemoveOperationData, "user" | "userId">, Omit<ReadRemark.Filter, "user" | "userId">> | OakOperation<"create", Omit<ReadRemark.CreateOperationData, "user" | "userId">[]> | Array<OakOperation<"create", Omit<ReadRemark.CreateOperationData, "user" | "userId">> | OakOperation<ReadRemark.UpdateOperation["action"], Omit<ReadRemark.UpdateOperationData, "user" | "userId">, Omit<ReadRemark.Filter, "user" | "userId">> | OakOperation<ReadRemark.RemoveOperation["action"], Omit<ReadRemark.RemoveOperationData, "user" | "userId">, Omit<ReadRemark.Filter, "user" | "userId">>>;
session$user?: OakOperation<Session.UpdateOperation["action"], Omit<Session.UpdateOperationData, "user" | "userId">, Omit<Session.Filter, "user" | "userId">> | OakOperation<Session.RemoveOperation["action"], Omit<Session.RemoveOperationData, "user" | "userId">, Omit<Session.Filter, "user" | "userId">> | OakOperation<"create", Omit<Session.CreateOperationData, "user" | "userId">[]> | Array<OakOperation<"create", Omit<Session.CreateOperationData, "user" | "userId">> | OakOperation<Session.UpdateOperation["action"], Omit<Session.UpdateOperationData, "user" | "userId">, Omit<Session.Filter, "user" | "userId">> | OakOperation<Session.RemoveOperation["action"], Omit<Session.RemoveOperationData, "user" | "userId">, Omit<Session.Filter, "user" | "userId">>>;
sessionMessage$user?: OakOperation<SessionMessage.UpdateOperation["action"], Omit<SessionMessage.UpdateOperationData, "user" | "userId">, Omit<SessionMessage.Filter, "user" | "userId">> | OakOperation<SessionMessage.RemoveOperation["action"], Omit<SessionMessage.RemoveOperationData, "user" | "userId">, Omit<SessionMessage.Filter, "user" | "userId">> | OakOperation<"create", Omit<SessionMessage.CreateOperationData, "user" | "userId">[]> | Array<OakOperation<"create", Omit<SessionMessage.CreateOperationData, "user" | "userId">> | OakOperation<SessionMessage.UpdateOperation["action"], Omit<SessionMessage.UpdateOperationData, "user" | "userId">, Omit<SessionMessage.Filter, "user" | "userId">> | OakOperation<SessionMessage.RemoveOperation["action"], Omit<SessionMessage.RemoveOperationData, "user" | "userId">, Omit<SessionMessage.Filter, "user" | "userId">>>;
token$user?: OakOperation<Token.UpdateOperation["action"], Omit<Token.UpdateOperationData, "user" | "userId">, Omit<Token.Filter, "user" | "userId">> | OakOperation<Token.RemoveOperation["action"], Omit<Token.RemoveOperationData, "user" | "userId">, Omit<Token.Filter, "user" | "userId">> | OakOperation<"create", Omit<Token.CreateOperationData, "user" | "userId">[]> | Array<OakOperation<"create", Omit<Token.CreateOperationData, "user" | "userId">> | OakOperation<Token.UpdateOperation["action"], Omit<Token.UpdateOperationData, "user" | "userId">, Omit<Token.Filter, "user" | "userId">> | OakOperation<Token.RemoveOperation["action"], Omit<Token.RemoveOperationData, "user" | "userId">, Omit<Token.Filter, "user" | "userId">>>;
token$player?: OakOperation<Token.UpdateOperation["action"], Omit<Token.UpdateOperationData, "player" | "playerId">, Omit<Token.Filter, "player" | "playerId">> | OakOperation<Token.RemoveOperation["action"], Omit<Token.RemoveOperationData, "player" | "playerId">, Omit<Token.Filter, "player" | "playerId">> | OakOperation<"create", Omit<Token.CreateOperationData, "player" | "playerId">[]> | Array<OakOperation<"create", Omit<Token.CreateOperationData, "player" | "playerId">> | OakOperation<Token.UpdateOperation["action"], Omit<Token.UpdateOperationData, "player" | "playerId">, Omit<Token.Filter, "player" | "playerId">> | OakOperation<Token.RemoveOperation["action"], Omit<Token.RemoveOperationData, "player" | "playerId">, Omit<Token.Filter, "player" | "playerId">>>;

View File

@ -60,33 +60,33 @@ export const desc = {
attributes: [
{
name: 'birth',
direction: 'ASC',
direction: 'ASC'
},
],
]
},
{
name: 'index_fulltext',
attributes: [
{
name: 'name',
name: 'name'
},
{
name: 'nickname',
name: 'nickname'
}
],
config: {
type: 'fulltext',
parser: 'ngram',
parser: 'ngram'
}
},
{
name: 'index_userState_refId',
attributes: [
{
name: 'userState',
name: 'userState'
},
{
name: "refId",
name: "refId"
}
]
}

View File

@ -76,23 +76,23 @@ export const desc = {
name: 'index_entity_entityId',
attributes: [
{
name: 'entity',
name: 'entity'
},
{
name: 'entityId',
name: 'entityId'
},
],
]
},
{
name: 'index_uuid',
attributes: [
{
name: 'expired',
name: 'expired'
},
{
name: 'expiresAt',
name: 'expiresAt'
}
],
]
}
]
};

View File

@ -34,21 +34,21 @@ export const desc = {
name: 'index_user_entity_entityId_relation',
attributes: [
{
name: "userId",
name: "userId"
},
{
name: 'entity',
name: 'entity'
},
{
name: 'entityId',
name: 'entityId'
},
{
name: "relationId",
name: "relationId"
},
],
config: {
unique: true,
},
unique: true
}
}
]
};

View File

@ -36,12 +36,12 @@ export const desc = {
name: 'index_uuid',
attributes: [
{
name: 'expired',
name: 'expired'
},
{
name: 'expiresAt',
name: 'expiresAt'
},
],
]
}
]
};

View File

@ -34,15 +34,15 @@ export const desc = {
name: 'index_text_application',
attributes: [
{
name: 'text',
name: 'text'
},
{
name: "applicationId",
name: "applicationId"
},
],
config: {
unique: true,
},
unique: true
}
}
]
};

View File

@ -75,34 +75,34 @@ export const desc = {
name: 'index_entity_entityId_tag',
attributes: [
{
name: 'entity',
name: 'entity'
},
{
name: 'entityId',
name: 'entityId'
},
{
name: 'tag',
name: 'tag'
}
],
]
},
{
name: 'index_expired_expiresAt',
attributes: [
{
name: 'expired',
name: 'expired'
},
{
name: 'expiresAt',
name: 'expiresAt'
},
],
]
},
{
name: 'index_url',
attributes: [
{
name: 'url',
name: 'url'
},
],
]
}
]
};

View File

@ -28,6 +28,7 @@ import * as Mobile from "./Mobile/Schema";
import * as Notification from "./Notification/Schema";
import * as Parasite from "./Parasite/Schema";
import * as Platform from "./Platform/Schema";
import * as ReadRemark from "./ReadRemark/Schema";
import * as Session from "./Session/Schema";
import * as SessionMessage from "./SessionMessage/Schema";
import * as Station from "./Station/Schema";
@ -114,6 +115,10 @@ export type UserIdSubQuery = {
entity: "mobile";
}) | (Parasite.UserIdSubQuery & {
entity: "parasite";
}) | (ReadRemark.UserIdSubQuery & {
entity: "readRemark";
}) | (Session.UserIdSubQuery & {
entity: "session";
}) | (SessionMessage.UserIdSubQuery & {
entity: "sessionMessage";
}) | (Token.UserIdSubQuery & {
@ -299,8 +304,15 @@ export type PlatformIdSubQuery = {
entity: "platform";
}) | any;
};
export type ReadRemarkIdSubQuery = {
[K in "$in" | "$nin"]?: (ReadRemark.ReadRemarkIdSubQuery & {
entity: "readRemark";
}) | any;
};
export type SessionIdSubQuery = {
[K in "$in" | "$nin"]?: (SessionMessage.SessionIdSubQuery & {
[K in "$in" | "$nin"]?: (ReadRemark.SessionIdSubQuery & {
entity: "readRemark";
}) | (SessionMessage.SessionIdSubQuery & {
entity: "sessionMessage";
}) | (UserEntityGrant.SessionIdSubQuery & {
entity: "userEntityGrant";

4
es/pages/session/byEntity/index.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
/// <reference types="wechat-miniprogram" />
/// <reference types="react" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, keyof import("../../../oak-app-domain").EntityDict, false, WechatMiniprogram.Component.DataOption>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
export default _default;

View File

@ -0,0 +1,3 @@
export default OakComponent({
isList: false,
});

View File

@ -0,0 +1,4 @@
{
"navigationBarTitleText": "会话列表",
"usingComponents": {}
}

3
es/pages/session/byEntity/web.d.ts vendored Normal file
View File

@ -0,0 +1,3 @@
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
export default function Render(props: WebComponentProps<EntityDict, 'session', false, {}, {}>): import("react/jsx-runtime").JSX.Element;

View File

@ -0,0 +1,7 @@
import { jsx as _jsx } from "react/jsx-runtime";
import SessionList from '../list';
export default function Render(props) {
const { data } = props;
const { oakFullpath } = data;
return (_jsx(SessionList, { oakAutoUnmount: true, oakPath: oakFullpath ? `$$session-byEntity/list` : undefined, entity: "", entityFilter: "" }));
}

4
es/pages/session/byUser/index.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
/// <reference types="wechat-miniprogram" />
/// <reference types="react" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, keyof import("../../../oak-app-domain").EntityDict, false, WechatMiniprogram.Component.DataOption>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
export default _default;

View File

@ -0,0 +1,3 @@
export default OakComponent({
isList: false,
});

View File

@ -0,0 +1,4 @@
{
"navigationBarTitleText": "会话列表",
"usingComponents": {}
}

3
es/pages/session/byUser/web.d.ts vendored Normal file
View File

@ -0,0 +1,3 @@
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
export default function Render(props: WebComponentProps<EntityDict, 'session', false, {}, {}>): import("react/jsx-runtime").JSX.Element;

Some files were not shown because too many files have changed in this diff Show More