From 8ee1215a9a04c6c47eec04c35ab9dcee2aa61f64 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Sun, 5 Mar 2023 17:17:09 +0800 Subject: [PATCH] feat: add image parser then we can flexibly modify the domain name without worrying about the file storage path --- client/packages/design/components/Avatar/index.tsx | 3 ++- client/packages/design/components/Image/index.tsx | 7 +++++++ client/packages/design/components/index.ts | 2 +- client/shared/model/user.ts | 5 ----- client/web/src/init.tsx | 4 ++++ client/web/src/utils/file-helper.ts | 4 +++- docker-compose.env | 1 + server/.env.example | 1 + server/packages/sdk/src/services/lib/settings.ts | 3 ++- website/docs/deployment/environment.md | 3 ++- .../current/deployment/environment.md | 3 ++- 11 files changed, 25 insertions(+), 11 deletions(-) diff --git a/client/packages/design/components/Avatar/index.tsx b/client/packages/design/components/Avatar/index.tsx index b827d8da..11ff9307 100644 --- a/client/packages/design/components/Avatar/index.tsx +++ b/client/packages/design/components/Avatar/index.tsx @@ -9,6 +9,7 @@ import _omit from 'lodash/omit'; import type { AvatarProps as AntdAvatarProps } from 'antd/lib/avatar'; import { getTextColorHex, px2rem } from './utils'; import { isValidStr } from '../utils'; +import { imageUrlParser } from '../Image'; export { getTextColorHex }; @@ -18,7 +19,7 @@ export interface AvatarProps extends AntdAvatarProps { } export const Avatar: React.FC = React.memo((_props) => { const { isOnline, ...props } = _props; - const src = isValidStr(props.src) ? props.src : undefined; + const src = isValidStr(props.src) ? imageUrlParser(props.src) : undefined; const name = useMemo(() => _upperCase(_head(props.name)), [props.name]); diff --git a/client/packages/design/components/Image/index.tsx b/client/packages/design/components/Image/index.tsx index ddfd6b2e..97889a44 100644 --- a/client/packages/design/components/Image/index.tsx +++ b/client/packages/design/components/Image/index.tsx @@ -1,6 +1,8 @@ import React from 'react'; import { Image as AntdImage, ImageProps as AntdImageProps } from 'antd'; +export let imageUrlParser = (url: string) => url; + export const Image: React.FC = React.memo((props) => { return ( = React.memo((props) => { preview={false} loading="lazy" {...props} + src={props.src ? imageUrlParser(props.src) : undefined} /> ); }); Image.displayName = 'Image'; + +export function setImageUrlParser(parser: (url: string) => string): void { + imageUrlParser = parser; +} diff --git a/client/packages/design/components/index.ts b/client/packages/design/components/index.ts index 71061365..eea9c9be 100644 --- a/client/packages/design/components/index.ts +++ b/client/packages/design/components/index.ts @@ -6,7 +6,7 @@ export { CombinedAvatar } from './Avatar/combined'; export { DelayTip } from './DelayTip'; export { Highlight } from './Highlight'; export { Icon } from './Icon'; -export { Image } from './Image'; +export { Image, setImageUrlParser } from './Image'; export { SensitiveText } from './SensitiveText'; export { VirtualChatList } from './VirtualChatList'; diff --git a/client/shared/model/user.ts b/client/shared/model/user.ts index 097ea055..87e84674 100644 --- a/client/shared/model/user.ts +++ b/client/shared/model/user.ts @@ -8,7 +8,6 @@ import _uniq from 'lodash/uniq'; import _flatten from 'lodash/flatten'; import _zipObject from 'lodash/zipObject'; import { t } from '../i18n'; -import { parseUrlStr } from '../utils/url-helper'; export interface UserBaseInfo { _id: string; @@ -264,10 +263,6 @@ export async function fetchUserInfo(userId: string): Promise { const userInfo = await _fetchUserInfo(userId); - if (userInfo && userInfo.avatar) { - userInfo.avatar = parseUrlStr(userInfo.avatar); // 用户信息从来源支持常量替换 - } - return userInfo; } diff --git a/client/web/src/init.tsx b/client/web/src/init.tsx index 252f1ca3..ec12476b 100644 --- a/client/web/src/init.tsx +++ b/client/web/src/init.tsx @@ -14,12 +14,14 @@ import { isDevelopment, setErrorHook, showToasts, + parseUrlStr, } from 'tailchat-shared'; import { getPopupContainer } from './utils/dom-helper'; import { getUserJWT } from './utils/jwt-helper'; import _get from 'lodash/get'; import { recordMeasure } from './utils/measure-helper'; import { postMessageEvent } from './utils/event-helper'; +import { setImageUrlParser } from 'tailchat-design'; recordMeasure('init'); postMessageEvent('init'); @@ -68,6 +70,8 @@ setGlobalLoading((text) => { return hide; }); +setImageUrlParser(parseUrlStr); + const backToLoginPage = (() => { let timer: number; diff --git a/client/web/src/utils/file-helper.ts b/client/web/src/utils/file-helper.ts index bb876502..54757bb6 100644 --- a/client/web/src/utils/file-helper.ts +++ b/client/web/src/utils/file-helper.ts @@ -1,4 +1,5 @@ import _get from 'lodash/get'; +import { parseUrlStr } from 'tailchat-shared'; /** * 传入一个图片文件, 返回对应的 Base64 编码 @@ -91,8 +92,9 @@ export async function blobUrlToFile( */ export function downloadUrl(url: string, fileName: string) { const a = document.createElement('a'); - a.href = url; + a.href = parseUrlStr(url); a.download = fileName; // 这里填保存成的文件名 + a.target = '_blank'; a.click(); } diff --git a/docker-compose.env b/docker-compose.env index 30653735..5ee7c346 100644 --- a/docker-compose.env +++ b/docker-compose.env @@ -11,6 +11,7 @@ MONGO_URL=mongodb://mongo/tailchat SECRET= # file +STAIC_HOST="{BACKEND}" API_URL=https://tailchat-nightly.moonrailgun.com # minio diff --git a/server/.env.example b/server/.env.example index b9be86f4..ea0080bf 100644 --- a/server/.env.example +++ b/server/.env.example @@ -10,6 +10,7 @@ REDIS_URL=redis://localhost:6379/ TRANSPORTER= # 填写服务端可访问的接口地址 +STAIC_HOST="{BACKEND}" API_URL= # 文件存储 diff --git a/server/packages/sdk/src/services/lib/settings.ts b/server/packages/sdk/src/services/lib/settings.ts index 102e6b59..ef8a9b6f 100644 --- a/server/packages/sdk/src/services/lib/settings.ts +++ b/server/packages/sdk/src/services/lib/settings.ts @@ -8,6 +8,7 @@ dotenv.config(); */ const port = process.env.PORT ? Number(process.env.PORT) : 11000; const apiUrl = process.env.API_URL || `http://127.0.0.1:${port}`; +const staticHost = process.env.STAIC_HOST || apiUrl; export const config = { port, secret: process.env.SECRET || 'tailchat', @@ -35,7 +36,7 @@ export const config = { : 1 * 1024 * 1024, }, apiUrl, - staticUrl: `${apiUrl}/static/`, + staticUrl: `${staticHost}/static/`, enableOpenapi: true, // 是否开始openapi emailVerification: checkEnvTrusty(process.env.EMAIL_VERIFY) || false, // 是否在注册后验证邮箱可用性 diff --git a/website/docs/deployment/environment.md b/website/docs/deployment/environment.md index ffc9e7c3..39924ad5 100644 --- a/website/docs/deployment/environment.md +++ b/website/docs/deployment/environment.md @@ -9,7 +9,8 @@ title: Environment Variable | ----- | ------ | --- | | PORT | 11000 | Gateway service port number | | SECRET | tailchat | encryption key, used for JWT | -| API_URL | http://127.0.0.1:11000 | Externally accessible url address, used for file service access | +| STAIC_HOST | "{BACKEND}" | Externally accessible static service address, used for file service access, the default is the dynamic server address inferred from the front-end request, if it is expected to be stored in a third-party OSS, it needs to be modified | +| API_URL | http://127.0.0.1:11000 | Externally accessible url address, used for issuer issuance on open platforms or as a fallback for file services | | MONGO_URL | - | Database service address | | REDIS_URL | - | Redis service address | | MINIO_URL | - | File service address (minio) | diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/deployment/environment.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/deployment/environment.md index 33d4794e..6aa818ee 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/deployment/environment.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/deployment/environment.md @@ -9,7 +9,8 @@ title: 环境变量 | ----- | ------ | --- | | PORT | 11000 | 网关服务端口号 | | SECRET | tailchat | 加密秘钥, 用于JWT | -| API_URL | http://127.0.0.1:11000 | 对外可访问的url地址,用于文件服务访问 | +| STAIC_HOST | "{BACKEND}" | 对外可访问的静态服务地址,用于文件服务访问, 默认为动态根据前端请求推断出的服务端地址,如果期望存储在第三方OSS中需要进行修改 | +| API_URL | http://127.0.0.1:11000 | 对外可访问的url地址,用于开放平台的issuer签发或者作为文件服务的fallback | | MONGO_URL | - | 数据库服务地址 | | REDIS_URL | - | Redis服务地址 | | MINIO_URL | - | 文件服务地址(minio) |