### What problem does this PR solve? feat: Add component TuShare #1739 ### Type of change - [ ] Bug Fix (non-breaking change which fixes an issue) - [x] New Feature (non-breaking change which adds functionality) - [ ] Documentation Update - [ ] Refactoring - [ ] Performance Improvement - [ ] Other (please describe):tags/v0.13.0
| copy: ['src/conf.json'], | copy: ['src/conf.json'], | ||||
| proxy: { | proxy: { | ||||
| '/v1': { | '/v1': { | ||||
| target: 'http://127.0.0.1:9380/', | |||||
| target: 'http://127.0.0.1:9456/', | |||||
| changeOrigin: true, | changeOrigin: true, | ||||
| ws: true, | ws: true, | ||||
| logger: console, | logger: console, |
| <svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="24" height="32"> | |||||
| <title>tushare</title> | |||||
| <defs> | |||||
| <image width="20" height="32" id="img1" | |||||
| href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAdCAMAAACdWLz3AAAAAXNSR0IB2cksfwAAAnZQTFRF///////9z/msyvil/f/38Pzl/f/8xfGhf+Euf+Evs+2C+P33/v/9y/WiqO5gvPKEnulgjOREjuVGnuldtOmhb9VMe9hb6Pji8fzlpu5erO9oqu5lk+ZMj+VJk+ZLd9pCWM4xXtA3UMwlnOKD+/73uPF9p+5fr/BtmOhTkeZJgt9GYNA8Y9I+ZNI+Us0os+mh7/zhsO9uqO5foetcjuVEbtc9YNE9YdE7U80oi91u+v758v/zw/idsPFwo+tfcddFVs4wYtNAneiR+v////br/+fO/+nQ/+nR/+bO/+PL9vfh+f7y6/nl0fLG6fDR/+TM//fv/9Ke/4kF/5IW/5IX/4wL/5cg/9ap//v6//r4/86Y/5EV/44O/4kH/9mv/9Og/4wJ/5Qb/5Qc/5gk/+zW/+G//5MY/9qw/9Oh/40L/5Ud/44N/9an/8aF/40M/40N/9qx/5oo//jw//Lj/50t//jx//r0/9Ge/82V/9Gc/8uR/5Ye/5Qa/+3a/5wr/5Uc/+C+//36//ny/9Gd/6ZC/7Ja/7Nd/+rT/7pu/65R/6tL/6ZA/+TF/5ws/5AR/6pJ/9mu/4wK/5gl//Xp//bt/7lq/7Ne/7lp/6I5/5AS/+TG//Tp/61R/6M6/5Ue/9Oi/8+Z/+bK/48R/9y0/7Zj/8qP/48Q/+3Z/5sq/6hF/48S//Hh//38/6Q8/8+a/9y1/48P/6lI///+/82U/5IY/5Yg/+bL/4oH/9eq//z5/6pK/4sI/5MZ/61Q/69V/5EU/4oF/7Jb//Xq/6dE/65T//v3/8aG/54x/58y//79//v2/+fM/8+Y/8iJ/8eI/8iL/9Sj/+XHh/PjeAAAANJ0Uk5TAAD//wCgAP////8AAP/////////////QoP//////////////AP//////////////4P///////////wAA/////////wBA///////gAKD///8A/////////wAA////////////////////////////////AMD/AAD/////////////AAD/////////////////////YCD///////9g////////////////////4AD//////wD///////8A//////////9Q//8A////AAD/////////BLUGZwAAAZpJREFUeJxNkV0og2EUx89f87U3lreGiRIrN4oLJc0FkSQUoVZqboiLKZFys3zcKCVld5QkoaYpUfKZfJR244KaWhEbttWo+WrTPM/7sTk3z3N+73PO/z3nD1ICLKLqXT6SOcOngHAcpqQiHq8qzE0weFRo/Aev4z3LE/AiIWRS2aEkVA/I/yPrJ8UoJqCNQSlfJzKz4zumBSzs8pOGRblNb0iMhEX0Sy/t6mBWRNkgDEYFzKpw+D4zU4L+QsywfJQ1ConwyVD05k/xR8KTQfNYEJDLKTlrnJdOgN6yghEF+su52hj/MO1ThEj84CsZYWxSuMxWoBFDivgc3KTAaCmsRHY+134OhxYtSJ+HPqIFvBiO6lwcLl2xhZToeqTqZXgCHK64ImxLVd0SXA26SV9yjLUbbzr5O+5sHG7ghMSiDDgQZA4EzO2MOTeLA9TA5Gh7qdlFTdhaoN19v46oBY2gPeDRVbEzADg6D0LUhfdWJn2K39hK2let5rbooQaaI5tk3DkzwflcTXRWX+YxVqpuXmF+UDIqbOLpH/bLcsV/98goAAAAAElFTkSuQmCC" /> | |||||
| </defs> | |||||
| <style> | |||||
| </style> | |||||
| <use id="Background" href="#img1" x="6" y="1" /> | |||||
| </svg> |
| concentrator: 'Concentrator', | concentrator: 'Concentrator', | ||||
| concentratorDescription: | concentratorDescription: | ||||
| 'A component that receives the output from the upstream component and passes it on as input to the downstream components.', | 'A component that receives the output from the upstream component and passes it on as input to the downstream components.', | ||||
| tuShare: 'TuShare', | |||||
| tuShareDescription: | |||||
| 'This component can be used to obtain financial news briefs from mainstream financial websites, aiding industry and quantitative research.', | |||||
| tuShareSrcOptions: { | |||||
| sina: 'Sina', | |||||
| wallstreetcn: 'wallstreetcn', | |||||
| '10jqka': 'Straight flush', | |||||
| eastmoney: 'Eastmoney', | |||||
| yuncaijing: 'YUNCAIJING', | |||||
| fenghuang: 'FENGHUANG', | |||||
| jinrongjie: 'JRJ', | |||||
| }, | |||||
| token: 'Token', | |||||
| src: 'Source', | |||||
| startDate: 'Start date', | |||||
| endDate: 'End date', | |||||
| keyword: 'Keyword', | |||||
| }, | }, | ||||
| footer: { | footer: { | ||||
| profile: 'All rights reserved @ React', | profile: 'All rights reserved @ React', |
| concentrator: '集線器', | concentrator: '集線器', | ||||
| concentratorDescription: | concentratorDescription: | ||||
| '此組件可用於連接多個下游組件。它接收來自上游組件的輸入並將其傳遞給每個下游組件。 ', | '此組件可用於連接多個下游組件。它接收來自上游組件的輸入並將其傳遞給每個下游組件。 ', | ||||
| tuShare: 'TuShare', | |||||
| tuShareDescription: | |||||
| '該組件可用於從主流金融網站獲取金融新聞簡報,輔助行業和量化研究。 ', | |||||
| tuShareSrcOptions: { | |||||
| sina: '新浪財經', | |||||
| wallstreetcn: '華爾街見聞', | |||||
| '10jqka': '同花順', | |||||
| eastmoney: '東方財富', | |||||
| yuncaijing: '雲財經', | |||||
| fenghuang: '鳳凰新聞', | |||||
| jinrongjie: '金融界', | |||||
| }, | |||||
| token: 'Token', | |||||
| src: '來源', | |||||
| startDate: '開始日期', | |||||
| endDate: '結束日期', | |||||
| keyword: '關鍵字', | |||||
| }, | }, | ||||
| footer: { | footer: { | ||||
| profile: '“保留所有權利 @ react”', | profile: '“保留所有權利 @ react”', |
| concentrator: '集线器', | concentrator: '集线器', | ||||
| concentratorDescription: | concentratorDescription: | ||||
| '该组件可用于连接多个下游组件。它接收来自上游组件的输入并将其传递给每个下游组件。', | '该组件可用于连接多个下游组件。它接收来自上游组件的输入并将其传递给每个下游组件。', | ||||
| tuShare: 'TuShare', | |||||
| tuShareDescription: | |||||
| '该组件可用于从主流金融网站获取金融新闻简报,辅助行业和量化研究。', | |||||
| tuShareSrcOptions: { | |||||
| sina: '新浪财经', | |||||
| wallstreetcn: '华尔街见闻', | |||||
| '10jqka': '同花顺', | |||||
| eastmoney: '东方财富', | |||||
| yuncaijing: '云财经', | |||||
| fenghuang: '凤凰新闻', | |||||
| jinrongjie: '金融界', | |||||
| }, | |||||
| token: 'Token', | |||||
| src: '源', | |||||
| startDate: '开始日期', | |||||
| endDate: '结束日期', | |||||
| keyword: '关键字', | |||||
| }, | }, | ||||
| footer: { | footer: { | ||||
| profile: 'All rights reserved @ React', | profile: 'All rights reserved @ React', |
| import { ReactComponent as PubMedIcon } from '@/assets/svg/pubmed.svg'; | import { ReactComponent as PubMedIcon } from '@/assets/svg/pubmed.svg'; | ||||
| import { ReactComponent as QWeatherIcon } from '@/assets/svg/qweather.svg'; | import { ReactComponent as QWeatherIcon } from '@/assets/svg/qweather.svg'; | ||||
| import { ReactComponent as SwitchIcon } from '@/assets/svg/switch.svg'; | import { ReactComponent as SwitchIcon } from '@/assets/svg/switch.svg'; | ||||
| import { ReactComponent as TuShareIcon } from '@/assets/svg/tushare.svg'; | |||||
| import { ReactComponent as WenCaiIcon } from '@/assets/svg/wencai.svg'; | import { ReactComponent as WenCaiIcon } from '@/assets/svg/wencai.svg'; | ||||
| import { ReactComponent as WikipediaIcon } from '@/assets/svg/wikipedia.svg'; | import { ReactComponent as WikipediaIcon } from '@/assets/svg/wikipedia.svg'; | ||||
| import { ReactComponent as YahooFinanceIcon } from '@/assets/svg/yahoo-finance.svg'; | import { ReactComponent as YahooFinanceIcon } from '@/assets/svg/yahoo-finance.svg'; | ||||
| YahooFinance = 'YahooFinance', | YahooFinance = 'YahooFinance', | ||||
| Jin10 = 'Jin10', | Jin10 = 'Jin10', | ||||
| Concentrator = 'Concentrator', | Concentrator = 'Concentrator', | ||||
| TuShare = 'TuShare', | |||||
| } | } | ||||
| export const operatorIconMap = { | export const operatorIconMap = { | ||||
| [Operator.YahooFinance]: YahooFinanceIcon, | [Operator.YahooFinance]: YahooFinanceIcon, | ||||
| [Operator.Jin10]: Jin10Icon, | [Operator.Jin10]: Jin10Icon, | ||||
| [Operator.Concentrator]: ConcentratorIcon, | [Operator.Concentrator]: ConcentratorIcon, | ||||
| [Operator.TuShare]: TuShareIcon, | |||||
| }; | }; | ||||
| export const operatorMap: Record< | export const operatorMap: Record< | ||||
| fontSize: 10, | fontSize: 10, | ||||
| iconFontSize: 16, | iconFontSize: 16, | ||||
| }, | }, | ||||
| [Operator.TuShare]: { backgroundColor: '#f8cfa0' }, | |||||
| }; | }; | ||||
| export const componentMenuList = [ | export const componentMenuList = [ | ||||
| { | { | ||||
| name: Operator.Jin10, | name: Operator.Jin10, | ||||
| }, | }, | ||||
| { | |||||
| name: Operator.TuShare, | |||||
| }, | |||||
| ]; | ]; | ||||
| export const initialRetrievalValues = { | export const initialRetrievalValues = { | ||||
| export const initialConcentratorValues = {}; | export const initialConcentratorValues = {}; | ||||
| export const initialTuShareValues = { | |||||
| token: 'xxx', | |||||
| src: 'eastmoney', | |||||
| start_date: '2024-01-01 09:00:00', | |||||
| }; | |||||
| export const CategorizeAnchorPointPositions = [ | export const CategorizeAnchorPointPositions = [ | ||||
| { top: 1, right: 34 }, | { top: 1, right: 34 }, | ||||
| { top: 8, right: 18 }, | { top: 8, right: 18 }, | ||||
| [Operator.YahooFinance]: [Operator.Begin], | [Operator.YahooFinance]: [Operator.Begin], | ||||
| [Operator.Jin10]: [Operator.Begin], | [Operator.Jin10]: [Operator.Begin], | ||||
| [Operator.Concentrator]: [Operator.Begin], | [Operator.Concentrator]: [Operator.Begin], | ||||
| [Operator.TuShare]: [Operator.Begin], | |||||
| }; | }; | ||||
| export const NodeMap = { | export const NodeMap = { | ||||
| [Operator.AkShare]: 'ragNode', | [Operator.AkShare]: 'ragNode', | ||||
| [Operator.YahooFinance]: 'ragNode', | [Operator.YahooFinance]: 'ragNode', | ||||
| [Operator.Jin10]: 'ragNode', | [Operator.Jin10]: 'ragNode', | ||||
| [Operator.TuShare]: 'ragNode', | |||||
| }; | }; | ||||
| export const LanguageOptions = [ | export const LanguageOptions = [ | ||||
| export const Jin10CalendarDatashapeOptions = ['data', 'event', 'holiday']; | export const Jin10CalendarDatashapeOptions = ['data', 'event', 'holiday']; | ||||
| export const Jin10SymbolsTypeOptions = ['GOODS', 'FOREX', 'FUTURE', 'CRYPTO']; | export const Jin10SymbolsTypeOptions = ['GOODS', 'FOREX', 'FUTURE', 'CRYPTO']; | ||||
| export const Jin10SymbolsDatatypeOptions = ['symbols', 'quotes']; | export const Jin10SymbolsDatatypeOptions = ['symbols', 'quotes']; | ||||
| export const TuShareSrcOptions = [ | |||||
| 'sina', | |||||
| 'wallstreetcn', | |||||
| '10jqka', | |||||
| 'eastmoney', | |||||
| 'yuncaijing', | |||||
| 'fenghuang', | |||||
| 'jinrongjie', | |||||
| ]; |
| import RetrievalForm from '../retrieval-form'; | import RetrievalForm from '../retrieval-form'; | ||||
| import RewriteQuestionForm from '../rewrite-question-form'; | import RewriteQuestionForm from '../rewrite-question-form'; | ||||
| import SwitchForm from '../switch-form'; | import SwitchForm from '../switch-form'; | ||||
| import TuShareForm from '../tushare-form'; | |||||
| import WenCaiForm from '../wencai-form'; | import WenCaiForm from '../wencai-form'; | ||||
| import WikipediaForm from '../wikipedia-form'; | import WikipediaForm from '../wikipedia-form'; | ||||
| [Operator.AkShare]: AkShareForm, | [Operator.AkShare]: AkShareForm, | ||||
| [Operator.YahooFinance]: YahooFinanceForm, | [Operator.YahooFinance]: YahooFinanceForm, | ||||
| [Operator.Jin10]: Jin10Form, | [Operator.Jin10]: Jin10Form, | ||||
| [Operator.TuShare]: TuShareForm, | |||||
| }; | }; | ||||
| const EmptyContent = () => <div>empty</div>; | const EmptyContent = () => <div>empty</div>; |
| initialRetrievalValues, | initialRetrievalValues, | ||||
| initialRewriteQuestionValues, | initialRewriteQuestionValues, | ||||
| initialSwitchValues, | initialSwitchValues, | ||||
| initialTuShareValues, | |||||
| initialWenCaiValues, | initialWenCaiValues, | ||||
| initialWikipediaValues, | initialWikipediaValues, | ||||
| initialYahooFinanceValues, | initialYahooFinanceValues, | ||||
| [Operator.YahooFinance]: initialYahooFinanceValues, | [Operator.YahooFinance]: initialYahooFinanceValues, | ||||
| [Operator.Jin10]: initialJin10Values, | [Operator.Jin10]: initialJin10Values, | ||||
| [Operator.Concentrator]: initialConcentratorValues, | [Operator.Concentrator]: initialConcentratorValues, | ||||
| [Operator.TuShare]: initialTuShareValues, | |||||
| }; | }; | ||||
| }, [llmId]); | }, [llmId]); | ||||
| import { useTranslate } from '@/hooks/common-hooks'; | |||||
| import { DatePicker, DatePickerProps, Form, Input, Select } from 'antd'; | |||||
| import dayjs from 'dayjs'; | |||||
| import { useCallback, useMemo } from 'react'; | |||||
| import { TuShareSrcOptions } from '../constant'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| const DateTimePicker = ({ | |||||
| onChange, | |||||
| value, | |||||
| }: { | |||||
| onChange?: (val: number | undefined) => void; | |||||
| value?: number | undefined; | |||||
| }) => { | |||||
| const handleChange: DatePickerProps['onChange'] = useCallback( | |||||
| (val: any) => { | |||||
| const nextVal = val?.format('YYYY-MM-DD HH:mm:ss'); | |||||
| onChange?.(nextVal ? nextVal : undefined); | |||||
| }, | |||||
| [onChange], | |||||
| ); | |||||
| // The value needs to be converted into a string and saved to the backend | |||||
| const nextValue = useMemo(() => { | |||||
| if (value) { | |||||
| return dayjs(value); | |||||
| } | |||||
| return undefined; | |||||
| }, [value]); | |||||
| return ( | |||||
| <DatePicker | |||||
| showTime | |||||
| format="YYYY-MM-DD HH:mm:ss" | |||||
| onChange={handleChange} | |||||
| value={nextValue} | |||||
| /> | |||||
| ); | |||||
| }; | |||||
| const TuShareForm = ({ onValuesChange, form }: IOperatorForm) => { | |||||
| const { t } = useTranslate('flow'); | |||||
| const tuShareSrcOptions = useMemo(() => { | |||||
| return TuShareSrcOptions.map((x) => ({ | |||||
| value: x, | |||||
| label: t(`tuShareSrcOptions.${x}`), | |||||
| })); | |||||
| }, [t]); | |||||
| return ( | |||||
| <Form | |||||
| name="basic" | |||||
| labelCol={{ span: 6 }} | |||||
| wrapperCol={{ span: 18 }} | |||||
| autoComplete="off" | |||||
| form={form} | |||||
| onValuesChange={onValuesChange} | |||||
| > | |||||
| <Form.Item | |||||
| label={t('token')} | |||||
| name={'token'} | |||||
| tooltip={'Get from https://tushare.pro/'} | |||||
| > | |||||
| <Input></Input> | |||||
| </Form.Item> | |||||
| <Form.Item label={t('src')} name={'src'}> | |||||
| <Select options={tuShareSrcOptions}></Select> | |||||
| </Form.Item> | |||||
| <Form.Item label={t('startDate')} name={'start_date'}> | |||||
| <DateTimePicker /> | |||||
| </Form.Item> | |||||
| <Form.Item label={t('endDate')} name={'end_date'}> | |||||
| <DateTimePicker /> | |||||
| </Form.Item> | |||||
| <Form.Item label={t('keyword')} name={'keyword'}> | |||||
| <Input></Input> | |||||
| </Form.Item> | |||||
| </Form> | |||||
| ); | |||||
| }; | |||||
| export default TuShareForm; |