index.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. import * as React from 'react';
  2. import { observer } from 'mobx-react';
  3. import { generatePath, useLocation, useParams } from 'react-router-dom';
  4. import { List, Button, Divider, Empty, Modal, Form, Input, message } from 'antd';
  5. import { SettingOutlined, DeleteOutlined, ArrowLeftOutlined, PlusOutlined } from '@ant-design/icons';
  6. import { apis } from '@/apis';
  7. import { PaginationConfig } from 'antd/es/pagination';
  8. import router from '@/router';
  9. import './style.less';
  10. import LocalStorage from '@/LocalStorage';
  11. import { makeAutoObservable } from 'mobx';
  12. const FormItem = Form.Item;
  13. const page = makeAutoObservable({
  14. pageNum: 1,
  15. pageSize: 10,
  16. total: 0,
  17. });
  18. const SliceList: React.FC = () => {
  19. const [form] = Form.useForm();
  20. const params = useParams();
  21. interface Item {
  22. slice_id: string,
  23. document_id: string,
  24. slice_text: string,
  25. slice_char_len: number,
  26. };
  27. const location = useLocation();
  28. const [listLoading, setListLoading] = React.useState(false);
  29. const [list, setList] = React.useState<Item[]>([]);
  30. const [createFlag, setCreateFlag] = React.useState<boolean>();
  31. const [deleteFlag, setDeleteFlag] = React.useState<boolean>();
  32. const [updateFlag, setUpdateFlag] = React.useState<boolean>();
  33. const [listFlag, setListFlag] = React.useState<boolean>();
  34. const appApi = {
  35. fetchList: async (p0: { searchText: string; }) => {
  36. setListLoading(true);
  37. try {
  38. const res = await apis.fetchTakaiSliceList({
  39. knowledge_id: params.knowledgeId || '',
  40. document_id: params.documentId || '',
  41. text: p0.searchText,
  42. pageSize: page.pageSize,
  43. pageNum: page.pageNum
  44. })
  45. const list = res.rows.map((item: any) => {
  46. return {
  47. slice_id: item.sliceId,
  48. document_id: item.documentId,
  49. slice_text: item.sliceText,
  50. slice_char_len: item.sliceText.length,
  51. }
  52. });
  53. setList(list);
  54. page.total = res.total;
  55. } catch (error) {
  56. console.error(error);
  57. } finally {
  58. setListLoading(false);
  59. }
  60. },
  61. };
  62. const handleClickSearch = () => {
  63. const values = form.getFieldsValue();
  64. appApi.fetchList({ searchText: values.text });
  65. }
  66. const handleClickReset = () => {
  67. form.resetFields();
  68. appApi.fetchList({ searchText: '' });
  69. }
  70. const deleteSlice = async (slice_id: string, knowledgeId: string) => {
  71. try {
  72. if (!params.knowledgeId || !params.documentId) {
  73. throw new Error('knowledgeId或documentId未定义,请检查路由参数');
  74. }
  75. const res = await apis.deleteTakaiSlice(slice_id, params.knowledgeId, params.documentId);
  76. if (res.code === 200 && res.data === 1) {
  77. appApi.fetchList({ searchText: '' });
  78. message.success('删除切片成功');
  79. }
  80. } catch (error) {
  81. console.error('删除切片失败:', error);
  82. }
  83. }
  84. const init = async () => {
  85. if (location.state) {
  86. const { text, page: currentPage } = location.state;
  87. if (text) {
  88. form.setFieldsValue({
  89. text: text,
  90. });
  91. }
  92. if (currentPage && currentPage.pageNum && currentPage.pageSize) {
  93. page.pageNum = currentPage.pageNum;
  94. page.pageSize = currentPage.pageSize;
  95. page.total = currentPage.total;
  96. }
  97. }
  98. const values = form.getFieldsValue();
  99. const searchText = values.text ? values.text : '';
  100. await appApi.fetchList({ searchText: searchText });
  101. }
  102. React.useEffect(() => {
  103. init();
  104. const cFlag = LocalStorage.getStatusFlag('deepseek:slice:create');
  105. setCreateFlag(cFlag);
  106. const dFlag = LocalStorage.getStatusFlag('deepseek:slice:delete');
  107. setDeleteFlag(dFlag);
  108. const tFlag = LocalStorage.getStatusFlag('deepseek:slice:update');
  109. setUpdateFlag(tFlag);
  110. const lFlag = LocalStorage.getStatusFlag('deepseek:slice:list');
  111. setListFlag(lFlag);
  112. return () => {
  113. page.pageNum = 1;
  114. page.pageSize = 10;
  115. page.total = 0;
  116. };
  117. }, [])
  118. const paginationConfig: PaginationConfig = {
  119. // 显示数据总量
  120. showTotal: (total: number) => {
  121. return `共 ${total} 条`;
  122. },
  123. // 展示分页条数切换
  124. showSizeChanger: true,
  125. // 指定每页显示条数
  126. pageSizeOptions: ['10', '20', '50', '100'],
  127. // 快速跳转至某页
  128. showQuickJumper: true,
  129. current: page.pageNum,
  130. pageSize: page.pageSize,
  131. total: page.total,
  132. onChange: async (pageNum, pageSize) => {
  133. page.pageNum = pageNum;
  134. page.pageSize = pageSize;
  135. const values = form.getFieldsValue();
  136. const searchText = values.text ? values.text : '';
  137. await appApi.fetchList({ searchText: searchText });
  138. },
  139. };
  140. return (
  141. <div>
  142. <div className='slice-search'>
  143. <div style={{ display: 'flex', justifyContent: 'space-between' }}>
  144. <Form form={form} layout='inline' colon={false}>
  145. <FormItem label='切片' name='text'>
  146. <Input />
  147. </FormItem>
  148. <FormItem>
  149. <Button
  150. style={{ marginRight: 16 }}
  151. type='primary'
  152. onClick={handleClickSearch}
  153. >
  154. 查询
  155. </Button>
  156. <Button onClick={handleClickReset}>
  157. 重置
  158. </Button>
  159. </FormItem>
  160. </Form>
  161. <div>
  162. {
  163. createFlag &&
  164. <Button
  165. style={{ marginRight: 16 }}
  166. type='primary'
  167. icon={<PlusOutlined />}
  168. onClick={() => {
  169. const path = generatePath('/deepseek/knowledgeLib/:knowledgeId/slice/:documentId/:embeddingId/:sliceId', {
  170. knowledgeId: params.knowledgeId as string,
  171. documentId: params.documentId as string,
  172. embeddingId: params.embeddingId as string,
  173. sliceId: 'new',
  174. });
  175. const { text } = form.getFieldsValue();
  176. router.navigate({ pathname: path }, { state: { text: text, page: { pageNum: page.pageNum, pageSize: page.pageSize, total: page.total } } });
  177. }}>
  178. 新增切片
  179. </Button>
  180. }
  181. <Button type='primary' icon={<ArrowLeftOutlined />} onClick={() => {
  182. const path = generatePath('/deepseek/knowledgeLib/:knowledgeId', {
  183. knowledgeId: params.knowledgeId as string,
  184. });
  185. router.navigate({ pathname: path });
  186. }}>
  187. 返回
  188. </Button>
  189. </div>
  190. </div>
  191. </div>
  192. {
  193. list.length
  194. ?
  195. <div className='questionAnswerList'>
  196. <div className='applicationList'>
  197. <List
  198. style={{ height: 400 }}
  199. loading={listLoading}
  200. grid={{
  201. gutter: 16,
  202. xs: 1,
  203. sm: 2,
  204. md: 4,
  205. lg: 4,
  206. xl: 6,
  207. xxl: 2, // 展示的列数
  208. }}
  209. dataSource={list}
  210. renderItem={(item) => (
  211. <List.Item>
  212. <div className='card'>
  213. <div style={{ height: 80, overflow: 'auto' }}>
  214. {
  215. item.slice_text
  216. }
  217. </div>
  218. <Divider plain></Divider>
  219. <div style={{ display: 'flex', justifyContent: 'space-between', overflow: 'auto' }}>
  220. <div style={{ overflow: 'auto' }}>
  221. {
  222. updateFlag &&
  223. <a
  224. style={{ marginRight: 20 }}
  225. onClick={() => {
  226. const path = generatePath('/deepseek/knowledgeLib/:knowledgeId/slice/:documentId/:embeddingId/:sliceId', {
  227. knowledgeId: params.knowledgeId as string,
  228. documentId: params.documentId as string,
  229. embeddingId: params.embeddingId as string,
  230. sliceId: item.slice_id,
  231. });
  232. const { text } = form.getFieldsValue();
  233. router.navigate({ pathname: path }, { state: { text: text, page: { pageNum: page.pageNum, pageSize: page.pageSize, total: page.total } } });
  234. }}>
  235. <SettingOutlined /> 编辑
  236. </a>
  237. }
  238. {
  239. deleteFlag &&
  240. <a className='text-error' onClick={() => {
  241. Modal.confirm({
  242. title: '删除',
  243. content: `确定删除切片: ` + item.slice_id + ` 吗?`,
  244. okType: 'danger',
  245. onOk: async () => {
  246. const knowledgeId = params.knowledgeId || ''; // 提供默认值
  247. await deleteSlice(item.slice_id, knowledgeId);
  248. }
  249. });
  250. }}>
  251. <DeleteOutlined /> 删除
  252. </a>
  253. }
  254. </div>
  255. <div>
  256. {
  257. item.slice_char_len
  258. }
  259. </div>
  260. </div>
  261. </div>
  262. </List.Item>
  263. )}
  264. pagination={paginationConfig} // 分页
  265. />
  266. </div>
  267. </div>
  268. :
  269. <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
  270. }
  271. </div >
  272. )
  273. };
  274. export default observer(SliceList);