|
|
@@ -0,0 +1,298 @@
|
|
|
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|
|
+import styles from './index.module.scss'
|
|
|
+import { Button, Switch } from 'antd'
|
|
|
+import TextArea from 'antd/es/input/TextArea'
|
|
|
+import { useDispatch, useSelector } from 'react-redux'
|
|
|
+import classNames from 'classnames'
|
|
|
+import {
|
|
|
+ API_A21del,
|
|
|
+ API_A21delLog,
|
|
|
+ API_A21getInfo,
|
|
|
+ API_A21getLog,
|
|
|
+ API_A21getMes,
|
|
|
+ API_A21send,
|
|
|
+ API_A21setInfo,
|
|
|
+ API_A21setLog,
|
|
|
+ API_A21switchFu
|
|
|
+} from '@/store/action/A2content'
|
|
|
+import { RootState } from '@/store'
|
|
|
+import MyPopconfirm from '@/components/MyPopconfirm'
|
|
|
+import { MessageFu } from '@/utils/message'
|
|
|
+import { handeUpFile } from '@/utils/upFile'
|
|
|
+import MyTable from '@/components/MyTable'
|
|
|
+import { downloadFileByUrl } from '@/utils/history'
|
|
|
+function A2tab1() {
|
|
|
+ const dispatch = useDispatch()
|
|
|
+
|
|
|
+ const getInfoFu = useCallback(() => {
|
|
|
+ dispatch(API_A21getInfo())
|
|
|
+ }, [dispatch])
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ getInfoFu()
|
|
|
+ }, [getInfoFu])
|
|
|
+
|
|
|
+ const A21info = useSelector((state: RootState) => state.A2content.A21info)
|
|
|
+
|
|
|
+ const intro = useMemo(() => {
|
|
|
+ return A21info.intro || ''
|
|
|
+ }, [A21info.intro])
|
|
|
+
|
|
|
+ const file = useMemo(() => {
|
|
|
+ return A21info.file || []
|
|
|
+ }, [A21info.file])
|
|
|
+
|
|
|
+ const [value, setValue] = useState('')
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ setValue(intro)
|
|
|
+ }, [intro])
|
|
|
+
|
|
|
+ const [txtShow, setTxtShow] = useState(false)
|
|
|
+
|
|
|
+ // 提示词修改 点击确定
|
|
|
+ const txtBtnOk = useCallback(async () => {
|
|
|
+ const res = await API_A21setInfo({ intro: value })
|
|
|
+
|
|
|
+ if (res.code === 0) {
|
|
|
+ MessageFu.success('修改成功')
|
|
|
+ setTxtShow(false)
|
|
|
+ getInfoFu()
|
|
|
+ }
|
|
|
+ }, [getInfoFu, value])
|
|
|
+
|
|
|
+ const myInput = useRef<HTMLInputElement>(null)
|
|
|
+
|
|
|
+ // 上传文件成功
|
|
|
+ const upSuccFu = useCallback(
|
|
|
+ async (data: any) => {
|
|
|
+ const fileArr = [...file, data]
|
|
|
+
|
|
|
+ const res = await API_A21setInfo({ fileIds: fileArr.map(v => v.id).join(',') })
|
|
|
+
|
|
|
+ if (res.code === 0) {
|
|
|
+ MessageFu.success('上传成功')
|
|
|
+ getInfoFu()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ [file, getInfoFu]
|
|
|
+ )
|
|
|
+
|
|
|
+ // 点击删除
|
|
|
+ const delTableFu = useCallback(
|
|
|
+ async (id: number) => {
|
|
|
+ const res: any = await API_A21del([id])
|
|
|
+ if (res.code === 0) {
|
|
|
+ MessageFu.success('删除成功')
|
|
|
+ getInfoFu()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ [getInfoFu]
|
|
|
+ )
|
|
|
+
|
|
|
+ // 启用
|
|
|
+ const switchFu = useCallback(
|
|
|
+ async (id: number, val: 1 | 0 | null) => {
|
|
|
+ const usable = val === 1 ? 0 : 1
|
|
|
+
|
|
|
+ const res = await API_A21switchFu(id, usable)
|
|
|
+ if (res.code === 0) {
|
|
|
+ MessageFu.success('操作成功')
|
|
|
+ getInfoFu()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ [getInfoFu]
|
|
|
+ )
|
|
|
+
|
|
|
+ const tableLastBtn = useMemo(() => {
|
|
|
+ return [
|
|
|
+ {
|
|
|
+ title: '启用',
|
|
|
+ render: (item: any) => (
|
|
|
+ <Switch checked={item.display === 1} onChange={() => switchFu(item.id, item.display)} />
|
|
|
+ )
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '操作',
|
|
|
+ render: (item: any) => (
|
|
|
+ <>
|
|
|
+ <Button size='small' type='text' onClick={() => downloadFileByUrl(item.filePath)}>
|
|
|
+ 下载
|
|
|
+ </Button>
|
|
|
+ <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
|
|
|
+ </>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }, [delTableFu, switchFu])
|
|
|
+
|
|
|
+ // ---------------右侧----------------------
|
|
|
+ const [value2, setValue2] = useState('')
|
|
|
+
|
|
|
+ const [rInfo, setRInfo] = useState({ list: [] as any[], loding: false })
|
|
|
+
|
|
|
+ const getLogFu = useCallback(async () => {
|
|
|
+ const res = await API_A21getLog()
|
|
|
+ if (res.code === 0) {
|
|
|
+ setRInfo({ list: res.data || [], loding: true })
|
|
|
+ setTimeout(() => {
|
|
|
+ if (A21r2MainRef.current) {
|
|
|
+ A21r2MainRef.current.scrollTop = 999999999
|
|
|
+ }
|
|
|
+ }, 100)
|
|
|
+ }
|
|
|
+ }, [])
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ getLogFu()
|
|
|
+ }, [getLogFu])
|
|
|
+
|
|
|
+ const A21r2MainRef = useRef<HTMLDivElement>(null)
|
|
|
+
|
|
|
+ // 发送消息
|
|
|
+ const sendMesFu = useCallback(async () => {
|
|
|
+ if (value2.trim().replaceAll(/\s/g, '') === '') {
|
|
|
+ setValue2('')
|
|
|
+ return MessageFu.warning('内容不能为空')
|
|
|
+ }
|
|
|
+
|
|
|
+ const res1 = await API_A21getMes()
|
|
|
+ if (res1.code === 0) {
|
|
|
+ const res2: any = await API_A21send(value2, rInfo.list, res1.data || [])
|
|
|
+
|
|
|
+ // 保存回答记录
|
|
|
+ const res3 = await API_A21setLog({ name: 'user', rtf: value2 })
|
|
|
+ const res4 = await API_A21setLog({ name: res2.message.role, rtf: res2.message.content })
|
|
|
+
|
|
|
+ if (res3.code === 0 && res4.code === 0) {
|
|
|
+ getLogFu()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ setValue2('')
|
|
|
+ }, [getLogFu, rInfo.list, value2])
|
|
|
+
|
|
|
+ // 点击清空记录
|
|
|
+ const clearFu = useCallback(async () => {
|
|
|
+ const res = await API_A21delLog()
|
|
|
+ if (res.code === 0) {
|
|
|
+ MessageFu.success('清空记录成功')
|
|
|
+ getLogFu()
|
|
|
+ }
|
|
|
+ }, [getLogFu])
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className={styles.A2tab1}>
|
|
|
+ <input
|
|
|
+ id='upInput'
|
|
|
+ type='file'
|
|
|
+ accept='.txt'
|
|
|
+ ref={myInput}
|
|
|
+ onChange={e =>
|
|
|
+ handeUpFile(e, ['txt'], 'cms/ai/upload', 'A2content1', data => upSuccFu(data), {
|
|
|
+ isDb: 'true'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ />
|
|
|
+
|
|
|
+ <div className='A21left'>
|
|
|
+ <div className='A21l1'>
|
|
|
+ <div className='A21tit'>提示词</div>
|
|
|
+ {txtShow ? (
|
|
|
+ <div>
|
|
|
+ <MyPopconfirm
|
|
|
+ txtK='取消'
|
|
|
+ onConfirm={() => {
|
|
|
+ setTxtShow(false)
|
|
|
+ setValue(intro)
|
|
|
+ }}
|
|
|
+ />
|
|
|
+  
|
|
|
+ <Button type='primary' onClick={txtBtnOk}>
|
|
|
+ 确定
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ ) : (
|
|
|
+ <Button type='primary' onClick={() => setTxtShow(true)}>
|
|
|
+ 修改
|
|
|
+ </Button>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ <TextArea
|
|
|
+ placeholder={txtShow ? '请输入内容' : '(空)'}
|
|
|
+ readOnly={!txtShow}
|
|
|
+ value={value}
|
|
|
+ onChange={e => setValue(e.target.value)}
|
|
|
+ />
|
|
|
+
|
|
|
+ <div className='A21l1 A21l2'>
|
|
|
+ <div className='A21tit'>知识库</div>
|
|
|
+ <div className='A21lBtn'>
|
|
|
+ <span>仅支持txt格式</span>
|
|
|
+ <Button type='primary' onClick={() => myInput.current?.click()}>
|
|
|
+ 上传
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <MyTable
|
|
|
+ yHeight={475}
|
|
|
+ list={file}
|
|
|
+ columnsTemp={[['txt', '文件名称', 'fileName']]}
|
|
|
+ lastBtn={tableLastBtn}
|
|
|
+ pagingInfo={false}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 右侧--------------------- */}
|
|
|
+ <div className='A21right'>
|
|
|
+ <div className='A21r1'>
|
|
|
+ <div className='A21tit'>调试预览</div>
|
|
|
+ <MyPopconfirm
|
|
|
+ txtK='清空记录'
|
|
|
+ onConfirm={clearFu}
|
|
|
+ Dom={<Button type='primary'>清空记录</Button>}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className='A21r2'>
|
|
|
+ {rInfo.loding && rInfo.list.length > 0 ? (
|
|
|
+ <div className='A21r2Main' ref={A21r2MainRef}>
|
|
|
+ {rInfo.list.map((item, index) => (
|
|
|
+ <div
|
|
|
+ hidden={item.name === 'system'}
|
|
|
+ key={index}
|
|
|
+ className={classNames('A21r2Row', item.name === 'assistant' ? '' : 'A21r2Row2')}
|
|
|
+ >
|
|
|
+ <div>{item.name === 'assistant' ? '数字人' : '用户'}:</div>
|
|
|
+ <p>{item.rtf}</p>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ ) : (
|
|
|
+ <div className='A21r2Null'>暂无记录</div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className='A21r3'>
|
|
|
+ <TextArea
|
|
|
+ placeholder='请输入内容'
|
|
|
+ value={value2}
|
|
|
+ onChange={e => setValue2(e.target.value)}
|
|
|
+ />
|
|
|
+ <div>
|
|
|
+ <Button onClick={() => setValue2('')}>清空</Button>
|
|
|
+
|
|
|
+ <Button type='primary' onClick={sendMesFu}>
|
|
|
+ 发送
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+const MemoA2tab1 = React.memo(A2tab1)
|
|
|
+
|
|
|
+export default MemoA2tab1
|