balibabu commited on
Commit
b916b29
·
1 Parent(s): 166f8cd

feat: add overview (#391)

Browse files

### What problem does this PR solve?

feat: render stats charts
feat: create api token
feat: delete api token
feat: add ChatApiKeyModal
feat: add RagLineChart


Issue link: #345

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

web/package-lock.json CHANGED
@@ -13,19 +13,21 @@
13
  "antd": "^5.12.7",
14
  "axios": "^1.6.3",
15
  "classnames": "^2.5.1",
 
16
  "i18next": "^23.7.16",
17
  "js-base64": "^3.7.5",
18
  "jsencrypt": "^3.3.2",
19
  "lodash": "^4.17.21",
20
- "moment": "^2.30.1",
21
  "rc-tween-one": "^3.0.6",
22
  "react-chat-elements": "^12.0.13",
 
23
  "react-i18next": "^14.0.0",
24
  "react-infinite-scroll-component": "^6.1.0",
25
  "react-markdown": "^9.0.1",
26
  "react-pdf-highlighter": "^6.1.0",
27
  "react-string-replace": "^1.1.1",
28
  "react-syntax-highlighter": "^15.5.0",
 
29
  "remark-gfm": "^4.0.0",
30
  "umi": "^4.0.90",
31
  "umi-request": "^1.4.0",
@@ -36,6 +38,7 @@
36
  "@react-dev-inspector/umi4-plugin": "^2.0.1",
37
  "@types/lodash": "^4.14.202",
38
  "@types/react": "^18.0.33",
 
39
  "@types/react-dom": "^18.0.11",
40
  "@types/react-syntax-highlighter": "^15.5.11",
41
  "@types/uuid": "^9.0.8",
@@ -2676,6 +2679,60 @@
2676
  "@babel/types": "^7.20.7"
2677
  }
2678
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2679
  "node_modules/@types/debug": {
2680
  "version": "4.1.12",
2681
  "resolved": "https://registry.npmmirror.com/@types/debug/-/debug-4.1.12.tgz",
@@ -2884,6 +2941,15 @@
2884
  "csstype": "^3.0.2"
2885
  }
2886
  },
 
 
 
 
 
 
 
 
 
2887
  "node_modules/@types/react-dom": {
2888
  "version": "18.2.18",
2889
  "resolved": "https://registry.npmmirror.com/@types/react-dom/-/react-dom-18.2.18.tgz",
@@ -5832,6 +5898,14 @@
5832
  "node": ">=12"
5833
  }
5834
  },
 
 
 
 
 
 
 
 
5835
  "node_modules/coa": {
5836
  "version": "2.0.2",
5837
  "resolved": "https://registry.npmmirror.com/coa/-/coa-2.0.2.tgz",
@@ -6640,11 +6714,132 @@
6640
  "resolved": "https://registry.npmmirror.com/d3-array/-/d3-array-1.2.4.tgz",
6641
  "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
6642
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6643
  "node_modules/d3-polygon": {
6644
  "version": "1.0.6",
6645
  "resolved": "https://registry.npmmirror.com/d3-polygon/-/d3-polygon-1.0.6.tgz",
6646
  "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ=="
6647
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6648
  "node_modules/data-uri-to-buffer": {
6649
  "version": "4.0.1",
6650
  "resolved": "https://registry.npmmirror.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
@@ -6705,6 +6900,11 @@
6705
  "node": ">=0.10.0"
6706
  }
6707
  },
 
 
 
 
 
6708
  "node_modules/decode-named-character-reference": {
6709
  "version": "1.0.2",
6710
  "resolved": "https://registry.npmmirror.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz",
@@ -7032,6 +7232,15 @@
7032
  "utila": "~0.4"
7033
  }
7034
  },
 
 
 
 
 
 
 
 
 
7035
  "node_modules/dom-serializer": {
7036
  "version": "1.4.1",
7037
  "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz",
@@ -8151,6 +8360,11 @@
8151
  "es5-ext": "~0.10.14"
8152
  }
8153
  },
 
 
 
 
 
8154
  "node_modules/events": {
8155
  "version": "3.3.0",
8156
  "resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz",
@@ -8356,6 +8570,14 @@
8356
  "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
8357
  "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
8358
  },
 
 
 
 
 
 
 
 
8359
  "node_modules/fast-glob": {
8360
  "version": "3.2.12",
8361
  "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.2.12.tgz",
@@ -9693,6 +9915,14 @@
9693
  "node": ">= 0.4"
9694
  }
9695
  },
 
 
 
 
 
 
 
 
9696
  "node_modules/intersection-observer": {
9697
  "version": "0.12.2",
9698
  "resolved": "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.12.2.tgz",
@@ -11925,6 +12155,7 @@
11925
  "version": "2.30.1",
11926
  "resolved": "https://registry.npmmirror.com/moment/-/moment-2.30.1.tgz",
11927
  "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
 
11928
  "engines": {
11929
  "node": "*"
11930
  }
@@ -14356,6 +14587,18 @@
14356
  "react-dom": "18.2.0"
14357
  }
14358
  },
 
 
 
 
 
 
 
 
 
 
 
 
14359
  "node_modules/react-dev-inspector": {
14360
  "version": "2.0.1",
14361
  "resolved": "https://registry.npmmirror.com/react-dev-inspector/-/react-dev-inspector-2.0.1.tgz",
@@ -14934,6 +15177,20 @@
14934
  "react": ">=15"
14935
  }
14936
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14937
  "node_modules/react-spinkit": {
14938
  "version": "3.0.0",
14939
  "resolved": "https://registry.npmmirror.com/react-spinkit/-/react-spinkit-3.0.0.tgz",
@@ -14968,6 +15225,21 @@
14968
  "react": ">= 0.14.0"
14969
  }
14970
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14971
  "node_modules/reactcss": {
14972
  "version": "1.2.3",
14973
  "resolved": "https://registry.npmmirror.com/reactcss/-/reactcss-1.2.3.tgz",
@@ -15145,6 +15417,41 @@
15145
  "node": ">= 12.13.0"
15146
  }
15147
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15148
  "node_modules/recursive-readdir": {
15149
  "version": "2.2.3",
15150
  "resolved": "https://registry.npmmirror.com/recursive-readdir/-/recursive-readdir-2.2.3.tgz",
@@ -17000,9 +17307,7 @@
17000
  "node_modules/tiny-invariant": {
17001
  "version": "1.3.1",
17002
  "resolved": "https://registry.npmmirror.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz",
17003
- "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==",
17004
- "dev": true,
17005
- "peer": true
17006
  },
17007
  "node_modules/tiny-warning": {
17008
  "version": "1.0.3",
@@ -18221,6 +18526,38 @@
18221
  "unist-util-stringify-position": "^4.0.0"
18222
  }
18223
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18224
  "node_modules/vite": {
18225
  "version": "4.3.1",
18226
  "resolved": "https://registry.npmmirror.com/vite/-/vite-4.3.1.tgz",
 
13
  "antd": "^5.12.7",
14
  "axios": "^1.6.3",
15
  "classnames": "^2.5.1",
16
+ "dayjs": "^1.11.10",
17
  "i18next": "^23.7.16",
18
  "js-base64": "^3.7.5",
19
  "jsencrypt": "^3.3.2",
20
  "lodash": "^4.17.21",
 
21
  "rc-tween-one": "^3.0.6",
22
  "react-chat-elements": "^12.0.13",
23
+ "react-copy-to-clipboard": "^5.1.0",
24
  "react-i18next": "^14.0.0",
25
  "react-infinite-scroll-component": "^6.1.0",
26
  "react-markdown": "^9.0.1",
27
  "react-pdf-highlighter": "^6.1.0",
28
  "react-string-replace": "^1.1.1",
29
  "react-syntax-highlighter": "^15.5.0",
30
+ "recharts": "^2.12.4",
31
  "remark-gfm": "^4.0.0",
32
  "umi": "^4.0.90",
33
  "umi-request": "^1.4.0",
 
38
  "@react-dev-inspector/umi4-plugin": "^2.0.1",
39
  "@types/lodash": "^4.14.202",
40
  "@types/react": "^18.0.33",
41
+ "@types/react-copy-to-clipboard": "^5.0.7",
42
  "@types/react-dom": "^18.0.11",
43
  "@types/react-syntax-highlighter": "^15.5.11",
44
  "@types/uuid": "^9.0.8",
 
2679
  "@babel/types": "^7.20.7"
2680
  }
2681
  },
2682
+ "node_modules/@types/d3-array": {
2683
+ "version": "3.2.1",
2684
+ "resolved": "https://registry.npmmirror.com/@types/d3-array/-/d3-array-3.2.1.tgz",
2685
+ "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg=="
2686
+ },
2687
+ "node_modules/@types/d3-color": {
2688
+ "version": "3.1.3",
2689
+ "resolved": "https://registry.npmmirror.com/@types/d3-color/-/d3-color-3.1.3.tgz",
2690
+ "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="
2691
+ },
2692
+ "node_modules/@types/d3-ease": {
2693
+ "version": "3.0.2",
2694
+ "resolved": "https://registry.npmmirror.com/@types/d3-ease/-/d3-ease-3.0.2.tgz",
2695
+ "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="
2696
+ },
2697
+ "node_modules/@types/d3-interpolate": {
2698
+ "version": "3.0.4",
2699
+ "resolved": "https://registry.npmmirror.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
2700
+ "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
2701
+ "dependencies": {
2702
+ "@types/d3-color": "*"
2703
+ }
2704
+ },
2705
+ "node_modules/@types/d3-path": {
2706
+ "version": "3.1.0",
2707
+ "resolved": "https://registry.npmmirror.com/@types/d3-path/-/d3-path-3.1.0.tgz",
2708
+ "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ=="
2709
+ },
2710
+ "node_modules/@types/d3-scale": {
2711
+ "version": "4.0.8",
2712
+ "resolved": "https://registry.npmmirror.com/@types/d3-scale/-/d3-scale-4.0.8.tgz",
2713
+ "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==",
2714
+ "dependencies": {
2715
+ "@types/d3-time": "*"
2716
+ }
2717
+ },
2718
+ "node_modules/@types/d3-shape": {
2719
+ "version": "3.1.6",
2720
+ "resolved": "https://registry.npmmirror.com/@types/d3-shape/-/d3-shape-3.1.6.tgz",
2721
+ "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==",
2722
+ "dependencies": {
2723
+ "@types/d3-path": "*"
2724
+ }
2725
+ },
2726
+ "node_modules/@types/d3-time": {
2727
+ "version": "3.0.3",
2728
+ "resolved": "https://registry.npmmirror.com/@types/d3-time/-/d3-time-3.0.3.tgz",
2729
+ "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw=="
2730
+ },
2731
+ "node_modules/@types/d3-timer": {
2732
+ "version": "3.0.2",
2733
+ "resolved": "https://registry.npmmirror.com/@types/d3-timer/-/d3-timer-3.0.2.tgz",
2734
+ "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="
2735
+ },
2736
  "node_modules/@types/debug": {
2737
  "version": "4.1.12",
2738
  "resolved": "https://registry.npmmirror.com/@types/debug/-/debug-4.1.12.tgz",
 
2941
  "csstype": "^3.0.2"
2942
  }
2943
  },
2944
+ "node_modules/@types/react-copy-to-clipboard": {
2945
+ "version": "5.0.7",
2946
+ "resolved": "https://registry.npmmirror.com/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.7.tgz",
2947
+ "integrity": "sha512-Gft19D+as4M+9Whq1oglhmK49vqPhcLzk8WfvfLvaYMIPYanyfLy0+CwFucMJfdKoSFyySPmkkWn8/E6voQXjQ==",
2948
+ "dev": true,
2949
+ "dependencies": {
2950
+ "@types/react": "*"
2951
+ }
2952
+ },
2953
  "node_modules/@types/react-dom": {
2954
  "version": "18.2.18",
2955
  "resolved": "https://registry.npmmirror.com/@types/react-dom/-/react-dom-18.2.18.tgz",
 
5898
  "node": ">=12"
5899
  }
5900
  },
5901
+ "node_modules/clsx": {
5902
+ "version": "2.1.0",
5903
+ "resolved": "https://registry.npmmirror.com/clsx/-/clsx-2.1.0.tgz",
5904
+ "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==",
5905
+ "engines": {
5906
+ "node": ">=6"
5907
+ }
5908
+ },
5909
  "node_modules/coa": {
5910
  "version": "2.0.2",
5911
  "resolved": "https://registry.npmmirror.com/coa/-/coa-2.0.2.tgz",
 
6714
  "resolved": "https://registry.npmmirror.com/d3-array/-/d3-array-1.2.4.tgz",
6715
  "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
6716
  },
6717
+ "node_modules/d3-color": {
6718
+ "version": "3.1.0",
6719
+ "resolved": "https://registry.npmmirror.com/d3-color/-/d3-color-3.1.0.tgz",
6720
+ "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
6721
+ "engines": {
6722
+ "node": ">=12"
6723
+ }
6724
+ },
6725
+ "node_modules/d3-ease": {
6726
+ "version": "3.0.1",
6727
+ "resolved": "https://registry.npmmirror.com/d3-ease/-/d3-ease-3.0.1.tgz",
6728
+ "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
6729
+ "engines": {
6730
+ "node": ">=12"
6731
+ }
6732
+ },
6733
+ "node_modules/d3-format": {
6734
+ "version": "3.1.0",
6735
+ "resolved": "https://registry.npmmirror.com/d3-format/-/d3-format-3.1.0.tgz",
6736
+ "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
6737
+ "engines": {
6738
+ "node": ">=12"
6739
+ }
6740
+ },
6741
+ "node_modules/d3-interpolate": {
6742
+ "version": "3.0.1",
6743
+ "resolved": "https://registry.npmmirror.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
6744
+ "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
6745
+ "dependencies": {
6746
+ "d3-color": "1 - 3"
6747
+ },
6748
+ "engines": {
6749
+ "node": ">=12"
6750
+ }
6751
+ },
6752
+ "node_modules/d3-path": {
6753
+ "version": "3.1.0",
6754
+ "resolved": "https://registry.npmmirror.com/d3-path/-/d3-path-3.1.0.tgz",
6755
+ "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
6756
+ "engines": {
6757
+ "node": ">=12"
6758
+ }
6759
+ },
6760
  "node_modules/d3-polygon": {
6761
  "version": "1.0.6",
6762
  "resolved": "https://registry.npmmirror.com/d3-polygon/-/d3-polygon-1.0.6.tgz",
6763
  "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ=="
6764
  },
6765
+ "node_modules/d3-scale": {
6766
+ "version": "4.0.2",
6767
+ "resolved": "https://registry.npmmirror.com/d3-scale/-/d3-scale-4.0.2.tgz",
6768
+ "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
6769
+ "dependencies": {
6770
+ "d3-array": "2.10.0 - 3",
6771
+ "d3-format": "1 - 3",
6772
+ "d3-interpolate": "1.2.0 - 3",
6773
+ "d3-time": "2.1.1 - 3",
6774
+ "d3-time-format": "2 - 4"
6775
+ },
6776
+ "engines": {
6777
+ "node": ">=12"
6778
+ }
6779
+ },
6780
+ "node_modules/d3-scale/node_modules/d3-array": {
6781
+ "version": "3.2.4",
6782
+ "resolved": "https://registry.npmmirror.com/d3-array/-/d3-array-3.2.4.tgz",
6783
+ "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
6784
+ "dependencies": {
6785
+ "internmap": "1 - 2"
6786
+ },
6787
+ "engines": {
6788
+ "node": ">=12"
6789
+ }
6790
+ },
6791
+ "node_modules/d3-shape": {
6792
+ "version": "3.2.0",
6793
+ "resolved": "https://registry.npmmirror.com/d3-shape/-/d3-shape-3.2.0.tgz",
6794
+ "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
6795
+ "dependencies": {
6796
+ "d3-path": "^3.1.0"
6797
+ },
6798
+ "engines": {
6799
+ "node": ">=12"
6800
+ }
6801
+ },
6802
+ "node_modules/d3-time": {
6803
+ "version": "3.1.0",
6804
+ "resolved": "https://registry.npmmirror.com/d3-time/-/d3-time-3.1.0.tgz",
6805
+ "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
6806
+ "dependencies": {
6807
+ "d3-array": "2 - 3"
6808
+ },
6809
+ "engines": {
6810
+ "node": ">=12"
6811
+ }
6812
+ },
6813
+ "node_modules/d3-time-format": {
6814
+ "version": "4.1.0",
6815
+ "resolved": "https://registry.npmmirror.com/d3-time-format/-/d3-time-format-4.1.0.tgz",
6816
+ "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
6817
+ "dependencies": {
6818
+ "d3-time": "1 - 3"
6819
+ },
6820
+ "engines": {
6821
+ "node": ">=12"
6822
+ }
6823
+ },
6824
+ "node_modules/d3-time/node_modules/d3-array": {
6825
+ "version": "3.2.4",
6826
+ "resolved": "https://registry.npmmirror.com/d3-array/-/d3-array-3.2.4.tgz",
6827
+ "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
6828
+ "dependencies": {
6829
+ "internmap": "1 - 2"
6830
+ },
6831
+ "engines": {
6832
+ "node": ">=12"
6833
+ }
6834
+ },
6835
+ "node_modules/d3-timer": {
6836
+ "version": "3.0.1",
6837
+ "resolved": "https://registry.npmmirror.com/d3-timer/-/d3-timer-3.0.1.tgz",
6838
+ "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
6839
+ "engines": {
6840
+ "node": ">=12"
6841
+ }
6842
+ },
6843
  "node_modules/data-uri-to-buffer": {
6844
  "version": "4.0.1",
6845
  "resolved": "https://registry.npmmirror.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
 
6900
  "node": ">=0.10.0"
6901
  }
6902
  },
6903
+ "node_modules/decimal.js-light": {
6904
+ "version": "2.5.1",
6905
+ "resolved": "https://registry.npmmirror.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
6906
+ "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="
6907
+ },
6908
  "node_modules/decode-named-character-reference": {
6909
  "version": "1.0.2",
6910
  "resolved": "https://registry.npmmirror.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz",
 
7232
  "utila": "~0.4"
7233
  }
7234
  },
7235
+ "node_modules/dom-helpers": {
7236
+ "version": "5.2.1",
7237
+ "resolved": "https://registry.npmmirror.com/dom-helpers/-/dom-helpers-5.2.1.tgz",
7238
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
7239
+ "dependencies": {
7240
+ "@babel/runtime": "^7.8.7",
7241
+ "csstype": "^3.0.2"
7242
+ }
7243
+ },
7244
  "node_modules/dom-serializer": {
7245
  "version": "1.4.1",
7246
  "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz",
 
8360
  "es5-ext": "~0.10.14"
8361
  }
8362
  },
8363
+ "node_modules/eventemitter3": {
8364
+ "version": "4.0.7",
8365
+ "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-4.0.7.tgz",
8366
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
8367
+ },
8368
  "node_modules/events": {
8369
  "version": "3.3.0",
8370
  "resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz",
 
8570
  "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
8571
  "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
8572
  },
8573
+ "node_modules/fast-equals": {
8574
+ "version": "5.0.1",
8575
+ "resolved": "https://registry.npmmirror.com/fast-equals/-/fast-equals-5.0.1.tgz",
8576
+ "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==",
8577
+ "engines": {
8578
+ "node": ">=6.0.0"
8579
+ }
8580
+ },
8581
  "node_modules/fast-glob": {
8582
  "version": "3.2.12",
8583
  "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.2.12.tgz",
 
9915
  "node": ">= 0.4"
9916
  }
9917
  },
9918
+ "node_modules/internmap": {
9919
+ "version": "2.0.3",
9920
+ "resolved": "https://registry.npmmirror.com/internmap/-/internmap-2.0.3.tgz",
9921
+ "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
9922
+ "engines": {
9923
+ "node": ">=12"
9924
+ }
9925
+ },
9926
  "node_modules/intersection-observer": {
9927
  "version": "0.12.2",
9928
  "resolved": "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.12.2.tgz",
 
12155
  "version": "2.30.1",
12156
  "resolved": "https://registry.npmmirror.com/moment/-/moment-2.30.1.tgz",
12157
  "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
12158
+ "devOptional": true,
12159
  "engines": {
12160
  "node": "*"
12161
  }
 
14587
  "react-dom": "18.2.0"
14588
  }
14589
  },
14590
+ "node_modules/react-copy-to-clipboard": {
14591
+ "version": "5.1.0",
14592
+ "resolved": "https://registry.npmmirror.com/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz",
14593
+ "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==",
14594
+ "dependencies": {
14595
+ "copy-to-clipboard": "^3.3.1",
14596
+ "prop-types": "^15.8.1"
14597
+ },
14598
+ "peerDependencies": {
14599
+ "react": "^15.3.0 || 16 || 17 || 18"
14600
+ }
14601
+ },
14602
  "node_modules/react-dev-inspector": {
14603
  "version": "2.0.1",
14604
  "resolved": "https://registry.npmmirror.com/react-dev-inspector/-/react-dev-inspector-2.0.1.tgz",
 
15177
  "react": ">=15"
15178
  }
15179
  },
15180
+ "node_modules/react-smooth": {
15181
+ "version": "4.0.1",
15182
+ "resolved": "https://registry.npmmirror.com/react-smooth/-/react-smooth-4.0.1.tgz",
15183
+ "integrity": "sha512-OE4hm7XqR0jNOq3Qmk9mFLyd6p2+j6bvbPJ7qlB7+oo0eNcL2l7WQzG6MBnT3EXY6xzkLMUBec3AfewJdA0J8w==",
15184
+ "dependencies": {
15185
+ "fast-equals": "^5.0.1",
15186
+ "prop-types": "^15.8.1",
15187
+ "react-transition-group": "^4.4.5"
15188
+ },
15189
+ "peerDependencies": {
15190
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
15191
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
15192
+ }
15193
+ },
15194
  "node_modules/react-spinkit": {
15195
  "version": "3.0.0",
15196
  "resolved": "https://registry.npmmirror.com/react-spinkit/-/react-spinkit-3.0.0.tgz",
 
15225
  "react": ">= 0.14.0"
15226
  }
15227
  },
15228
+ "node_modules/react-transition-group": {
15229
+ "version": "4.4.5",
15230
+ "resolved": "https://registry.npmmirror.com/react-transition-group/-/react-transition-group-4.4.5.tgz",
15231
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
15232
+ "dependencies": {
15233
+ "@babel/runtime": "^7.5.5",
15234
+ "dom-helpers": "^5.0.1",
15235
+ "loose-envify": "^1.4.0",
15236
+ "prop-types": "^15.6.2"
15237
+ },
15238
+ "peerDependencies": {
15239
+ "react": ">=16.6.0",
15240
+ "react-dom": ">=16.6.0"
15241
+ }
15242
+ },
15243
  "node_modules/reactcss": {
15244
  "version": "1.2.3",
15245
  "resolved": "https://registry.npmmirror.com/reactcss/-/reactcss-1.2.3.tgz",
 
15417
  "node": ">= 12.13.0"
15418
  }
15419
  },
15420
+ "node_modules/recharts": {
15421
+ "version": "2.12.4",
15422
+ "resolved": "https://registry.npmmirror.com/recharts/-/recharts-2.12.4.tgz",
15423
+ "integrity": "sha512-dM4skmk4fDKEDjL9MNunxv6zcTxePGVEzRnLDXALRpfJ85JoQ0P0APJ/CoJlmnQI0gPjBlOkjzrwrfQrRST3KA==",
15424
+ "dependencies": {
15425
+ "clsx": "^2.0.0",
15426
+ "eventemitter3": "^4.0.1",
15427
+ "lodash": "^4.17.21",
15428
+ "react-is": "^16.10.2",
15429
+ "react-smooth": "^4.0.0",
15430
+ "recharts-scale": "^0.4.4",
15431
+ "tiny-invariant": "^1.3.1",
15432
+ "victory-vendor": "^36.6.8"
15433
+ },
15434
+ "engines": {
15435
+ "node": ">=14"
15436
+ },
15437
+ "peerDependencies": {
15438
+ "react": "^16.0.0 || ^17.0.0 || ^18.0.0",
15439
+ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
15440
+ }
15441
+ },
15442
+ "node_modules/recharts-scale": {
15443
+ "version": "0.4.5",
15444
+ "resolved": "https://registry.npmmirror.com/recharts-scale/-/recharts-scale-0.4.5.tgz",
15445
+ "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==",
15446
+ "dependencies": {
15447
+ "decimal.js-light": "^2.4.1"
15448
+ }
15449
+ },
15450
+ "node_modules/recharts/node_modules/react-is": {
15451
+ "version": "16.13.1",
15452
+ "resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz",
15453
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
15454
+ },
15455
  "node_modules/recursive-readdir": {
15456
  "version": "2.2.3",
15457
  "resolved": "https://registry.npmmirror.com/recursive-readdir/-/recursive-readdir-2.2.3.tgz",
 
17307
  "node_modules/tiny-invariant": {
17308
  "version": "1.3.1",
17309
  "resolved": "https://registry.npmmirror.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz",
17310
+ "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw=="
 
 
17311
  },
17312
  "node_modules/tiny-warning": {
17313
  "version": "1.0.3",
 
18526
  "unist-util-stringify-position": "^4.0.0"
18527
  }
18528
  },
18529
+ "node_modules/victory-vendor": {
18530
+ "version": "36.9.2",
18531
+ "resolved": "https://registry.npmmirror.com/victory-vendor/-/victory-vendor-36.9.2.tgz",
18532
+ "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==",
18533
+ "dependencies": {
18534
+ "@types/d3-array": "^3.0.3",
18535
+ "@types/d3-ease": "^3.0.0",
18536
+ "@types/d3-interpolate": "^3.0.1",
18537
+ "@types/d3-scale": "^4.0.2",
18538
+ "@types/d3-shape": "^3.1.0",
18539
+ "@types/d3-time": "^3.0.0",
18540
+ "@types/d3-timer": "^3.0.0",
18541
+ "d3-array": "^3.1.6",
18542
+ "d3-ease": "^3.0.1",
18543
+ "d3-interpolate": "^3.0.1",
18544
+ "d3-scale": "^4.0.2",
18545
+ "d3-shape": "^3.1.0",
18546
+ "d3-time": "^3.0.0",
18547
+ "d3-timer": "^3.0.1"
18548
+ }
18549
+ },
18550
+ "node_modules/victory-vendor/node_modules/d3-array": {
18551
+ "version": "3.2.4",
18552
+ "resolved": "https://registry.npmmirror.com/d3-array/-/d3-array-3.2.4.tgz",
18553
+ "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
18554
+ "dependencies": {
18555
+ "internmap": "1 - 2"
18556
+ },
18557
+ "engines": {
18558
+ "node": ">=12"
18559
+ }
18560
+ },
18561
  "node_modules/vite": {
18562
  "version": "4.3.1",
18563
  "resolved": "https://registry.npmmirror.com/vite/-/vite-4.3.1.tgz",
web/package.json CHANGED
@@ -17,19 +17,21 @@
17
  "antd": "^5.12.7",
18
  "axios": "^1.6.3",
19
  "classnames": "^2.5.1",
 
20
  "i18next": "^23.7.16",
21
  "js-base64": "^3.7.5",
22
  "jsencrypt": "^3.3.2",
23
  "lodash": "^4.17.21",
24
- "moment": "^2.30.1",
25
  "rc-tween-one": "^3.0.6",
26
  "react-chat-elements": "^12.0.13",
 
27
  "react-i18next": "^14.0.0",
28
  "react-infinite-scroll-component": "^6.1.0",
29
  "react-markdown": "^9.0.1",
30
  "react-pdf-highlighter": "^6.1.0",
31
  "react-string-replace": "^1.1.1",
32
  "react-syntax-highlighter": "^15.5.0",
 
33
  "remark-gfm": "^4.0.0",
34
  "umi": "^4.0.90",
35
  "umi-request": "^1.4.0",
@@ -40,6 +42,7 @@
40
  "@react-dev-inspector/umi4-plugin": "^2.0.1",
41
  "@types/lodash": "^4.14.202",
42
  "@types/react": "^18.0.33",
 
43
  "@types/react-dom": "^18.0.11",
44
  "@types/react-syntax-highlighter": "^15.5.11",
45
  "@types/uuid": "^9.0.8",
 
17
  "antd": "^5.12.7",
18
  "axios": "^1.6.3",
19
  "classnames": "^2.5.1",
20
+ "dayjs": "^1.11.10",
21
  "i18next": "^23.7.16",
22
  "js-base64": "^3.7.5",
23
  "jsencrypt": "^3.3.2",
24
  "lodash": "^4.17.21",
 
25
  "rc-tween-one": "^3.0.6",
26
  "react-chat-elements": "^12.0.13",
27
+ "react-copy-to-clipboard": "^5.1.0",
28
  "react-i18next": "^14.0.0",
29
  "react-infinite-scroll-component": "^6.1.0",
30
  "react-markdown": "^9.0.1",
31
  "react-pdf-highlighter": "^6.1.0",
32
  "react-string-replace": "^1.1.1",
33
  "react-syntax-highlighter": "^15.5.0",
34
+ "recharts": "^2.12.4",
35
  "remark-gfm": "^4.0.0",
36
  "umi": "^4.0.90",
37
  "umi-request": "^1.4.0",
 
42
  "@react-dev-inspector/umi4-plugin": "^2.0.1",
43
  "@types/lodash": "^4.14.202",
44
  "@types/react": "^18.0.33",
45
+ "@types/react-copy-to-clipboard": "^5.0.7",
46
  "@types/react-dom": "^18.0.11",
47
  "@types/react-syntax-highlighter": "^15.5.11",
48
  "@types/uuid": "^9.0.8",
web/src/app.tsx CHANGED
@@ -6,6 +6,21 @@ import zh_HK from 'antd/locale/zh_HK';
6
  import React, { ReactNode, useEffect, useState } from 'react';
7
  import storage from './utils/authorizationUtil';
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  const AntLanguageMap = {
10
  en: enUS,
11
  zh: zhCN,
 
6
  import React, { ReactNode, useEffect, useState } from 'react';
7
  import storage from './utils/authorizationUtil';
8
 
9
+ import dayjs from 'dayjs';
10
+ import advancedFormat from 'dayjs/plugin/advancedFormat';
11
+ import customParseFormat from 'dayjs/plugin/customParseFormat';
12
+ import localeData from 'dayjs/plugin/localeData';
13
+ import weekday from 'dayjs/plugin/weekday';
14
+ import weekOfYear from 'dayjs/plugin/weekOfYear';
15
+ import weekYear from 'dayjs/plugin/weekYear';
16
+
17
+ dayjs.extend(customParseFormat);
18
+ dayjs.extend(advancedFormat);
19
+ dayjs.extend(weekday);
20
+ dayjs.extend(localeData);
21
+ dayjs.extend(weekOfYear);
22
+ dayjs.extend(weekYear);
23
+
24
  const AntLanguageMap = {
25
  en: enUS,
26
  zh: zhCN,
web/src/components/copy-to-clipboard.tsx ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useTranslate } from '@/hooks/commonHooks';
2
+ import { CheckOutlined, CopyOutlined } from '@ant-design/icons';
3
+ import { Tooltip } from 'antd';
4
+ import { useState } from 'react';
5
+ import { CopyToClipboard as Clipboard, Props } from 'react-copy-to-clipboard';
6
+
7
+ const CopyToClipboard = ({ text }: Props) => {
8
+ const [copied, setCopied] = useState(false);
9
+ const { t } = useTranslate('common');
10
+
11
+ const handleCopy = () => {
12
+ setCopied(true);
13
+ setTimeout(() => {
14
+ setCopied(false);
15
+ }, 2000);
16
+ };
17
+
18
+ return (
19
+ <Tooltip title={copied ? t('copied') : t('copy')}>
20
+ <Clipboard text={text} onCopy={handleCopy}>
21
+ {copied ? <CheckOutlined /> : <CopyOutlined />}
22
+ </Clipboard>
23
+ </Tooltip>
24
+ );
25
+ };
26
+
27
+ export default CopyToClipboard;
web/src/components/line-chart/index.tsx ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import {
2
+ CartesianGrid,
3
+ Legend,
4
+ Line,
5
+ LineChart,
6
+ ResponsiveContainer,
7
+ Tooltip,
8
+ XAxis,
9
+ YAxis,
10
+ } from 'recharts';
11
+ import { CategoricalChartProps } from 'recharts/types/chart/generateCategoricalChart';
12
+
13
+ const data = [
14
+ {
15
+ name: 'Page A',
16
+ uv: 4000,
17
+ pv: 2400,
18
+ },
19
+ {
20
+ name: 'Page B',
21
+ uv: 3000,
22
+ pv: 1398,
23
+ },
24
+ {
25
+ name: 'Page C',
26
+ uv: 2000,
27
+ pv: 9800,
28
+ },
29
+ {
30
+ name: 'Page D',
31
+ uv: 2780,
32
+ pv: 3908,
33
+ },
34
+ {
35
+ name: 'Page E',
36
+ uv: 1890,
37
+ pv: 4800,
38
+ },
39
+ {
40
+ name: 'Page F',
41
+ uv: 2390,
42
+ pv: 3800,
43
+ },
44
+ {
45
+ name: 'Page G',
46
+ uv: 3490,
47
+ pv: 4300,
48
+ },
49
+ ];
50
+
51
+ interface IProps extends CategoricalChartProps {
52
+ data?: Array<{ xAxis: string; yAxis: number }>;
53
+ }
54
+
55
+ const RagLineChart = ({ data }: IProps) => {
56
+ return (
57
+ <ResponsiveContainer width="100%" height="100%">
58
+ <LineChart
59
+ // width={500}
60
+ // height={300}
61
+ data={data}
62
+ margin={
63
+ {
64
+ // top: 5,
65
+ // right: 30,
66
+ // left: 20,
67
+ // bottom: 10,
68
+ }
69
+ }
70
+ >
71
+ <CartesianGrid strokeDasharray="3 3" />
72
+ <XAxis dataKey="xAxis" />
73
+ <YAxis />
74
+ <Tooltip />
75
+ <Legend />
76
+ <Line
77
+ type="monotone"
78
+ dataKey="yAxis"
79
+ stroke="#8884d8"
80
+ activeDot={{ r: 8 }}
81
+ />
82
+ {/* <Line type="monotone" dataKey="uv" stroke="#82ca9d" /> */}
83
+ </LineChart>
84
+ </ResponsiveContainer>
85
+ );
86
+ };
87
+
88
+ export default RagLineChart;
web/src/hooks/chatHooks.ts CHANGED
@@ -1,4 +1,9 @@
1
- import { IConversation, IDialog } from '@/interfaces/database/chat';
 
 
 
 
 
2
  import { useCallback } from 'react';
3
  import { useDispatch, useSelector } from 'umi';
4
 
@@ -164,3 +169,82 @@ export const useCompleteConversation = () => {
164
 
165
  return completeConversation;
166
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import {
2
+ IConversation,
3
+ IDialog,
4
+ IStats,
5
+ IToken,
6
+ } from '@/interfaces/database/chat';
7
  import { useCallback } from 'react';
8
  import { useDispatch, useSelector } from 'umi';
9
 
 
169
 
170
  return completeConversation;
171
  };
172
+
173
+ // #region API provided for external calls
174
+
175
+ export const useCreateToken = (dialogId: string) => {
176
+ const dispatch = useDispatch();
177
+
178
+ const createToken = useCallback(() => {
179
+ return dispatch<any>({
180
+ type: 'chatModel/createToken',
181
+ payload: { dialogId },
182
+ });
183
+ }, [dispatch, dialogId]);
184
+
185
+ return createToken;
186
+ };
187
+
188
+ export const useListToken = () => {
189
+ const dispatch = useDispatch();
190
+
191
+ const listToken = useCallback(
192
+ (dialogId: string) => {
193
+ return dispatch<any>({
194
+ type: 'chatModel/listToken',
195
+ payload: { dialogId },
196
+ });
197
+ },
198
+ [dispatch],
199
+ );
200
+
201
+ return listToken;
202
+ };
203
+
204
+ export const useSelectTokenList = () => {
205
+ const tokenList: IToken[] = useSelector(
206
+ (state: any) => state.chatModel.tokenList,
207
+ );
208
+
209
+ return tokenList;
210
+ };
211
+
212
+ export const useRemoveToken = () => {
213
+ const dispatch = useDispatch();
214
+
215
+ const removeToken = useCallback(
216
+ (payload: { tenantId: string; dialogId: string; tokens: string[] }) => {
217
+ return dispatch<any>({
218
+ type: 'chatModel/removeToken',
219
+ payload: payload,
220
+ });
221
+ },
222
+ [dispatch],
223
+ );
224
+
225
+ return removeToken;
226
+ };
227
+
228
+ export const useFetchStats = () => {
229
+ const dispatch = useDispatch();
230
+
231
+ const fetchStats = useCallback(
232
+ (payload: any) => {
233
+ return dispatch<any>({
234
+ type: 'chatModel/getStats',
235
+ payload,
236
+ });
237
+ },
238
+ [dispatch],
239
+ );
240
+
241
+ return fetchStats;
242
+ };
243
+
244
+ export const useSelectStats = () => {
245
+ const stats: IStats = useSelector((state: any) => state.chatModel.stats);
246
+
247
+ return stats;
248
+ };
249
+
250
+ //#endregion
web/src/interfaces/database/chat.ts CHANGED
@@ -91,3 +91,21 @@ export interface Docagg {
91
  // term_similarity: number;
92
  // vector_similarity: number;
93
  // }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  // term_similarity: number;
92
  // vector_similarity: number;
93
  // }
94
+
95
+ export interface IToken {
96
+ create_date: string;
97
+ create_time: number;
98
+ tenant_id: string;
99
+ token: string;
100
+ update_date?: any;
101
+ update_time?: any;
102
+ }
103
+
104
+ export interface IStats {
105
+ pv: [string, number][];
106
+ uv: [string, number][];
107
+ speed: [string, number][];
108
+ tokens: [string, number][];
109
+ round: [string, number][];
110
+ thumb_up: [string, number][];
111
+ }
web/src/locales/en.ts CHANGED
@@ -20,6 +20,8 @@ export default {
20
  language: 'Language',
21
  languageMessage: 'Please input your language!',
22
  languagePlaceholder: 'select your language',
 
 
23
  },
24
  login: {
25
  login: 'Sign in',
@@ -335,6 +337,24 @@ export default {
335
  'This sets the maximum length of the model’s output, measured in the number of tokens (words or pieces of words).',
336
  quote: 'Show Quote',
337
  quoteTip: 'Should the source of the original text be displayed?',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
  },
339
  setting: {
340
  profile: 'Profile',
 
20
  language: 'Language',
21
  languageMessage: 'Please input your language!',
22
  languagePlaceholder: 'select your language',
23
+ copy: 'Copy',
24
+ copied: 'Copied',
25
  },
26
  login: {
27
  login: 'Sign in',
 
337
  'This sets the maximum length of the model’s output, measured in the number of tokens (words or pieces of words).',
338
  quote: 'Show Quote',
339
  quoteTip: 'Should the source of the original text be displayed?',
340
+ overview: 'Overview',
341
+ pv: 'Number of messages',
342
+ uv: 'Active user number',
343
+ speed: 'Token output speed',
344
+ tokens: 'Consume the token number',
345
+ round: 'Session Interaction Number',
346
+ thumbUp: 'customer satisfaction',
347
+ publicUrl: 'Public URL',
348
+ preview: 'Preview',
349
+ embedded: 'Embedded',
350
+ serviceApiEndpoint: 'Service API Endpoint',
351
+ apiKey: 'Api Key',
352
+ apiReference: 'Api Reference',
353
+ dateRange: 'Date Range:',
354
+ backendServiceApi: 'Backend service API',
355
+ createNewKey: 'Create new key',
356
+ created: 'Created',
357
+ action: 'Action',
358
  },
359
  setting: {
360
  profile: 'Profile',
web/src/locales/zh-traditional.ts CHANGED
@@ -15,11 +15,13 @@ export default {
15
  edit: '編輯',
16
  upload: '上傳',
17
  english: '英語',
18
- chinese: '中文簡體',
19
- traditionalChinese: '中文繁體',
20
  language: '語言',
21
  languageMessage: '請輸入語言',
22
  languagePlaceholder: '請選擇語言',
 
 
23
  },
24
  login: {
25
  login: '登入',
@@ -269,7 +271,7 @@ export default {
269
  systemMessage: '請輸入',
270
  systemTip:
271
  '當LLM回答問題時,你需要LLM遵循的說明,比如角色設計、答案長度和答案語言等。',
272
- topN: 'top n',
273
  topNTip: `並非所有相似度得分高於“相似度閾值”的塊都會被提供給法學碩士。LLM 只能看到這些“Top N”塊。`,
274
  variable: '變量',
275
  variableTip: `如果您使用对话 API,变量可能会帮助您使用不同的策略与客户聊天。
@@ -310,6 +312,24 @@ export default {
310
  '這設置了模型輸出的最大長度,以標記(單詞或單詞片段)的數量來衡量。',
311
  quote: '顯示引文',
312
  quoteTip: '是否應該顯示原文出處?',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  },
314
  setting: {
315
  profile: '概述',
 
15
  edit: '編輯',
16
  upload: '上傳',
17
  english: '英語',
18
+ chinese: '簡體中文',
19
+ traditionalChinese: '繁體中文',
20
  language: '語言',
21
  languageMessage: '請輸入語言',
22
  languagePlaceholder: '請選擇語言',
23
+ copy: '複製',
24
+ copied: '複製成功',
25
  },
26
  login: {
27
  login: '登入',
 
271
  systemMessage: '請輸入',
272
  systemTip:
273
  '當LLM回答問題時,你需要LLM遵循的說明,比如角色設計、答案長度和答案語言等。',
274
+ topN: 'Top N',
275
  topNTip: `並非所有相似度得分高於“相似度閾值”的塊都會被提供給法學碩士。LLM 只能看到這些“Top N”塊。`,
276
  variable: '變量',
277
  variableTip: `如果您使用对话 API,变量可能会帮助您使用不同的策略与客户聊天。
 
312
  '這設置了模型輸出的最大長度,以標記(單詞或單詞片段)的數量來衡量。',
313
  quote: '顯示引文',
314
  quoteTip: '是否應該顯示原文出處?',
315
+ overview: '概覽',
316
+ pv: '消息數',
317
+ uv: '活躍用戶數',
318
+ speed: 'Token 輸出速度',
319
+ tokens: '消耗Token數',
320
+ round: '會話互動數',
321
+ thumbUp: '用戶滿意度',
322
+ publicUrl: '公共url',
323
+ preview: '預覽',
324
+ embedded: '嵌入',
325
+ serviceApiEndpoint: '服務API端點',
326
+ apiKey: 'API鍵',
327
+ apiReference: 'API參考',
328
+ dateRange: '日期範圍:',
329
+ backendServiceApi: '後端服務API',
330
+ createNewKey: '創建新密鑰',
331
+ created: '創建於',
332
+ action: '操作',
333
  },
334
  setting: {
335
  profile: '概述',
web/src/locales/zh.ts CHANGED
@@ -15,11 +15,13 @@ export default {
15
  edit: '编辑',
16
  upload: '上传',
17
  english: '英文',
18
- chinese: '中文简体',
19
- traditionalChinese: '中文繁体',
20
  language: '语言',
21
  languageMessage: '请输入语言',
22
  languagePlaceholder: '请选择语言',
 
 
23
  },
24
  login: {
25
  login: '登录',
@@ -326,6 +328,24 @@ export default {
326
  '这设置了模型输出的最大长度,以标记(单词或单词片段)的数量来衡量。',
327
  quote: '显示引文',
328
  quoteTip: '是否应该显示原文出处?',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
  },
330
  setting: {
331
  profile: '概要',
 
15
  edit: '编辑',
16
  upload: '上传',
17
  english: '英文',
18
+ chinese: '简体中文',
19
+ traditionalChinese: '繁体中文',
20
  language: '语言',
21
  languageMessage: '请输入语言',
22
  languagePlaceholder: '请选择语言',
23
+ copy: '复制',
24
+ copied: '复制成功',
25
  },
26
  login: {
27
  login: '登录',
 
328
  '这设置了模型输出的最大长度,以标记(单词或单词片段)的数量来衡量。',
329
  quote: '显示引文',
330
  quoteTip: '是否应该显示原文出处?',
331
+ overview: '概览',
332
+ pv: '消息数',
333
+ uv: '活跃用户数',
334
+ speed: 'Token 输出速度',
335
+ tokens: '消耗Token数',
336
+ round: '会话互动数',
337
+ thumbUp: '用户满意度',
338
+ publicUrl: '公共Url',
339
+ preview: '预览',
340
+ embedded: '嵌入',
341
+ serviceApiEndpoint: '服务API端点',
342
+ apiKey: 'API键',
343
+ apiReference: 'API参考',
344
+ dateRange: '日期范围:',
345
+ backendServiceApi: '后端服务API',
346
+ createNewKey: '创建新密钥',
347
+ created: '创建于',
348
+ action: '操作',
349
  },
350
  setting: {
351
  profile: '概要',
web/src/pages/add-knowledge/components/knowledge-file/index.tsx CHANGED
@@ -26,6 +26,7 @@ import ParsingActionCell from './parsing-action-cell';
26
  import ParsingStatusCell from './parsing-status-cell';
27
  import RenameModal from './rename-modal';
28
 
 
29
  import styles from './index.less';
30
 
31
  const KnowledgeFile = () => {
@@ -94,6 +95,9 @@ const KnowledgeFile = () => {
94
  title: t('uploadDate'),
95
  dataIndex: 'create_date',
96
  key: 'create_date',
 
 
 
97
  },
98
  {
99
  title: t('chunkMethod'),
 
26
  import ParsingStatusCell from './parsing-status-cell';
27
  import RenameModal from './rename-modal';
28
 
29
+ import { formatDate } from '@/utils/date';
30
  import styles from './index.less';
31
 
32
  const KnowledgeFile = () => {
 
95
  title: t('uploadDate'),
96
  dataIndex: 'create_date',
97
  key: 'create_date',
98
+ render(value) {
99
+ return formatDate(value);
100
+ },
101
  },
102
  {
103
  title: t('chunkMethod'),
web/src/pages/chat/chat-api-key-modal/index.tsx ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import CopyToClipboard from '@/components/copy-to-clipboard';
2
+ import { useTranslate } from '@/hooks/commonHooks';
3
+ import { IModalProps } from '@/interfaces/common';
4
+ import { IToken } from '@/interfaces/database/chat';
5
+ import { formatDate } from '@/utils/date';
6
+ import { DeleteOutlined } from '@ant-design/icons';
7
+ import type { TableProps } from 'antd';
8
+ import { Button, Modal, Space, Table } from 'antd';
9
+ import { useOperateApiKey } from '../hooks';
10
+
11
+ const ChatApiKeyModal = ({
12
+ visible,
13
+ dialogId,
14
+ hideModal,
15
+ }: IModalProps<any> & { dialogId: string }) => {
16
+ const { createToken, removeToken, tokenList, listLoading, creatingLoading } =
17
+ useOperateApiKey(visible, dialogId);
18
+ const { t } = useTranslate('chat');
19
+
20
+ const columns: TableProps<IToken>['columns'] = [
21
+ {
22
+ title: 'Token',
23
+ dataIndex: 'token',
24
+ key: 'token',
25
+ render: (text) => <a>{text}</a>,
26
+ },
27
+ {
28
+ title: t('created'),
29
+ dataIndex: 'create_date',
30
+ key: 'create_date',
31
+ render: (text) => formatDate(text),
32
+ },
33
+ {
34
+ title: t('action'),
35
+ key: 'action',
36
+ render: (_, record) => (
37
+ <Space size="middle">
38
+ <CopyToClipboard text={record.token}></CopyToClipboard>
39
+ <DeleteOutlined
40
+ onClick={() => removeToken(record.token, record.tenant_id)}
41
+ />
42
+ </Space>
43
+ ),
44
+ },
45
+ ];
46
+
47
+ return (
48
+ <>
49
+ <Modal
50
+ title={t('apiKey')}
51
+ open={visible}
52
+ onCancel={hideModal}
53
+ style={{ top: 300 }}
54
+ width={'50vw'}
55
+ >
56
+ <Table
57
+ columns={columns}
58
+ dataSource={tokenList}
59
+ rowKey={'token'}
60
+ loading={listLoading}
61
+ />
62
+ <Button onClick={createToken} loading={creatingLoading}>
63
+ {t('createNewKey')}
64
+ </Button>
65
+ </Modal>
66
+ </>
67
+ );
68
+ };
69
+
70
+ export default ChatApiKeyModal;
web/src/pages/chat/chat-configuration-modal/assistant-setting.tsx CHANGED
@@ -1,6 +1,6 @@
1
  import { useFetchKnowledgeList } from '@/hooks/knowledgeHook';
2
  import { PlusOutlined } from '@ant-design/icons';
3
- import { Form, Input, Select, Upload } from 'antd';
4
  import classNames from 'classnames';
5
  import { ISegmentedContentProps } from '../interface';
6
 
@@ -83,6 +83,15 @@ const AssistantSetting = ({ show }: ISegmentedContentProps) => {
83
  >
84
  <Input.TextArea autoSize={{ minRows: 5 }} />
85
  </Form.Item>
 
 
 
 
 
 
 
 
 
86
  <Form.Item
87
  label={t('knowledgeBases')}
88
  name="kb_ids"
 
1
  import { useFetchKnowledgeList } from '@/hooks/knowledgeHook';
2
  import { PlusOutlined } from '@ant-design/icons';
3
+ import { Form, Input, Select, Switch, Upload } from 'antd';
4
  import classNames from 'classnames';
5
  import { ISegmentedContentProps } from '../interface';
6
 
 
83
  >
84
  <Input.TextArea autoSize={{ minRows: 5 }} />
85
  </Form.Item>
86
+ <Form.Item
87
+ label={t('quote')}
88
+ valuePropName="checked"
89
+ name={['prompt_config', 'quote']}
90
+ tooltip={t('quoteTip')}
91
+ initialValue={true}
92
+ >
93
+ <Switch />
94
+ </Form.Item>
95
  <Form.Item
96
  label={t('knowledgeBases')}
97
  name="kb_ids"
web/src/pages/chat/chat-configuration-modal/prompt-engine.tsx CHANGED
@@ -172,15 +172,7 @@ const PromptEngine = (
172
  >
173
  <Slider max={30} />
174
  </Form.Item>
175
- <Form.Item
176
- label={t('quote')}
177
- valuePropName="checked"
178
- name={['prompt_config', 'quote']}
179
- tooltip={t('quoteTip')}
180
- initialValue={true}
181
- >
182
- <Switch />
183
- </Form.Item>
184
  <section className={classNames(styles.variableContainer)}>
185
  <Row align={'middle'} justify="end">
186
  <Col span={7} className={styles.variableAlign}>
 
172
  >
173
  <Slider max={30} />
174
  </Form.Item>
175
+
 
 
 
 
 
 
 
 
176
  <section className={classNames(styles.variableContainer)}>
177
  <Row align={'middle'} justify="end">
178
  <Col span={7} className={styles.variableAlign}>
web/src/pages/chat/chat-overview-modal/index.less ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .chartWrapper {
2
+ height: 40vh;
3
+ overflow: auto;
4
+ }
5
+
6
+ .chartItem {
7
+ height: 300px;
8
+ padding: 10px 0 30px;
9
+ }
10
+
11
+ .chartLabel {
12
+ display: inline-block;
13
+ padding-left: 60px;
14
+ padding-bottom: 20px;
15
+ }
16
+ .linkText {
17
+ border-radius: 6px;
18
+ padding: 6px 10px;
19
+ background-color: #eff8ff;
20
+ border: 1px;
21
+ }
web/src/pages/chat/chat-overview-modal/index.tsx ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import LineChart from '@/components/line-chart';
2
+ import { useSetModalState, useTranslate } from '@/hooks/commonHooks';
3
+ import { IModalProps } from '@/interfaces/common';
4
+ import { IDialog, IStats } from '@/interfaces/database/chat';
5
+ import { Button, Card, DatePicker, Flex, Modal, Space, Typography } from 'antd';
6
+ import { RangePickerProps } from 'antd/es/date-picker';
7
+ import dayjs from 'dayjs';
8
+ import camelCase from 'lodash/camelCase';
9
+ import ChatApiKeyModal from '../chat-api-key-modal';
10
+ import { useFetchStatsOnMount, useSelectChartStatsList } from '../hooks';
11
+ import styles from './index.less';
12
+
13
+ const { Paragraph } = Typography;
14
+ const { RangePicker } = DatePicker;
15
+
16
+ const ChatOverviewModal = ({
17
+ visible,
18
+ hideModal,
19
+ dialog,
20
+ }: IModalProps<any> & { dialog: IDialog }) => {
21
+ const { t } = useTranslate('chat');
22
+ const chartList = useSelectChartStatsList();
23
+
24
+ const {
25
+ visible: apiKeyVisible,
26
+ hideModal: hideApiKeyModal,
27
+ showModal: showApiKeyModal,
28
+ } = useSetModalState();
29
+
30
+ const { pickerValue, setPickerValue } = useFetchStatsOnMount(visible);
31
+
32
+ const disabledDate: RangePickerProps['disabledDate'] = (current) => {
33
+ return current && current > dayjs().endOf('day');
34
+ };
35
+
36
+ return (
37
+ <>
38
+ <Modal
39
+ title={t('overview')}
40
+ open={visible}
41
+ onCancel={hideModal}
42
+ width={'100vw'}
43
+ >
44
+ <Flex vertical gap={'middle'}>
45
+ <Card title={dialog.name}>
46
+ <Flex gap={8} vertical>
47
+ {t('publicUrl')}
48
+ <Paragraph copyable className={styles.linkText}>
49
+ This is a copyable text.
50
+ </Paragraph>
51
+ </Flex>
52
+ <Space size={'middle'}>
53
+ <Button>{t('preview')}</Button>
54
+ <Button>{t('embedded')}</Button>
55
+ </Space>
56
+ </Card>
57
+ <Card title={t('backendServiceApi')}>
58
+ <Flex gap={8} vertical>
59
+ {t('serviceApiEndpoint')}
60
+ <Paragraph copyable className={styles.linkText}>
61
+ This is a copyable text.
62
+ </Paragraph>
63
+ </Flex>
64
+ <Space size={'middle'}>
65
+ <Button onClick={showApiKeyModal}>{t('apiKey')}</Button>
66
+ <Button>{t('apiReference')}</Button>
67
+ </Space>
68
+ </Card>
69
+ <Space>
70
+ <b>{t('dateRange')}</b>
71
+ <RangePicker
72
+ disabledDate={disabledDate}
73
+ value={pickerValue}
74
+ onChange={setPickerValue}
75
+ allowClear={false}
76
+ />
77
+ </Space>
78
+ <div className={styles.chartWrapper}>
79
+ {Object.keys(chartList).map((x) => (
80
+ <div key={x} className={styles.chartItem}>
81
+ <b className={styles.chartLabel}>{t(camelCase(x))}</b>
82
+ <LineChart data={chartList[x as keyof IStats]}></LineChart>
83
+ </div>
84
+ ))}
85
+ </div>
86
+ </Flex>
87
+ <ChatApiKeyModal
88
+ visible={apiKeyVisible}
89
+ hideModal={hideApiKeyModal}
90
+ dialogId={dialog.id}
91
+ ></ChatApiKeyModal>
92
+ </Modal>
93
+ </>
94
+ );
95
+ };
96
+
97
+ export default ChatOverviewModal;
web/src/pages/chat/hooks.ts CHANGED
@@ -2,22 +2,28 @@ import { MessageType } from '@/constants/chat';
2
  import { fileIconMap } from '@/constants/common';
3
  import {
4
  useCompleteConversation,
 
5
  useFetchConversation,
6
  useFetchConversationList,
7
  useFetchDialog,
8
  useFetchDialogList,
 
 
9
  useRemoveConversation,
10
  useRemoveDialog,
 
11
  useSelectConversationList,
12
  useSelectDialogList,
 
13
  useSetDialog,
14
  useUpdateConversation,
15
  } from '@/hooks/chatHooks';
16
  import { useSetModalState, useShowDeleteConfirm } from '@/hooks/commonHooks';
17
  import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
18
- import { IConversation, IDialog } from '@/interfaces/database/chat';
19
  import { IChunk } from '@/interfaces/database/knowledge';
20
  import { getFileExtension } from '@/utils';
 
21
  import omit from 'lodash/omit';
22
  import {
23
  ChangeEventHandler,
@@ -704,3 +710,108 @@ export const useGetSendButtonDisabled = () => {
704
  return dialogId === '' && conversationId === '';
705
  };
706
  //#endregion
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  import { fileIconMap } from '@/constants/common';
3
  import {
4
  useCompleteConversation,
5
+ useCreateToken,
6
  useFetchConversation,
7
  useFetchConversationList,
8
  useFetchDialog,
9
  useFetchDialogList,
10
+ useFetchStats,
11
+ useListToken,
12
  useRemoveConversation,
13
  useRemoveDialog,
14
+ useRemoveToken,
15
  useSelectConversationList,
16
  useSelectDialogList,
17
+ useSelectTokenList,
18
  useSetDialog,
19
  useUpdateConversation,
20
  } from '@/hooks/chatHooks';
21
  import { useSetModalState, useShowDeleteConfirm } from '@/hooks/commonHooks';
22
  import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
23
+ import { IConversation, IDialog, IStats } from '@/interfaces/database/chat';
24
  import { IChunk } from '@/interfaces/database/knowledge';
25
  import { getFileExtension } from '@/utils';
26
+ import dayjs, { Dayjs } from 'dayjs';
27
  import omit from 'lodash/omit';
28
  import {
29
  ChangeEventHandler,
 
710
  return dialogId === '' && conversationId === '';
711
  };
712
  //#endregion
713
+
714
+ //#region API provided for external calls
715
+
716
+ type RangeValue = [Dayjs | null, Dayjs | null] | null;
717
+
718
+ export const useFetchStatsOnMount = (visible: boolean) => {
719
+ const fetchStats = useFetchStats();
720
+ const [pickerValue, setPickerValue] = useState<RangeValue>([
721
+ dayjs(),
722
+ dayjs().subtract(7, 'day'),
723
+ ]);
724
+
725
+ useEffect(() => {
726
+ if (visible && Array.isArray(pickerValue) && pickerValue[0]) {
727
+ fetchStats({ fromDate: pickerValue[0], toDate: pickerValue[1] });
728
+ }
729
+ }, [fetchStats, pickerValue, visible]);
730
+
731
+ return {
732
+ pickerValue,
733
+ setPickerValue,
734
+ };
735
+ };
736
+
737
+ export const useOperateApiKey = (visible: boolean, dialogId: string) => {
738
+ const removeToken = useRemoveToken();
739
+ const createToken = useCreateToken(dialogId);
740
+ const listToken = useListToken();
741
+ const tokenList = useSelectTokenList();
742
+ const creatingLoading = useOneNamespaceEffectsLoading('chatModel', [
743
+ 'createToken',
744
+ ]);
745
+ const listLoading = useOneNamespaceEffectsLoading('chatModel', ['list']);
746
+
747
+ const showDeleteConfirm = useShowDeleteConfirm();
748
+
749
+ const onRemoveToken = (token: string, tenantId: string) => {
750
+ showDeleteConfirm({
751
+ onOk: () => removeToken({ dialogId, tokens: [token], tenantId }),
752
+ });
753
+ };
754
+
755
+ useEffect(() => {
756
+ if (visible && dialogId) {
757
+ listToken(dialogId);
758
+ }
759
+ }, [listToken, dialogId, visible]);
760
+
761
+ return {
762
+ removeToken: onRemoveToken,
763
+ createToken,
764
+ tokenList,
765
+ creatingLoading,
766
+ listLoading,
767
+ };
768
+ };
769
+
770
+ type ChartStatsType = {
771
+ [k in keyof IStats]: Array<{ xAxis: string; yAxis: number }>;
772
+ };
773
+
774
+ export const useSelectChartStatsList = (): ChartStatsType => {
775
+ // const stats: IStats = useSelectStats();
776
+ const stats = {
777
+ pv: [
778
+ ['2024-06-01', 1],
779
+ ['2024-07-24', 3],
780
+ ['2024-09-01', 10],
781
+ ],
782
+ uv: [
783
+ ['2024-02-01', 0],
784
+ ['2024-03-01', 99],
785
+ ['2024-05-01', 3],
786
+ ],
787
+ speed: [
788
+ ['2024-09-01', 2],
789
+ ['2024-09-01', 3],
790
+ ],
791
+ tokens: [
792
+ ['2024-09-01', 1],
793
+ ['2024-09-01', 3],
794
+ ],
795
+ round: [
796
+ ['2024-09-01', 0],
797
+ ['2024-09-01', 3],
798
+ ],
799
+ thumb_up: [
800
+ ['2024-09-01', 3],
801
+ ['2024-09-01', 9],
802
+ ],
803
+ };
804
+
805
+ return Object.keys(stats).reduce((pre, cur) => {
806
+ const item = stats[cur as keyof IStats];
807
+ if (item.length > 0) {
808
+ pre[cur as keyof IStats] = item.map((x) => ({
809
+ xAxis: x[0] as string,
810
+ yAxis: x[1] as number,
811
+ }));
812
+ }
813
+ return pre;
814
+ }, {} as ChartStatsType);
815
+ };
816
+
817
+ //#endregion
web/src/pages/chat/index.tsx CHANGED
@@ -35,7 +35,10 @@ import {
35
  useSelectFirstDialogOnMount,
36
  } from './hooks';
37
 
38
- import { useTranslate } from '@/hooks/commonHooks';
 
 
 
39
  import styles from './index.less';
40
 
41
  const Chat = () => {
@@ -73,6 +76,12 @@ const Chat = () => {
73
  const dialogLoading = useSelectDialogListLoading();
74
  const conversationLoading = useSelectConversationListLoading();
75
  const { t } = useTranslate('chat');
 
 
 
 
 
 
76
 
77
  useFetchDialogOnMount(dialogId, true);
78
 
@@ -100,6 +109,15 @@ const Chat = () => {
100
  onRemoveDialog([dialogId]);
101
  };
102
 
 
 
 
 
 
 
 
 
 
103
  const handleRemoveConversation =
104
  (conversationId: string): MenuItemProps['onClick'] =>
105
  ({ domEvent }) => {
@@ -141,7 +159,9 @@ const Chat = () => {
141
  },
142
  ];
143
 
144
- const buildAppItems = (dialogId: string) => {
 
 
145
  const appItems: MenuProps['items'] = [
146
  {
147
  key: '1',
@@ -164,6 +184,17 @@ const Chat = () => {
164
  </Space>
165
  ),
166
  },
 
 
 
 
 
 
 
 
 
 
 
167
  ];
168
 
169
  return appItems;
@@ -230,7 +261,7 @@ const Chat = () => {
230
  </Space>
231
  {activated === x.id && (
232
  <section>
233
- <Dropdown menu={{ items: buildAppItems(x.id) }}>
234
  <ChatAppCube
235
  className={styles.cubeIcon}
236
  ></ChatAppCube>
@@ -315,6 +346,11 @@ const Chat = () => {
315
  initialName={initialConversationName}
316
  loading={conversationRenameLoading}
317
  ></RenameModal>
 
 
 
 
 
318
  </Flex>
319
  );
320
  };
 
35
  useSelectFirstDialogOnMount,
36
  } from './hooks';
37
 
38
+ import { useSetModalState, useTranslate } from '@/hooks/commonHooks';
39
+ import { useSetSelectedRecord } from '@/hooks/logicHooks';
40
+ import { IDialog } from '@/interfaces/database/chat';
41
+ import ChatOverviewModal from './chat-overview-modal';
42
  import styles from './index.less';
43
 
44
  const Chat = () => {
 
76
  const dialogLoading = useSelectDialogListLoading();
77
  const conversationLoading = useSelectConversationListLoading();
78
  const { t } = useTranslate('chat');
79
+ const {
80
+ visible: overviewVisible,
81
+ hideModal: hideOverviewModal,
82
+ showModal: showOverviewModal,
83
+ } = useSetModalState();
84
+ const { currentRecord, setRecord } = useSetSelectedRecord<IDialog>();
85
 
86
  useFetchDialogOnMount(dialogId, true);
87
 
 
109
  onRemoveDialog([dialogId]);
110
  };
111
 
112
+ const handleShowOverviewModal =
113
+ (dialog: IDialog): any =>
114
+ (info: any) => {
115
+ info?.domEvent?.preventDefault();
116
+ info?.domEvent?.stopPropagation();
117
+ setRecord(dialog);
118
+ showOverviewModal();
119
+ };
120
+
121
  const handleRemoveConversation =
122
  (conversationId: string): MenuItemProps['onClick'] =>
123
  ({ domEvent }) => {
 
159
  },
160
  ];
161
 
162
+ const buildAppItems = (dialog: IDialog) => {
163
+ const dialogId = dialog.id;
164
+
165
  const appItems: MenuProps['items'] = [
166
  {
167
  key: '1',
 
184
  </Space>
185
  ),
186
  },
187
+ { type: 'divider' },
188
+ // {
189
+ // key: '3',
190
+ // onClick: handleShowOverviewModal(dialog),
191
+ // label: (
192
+ // <Space>
193
+ // <ProfileOutlined />
194
+ // {t('overview')}
195
+ // </Space>
196
+ // ),
197
+ // },
198
  ];
199
 
200
  return appItems;
 
261
  </Space>
262
  {activated === x.id && (
263
  <section>
264
+ <Dropdown menu={{ items: buildAppItems(x) }}>
265
  <ChatAppCube
266
  className={styles.cubeIcon}
267
  ></ChatAppCube>
 
346
  initialName={initialConversationName}
347
  loading={conversationRenameLoading}
348
  ></RenameModal>
349
+ <ChatOverviewModal
350
+ visible={overviewVisible}
351
+ hideModal={hideOverviewModal}
352
+ dialog={currentRecord}
353
+ ></ChatOverviewModal>
354
  </Flex>
355
  );
356
  };
web/src/pages/chat/model.ts CHANGED
@@ -1,7 +1,14 @@
1
- import { IConversation, IDialog, Message } from '@/interfaces/database/chat';
 
 
 
 
 
 
2
  import i18n from '@/locales/config';
3
  import chatService from '@/services/chatService';
4
  import { message } from 'antd';
 
5
  import { DvaModel } from 'umi';
6
  import { v4 as uuid } from 'uuid';
7
  import { IClientConversation, IMessage } from './interface';
@@ -13,6 +20,8 @@ export interface ChatModelState {
13
  currentDialog: IDialog;
14
  conversationList: IConversation[];
15
  currentConversation: IClientConversation;
 
 
16
  }
17
 
18
  const model: DvaModel<ChatModelState> = {
@@ -23,6 +32,8 @@ const model: DvaModel<ChatModelState> = {
23
  currentDialog: <IDialog>{},
24
  conversationList: [],
25
  currentConversation: {} as IClientConversation,
 
 
26
  },
27
  reducers: {
28
  save(state, action) {
@@ -60,6 +71,18 @@ const model: DvaModel<ChatModelState> = {
60
  currentConversation: { ...payload, message: messageList },
61
  };
62
  },
 
 
 
 
 
 
 
 
 
 
 
 
63
  },
64
 
65
  effects: {
@@ -160,6 +183,78 @@ const model: DvaModel<ChatModelState> = {
160
  }
161
  return data.retcode;
162
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  },
164
  };
165
 
 
1
+ import {
2
+ IConversation,
3
+ IDialog,
4
+ IStats,
5
+ IToken,
6
+ Message,
7
+ } from '@/interfaces/database/chat';
8
  import i18n from '@/locales/config';
9
  import chatService from '@/services/chatService';
10
  import { message } from 'antd';
11
+ import omit from 'lodash/omit';
12
  import { DvaModel } from 'umi';
13
  import { v4 as uuid } from 'uuid';
14
  import { IClientConversation, IMessage } from './interface';
 
20
  currentDialog: IDialog;
21
  conversationList: IConversation[];
22
  currentConversation: IClientConversation;
23
+ tokenList: IToken[];
24
+ stats: IStats;
25
  }
26
 
27
  const model: DvaModel<ChatModelState> = {
 
32
  currentDialog: <IDialog>{},
33
  conversationList: [],
34
  currentConversation: {} as IClientConversation,
35
+ tokenList: [],
36
+ stats: {} as IStats,
37
  },
38
  reducers: {
39
  save(state, action) {
 
71
  currentConversation: { ...payload, message: messageList },
72
  };
73
  },
74
+ setTokenList(state, { payload }) {
75
+ return {
76
+ ...state,
77
+ tokenList: payload,
78
+ };
79
+ },
80
+ setStats(state, { payload }) {
81
+ return {
82
+ ...state,
83
+ stats: payload,
84
+ };
85
+ },
86
  },
87
 
88
  effects: {
 
183
  }
184
  return data.retcode;
185
  },
186
+ *createToken({ payload }, { call, put }) {
187
+ const { data } = yield call(chatService.createToken, payload);
188
+ if (data.retcode === 0) {
189
+ yield put({
190
+ type: 'listToken',
191
+ payload: payload,
192
+ });
193
+ message.success(i18n.t('message.created'));
194
+ }
195
+ return data.retcode;
196
+ },
197
+ *listToken({ payload }, { call, put }) {
198
+ const { data } = yield call(chatService.listToken, payload);
199
+ if (data.retcode === 0) {
200
+ yield put({
201
+ type: 'setTokenList',
202
+ payload: data.data,
203
+ });
204
+ }
205
+ return data.retcode;
206
+ },
207
+ *removeToken({ payload }, { call, put }) {
208
+ const { data } = yield call(
209
+ chatService.removeToken,
210
+ omit(payload, ['dialogId']),
211
+ );
212
+ if (data.retcode === 0) {
213
+ yield put({
214
+ type: 'listToken',
215
+ payload: { dialog_id: payload.dialogId },
216
+ });
217
+ }
218
+ return data.retcode;
219
+ },
220
+ *getStats({ payload }, { call, put }) {
221
+ const { data } = yield call(chatService.getStats, payload);
222
+ if (data.retcode === 0) {
223
+ yield put({
224
+ type: 'setStats',
225
+ payload: data.data,
226
+ });
227
+ }
228
+ return data.retcode;
229
+ },
230
+ *createExternalConversation({ payload }, { call, put }) {
231
+ const { data } = yield call(
232
+ chatService.createExternalConversation,
233
+ payload,
234
+ );
235
+ if (data.retcode === 0) {
236
+ yield put({
237
+ type: 'getExternalConversation',
238
+ payload: { conversation_id: payload.conversationId },
239
+ });
240
+ }
241
+ return data.retcode;
242
+ },
243
+ *getExternalConversation({ payload }, { call }) {
244
+ const { data } = yield call(
245
+ chatService.getExternalConversation,
246
+ null,
247
+ payload,
248
+ );
249
+ return data.retcode;
250
+ },
251
+ *completeExternalConversation({ payload }, { call }) {
252
+ const { data } = yield call(
253
+ chatService.completeExternalConversation,
254
+ payload,
255
+ );
256
+ return data.retcode;
257
+ },
258
  },
259
  };
260
 
web/src/services/chatService.ts CHANGED
@@ -12,6 +12,13 @@ const {
12
  completeConversation,
13
  listConversation,
14
  removeConversation,
 
 
 
 
 
 
 
15
  } = api;
16
 
17
  const methods = {
@@ -51,6 +58,34 @@ const methods = {
51
  url: removeConversation,
52
  method: 'post',
53
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  } as const;
55
 
56
  const chatService = registerServer<keyof typeof methods>(methods, request);
 
12
  completeConversation,
13
  listConversation,
14
  removeConversation,
15
+ createToken,
16
+ listToken,
17
+ removeToken,
18
+ getStats,
19
+ createExternalConversation,
20
+ getExternalConversation,
21
+ completeExternalConversation,
22
  } = api;
23
 
24
  const methods = {
 
58
  url: removeConversation,
59
  method: 'post',
60
  },
61
+ createToken: {
62
+ url: createToken,
63
+ method: 'post',
64
+ },
65
+ listToken: {
66
+ url: listToken,
67
+ method: 'get',
68
+ },
69
+ removeToken: {
70
+ url: removeToken,
71
+ method: 'post',
72
+ },
73
+ getStats: {
74
+ url: getStats,
75
+ method: 'get',
76
+ },
77
+ createExternalConversation: {
78
+ url: createExternalConversation,
79
+ method: 'post',
80
+ },
81
+ getExternalConversation: {
82
+ url: getExternalConversation,
83
+ method: 'get',
84
+ },
85
+ completeExternalConversation: {
86
+ url: completeExternalConversation,
87
+ method: 'post',
88
+ },
89
  } as const;
90
 
91
  const chatService = registerServer<keyof typeof methods>(methods, request);
web/src/utils/api.ts CHANGED
@@ -3,7 +3,7 @@ let api_host = `/v1`;
3
  export { api_host };
4
 
5
  export default {
6
- // 用户
7
  login: `${api_host}/user/login`,
8
  logout: `${api_host}/user/logout`,
9
  register: `${api_host}/user/register`,
@@ -12,21 +12,21 @@ export default {
12
  tenant_info: `${api_host}/user/tenant_info`,
13
  set_tenant_info: `${api_host}/user/set_tenant_info`,
14
 
15
- // 模型管理
16
  factories_list: `${api_host}/llm/factories`,
17
  llm_list: `${api_host}/llm/list`,
18
  my_llm: `${api_host}/llm/my_llms`,
19
  set_api_key: `${api_host}/llm/set_api_key`,
20
  add_llm: `${api_host}/llm/add_llm`,
21
 
22
- //知识库管理
23
  kb_list: `${api_host}/kb/list`,
24
  create_kb: `${api_host}/kb/create`,
25
  update_kb: `${api_host}/kb/update`,
26
  rm_kb: `${api_host}/kb/rm`,
27
  get_kb_detail: `${api_host}/kb/detail`,
28
 
29
- // chunk管理
30
  chunk_list: `${api_host}/chunk/list`,
31
  create_chunk: `${api_host}/chunk/create`,
32
  set_chunk: `${api_host}/chunk/set`,
@@ -35,7 +35,7 @@ export default {
35
  rm_chunk: `${api_host}/chunk/rm`,
36
  retrieval_test: `${api_host}/chunk/retrieval_test`,
37
 
38
- // 文件管理
39
  upload: `${api_host}/document/upload`,
40
  get_document_list: `${api_host}/document/list`,
41
  document_change_status: `${api_host}/document/change_status`,
@@ -48,14 +48,22 @@ export default {
48
  get_document_file: `${api_host}/document/get`,
49
  document_upload: `${api_host}/document/upload`,
50
 
 
51
  setDialog: `${api_host}/dialog/set`,
52
  getDialog: `${api_host}/dialog/get`,
53
  removeDialog: `${api_host}/dialog/rm`,
54
  listDialog: `${api_host}/dialog/list`,
55
-
56
  setConversation: `${api_host}/conversation/set`,
57
  getConversation: `${api_host}/conversation/get`,
58
  listConversation: `${api_host}/conversation/list`,
59
  removeConversation: `${api_host}/conversation/rm`,
60
  completeConversation: `${api_host}/conversation/completion`,
 
 
 
 
 
 
 
 
61
  };
 
3
  export { api_host };
4
 
5
  export default {
6
+ // user
7
  login: `${api_host}/user/login`,
8
  logout: `${api_host}/user/logout`,
9
  register: `${api_host}/user/register`,
 
12
  tenant_info: `${api_host}/user/tenant_info`,
13
  set_tenant_info: `${api_host}/user/set_tenant_info`,
14
 
15
+ // llm model
16
  factories_list: `${api_host}/llm/factories`,
17
  llm_list: `${api_host}/llm/list`,
18
  my_llm: `${api_host}/llm/my_llms`,
19
  set_api_key: `${api_host}/llm/set_api_key`,
20
  add_llm: `${api_host}/llm/add_llm`,
21
 
22
+ // knowledge base
23
  kb_list: `${api_host}/kb/list`,
24
  create_kb: `${api_host}/kb/create`,
25
  update_kb: `${api_host}/kb/update`,
26
  rm_kb: `${api_host}/kb/rm`,
27
  get_kb_detail: `${api_host}/kb/detail`,
28
 
29
+ // chunk
30
  chunk_list: `${api_host}/chunk/list`,
31
  create_chunk: `${api_host}/chunk/create`,
32
  set_chunk: `${api_host}/chunk/set`,
 
35
  rm_chunk: `${api_host}/chunk/rm`,
36
  retrieval_test: `${api_host}/chunk/retrieval_test`,
37
 
38
+ // document
39
  upload: `${api_host}/document/upload`,
40
  get_document_list: `${api_host}/document/list`,
41
  document_change_status: `${api_host}/document/change_status`,
 
48
  get_document_file: `${api_host}/document/get`,
49
  document_upload: `${api_host}/document/upload`,
50
 
51
+ // chat
52
  setDialog: `${api_host}/dialog/set`,
53
  getDialog: `${api_host}/dialog/get`,
54
  removeDialog: `${api_host}/dialog/rm`,
55
  listDialog: `${api_host}/dialog/list`,
 
56
  setConversation: `${api_host}/conversation/set`,
57
  getConversation: `${api_host}/conversation/get`,
58
  listConversation: `${api_host}/conversation/list`,
59
  removeConversation: `${api_host}/conversation/rm`,
60
  completeConversation: `${api_host}/conversation/completion`,
61
+ // chat for external
62
+ createToken: `${api_host}/api/new_token`,
63
+ listToken: `${api_host}/api/token_list`,
64
+ removeToken: `${api_host}/api/rm`,
65
+ getStats: `${api_host}/api/stats`,
66
+ createExternalConversation: `${api_host}/api/new_conversation`,
67
+ getExternalConversation: `${api_host}/api/conversation`,
68
+ completeExternalConversation: `${api_host}/api/completion`,
69
  };
web/src/utils/commonUtil.ts ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import isObject from 'lodash/isObject';
2
+ import snakeCase from 'lodash/snakeCase';
3
+
4
+ export const isFormData = (data: unknown): data is FormData => {
5
+ return data instanceof FormData;
6
+ };
7
+
8
+ export const convertTheKeysOfTheObjectToSnake = (data: unknown) => {
9
+ if (isObject(data) && !isFormData(data)) {
10
+ return Object.keys(data).reduce<Record<string, any>>((pre, cur) => {
11
+ const value = (data as Record<string, any>)[cur];
12
+ pre[isFormData(value) ? cur : snakeCase(cur)] = value;
13
+ return pre;
14
+ }, {});
15
+ }
16
+ return data;
17
+ };
web/src/utils/date.ts CHANGED
@@ -1,20 +1,20 @@
1
- import moment from 'moment';
2
 
3
  export function today() {
4
- return formatDate(moment());
5
  }
6
 
7
  export function lastDay() {
8
- return formatDate(moment().subtract(1, 'days'));
9
  }
10
 
11
  export function lastWeek() {
12
- return formatDate(moment().subtract(1, 'weeks'));
13
  }
14
 
15
  export function formatDate(date: any) {
16
  if (!date) {
17
  return '';
18
  }
19
- return moment(date).format('DD/MM/YYYY');
20
  }
 
1
+ import dayjs from 'dayjs';
2
 
3
  export function today() {
4
+ return formatDate(dayjs());
5
  }
6
 
7
  export function lastDay() {
8
+ return formatDate(dayjs().subtract(1, 'days'));
9
  }
10
 
11
  export function lastWeek() {
12
+ return formatDate(dayjs().subtract(1, 'weeks'));
13
  }
14
 
15
  export function formatDate(date: any) {
16
  if (!date) {
17
  return '';
18
  }
19
+ return dayjs(date).format('DD/MM/YYYY');
20
  }
web/src/utils/registerServer.ts CHANGED
@@ -8,16 +8,20 @@ const registerServer = <T extends string>(
8
  ) => {
9
  const server: Service<T> = {} as Service<T>;
10
  for (let key in opt) {
11
- server[key] = (params) => {
 
 
 
 
12
  if (opt[key].method === 'post' || opt[key].method === 'POST') {
13
- return request(opt[key].url, {
14
  method: opt[key].method,
15
  data: params,
16
  });
17
  }
18
 
19
  if (opt[key].method === 'get' || opt[key].method === 'GET') {
20
- return request.get(opt[key].url, {
21
  params,
22
  });
23
  }
 
8
  ) => {
9
  const server: Service<T> = {} as Service<T>;
10
  for (let key in opt) {
11
+ server[key] = (params: any, urlAppendix?: string) => {
12
+ let url = opt[key].url;
13
+ if (urlAppendix) {
14
+ url = url + '/' + urlAppendix;
15
+ }
16
  if (opt[key].method === 'post' || opt[key].method === 'POST') {
17
+ return request(url, {
18
  method: opt[key].method,
19
  data: params,
20
  });
21
  }
22
 
23
  if (opt[key].method === 'get' || opt[key].method === 'GET') {
24
+ return request.get(url, {
25
  params,
26
  });
27
  }
web/src/utils/request.ts CHANGED
@@ -4,6 +4,7 @@ import authorizationUtil from '@/utils/authorizationUtil';
4
  import { message, notification } from 'antd';
5
  import { history } from 'umi';
6
  import { RequestMethod, extend } from 'umi-request';
 
7
 
8
  const ABORT_REQUEST_ERR_MESSAGE = 'The user aborted a request.'; // 手动中断请求。errorHandler 抛出的error message
9
 
@@ -87,10 +88,15 @@ const request: RequestMethod = extend({
87
 
88
  request.interceptors.request.use((url: string, options: any) => {
89
  const authorization = authorizationUtil.getAuthorization();
 
 
 
90
  return {
91
  url,
92
  options: {
93
  ...options,
 
 
94
  headers: {
95
  ...(options.skipToken ? undefined : { [Authorization]: authorization }),
96
  ...options.headers,
 
4
  import { message, notification } from 'antd';
5
  import { history } from 'umi';
6
  import { RequestMethod, extend } from 'umi-request';
7
+ import { convertTheKeysOfTheObjectToSnake } from './commonUtil';
8
 
9
  const ABORT_REQUEST_ERR_MESSAGE = 'The user aborted a request.'; // 手动中断请求。errorHandler 抛出的error message
10
 
 
88
 
89
  request.interceptors.request.use((url: string, options: any) => {
90
  const authorization = authorizationUtil.getAuthorization();
91
+ const data = convertTheKeysOfTheObjectToSnake(options.data);
92
+ const params = convertTheKeysOfTheObjectToSnake(options.params);
93
+
94
  return {
95
  url,
96
  options: {
97
  ...options,
98
+ // data,
99
+ // params,
100
  headers: {
101
  ...(options.skipToken ? undefined : { [Authorization]: authorization }),
102
  ...options.headers,