├── chatbot └── .gitkeep ├── servers └── .gitkeep ├── web ├── packages │ ├── ueme-chat-app │ │ └── .gitkeep │ ├── ueme-chat-schema │ │ ├── src │ │ │ ├── api │ │ │ │ ├── index.ts │ │ │ │ ├── MscClient.ts │ │ │ │ ├── SocketIoClient.ts │ │ │ │ └── WsApi.ts │ │ │ └── protocol │ │ │ │ ├── index.ts │ │ │ │ ├── AttachmentMsg.ts │ │ │ │ ├── TextMsg.ts │ │ │ │ ├── CmdMsg.ts │ │ │ │ ├── MediaMsg.ts │ │ │ │ └── MsgBase.ts │ │ ├── .eslintrc.js │ │ ├── tslint.json │ │ ├── .prettierrc.js │ │ ├── tsconfig.json │ │ ├── tsconfig.test.json │ │ ├── scripts │ │ │ ├── jest │ │ │ │ └── jest.config.js │ │ │ └── webpack │ │ │ │ └── webpack.config.umd.js │ │ ├── .eslintignore │ │ ├── tsconfig.cjs.json │ │ ├── babel.config.js │ │ ├── tsconfig.es.json │ │ ├── .vscode │ │ │ └── setting.json │ │ └── package.json │ └── ueme-chat-ui │ │ ├── postcss.config.js │ │ ├── src │ │ ├── types │ │ │ ├── index.ts │ │ │ └── IRoomProps.ts │ │ ├── index.css │ │ ├── room │ │ │ ├── index.ts │ │ │ └── LiveConsultationRoom │ │ │ │ ├── index.css │ │ │ │ └── index.tsx │ │ ├── index.ts │ │ └── decorators │ │ │ └── exception │ │ │ └── Exception.tsx │ │ ├── .eslintrc.js │ │ ├── tslint.json │ │ ├── .prettierrc.js │ │ ├── README.md │ │ ├── tsconfig.json │ │ ├── .storybook │ │ ├── addons.js │ │ ├── config.js │ │ └── webpack.config.js │ │ ├── example │ │ ├── types.d.ts │ │ ├── index.tsx │ │ └── Simple │ │ │ └── index.tsx │ │ ├── public │ │ ├── favicon.ico │ │ ├── manifest.json │ │ └── index.html │ │ ├── scripts │ │ ├── jest │ │ │ └── jest.config.js │ │ └── webpack │ │ │ ├── webpack.config.dev.js │ │ │ └── webpack.config.umd.js │ │ ├── .eslintignore │ │ ├── tsconfig.cjs.json │ │ ├── babel.config.js │ │ ├── .vscode │ │ └── setting.json │ │ ├── tsconfig.es.json │ │ ├── stories │ │ └── index.stories.tsx │ │ └── package.json ├── .huskyrc.js ├── .lintstagedrc.js ├── .postcssrc.js ├── jsconfig.json ├── .prettierrc.js ├── scripts │ ├── jest │ │ └── jest.config.js │ ├── docker │ │ ├── Dockerfile.local │ │ ├── Dockerfile.gitlab │ │ ├── build-locally-dev.sh │ │ ├── build-locally-release.sh │ │ └── build-on-gitlab.sh │ ├── tools │ │ ├── lint_pkgs.sh │ │ └── upgrade_pkgs.sh │ └── webpack │ │ └── webpack.config.js ├── .prettierignore ├── tsconfig.test.json ├── .eslintignore ├── .github │ └── ISSUE_TEMPLATE │ │ ├── custom.md │ │ ├── feature_request.md │ │ └── bug_report.md ├── .editorconfig ├── .gitignore ├── .eslintrc.js ├── .vscode │ └── setting.json ├── tsconfig.json ├── tslint.json ├── .gitlab-ci.yml ├── LICENSE ├── package.json └── README.md ├── .github └── ISSUE_TEMPLATE │ ├── custom.md │ ├── feature_request.md │ └── bug_report.md ├── README.md ├── header.svg └── LICENSE /chatbot/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /servers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-app/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/src/api/index.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/src/api/MscClient.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/src/protocol/index.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/src/api/SocketIoClient.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/src/protocol/AttachmentMsg.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/.huskyrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@m-fe/husky-config'); 2 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | -------------------------------------------------------------------------------- /web/.lintstagedrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@m-fe/lint-staged'); 2 | -------------------------------------------------------------------------------- /web/.postcssrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@m-fe/postcss-config'); 2 | -------------------------------------------------------------------------------- /web/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@m-fe/tsconfig/jsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './IRoomProps'; 2 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require("../../.eslintrc.js") -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require("../../.eslintrc.js") -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/src/index.css: -------------------------------------------------------------------------------- 1 | .container { 2 | position: relative; 3 | } 4 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/src/room/index.ts: -------------------------------------------------------------------------------- 1 | export * from './LiveConsultationRoom'; 2 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../tslint.json"] 3 | } 4 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../tslint.json"] 3 | } 4 | -------------------------------------------------------------------------------- /web/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ...require('@m-fe/prettier-config/semi'), 3 | }; 4 | -------------------------------------------------------------------------------- /web/scripts/jest/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@m-fe/jest-config/jest.config'); 2 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ...require('../../.prettierrc.js'), 3 | }; 4 | -------------------------------------------------------------------------------- /web/.prettierignore: -------------------------------------------------------------------------------- 1 | !/.vscode/settings.json 2 | *.min.* 3 | *.production.* 4 | coverage 5 | dist 6 | node_modules 7 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ...require('../../.prettierrc.js'), 3 | }; 4 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/README.md: -------------------------------------------------------------------------------- 1 | # rtw-components 2 | 3 | rtw-components 是对应用开发过程中的常见组件进行抽取,以 CJS/UMD 形式发布。 4 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src/**/*"] 4 | } 5 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src/**/*"] 4 | } 5 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/src/room/LiveConsultationRoom/index.css: -------------------------------------------------------------------------------- 1 | .live-consultation-room-container { 2 | position: relative; 3 | } 4 | -------------------------------------------------------------------------------- /web/tsconfig.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/.storybook/addons.js: -------------------------------------------------------------------------------- 1 | import '@storybook/addon-actions/register'; 2 | import '@storybook/addon-links/register'; 3 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/example/types.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.less' { 2 | const styles: Record; 3 | export = styles; 4 | } 5 | -------------------------------------------------------------------------------- /web/scripts/docker/Dockerfile.local: -------------------------------------------------------------------------------- 1 | FROM abiosoft/caddy 2 | COPY . /srv 3 | RUN find . -name '*.map' -type f -exec rm -f {} \; 4 | EXPOSE 2015 5 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/tsconfig.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wx-chevalier/ueme-live-chat-support/HEAD/web/packages/ueme-chat-ui/public/favicon.ico -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/scripts/jest/jest.config.js: -------------------------------------------------------------------------------- 1 | const baseConfig = require('../../../../scripts/jest/jest.config'); 2 | 3 | module.exports = baseConfig; 4 | -------------------------------------------------------------------------------- /web/.eslintignore: -------------------------------------------------------------------------------- 1 | !/.*.js 2 | *.min.* 3 | *.production.* 4 | *.md 5 | *.js 6 | *.json 7 | 8 | coverage 9 | dist 10 | node_modules 11 | build 12 | scripts 13 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/scripts/jest/jest.config.js: -------------------------------------------------------------------------------- 1 | const baseConfig = require('../../../../scripts/jest/jest.config'); 2 | 3 | module.exports = baseConfig; 4 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/.eslintignore: -------------------------------------------------------------------------------- 1 | !/.*.js 2 | *.min.* 3 | *.production.* 4 | *.md 5 | *.js 6 | *.json 7 | 8 | coverage 9 | dist 10 | node_modules 11 | build 12 | scripts 13 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/.eslintignore: -------------------------------------------------------------------------------- 1 | !/.*.js 2 | *.min.* 3 | *.production.* 4 | *.md 5 | *.js 6 | *.json 7 | 8 | coverage 9 | dist 10 | node_modules 11 | build 12 | scripts 13 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/src/index.ts: -------------------------------------------------------------------------------- 1 | import '@chatui/core/dist/index.css'; 2 | 3 | // 默认使用图标库 4 | export * from '@chatui/core'; 5 | 6 | export * from './types'; 7 | export * from './room'; 8 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/src/decorators/exception/Exception.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export const Exception = ({ ...args }) =>
Simple Exception Component
; 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /web/.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "outDir": "dist/cjs", 6 | "declaration": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "outDir": "dist/cjs", 6 | "declaration": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /web/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | tab_width = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/example/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import * as ReactDOM from 'react-dom'; 3 | 4 | import Simple from './Simple'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /web/.gitignore: -------------------------------------------------------------------------------- 1 | # Node files 2 | node_modules 3 | 4 | # OS junk files 5 | .DS_Store 6 | .stylelintcache 7 | .eslintcache 8 | 9 | # Project specific stuff 10 | .cache-loader 11 | @coverage 12 | *.log 13 | dist 14 | build 15 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@m-fe', 5 | { 6 | import: true, 7 | react: true, 8 | typescript: true 9 | } 10 | ] 11 | ] 12 | }; 13 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/.vscode/setting.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.validate": [ 3 | "javascript", 4 | "javascriptreact", 5 | { "language": "typescript", "autoFix": true }, 6 | { "language": "typescriptreact", "autoFix": true } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/tsconfig.es.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "es6", 5 | "outDir": "dist/es", 6 | "declaration": true, 7 | "declarationDir": "dist/types" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /web/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: '@m-fe/eslint-config/base', 3 | parserOptions: { 4 | ecmaVersion: 2018, 5 | sourceType: 'module', 6 | project: './tsconfig.json', 7 | tsconfigRootDir: __dirname, 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@m-fe', 5 | { 6 | import: true, 7 | react: true, 8 | typescript: true, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/tsconfig.es.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "es6", 5 | "outDir": "dist/es", 6 | "declaration": true, 7 | "declarationDir": "dist/types" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/example/Simple/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import { LiveConsultationRoom } from '../../src'; 4 | 5 | export default function Simple() { 6 | return m} />; 7 | } 8 | -------------------------------------------------------------------------------- /web/.vscode/setting.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.validate": [ 3 | "javascript", 4 | "javascriptreact", 5 | { 6 | "language": "typescript", 7 | "autoFix": true 8 | }, 9 | { 10 | "language": "typescriptreact", 11 | "autoFix": true 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/.vscode/setting.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.validate": [ 3 | "javascript", 4 | "javascriptreact", 5 | { 6 | "language": "typescript", 7 | "autoFix": true 8 | }, 9 | { 10 | "language": "typescriptreact", 11 | "autoFix": true 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /web/scripts/tools/lint_pkgs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | cd ./packages 5 | 6 | for file in *; do 7 | [ -d "$file" ] || continue 8 | 9 | if [ "$file" == "config" ]; then 10 | continue 11 | fi 12 | 13 | echo "cd $file"; 14 | cd ./$file 15 | yarn run lint 16 | cd .. 17 | done 18 | -------------------------------------------------------------------------------- /web/scripts/tools/upgrade_pkgs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | cd ./packages 5 | 6 | for file in *; do 7 | [ -d "$file" ] || continue 8 | 9 | if [ "$file" == "config" ]; then 10 | continue 11 | fi 12 | 13 | echo "cd $file"; 14 | cd ./$file 15 | ncu -u 16 | cd .. 17 | done 18 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/.storybook/config.js: -------------------------------------------------------------------------------- 1 | import { configure } from '@storybook/react'; 2 | 3 | // automatically import all files ending in *.stories.js 4 | const req = require.context('../stories', true, /\.stories\.tsx?$/); 5 | function loadStories() { 6 | req.keys().forEach(filename => req(filename)); 7 | } 8 | 9 | configure(loadStories, module); 10 | -------------------------------------------------------------------------------- /web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@m-fe/tsconfig/tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["packages/rtw-host-app/src/*"] 7 | }, 8 | "strictFunctionTypes": false, 9 | "strictNullChecks": false, 10 | "suppressImplicitAnyIndexErrors": true 11 | }, 12 | "include": ["**/*.ts", "**/*.tsx"] 13 | } 14 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/src/protocol/TextMsg.ts: -------------------------------------------------------------------------------- 1 | import { MsgBase, MsgType } from './MsgBase'; 2 | 3 | export class TextMsg extends MsgBase { 4 | type: MsgType = 'text'; 5 | 6 | // 消息内容 7 | msg: string; 8 | 9 | static createMsg(baseMsg: Partial): TextMsg { 10 | const msg = new TextMsg(); 11 | Object.assign(msg, baseMsg); 12 | return msg; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/src/types/IRoomProps.ts: -------------------------------------------------------------------------------- 1 | import { ChatProps, MessageProps } from '@chatui/core'; 2 | 3 | type MessageWithoutId = Omit; 4 | 5 | export interface IRoomProps extends Partial { 6 | title?: string; 7 | initialMessages?: MessageWithoutId[]; 8 | 9 | /** 针对消息进行回复 */ 10 | answerMessage: (message: MessageWithoutId) => Promise; 11 | } 12 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/src/protocol/CmdMsg.ts: -------------------------------------------------------------------------------- 1 | import { MsgBase, MsgType } from './MsgBase'; 2 | 3 | export class CmdMsg extends MsgBase { 4 | type: MsgType = 'cmd'; 5 | 6 | // 消息内容 7 | msg: string; 8 | // 命令 9 | action: string; 10 | 11 | static createMsg(baseMsg: Partial): CmdMsg { 12 | const msg = new CmdMsg(); 13 | Object.assign(msg, baseMsg); 14 | return msg; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "RTW", 3 | "name": "Micro Frontend Boilerplate", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/scripts/webpack/webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const merge = require('webpack-merge'); 3 | 4 | const devConfig = require('../../../../scripts/webpack/webpack.config').devConfig; 5 | 6 | module.exports = merge(devConfig, { 7 | entry: { 8 | index: path.resolve(__dirname, '../../example') 9 | }, 10 | devServer: { 11 | contentBase: path.resolve(__dirname, '../../public') 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/stories/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import { action } from '@storybook/addon-actions'; 2 | import { storiesOf } from '@storybook/react'; 3 | import * as React from 'react'; 4 | 5 | import { Exception } from '../src/decorators/exception/Exception'; 6 | 7 | storiesOf('Exception', module).add( 8 | 'with text', 9 | () => Hello Button, 10 | { 11 | info: { inline: true } 12 | } 13 | ); 14 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/scripts/webpack/webpack.config.umd.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const merge = require('webpack-merge'); 3 | 4 | const umdConfig = require('../../../../scripts/webpack/webpack.config').umdConfig; 5 | 6 | const rootPath = process.cwd(); 7 | 8 | module.exports = merge(umdConfig, { 9 | output: { 10 | library: 'rtwComponents' 11 | }, 12 | entry: { 13 | index: path.resolve(rootPath, './src/index.ts') 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/scripts/webpack/webpack.config.umd.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const merge = require('webpack-merge'); 3 | 4 | const umdConfig = require('../../../../scripts/webpack/webpack.config') 5 | .umdConfig; 6 | 7 | const rootPath = process.cwd(); 8 | 9 | module.exports = merge(umdConfig, { 10 | output: { 11 | library: 'rtwCore', 12 | }, 13 | entry: { 14 | index: path.resolve(rootPath, './src/index.ts'), 15 | }, 16 | }); 17 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/.storybook/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = ({ config }) => { 2 | config.module.rules.push({ 3 | test: /\.(ts|tsx)$/, 4 | use: [ 5 | { 6 | loader: require.resolve('awesome-typescript-loader') 7 | }, 8 | // Optional 9 | { 10 | loader: require.resolve('react-docgen-typescript-loader') 11 | } 12 | ] 13 | }); 14 | config.resolve.extensions.push('.ts', '.tsx'); 15 | return config; 16 | }; 17 | -------------------------------------------------------------------------------- /web/scripts/docker/Dockerfile.gitlab: -------------------------------------------------------------------------------- 1 | FROM registry.mybiz.com/ufc/ufc-fe-builder:latest as builder 2 | 3 | RUN apk upgrade --update-cache --available \\ 4 | && apk add --upgrade autoconf automake build-base libtool nasm pkgconfig zlib-dev libpng-dev 5 | 6 | # 安装与编译代码 7 | COPY . /app 8 | WORKDIR /app 9 | 10 | RUN yarn install --frozen-lockfile --registry https://registry.npm.taobao.org/ 11 | RUN yarn build 12 | RUN find . -name '*.map' -type f -exec rm -f {} \; 13 | 14 | # 最终的应用 15 | FROM abiosoft/caddy 16 | COPY --from=builder /app/build /srv 17 | EXPOSE 2015 18 | -------------------------------------------------------------------------------- /web/scripts/docker/build-locally-dev.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # 本地构建并推送项目镜像 4 | # 5 | # Globals: 6 | # DOCKER_REGISTRY_SERVER 7 | # TAG 8 | 9 | set -e 10 | 11 | cd $(dirname $0)/../.. 12 | 13 | DOCKER_REGISTRY_SERVER=${DOCKER_REGISTRY_SERVER:=registry.mybiz.com} 14 | IMAGE=${DOCKER_REGISTRY_SERVER}/m-fe-web-client 15 | TAG=${TAG:=latest} 16 | 17 | yarn build 18 | 19 | echo "[*] Finished building" 20 | 21 | docker build --tag $IMAGE:$TAG -f scripts/docker/Dockerfile.local ./build 22 | 23 | echo "[*] Pushing $IMAGE:$TAG" 24 | 25 | docker push $IMAGE:$TAG 26 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @m-fe/react-lib 7 | 8 | 9 | 10 | 11 | 12 |
13 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /web/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@m-fe/tslint-config/react", "tslint-config-eslint/prettier"], 3 | "rules": { 4 | "jsx-no-lambda": false, 5 | "ordered-imports": [ 6 | true, 7 | { 8 | "grouped-imports": true, 9 | "import-sources-order": "lowercase-first", 10 | "named-imports-order": "lowercase-last", 11 | "groups": [ 12 | "^(?!rtw-)(@[^/]|[^@.])", 13 | "^(@/|rtw-)", 14 | "^(../)+", 15 | "^(?!\\./.*\\.less)" 16 | ] 17 | } 18 | ] 19 | }, 20 | "linterOptions": { 21 | "exclude": ["**/*.d.ts"] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /web/.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /web/scripts/docker/build-locally-release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # 本地构建并推送项目镜像 4 | # 5 | # Globals: 6 | # DOCKER_REGISTRY_SERVER 7 | # TAG 8 | 9 | set -e 10 | 11 | cd $(dirname $0)/../.. 12 | 13 | PACKAGE_VERSION=$(cat package.json | grep version | head -1 | awk -F= "{ print $2 }" | sed 's/[version:,\",]//g' | tr -d '[[:space:]]') 14 | 15 | DOCKER_REGISTRY_SERVER=${DOCKER_REGISTRY_SERVER:=registry.mybiz.com} 16 | IMAGE=${DOCKER_REGISTRY_SERVER}/m-fe-web-client 17 | TAG=v${PACKAGE_VERSION:=latest}-rc 18 | 19 | yarn build 20 | 21 | echo "[*] Finished building" 22 | 23 | docker build --tag $IMAGE:$TAG -f scripts/docker/Dockerfile.local ./build 24 | 25 | echo "[*] Pushing $IMAGE:$TAG" 26 | 27 | docker push $IMAGE:$TAG 28 | -------------------------------------------------------------------------------- /web/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | variables: 2 | DOCKER_DRIVER: overlay2 3 | EFF_NO_LINK_RULES: 'true' 4 | GIT_CLEAN_FLAGS: -ffdx -e /dist/ 5 | NODE_OPTIONS: --max-old-space-size=2048 6 | PARSER_NO_WATCH: 'true' 7 | DOCKER_TLS_CERTDIR: '' 8 | DOCKER_HOST: tcp://localhost:2375 9 | DOCKER_VERSION: 19.03.5 10 | 11 | build image: 12 | only: 13 | - dev 14 | - master 15 | stage: build 16 | image: docker:${DOCKER_VERSION} 17 | services: 18 | - name: docker:${DOCKER_VERSION}-dind 19 | before_script: 20 | - docker info 21 | - docker login ${DOCKER_REGISTRY_SERVER} -u ${DOCKER_REGISTRY_USER} -p ${DOCKER_REGISTRY_PASSWORD} 22 | script: 23 | - export IMAGE=${DOCKER_REGISTRY_SERVER}/m-fe-web-client 24 | - sh ./scripts/docker/build-on-gitlab.sh 25 | -------------------------------------------------------------------------------- /web/scripts/webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@m-fe/webpack-config')({ 2 | themeVars: { 3 | 'primary-color': '#5d4bff', 4 | }, 5 | extendedBaseConfig: { 6 | module: { 7 | rules: [ 8 | // svg 的加载交于应用自身决定 9 | { 10 | test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, 11 | oneOf: [ 12 | { 13 | issuer: /\.[jt]sx?$/, 14 | use: [ 15 | { 16 | loader: '@svgr/webpack', 17 | // loader: 'svg-inline-loader', 18 | }, 19 | ], 20 | }, 21 | { 22 | loader: 'url-loader', 23 | }, 24 | ], 25 | }, 26 | ], 27 | }, 28 | resolve: { 29 | alias: { 30 | dayjs: 'dayjs/esm', 31 | moment$: 'dayjs/esm', 32 | systemjs$: 'systemjs/dist/system.js', 33 | }, 34 | }, 35 | }, 36 | }); 37 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/src/protocol/MediaMsg.ts: -------------------------------------------------------------------------------- 1 | import { MsgBase, MsgType } from './MsgBase'; 2 | 3 | export class MediaMsg extends MsgBase { 4 | type: MsgType = 'media'; 5 | 6 | // 消息内容 7 | file: { data: Blob | null; url: string }; 8 | 9 | // 创建消息 10 | static createMsg(baseMsg: Partial): MediaMsg { 11 | const msg = new MediaMsg(); 12 | Object.assign(msg, baseMsg); 13 | return msg; 14 | } 15 | 16 | // 从剪贴板中创建 17 | static createFromClipboard(baseMsg: Partial, clipboardData: DataTransfer) { 18 | if (clipboardData && clipboardData.types) { 19 | if (clipboardData.items.length > 0) { 20 | const blob = clipboardData.items[0].getAsFile(); 21 | const url = window.URL.createObjectURL(blob); 22 | 23 | return MediaMsg.createMsg({ 24 | ...baseMsg, 25 | file: { 26 | data: blob, 27 | url 28 | } 29 | }); 30 | } 31 | } 32 | 33 | return null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /web/.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /web/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 王下邀月熊 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/src/protocol/MsgBase.ts: -------------------------------------------------------------------------------- 1 | import { uuid } from '../utils/uuid'; 2 | 3 | export type MsgType = 'text' | 'media' | 'cmd' | 'attachment'; 4 | 5 | export type RoomType = 'single' | 'room'; 6 | 7 | export type GroupOption = { 8 | subject: string; // 群名称 9 | description: string; // 群简介 10 | members: string[]; // 成员列表 11 | optionsPublic: boolean; // 允许任何人加入 12 | optionsModerate: boolean; // 加入需审批 13 | optionsMembersOnly: boolean; // 不允许任何人主动加入 14 | optionsAllowInvites: boolean; // 允许群人员邀请 15 | }; 16 | 17 | export class MsgBase { 18 | // 消息编号 19 | id: string = uuid(); 20 | 21 | // 消息发送方,如果是从多个人发出,则用 , 逗号分隔 22 | from: string; 23 | 24 | // 消息接收方/目标方,如果是发送给多个人,则用 , 逗号分隔 25 | to: string; 26 | 27 | // 消息类型 28 | type: MsgType; 29 | 30 | // 聊天室类型 31 | roomType: RoomType; 32 | 33 | // 扩展消息 34 | ext: Record; 35 | 36 | /** 校验当前消息是否有效 */ 37 | isValid() { 38 | if (!this.from || !this.to) { 39 | return false; 40 | } 41 | 42 | return true; 43 | } 44 | 45 | static createMsg(baseMsg: Partial): MsgBase { 46 | const msg = new MsgBase(); 47 | Object.assign(msg, baseMsg); 48 | return msg; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@m-fe/ueme-chat", 3 | "version": "0.0.1", 4 | "description": "Micro-Frontend Libs, with React & TS & Webpack", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/wx-chevalier/m-fe-libs" 8 | }, 9 | "author": "wx-chevalier@github", 10 | "license": "MIT", 11 | "private": true, 12 | "workspaces": [ 13 | "packages/*" 14 | ], 15 | "keywords": [ 16 | "react", 17 | "redux", 18 | "mobx", 19 | "webpack", 20 | "typescript" 21 | ], 22 | "scripts": { 23 | "bootstrap": "yarn install && yarn run build", 24 | "build": "npm run clean && yarn workspaces run build && cp -r ./packages/app-lib/build/ ./build", 25 | "clean": "rm -rf ./build && yarn workspaces run clean", 26 | "clean:cov": "yarn workspaces run clean:cov", 27 | "dev": "npm start", 28 | "lint": "./scripts/tools/lint_pkgs.sh", 29 | "lint-staged": "lint-staged", 30 | "postinstall": "node ./node_modules/husky/lib/installer/bin install", 31 | "prettier-all": "prettier --write 'packages/**/src/**/*.{ts,tsx}' '!src/{assets,datas}/**'", 32 | "start": "(cd packages/app-lib && npm start)", 33 | "test": "yarn workspaces run test", 34 | "test:cov": "yarn workspaces run test:cov", 35 | "test:watch": "yarn workspaces run test:watch", 36 | "upgrade": "./scripts/tools/upgrade_pkgs.sh" 37 | }, 38 | "devDependencies": { 39 | "@m-fe/app-config": "^0.6.9", 40 | "@svgr/webpack": "^5.4.0" 41 | }, 42 | "browserslist": [ 43 | "extends @m-fe/browserslist-config" 44 | ], 45 | "commitlint": { 46 | "extends": [ 47 | "@m-fe" 48 | ] 49 | }, 50 | "remarkConfig": { 51 | "plugins": [ 52 | "@m-fe/remark-config" 53 | ] 54 | }, 55 | "stylelint": { 56 | "extends": [ 57 | "@m-fe/stylelint-config", 58 | "@m-fe/stylelint-config/modules" 59 | ], 60 | "rules": { 61 | "font-family-no-missing-generic-family-keyword": null, 62 | "no-descending-specificity": null, 63 | "plugin/no-unsupported-browser-features": null, 64 | "plugin/no-low-performance-animation-properties": null 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@m-fe/ts-lib", 3 | "version": "0.0.1", 4 | "description": "@m-fe/ts-lib", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/wx-chevalier/fe-boilerplates" 8 | }, 9 | "author": "wx-chevalier@github", 10 | "license": "MIT", 11 | "main": "dist/cjs/index.js", 12 | "module": "dist/es/index.js", 13 | "types": "dist/types/index.d.ts", 14 | "files": [ 15 | "dist/" 16 | ], 17 | "keywords": [ 18 | "webpack", 19 | "react" 20 | ], 21 | "scripts": { 22 | "build": "npm run clean && npm run build:es && npm run build:cjs && npm run build:umd", 23 | "build:cjs": "tsc --project ./tsconfig.cjs.json", 24 | "build:es": "tsc --project ./tsconfig.es.json", 25 | "build:umd": "cross-env NODE_ENV=production webpack -p --config ./scripts/webpack/webpack.config.umd.js", 26 | "clean": "rimraf dist", 27 | "clean:r": "rimraf ./dist/*.map && rimraf ./dist/**/*.map && rimraf ./dist/**/*.tsbuildinfo", 28 | "dev": "tsc -w --project ./tsconfig.cjs.json", 29 | "lint": "run-p lint:*", 30 | "lint:es": "cross-env PARSER_NO_WATCH=true eslint . --cache --ext js,md,ts,tsx -f friendly --max-warnings 10", 31 | "lint:ts": "tslint -p . -t stylish", 32 | "lint:tsc": "tsc -p tsconfig.json --incremental false --noEmit", 33 | "prepublish": "npm run clean:r", 34 | "pub": "npm publish --registry=https://registry.npmjs.org/ --access public", 35 | "test": "jest --config ./scripts/jest/jest.config.js", 36 | "test:cov": "npm run cleanCov && npm test -- --coverage", 37 | "test:watch": "npm test -- --watch" 38 | }, 39 | "dependencies": {}, 40 | "devDependencies": { 41 | "@m-fe/app-config": "^0.6.9", 42 | "cross-env": "^7.0.2", 43 | "webpack": "^4.43.0" 44 | }, 45 | "browserslist": [ 46 | "extends @m-fe/browserslist-config" 47 | ], 48 | "commitlint": { 49 | "extends": [ 50 | "@m-fe" 51 | ] 52 | }, 53 | "remarkConfig": { 54 | "plugins": [ 55 | "@m-fe/remark-config" 56 | ] 57 | }, 58 | "stylelint": { 59 | "extends": [ 60 | "@m-fe/stylelint-config", 61 | "@m-fe/stylelint-config/modules" 62 | ], 63 | "rules": { 64 | "font-family-no-missing-generic-family-keyword": null, 65 | "no-descending-specificity": null, 66 | "plugin/no-unsupported-browser-features": null, 67 | "plugin/no-low-performance-animation-properties": null 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@m-fe/ueme-chat-ui", 3 | "version": "0.0.3", 4 | "description": "Micro Front-end Libs", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/wx-chevalier/fe-boilerplates" 8 | }, 9 | "author": "wx-chevalier@github", 10 | "license": "MIT", 11 | "main": "dist/cjs/index.js", 12 | "module": "dist/es/index.js", 13 | "types": "dist/types/index.d.ts", 14 | "files": [ 15 | "dist/" 16 | ], 17 | "keywords": [ 18 | "webpack", 19 | "react" 20 | ], 21 | "scripts": { 22 | "build": "npm run clean && run-p build:* && npm run clean:r && run-p copy:*", 23 | "build-storybook": "build-storybook", 24 | "build:cjs": "tsc --project ./tsconfig.cjs.json", 25 | "build:es": "tsc --project ./tsconfig.es.json", 26 | "clean": "rimraf dist", 27 | "clean:r": "rimraf ./dist/*.map && rimraf ./dist/**/*.map && rimraf ./dist/**/*.tsbuildinfo", 28 | "copy:cjs": "copyfiles -u 1 './src/**/*.{less,svg,css}' dist/cjs/", 29 | "copy:es": "copyfiles -u 1 './src/**/*.{less,svg,css}' dist/es/", 30 | "dev": "webpack-dev-server --config ./scripts/webpack/webpack.config.dev.js --hot", 31 | "lint": "run-p lint:*", 32 | "lint:es": "cross-env PARSER_NO_WATCH=true eslint . --cache --ext js,md,ts,tsx -f friendly --max-warnings 10", 33 | "lint:style": "stylelint **/*.less --cache", 34 | "lint:ts": "tslint -p . -t stylish", 35 | "lint:tsc": "tsc -p tsconfig.json --incremental false --noEmit", 36 | "start": "npm run dev", 37 | "storybook": "start-storybook -p 6006" 38 | }, 39 | "peerDependencies": { 40 | "@m-fe/utils": "^0.4.0", 41 | "react": "16.13.1", 42 | "react-dom": "16.13.1" 43 | }, 44 | "dependencies": { 45 | "@chatui/core": "^0.1.1", 46 | "react-hot-keys": "^2.6.0" 47 | }, 48 | "devDependencies": { 49 | "@m-fe/app-config": "^0.6.9", 50 | "@storybook/addon-actions": "^5.3.18", 51 | "@storybook/addon-info": "^5.3.18", 52 | "@storybook/addon-links": "^5.3.18", 53 | "@storybook/addons": "^5.3.18", 54 | "@storybook/react": "^5.3.18", 55 | "copyfiles": "^2.2.0", 56 | "cross-env": "^7.0.2", 57 | "npm-run-all": "^4.1.5", 58 | "webpack": "^4.43.0", 59 | "webpack-dev-server": "^3.11.0" 60 | }, 61 | "lint-staged": { 62 | "*.{ts,tsx,scss,less,md}": [ 63 | "prettier --write", 64 | "git add" 65 | ] 66 | }, 67 | "prettier": { 68 | "printWidth": 100, 69 | "singleQuote": true 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /web/scripts/docker/build-on-gitlab.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Gitlab CI 项目镜像构建 4 | # 5 | # Gitlab CI 预定义变量: 6 | # https://docs.gitlab.com/ee/ci/variables/predefined_variables.html 7 | # 8 | # Globals: 9 | # CI_COMMIT_TAG: 当前提交的 tag 10 | # CI_COMMIT_SHA: 当前提交的 commit sha 11 | # CI_COMMIT_REF_NAME: 当前提交的 ref name (branch/tag) 12 | # 13 | # 测试: 14 | # CI_COMMIT_TAG= ./build-on-gitlab.sh 15 | # CI_COMMIT_SHA= CI_COMMIT_REF_NAME=dev ./build-on-gitlab.sh 16 | 17 | # 切入项目根目录 18 | cd $(dirname $0)/../.. 19 | 20 | DOCKERFILE=${DOCKERFILE:=scripts/docker/Dockerfile.gitlab} 21 | IMAGE=${IMAGE} 22 | PACKAGE_VERSION=$(cat package.json | grep version | head -1 | awk -F= "{ print $2 }" | sed 's/[version:,\",]//g' | tr -d '[[:space:]]') 23 | 24 | ####################################### 25 | # 构建 tag 了的 commit 的镜像并推送 26 | # 27 | # Globals: 28 | # CI_COMMIT_TAG 29 | # IMAGE 30 | # DOCKERFILE 31 | ####################################### 32 | build_tag() { 33 | echo "[1/2] Building ${IMAGE}:${CI_COMMIT_TAG}" 34 | docker build -t ${IMAGE}:${CI_COMMIT_TAG} -f ${DOCKERFILE} . 35 | 36 | echo "[2/2] Pushing ${IMAGE}:${CI_COMMIT_TAG}" 37 | docker push ${IMAGE}:${CI_COMMIT_TAG} 38 | } 39 | 40 | ####################################### 41 | # 在 master 分支构建 rc 镜像,tag 为 package.json 版本 42 | # 43 | # Globals: 44 | # CHART_VERSION 45 | # IMAGE 46 | # DOCKERFILE 47 | ####################################### 48 | build_master() { 49 | local image_tag=v${PACKAGE_VERSION}-rc 50 | echo "[1/2] Building ${IMAGE}:${image_tag}" 51 | docker build -t ${IMAGE}:${image_tag} -f ${DOCKERFILE} . 52 | 53 | echo "[2/2] Pushing ${IMAGE}:${image_tag}" 54 | docker push ${IMAGE}:${image_tag} 55 | } 56 | 57 | ####################################### 58 | # 构建 dev 分支镜像,将构建 COMMIT_SHA 和 latest 两个 tag 的镜像 59 | # 60 | # Globals: 61 | # CI_COMMIT_SHA 62 | # IMAGE 63 | # DOCKERFILE 64 | ####################################### 65 | build_dev() { 66 | echo "[1/3] Building ${IMAGE}:${CI_COMMIT_SHA} $IMAGE:latest" 67 | docker build -t ${IMAGE}:${CI_COMMIT_SHA} -t ${IMAGE}:latest -f ${DOCKERFILE} . || return $? 68 | 69 | echo "[2/3] Pushing ${IMAGE}:latest" 70 | docker push ${IMAGE}:latest || return $? 71 | 72 | # echo "[3/3] Pushing ${IMAGE}:${CI_COMMIT_SHA}" 73 | # docker push ${IMAGE}:${CI_COMMIT_SHA} || return $? 74 | } 75 | 76 | ####################################### 77 | # 非 dev/master 且未 tag 的 commit 生成该分支的镜像 78 | # 79 | # Globals: 80 | # CI_COMMIT_REF_NAME 81 | # IMAGE 82 | # DOCKERFILE 83 | ####################################### 84 | build_other_branch() { 85 | local tag=$(echo ${CI_COMMIT_REF_NAME} | sed 's/\//-/g') 86 | 87 | echo "[1/2] Building ${IMAGE}:${tag}" 88 | docker build -t ${IMAGE}:${tag} -f ${DOCKERFILE} . || return $? 89 | 90 | echo "[2/2] Pushing ${IMAGE}:${tag}" 91 | docker push ${IMAGE}:${tag} || return $? 92 | } 93 | 94 | case ${CI_COMMIT_REF_NAME} in 95 | dev) 96 | echo "Build on dev branch" 97 | build_dev 98 | ;; 99 | master) 100 | echo "Build on master branch" 101 | build_master 102 | ;; 103 | *) 104 | if [[ ! -z ${CI_COMMIT_TAG} ]]; then 105 | echo "Build tag ${CI_COMMIT_TAG}" 106 | build_tag 107 | else 108 | if [[ ! -z ${CI_COMMIT_REF_NAME} ]]; then 109 | echo "Build on ${CI_COMMIT_REF_NAME} branch" 110 | build_other_branch 111 | fi 112 | fi 113 | ;; 114 | esac 115 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-ui/src/room/LiveConsultationRoom/index.tsx: -------------------------------------------------------------------------------- 1 | import Chat, { Bubble, MessageProps, QuickReplyItemProps, useMessages } from '@chatui/core'; 2 | import cn from 'classnames'; 3 | import * as React from 'react'; 4 | 5 | import { IRoomProps } from '../../types'; 6 | 7 | import './index.css'; 8 | 9 | const prefix = 'live-consultation-room'; 10 | 11 | const defaultInitialMessages = [ 12 | { 13 | type: 'text', 14 | content: { text: '主人好,我是智能助理,你的贴心小助手~' }, 15 | user: { 16 | avatar: 17 | 'https://ufc-assets.oss-cn-shanghai.aliyuncs.com/%E5%89%8D%E7%AB%AF%E8%B5%84%E6%BA%90/Logo/logo_%E7%95%99%E7%A9%BA.jpg' 18 | } 19 | }, 20 | { 21 | type: 'image', 22 | content: { 23 | picUrl: '//img.alicdn.com/tfs/TB1p_nirYr1gK0jSZR0XXbP8XXa-300-300.png' 24 | } 25 | } 26 | ]; 27 | 28 | // 默认快捷短语,可选 29 | const defaultQuickReplies = [ 30 | { 31 | icon: 'message', 32 | name: '人工服务' 33 | }, 34 | { 35 | icon: 'keyboard', 36 | name: '更多操作' 37 | } 38 | ]; 39 | 40 | export interface LiveConsultationRoomProps extends IRoomProps { 41 | className?: string; 42 | style?: Record; 43 | } 44 | 45 | export const LiveConsultationRoom = ({ 46 | className, 47 | style, 48 | quickReplies = defaultQuickReplies, 49 | 50 | title = '智能助理', 51 | initialMessages = defaultInitialMessages, 52 | answerMessage, 53 | ...rest 54 | }: LiveConsultationRoomProps) => { 55 | // 消息列表 56 | const { messages, appendMsg, setTyping } = useMessages(initialMessages); 57 | 58 | // 发送回调 59 | function handleSend(type: string, val: string) { 60 | if (type === 'text' && val.trim()) { 61 | // 添加用户发送的消息 62 | appendMsg({ 63 | type: 'text', 64 | content: { text: val }, 65 | position: 'right' 66 | }); 67 | 68 | setTyping(true); 69 | } 70 | 71 | // 获得回复的消息,然后添加 72 | (async () => { 73 | const replyMessage = await answerMessage({ 74 | type: 'text', 75 | content: { text: val } 76 | }); 77 | 78 | // 模拟回复消息 79 | setTimeout(() => { 80 | appendMsg({ 81 | type: replyMessage.type, 82 | content: replyMessage.content 83 | }); 84 | }, 599); 85 | })(); 86 | } 87 | 88 | // 快捷短语回调,可根据 item 数据做出不同的操作,这里以发送文本消息为例 89 | function handleQuickReplyClick(item: QuickReplyItemProps) { 90 | handleSend('text', item.name); 91 | } 92 | 93 | function renderMessageContent(msg: MessageProps) { 94 | const { type, content } = msg; 95 | 96 | // 根据消息类型来渲染 97 | switch (type) { 98 | case 'text': 99 | return ; 100 | case 'image': 101 | return ( 102 | 103 | 104 | 105 | ); 106 | default: 107 | return null; 108 | } 109 | } 110 | 111 | return ( 112 |
113 | 122 |
123 | ); 124 | }; 125 | -------------------------------------------------------------------------------- /web/README.md: -------------------------------------------------------------------------------- 1 | ![](https://i.postimg.cc/0N7w0mnN/image.png) 2 | 3 | # m-fe/libs 4 | 5 | 在 [Web 开发导论/微前端与大前端](https://github.com/wx-chevalier/Web-Series)一文中,笔者简述了微服务与微前端的设计理念以及微前端的潜在可行方案。微服务与微前端,都是希望将某个单一的单体应用,转化为多个可以独立运行、独立开发、独立部署、独立维护的服务或者应用的聚合,从而满足业务快速变化及分布式多团队并行开发的需求。如康威定律(Conway’s Law)所言,设计系统的组织,其产生的设计和架构等价于组织间的沟通结构;微服务与微前端不仅仅是技术架构的变化,还包含了组织方式、沟通方式的变化。微服务与微前端原理和软件工程,面向对象设计中的原理同样相通,都是遵循单一职责(Single Responsibility)、关注分离(Separation of Concerns)、模块化(Modularity)与分而治之(Divide & Conquer)等基本的原则。 6 | 7 | ![微前端项目结构](https://user-images.githubusercontent.com/5803001/44003230-de68ac5c-9e81-11e8-81f5-8092f7a9b421.png) 8 | 9 | 当我们考量项目框架、模板或者脚手架的时候,首先想到的点就是希望尽可能对上层屏蔽细节,但是对于长期维护的、多人协作的中大型项目而言,如果项目的主导者直接使用了部分抽象的脚手架,不免会给未来的更新、迭代带来一定的技术负债;同时,目前也有很多成熟的工程化脚手架,因此笔者选择以项目模板的形式抽象出微前端中所需要的部分。尽可能地遵循简约、直观的原则,减少抽象/Magic Function 等;大型项目可能会抽象出专用的开发工具流,但是对于大部分项目而言,在现有框架/工具链的基础上进行适当封装会是较优选择。 10 | 11 | # Develop 12 | 13 | ```sh 14 | # 拉取并且提取出子项目 15 | $ git clone https://github.com/wx-chevalier/m-fe-rtw 16 | 17 | # 添加全局的依赖更新工具 18 | $ yarn global add npm-check-updates npm-run-all cross-env copyfiles 19 | 20 | # 为各个子项目安装依赖,以及链接各个子项目 21 | $ yarn bootstrap && yarn build 22 | 23 | # 执行预编译操作 24 | $ yarn start 25 | 26 | # 执行 Lint 操作 27 | $ yarn lint 28 | ``` 29 | 30 | 值得说明的是,微前端作为概念对于不同人承载了不同的考量,其实现方式、落地路径也是见仁见智,若有不妥,敬请指教。 31 | 32 | ## Features 33 | 34 | - 状态管理,灵活支持 Redux/MobX/Dva 等不同的状态管理框架,对于 Redux 提供全局统一的 Store 声明。 35 | 36 | - 模块分割,非 APP 类可单独发布,APP 类可单独运行,与发布。发布版本可包含 ES, CJS, UMD 等,dist 目录下包含 ES/CJS 模块,build 目录下包含 APP 完整资源以及 UMD 模块。 37 | 38 | - 应用编排:版本控制、应用注册、应用路由,子应用资源不使用 Hash 方式,而是使用语义化版本,`/[cdnHost]/[projectName]/[subAppName]/[x.y.z]/index.{js,css}`。 39 | 40 | - 动态主题与样式切换,- 样式,LESS 文件支持 CSS Modules,CSS/SCSS 使用标准 CSS。 41 | 42 | - 权限控制 43 | 44 | - 路由与导航框架 45 | 46 | - 国际化 47 | 48 | - PWA 49 | 50 | - 服务端渲染 51 | 52 | ## CI 53 | 54 | m-fe-rtw 内置了 Gitlab CI 的完整流程,请参考 .gitlab-ci.yml 及 scripts/{deploy, docker} 中的配置。 55 | 56 | ## Nav | 关联项目 57 | 58 | - [m-fe-configs](https://github.com/wx-chevalier/m-fe-configs):Common Dev Configs(ESLint, Prettier, Husky, etc.) for Micro-Frontend Apps 59 | 60 | - [m-fe-rtw](https://github.com/wx-chevalier/m-fe-rtw): Micro-Frontend boilerplate with React & TypeScript & Webpack, for complicated cooperative applications. | 微前端项目模板 61 | 62 | - [m-fe-vtw](https://github.com/wx-chevalier/m-fe-vtw): Micro-Frontend boilerplate with Vue & TypeScript & Webpack, for complicated cooperative applications. | 微前端项目模板 63 | 64 | - [m-fe-rm](https://github.com/wx-chevalier/m-fe-rm): 基于 React & TS & Webpack & APICloud 提供快速移动端应用开发的能力 65 | 66 | - [m-fe-taro](https://github.com/wx-chevalier/m-fe-taro): 基于 Taro & TS 的多端小程序开发模板。 67 | 68 | - [m-fe-scaffold](https://github.com/wx-chevalier/m-fe-scaffold/): Cli Toolkits for Web Development & Deploy on Kubernetes,微前端实践中沉淀的一系列脚手架工具。 69 | 70 | - [m-fe-libs](https://github.com/wx-chevalier/m-fe-libs): Micro-Frontend boilerplate with React & TypeScript & Webpack, for complicated cooperative applications. | 微前端项目模板 71 | 72 | -- 73 | 74 | - [react-snippets](https://github.com/wx-chevalier/react-snippets): React Snippets(.ts/.tsx), about design patterns/techniques used while developing with React and TypeScript. 75 | 76 | - [vue-snippets](https://github.com/wx-chevalier/vue-snippets): Vue Snippets(.js/.ts), about design patterns/techniques used while developing with Vue and JavaScript/TypeScript. 77 | 78 | - [fractal-components](https://github.com/wx-chevalier/fractal-components): Massive Fractal Components in Several Libraries(Vanilla, React, Vue, Weapp), for building your great apps easily again 79 | 80 | - [Legoble](https://github.com/wx-chevalier/Legoble): Build your apps like stacking Lego blocks 💫 总想自己实现一款可视化配置的动态应用构建工具,动态表单、动态布局、动态报告、动态规则、动态选择、动态流程 81 | 82 | # About 83 | 84 | ## Copyright & More | 延伸阅读 85 | 86 | 笔者所有文章遵循 [知识共享 署名-非商业性使用-禁止演绎 4.0 国际许可协议](https://creativecommons.org/licenses/by-nc-nd/4.0/deed.zh),欢迎转载,尊重版权。您还可以前往 [NGTE Books](https://ng-tech.icu/books/) 主页浏览包含知识体系、编程语言、软件工程、模式与架构、Web 与大前端、服务端开发实践与工程架构、分布式基础架构、人工智能与深度学习、产品运营与创业等多类目的书籍列表: 87 | 88 | ![NGTE Books](https://s2.ax1x.com/2020/01/18/19uXtI.png) 89 | -------------------------------------------------------------------------------- /web/packages/ueme-chat-schema/src/api/WsApi.ts: -------------------------------------------------------------------------------- 1 | import { MsgBase, GroupOption } from '../protocol/MsgBase'; 2 | import { CmdMsg } from '../protocol/CmdMsg'; 3 | 4 | /** WebSocket Api */ 5 | export class WsApi { 6 | // 保存公共的状态信息 7 | token: string; 8 | from: string; 9 | 10 | async sendMsg(msg: Partial) { 11 | console.log(msg); 12 | } 13 | 14 | /** @start 好友管理 */ 15 | // 通用查询 16 | async sendGetCmdMsg(action: string, extra: {} = {}) { 17 | const msg = CmdMsg.createMsg({ from: this.from, action, ...extra }); 18 | 19 | return this.sendMsg(msg); 20 | } 21 | 22 | // 通用操作 23 | async sendPostCmdMsg(action: string, userIds: string[] | null, extra: {} = {}) { 24 | const msg = CmdMsg.createMsg({ 25 | from: this.from, 26 | to: (userIds || []).join(','), 27 | action, 28 | ...extra 29 | }); 30 | 31 | return this.sendMsg(msg); 32 | } 33 | 34 | // 查询好友列表 35 | getRoster() { 36 | return this.sendGetCmdMsg('getRoster'); 37 | } 38 | 39 | // 添加好友 40 | addFriends(userIds: string[]) { 41 | return this.sendPostCmdMsg('addFriends', userIds); 42 | } 43 | 44 | // 同意好友请求 45 | agreeFriends(userIds: string[]) { 46 | return this.sendPostCmdMsg('agreeFriends', userIds); 47 | } 48 | 49 | // 拒绝好友请求 50 | rejectFriends(userIds: string[]) { 51 | return this.sendPostCmdMsg('rejectFriends', userIds); 52 | } 53 | 54 | // 移除 55 | removeFriends(userIds: string[]) { 56 | return this.sendPostCmdMsg('removeFriends', userIds); 57 | } 58 | 59 | // 获取黑名单列表 60 | getBlacklist() { 61 | return this.sendGetCmdMsg('getBlacklist'); 62 | } 63 | 64 | // 加入黑名单 65 | addToBlackList(userIds: string[]) { 66 | return this.sendPostCmdMsg('addToBlackList', userIds); 67 | } 68 | 69 | // 移出黑名单 70 | removeBlackList(userIds: string[]) { 71 | return this.sendPostCmdMsg('removeBlackList', userIds); 72 | } 73 | 74 | /** @end 好友管理 */ 75 | 76 | /** @start 群组管理 */ 77 | // 列出所有的群组 78 | listGroups() { 79 | return this.sendGetCmdMsg('listGroups'); 80 | } 81 | 82 | // 获取群组信息 83 | queryGroupInfo(roomId: string) { 84 | return this.sendGetCmdMsg('queryGroupInfo', { to: roomId }); 85 | } 86 | 87 | // 查询群组的成员 88 | queryRoomMember(roomId: string) { 89 | return this.sendGetCmdMsg('queryRoomMember', { to: roomId }); 90 | } 91 | 92 | // 获取群组黑名单 93 | getGroupBlackList(roomId: string) { 94 | return this.sendGetCmdMsg('getGroupBlackList', { to: roomId }); 95 | } 96 | 97 | // 建立群组 98 | createGroup(groupOption: GroupOption) { 99 | return this.sendPostCmdMsg('createGroup', null, { ext: groupOption }); 100 | } 101 | 102 | // 更新群组 103 | changeGroupInfo(groupOption: GroupOption) { 104 | return this.sendPostCmdMsg('changeGroupInfo', null, { ext: groupOption }); 105 | } 106 | 107 | // 将好友加入群组 108 | addGroupMembers(roomId: string, userIds: string[]) { 109 | return this.sendPostCmdMsg('addGroupMembers', [roomId], { 110 | ext: { 111 | members: userIds 112 | } 113 | }); 114 | } 115 | 116 | // 将成员踢出群组 117 | addToGroupBlackList(roomId: string, userIds: string[]) { 118 | return this.sendPostCmdMsg('addToGroupBlackList', [roomId], { 119 | ext: { 120 | members: userIds 121 | } 122 | }); 123 | } 124 | 125 | // 解散群组 126 | destroyGroup(roomId: string) { 127 | return this.sendPostCmdMsg('destroyGroup', [roomId]); 128 | } 129 | 130 | // 退出群组 131 | leaveGroup(roomId: string) { 132 | return this.sendPostCmdMsg('leaveGroup', [roomId]); 133 | } 134 | 135 | /** @end 群组管理 */ 136 | // 创建聊天室群组 137 | createRoom(groupOption: GroupOption) { 138 | return this.sendPostCmdMsg('createGroup', null, { ext: groupOption }); 139 | } 140 | 141 | // 列出所有的聊天室 142 | listRooms() { 143 | return this.sendGetCmdMsg('listRooms'); 144 | } 145 | 146 | // 退出聊天室 147 | joinRoom(roomId: string) { 148 | return this.sendPostCmdMsg('joinRoom', [roomId]); 149 | } 150 | 151 | // 退出聊天室 152 | quitRoom(roomId: string) { 153 | return this.sendPostCmdMsg('quitRoom', [roomId]); 154 | } 155 | 156 | /** @start 聊天室管理 */ 157 | /** @end 聊天室管理 */ 158 | } 159 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Contributors][contributors-shield]][contributors-url] 2 | [![Forks][forks-shield]][forks-url] 3 | [![Stargazers][stars-shield]][stars-url] 4 | [![Issues][issues-shield]][issues-url] 5 | [![MIT License][license-shield]][license-url] 6 | 7 | 8 |
9 |

10 | 11 | Logo 12 | 13 | 14 |

15 | Demo 16 | · 17 | 更多项目 18 | · 19 | 参考资料 20 |

21 |

22 | 23 | 24 | 25 | # Introduction 26 | 27 | ueme-chat 从属于 [ueme](https://github.com/wx-chevalier/ueme?q=) 体验中台系列,该仓库是笔者对于 IM 聊天/Live 直播等领域的实验尝试集锦。 28 | 29 | ![电话虫示意](https://user-images.githubusercontent.com/5803001/47567173-68044c00-d960-11e8-99f6-6f4bd83dabfb.png) 30 | 31 | ## Nav | 导航 32 | 33 | # Getting Started 34 | 35 | To get a local copy up and running follow these simple steps. 36 | 37 | ## Prerequisites 38 | 39 | This is an example of how to list things you need to use the software and how to install them. 40 | 41 | - npm 42 | 43 | ```sh 44 | npm install npm@latest -g 45 | ``` 46 | 47 | ## Installation 48 | 49 | 1. Clone the repo 50 | 51 | ```sh 52 | git clone https://github.com/wx-chevalier/repo.git 53 | ``` 54 | 55 | 2. Install NPM packages 56 | 57 | ```sh 58 | npm install 59 | ``` 60 | 61 | 62 | 63 | ## Usage 64 | 65 | Use this space to show useful examples of how a project can be used. Additional screenshots, code examples and demos work well in this space. You may also link to more resources. 66 | 67 | _For more examples, please refer to the [Documentation](https://example.com)_ 68 | 69 | # About 70 | 71 | 72 | 73 | ## Roadmap 74 | 75 | See the [open issues](https://github.com/wx-chevalier/repo/issues) for a list of proposed features (and known issues). 76 | 77 | 78 | 79 | ## Contributing 80 | 81 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 82 | 83 | 1. Fork the Project 84 | 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) 85 | 3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) 86 | 4. Push to the Branch (`git push origin feature/AmazingFeature`) 87 | 5. Open a Pull Request 88 | 89 | 90 | 91 | ## License 92 | 93 | Distributed under the MIT License. See `LICENSE` for more information. 94 | 95 | 96 | 97 | ## Acknowledgements 98 | 99 | - [Awesome-Lists](https://github.com/wx-chevalier/Awesome-Lists): 📚 Guide to Galaxy, curated, worthy and up-to-date links/reading list for ITCS-Coding/Algorithm/SoftwareArchitecture/AI. 💫 ITCS-编程/算法/软件架构/人工智能等领域的文章/书籍/资料/项目链接精选。 100 | 101 | - [Awesome-CS-Books](https://github.com/wx-chevalier/Awesome-CS-Books): :books: Awesome CS Books/Series(.pdf by git lfs) Warehouse for Geeks, ProgrammingLanguage, SoftwareEngineering, Web, AI, ServerSideApplication, Infrastructure, FE etc. :dizzy: 优秀计算机科学与技术领域相关的书籍归档。 102 | 103 | ### FE 104 | 105 | - [ChatUI #Project#](https://github.com/alibaba/ChatUI): The UI design language and React library for Conversational UI. 106 | 107 | - [react-chat-ui](https://github.com/brandonmowat/react-chat-ui): 🙊 A library of React components for building chat UI's. 108 | 109 | - [css-only-chat](https://github.com/kkuchta/css-only-chat): A truly monstrous async web chat using no JS whatsoever on the frontend. 110 | 111 | - [react-messenger](https://github.com/sejr/react-messenger): Chat UX components built with React, inspired by Facebook Messenger. 112 | 113 | - [react-chat-elements](https://github.com/Detaysoft/react-chat-elements): Reactjs chat elements chat UI, react chat components 114 | 115 | ### Java 116 | 117 | - [CookIM #Project#](https://github.com/cookeem/CookIM): Distributed web chat application base websocket built on akka. 118 | 119 | - [gossip](https://github.com/amezng/gossip) 120 | 121 | - [cim #Project#](https://github.com/crossoverJie/cim): 📲cim(cross IM) 适用于开发者的即时通讯系统 - 122 | 123 | ### Go 124 | 125 | - [goim #Project#](https://github.com/alberliu/goim): IM 是一个即时通讯服务器,代码全部使用 Golang 完成。 126 | 127 | ### Node.js 128 | 129 | ### Chatbot 130 | 131 | - [botui](https://github.com/botui/botui) 132 | 133 | ## Copyright & More | 延伸阅读 134 | 135 | 笔者所有文章遵循[知识共享 署名 - 非商业性使用 - 禁止演绎 4.0 国际许可协议](https://creativecommons.org/licenses/by-nc-nd/4.0/deed.zh),欢迎转载,尊重版权。您还可以前往 [NGTE Books](https://ng-tech.icu/books/) 主页浏览包含知识体系、编程语言、软件工程、模式与架构、Web 与大前端、服务端开发实践与工程架构、分布式基础架构、人工智能与深度学习、产品运营与创业等多类目的书籍列表: 136 | 137 | [![NGTE Books](https://s2.ax1x.com/2020/01/18/19uXtI.png)](https://ng-tech.icu/books/) 138 | 139 | 140 | 141 | 142 | [contributors-shield]: https://img.shields.io/github/contributors/wx-chevalier/repo.svg?style=flat-square 143 | [contributors-url]: https://github.com/wx-chevalier/repo/graphs/contributors 144 | [forks-shield]: https://img.shields.io/github/forks/wx-chevalier/repo.svg?style=flat-square 145 | [forks-url]: https://github.com/wx-chevalier/repo/network/members 146 | [stars-shield]: https://img.shields.io/github/stars/wx-chevalier/repo.svg?style=flat-square 147 | [stars-url]: https://github.com/wx-chevalier/repo/stargazers 148 | [issues-shield]: https://img.shields.io/github/issues/wx-chevalier/repo.svg?style=flat-square 149 | [issues-url]: https://github.com/wx-chevalier/repo/issues 150 | [license-shield]: https://img.shields.io/github/license/wx-chevalier/repo.svg?style=flat-square 151 | [license-url]: https://github.com/wx-chevalier/repo/blob/master/LICENSE.txt 152 | -------------------------------------------------------------------------------- /header.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 101 | 366 |
367 |

368 | ueme-chat 369 |

370 |

371 | #UEME# 在线聊天咨询、客服机器人、打通企业微信 372 |

373 |
374 | 375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 | 391 | 392 |
393 |
394 |
-------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International 2 | Public License 3 | 4 | By exercising the Licensed Rights (defined below), You accept and agree 5 | to be bound by the terms and conditions of this Creative Commons 6 | Attribution-NonCommercial-ShareAlike 4.0 International Public License 7 | ("Public License"). To the extent this Public License may be 8 | interpreted as a contract, You are granted the Licensed Rights in 9 | consideration of Your acceptance of these terms and conditions, and the 10 | Licensor grants You such rights in consideration of benefits the 11 | Licensor receives from making the Licensed Material available under 12 | these terms and conditions. 13 | 14 | 15 | Section 1 -- Definitions. 16 | 17 | a. Adapted Material means material subject to Copyright and Similar 18 | Rights that is derived from or based upon the Licensed Material 19 | and in which the Licensed Material is translated, altered, 20 | arranged, transformed, or otherwise modified in a manner requiring 21 | permission under the Copyright and Similar Rights held by the 22 | Licensor. For purposes of this Public License, where the Licensed 23 | Material is a musical work, performance, or sound recording, 24 | Adapted Material is always produced where the Licensed Material is 25 | synched in timed relation with a moving image. 26 | 27 | b. Adapter's License means the license You apply to Your Copyright 28 | and Similar Rights in Your contributions to Adapted Material in 29 | accordance with the terms and conditions of this Public License. 30 | 31 | c. BY-NC-SA Compatible License means a license listed at 32 | creativecommons.org/compatiblelicenses, approved by Creative 33 | Commons as essentially the equivalent of this Public License. 34 | 35 | d. Copyright and Similar Rights means copyright and/or similar rights 36 | closely related to copyright including, without limitation, 37 | performance, broadcast, sound recording, and Sui Generis Database 38 | Rights, without regard to how the rights are labeled or 39 | categorized. For purposes of this Public License, the rights 40 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 41 | Rights. 42 | 43 | e. Effective Technological Measures means those measures that, in the 44 | absence of proper authority, may not be circumvented under laws 45 | fulfilling obligations under Article 11 of the WIPO Copyright 46 | Treaty adopted on December 20, 1996, and/or similar international 47 | agreements. 48 | 49 | f. Exceptions and Limitations means fair use, fair dealing, and/or 50 | any other exception or limitation to Copyright and Similar Rights 51 | that applies to Your use of the Licensed Material. 52 | 53 | g. License Elements means the license attributes listed in the name 54 | of a Creative Commons Public License. The License Elements of this 55 | Public License are Attribution, NonCommercial, and ShareAlike. 56 | 57 | h. Licensed Material means the artistic or literary work, database, 58 | or other material to which the Licensor applied this Public 59 | License. 60 | 61 | i. Licensed Rights means the rights granted to You subject to the 62 | terms and conditions of this Public License, which are limited to 63 | all Copyright and Similar Rights that apply to Your use of the 64 | Licensed Material and that the Licensor has authority to license. 65 | 66 | j. Licensor means the individual(s) or entity(ies) granting rights 67 | under this Public License. 68 | 69 | k. NonCommercial means not primarily intended for or directed towards 70 | commercial advantage or monetary compensation. For purposes of 71 | this Public License, the exchange of the Licensed Material for 72 | other material subject to Copyright and Similar Rights by digital 73 | file-sharing or similar means is NonCommercial provided there is 74 | no payment of monetary compensation in connection with the 75 | exchange. 76 | 77 | l. Share means to provide material to the public by any means or 78 | process that requires permission under the Licensed Rights, such 79 | as reproduction, public display, public performance, distribution, 80 | dissemination, communication, or importation, and to make material 81 | available to the public including in ways that members of the 82 | public may access the material from a place and at a time 83 | individually chosen by them. 84 | 85 | m. Sui Generis Database Rights means rights other than copyright 86 | resulting from Directive 96/9/EC of the European Parliament and of 87 | the Council of 11 March 1996 on the legal protection of databases, 88 | as amended and/or succeeded, as well as other essentially 89 | equivalent rights anywhere in the world. 90 | 91 | n. You means the individual or entity exercising the Licensed Rights 92 | under this Public License. Your has a corresponding meaning. 93 | 94 | 95 | Section 2 -- Scope. 96 | 97 | a. License grant. 98 | 99 | 1. Subject to the terms and conditions of this Public License, 100 | the Licensor hereby grants You a worldwide, royalty-free, 101 | non-sublicensable, non-exclusive, irrevocable license to 102 | exercise the Licensed Rights in the Licensed Material to: 103 | 104 | a. reproduce and Share the Licensed Material, in whole or 105 | in part, for NonCommercial purposes only; and 106 | 107 | b. produce, reproduce, and Share Adapted Material for 108 | NonCommercial purposes only. 109 | 110 | 2. Exceptions and Limitations. For the avoidance of doubt, where 111 | Exceptions and Limitations apply to Your use, this Public 112 | License does not apply, and You do not need to comply with 113 | its terms and conditions. 114 | 115 | 3. Term. The term of this Public License is specified in Section 116 | 6(a). 117 | 118 | 4. Media and formats; technical modifications allowed. The 119 | Licensor authorizes You to exercise the Licensed Rights in 120 | all media and formats whether now known or hereafter created, 121 | and to make technical modifications necessary to do so. The 122 | Licensor waives and/or agrees not to assert any right or 123 | authority to forbid You from making technical modifications 124 | necessary to exercise the Licensed Rights, including 125 | technical modifications necessary to circumvent Effective 126 | Technological Measures. For purposes of this Public License, 127 | simply making modifications authorized by this Section 2(a) 128 | (4) never produces Adapted Material. 129 | 130 | 5. Downstream recipients. 131 | 132 | a. Offer from the Licensor -- Licensed Material. Every 133 | recipient of the Licensed Material automatically 134 | receives an offer from the Licensor to exercise the 135 | Licensed Rights under the terms and conditions of this 136 | Public License. 137 | 138 | b. Additional offer from the Licensor -- Adapted Material. 139 | Every recipient of Adapted Material from You 140 | automatically receives an offer from the Licensor to 141 | exercise the Licensed Rights in the Adapted Material 142 | under the conditions of the Adapter's License You apply. 143 | 144 | c. No downstream restrictions. You may not offer or impose 145 | any additional or different terms or conditions on, or 146 | apply any Effective Technological Measures to, the 147 | Licensed Material if doing so restricts exercise of the 148 | Licensed Rights by any recipient of the Licensed 149 | Material. 150 | 151 | 6. No endorsement. Nothing in this Public License constitutes or 152 | may be construed as permission to assert or imply that You 153 | are, or that Your use of the Licensed Material is, connected 154 | with, or sponsored, endorsed, or granted official status by, 155 | the Licensor or others designated to receive attribution as 156 | provided in Section 3(a)(1)(A)(i). 157 | 158 | b. Other rights. 159 | 160 | 1. Moral rights, such as the right of integrity, are not 161 | licensed under this Public License, nor are publicity, 162 | privacy, and/or other similar personality rights; however, to 163 | the extent possible, the Licensor waives and/or agrees not to 164 | assert any such rights held by the Licensor to the limited 165 | extent necessary to allow You to exercise the Licensed 166 | Rights, but not otherwise. 167 | 168 | 2. Patent and trademark rights are not licensed under this 169 | Public License. 170 | 171 | 3. To the extent possible, the Licensor waives any right to 172 | collect royalties from You for the exercise of the Licensed 173 | Rights, whether directly or through a collecting society 174 | under any voluntary or waivable statutory or compulsory 175 | licensing scheme. In all other cases the Licensor expressly 176 | reserves any right to collect such royalties, including when 177 | the Licensed Material is used other than for NonCommercial 178 | purposes. 179 | 180 | 181 | Section 3 -- License Conditions. 182 | 183 | Your exercise of the Licensed Rights is expressly made subject to the 184 | following conditions. 185 | 186 | a. Attribution. 187 | 188 | 1. If You Share the Licensed Material (including in modified 189 | form), You must: 190 | 191 | a. retain the following if it is supplied by the Licensor 192 | with the Licensed Material: 193 | 194 | i. identification of the creator(s) of the Licensed 195 | Material and any others designated to receive 196 | attribution, in any reasonable manner requested by 197 | the Licensor (including by pseudonym if 198 | designated); 199 | 200 | ii. a copyright notice; 201 | 202 | iii. a notice that refers to this Public License; 203 | 204 | iv. a notice that refers to the disclaimer of 205 | warranties; 206 | 207 | v. a URI or hyperlink to the Licensed Material to the 208 | extent reasonably practicable; 209 | 210 | b. indicate if You modified the Licensed Material and 211 | retain an indication of any previous modifications; and 212 | 213 | c. indicate the Licensed Material is licensed under this 214 | Public License, and include the text of, or the URI or 215 | hyperlink to, this Public License. 216 | 217 | 2. You may satisfy the conditions in Section 3(a)(1) in any 218 | reasonable manner based on the medium, means, and context in 219 | which You Share the Licensed Material. For example, it may be 220 | reasonable to satisfy the conditions by providing a URI or 221 | hyperlink to a resource that includes the required 222 | information. 223 | 3. If requested by the Licensor, You must remove any of the 224 | information required by Section 3(a)(1)(A) to the extent 225 | reasonably practicable. 226 | 227 | b. ShareAlike. 228 | 229 | In addition to the conditions in Section 3(a), if You Share 230 | Adapted Material You produce, the following conditions also apply. 231 | 232 | 1. The Adapter's License You apply must be a Creative Commons 233 | license with the same License Elements, this version or 234 | later, or a BY-NC-SA Compatible License. 235 | 236 | 2. You must include the text of, or the URI or hyperlink to, the 237 | Adapter's License You apply. You may satisfy this condition 238 | in any reasonable manner based on the medium, means, and 239 | context in which You Share Adapted Material. 240 | 241 | 3. You may not offer or impose any additional or different terms 242 | or conditions on, or apply any Effective Technological 243 | Measures to, Adapted Material that restrict exercise of the 244 | rights granted under the Adapter's License You apply. 245 | 246 | 247 | Section 4 -- Sui Generis Database Rights. 248 | 249 | Where the Licensed Rights include Sui Generis Database Rights that 250 | apply to Your use of the Licensed Material: 251 | 252 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 253 | to extract, reuse, reproduce, and Share all or a substantial 254 | portion of the contents of the database for NonCommercial purposes 255 | only; 256 | 257 | b. if You include all or a substantial portion of the database 258 | contents in a database in which You have Sui Generis Database 259 | Rights, then the database in which You have Sui Generis Database 260 | Rights (but not its individual contents) is Adapted Material, 261 | including for purposes of Section 3(b); and 262 | 263 | c. You must comply with the conditions in Section 3(a) if You Share 264 | all or a substantial portion of the contents of the database. 265 | 266 | For the avoidance of doubt, this Section 4 supplements and does not 267 | replace Your obligations under this Public License where the Licensed 268 | Rights include other Copyright and Similar Rights. 269 | 270 | 271 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 272 | 273 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 274 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 275 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 276 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 277 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 278 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 279 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 280 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 281 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 282 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 283 | 284 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 285 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 286 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 287 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 288 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 289 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 290 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 291 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 292 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 293 | 294 | c. The disclaimer of warranties and limitation of liability provided 295 | above shall be interpreted in a manner that, to the extent 296 | possible, most closely approximates an absolute disclaimer and 297 | waiver of all liability. 298 | 299 | 300 | Section 6 -- Term and Termination. 301 | 302 | a. This Public License applies for the term of the Copyright and 303 | Similar Rights licensed here. However, if You fail to comply with 304 | this Public License, then Your rights under this Public License 305 | terminate automatically. 306 | 307 | b. Where Your right to use the Licensed Material has terminated under 308 | Section 6(a), it reinstates: 309 | 310 | 1. automatically as of the date the violation is cured, provided 311 | it is cured within 30 days of Your discovery of the 312 | violation; or 313 | 314 | 2. upon express reinstatement by the Licensor. 315 | 316 | For the avoidance of doubt, this Section 6(b) does not affect any 317 | right the Licensor may have to seek remedies for Your violations 318 | of this Public License. 319 | 320 | c. For the avoidance of doubt, the Licensor may also offer the 321 | Licensed Material under separate terms or conditions or stop 322 | distributing the Licensed Material at any time; however, doing so 323 | will not terminate this Public License. 324 | 325 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 326 | License. 327 | 328 | 329 | Section 7 -- Other Terms and Conditions. 330 | 331 | a. The Licensor shall not be bound by any additional or different 332 | terms or conditions communicated by You unless expressly agreed. 333 | 334 | b. Any arrangements, understandings, or agreements regarding the 335 | Licensed Material not stated herein are separate from and 336 | independent of the terms and conditions of this Public License. 337 | 338 | 339 | Section 8 -- Interpretation. 340 | 341 | a. For the avoidance of doubt, this Public License does not, and 342 | shall not be interpreted to, reduce, limit, restrict, or impose 343 | conditions on any use of the Licensed Material that could lawfully 344 | be made without permission under this Public License. 345 | 346 | b. To the extent possible, if any provision of this Public License is 347 | deemed unenforceable, it shall be automatically reformed to the 348 | minimum extent necessary to make it enforceable. If the provision 349 | cannot be reformed, it shall be severed from this Public License 350 | without affecting the enforceability of the remaining terms and 351 | conditions. 352 | 353 | c. No term or condition of this Public License will be waived and no 354 | failure to comply consented to unless expressly agreed to by the 355 | Licensor. 356 | 357 | d. Nothing in this Public License constitutes or may be interpreted 358 | as a limitation upon, or waiver of, any privileges and immunities 359 | that apply to the Licensor or You, including from the legal 360 | processes of any jurisdiction or authority. --------------------------------------------------------------------------------