From bce86d2495848058c4a98840114700b7ecd6505c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E5=BE=B7=E5=8D=8E?= <1139168548@qq.com> Date: Mon, 3 Jul 2023 16:09:39 +0800 Subject: [PATCH] feat(dashboard): Add button component with URL, dashboard, and data chart navigation This commit adds a new button component to the dashboard. Users can utilize this component to navigate to specific URLs, dashboards, or data charts. Additionally, users have the ability to customize the button styles. --- .../FormGenerator/Customize/BtnFormat.tsx | 212 +++++++++++++++++ .../FormGenerator/Customize/index.ts | 1 + .../FormGenerator/Layout/ItemLayout.tsx | 3 + frontend/src/app/constants.ts | 10 +- .../components/WidgetManager/index.tsx | 2 + .../components/WidgetManager/utils/init.ts | 21 +- .../components/WidgetMapper/WidgetMapper.tsx | 4 +- .../CustomBtnWidget/CustomBtnWidget.tsx | 60 +++++ .../CustomBtnWidget/CustomBtnWidgetCore.tsx | 101 ++++++++ .../CustomBtnWidget/customBtnConfig.ts | 217 ++++++++++++++++++ .../Widgets/CustomBtnWidget/util/Icon.tsx | 16 ++ .../src/app/pages/DashBoardPage/constants.ts | 1 + .../DashBoardPage/pages/Board/slice/types.ts | 1 + .../BoardToolBar/AddMedia/AddMedia.tsx | 5 + frontend/src/types.ts | 12 + 15 files changed, 659 insertions(+), 7 deletions(-) create mode 100644 frontend/src/app/components/FormGenerator/Customize/BtnFormat.tsx create mode 100644 frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/CustomBtnWidget.tsx create mode 100644 frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/CustomBtnWidgetCore.tsx create mode 100644 frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/customBtnConfig.ts create mode 100644 frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/util/Icon.tsx diff --git a/frontend/src/app/components/FormGenerator/Customize/BtnFormat.tsx b/frontend/src/app/components/FormGenerator/Customize/BtnFormat.tsx new file mode 100644 index 000000000..15444e2fa --- /dev/null +++ b/frontend/src/app/components/FormGenerator/Customize/BtnFormat.tsx @@ -0,0 +1,212 @@ +import { Input, Radio, Select, Space, Switch, Typography } from 'antd'; +import { FC, memo, useEffect } from 'react'; +import { ChartStyleConfig } from '../../../types/ChartConfig'; + +import { ItemLayoutProps } from '../types'; +import { updateByKey } from '../../../utils/mutation'; +import { IconList } from '../../../pages/DashBoardPage/components/Widgets/CustomBtnWidget/util/Icon'; + +const BtnFormat: FC> = memo( + ({ ancestors, translate: t = title => title, data, onChange, context }) => { + const TextSecondary = props => ( + + ); + + const handleSettingChange = key => e => { + const val = e.target.value; + handleSettingChangeWithValue(key)(val); + }; + + const handleSettingChangeWithValue = key => val => { + const newData = updateByKey( + data, + 'value', + Object.assign({}, data.value, { [key]: val }), + ); + onChange?.(ancestors, newData); + }; + + const BtnTypes = [ + { + name: '默认', + value: 'default', + }, + { + name: '主要', + value: 'primary', + }, + { + name: '文字', + value: 'text', + }, + { + name: '链接', + value: 'link', + }, + { + name: '虚线', + value: 'dashed', + }, + ]; + + const BtnSizes = [ + { + name: '大', + value: 'large', + }, + { + name: '中', + value: 'middle', + }, + { + name: '小', + value: 'small', + }, + ]; + + return ( + + + 按钮文字 + + + + 按钮类型 + + + + 危险操作 + + + + 按钮图标 + + {BtnSizes.map(ele => ( + + {ele.name} + + ))} + + + + 跳转设置 + + URL + 仪表板 + 图表 + + + {data.value?.jumpType && ( + + 打开方式 + + 新窗口 + 当前页 + + + )} + {data.value?.jumpType === 'url' && ( + + URL + + + )} + {data.value?.jumpType === 'dashboard' && ( + + 仪表板 + + + )} + {data.value?.jumpType === 'datachart' && ( + + 图表 + + + )} + + ); + }, +); + +export default BtnFormat; diff --git a/frontend/src/app/components/FormGenerator/Customize/index.ts b/frontend/src/app/components/FormGenerator/Customize/index.ts index 6f9149ac2..dd238cfe2 100644 --- a/frontend/src/app/components/FormGenerator/Customize/index.ts +++ b/frontend/src/app/components/FormGenerator/Customize/index.ts @@ -36,3 +36,4 @@ export { default as TimerFormat } from './TimerFormat'; export { default as UnControlledTableHeaderPanel } from './UnControlledTableHeaderPanel'; export { default as WidgetBorder } from './WidgetBorder'; export { default as YAxisNumberFormatPanel } from './YAxisNumberFormatPanel'; +export { default as BtnFormat } from './BtnFormat'; diff --git a/frontend/src/app/components/FormGenerator/Layout/ItemLayout.tsx b/frontend/src/app/components/FormGenerator/Layout/ItemLayout.tsx index 1091942ee..b1741feb3 100644 --- a/frontend/src/app/components/FormGenerator/Layout/ItemLayout.tsx +++ b/frontend/src/app/components/FormGenerator/Layout/ItemLayout.tsx @@ -69,6 +69,7 @@ import { ViewDetailPanel, WidgetBorder, YAxisNumberFormatPanel, + BtnFormat, } from '../Customize'; import { FormGeneratorLayoutProps } from '../types'; import { groupLayoutComparer, invokeDependencyWatcher } from '../utils'; @@ -216,6 +217,8 @@ const ItemLayout: FC> = memo( return ; case ChartStyleSectionComponentType.Y_AXIS_NUMBER_FORMAT_PANEL: return ; + case ChartStyleSectionComponentType.BTN_FORMAT: + return ; default: return
{`no matched component comType of ${data.comType}`}
; } diff --git a/frontend/src/app/constants.ts b/frontend/src/app/constants.ts index 22003a54b..ab50832ef 100644 --- a/frontend/src/app/constants.ts +++ b/frontend/src/app/constants.ts @@ -17,7 +17,7 @@ */ import { FONT_FAMILY, G90 } from 'styles/StyleConstants'; -import { IFontDefault } from 'types'; +import { ICustomBtnDefault, IFontDefault } from 'types'; export enum TenantManagementMode { Team = 'TEAM', @@ -215,6 +215,7 @@ export const ChartStyleSectionComponentType = { TEXT: 'text', CONDITIONAL_STYLE: 'conditionalStylePanel', RADIO: 'radio', + BTN_FORMAT: 'btnFormat', // Customize Component FONT_ALIGNMENT: 'fontAlignment', @@ -253,6 +254,13 @@ export const FONT_DEFAULT: IFontDefault = { color: G90, }; +export const CUSTOM_BTN_DEFAULT: ICustomBtnDefault = { + btnSize: 'middle', + btnType: 'default', + content: '按钮', + danger: false, +}; + export enum AuthorizationStatus { Initialized = 'initialized', Pending = 'pending', diff --git a/frontend/src/app/pages/DashBoardPage/components/WidgetManager/index.tsx b/frontend/src/app/pages/DashBoardPage/components/WidgetManager/index.tsx index cd3397c97..f61a34e47 100644 --- a/frontend/src/app/pages/DashBoardPage/components/WidgetManager/index.tsx +++ b/frontend/src/app/pages/DashBoardPage/components/WidgetManager/index.tsx @@ -39,6 +39,7 @@ import tabProto from '../Widgets/TabWidget/tabConfig'; import timerProto from '../Widgets/TimerWidget/timerConfig'; import videoProto from '../Widgets/VideoWidget/videoConfig'; import { widgetManagerInstance as widgetManager } from './WidgetManager'; +import customBtnProto from '../Widgets/CustomBtnWidget/customBtnConfig'; const protoList: WidgetProto[] = [ linkedChartProto, // chart @@ -57,6 +58,7 @@ const protoList: WidgetProto[] = [ radioGroupProto, textProto, timeProto, + customBtnProto, dropDownTree, rangeTimeProto, rangeValueProto, diff --git a/frontend/src/app/pages/DashBoardPage/components/WidgetManager/utils/init.ts b/frontend/src/app/pages/DashBoardPage/components/WidgetManager/utils/init.ts index 7fd6f7d3c..841aebc4a 100644 --- a/frontend/src/app/pages/DashBoardPage/components/WidgetManager/utils/init.ts +++ b/frontend/src/app/pages/DashBoardPage/components/WidgetManager/utils/init.ts @@ -317,7 +317,18 @@ export const TitleI18N = { }, }, }; -export const initPaddingTpl = () => { +export const initPaddingTpl = (obj?: { + top?: number; + bottom?: number; + left?: number; + right?: number; +}) => { + const { top, bottom, left, right } = obj || { + top: 8, + bottom: 8, + left: 8, + right: 8, + }; const paddingTpl: ChartStyleConfig = { label: 'padding.paddingGroup', key: 'paddingGroup', @@ -326,25 +337,25 @@ export const initPaddingTpl = () => { { label: 'padding.top', key: 'top', - value: 8, + value: top, comType: 'inputNumber', }, { label: 'padding.bottom', key: 'bottom', - value: 8, + value: bottom, comType: 'inputNumber', }, { label: 'padding.left', key: 'left', - value: 8, + value: left, comType: 'inputNumber', }, { label: 'padding.right', key: 'right', - value: 8, + value: right, comType: 'inputNumber', }, ], diff --git a/frontend/src/app/pages/DashBoardPage/components/WidgetMapper/WidgetMapper.tsx b/frontend/src/app/pages/DashBoardPage/components/WidgetMapper/WidgetMapper.tsx index 6cad8b5d6..76cfec677 100644 --- a/frontend/src/app/pages/DashBoardPage/components/WidgetMapper/WidgetMapper.tsx +++ b/frontend/src/app/pages/DashBoardPage/components/WidgetMapper/WidgetMapper.tsx @@ -30,6 +30,7 @@ import { RichTextWidget } from '../Widgets/RichTextWidget/RichTextWidget'; import { TabWidget } from '../Widgets/TabWidget/TabWidget'; import { TimerWidget } from '../Widgets/TimerWidget/TimerWidget'; import { VideoWidget } from '../Widgets/VideoWidget/VideoWidget'; +import { CustomBtnWidget } from '../Widgets/CustomBtnWidget/CustomBtnWidget'; export const WidgetMapper: React.FC<{ boardEditing: boolean; @@ -63,7 +64,8 @@ export const WidgetMapper: React.FC<{ return ; case ORIGINAL_TYPE_MAP.timer: return ; - + case ORIGINAL_TYPE_MAP.customBtn: + return ; // tab case ORIGINAL_TYPE_MAP.tab: return ; diff --git a/frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/CustomBtnWidget.tsx b/frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/CustomBtnWidget.tsx new file mode 100644 index 000000000..0be497df8 --- /dev/null +++ b/frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/CustomBtnWidget.tsx @@ -0,0 +1,60 @@ +/** + * Datart + * + * Copyright 2021 + * + * 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 { Space } from 'antd'; +import { WidgetContext } from 'app/pages/DashBoardPage/components/WidgetProvider/WidgetProvider'; +import { memo, useContext } from 'react'; +import { BoardContext } from '../../BoardProvider/BoardProvider'; +import { FlexStyle, ZIndexStyle } from '../../WidgetComponents/constants'; +import { EditMask } from '../../WidgetComponents/EditMask'; +import { LockIconFn } from '../../WidgetComponents/StatusIcon'; +import { StyledWidgetToolBar } from '../../WidgetComponents/StyledWidgetToolBar'; +import { WidgetDropdownList } from '../../WidgetComponents/WidgetDropdownList'; +import { WidgetWrapper } from '../../WidgetComponents/WidgetWrapper'; +import { + getWidgetBaseStyle, + getWidgetTitle, +} from '../../WidgetManager/utils/utils'; +import { CustomBtnWidgetCore } from './CustomBtnWidgetCore'; + +export const CustomBtnWidget: React.FC<{ hideTitle: boolean }> = memo( + ({ hideTitle }) => { + const widget = useContext(WidgetContext); + const { editing } = useContext(BoardContext); + const { background, border, padding } = getWidgetBaseStyle( + widget.config.customConfig.props, + ); + const title = getWidgetTitle(widget.config.customConfig.props); + title.title = widget.config.name; + return ( + + + {editing && } + + + + + + + + ); + }, +); diff --git a/frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/CustomBtnWidgetCore.tsx b/frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/CustomBtnWidgetCore.tsx new file mode 100644 index 000000000..fa1fce8d4 --- /dev/null +++ b/frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/CustomBtnWidgetCore.tsx @@ -0,0 +1,101 @@ +/** + * Datart + * + * Copyright 2021 + * + * 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 { Button } from 'antd'; +import React, { memo, useContext } from 'react'; +import useDrillThrough from '../../../../../hooks/useDrillThrough'; +import { BoardContext } from '../../BoardProvider/BoardProvider'; +import { WidgetContext } from '../../WidgetProvider/WidgetProvider'; +import { customBtnWidgetToolKit } from './customBtnConfig'; +import { Icon } from './util/Icon'; + +export const CustomBtnWidgetCore: React.FC = memo(props => { + const widget = useContext(WidgetContext); + const { orgId } = useContext(BoardContext); + const customBtnConfig = customBtnWidgetToolKit.getCustomBtnConfig( + widget.config.customConfig.props, + ); + const customBtnFont = customBtnWidgetToolKit.getCustomBtnFont( + widget.config.customConfig.props, + ); + + const btnStyle = { + width: '100%', + height: '100%', + // todo: 适配background style,优先使用button type的预设值 + // 但下面这样会导致按钮type预设失效 + // background: 'transparent', + }; + + // todo: 需要特殊处理font size与 font color, + // 令其优先使用button type和button size的预设值 + const textStyle = { + // ...customBtnFont + }; + + const finalStyle = customBtnFont ? { ...textStyle, ...btnStyle } : btnStyle; + + const { openNewTab, openBrowserTab, redirectByUrl, openNewByUrl } = + useDrillThrough(); + + const onClick = () => { + switch (customBtnConfig?.jumpType) { + case 'dashboard': + jump(customBtnConfig?.dashboardId); + break; + case 'datachart': + jump(customBtnConfig?.datachartId); + break; + case 'url': + jumpByHref(); + } + }; + + const jump = relId => { + if (!relId) return; + const { target } = customBtnConfig; + if (target === '_self') { + openNewTab(orgId, relId); + } else { + openBrowserTab(orgId, relId); + } + }; + + const jumpByHref = () => { + const { target, href } = customBtnConfig; + if (!href) return; + if (target === '_self') { + redirectByUrl(href); + } else { + openNewByUrl(href); + } + }; + + return ( + + ); +}); diff --git a/frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/customBtnConfig.ts b/frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/customBtnConfig.ts new file mode 100644 index 000000000..66a490311 --- /dev/null +++ b/frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/customBtnConfig.ts @@ -0,0 +1,217 @@ +/** + * Datart + * + * Copyright 2021 + * + * 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 { CUSTOM_BTN_DEFAULT, FONT_DEFAULT } from 'app/constants'; +import { + ORIGINAL_TYPE_MAP, + TimeDefault, +} from 'app/pages/DashBoardPage/constants'; +import type { + WidgetActionListItem, + widgetActionType, + WidgetMeta, + WidgetProto, + WidgetToolkit, +} from 'app/pages/DashBoardPage/types/widgetTypes'; +import { getJsonConfigs } from 'app/pages/DashBoardPage/utils'; +import { WHITE } from 'styles/StyleConstants'; +import { ICustomBtnDefault, IFontDefault } from '../../../../../../types'; +import { ITimeDefault } from '../../../types/widgetTypes'; +import { + initBackgroundTpl, + initBorderTpl, + initInteractionTpl, + initPaddingTpl, + initTitleTpl, + initWidgetName, + InteractionI18N, + PaddingI18N, + TitleI18N, + widgetTpl, +} from '../../WidgetManager/utils/init'; + +const initCustomBtnTpl = () => { + return [ + { + label: 'customBtn.meta', + key: 'metaGroup', + comType: 'group', + rows: [ + { + label: '按钮属性', + key: 'btnFormat', + comType: 'btnFormat', + value: CUSTOM_BTN_DEFAULT, + }, + ], + }, + { + label: 'customBtn.btnFontGroup', + key: 'btnFontGroup', + comType: 'group', + rows: [ + { + label: '按钮字体', + key: 'btnFont', + comType: 'font', + value: FONT_DEFAULT, + }, + ], + }, + ]; +}; +const customBtnI18N = { + zh: { + meta: '按钮属性', + btnFontGroup: '按钮字体', + }, + en: { + meta: 'Button Props', + btnFontGroup: 'Button Font', + }, +}; +const NameI18N = { + zh: '按钮', + en: 'Button', +}; +export const widgetMeta: WidgetMeta = { + icon: 'query-widget', + originalType: ORIGINAL_TYPE_MAP.customBtn, + canWrapped: true, + controllable: false, + linkable: false, + canFullScreen: true, + singleton: false, + + i18ns: [ + { + lang: 'zh-CN', + translation: { + ...InteractionI18N.zh, + desc: 'customBtn', + widgetName: NameI18N.zh, + action: {}, + title: TitleI18N.zh, + customBtn: customBtnI18N.zh, + background: { backgroundGroup: '背景' }, + padding: PaddingI18N.zh, + border: { borderGroup: '边框' }, + }, + }, + { + lang: 'en-US', + translation: { + ...InteractionI18N.en, + desc: 'customBtn', + widgetName: NameI18N.en, + action: {}, + title: TitleI18N.en, + background: { backgroundGroup: 'Background' }, + padding: PaddingI18N.en, + customBtn: customBtnI18N.en, + border: { borderGroup: 'Border' }, + }, + }, + ], +}; +export interface CustomBtnWidgetToolKit extends WidgetToolkit { + getCustomBtnConfig: (props) => ICustomBtnDefault; + getCustomBtnFont: (props) => IFontDefault; +} +export const widgetToolkit: CustomBtnWidgetToolKit = { + create: opt => { + const widget = widgetTpl(); + widget.id = widgetMeta.originalType + widget.id; + widget.parentId = opt.parentId || ''; + widget.viewIds = opt.viewIds || []; + widget.relations = opt.relations || []; + widget.config.originalType = widgetMeta.originalType; + widget.config.type = 'media'; + widget.config.name = opt.name || ''; + widget.config.rect.width = 100; + widget.config.rect.height = 60; + widget.config.pRect.width = 2; + widget.config.pRect.height = 1; + + widget.config.customConfig.props = [ + ...initCustomBtnTpl(), + // { ...initTitleTpl() }, + { ...initBackgroundTpl(WHITE) }, + { ...initPaddingTpl({ top: 0, bottom: 0, left: 0, right: 0 }) }, + { ...initBorderTpl() }, + ]; + + widget.config.customConfig.interactions = [...initInteractionTpl()]; + + return widget; + }, + getName(key) { + return initWidgetName(NameI18N, key); + }, + edit() {}, + save() {}, + getDropDownList(...arg) { + const list: WidgetActionListItem[] = [ + { + key: 'edit', + renderMode: ['edit'], + }, + { + key: 'delete', + renderMode: ['edit'], + }, + { + key: 'lock', + renderMode: ['edit'], + }, + { + key: 'group', + renderMode: ['edit'], + }, + ]; + return list; + }, + getCustomBtnConfig(props) { + const [btnFormat] = getJsonConfigs(props, ['metaGroup'], ['btnFormat']) as [ + ICustomBtnDefault, + ]; + return btnFormat; + }, + getCustomBtnFont(props) { + const [btnFont] = getJsonConfigs(props, ['btnFontGroup'], ['btnFont']) as [ + IFontDefault, + ]; + return btnFont; + }, + // lock() {}, + // unlock() {}, + // copy() {}, + // paste() {}, + // delete() {}, + // changeTitle() {}, + // getMeta() {}, + // getWidgetName() {}, + // // +}; + +const customBtnProto: WidgetProto = { + originalType: widgetMeta.originalType, + meta: widgetMeta, + toolkit: widgetToolkit, +}; +export const customBtnWidgetToolKit = widgetToolkit; +export default customBtnProto; diff --git a/frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/util/Icon.tsx b/frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/util/Icon.tsx new file mode 100644 index 000000000..a2e7e58d9 --- /dev/null +++ b/frontend/src/app/pages/DashBoardPage/components/Widgets/CustomBtnWidget/util/Icon.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import * as icons from '@ant-design/icons'; + +export const Icon = (props: { icon: string }) => { + const { icon } = props; + if (icons[icon] === undefined) return null; + const antIcon: { [key: string]: any } = icons; + return React.createElement(antIcon[icon]); +}; + +export const IconList = Object.keys(icons).map(icon => { + return { + key: icon, + value: icon, + }; +}); diff --git a/frontend/src/app/pages/DashBoardPage/constants.ts b/frontend/src/app/pages/DashBoardPage/constants.ts index b2b934420..a41c0f073 100644 --- a/frontend/src/app/pages/DashBoardPage/constants.ts +++ b/frontend/src/app/pages/DashBoardPage/constants.ts @@ -84,6 +84,7 @@ export const ORIGINAL_TYPE_MAP = { timer: 'timer', richText: 'richText', iframe: 'iframe', + customBtn: 'customBtn', queryBtn: 'queryBtn', resetBtn: 'resetBtn', diff --git a/frontend/src/app/pages/DashBoardPage/pages/Board/slice/types.ts b/frontend/src/app/pages/DashBoardPage/pages/Board/slice/types.ts index c1a8fa7f5..553c46e9f 100644 --- a/frontend/src/app/pages/DashBoardPage/pages/Board/slice/types.ts +++ b/frontend/src/app/pages/DashBoardPage/pages/Board/slice/types.ts @@ -335,6 +335,7 @@ export declare const MediaWidgetTypes: [ 'image', 'video', 'iframe', + 'customBtn', ]; export type MediaWidgetType = typeof MediaWidgetTypes[number]; diff --git a/frontend/src/app/pages/DashBoardPage/pages/BoardEditor/components/BoardToolBar/AddMedia/AddMedia.tsx b/frontend/src/app/pages/DashBoardPage/pages/BoardEditor/components/BoardToolBar/AddMedia/AddMedia.tsx index 34cb4e18f..01a1f527a 100644 --- a/frontend/src/app/pages/DashBoardPage/pages/BoardEditor/components/BoardToolBar/AddMedia/AddMedia.tsx +++ b/frontend/src/app/pages/DashBoardPage/pages/BoardEditor/components/BoardToolBar/AddMedia/AddMedia.tsx @@ -72,6 +72,11 @@ export const AddMedia: React.FC<{}> = () => { icon: '', type: 'video', }, + { + name: '按钮', + icon: '', + type: 'customBtn', + }, ]; const mediaWidgetItems = ( diff --git a/frontend/src/types.ts b/frontend/src/types.ts index d619fef36..d2b4fa8bd 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -74,3 +74,15 @@ export interface IFontDefault { fontStyle: string; color: string; } +export interface ICustomBtnDefault { + content: string; + btnType: 'primary' | 'default' | 'text' | 'dashed' | 'link'; + btnSize: 'large' | 'middle' | 'small'; + danger: boolean; + icon?: string; + jumpType?: 'dashboard' | 'datachart' | 'url'; + dashboardId?: string; + datachartId?: string; + href?: string; + target?: '_blank' | '_self' | '_parent' | '_top'; +}