| import type { AppIconType } from '@/types/app' | import type { AppIconType } from '@/types/app' | ||||
| import React, { useCallback, useEffect, useRef, useState } from 'react' | import React, { useCallback, useEffect, useRef, useState } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import PermissionSelector from '../../settings/permission-selector' | |||||
| import PermissionSelector from '@/app/components/datasets/settings/permission-selector' | |||||
| import Button from '@/app/components/base/button' | import Button from '@/app/components/base/button' | ||||
| import { RiCloseLine } from '@remixicon/react' | import { RiCloseLine } from '@remixicon/react' | ||||
| import Toast from '@/app/components/base/toast' | import Toast from '@/app/components/base/toast' |
| setFileContent('') | setFileContent('') | ||||
| } | } | ||||
| // todo: TBD billing plan | |||||
| // const plan = useProviderContextSelector(state => state.plan) | |||||
| // const enableBilling = useProviderContextSelector(state => state.enableBilling) | |||||
| // const isAppsFull = (enableBilling && plan.usage.buildApps >= plan.total.buildApps) | |||||
| const isCreatingRef = useRef(false) | const isCreatingRef = useRef(false) | ||||
| const { mutateAsync: importDSL } = useImportPipelineDSL() | const { mutateAsync: importDSL } = useImportPipelineDSL() |
| import type { RemixiconComponentType } from '@remixicon/react' | |||||
| import React from 'react' | |||||
| type ItemProps = { | |||||
| Icon: RemixiconComponentType | |||||
| title: string | |||||
| description: string | |||||
| onClick: () => void | |||||
| } | |||||
| const Item = ({ | |||||
| Icon, | |||||
| title, | |||||
| description, | |||||
| onClick, | |||||
| }: ItemProps) => { | |||||
| return ( | |||||
| <div | |||||
| className='group flex w-[337px] cursor-pointer items-center gap-x-3 rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg p-4 shadow-xs shadow-shadow-shadow-3 hover:shadow-md hover:shadow-shadow-shadow-5' | |||||
| onClick={onClick} | |||||
| > | |||||
| <div className='flex size-10 shrink-0 items-center justify-center rounded-[10px] border border-dashed border-divider-regular bg-background-section group-hover:border-state-accent-hover-alt group-hover:bg-state-accent-hover'> | |||||
| <Icon className='size-5 text-text-quaternary group-hover:text-text-accent' /> | |||||
| </div> | |||||
| <div className='flex grow flex-col gap-y-0.5 py-px'> | |||||
| <div className='system-md-semibold truncate text-text-secondary'> | |||||
| {title} | |||||
| </div> | |||||
| <div className='system-xs-regular text-text-tertiary'> | |||||
| {description} | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| ) | |||||
| } | |||||
| export default React.memo(Item) |
| import React, { useCallback, useMemo, useState } from 'react' | import React, { useCallback, useMemo, useState } from 'react' | ||||
| import Item from './item' | |||||
| import { RiAddCircleFill, RiFileUploadLine } from '@remixicon/react' | |||||
| import CreateFromScratchModal from './create-from-scratch-modal' | |||||
| import { useRouter, useSearchParams } from 'next/navigation' | |||||
| import CreateFromDSLModal, { CreateFromDSLModalTab } from './create-from-dsl-modal' | |||||
| import { useProviderContextSelector } from '@/context/provider-context' | |||||
| import { RiFileUploadLine } from '@remixicon/react' | |||||
| import Divider from '../../base/divider' | |||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import CreateFromDSLModal, { CreateFromDSLModalTab } from './create-options/create-from-dsl-modal' | |||||
| import { useRouter, useSearchParams } from 'next/navigation' | |||||
| import { useResetDatasetList } from '@/service/knowledge/use-dataset' | import { useResetDatasetList } from '@/service/knowledge/use-dataset' | ||||
| const CreateOptions = () => { | |||||
| const Footer = () => { | |||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| const [showCreateModal, setShowCreateModal] = useState(false) | |||||
| const [showImportModal, setShowImportModal] = useState(false) | const [showImportModal, setShowImportModal] = useState(false) | ||||
| const onPlanInfoChanged = useProviderContextSelector(state => state.onPlanInfoChanged) | |||||
| const searchParams = useSearchParams() | const searchParams = useSearchParams() | ||||
| const { replace } = useRouter() | const { replace } = useRouter() | ||||
| const dslUrl = searchParams.get('remoteInstallUrl') || undefined | const dslUrl = searchParams.get('remoteInstallUrl') || undefined | ||||
| return undefined | return undefined | ||||
| }, [dslUrl]) | }, [dslUrl]) | ||||
| const openCreateFromScratch = useCallback(() => { | |||||
| setShowCreateModal(true) | |||||
| }, []) | |||||
| const closeCreateFromScratch = useCallback(() => { | |||||
| setShowCreateModal(false) | |||||
| }, []) | |||||
| const openImportFromDSL = useCallback(() => { | const openImportFromDSL = useCallback(() => { | ||||
| setShowImportModal(true) | setShowImportModal(true) | ||||
| }, []) | }, []) | ||||
| }, [dslUrl, replace]) | }, [dslUrl, replace]) | ||||
| const onImportFromDSLSuccess = useCallback(() => { | const onImportFromDSLSuccess = useCallback(() => { | ||||
| onPlanInfoChanged() | |||||
| resetDatasetList() | resetDatasetList() | ||||
| }, [onPlanInfoChanged, resetDatasetList]) | |||||
| }, [resetDatasetList]) | |||||
| return ( | return ( | ||||
| <div className='flex items-center gap-x-3 px-16 py-2'> | |||||
| <Item | |||||
| Icon={RiAddCircleFill} | |||||
| title={t('datasetPipeline.creation.createFromScratch.title')} | |||||
| description={t('datasetPipeline.creation.createFromScratch.description')} | |||||
| onClick={openCreateFromScratch} | |||||
| /> | |||||
| <Item | |||||
| Icon={RiFileUploadLine} | |||||
| title={t('datasetPipeline.creation.ImportDSL.title')} | |||||
| description={t('datasetPipeline.creation.ImportDSL.description')} | |||||
| <div className='absolute bottom-0 left-0 right-0 z-10 flex flex-col gap-y-4 bg-knowledge-pipeline-creation-footer-bg px-16 pb-6 backdrop-blur-[6px]'> | |||||
| <Divider type='horizontal' className='my-0 w-8' /> | |||||
| <button | |||||
| type='button' | |||||
| className='system-md-medium flex items-center gap-x-3 text-text-accent' | |||||
| onClick={openImportFromDSL} | onClick={openImportFromDSL} | ||||
| /> | |||||
| <CreateFromScratchModal | |||||
| show={showCreateModal} | |||||
| onClose={closeCreateFromScratch} | |||||
| /> | |||||
| > | |||||
| <RiFileUploadLine className='size-5' /> | |||||
| <span>{t('datasetPipeline.creation.importDSL')}</span> | |||||
| </button> | |||||
| <CreateFromDSLModal | <CreateFromDSLModal | ||||
| show={showImportModal} | show={showImportModal} | ||||
| onClose={onCloseImportModal} | onClose={onCloseImportModal} | ||||
| ) | ) | ||||
| } | } | ||||
| export default CreateOptions | |||||
| export default React.memo(Footer) |
| 'use client' | 'use client' | ||||
| import Header from './header' | import Header from './header' | ||||
| import CreateOptions from './create-options' | |||||
| import List from './list' | import List from './list' | ||||
| import Effect from '../../base/effect' | import Effect from '../../base/effect' | ||||
| import Footer from './footer' | |||||
| const CreateFromPipeline = () => { | const CreateFromPipeline = () => { | ||||
| return ( | return ( | ||||
| > | > | ||||
| <Effect className='left-8 top-[-34px] opacity-20' /> | <Effect className='left-8 top-[-34px] opacity-20' /> | ||||
| <Header /> | <Header /> | ||||
| <CreateOptions /> | |||||
| <List /> | <List /> | ||||
| <Footer /> | |||||
| </div> | </div> | ||||
| ) | ) | ||||
| } | } |
| import { usePipelineTemplateList } from '@/service/use-pipeline' | import { usePipelineTemplateList } from '@/service/use-pipeline' | ||||
| import TemplateCard from './template-card' | import TemplateCard from './template-card' | ||||
| import CreateCard from './create-card' | |||||
| const BuiltInPipelineList = () => { | const BuiltInPipelineList = () => { | ||||
| const { data: pipelineList, isLoading } = usePipelineTemplateList({ type: 'built-in' }) | const { data: pipelineList, isLoading } = usePipelineTemplateList({ type: 'built-in' }) | ||||
| const list = pipelineList?.pipeline_templates | |||||
| if (isLoading || !list) | |||||
| return null | |||||
| const list = pipelineList?.pipeline_templates || [] | |||||
| return ( | return ( | ||||
| <div className='grid grid-cols-1 gap-3 py-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4'> | |||||
| {list.map((pipeline, index) => ( | |||||
| <div className='grid grid-cols-1 gap-3 py-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4'> | |||||
| <CreateCard /> | |||||
| {!isLoading && list.map((pipeline, index) => ( | |||||
| <TemplateCard | <TemplateCard | ||||
| key={index} | key={index} | ||||
| type='built-in' | type='built-in' |
| import React, { useCallback, useState } from 'react' | |||||
| import { useTranslation } from 'react-i18next' | |||||
| import { RiAddCircleLine } from '@remixicon/react' | |||||
| import CreateFromScratchModal from '../create-options/create-from-scratch-modal' | |||||
| const CreateCard = () => { | |||||
| const { t } = useTranslation() | |||||
| const [showCreateModal, setShowCreateModal] = useState(false) | |||||
| const openCreateFromScratch = useCallback(() => { | |||||
| setShowCreateModal(true) | |||||
| }, []) | |||||
| const closeCreateFromScratch = useCallback(() => { | |||||
| setShowCreateModal(false) | |||||
| }, []) | |||||
| return ( | |||||
| <div | |||||
| className='group relative flex h-[132px] cursor-pointer flex-col rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg pb-3 shadow-xs shadow-shadow-shadow-3' | |||||
| onClick={openCreateFromScratch} | |||||
| > | |||||
| <div className='flex items-center gap-x-3 p-4 pb-2'> | |||||
| <div className='flex size-10 shrink-0 items-center justify-center rounded-[10px] border border-dashed border-divider-regular bg-background-section group-hover:border-state-accent-hover-alt group-hover:bg-state-accent-hover'> | |||||
| <RiAddCircleLine className='size-5 text-text-quaternary group-hover:text-text-accent' /> | |||||
| </div> | |||||
| <div className='system-md-semibold truncate text-text-primary'> | |||||
| {t('datasetPipeline.creation.createFromScratch.title')} | |||||
| </div> | |||||
| </div> | |||||
| <p className='system-xs-regular line-clamp-3 px-4 py-1 text-text-tertiary'> | |||||
| {t('datasetPipeline.creation.createFromScratch.description')} | |||||
| </p> | |||||
| <CreateFromScratchModal | |||||
| show={showCreateModal} | |||||
| onClose={closeCreateFromScratch} | |||||
| /> | |||||
| </div> | |||||
| ) | |||||
| } | |||||
| export default React.memo(CreateCard) |
| import TemplateCard from './template-card' | import TemplateCard from './template-card' | ||||
| import { usePipelineTemplateList } from '@/service/use-pipeline' | import { usePipelineTemplateList } from '@/service/use-pipeline' | ||||
| import { useTranslation } from 'react-i18next' | |||||
| const CustomizedList = () => { | const CustomizedList = () => { | ||||
| const { t } = useTranslation() | |||||
| const { data: pipelineList, isLoading } = usePipelineTemplateList({ type: 'customized' }) | const { data: pipelineList, isLoading } = usePipelineTemplateList({ type: 'customized' }) | ||||
| const list = pipelineList?.pipeline_templates | |||||
| const list = pipelineList?.pipeline_templates || [] | |||||
| if (isLoading || !list) | |||||
| if (isLoading || list.length === 0) | |||||
| return null | return null | ||||
| return ( | return ( | ||||
| <div className='grid grid-cols-1 gap-3 py-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4'> | |||||
| {list.map((pipeline, index) => ( | |||||
| <TemplateCard | |||||
| key={index} | |||||
| type='customized' | |||||
| pipeline={pipeline} | |||||
| /> | |||||
| ))} | |||||
| </div> | |||||
| <> | |||||
| <div className='system-sm-semibold-uppercase pt-2 text-text-tertiary'>{t('datasetPipeline.templates.customized')}</div> | |||||
| <div className='grid grid-cols-1 gap-3 py-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4'> | |||||
| {list.map((pipeline, index) => ( | |||||
| <TemplateCard | |||||
| key={index} | |||||
| type='customized' | |||||
| pipeline={pipeline} | |||||
| /> | |||||
| ))} | |||||
| </div> | |||||
| </> | |||||
| ) | ) | ||||
| } | } | ||||
| import { useCallback, useMemo, useState } from 'react' | |||||
| import Tab from './tab' | |||||
| import BuiltInPipelineList from './built-in-pipeline-list' | import BuiltInPipelineList from './built-in-pipeline-list' | ||||
| import CustomizedList from './customized-list' | import CustomizedList from './customized-list' | ||||
| import { useTranslation } from 'react-i18next' | |||||
| const List = () => { | const List = () => { | ||||
| const { t } = useTranslation() | |||||
| const [activeTab, setActiveTab] = useState('built-in') | |||||
| const options = useMemo(() => { | |||||
| return [ | |||||
| { value: 'built-in', label: t('datasetPipeline.tabs.builtInPipeline') }, | |||||
| { value: 'customized', label: t('datasetPipeline.tabs.customized') }, | |||||
| ] | |||||
| }, [t]) | |||||
| const handleTabChange = useCallback((tab: string) => { | |||||
| setActiveTab(tab) | |||||
| }, []) | |||||
| return ( | return ( | ||||
| <div className='flex grow flex-col overflow-hidden'> | |||||
| <Tab | |||||
| activeTab={activeTab} | |||||
| handleTabChange={handleTabChange} | |||||
| options={options} | |||||
| /> | |||||
| <div className='grow overflow-y-auto px-16'> | |||||
| { | |||||
| activeTab === 'built-in' && <BuiltInPipelineList /> | |||||
| } | |||||
| { | |||||
| activeTab === 'customized' && <CustomizedList /> | |||||
| } | |||||
| </div> | |||||
| <div className='grow gap-y-1 overflow-y-auto px-16 pb-[60px] pt-1'> | |||||
| <BuiltInPipelineList /> | |||||
| <CustomizedList /> | |||||
| </div> | </div> | ||||
| ) | ) | ||||
| } | } |
| import React from 'react' | |||||
| import Item from './item' | |||||
| type TabProps = { | |||||
| activeTab: string | |||||
| handleTabChange: (tab: string) => void | |||||
| options: { value: string; label: string; }[] | |||||
| } | |||||
| const Tab = ({ | |||||
| activeTab, | |||||
| handleTabChange, | |||||
| options, | |||||
| }: TabProps) => { | |||||
| return ( | |||||
| <div className='px-16 pt-2'> | |||||
| <div className='relative flex h-10 items-center gap-x-6'> | |||||
| {options.map((option, index) => ( | |||||
| <Item | |||||
| key={index} | |||||
| option={option} | |||||
| isSelected={activeTab === option.value} | |||||
| onClick={handleTabChange} | |||||
| /> | |||||
| ))} | |||||
| <div className='absolute bottom-0 left-0 h-px w-full bg-divider-subtle' /> | |||||
| </div> | |||||
| </div> | |||||
| ) | |||||
| } | |||||
| export default React.memo(Tab) |
| import cn from '@/utils/classnames' | |||||
| import React from 'react' | |||||
| type ItemProps = { | |||||
| isSelected: boolean | |||||
| option: { value: string; label: string } | |||||
| onClick: (value: string) => void | |||||
| } | |||||
| const Item = ({ | |||||
| isSelected, | |||||
| option, | |||||
| onClick, | |||||
| }: ItemProps) => { | |||||
| return ( | |||||
| <div | |||||
| className={cn( | |||||
| 'system-sm-semibold-uppercase relative flex h-full cursor-pointer items-center', | |||||
| isSelected ? 'text-text-primary' : 'text-text-tertiary', | |||||
| )} | |||||
| onClick={onClick.bind(null, option.value)} | |||||
| > | |||||
| <span>{option.label}</span> | |||||
| {isSelected && <div className='absolute bottom-0 left-0 h-0.5 w-full bg-util-colors-blue-brand-blue-brand-600' />} | |||||
| </div> | |||||
| ) | |||||
| } | |||||
| export default React.memo(Item) |
| const translation = { | const translation = { | ||||
| creation: { | creation: { | ||||
| title: 'Create knowledge pipeline', | |||||
| title: 'Blank Knowledge Pipeline', | |||||
| createFromScratch: { | createFromScratch: { | ||||
| title: 'Create from scratch', | |||||
| description: 'Blank knowledge pipeline', | |||||
| }, | |||||
| ImportDSL: { | |||||
| title: 'Import', | |||||
| description: 'Import from a DSL file', | |||||
| title: 'Blank knowledge pipeline', | |||||
| description: 'Create a custom pipeline from scratch with full control over data processing and structure.', | |||||
| }, | }, | ||||
| importDSL: 'Import from a DSL file', | |||||
| createKnowledge: 'Create Knowledge', | createKnowledge: 'Create Knowledge', | ||||
| errorTip: 'Failed to create a Knowledge Base', | errorTip: 'Failed to create a Knowledge Base', | ||||
| successTip: 'Successfully created a Knowledge Base', | successTip: 'Successfully created a Knowledge Base', | ||||
| caution: 'Caution', | caution: 'Caution', | ||||
| }, | }, | ||||
| tabs: { | |||||
| builtInPipeline: 'Built-in pipeline', | |||||
| templates: { | |||||
| customized: 'Customized', | customized: 'Customized', | ||||
| }, | }, | ||||
| operations: { | operations: { |
| const translation = { | const translation = { | ||||
| creation: { | creation: { | ||||
| title: '创建知识库 pipeline', | |||||
| title: '创建知识流水线', | |||||
| createFromScratch: { | createFromScratch: { | ||||
| title: '从零开始创建', | |||||
| description: '空白知识库 pipeline', | |||||
| title: '空白知识流水线', | |||||
| description: '从零开始创建一个自定义知识流水线,对数据处理和结构拥有完全控制权。', | |||||
| }, | }, | ||||
| ImportDSL: { | |||||
| title: '导入', | |||||
| description: '从 DSL 文件导入', | |||||
| }, | |||||
| createKnowledge: '创建知识库', | |||||
| errorTip: '创建知识库', | |||||
| successTip: '成功创建知识库', | |||||
| importDSL: '从 DSL 文件导入', | |||||
| createKnowledge: '创建知识流水线', | |||||
| errorTip: '创建知识流水线失败', | |||||
| successTip: '成功创建知识流水线', | |||||
| caution: '注意', | caution: '注意', | ||||
| }, | }, | ||||
| tabs: { | |||||
| builtInPipeline: '内置 pipeline', | |||||
| templates: { | |||||
| customized: '自定义', | customized: '自定义', | ||||
| }, | }, | ||||
| operations: { | operations: { | ||||
| details: '详情', | details: '详情', | ||||
| editInfo: '编辑信息', | editInfo: '编辑信息', | ||||
| exportDSL: '导出 DSL', | exportDSL: '导出 DSL', | ||||
| useTemplate: '使用此知识库 pipeline', | |||||
| useTemplate: '使用此知识流水线', | |||||
| backToDataSource: '返回数据源', | backToDataSource: '返回数据源', | ||||
| process: '处理', | process: '处理', | ||||
| dataSource: '数据源', | dataSource: '数据源', | ||||
| saveAndProcess: '保存并处理', | saveAndProcess: '保存并处理', | ||||
| preview: '预览', | preview: '预览', | ||||
| exportPipeline: '导出 pipeline', | |||||
| exportPipeline: '导出知识流水线', | |||||
| convert: '转换', | convert: '转换', | ||||
| }, | }, | ||||
| knowledgeNameAndIcon: '知识库名称和图标', | knowledgeNameAndIcon: '知识库名称和图标', | ||||
| knowledgeDescription: '知识库描述', | knowledgeDescription: '知识库描述', | ||||
| knowledgeDescriptionPlaceholder: '描述知识库中的内容。详细的描述可以让 AI 更准确地访问数据集的内容。如果为空,Dify 将使用默认的命中策略。(可选)', | knowledgeDescriptionPlaceholder: '描述知识库中的内容。详细的描述可以让 AI 更准确地访问数据集的内容。如果为空,Dify 将使用默认的命中策略。(可选)', | ||||
| knowledgePermissions: '权限', | knowledgePermissions: '权限', | ||||
| editPipelineInfo: '编辑 pipeline 信息', | |||||
| pipelineNameAndIcon: 'pipeline 名称和图标', | |||||
| editPipelineInfo: '编辑知识流水线信息', | |||||
| pipelineNameAndIcon: '知识流水线名称和图标', | |||||
| deletePipeline: { | deletePipeline: { | ||||
| title: '要删除此 pipeline 模板吗?', | |||||
| content: '删除 pipeline 模板是不可逆的。', | |||||
| title: '要删除此知识流水线模板吗?', | |||||
| content: '删除知识流水线模板是不可逆的。', | |||||
| }, | }, | ||||
| exportDSL: { | exportDSL: { | ||||
| successTip: '成功导出 pipeline DSL', | |||||
| errorTip: '导出 pipeline DSL 失败', | |||||
| successTip: '成功导出知识流水线 DSL', | |||||
| errorTip: '导出知识流水线 DSL 失败', | |||||
| }, | }, | ||||
| details: { | details: { | ||||
| createdBy: '由 {{author}} 创建', | createdBy: '由 {{author}} 创建', | ||||
| inputField: '输入字段', | inputField: '输入字段', | ||||
| inputFieldPanel: { | inputFieldPanel: { | ||||
| title: '用户输入字段', | title: '用户输入字段', | ||||
| description: '用户输入字段用于定义和收集 pipeline 执行过程中所需的变量,用户可以自定义字段类型,并灵活配置输入,以满足不同数据源或文档处理的需求。', | |||||
| description: '用户输入字段用于定义和收集知识流水线执行过程中所需的变量,用户可以自定义字段类型,并灵活配置输入,以满足不同数据源或文档处理的需求。', | |||||
| uniqueInputs: { | uniqueInputs: { | ||||
| title: '非共享输入', | title: '非共享输入', | ||||
| tooltip: '非共享输入只能被选定的数据源及其下游节点访问。用户在选择其他数据源时不需要填写它。只有数据源变量引用的输入字段才会出现在第一步(数据源)中。所有其他字段将在第二步(Process Documents)中显示。', | tooltip: '非共享输入只能被选定的数据源及其下游节点访问。用户在选择其他数据源时不需要填写它。只有数据源变量引用的输入字段才会出现在第一步(数据源)中。所有其他字段将在第二步(Process Documents)中显示。', | ||||
| }, | }, | ||||
| configurationTip: '配置 {{pluginName}}', | configurationTip: '配置 {{pluginName}}', | ||||
| conversion: { | conversion: { | ||||
| title: '转换为知识库 pipeline', | |||||
| descriptionChunk1: '您现在可以将现有知识库转换为使用知识库 pipeline 来处理文档', | |||||
| title: '转换为知识流水线', | |||||
| descriptionChunk1: '您现在可以将现有知识库转换为使用知识流水线来处理文档', | |||||
| descriptionChunk2: ' —— 这是一种更开放、更灵活的方式,可以访问我们市场中的插件。新的处理方式将应用到后续添加的所有文档。', | descriptionChunk2: ' —— 这是一种更开放、更灵活的方式,可以访问我们市场中的插件。新的处理方式将应用到后续添加的所有文档。', | ||||
| warning: '此操作无法撤销。', | warning: '此操作无法撤销。', | ||||
| confirm: { | confirm: { | ||||
| title: '确认', | title: '确认', | ||||
| content: '此操作是永久性的。您将无法恢复到之前的方式。请确认转换。', | content: '此操作是永久性的。您将无法恢复到之前的方式。请确认转换。', | ||||
| }, | }, | ||||
| errorMessage: '转换数据集为 pipeline 失败', | |||||
| successMessage: '成功将数据集转换为 pipeline', | |||||
| errorMessage: '转换数据集为知识流水线失败', | |||||
| successMessage: '成功将数据集转换为知识流水线', | |||||
| }, | }, | ||||
| } | } | ||||
| 'billing-plan-title-bg': 'var(--color-billing-plan-title-bg)', | 'billing-plan-title-bg': 'var(--color-billing-plan-title-bg)', | ||||
| 'billing-plan-card-premium-bg': 'var(--color-billing-plan-card-premium-bg)', | 'billing-plan-card-premium-bg': 'var(--color-billing-plan-card-premium-bg)', | ||||
| 'billing-plan-card-enterprise-bg': 'var(--color-billing-plan-card-enterprise-bg)', | 'billing-plan-card-enterprise-bg': 'var(--color-billing-plan-card-enterprise-bg)', | ||||
| 'knowledge-pipeline-creation-footer-bg': 'var(--color-knowledge-pipeline-creation-footer-bg)', | |||||
| }, | }, | ||||
| animation: { | animation: { | ||||
| 'spin-slow': 'spin 2s linear infinite', | 'spin-slow': 'spin 2s linear infinite', |
| --color-billing-plan-title-bg: linear-gradient(95deg, #0A68FF 29.47%, #03F 105.31%); | --color-billing-plan-title-bg: linear-gradient(95deg, #0A68FF 29.47%, #03F 105.31%); | ||||
| --color-billing-plan-card-premium-bg: linear-gradient(180deg, #F90 0%, rgba(255, 153, 0, 0.00) 100%); | --color-billing-plan-card-premium-bg: linear-gradient(180deg, #F90 0%, rgba(255, 153, 0, 0.00) 100%); | ||||
| --color-billing-plan-card-enterprise-bg: linear-gradient(180deg, #03F 0%, rgba(0, 51, 255, 0.00) 100%); | --color-billing-plan-card-enterprise-bg: linear-gradient(180deg, #03F 0%, rgba(0, 51, 255, 0.00) 100%); | ||||
| --color-knowledge-pipeline-creation-footer-bg: linear-gradient(90deg, rgba(34, 34, 37, 1) 4.89%, rgba(0, 0, 0, 0) 100%); | |||||
| } | } |
| --color-billing-plan-title-bg: linear-gradient(95deg, #03F 29.47%, #03F 105.31%); | --color-billing-plan-title-bg: linear-gradient(95deg, #03F 29.47%, #03F 105.31%); | ||||
| --color-billing-plan-card-premium-bg: linear-gradient(180deg, #F90 0%, rgba(255, 153, 0, 0.00) 100%); | --color-billing-plan-card-premium-bg: linear-gradient(180deg, #F90 0%, rgba(255, 153, 0, 0.00) 100%); | ||||
| --color-billing-plan-card-enterprise-bg: linear-gradient(180deg, #03F 0%, rgba(0, 51, 255, 0.00) 100%); | --color-billing-plan-card-enterprise-bg: linear-gradient(180deg, #03F 0%, rgba(0, 51, 255, 0.00) 100%); | ||||
| --color-knowledge-pipeline-creation-footer-bg: linear-gradient(90deg, #FCFCFD 4.89%, rgba(255, 255, 255, 0.00) 100%); | |||||
| } | } |