/* * Copyright 2025 coze-dev Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { Component, type ReactNode } from 'react'; import { isEmpty, last } from 'lodash-es'; import JsonView, { ValueQuote } from '@uiw/react-json-view'; import { I18n } from '@coze-arch/i18n'; import { Tooltip, Typography } from '@coze-arch/coze-design'; import { EVENT_NAMES, sendTeaEvent } from '@coze-arch/bot-tea'; import { isValidHttpUrl } from './utils/url'; import { type Result, parse, type JsonValue } from './utils/parse'; import { ImagePreview, type JsonPreviewBasePlugin } from './plugins'; import OverlayAPI from './common/overlay'; import { NotSupport } from './common/not-support'; import styles from './index.module.less'; interface JsonLinkPreviewProps { src: unknown[]; bot_id?: string; space_id: string; entityId?: string; } export class JsonLinkPreview extends Component { parse: (inputValue: JsonValue[]) => Record; linkMap: Record; plugins: JsonPreviewBasePlugin[]; constructor(props: JsonLinkPreviewProps) { super(props); this.parse = parse; this.linkMap = this.parse(props.src as JsonValue[]); this.plugins = [new ImagePreview()]; } componentDidUpdate(prevProps: Readonly): void { this.linkMap = this.parse(this.props.src as JsonValue[]); } handleClick = ( link: string, contentType: string, extraInfo?: Record, ) => { sendTeaEvent(EVENT_NAMES.preview_link_click, { host: window.location.href, content_type: contentType, bot_id: this.props.bot_id || this.props.entityId || '', space_id: this.props.space_id, }); const renderPlugins = this.plugins.filter(plugin => plugin.match(contentType), ); if (isEmpty(renderPlugins)) { OverlayAPI.show({ content(onClose) { return (
); }, }); return; } renderPlugins.sort((a, b) => a.priority - b.priority); const renderPlugin = last(renderPlugins); renderPlugin?.render(link, extraInfo); }; render(): ReactNode { return ( { if ( type === 'value' && typeof value === 'string' && isValidHttpUrl(value) ) { return ( { this.handleClick( value, this.linkMap[value]?.contentType || '', this.linkMap[value]?.extraInfo, ); }} > {I18n.t('analytics_query_aigc_detail')} } > { event.preventDefault(); }} > {value} ); } }} /> ); } }