Ver código fonte

add front end code (#27)

tags/v0.1.0
KevinHuSh 1 ano atrás
pai
commit
6b8fc2ce1f
89 arquivos alterados com 21430 adições e 0 exclusões
  1. 0
    0
      web/.env
  2. 9
    0
      web/.gitignore
  3. 2
    0
      web/.npmrc
  4. 28
    0
      web/.umirc.ts
  5. 16385
    0
      web/package-lock.json
  6. 35
    0
      web/package.json
  7. 27
    0
      web/reducer.js
  8. 89
    0
      web/routes.js
  9. 9
    0
      web/src/.umi/core/EmptyRoute.tsx
  10. 17
    0
      web/src/.umi/core/defineApp.ts
  11. 10
    0
      web/src/.umi/core/helmet.ts
  12. 4
    0
      web/src/.umi/core/helmetContext.ts
  13. 66
    0
      web/src/.umi/core/history.ts
  14. 132
    0
      web/src/.umi/core/historyIntelli.ts
  15. 45
    0
      web/src/.umi/core/plugin.ts
  16. 292
    0
      web/src/.umi/core/pluginConfig.ts
  17. 7
    0
      web/src/.umi/core/pluginConfigJoi.d.ts
  18. 220
    0
      web/src/.umi/core/polyfill.ts
  19. 22
    0
      web/src/.umi/core/route.tsx
  20. 37
    0
      web/src/.umi/core/terminal.ts
  21. 22
    0
      web/src/.umi/exports.ts
  22. 60
    0
      web/src/.umi/plugin-dva/dva.tsx
  23. 5
    0
      web/src/.umi/plugin-dva/index.ts
  24. 20
    0
      web/src/.umi/plugin-dva/models.ts
  25. 9
    0
      web/src/.umi/plugin-dva/runtime.tsx
  26. 19
    0
      web/src/.umi/plugin-dva/runtimeConfig.d.ts
  27. 58
    0
      web/src/.umi/plugin-dva/types.d.ts
  28. 8
    0
      web/src/.umi/plugin-icons/icons.tsx
  29. 27
    0
      web/src/.umi/plugin-icons/index.css
  30. 243
    0
      web/src/.umi/plugin-icons/index.tsx
  31. 87
    0
      web/src/.umi/testBrowser.tsx
  32. 43
    0
      web/src/.umi/tsconfig.json
  33. 136
    0
      web/src/.umi/typings.d.ts
  34. 76
    0
      web/src/.umi/umi.ts
  35. BIN
      web/src/assets/logo.png
  36. BIN
      web/src/assets/yay.jpg
  37. 10
    0
      web/src/icons/github.svg
  38. 13
    0
      web/src/icons/google.svg
  39. 38
    0
      web/src/layouts/components/user/index.tsx
  40. 33
    0
      web/src/layouts/index.less
  41. 74
    0
      web/src/layouts/index.tsx
  42. 24
    0
      web/src/locales/config.ts
  43. 20
    0
      web/src/locales/en.json
  44. 20
    0
      web/src/locales/zh.json
  45. 17
    0
      web/src/pages/404.jsx
  46. 72
    0
      web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx
  47. 24
    0
      web/src/pages/add-knowledge/components/knowledge-file/index.less
  48. 218
    0
      web/src/pages/add-knowledge/components/knowledge-file/index.tsx
  49. 127
    0
      web/src/pages/add-knowledge/components/knowledge-file/model.ts
  50. 84
    0
      web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx
  51. 30
    0
      web/src/pages/add-knowledge/components/knowledge-file/upload.tsx
  52. 3
    0
      web/src/pages/add-knowledge/components/knowledge-search/index.tsx
  53. 24
    0
      web/src/pages/add-knowledge/components/knowledge-setting/index.less
  54. 192
    0
      web/src/pages/add-knowledge/components/knowledge-setting/index.tsx
  55. 53
    0
      web/src/pages/add-knowledge/components/knowledge-setting/model.ts
  56. 19
    0
      web/src/pages/add-knowledge/index.less
  57. 106
    0
      web/src/pages/add-knowledge/index.tsx
  58. 34
    0
      web/src/pages/add-knowledge/model.ts
  59. 19
    0
      web/src/pages/chat/index.tsx
  60. 52
    0
      web/src/pages/chat/model.ts
  61. 51
    0
      web/src/pages/file/index.tsx
  62. 41
    0
      web/src/pages/knowledge/index.less
  63. 109
    0
      web/src/pages/knowledge/index.tsx
  64. 61
    0
      web/src/pages/knowledge/model.ts
  65. 63
    0
      web/src/pages/login/index.less
  66. 157
    0
      web/src/pages/login/index.tsx
  67. 61
    0
      web/src/pages/login/model.ts
  68. 92
    0
      web/src/pages/setting/CPwModal.tsx
  69. 197
    0
      web/src/pages/setting/List.tsx
  70. 84
    0
      web/src/pages/setting/SAKModal.tsx
  71. 153
    0
      web/src/pages/setting/SSModal.tsx
  72. 58
    0
      web/src/pages/setting/TntModal.tsx
  73. 49
    0
      web/src/pages/setting/index.less
  74. 90
    0
      web/src/pages/setting/index.tsx
  75. 181
    0
      web/src/pages/setting/model.ts
  76. 70
    0
      web/src/services/kbService.ts
  77. 21
    0
      web/src/services/uploadService.ts
  78. 57
    0
      web/src/services/userService.ts
  79. 11
    0
      web/src/theme/theme.ts
  80. 9
    0
      web/src/theme/vars.less
  81. 42
    0
      web/src/utils/api.ts
  82. 20
    0
      web/src/utils/date.ts
  83. 14
    0
      web/src/utils/hooks.ts
  84. 26
    0
      web/src/utils/index.ts
  85. 22
    0
      web/src/utils/registerServer.ts
  86. 116
    0
      web/src/utils/request.ts
  87. 12
    0
      web/src/wrappers/auth.tsx
  88. 6
    0
      web/tsconfig.json
  89. 2
    0
      web/typings.d.ts

+ 0
- 0
web/.env Ver arquivo


+ 9
- 0
web/.gitignore Ver arquivo

@@ -0,0 +1,9 @@
/node_modules
/.env.local
/.umirc.local.ts
/config/config.local.ts
/src/.umi
/src/.umi-production
/src/.umi-test
/dist
.swc

+ 2
- 0
web/.npmrc Ver arquivo

@@ -0,0 +1,2 @@
registry=https://registry.npmmirror.com/

+ 28
- 0
web/.umirc.ts Ver arquivo

@@ -0,0 +1,28 @@
import { defineConfig } from "umi";
import routes from './routes'
export default defineConfig({
outputPath: 'dist',
// alias: { '@': './src' },
routes,
npmClient: 'npm',
base: '/',
publicPath: '/client/dist/',
icons: {
},
hash: true,
history: {
type: 'hash',
},
plugins: ['@umijs/plugins/dist/dva'],
dva: {},
proxy: {
'/v1': {
'target': 'http://54.80.112.79:9380/',
'changeOrigin': true,
'pathRewrite': { '^/v1': '/v1' },
},
},
});

+ 16385
- 0
web/package-lock.json
Diferenças do arquivo suprimidas por serem muito extensas
Ver arquivo


+ 35
- 0
web/package.json Ver arquivo

@@ -0,0 +1,35 @@
{
"private": true,
"author": "zhaofengchao <13723060510@163.com>",
"scripts": {
"dev": "umi dev",
"build": "umi build",
"postinstall": "umi setup",
"setup": "umi setup",
"start": "npm run dev"
},
"dependencies": {
"@ant-design/icons": "^5.2.6",
"@ant-design/pro-components": "^2.6.46",
"@ant-design/pro-layout": "^7.17.16",
"antd": "^5.12.7",
"axios": "^1.6.3",
"classnames": "^2.5.1",
"i18next": "^23.7.16",
"js-base64": "^3.7.5",
"jsencrypt": "^3.3.2",
"lodash": "^4.17.21",
"react-i18next": "^14.0.0",
"react-infinite-scroll-component": "^6.1.0",
"umi": "^4.0.90",
"umi-request": "^1.4.0"
},
"devDependencies": {
"@types/lodash": "^4.14.202",
"@types/react": "^18.0.33",
"@types/react-dom": "^18.0.11",
"@umijs/plugins": "^4.1.0",
"typescript": "^5.0.3",
"umi-plugin-icons": "^0.1.1"
}
}

+ 27
- 0
web/reducer.js Ver arquivo

@@ -0,0 +1,27 @@
import React, { useReducer } from 'react'
const CHANGE_LOCALE = 'CHANGE_LOCALE'
const mainContext = React.createContext()
const reducer = (state, action) => {
switch (action.type) {
case CHANGE_LOCALE:
return { ...state, locale: action.locale || 'zh' }
default:
return state
}
}
const ContextProvider = (props) => {
const [state, dispatch] = useReducer(reducer, {
locale: 'zh'
})
return (
<mainContext.Provider value={{ state, dispatch }}>
{props.children}
</mainContext.Provider>
)
}
export { reducer, mainContext, ContextProvider }

+ 89
- 0
web/routes.js Ver arquivo

@@ -0,0 +1,89 @@
const routes = [
{
path: '/login',
component: '@/pages/login',
layout: false
},
{
path: '/',
component: '@/layouts', // 默认页面
redirect: '/knowledge',
// wrappers: [
// '@/wrappers/auth',
// ]
},
{
id: 2,
name: '知识库',
icon: 'home',
auth: [3, 4, 100],
path: '/knowledge',
component: '@/pages/knowledge',
pathname: 'knowledge'
},
{
id: 2,
name: '知识库',
icon: 'home',
auth: [3, 4, 100],
path: '/knowledge/add/*',
component: '@/pages/add-knowledge',
pathname: 'knowledge',
// routes: [{
// id: 3,
// name: '设置',
// icon: 'home',
// auth: [3, 4, 100],
// path: '/knowledge/add/setting',
// component: '@/pages/setting',
// pathname: "setting"
// }, {
// id: 1,
// name: '文件',
// icon: 'file',
// auth: [3, 4, 100],
// path: '/knowledge/add/file',
// component: '@/pages/file',
// pathname: 'file'
// },]
},
{
id: 3,
name: '聊天',
icon: 'home',
auth: [3, 4, 100],
path: '/chat',
component: '@/pages/chat',
pathname: "chat"
},
{
id: 3,
name: '设置',
icon: 'home',
auth: [3, 4, 100],
path: '/setting',
component: '@/pages/setting',
pathname: "setting"
},
{
id: 1,
name: '文件',
icon: 'file',
auth: [3, 4, 100],
path: '/file',
component: '@/pages/file',
pathname: 'file'
},
{
path: '/*',
component: '@/pages/404',
layout: false
}
];
module.exports = routes;

+ 9
- 0
web/src/.umi/core/EmptyRoute.tsx Ver arquivo

@@ -0,0 +1,9 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import { Outlet, useOutletContext } from 'umi';
export default function EmptyRoute() {
const context = useOutletContext();
return <Outlet context={context} />;
}

+ 17
- 0
web/src/.umi/core/defineApp.ts Ver arquivo

@@ -0,0 +1,17 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import type { IRuntimeConfig as Plugin0 } from 'C:/Users/zfc/Desktop/docgpt/client/src/.umi/plugin-dva/runtimeConfig.d'
interface IDefaultRuntimeConfig {
onRouteChange?: (props: { routes: any, clientRoutes: any, location: any, action: any, isFirst: boolean }) => void;
patchRoutes?: (props: { routes: any }) => void;
patchClientRoutes?: (props: { routes: any }) => void;
render?: (oldRender: () => void) => void;
rootContainer?: (lastRootContainer: JSX.Element, args?: any) => void;
[key: string]: any;
}
export type RuntimeConfig = IDefaultRuntimeConfig & Plugin0

export function defineApp(config: RuntimeConfig): RuntimeConfig {
return config;
}

+ 10
- 0
web/src/.umi/core/helmet.ts Ver arquivo

@@ -0,0 +1,10 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import { HelmetProvider } from 'C:/Users/zfc/Desktop/docgpt/client/node_modules/@umijs/renderer-react';
import { context } from './helmetContext';

export const innerProvider = (container) => {
return React.createElement(HelmetProvider, { context }, container);
}

+ 4
- 0
web/src/.umi/core/helmetContext.ts Ver arquivo

@@ -0,0 +1,4 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
export const context = {};

+ 66
- 0
web/src/.umi/core/history.ts Ver arquivo

@@ -0,0 +1,66 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import { createHashHistory, createMemoryHistory, createBrowserHistory } from 'C:/Users/zfc/Desktop/docgpt/client/node_modules/@umijs/renderer-react';
import type { UmiHistory } from './historyIntelli';

let history: UmiHistory;
let basename: string = '/';
export function createHistory(opts: any) {
let h;
if (opts.type === 'hash') {
h = createHashHistory();
} else if (opts.type === 'memory') {
h = createMemoryHistory(opts);
} else {
h = createBrowserHistory();
}
if (opts.basename) {
basename = opts.basename;
}


history = {
...h,
push(to, state) {
h.push(patchTo(to, h), state);
},
replace(to, state) {
h.replace(patchTo(to, h), state);
},
get location() {
return h.location;
},
get action() {
return h.action;
}
}

return h;
}

// Patch `to` to support basename
// Refs:
// https://github.com/remix-run/history/blob/3e9dab4/packages/history/index.ts#L484
// https://github.com/remix-run/history/blob/dev/docs/api-reference.md#to
function patchTo(to: any, h: History) {
if (typeof to === 'string') {
return `${stripLastSlash(basename)}${to}`;
} else if (typeof to === 'object') {

const currentPathname = h.location.pathname;

return {
...to,
pathname: to.pathname? `${stripLastSlash(basename)}${to.pathname}` : currentPathname,
};
} else {
throw new Error(`Unexpected to: ${to}`);
}
}

function stripLastSlash(path) {
return path.slice(-1) === '/' ? path.slice(0, -1) : path;
}

export { history };

+ 132
- 0
web/src/.umi/core/historyIntelli.ts Ver arquivo

@@ -0,0 +1,132 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import { getRoutes } from './route'
import type { History } from 'C:/Users/zfc/Desktop/docgpt/client/node_modules/@umijs/renderer-react'

type Routes = Awaited<ReturnType<typeof getRoutes>>['routes']
type AllRoute = Routes[keyof Routes]
type IsRoot<T extends any> = 'parentId' extends keyof T ? false : true

// show `/` in not `layout / wrapper` only
type GetAllRouteWithoutLayout<Item extends AllRoute> = Item extends any
? 'isWrapper' extends keyof Item
? never
: 'isLayout' extends keyof Item
? never
: Item
: never
type AllRouteWithoutLayout = GetAllRouteWithoutLayout<AllRoute>
type IndexRoutePathname = '/' extends AllRouteWithoutLayout['path']
? '/'
: never

type GetChildrens<T extends any> = T extends any
? IsRoot<T> extends true
? never
: T
: never
type Childrens = GetChildrens<AllRoute>
type Root = Exclude<AllRoute, Childrens>
type AllIds = AllRoute['id']

type GetChildrensByParentId<
Id extends AllIds,
Item = AllRoute
> = Item extends any
? 'parentId' extends keyof Item
? Item['parentId'] extends Id
? Item
: never
: never
: never

type RouteObject<
Id extends AllIds,
Item = GetChildrensByParentId<Id>
> = IsNever<Item> extends true
? ''
: Item extends AllRoute
? {
[Key in Item['path'] as TrimSlash<Key>]: UnionMerge<
RouteObject<Item['id']>
>
}
: never

type GetRootRouteObject<Item extends Root> = Item extends Root
? {
[K in Item['path'] as TrimSlash<K>]: UnionMerge<RouteObject<Item['id']>>
}
: never
type MergedResult = UnionMerge<GetRootRouteObject<Root>>

// --- patch history types ---

type HistoryTo = Parameters<History['push']>['0']
type HistoryPath = Exclude<HistoryTo, string>

type UmiPathname = Path<MergedResult> | (string & {})
interface UmiPath extends HistoryPath {
pathname: UmiPathname
}
type UmiTo = UmiPathname | UmiPath

type UmiPush = (to: UmiTo, state?: any) => void
type UmiReplace = (to: UmiTo, state?: any) => void


export interface UmiHistory extends History {
push: UmiPush
replace: UmiReplace
}

// --- type utils ---
type TrimLeftSlash<T extends string> = T extends `/${infer R}`
? TrimLeftSlash<R>
: T
type TrimRightSlash<T extends string> = T extends `${infer R}/`
? TrimRightSlash<R>
: T
type TrimSlash<T extends string> = TrimLeftSlash<TrimRightSlash<T>>

type IsNever<T> = [T] extends [never] ? true : false
type IsEqual<A, B> = (<G>() => G extends A ? 1 : 2) extends <G>() => G extends B
? 1
: 2
? true
: false

type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
k: infer I
) => void
? I
: never
type UnionMerge<U> = UnionToIntersection<U> extends infer O
? { [K in keyof O]: O[K] }
: never

type ExcludeEmptyKey<T> = IsEqual<T, ''> extends true ? never : T

type PathConcat<
TKey extends string,
TValue,
N = TrimSlash<TKey>
> = TValue extends string
? ExcludeEmptyKey<N>
:
| ExcludeEmptyKey<N>
| `${N & string}${IsNever<ExcludeEmptyKey<N>> extends true
? ''
: '/'}${UnionPath<TValue>}`

type UnionPath<T> = {
[K in keyof T]-?: PathConcat<K & string, T[K]>
}[keyof T]

type MakeSureLeftSlash<T> = T extends any
? `/${TrimRightSlash<T & string>}`
: never

// exclude `/*`, because it always at the top of the IDE tip list
type Path<T, K = UnionPath<T>> = Exclude<MakeSureLeftSlash<K>, '/*'> | IndexRoutePathname

+ 45
- 0
web/src/.umi/core/plugin.ts Ver arquivo

@@ -0,0 +1,45 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import * as Plugin_0 from '@@/core/helmet.ts';
import * as Plugin_1 from 'C:/Users/zfc/Desktop/docgpt/client/src/.umi/plugin-dva/runtime.tsx';
import { PluginManager } from 'umi';

function __defaultExport (obj) {
if (obj.default) {
return typeof obj.default === 'function' ? obj.default() : obj.default
}
return obj;
}
export function getPlugins() {
return [
{
apply: Plugin_0,
path: process.env.NODE_ENV === 'production' ? void 0 : '@@/core/helmet.ts',
},
{
apply: Plugin_1,
path: process.env.NODE_ENV === 'production' ? void 0 : 'C:/Users/zfc/Desktop/docgpt/client/src/.umi/plugin-dva/runtime.tsx',
},
];
}

export function getValidKeys() {
return ['patchRoutes','patchClientRoutes','modifyContextOpts','modifyClientRenderOpts','rootContainer','innerProvider','i18nProvider','accessProvider','dataflowProvider','outerProvider','render','onRouteChange','dva',];
}

let pluginManager = null;

export function createPluginManager() {
pluginManager = PluginManager.create({
plugins: getPlugins(),
validKeys: getValidKeys(),
});


return pluginManager;
}

export function getPluginManager() {
return pluginManager;
}

+ 292
- 0
web/src/.umi/core/pluginConfig.ts Ver arquivo

@@ -0,0 +1,292 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import { IConfigFromPluginsJoi } from "./pluginConfigJoi.d";

interface IConfigTypes {
codeSplitting: {
jsStrategy: "bigVendors" | "depPerChunk" | "granularChunks";
jsStrategyOptions?: ({

} | undefined);
cssStrategy?: ("mergeAll" | undefined);
cssStrategyOptions?: ({

} | undefined);
};
title: string;
styles: Array<string | {
src?: (string | undefined);
} | {
content?: (string | undefined);
} | { [x: string]: any }>;
scripts: Array<string | {
src?: (string | undefined);
} | {
content?: (string | undefined);
} | { [x: string]: any }>;
routes: Array<{
component?: (string | undefined);
layout?: (false | undefined);
path?: (string | undefined);
redirect?: (string | undefined);
routes?: IConfigTypes['routes'];
wrappers?: (Array<string> | undefined);
} | { [x: string]: any }>;
routeLoader: {
moduleType: "esm" | "cjs";
};
reactRouter5Compat: boolean | {

};
presets: Array<string>;
plugins: Array<string>;
npmClient: "pnpm" | "tnpm" | "cnpm" | "yarn" | "npm";
mountElementId: string;
metas: Array<{
charset?: (string | undefined);
content?: (string | undefined);
"http-equiv"?: (string | undefined);
name?: (string | undefined);
} | { [x: string]: any }>;
links: Array<{
crossorigin?: (string | undefined);
href?: (string | undefined);
hreflang?: (string | undefined);
media?: (string | undefined);
referrerpolicy?: (string | undefined);
rel?: (string | undefined);
sizes?: (any | undefined);
title?: (any | undefined);
type?: (any | undefined);
} | { [x: string]: any }>;
historyWithQuery: {

};
history: {
type: "browser" | "hash" | "memory";
};
headScripts: Array<string | {
src?: (string | undefined);
} | {
content?: (string | undefined);
} | { [x: string]: any }>;
esbuildMinifyIIFE: boolean;
conventionRoutes: {
base?: (string | undefined);
exclude?: (Array<any> | undefined);
};
conventionLayout: boolean;
base: string;
analyze: {

};
writeToDisk: boolean;
theme: { [x: string]: any };
targets: { [x: string]: any };
svgr: { [x: string]: any };
svgo: { [x: string]: any } | boolean;
stylusLoader: { [x: string]: any };
styleLoader: { [x: string]: any };
srcTranspilerOptions: {
esbuild?: ({ [x: string]: any } | undefined);
swc?: ({ [x: string]: any } | undefined);
};
srcTranspiler: "babel" | "esbuild" | "swc";
sassLoader: { [x: string]: any };
runtimePublicPath: {

};
purgeCSS: { [x: string]: any };
publicPath: string;
proxy: { [x: string]: any } | Array<any>;
postcssLoader: { [x: string]: any };
outputPath: string;
normalCSSLoaderModules: { [x: string]: any };
mfsu: {
cacheDirectory?: (string | undefined);
chainWebpack?: (((...args: any[]) => unknown) | undefined);
esbuild?: (boolean | undefined);
exclude?: (Array<string | any> | undefined);
include?: (Array<string> | undefined);
mfName?: (string | undefined);
remoteAliases?: (Array<string> | undefined);
remoteName?: (string | undefined);
runtimePublicPath?: (boolean | undefined);
shared?: ({ [x: string]: any } | undefined);
strategy?: ("eager" | "normal" | undefined);
} | boolean;
mdx: {
loader?: (string | undefined);
loaderOptions?: ({ [x: string]: any } | undefined);
};
manifest: {
basePath?: (string | undefined);
fileName?: (string | undefined);
};
lessLoader: { [x: string]: any };
jsMinifierOptions: { [x: string]: any };
jsMinifier: "esbuild" | "swc" | "terser" | "uglifyJs" | "none";
inlineLimit: number;
ignoreMomentLocale: boolean;
https: {
cert?: (string | undefined);
hosts?: (Array<string> | undefined);
http2?: (boolean | undefined);
key?: (string | undefined);
};
hash: boolean;
forkTSChecker: { [x: string]: any };
fastRefresh: boolean;
extraPostCSSPlugins: Array<any>;
extraBabelPresets: Array<string | Array<any>>;
extraBabelPlugins: Array<string | Array<any>>;
extraBabelIncludes: Array<string | any>;
externals: { [x: string]: any } | string | ((...args: any[]) => unknown);
esm: {

};
devtool: "cheap-source-map" | "cheap-module-source-map" | "eval" | "eval-source-map" | "eval-cheap-source-map" | "eval-cheap-module-source-map" | "eval-nosources-cheap-source-map" | "eval-nosources-cheap-module-source-map" | "eval-nosources-source-map" | "source-map" | "hidden-source-map" | "hidden-nosources-cheap-source-map" | "hidden-nosources-cheap-module-source-map" | "hidden-nosources-source-map" | "hidden-cheap-source-map" | "hidden-cheap-module-source-map" | "inline-source-map" | "inline-cheap-source-map" | "inline-cheap-module-source-map" | "inline-nosources-cheap-source-map" | "inline-nosources-cheap-module-source-map" | "inline-nosources-source-map" | "nosources-source-map" | "nosources-cheap-source-map" | "nosources-cheap-module-source-map" | boolean;
depTranspiler: "babel" | "esbuild" | "swc" | "none";
define: { [x: string]: any };
deadCode: {
context?: (string | undefined);
detectUnusedExport?: (boolean | undefined);
detectUnusedFiles?: (boolean | undefined);
exclude?: (Array<string> | undefined);
failOnHint?: (boolean | undefined);
patterns?: (Array<string> | undefined);
};
cssPublicPath: string;
cssMinifierOptions: { [x: string]: any };
cssMinifier: "cssnano" | "esbuild" | "parcelCSS" | "none";
cssLoaderModules: { [x: string]: any };
cssLoader: { [x: string]: any };
copy: Array<{
from: string;
to: string;
} | string>;
checkDepCssModules?: boolean;
cacheDirectoryPath: string;
babelLoaderCustomize: string;
autoprefixer: { [x: string]: any };
autoCSSModules: boolean;
alias: { [x: string]: any };
crossorigin: boolean | {
includes?: (Array<any> | undefined);
};
esmi: {
cdnOrigin: string;
shimUrl?: (string | undefined);
};
exportStatic: {
extraRoutePaths?: (((...args: any[]) => unknown) | Array<string> | undefined);
ignorePreRenderError?: (boolean | undefined);
};
favicons: Array<string>;
helmet: boolean;
icons: {
autoInstall?: ({

} | undefined);
defaultComponentConfig?: ({

} | undefined);
alias?: ({

} | undefined);
include?: (Array<string> | undefined);
};
mock: {
exclude?: (Array<string> | undefined);
include?: (Array<string> | undefined);
};
mpa: {
template?: (string | undefined);
layout?: (string | undefined);
getConfigFromEntryFile?: (boolean | undefined);
entry?: ({

} | undefined);
};
phantomDependency: {
exclude?: (Array<string> | undefined);
};
polyfill: {
imports?: (Array<string> | undefined);
};
routePrefetch: {

};
terminal: {

};
tmpFiles: boolean;
clientLoader: {

};
routeProps: {

};
ssr: {
serverBuildPath?: (string | undefined);
platform?: (string | undefined);
builder?: ("esbuild" | "webpack" | undefined);
};
lowImport: {
libs?: (Array<any> | undefined);
css?: (string | undefined);
};
vite: {

};
apiRoute: {
platform?: (string | undefined);
};
monorepoRedirect: boolean | {
srcDir?: (Array<string> | undefined);
exclude?: (Array<any> | undefined);
peerDeps?: (boolean | undefined);
};
test: {

};
clickToComponent: {
/** 默认情况下,点击将默认编辑器为vscode, 你可以设置编辑器 vscode 或者 vscode-insiders */
editor?: (string | undefined);
};
legacy: {
buildOnly?: (boolean | undefined);
nodeModulesTransform?: (boolean | undefined);
checkOutput?: (boolean | undefined);
};
/** 设置 babel class-properties 启用 loose
@doc https://umijs.org/docs/api/config#classpropertiesloose */
classPropertiesLoose: boolean | {

};
ui: {

};
hmrGuardian: boolean;
verifyCommit: {
scope?: (Array<string> | undefined);
allowEmoji?: (boolean | undefined);
};
run: {
globals?: (Array<string> | undefined);
};
dva: {
extraModels?: (Array<string> | undefined);
immer?: ({ [x: string]: any } | undefined);
skipModelValidate?: (boolean | undefined);
};
};

type PrettifyWithCloseable<T> = {
[K in keyof T]: T[K] | false;
} & {};

export type IConfigFromPlugins = PrettifyWithCloseable<
IConfigFromPluginsJoi & Partial<IConfigTypes>
>;

+ 7
- 0
web/src/.umi/core/pluginConfigJoi.d.ts Ver arquivo

@@ -0,0 +1,7 @@
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
// Created by Umi Plugin

export interface IConfigFromPluginsJoi {

}

+ 220
- 0
web/src/.umi/core/polyfill.ts Ver arquivo

@@ -0,0 +1,220 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.error.cause.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.aggregate-error.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.aggregate-error.cause.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.array.at.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.array.find-last.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.array.find-last-index.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.array.push.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.array.reduce.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.array.reduce-right.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.array.to-reversed.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.array.to-sorted.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.array.to-spliced.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.array.with.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.map.group-by.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.object.group-by.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.object.has-own.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.promise.any.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.promise.with-resolvers.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.reflect.to-string-tag.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.regexp.flags.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.string.at-alternative.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.string.is-well-formed.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.string.replace-all.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.string.to-well-formed.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.typed-array.at.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.typed-array.find-last.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.typed-array.find-last-index.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.typed-array.set.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.typed-array.to-reversed.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.typed-array.to-sorted.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/es.typed-array.with.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.suppressed-error.constructor.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.array.from-async.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.array.filter-out.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.array.filter-reject.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.array.group.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.array.group-by.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.array.group-by-to-map.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.array.group-to-map.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.array.is-template-object.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.array.last-index.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.array.last-item.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.array.unique-by.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.array-buffer.detached.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.array-buffer.transfer.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.array-buffer.transfer-to-fixed-length.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-disposable-stack.constructor.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.constructor.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.as-indexed-pairs.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.async-dispose.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.drop.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.every.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.filter.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.find.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.flat-map.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.for-each.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.from.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.indexed.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.map.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.reduce.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.some.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.take.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.async-iterator.to-array.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.bigint.range.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.composite-key.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.composite-symbol.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.data-view.get-float16.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.data-view.get-uint8-clamped.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.data-view.set-float16.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.data-view.set-uint8-clamped.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.disposable-stack.constructor.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.function.demethodize.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.function.is-callable.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.function.is-constructor.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.function.metadata.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.function.un-this.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.constructor.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.as-indexed-pairs.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.dispose.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.drop.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.every.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.filter.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.find.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.flat-map.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.for-each.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.from.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.indexed.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.map.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.range.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.reduce.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.some.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.take.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.to-array.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.iterator.to-async.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.json.is-raw-json.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.json.parse.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.json.raw-json.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.delete-all.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.emplace.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.every.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.filter.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.find.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.find-key.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.from.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.includes.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.key-by.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.key-of.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.map-keys.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.map-values.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.merge.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.of.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.reduce.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.some.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.update.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.update-or-insert.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.map.upsert.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.math.clamp.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.math.deg-per-rad.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.math.degrees.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.math.fscale.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.math.f16round.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.math.iaddh.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.math.imulh.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.math.isubh.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.math.rad-per-deg.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.math.radians.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.math.scale.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.math.seeded-prng.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.math.signbit.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.math.umulh.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.number.from-string.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.number.range.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.object.iterate-entries.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.object.iterate-keys.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.object.iterate-values.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.observable.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.promise.try.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.reflect.define-metadata.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.reflect.delete-metadata.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.reflect.get-metadata.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.reflect.get-metadata-keys.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.reflect.get-own-metadata.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.reflect.get-own-metadata-keys.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.reflect.has-metadata.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.reflect.has-own-metadata.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.reflect.metadata.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.regexp.escape.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.add-all.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.delete-all.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.difference.v2.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.difference.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.every.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.filter.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.find.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.from.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.intersection.v2.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.intersection.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.is-disjoint-from.v2.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.is-disjoint-from.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.is-subset-of.v2.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.is-subset-of.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.is-superset-of.v2.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.is-superset-of.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.join.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.map.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.of.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.reduce.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.some.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.symmetric-difference.v2.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.symmetric-difference.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.union.v2.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.set.union.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.string.at.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.string.cooked.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.string.code-points.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.string.dedent.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.symbol.async-dispose.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.symbol.dispose.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.symbol.is-registered-symbol.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.symbol.is-registered.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.symbol.is-well-known-symbol.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.symbol.is-well-known.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.symbol.matcher.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.symbol.metadata.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.symbol.metadata-key.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.symbol.observable.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.symbol.pattern-match.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.symbol.replace-all.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.typed-array.from-async.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.typed-array.filter-out.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.typed-array.filter-reject.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.typed-array.group-by.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.typed-array.to-spliced.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.typed-array.unique-by.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.uint8-array.from-base64.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.uint8-array.from-hex.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.uint8-array.to-base64.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.uint8-array.to-hex.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.weak-map.delete-all.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.weak-map.from.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.weak-map.of.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.weak-map.emplace.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.weak-map.upsert.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.weak-set.add-all.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.weak-set.delete-all.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.weak-set.from.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/esnext.weak-set.of.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/web.dom-exception.stack.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/web.immediate.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/web.self.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/web.structured-clone.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/web.url.can-parse.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/web.url-search-params.delete.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/web.url-search-params.has.js";
import "C:/Users/zfc/Desktop/docgpt/client/node_modules/core-js/modules/web.url-search-params.size.js";
import 'C:/Users/zfc/Desktop/docgpt/client/node_modules/@umijs/preset-umi/node_modules/regenerator-runtime/runtime.js';
export {};

+ 22
- 0
web/src/.umi/core/route.tsx Ver arquivo

@@ -0,0 +1,22 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';

export async function getRoutes() {
const routes = {"1":{"path":"/login","layout":false,"id":"1"},"2":{"path":"/","redirect":"/knowledge","parentId":"@@/global-layout","id":"2"},"3":{"id":"3","name":"知识库","icon":"home","auth":[3,4,100],"path":"/knowledge","pathname":"knowledge","parentId":"@@/global-layout"},"4":{"id":"4","name":"知识库","icon":"home","auth":[3,4,100],"path":"/knowledge/add/*","pathname":"knowledge","parentId":"@@/global-layout"},"5":{"id":"5","name":"聊天","icon":"home","auth":[3,4,100],"path":"/chat","pathname":"chat","parentId":"@@/global-layout"},"6":{"id":"6","name":"设置","icon":"home","auth":[3,4,100],"path":"/setting","pathname":"setting","parentId":"@@/global-layout"},"7":{"id":"7","name":"文件","icon":"file","auth":[3,4,100],"path":"/file","pathname":"file","parentId":"@@/global-layout"},"8":{"path":"/*","layout":false,"id":"8"},"@@/global-layout":{"id":"@@/global-layout","path":"/","isLayout":true}} as const;
return {
routes,
routeComponents: {
'1': React.lazy(() => import(/* webpackChunkName: "p__login__index" */'@/pages/login/index.tsx')),
'2': React.lazy(() => import(/* webpackChunkName: "layouts__index" */'@/layouts/index.tsx')),
'3': React.lazy(() => import(/* webpackChunkName: "p__knowledge__index" */'@/pages/knowledge/index.tsx')),
'4': React.lazy(() => import(/* webpackChunkName: "p__add-knowledge__index" */'@/pages/add-knowledge/index.tsx')),
'5': React.lazy(() => import(/* webpackChunkName: "p__chat__index" */'@/pages/chat/index.tsx')),
'6': React.lazy(() => import(/* webpackChunkName: "p__setting__index" */'@/pages/setting/index.tsx')),
'7': React.lazy(() => import(/* webpackChunkName: "p__file__index" */'@/pages/file/index.tsx')),
'8': React.lazy(() => import(/* webpackChunkName: "p__404" */'@/pages/404.jsx')),
'@@/global-layout': React.lazy(() => import(/* webpackChunkName: "layouts__index" */'C:/Users/zfc/Desktop/docgpt/client/src/layouts/index.tsx')),
},
};
}

+ 37
- 0
web/src/.umi/core/terminal.ts Ver arquivo

@@ -0,0 +1,37 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
let count = 0;
let groupLevel = 0;
function send(type: string, message?: string) {
if(process.env.NODE_ENV==='production'){
return;
}else{
const encodedMessage = message ? `&m=${encodeURI(message)}` : '';
fetch(`/__umi/api/terminal?type=${type}&t=${Date.now()}&c=${count++}&g=${groupLevel}${encodedMessage}`, { mode: 'no-cors' })
}
}
function prettyPrint(obj: any) {
return JSON.stringify(obj, null, 2);
}
function stringifyObjs(objs: any[]) {
const obj = objs.length > 1 ? objs.map(stringify).join(' ') : objs[0];
return typeof obj === 'object' ? `${prettyPrint(obj)}` : obj.toString();
}
function stringify(obj: any) {
return typeof obj === 'object' ? `${JSON.stringify(obj)}` : obj.toString();
}
const terminal = {
log(...objs: any[]) { send('log', stringifyObjs(objs)) },
info(...objs: any[]) { send('info', stringifyObjs(objs)) },
warn(...objs: any[]) { send('warn', stringifyObjs(objs)) },
error(...objs: any[]) { send('error', stringifyObjs(objs)) },
group() { groupLevel++ },
groupCollapsed() { groupLevel++ },
groupEnd() { groupLevel && --groupLevel },
clear() { send('clear') },
trace(...args: any[]) { console.trace(...args) },
profile(...args: any[]) { console.profile(...args) },
profileEnd(...args: any[]) { console.profileEnd(...args) },
};
export { terminal };

+ 22
- 0
web/src/.umi/exports.ts Ver arquivo

@@ -0,0 +1,22 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
// defineApp
export { defineApp } from './core/defineApp'
export type { RuntimeConfig } from './core/defineApp'
// plugins
export { connect, useDispatch, useStore, useSelector, getDvaApp } from 'C:/Users/zfc/Desktop/docgpt/client/src/.umi/plugin-dva';
export { Icon } from 'C:/Users/zfc/Desktop/docgpt/client/src/.umi/plugin-icons';
// plugins types.d.ts
export * from 'C:/Users/zfc/Desktop/docgpt/client/src/.umi/plugin-dva/types.d';
// @umijs/renderer-*
export { createBrowserHistory, createHashHistory, createMemoryHistory, Helmet, HelmetProvider, createSearchParams, generatePath, matchPath, matchRoutes, Navigate, NavLink, Outlet, resolvePath, useLocation, useMatch, useNavigate, useOutlet, useOutletContext, useParams, useResolvedPath, useRoutes, useSearchParams, useAppData, useClientLoaderData, useRouteProps, useSelectedRoutes, useServerLoaderData, renderClient, __getRoot, Link, useRouteData, __useFetcher, withRouter } from 'C:/Users/zfc/Desktop/docgpt/client/node_modules/@umijs/renderer-react';
export type { History } from 'C:/Users/zfc/Desktop/docgpt/client/node_modules/@umijs/renderer-react'
// umi/client/client/plugin
export { ApplyPluginsType, PluginManager } from 'C:/Users/zfc/Desktop/docgpt/client/node_modules/umi/client/client/plugin.js';
export { history, createHistory } from './core/history';
export { terminal } from './core/terminal';
// react ssr
export const useServerInsertedHTML: Function = () => {};
// test
export { TestBrowser } from './testBrowser';

+ 60
- 0
web/src/.umi/plugin-dva/dva.tsx Ver arquivo

@@ -0,0 +1,60 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
// It's faked dva
// aliased to @umijs/plugins/templates/dva
import { create, Provider } from 'C:/Users/zfc/Desktop/docgpt/client/node_modules/@umijs/plugins/libs/dva.tsx';
import createLoading from 'C:/Users/zfc/Desktop/docgpt/client/node_modules/dva-loading/dist/index.js';

import React, { useRef } from 'react';
import { history, ApplyPluginsType, useAppData } from 'umi';
import { models } from './models';

let dvaApp: any;

export function RootContainer(props: any) {
const { pluginManager } = useAppData();
const app = useRef<any>();
const runtimeDva = pluginManager.applyPlugins({
key: 'dva',
type: ApplyPluginsType.modify,
initialValue: {},
});
if (!app.current) {
app.current = create(
{
history,
...(runtimeDva.config || {}),
},
{
initialReducer: {},
setupMiddlewares(middlewares: Function[]) {
return [...middlewares];
},
setupApp(app: IDvaApp) {
app._history = history;
},
},
);
dvaApp = app.current;
app.current.use(createLoading());
(runtimeDva.plugins || []).forEach((p) => {
app.current.use(p);
});
for (const id of Object.keys(models)) {
app.current.model({
namespace: models[id].namespace,
...models[id].model,
});
}
app.current.start();
}
return <Provider store={app.current!._store}>{props.children}</Provider>;
}

export function getDvaApp() {
return dvaApp;
}

+ 5
- 0
web/src/.umi/plugin-dva/index.ts Ver arquivo

@@ -0,0 +1,5 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
export { connect, useDispatch, useStore, useSelector } from 'C:/Users/zfc/Desktop/docgpt/client/node_modules/@umijs/plugins/libs/dva.tsx';
export { getDvaApp } from './dva';

+ 20
- 0
web/src/.umi/plugin-dva/models.ts Ver arquivo

@@ -0,0 +1,20 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import model_1 from 'C:/Users/zfc/Desktop/docgpt/client/src/pages/add-knowledge/components/knowledge-file/model';
import model_2 from 'C:/Users/zfc/Desktop/docgpt/client/src/pages/add-knowledge/components/knowledge-setting/model';
import model_3 from 'C:/Users/zfc/Desktop/docgpt/client/src/pages/add-knowledge/model';
import model_4 from 'C:/Users/zfc/Desktop/docgpt/client/src/pages/chat/model';
import model_5 from 'C:/Users/zfc/Desktop/docgpt/client/src/pages/knowledge/model';
import model_6 from 'C:/Users/zfc/Desktop/docgpt/client/src/pages/login/model';
import model_7 from 'C:/Users/zfc/Desktop/docgpt/client/src/pages/setting/model';

export const models = {
model_1: { namespace: 'add-knowledge.components.knowledge-file.model', model: model_1 },
model_2: { namespace: 'add-knowledge.components.knowledge-setting.model', model: model_2 },
model_3: { namespace: 'add-knowledge.model', model: model_3 },
model_4: { namespace: 'chat.model', model: model_4 },
model_5: { namespace: 'knowledge.model', model: model_5 },
model_6: { namespace: 'login.model', model: model_6 },
model_7: { namespace: 'setting.model', model: model_7 },
} as const

+ 9
- 0
web/src/.umi/plugin-dva/runtime.tsx Ver arquivo

@@ -0,0 +1,9 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import { RootContainer } from './dva';

export function dataflowProvider(container, opts) {
return React.createElement(RootContainer, opts, container);
}

+ 19
- 0
web/src/.umi/plugin-dva/runtimeConfig.d.ts Ver arquivo

@@ -0,0 +1,19 @@
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
export interface IRuntimeConfig {
dva?: {
config?: {
initialState?: Record<string, any>;
onError?: any;
onStateChange?: any;
onAction?: any;
onHmr?: any;
onReducer?: any;
onEffect?: any;
extraReducers?: any;
extraEnhancers?: any;
[key: string]: any;
},
plugins?: string[];
}
}

+ 58
- 0
web/src/.umi/plugin-dva/types.d.ts Ver arquivo

@@ -0,0 +1,58 @@
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import type { History } from 'umi';

export interface ConnectProps {
dispatch?: Dispatch;
}
type RequiredConnectProps = Required<ConnectProps>
export type ConnectRC<
T = {},
> = React.ForwardRefRenderFunction<any, T & RequiredConnectProps>;
interface Action<T = any> {
type: T
}
interface AnyAction extends Action {
// Allows any extra properties to be defined in an action.
[extraProps: string]: any
}
interface Dispatch<A extends Action = AnyAction> {
<T extends A>(action: T): T
}
interface EffectsCommandMap {
put: <A extends AnyAction>(action: A) => any,
call: Function,
select: Function,
take: Function,
cancel: Function,
[key: string]: any,
}
interface Action<T = any> {
type: T
}
export type Reducer<S = any, A extends Action = AnyAction> = (prevState: S, action: A) => S;
export type Effect = (action: AnyAction, effects: EffectsCommandMap) => void;
type EffectType = 'takeEvery' | 'takeLatest' | 'watcher' | 'throttle';
type EffectWithType = [Effect, { type: EffectType }];
export type Subscription = (api: SubscriptionAPI, done: Function) => void;

export interface ReducersMapObject<T> {
[key: string]: Reducer<T>,
}
export interface EffectsMapObject {
[key: string]: Effect | EffectWithType,
}
export interface SubscriptionAPI {
dispatch: Dispatch<any>,
history: History,
}
export interface SubscriptionsMapObject {
[key: string]: Subscription,
}
export interface DvaModel<T, E = EffectsMapObject, R = ReducersMapObject<T>> {
namespace: string,
state?: T,
reducers?: R,
effects?: E,
subscriptions?: SubscriptionsMapObject,
}

+ 8
- 0
web/src/.umi/plugin-icons/icons.tsx Ver arquivo

@@ -0,0 +1,8 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
const localGoogle = props => <svg width={16} height={17} viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}><g clipPath="url(#clip0_660_28)"><path d="M8 6.99902V10.0972H12.3054C12.1164 11.0936 11.549 11.9372 10.6981 12.5045L13.2945 14.5191C14.8072 13.1227 15.68 11.0718 15.68 8.63547C15.68 8.0682 15.6291 7.5227 15.5345 6.99911L8 6.99902Z" fill="#4285F4" /><path d="M3.51649 9.97632L2.93092 10.4246L0.858154 12.0391C2.17451 14.65 4.8725 16.4536 7.99974 16.4536C10.1597 16.4536 11.9706 15.7409 13.2942 14.5191L10.6979 12.5046C9.98516 12.9846 9.07606 13.2755 7.99974 13.2755C5.91976 13.2755 4.15254 11.8719 3.51976 9.98094L3.51649 9.97632Z" fill="#34A853" /><path d="M0.858119 4.86816C0.312695 5.94448 0 7.15905 0 8.45357C0 9.74809 0.312695 10.9627 0.858119 12.039C0.858119 12.0462 3.51998 9.97352 3.51998 9.97352C3.35998 9.49352 3.26541 8.98446 3.26541 8.45349C3.26541 7.92251 3.35998 7.41345 3.51998 6.93345L0.858119 4.86816Z" fill="#FBBC05" /><path d="M7.99991 3.63907C9.17811 3.63907 10.2254 4.04633 11.0617 4.83179L13.3526 2.54091C11.9635 1.24639 10.1599 0.453613 7.99991 0.453613C4.87266 0.453613 2.17451 2.24997 0.858154 4.86816L3.51994 6.93362C4.15263 5.04269 5.91992 3.63907 7.99991 3.63907Z" fill="#EA4335" /></g><defs><clipPath id="clip0_660_28"><rect width={16} height={16} fill="white" transform="translate(0 0.453613)" /></clipPath></defs></svg>;
export { localGoogle };
const localGithub = props => <svg width={17} height={17} viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}><g clipPath="url(#clip0_660_5)"><path fillRule="evenodd" clipRule="evenodd" d="M8.50662 0.453613C4.07917 0.453613 0.5 4.05917 0.5 8.51972C0.5 12.0853 2.79329 15.1035 5.9747 16.1717C6.37246 16.252 6.51816 15.9981 6.51816 15.7846C6.51816 15.5976 6.50505 14.9566 6.50505 14.2888C4.2778 14.7696 3.81399 13.3272 3.81399 13.3272C3.45606 12.3924 2.92572 12.1522 2.92572 12.1522C2.19674 11.658 2.97882 11.658 2.97882 11.658C3.78744 11.7115 4.21175 12.486 4.21175 12.486C4.92745 13.7145 6.08074 13.3674 6.54471 13.1537C6.61092 12.6328 6.82315 12.2723 7.0485 12.072C5.27211 11.885 3.40312 11.1906 3.40312 8.0923C3.40312 7.21091 3.72107 6.4898 4.22486 5.92897C4.14538 5.7287 3.86693 4.90057 4.30451 3.79219C4.30451 3.79219 4.98055 3.57848 6.50488 4.62016C7.1575 4.44359 7.83054 4.35377 8.50662 4.35302C9.18266 4.35302 9.87181 4.4466 10.5082 4.62016C12.0327 3.57848 12.7087 3.79219 12.7087 3.79219C13.1463 4.90057 12.8677 5.7287 12.7882 5.92897C13.3053 6.4898 13.6101 7.21091 13.6101 8.0923C13.6101 11.1906 11.7411 11.8716 9.95146 12.072C10.2432 12.3257 10.4949 12.8064 10.4949 13.5677C10.4949 14.6493 10.4818 15.5174 10.4818 15.7844C10.4818 15.9981 10.6277 16.252 11.0253 16.1719C14.2067 15.1033 16.5 12.0853 16.5 8.51972C16.5131 4.05917 12.9208 0.453613 8.50662 0.453613Z" fill="#24292F" /></g><defs><clipPath id="clip0_660_5"><rect width={16} height={16} fill="white" transform="translate(0.5 0.453613)" /></clipPath></defs></svg>;
export { localGithub };

+ 27
- 0
web/src/.umi/plugin-icons/index.css Ver arquivo

@@ -0,0 +1,27 @@
.umiIconDoNotUseThisHover {
display: none;
}
.umiIconDoNotUseThis:hover svg {
display: none;
}
.umiIconDoNotUseThis:hover .umiIconDoNotUseThisHover {
display: inline-block;
}
.umiIconLoadingCircle {
display: inline-block;
-webkit-animation: loadingCircle 1s infinite linear;
animation: umiIconLoadingCircle 1s linear infinite;
}

@-webkit-keyframes umiIconLoadingCircle {
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes umiIconLoadingCircle {
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}

+ 243
- 0
web/src/.umi/plugin-icons/index.tsx Ver arquivo

@@ -0,0 +1,243 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import * as iconsMap from './icons';
import './index.css';

const alias = {};
type AliasKeys = keyof typeof alias;
const localIcons = ["github","google"] as const;
type LocalIconsKeys = typeof localIcons[number];

type IconCollections = 'academicons' |
'akar-icons' |
'ant-design' |
'arcticons' |
'basil' |
'bi' |
'bpmn' |
'brandico' |
'bx' |
'bxl' |
'bxs' |
'bytesize' |
'carbon' |
'charm' |
'ci' |
'cib' |
'cif' |
'cil' |
'circle-flags' |
'circum' |
'clarity' |
'codicon' |
'cryptocurrency-color' |
'cryptocurrency' |
'dashicons' |
'ei' |
'el' |
'emblemicons' |
'emojione-monotone' |
'emojione-v1' |
'emojione' |
'entypo-social' |
'entypo' |
'eos-icons' |
'ep' |
'et' |
'eva' |
'fa-brands' |
'fa-regular' |
'fa-solid' |
'fa' |
'fa6-brands' |
'fa6-regular' |
'fa6-solid' |
'fad' |
'fe' |
'feather' |
'file-icons' |
'flag' |
'flagpack' |
'flat-color-icons' |
'flat-ui' |
'fluent-emoji-flat' |
'fluent-emoji-high-contrast' |
'fluent-emoji' |
'fluent-mdl2' |
'fluent' |
'fontelico' |
'fontisto' |
'foundation' |
'fxemoji' |
'gala' |
'game-icons' |
'geo' |
'gg' |
'gis' |
'gridicons' |
'grommet-icons' |
'healthicons' |
'heroicons-outline' |
'heroicons-solid' |
'heroicons' |
'humbleicons' |
'ic' |
'icomoon-free' |
'icon-park-outline' |
'icon-park-solid' |
'icon-park-twotone' |
'icon-park' |
'iconoir' |
'icons8' |
'il' |
'ion' |
'iwwa' |
'jam' |
'la' |
'line-md' |
'logos' |
'ls' |
'lucide' |
'majesticons' |
'maki' |
'map' |
'material-symbols' |
'mdi-light' |
'mdi' |
'medical-icon' |
'memory' |
'mi' |
'mingcute' |
'mono-icons' |
'nimbus' |
'nonicons' |
'noto-v1' |
'noto' |
'octicon' |
'oi' |
'ooui' |
'openmoji' |
'pajamas' |
'pepicons-pop' |
'pepicons-print' |
'pepicons' |
'ph' |
'pixelarticons' |
'prime' |
'ps' |
'quill' |
'radix-icons' |
'raphael' |
'ri' |
'si-glyph' |
'simple-icons' |
'simple-line-icons' |
'skill-icons' |
'subway' |
'svg-spinners' |
'system-uicons' |
'tabler' |
'teenyicons' |
'topcoat' |
'twemoji' |
'typcn' |
'uil' |
'uim' |
'uis' |
'uit' |
'uiw' |
'vaadin' |
'vs' |
'vscode-icons' |
'websymbol' |
'whh' |
'wi' |
'wpf' |
'zmdi' |
'zondicons';
type Icon = `${IconCollections}:${string}`;

interface IUmiIconProps extends React.SVGAttributes<SVGElement> {
icon: AliasKeys | Icon | `local:${LocalIconsKeys}`;
hover?: AliasKeys | string;
className?: string;
viewBox?: string;
width?: string;
height?: string;
style?: any;
spin?: boolean;
rotate?: number | string;
flip?: 'vertical' | 'horizontal' | 'horizontal,vertical' | 'vertical,horizontal';
}

export const Icon = React.forwardRef<HTMLSpanElement, IUmiIconProps>((props, ref) => {
const { icon, hover, style, className = '' , rotate, spin, flip, ...extraProps } = props;
const iconName = normalizeIconName(alias[icon] || icon);
const Component = iconsMap[iconName];
if (!Component) {
// TODO: give a error icon when dev, to help developer find the error
return null;
}
const HoverComponent = hover ? iconsMap[normalizeIconName(alias[hover] || hover)] : null;
const cls = spin ? 'umiIconLoadingCircle' : undefined;
const svgStyle = {};
const transform: string[] = [];
if (rotate) {
const rotateDeg = normalizeRotate(rotate);
transform.push(`rotate(${rotateDeg}deg)`);
}
if (flip) {
const flipMap = flip.split(',').reduce((memo, item) => {
memo[item] = 1;
return memo;
}, {});
if (flipMap.vertical) {
transform.push(`rotateY(180deg)`);
}
if (flipMap.horizontal) {
transform.push(`rotateX(180deg)`);
}
}
if (transform.length) {
const transformStr = transform.join('');
svgStyle.msTransform = transformStr;
svgStyle.transform = transformStr;
}

const spanClassName = HoverComponent ? 'umiIconDoNotUseThis ' : '' + className;
const spanClass = spanClassName ? { className: spanClassName } : {};

return (
<span role="img" ref={ref} {...spanClass} style={style}>
<Component {...extraProps} className={cls} style={svgStyle} />
{
HoverComponent ? <HoverComponent {...extraProps} className={'umiIconDoNotUseThisHover ' + cls} style={svgStyle} /> : null
}
</span>
);
});

function normalizeRotate(rotate: number | string) {
if (typeof rotate === 'number') {
return rotate * 90;
}
if (typeof rotate === 'string') {
if (rotate.endsWith('deg')) {
return parseInt(rotate, 10);
}
if (rotate.endsWith('%')) {
return parseInt(rotate, 10) / 100 * 360;
}
return 0;
}
}

function camelCase(str: string) {
return str.replace(/\//g, '-').replace(/-([a-zA-Z]|[1-9])/g, (g) => g[1].toUpperCase());
}

function normalizeIconName(name: string) {
return camelCase(name.replace(':', '-'));
}

+ 87
- 0
web/src/.umi/testBrowser.tsx Ver arquivo

@@ -0,0 +1,87 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React, { useEffect, useState } from 'react';
import { ApplyPluginsType } from 'umi';
import { renderClient, RenderClientOpts } from 'C:/Users/zfc/Desktop/docgpt/client/node_modules/@umijs/renderer-react';
import { createHistory } from './core/history';
import { createPluginManager } from './core/plugin';
import { getRoutes } from './core/route';
import type { Location } from 'history';


const publicPath = '/';
const runtimePublicPath = false;

type TestBrowserProps = {
location?: Partial<Location>;
historyRef?: React.MutableRefObject<Location>;
};

export function TestBrowser(props: TestBrowserProps) {
const pluginManager = createPluginManager();
const [context, setContext] = useState<RenderClientOpts | undefined>(
undefined
);
useEffect(() => {
const genContext = async () => {
const { routes, routeComponents } = await getRoutes(pluginManager);
// allow user to extend routes
await pluginManager.applyPlugins({
key: 'patchRoutes',
type: ApplyPluginsType.event,
args: {
routes,
routeComponents,
},
});
const contextOpts = pluginManager.applyPlugins({
key: 'modifyContextOpts',
type: ApplyPluginsType.modify,
initialValue: {},
});
const basename = contextOpts.basename || '/';
const history = createHistory({
type: 'memory',
basename,
});
const context = {
routes,
routeComponents,
pluginManager,
rootElement: contextOpts.rootElement || document.getElementById('root'),
publicPath,
runtimePublicPath,
history,
basename,
components: true,
};
const modifiedContext = pluginManager.applyPlugins({
key: 'modifyClientRenderOpts',
type: ApplyPluginsType.modify,
initialValue: context,
});
return modifiedContext;
};
genContext().then((context) => {
setContext(context);
if (props.location) {
context?.history?.push(props.location);
}
if (props.historyRef) {
props.historyRef.current = context?.history;
}
});
}, []);

if (context === undefined) {
return <div id="loading" />;
}

const Children = renderClient(context);
return (
<React.Fragment>
<Children />
</React.Fragment>
);
}

+ 43
- 0
web/src/.umi/tsconfig.json Ver arquivo

@@ -0,0 +1,43 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"moduleResolution": "bundler",
"importHelpers": true,
"noEmit": true,
"jsx": "react-jsx",
"esModuleInterop": true,
"sourceMap": true,
"baseUrl": "../../",
"strict": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"paths": {
"@/*": [
"src/*"
],
"@@/*": [
"src/.umi/*"
],
"umi": [
"C:\\Users\\zfc\\Desktop\\docgpt\\client\\node_modules\\umi"
],
"umi/typings": [
"src/.umi/typings"
]
}
},
"include": [
"../../.umirc.ts",
"../../**/*.d.ts",
"../../**/*.ts",
"../../**/*.tsx"
]
}

+ 136
- 0
web/src/.umi/typings.d.ts Ver arquivo

@@ -0,0 +1,136 @@
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
type CSSModuleClasses = { readonly [key: string]: string }
declare module '*.css' {
const classes: CSSModuleClasses
export default classes
}
declare module '*.scss' {
const classes: CSSModuleClasses
export default classes
}
declare module '*.sass' {
const classes: CSSModuleClasses
export default classes
}
declare module '*.less' {
const classes: CSSModuleClasses
export default classes
}
declare module '*.styl' {
const classes: CSSModuleClasses
export default classes
}
declare module '*.stylus' {
const classes: CSSModuleClasses
export default classes
}

// images
declare module '*.jpg' {
const src: string
export default src
}
declare module '*.jpeg' {
const src: string
export default src
}
declare module '*.png' {
const src: string
export default src
}
declare module '*.gif' {
const src: string
export default src
}
declare module '*.svg' {
import * as React from 'react';
export const ReactComponent: React.FunctionComponent<React.SVGProps<
SVGSVGElement
> & { title?: string }>;

const src: string
export default src
}
declare module '*.ico' {
const src: string
export default src
}
declare module '*.webp' {
const src: string
export default src
}
declare module '*.avif' {
const src: string
export default src
}

// media
declare module '*.mp4' {
const src: string
export default src
}
declare module '*.webm' {
const src: string
export default src
}
declare module '*.ogg' {
const src: string
export default src
}
declare module '*.mp3' {
const src: string
export default src
}
declare module '*.wav' {
const src: string
export default src
}
declare module '*.flac' {
const src: string
export default src
}
declare module '*.aac' {
const src: string
export default src
}

// fonts
declare module '*.woff' {
const src: string
export default src
}
declare module '*.woff2' {
const src: string
export default src
}
declare module '*.eot' {
const src: string
export default src
}
declare module '*.ttf' {
const src: string
export default src
}
declare module '*.otf' {
const src: string
export default src
}

// other
declare module '*.wasm' {
const initWasm: (options: WebAssembly.Imports) => Promise<WebAssembly.Exports>
export default initWasm
}
declare module '*.webmanifest' {
const src: string
export default src
}
declare module '*.pdf' {
const src: string
export default src
}
declare module '*.txt' {
const src: string
export default src
}

+ 76
- 0
web/src/.umi/umi.ts Ver arquivo

@@ -0,0 +1,76 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import './core/polyfill';

import { renderClient } from 'C:/Users/zfc/Desktop/docgpt/client/node_modules/@umijs/renderer-react';
import { getRoutes } from './core/route';
import { createPluginManager } from './core/plugin';
import { createHistory } from './core/history';
import { ApplyPluginsType } from 'umi';


const publicPath = "/client/dist/";
const runtimePublicPath = false;

async function render() {
const pluginManager = createPluginManager();
const { routes, routeComponents } = await getRoutes(pluginManager);

// allow user to extend routes
await pluginManager.applyPlugins({
key: 'patchRoutes',
type: ApplyPluginsType.event,
args: {
routes,
routeComponents,
},
});

const contextOpts = pluginManager.applyPlugins({
key: 'modifyContextOpts',
type: ApplyPluginsType.modify,
initialValue: {},
});

const basename = contextOpts.basename || '/';
const historyType = contextOpts.historyType || 'hash';

const history = createHistory({
type: historyType,
basename,
...contextOpts.historyOpts,
});

return (pluginManager.applyPlugins({
key: 'render',
type: ApplyPluginsType.compose,
initialValue() {
const context = {
routes,
routeComponents,
pluginManager,
rootElement: contextOpts.rootElement || document.getElementById('root'),
publicPath,
runtimePublicPath,
history,
historyType,
basename,
callback: contextOpts.callback,
};
const modifiedContext = pluginManager.applyPlugins({
key: 'modifyClientRenderOpts',
type: ApplyPluginsType.modify,
initialValue: context,
});
return renderClient(modifiedContext);
},
}))();
}


render();

window.g_umi = {
version: '4.1.0',
};

BIN
web/src/assets/logo.png Ver arquivo


BIN
web/src/assets/yay.jpg Ver arquivo


+ 10
- 0
web/src/icons/github.svg Ver arquivo

@@ -0,0 +1,10 @@
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_660_5)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.50662 0.453613C4.07917 0.453613 0.5 4.05917 0.5 8.51972C0.5 12.0853 2.79329 15.1035 5.9747 16.1717C6.37246 16.252 6.51816 15.9981 6.51816 15.7846C6.51816 15.5976 6.50505 14.9566 6.50505 14.2888C4.2778 14.7696 3.81399 13.3272 3.81399 13.3272C3.45606 12.3924 2.92572 12.1522 2.92572 12.1522C2.19674 11.658 2.97882 11.658 2.97882 11.658C3.78744 11.7115 4.21175 12.486 4.21175 12.486C4.92745 13.7145 6.08074 13.3674 6.54471 13.1537C6.61092 12.6328 6.82315 12.2723 7.0485 12.072C5.27211 11.885 3.40312 11.1906 3.40312 8.0923C3.40312 7.21091 3.72107 6.4898 4.22486 5.92897C4.14538 5.7287 3.86693 4.90057 4.30451 3.79219C4.30451 3.79219 4.98055 3.57848 6.50488 4.62016C7.1575 4.44359 7.83054 4.35377 8.50662 4.35302C9.18266 4.35302 9.87181 4.4466 10.5082 4.62016C12.0327 3.57848 12.7087 3.79219 12.7087 3.79219C13.1463 4.90057 12.8677 5.7287 12.7882 5.92897C13.3053 6.4898 13.6101 7.21091 13.6101 8.0923C13.6101 11.1906 11.7411 11.8716 9.95146 12.072C10.2432 12.3257 10.4949 12.8064 10.4949 13.5677C10.4949 14.6493 10.4818 15.5174 10.4818 15.7844C10.4818 15.9981 10.6277 16.252 11.0253 16.1719C14.2067 15.1033 16.5 12.0853 16.5 8.51972C16.5131 4.05917 12.9208 0.453613 8.50662 0.453613Z" fill="#24292F"/>
</g>
<defs>
<clipPath id="clip0_660_5">
<rect width="16" height="16" fill="white" transform="translate(0.5 0.453613)"/>
</clipPath>
</defs>
</svg>

+ 13
- 0
web/src/icons/google.svg Ver arquivo

@@ -0,0 +1,13 @@
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_660_28)">
<path d="M8 6.99902V10.0972H12.3054C12.1164 11.0936 11.549 11.9372 10.6981 12.5045L13.2945 14.5191C14.8072 13.1227 15.68 11.0718 15.68 8.63547C15.68 8.0682 15.6291 7.5227 15.5345 6.99911L8 6.99902Z" fill="#4285F4"/>
<path d="M3.51649 9.97632L2.93092 10.4246L0.858154 12.0391C2.17451 14.65 4.8725 16.4536 7.99974 16.4536C10.1597 16.4536 11.9706 15.7409 13.2942 14.5191L10.6979 12.5046C9.98516 12.9846 9.07606 13.2755 7.99974 13.2755C5.91976 13.2755 4.15254 11.8719 3.51976 9.98094L3.51649 9.97632Z" fill="#34A853"/>
<path d="M0.858119 4.86816C0.312695 5.94448 0 7.15905 0 8.45357C0 9.74809 0.312695 10.9627 0.858119 12.039C0.858119 12.0462 3.51998 9.97352 3.51998 9.97352C3.35998 9.49352 3.26541 8.98446 3.26541 8.45349C3.26541 7.92251 3.35998 7.41345 3.51998 6.93345L0.858119 4.86816Z" fill="#FBBC05"/>
<path d="M7.99991 3.63907C9.17811 3.63907 10.2254 4.04633 11.0617 4.83179L13.3526 2.54091C11.9635 1.24639 10.1599 0.453613 7.99991 0.453613C4.87266 0.453613 2.17451 2.24997 0.858154 4.86816L3.51994 6.93362C4.15263 5.04269 5.91992 3.63907 7.99991 3.63907Z" fill="#EA4335"/>
</g>
<defs>
<clipPath id="clip0_660_28">
<rect width="16" height="16" fill="white" transform="translate(0 0.453613)"/>
</clipPath>
</defs>
</svg>

+ 38
- 0
web/src/layouts/components/user/index.tsx Ver arquivo

@@ -0,0 +1,38 @@
import React, { useMemo } from 'react';
import type { MenuProps } from 'antd';
import { Button, Dropdown, } from 'antd';
import { history } from 'umi'
import { useTranslation, Trans } from 'react-i18next'
const App: React.FC = () => {
const { t } = useTranslation()
const logout = () => { history.push('/login') }
const toSetting = () => { history.push('/setting') }
const items: MenuProps['items'] = useMemo(() => {
return [
{
key: '1',
label: (
<Button type="text" onClick={logout}>{t('header.logout')}</Button>
),
},
{
key: '2',
label: (
<Button type="text" onClick={toSetting}>{t('header.setting')}</Button>
),
},
]
}, []);
return (<>
<Dropdown menu={{ items }} placement="bottomLeft" arrow>
<img
style={{ width: '50px', height: '50px', borderRadius: '25px' }}
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
/>
</Dropdown>
</>)
}
export default App;

+ 33
- 0
web/src/layouts/index.less Ver arquivo

@@ -0,0 +1,33 @@
.navs {
ul {
padding: 0;
list-style: none;
display: flex;
}
li {
margin-right: 1em;
}
}
.layout {
height: 100vh;
}
body {
margin: 0;
}
.tag {
height: 40px;
padding: 0 30px;
margin: 0 5px;
border: 1px solid #000;
border-radius: 10px;
cursor: pointer;
}
.checked {
color: #1677ff;
border-color: #1677ff;
}

+ 74
- 0
web/src/layouts/index.tsx Ver arquivo

@@ -0,0 +1,74 @@
import React, { useEffect, useState } from 'react';
import { history, Outlet, useLocation, useNavigate } from 'umi';
import { useTranslation, Trans } from 'react-i18next'
import classnames from 'classnames'
import '../locales/config';
import logo from '@/assets/logo.png'
import {
RedditOutlined
} from '@ant-design/icons';
import { Layout, Button, theme, Space, } from 'antd';
import styles from './index.less'
import User from './components/user'
import { head } from 'lodash';
const { Header, Content } = Layout;
const App: React.FC = (props) => {
const { t } = useTranslation()
const navigate = useNavigate()
const {
token: { colorBgContainer, borderRadiusLG },
} = theme.useToken();
const [current, setCurrent] = useState('knowledge');
const location = useLocation();
useEffect(() => {
if (location.pathname !== '/') {
const path = location.pathname.split('/')
setCurrent(path[1]);
}
console.log(location.pathname.split('/'))
}, [location.pathname])
const handleChange = (path: string) => {
setCurrent(path)
navigate(path);
};
const tagsData = [{ path: '/knowledge', name: 'knowledge' }, { path: '/chat', name: 'chat' }, { path: '/file', name: 'file' }];
return (
<Layout className={styles.layout} >
<Layout>
<Header style={{ padding: '0 8px', background: colorBgContainer, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<img src={logo} alt="" style={{ height: 30, width: 30 }} />
<Space size={[0, 8]} wrap>
{tagsData.map((item) =>
(<span key={item.name} className={classnames(styles['tag'], {
[styles['checked']]: current === item.name
})} onClick={() => handleChange(item.path)}>
{item.name}
</span>)
)}
</Space>
<User ></User>
</Header>
<Content
style={{
margin: '24px 16px',
minHeight: 280,
background: colorBgContainer,
borderRadius: borderRadiusLG,
overflow: 'auto'
}}
>
<Outlet />
</Content>
</Layout>
</Layout >
);
};
export default App;

+ 24
- 0
web/src/locales/config.ts Ver arquivo

@@ -0,0 +1,24 @@
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import translation_en from './en.json';
import translation_zh from './zh.json';
const resources = {
en: {
translation: translation_en,
},
zh: {
translation: translation_zh,
},
};
i18n.use(initReactI18next).init({
resources,
lng: 'zh',
interpolation: {
escapeValue: false,
},
});
export default i18n;

+ 20
- 0
web/src/locales/en.json Ver arquivo

@@ -0,0 +1,20 @@
{
"header": {
"register": "Register",
"signin": "Sign In",
"home": "Home",
"setting": "用户设置",
"logout": "登出"
},
"footer": {
"detail": "All rights reserved @ React"
},
"layout": {
"file": "file",
"knowledge": "knowledge",
"chat": "chat"
},
"setting": {
"btn": "en"
}
}

+ 20
- 0
web/src/locales/zh.json Ver arquivo

@@ -0,0 +1,20 @@
{
"header": {
"register": "注册",
"signin": "登陆",
"home": "首页",
"setting": "user setting",
"logout": "logout"
},
"footer": {
"detail": "版权所有 @ React"
},
"layout": {
"file": "文件",
"knowledge": "知识库",
"chat": "聊天"
},
"setting": {
"btn": "中文"
}
}

+ 17
- 0
web/src/pages/404.jsx Ver arquivo

@@ -0,0 +1,17 @@
import { Button, Result } from 'antd';
import React from 'react';
import { history } from 'umi';
const NoFoundPage = () => {
return (<Result
status="404"
title="404"
subTitle="页面未找到,请输入正确的地址。"
extra={< Button type="primary" onClick={() => history.push('/')}>
返回主页
</Button>}
/>
)
};
export default NoFoundPage;

+ 72
- 0
web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx Ver arquivo

@@ -0,0 +1,72 @@
import { connect } from 'umi';
import i18n from 'i18next';
import { useTranslation, Trans } from 'react-i18next'
import { Input, Modal, Form } from 'antd'
import { rsaPsw } from '@/utils'
import styles from './index.less';
type FieldType = {
name?: string;
};
const Index = ({ kFModel, dispatch, getKfList, kb_id }) => {
const { isShowCEFwModal } = kFModel
const { t } = useTranslation()
const handleCancel = () => {
dispatch({
type: 'kFModel/updateState',
payload: {
isShowCEFwModal: false
}
});
};
const [form] = Form.useForm()
const handleOk = async () => {
try {
const values = await form.validateFields();
dispatch({
type: 'kFModel/document_create',
payload: {
name: values.name,
kb_id
},
callback: () => {
dispatch({
type: 'kFModel/updateState',
payload: {
isShowCEFwModal: false
}
});
getKfList && getKfList()
}
});
} catch (errorInfo) {
console.log('Failed:', errorInfo);
}
};
return (
<Modal title="Basic Modal" open={isShowCEFwModal} onOk={handleOk} onCancel={handleCancel}>
<Form
form={form}
name="validateOnly"
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
style={{ maxWidth: 600 }}
autoComplete="off"
>
<Form.Item<FieldType>
label="文件名"
name="name"
rules={[{ required: true, message: 'Please input name!' }]}
>
<Input />
</Form.Item>
</Form>
</Modal >
);
}
export default connect(({ kFModel, loading }) => ({ kFModel, loading }))(Index);

+ 24
- 0
web/src/pages/add-knowledge/components/knowledge-file/index.less Ver arquivo

@@ -0,0 +1,24 @@
.filter {
height: 32px;
display: flex;
margin: 10px 0;
justify-content: space-between;
.search {
flex: 1;
}
.operate {
width: 200px;
}
}
.img {
height: 16px;
width: 16px;
margin-right: 6px;
}
.column {
min-width: 200px
}

+ 218
- 0
web/src/pages/add-knowledge/components/knowledge-file/index.tsx Ver arquivo

@@ -0,0 +1,218 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { connect, useNavigate, useLocation } from 'umi'
import { Space, Table, Tag, Input, Button, Switch, Popover, Dropdown, } from 'antd';
import type { MenuProps } from 'antd';
import { PlusOutlined, DownOutlined } from '@ant-design/icons'
import { debounce } from 'lodash';
import type { ColumnsType } from 'antd/es/table';
import UploadFile from './upload'
import CreateEPModal from './createEFileModal'
import SegmentSetModal from './segmentSetModal'
import styles from './index.less'
interface DataType {
name: string;
chunk_num: string;
token_num: number;
update_date: string;
size: string;
status: string;
id: string;
parser_id: string
}
const Index: React.FC = ({ kFModel, dispatch, id }) => {
const { data, loading } = kFModel
const [inputValue, setInputValue] = useState('')
const [doc_id, setDocId] = useState('0')
const [parser_id, setParserId] = useState('0')
const changeValue = (value: string) => {
{
console.log(value)
}
}
const getKfList = () => {
dispatch({
type: 'kFModel/getKfList',
payload: {
kb_id: id
}
});
}
useEffect(() => {
if (id) {
getKfList()
}
}, [id])
const debounceChange = debounce(changeValue, 300)
const debounceCallback = useCallback((value: string) => debounceChange(value), [])
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const value = e.target.value
setInputValue(value)
debounceCallback(e.target.value)
}
const onChangeStatus = (e: boolean, doc_id: string) => {
dispatch({
type: 'kFModel/updateDocumentStatus',
payload: {
doc_id,
status: Number(e)
},
callback() {
getKfList()
}
});
}
const onRmDocument = () => {
dispatch({
type: 'kFModel/document_rm',
payload: {
doc_id
},
callback() {
getKfList()
}
});
}
const showCEFModal = () => {
dispatch({
type: 'kFModel/updateState',
payload: {
isShowCEFwModal: true
}
});
};
const showSegmentSetModal = () => {
dispatch({
type: 'kFModel/updateState',
payload: {
isShowSegmentSetModal: true
}
});
};
const actionItems: MenuProps['items'] = useMemo(() => {
return [
{
key: '1',
label: (
<div>
<UploadFile kb_id={id} getKfList={getKfList} />
</div>
),
},
{
key: '2',
label: (
<div>
<Button type="link" onClick={showCEFModal}> 导入虚拟文件</Button>
</div>
),
// disabled: true,
},
]
}, [id]);
const chunkItems: MenuProps['items'] = [
{
key: '1',
label: (
<div>
<Button type="link" onClick={showSegmentSetModal}> 分段设置</Button>
</div>
),
},
{
key: '2',
label: (
<div>
<Button type="link" onClick={onRmDocument}> 删除</Button>
</div>
),
// disabled: true,
},
]
const columns: ColumnsType<DataType> = [
{
title: '名称',
dataIndex: 'name',
key: 'name',
render: (text) => <a><img className={styles.img} src='https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg' alt="" />{text}</a>,
className: `${styles.column}`
},
{
title: '数据总量',
dataIndex: 'chunk_num',
key: 'chunk_num',
className: `${styles.column}`
},
{
title: 'Tokens',
dataIndex: 'token_num',
key: 'token_num',
className: `${styles.column}`
},
{
title: '文件大小',
dataIndex: 'size',
key: 'size',
className: `${styles.column}`
},
{
title: '状态',
key: 'status',
dataIndex: 'status',
className: `${styles.column}`,
render: (_, { status: string, id }) => (
<>
<Switch defaultChecked={status === '1'} onChange={(e) => {
onChangeStatus(e, id)
}} />
</>
),
},
{
title: 'Action',
key: 'action',
className: `${styles.column}`,
render: (_, record) => (
<Space size="middle">
<Dropdown menu={{ items: chunkItems }} trigger={['click']}>
<a onClick={() => {
setDocId(record.id)
setParserId(record.parser_id)
}}>
分段设置 <DownOutlined />
</a>
</Dropdown>
</Space>
),
},
];
return <>
<div className={styles.filter}>
<div className="search">
<Input placeholder="搜索" value={inputValue} allowClear onChange={handleInputChange} />
</div>
<div className="operate">
<Dropdown menu={{ items: actionItems }} trigger={['click']} >
<a>
导入文件 <DownOutlined />
</a>
</Dropdown>
</div>
</div>
<Table rowKey='id' columns={columns} dataSource={data} loading={loading} pagination={false} scroll={{ scrollToFirstRowOnChange: true, x: true }} />
<CreateEPModal getKfList={getKfList} kb_id={id} />
<SegmentSetModal getKfList={getKfList} parser_id={parser_id} doc_id={doc_id} />
</>
};
export default connect(({ kFModel, loading }) => ({ kFModel, loading }))(Index);

+ 127
- 0
web/src/pages/add-knowledge/components/knowledge-file/model.ts Ver arquivo

@@ -0,0 +1,127 @@
import { message } from 'antd';
import { addParam } from '@/utils';
import kbService from '@/services/kbService';
const Model = {
namespace: 'kFModel',
state: {
isShowCEFwModal: false,
isShowTntModal: false,
isShowSegmentSetModal: false,
loading: false,
tenantIfo: {}
},
subscriptions: {
setup({ dispatch, history }) {
history.listen(location => {
});
}
},
effects: {
* createKf({ payload = {}, callback }, { call, put }) {
const { data, response } = yield call(kbService.createKb, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
message.success('创建成功!');
}
},
* updateKf({ payload = {}, callback }, { call, put }) {
const { data, response } = yield call(kbService.updateKb, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
message.success('修改成功!');
}
},
*getKfDetail({ payload = {}, callback }, { call, put }) {
const { data, response } = yield call(kbService.get_kb_detail, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
// localStorage.setItem('userInfo',res.)
callback && callback(res)
}
},
*getKfList({ payload = {} }, { call, put }) {
yield put({
type: 'updateState',
payload: {
loading: true
}
});
const { data, response } = yield call(kbService.get_document_list, payload);
const { retcode, data: res, retmsg } = data
yield put({
type: 'updateState',
payload: {
loading: false
}
});
if (retcode === 0) {
yield put({
type: 'updateState',
payload: {
data: res
}
});
}
},
*updateDocumentStatus({ payload = {}, callback }, { call, put }) {
yield put({
type: 'updateState',
payload: {
loading: true
}
});
const { data, response } = yield call(kbService.document_change_status, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
message.success('修改成功!');
yield put({
type: 'updateState',
payload: {
loading: false
}
});
callback && callback()
}
},
*document_rm({ payload = {}, callback }, { call, put }) {
const { data, response } = yield call(kbService.document_rm, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
message.success('删除成功!');
callback && callback()
}
},
*document_create({ payload = {}, callback }, { call, put }) {
const { data, response } = yield call(kbService.document_create, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
message.success('创建成功!');
callback && callback()
}
},
*document_change_parser({ payload = {}, callback }, { call, put }) {
const { data, response } = yield call(kbService.document_change_parser, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
message.success('修改成功!');
callback && callback()
}
},
},
reducers: {
updateState(state, { payload }) {
return {
...state,
...payload
};
}
}
};
export default Model;

+ 84
- 0
web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx Ver arquivo

@@ -0,0 +1,84 @@
import { connect } from 'umi';
import i18n from 'i18next';
import { useTranslation, Trans } from 'react-i18next'
import { Input, Modal, Form, Tag, Space } from 'antd'
import { rsaPsw } from '@/utils'
import { useEffect, useState } from 'react';
import styles from './index.less';
const { CheckableTag } = Tag;
type FieldType = {
name?: string;
};
const Index = ({ kFModel, settingModel, dispatch, getKfList, parser_id, doc_id }) => {
const [selectedTag, setSelectedTag] = useState('')
const { tenantIfo = {} } = settingModel
const { parser_ids = '' } = tenantIfo
useEffect(() => {
dispatch({
type: 'settingModel/getTenantInfo',
payload: {
}
});
setSelectedTag(parser_id)
}, [parser_id])
const { isShowSegmentSetModal } = kFModel
const { t } = useTranslation()
const handleCancel = () => {
dispatch({
type: 'kFModel/updateState',
payload: {
isShowSegmentSetModal: false
}
});
};
const handleOk = () => {
console.log(1111, selectedTag)
dispatch({
type: 'kFModel/document_change_parser',
payload: {
parser_id: selectedTag,
doc_id
},
callback: () => {
dispatch({
type: 'kFModel/updateState',
payload: {
isShowSegmentSetModal: false
}
});
getKfList && getKfList()
}
});
};
const handleChange = (tag: string, checked: boolean) => {
const nextSelectedTag = checked
? tag
: selectedTag;
console.log('You are interested in: ', nextSelectedTag);
setSelectedTag(nextSelectedTag);
};
return (
<Modal title="Basic Modal" open={isShowSegmentSetModal} onOk={handleOk} onCancel={handleCancel}>
<Space size={[0, 8]} wrap>
<div className={styles.tags}>
{
parser_ids.split(',').map((tag: string) => {
return (<CheckableTag
key={tag}
checked={selectedTag === tag}
onChange={(checked) => handleChange(tag, checked)}
>
{tag}
</CheckableTag>)
})
}
</div>
</Space>
</Modal >
);
}
export default connect(({ kFModel, settingModel, loading }) => ({ kFModel, settingModel, loading }))(Index);

+ 30
- 0
web/src/pages/add-knowledge/components/knowledge-file/upload.tsx Ver arquivo

@@ -0,0 +1,30 @@
import React from 'react';
import { connect } from 'umi'
import { UploadOutlined } from '@ant-design/icons';
import type { UploadProps } from 'antd';
import { Button, message, Upload } from 'antd';
import uploadService from '@/services/uploadService'
const Index = ({ kb_id, getKfList }) => {
console.log(kb_id)
const createRequest = async function ({ file, onSuccess, onError }) {
const { retcode, data } = await uploadService.uploadFile(file, kb_id);
if (retcode === 0) {
onSuccess(data, file);
} else {
onError(data);
}
getKfList && getKfList()
};
const uploadProps: UploadProps = {
customRequest: createRequest,
showUploadList: false,
};
return (<Upload {...uploadProps} >
<Button type="link">导入文件</Button>
</Upload>)
}
export default connect(({ kFModel, settingModel, loading }) => ({ kFModel, settingModel, loading }))(Index);

+ 3
- 0
web/src/pages/add-knowledge/components/knowledge-search/index.tsx Ver arquivo

@@ -0,0 +1,3 @@
export default () => {
return <div>知识库搜索</div>
}

+ 24
- 0
web/src/pages/add-knowledge/components/knowledge-setting/index.less Ver arquivo

@@ -0,0 +1,24 @@
.tags {
margin-bottom: 24px;
}
.preset {
display: flex;
height: 80px;
background-color: rgba(0, 0, 0, 0.1);
border-radius: 5px;
padding: 5px;
margin-bottom: 24px;
.left {
flex: 1;
}
.right {
width: 100px;
border-left: 1px solid rgba(0, 0, 0, 0.4);
margin: 10px 0px;
padding: 5px;
}
}

+ 192
- 0
web/src/pages/add-knowledge/components/knowledge-setting/index.tsx Ver arquivo

@@ -0,0 +1,192 @@
import React, { useEffect, useState } from 'react';
import { useNavigate, connect } from 'umi'
import { Button, Form, Input, InputNumber, Radio, Select, Tag, Space, Avatar, Divider, List, Skeleton } from 'antd';
import styles from './index.less'
const { CheckableTag } = Tag;
const layout = {
labelCol: { span: 8 },
wrapperCol: { span: 16 },
labelAlign: 'left' as const
};
const { Option } = Select
/* eslint-disable no-template-curly-in-string */
const validateMessages = {
required: '${label} is required!',
types: {
email: '${label} is not a valid email!',
number: '${label} is not a valid number!',
},
number: {
range: '${label} must be between ${min} and ${max}',
},
};
/* eslint-enable no-template-curly-in-string */
interface DataType {
gender: string;
name: {
title: string;
first: string;
last: string;
};
email: string;
picture: {
large: string;
medium: string;
thumbnail: string;
};
nat: string;
}
const tags = [{ title: '研报' }, { title: '法律' }, { title: '简历' }, { title: '说明书' }, { title: '书籍' }, { title: '演讲稿' }]
const Index: React.FC = ({ settingModel, kSModel, dispatch, ...props }) => {
let navigate = useNavigate();
const { tenantIfo = {} } = settingModel
const { parser_ids = '', embd_id = '' } = tenantIfo
const { id = '' } = props
const [form] = Form.useForm();
useEffect(() => {
dispatch({
type: 'settingModel/getTenantInfo',
payload: {
}
});
if (id) {
dispatch({
type: 'kSModel/getKbDetail',
payload: {
kb_id: id
},
callback(detail: any) {
console.log(detail)
const { description, name, permission, embd_id } = detail
form.setFieldsValue({ description, name, permission, embd_id })
setSelectedTag(detail.parser_id)
}
});
}
}, [id])
const [selectedTag, setSelectedTag] = useState('')
const values = Form.useWatch([], form);
console.log(values, '......变化')
const onFinish = () => {
form.validateFields().then(
() => {
if (id) {
dispatch({
type: 'kSModel/updateKb',
payload: {
...values,
parser_id: selectedTag,
kb_id: id,
embd_id: undefined
}
});
} else {
dispatch({
type: 'kSModel/createKb',
payload: {
...values,
parser_id: selectedTag
},
callback(id: string) {
navigate(`/knowledge/add/setting?activeKey=file&id=${id}`);
}
});
}
},
() => {
},
);
};
const handleChange = (tag: string, checked: boolean) => {
const nextSelectedTag = checked
? tag
: selectedTag;
console.log('You are interested in: ', nextSelectedTag);
setSelectedTag(nextSelectedTag);
};
return <Form
{...layout}
form={form}
name="validateOnly"
style={{ maxWidth: 1000, padding: 14 }}
>
<Form.Item name='name' label="知识库名称" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item name='description' label="知识库描述">
<Input.TextArea />
</Form.Item>
<Form.Item name="permission" label="可见权限">
<Radio.Group>
<Radio value="me">只有我</Radio>
<Radio value="team">所有团队成员</Radio>
</Radio.Group>
</Form.Item>
<Form.Item
name="embd_id"
label="Embedding 模型"
hasFeedback
rules={[{ required: true, message: 'Please select your country!' }]}
>
<Select placeholder="Please select a country" disabled={id}>
{embd_id.split(',').map((item: string) => {
return <Option value={item} key={item}>{item}</Option>
})}
</Select>
</Form.Item>
<div style={{ marginTop: '5px' }}>
修改Embedding 模型,请去<span style={{ color: '#1677ff' }}>设置</span>
</div>
<Space size={[0, 8]} wrap>
<div className={styles.tags}>
{
parser_ids.split(',').map((tag: string) => {
return (<CheckableTag
key={tag}
checked={selectedTag === tag}
onChange={(checked) => handleChange(tag, checked)}
>
{tag}
</CheckableTag>)
})
}
</div>
</Space>
<Space size={[0, 8]} wrap>
</Space>
<div className={styles.preset}>
<div className={styles.left}>
xxxxx文章
</div>
<div className={styles.right}>
预估份数
</div>
</div>
<Form.Item wrapperCol={{ ...layout.wrapperCol, offset: 8 }}>
<Button type="primary" onClick={onFinish}>
保存并处理
</Button>
<Button htmlType="button" style={{ marginLeft: '20px' }}>
取消
</Button>
</Form.Item>
</Form>
}
export default connect(({ settingModel, kSModel, loading }) => ({ settingModel, kSModel, loading }))(Index);

+ 53
- 0
web/src/pages/add-knowledge/components/knowledge-setting/model.ts Ver arquivo

@@ -0,0 +1,53 @@
import { message } from 'antd';
import { addParam } from '@/utils';
import kbService from '@/services/kbService';
const Model = {
namespace: 'kSModel',
state: {
isShowPSwModal: false,
isShowTntModal: false,
loading: false,
tenantIfo: {}
},
subscriptions: {
setup({ dispatch, history }) {
history.listen(location => {
});
}
},
effects: {
* createKb({ payload = {}, callback }, { call, put }) {
const { data, response } = yield call(kbService.createKb, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
message.success('创建知识库成功!');
callback && callback(res.kb_id)
}
},
* updateKb({ payload = {}, callback }, { call, put }) {
const { data, response } = yield call(kbService.updateKb, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
message.success('更新知识库成功!');
}
},
*getKbDetail({ payload = {}, callback }, { call, put }) {
const { data, response } = yield call(kbService.get_kb_detail, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
// localStorage.setItem('userInfo',res.)
callback && callback(res)
}
},
},
reducers: {
updateState(state, { payload }) {
return {
...state,
...payload
};
}
}
};
export default Model;

+ 19
- 0
web/src/pages/add-knowledge/index.less Ver arquivo

@@ -0,0 +1,19 @@
.container {
display: flex;
.menu {
.defaultWidth {
width: 256px;
}
.minWidth {
width: 50px
}
}
.content {
flex: 1;
overflow-x: auto;
height: 100%;
}
}

+ 106
- 0
web/src/pages/add-knowledge/index.tsx Ver arquivo

@@ -0,0 +1,106 @@
import { connect, useNavigate, useLocation } from 'umi'
import React, { useMemo, useState, useEffect } from 'react';
import type { MenuProps } from 'antd';
import { Radio, Space, Tabs, Menu } from 'antd';
import {
ToolOutlined,
BarsOutlined,
SearchOutlined
} from '@ant-design/icons';
import File from './components/knowledge-file'
import Setting from './components/knowledge-setting'
import Search from './components/knowledge-search'
import styles from './index.less'
import { getWidth } from '@/utils'
const Index: React.FC = ({ kAModel, dispatch }) => {
const [collapsed, setCollapsed] = useState(false);
const { id, activeKey } = kAModel
const [windowWidth, setWindowWidth] = useState(getWidth());
let navigate = useNavigate();
const location = useLocation();
// 标记一下
useEffect(() => {
const widthSize = () => {
const width = getWidth()
console.log(width)
setWindowWidth(width);
};
window.addEventListener("resize", widthSize);
return () => {
window.removeEventListener("resize", widthSize);
};
}, []);
useEffect(() => {
console.log(location)
const search = location.search.slice(1)
const map = search.split('&').reduce((obj, cur) => {
const [key, value] = cur.split('=')
obj[key] = value
return obj
}, {})
dispatch({
type: 'kAModel/updateState',
payload: {
...map
}
});
}, [location])
useEffect(() => {
if (windowWidth.width > 957) {
setCollapsed(false)
} else {
setCollapsed(true)
}
}, [windowWidth.width])
type MenuItem = Required<MenuProps>['items'][number];
function getItem(
label: React.ReactNode,
key: React.Key,
icon?: React.ReactNode,
children?: MenuItem[],
type?: 'group',
): MenuItem {
return {
key,
icon,
children,
label,
type,
} as MenuItem;
}
const items: MenuItem[] = [
getItem('配置', 'setting', <ToolOutlined />),
getItem('知识库', 'file', <BarsOutlined />),
getItem('搜索测试', 'search', <SearchOutlined />),
];
const handleSelect: MenuProps['onSelect'] = (e) => {
navigate(`/knowledge/add/setting?activeKey=${e.key}&id=${id}`);
}
return (
<>
<div className={styles.container}>
<div className={styles.menu}>
<Menu
selectedKeys={[activeKey]}
mode="inline"
className={windowWidth.width > 957 ? styles.defaultWidth : styles.minWidth}
inlineCollapsed={collapsed}
items={items}
onSelect={handleSelect}
/>
</div>
<div className={styles.content}>
{activeKey === 'file' && <File id={id} />}
{activeKey === 'setting' && <Setting id={id} />}
{activeKey === 'search' && <Search id={id} />}
</div>
</div>
</>
);
};
export default connect(({ kAModel, loading }) => ({ kAModel, loading }))(Index);

+ 34
- 0
web/src/pages/add-knowledge/model.ts Ver arquivo

@@ -0,0 +1,34 @@
import { message } from 'antd';
import { addParam } from '@/utils';
import kbService from '@/services/kbService';
const Model = {
namespace: 'kAModel',
state: {
isShowPSwModal: false,
isShowTntModal: false,
loading: false,
tenantIfo: {},
activeKey: 'setting',
id: ''
},
subscriptions: {
setup({ dispatch, history }) {
history.listen(location => {
});
}
},
effects: {
},
reducers: {
updateState(state, { payload }) {
return {
...state,
...payload
};
}
}
};
export default Model;

+ 19
- 0
web/src/pages/chat/index.tsx Ver arquivo

@@ -0,0 +1,19 @@
import React, { FC } from 'react';
import { IndexModelState, ConnectProps, Loading, connect } from 'umi';
interface PageProps extends ConnectProps {
index: IndexModelState;
loading: boolean;
}
const IndexPage: FC<PageProps> = ({ index, dispatch }) => {
const { name } = index;
return <div>chat: {name}</div>;
};
export default connect(
({ index, loading }: { index: IndexModelState; loading: Loading }) => ({
index,
loading: loading.models.index,
}),
)(IndexPage);

+ 52
- 0
web/src/pages/chat/model.ts Ver arquivo

@@ -0,0 +1,52 @@
import { Effect, ImmerReducer, Reducer, Subscription } from 'umi';
export interface IndexModelState {
name: string;
}
export interface IndexModelType {
namespace: 'index';
state: IndexModelState;
effects: {
query: Effect;
};
reducers: {
save: Reducer<IndexModelState>;
// 启用 immer 之后
// save: ImmerReducer<IndexModelState>;
};
subscriptions: { setup: Subscription };
}
const IndexModel: IndexModelType = {
namespace: 'index',
state: {
name: 'kate',
},
effects: {
*query({ payload }, { call, put }) { },
},
reducers: {
save(state, action) {
return {
...state,
...action.payload,
};
},
// 启用 immer 之后
// save(state, action) {
// state.name = action.payload;
// },
},
subscriptions: {
setup({ dispatch, history }) {
return history.listen((query) => {
console.log(query)
});
},
},
};
export default IndexModel;

+ 51
- 0
web/src/pages/file/index.tsx Ver arquivo

@@ -0,0 +1,51 @@
import React, { useEffect, useState } from 'react';
import { UploadOutlined } from '@ant-design/icons';
import { Button, Upload } from 'antd';
import type { UploadFile } from 'antd/es/upload/interface';
const App: React.FC = () => {
const [fileList, setFileList] = useState([{
uid: '0',
name: 'xxx.png',
status: 'uploading',
percent: 10,
}])
const obj = {
uid: '-1',
name: 'yyy.png',
status: 'done',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
thumbUrl: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
}
useEffect(() => {
const timer = setInterval(() => {
setFileList((fileList) => {
const percent = fileList[0]?.percent
if (percent + 10 >= 100) {
clearInterval(timer)
return [obj]
}
const list = [{ ...fileList[0], percent: percent + 10 }]
console.log(list)
return list
})
}, 300)
}, [])
return (
<>
<Upload
action="https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188"
listType="picture"
fileList={[...fileList]}
multiple
>
<Button icon={<UploadOutlined />}>Upload</Button>
</Upload>
</>
)
};
export default App;

+ 41
- 0
web/src/pages/knowledge/index.less Ver arquivo

@@ -0,0 +1,41 @@
.knowledge {
padding: 24px;
}
.container {
height: 100px;
display: flex;
flex-direction: column;
justify-content: space-between;
.content {
display: flex;
justify-content: space-between;
.context {
flex: 1
}
}
.footer {
height: 20px;
.text {
margin-left: 10px;
}
}
}
.card {
:global {
.ant-card-body {
padding: 10px;
margin: 0;
}
margin-bottom: 10px;
}
cursor: pointer;
}

+ 109
- 0
web/src/pages/knowledge/index.tsx Ver arquivo

@@ -0,0 +1,109 @@
import React, { useEffect, useState, } from 'react';
import { useNavigate, connect } from 'umi'
import { Card, List, Popconfirm, message, FloatButton, Row, Col } from 'antd';
import { MinusSquareOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons';
import styles from './index.less'
import { formatDate } from '@/utils/date'
const dd = [{
title: 'Title 4',
text: '4',
des: '111'
}]
const Index: React.FC = ({ knowledgeModel, dispatch }) => {
const navigate = useNavigate()
// const [datas, setDatas] = useState(data)
const { data } = knowledgeModel
const confirm = (id) => {
dispatch({
type: 'knowledgeModel/rmKb',
payload: {
kb_id: id
},
callback: () => {
dispatch({
type: 'knowledgeModel/getList',
payload: {
}
});
}
});
};
const handleAddKnowledge = () => {
navigate(`add/setting?activeKey=setting`);
}
const handleEditKnowledge = (id: string) => {
navigate(`add/setting?activeKey=file&id=${id}`);
}
useEffect(() => {
dispatch({
type: 'knowledgeModel/getList',
payload: {
}
});
}, [])
return (<>
<div className={styles.knowledge}>
<FloatButton onClick={handleAddKnowledge} icon={<PlusOutlined />} type="primary" style={{ right: 24, top: 100 }} />
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
{
data.map((item, index) => {
return (<Col className="gutter-row" key={item.title} xs={24} sm={12} md={8} lg={6}>
<Card className={styles.card}
onClick={() => { handleEditKnowledge(item.id) }}
>
<div className={styles.container}>
<div className={styles.content}>
<span className={styles.context}>
{item.name}
</span>
<span className={styles.delete}>
<Popconfirm
title="Delete the task"
description="Are you sure to delete this task?"
onConfirm={(e) => {
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation()
confirm(item.id)
}}
okText="Yes"
cancelText="No"
>
<DeleteOutlined onClick={(e) => {
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation()
}} />
</Popconfirm>
</span>
</div>
<div className={styles.footer}>
<span className={styles.text}>
<MinusSquareOutlined />{item.doc_num}文档
</span>
<span className={styles.text}>
<MinusSquareOutlined />{item.chunk_num}个
</span>
<span className={styles.text}>
<MinusSquareOutlined />{item.token_num}千字符
</span>
<span style={{ float: 'right' }}>
{formatDate(item.update_date)}
</span>
</div>
</div>
</Card>
</Col>)
})
}
</Row>
</div>
</>
)
};
export default connect(({ knowledgeModel, loading }) => ({ knowledgeModel, loading }))(Index);

+ 61
- 0
web/src/pages/knowledge/model.ts Ver arquivo

@@ -0,0 +1,61 @@
import { message } from 'antd';
import { addParam } from '@/utils';
import kbService from '@/services/kbService';
const Model = {
namespace: 'knowledgeModel',
state: {
loading: false,
data: []
},
subscriptions: {
setup({ dispatch, history }) {
history.listen(location => {
console.log(location)
});
}
},
effects: {
* rmKb({ payload = {}, callback }, { call, put }) {
const { data, response } = yield call(kbService.rmKb, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
callback && callback()
}
},
*getList({ payload = {} }, { call, put }) {
yield put({
type: 'updateState',
payload: {
loading: true
}
});
const { data, response } = yield call(kbService.getList, payload);
const { retcode, data: res, retmsg } = data
yield put({
type: 'updateState',
payload: {
loading: false
}
});
if (retcode === 0) {
yield put({
type: 'updateState',
payload: {
data: res
}
});
}
},
},
reducers: {
updateState(state, { payload }) {
return {
...state,
...payload
};
}
}
};
export default Model;

+ 63
- 0
web/src/pages/login/index.less Ver arquivo

@@ -0,0 +1,63 @@
@import '../../theme/vars';
.loginPage {
// width: 100%;
display: flex;
.loginLeft {
// width: 610px;
width: 40%;
background-color: #fff;
height: 100vh;
}
@media screen and (max-width:957px) {
.loginLeft {
// width: 610px;
width: 100%;
background-color: #fff;
height: 100vh;
}
.modal {
width: 80%;
}
}
.loginRight {
flex: 1;
background-color: #F2F4F7;
;
}
.loginTitle {
//styleName: Heading/1;
font-family: SF Pro Text;
font-size: 38px;
font-weight: 600;
line-height: 46px;
letter-spacing: 0em;
height: 80px;
margin-bottom: 69px;
// text-align: center;
span {
font-size: 16px;
line-height: 24px;
color: #000000A6;
}
}
}
.modal {
// width: 360px;
width: 60%;
height: 724px;
padding: 5px, 0px, 5px, 0px;
margin: 80px auto
}

+ 157
- 0
web/src/pages/login/index.tsx Ver arquivo

@@ -0,0 +1,157 @@
import { connect, Icon, Dispatch } from 'umi';
import { Input, Form, Button, Checkbox } from 'antd';
import styles from './index.less';
import { rsaPsw } from '@/utils'
import { useState, useEffect, FC } from 'react';
interface LoginProps {
dispatch: Dispatch;
}
const View: FC<LoginProps> = ({
dispatch,
}) => {
const [title, setTitle] = useState('login')
const changeTitle = () => {
setTitle((title) => title === 'login' ? 'register' : 'login')
}
const [form] = Form.useForm();
const [checkNick, setCheckNick] = useState(false);
useEffect(() => {
form.validateFields(['nickname']);
}, [checkNick, form]);
const onCheck = async () => {
try {
const params = await form.validateFields();
var rsaPassWord = rsaPsw(params.password)
if (title === 'login') {
dispatch({
type: 'loginModel/login',
payload: {
email: params.email,
password: rsaPassWord
}
});
} else {
dispatch({
type: 'loginModel/register',
payload: {
nickname: params.nickname,
email: params.email,
password: rsaPassWord,
},
callback() {
setTitle('login')
}
});
}
} catch (errorInfo) {
console.log('Failed:', errorInfo);
}
};
const formItemLayout = {
labelCol: { span: 6 },
// wrapperCol: { span: 8 },
};
const toGoogle = () => {
window.location.href = "https://github.com/login/oauth/authorize?scope=user:email&client_id=302129228f0d96055bee"
}
return (
<div className={styles.loginPage}>
<div className={styles.loginLeft}>
<div className={styles.modal}>
<div className={styles.loginTitle}>
<div>
{title === 'login' ? 'Sign in' : 'Create an account'}
</div>
<span >
{title === 'login' ? 'We’re so excited to see you again!' : 'Glad to have you on board!'}
</span>
</div>
<Form form={form} layout="vertical" name="dynamic_rule" style={{ maxWidth: 600 }}>
<Form.Item
{...formItemLayout}
name="email"
label="Email"
rules={[{ required: true, message: 'Please input your name' }]}
>
<Input size='large' placeholder="Please input your name" />
</Form.Item>
{
title === 'register' && <Form.Item
{...formItemLayout}
name="nickname"
label="Nickname"
rules={[{ required: true, message: 'Please input your nickname' }]}
>
<Input size='large' placeholder="Please input your nickname" />
</Form.Item>
}
<Form.Item
{...formItemLayout}
name="password"
label="Password"
rules={[{ required: true, message: 'Please input your name' }]}
>
<Input size='large' placeholder="Please input your name" />
</Form.Item>
{
title === 'login' && <Form.Item
name="remember"
valuePropName="checked"
>
<Checkbox> Remember me</Checkbox>
</Form.Item>
}
<div> {
title === 'login' && (<div>
Don’t have an account?
<Button type="link" onClick={changeTitle}>
Sign up
</Button>
</div>)
}
{
title === 'register' && (<div>
Already have an account?
<Button type="link" onClick={changeTitle}>
Sign in
</Button>
</div>)
}
</div>
<Button type="primary" block size='large' onClick={onCheck}>
{title === 'login' ? 'Sign in' : 'Continue'}
</Button>
{
title === 'login' && (<><Button block size='large' onClick={toGoogle} style={{ marginTop: 15 }}>
<div >
<Icon icon="local:google" style={{ verticalAlign: 'middle', marginRight: 5 }} />
Sign in with Google
</div>
</Button>
<Button block size='large' onClick={toGoogle} style={{ marginTop: 15 }}>
<div >
<Icon icon="local:github" style={{ verticalAlign: 'middle', marginRight: 5 }} />
Sign in with Github
</div>
</Button></>)
}
</Form>
</div>
</div>
<div className={styles.loginRight}>
</div>
</div>
);
};
export default connect(({ loginModel, loading }) => ({ loginModel, loading }))(View);

+ 61
- 0
web/src/pages/login/model.ts Ver arquivo

@@ -0,0 +1,61 @@
import { message } from 'antd';
import { addParam } from '@/utils';
import userService from '@/services/userService';
const Model = {
namespace: 'loginModel',
state: {
list: [],
info: {},
visible: false,
pagination: {},
campaignInfo: {}
},
subscriptions: {
setup({ dispatch, history }) {
history.listen(location => { });
}
},
effects: {
*login({ payload = {} }, { call, put }) {
console.log(111, payload)
const { data, response } = yield call(userService.login, payload);
const { retcode, data: res, retmsg } = data
console.log()
const Authorization = response.headers.get('Authorization')
if (retcode === 0) {
message.success('登录成功!');
const token = res.access_token;
const userInfo = {
avatar: res.avatar,
name: res.nickname,
email: res.email
};
localStorage.setItem('token', token)
localStorage.setItem('userInfo', JSON.stringify(userInfo))
localStorage.setItem('Authorization', Authorization)
setTimeout(() => {
window.location.href = '/file';
}, 300);
}
},
*register({ payload = {}, callback }, { call, put }) {
const { data, response } = yield call(userService.register, payload);
console.log()
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
message.success('注册成功!');
callback && callback()
}
}
},
reducers: {
updateState(state, { payload }) {
return {
...state,
...payload
};
}
}
};
export default Model;

+ 92
- 0
web/src/pages/setting/CPwModal.tsx Ver arquivo

@@ -0,0 +1,92 @@
import { connect, Dispatch } from 'umi';
import i18n from 'i18next';
import { useTranslation, Trans } from 'react-i18next'
import { Input, Modal, Form } from 'antd'
import { rsaPsw } from '@/utils'
import styles from './index.less';
import { FC } from 'react';
type FieldType = {
newPassword?: string;
password?: string;
};
interface CPwModalProps {
dispatch: Dispatch;
settingModel: any
}
const Index: FC<CPwModalProps> = ({ settingModel, dispatch }) => {
const { isShowPSwModal } = settingModel
const { t } = useTranslation()
const handleCancel = () => {
dispatch({
type: 'settingModel/updateState',
payload: {
isShowPSwModal: false
}
});
};
const [form] = Form.useForm()
const handleOk = async () => {
try {
const values = await form.validateFields();
var password = rsaPsw(values.password)
var new_password = rsaPsw(values.newPassword)
dispatch({
type: 'settingModel/setting',
payload: {
password,
new_password
},
callback: () => {
dispatch({
type: 'settingModel/updateState',
payload: {
isShowPSwModal: false
}
});
dispatch({
type: 'settingModel/getUserInfo',
payload: {
}
});
}
});
} catch (errorInfo) {
console.log('Failed:', errorInfo);
}
};
return (
<Modal title="Basic Modal" open={isShowPSwModal} onOk={handleOk} onCancel={handleCancel}>
<Form
form={form}
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
style={{ maxWidth: 600 }}
autoComplete="off"
>
<Form.Item<FieldType>
label="旧密码"
name="password"
rules={[{ required: true, message: 'Please input your password!' }]}
>
<Input.Password />
</Form.Item>
<Form.Item<FieldType>
label="新密码"
name="newPassword"
rules={[{ required: true, message: 'Please input your newPassword!' }]}
>
<Input.Password />
</Form.Item>
</Form>
</Modal >
);
}
export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index);

+ 197
- 0
web/src/pages/setting/List.tsx Ver arquivo

@@ -0,0 +1,197 @@
import { connect, Dispatch } from 'umi';
import i18n from 'i18next';
import { useTranslation, Trans } from 'react-i18next'
import styles from './index.less';
import type { ColumnsType } from 'antd/es/table';
import { useEffect, useState, FC } from 'react';
import { RadarChartOutlined } from '@ant-design/icons';
import { ProCard } from '@ant-design/pro-components';
import { Button, Tag, Row, Col, Card } from 'antd';
import { divide } from 'lodash';
interface DataType {
key: React.Key;
name: string;
age: number;
address: string;
description: string;
}
interface ListProps {
dispatch: Dispatch;
settingModel: any
}
const Index: FC<ListProps> = ({ settingModel, dispatch }) => {
const { llmInfo = {}, factoriesList, myLlm = [] } = settingModel
const { OpenAI = [], tongyi = [] } = llmInfo
console.log(OpenAI)
const [collapsed, setCollapsed] = useState(true);
const { t } = useTranslation()
const columns: ColumnsType<DataType> = [
{ title: 'Name', dataIndex: 'name', key: 'name' },
{ title: 'Age', dataIndex: 'age', key: 'age' },
{
title: 'Action',
dataIndex: '',
key: 'x',
render: () => <a>Delete</a>,
},
];
useEffect(() => {
dispatch({
type: 'settingModel/factories_list',
payload: {
},
});
dispatch({
type: 'settingModel/llm_list',
payload: {
},
});
dispatch({
type: 'settingModel/my_llm',
payload: {
},
});
}, [])
const data: DataType[] = [
{
key: 1,
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
description: 'My name is John Brown, I am 32 years old, living in New York No. 1 Lake Park.',
},
{
key: 2,
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
description: 'My name is Jim Green, I am 42 years old, living in London No. 1 Lake Park.',
},
{
key: 3,
name: 'Not Expandable',
age: 29,
address: 'Jiangsu No. 1 Lake Park',
description: 'This not expandable',
},
{
key: 4,
name: 'Joe Black',
age: 32,
address: 'Sydney No. 1 Lake Park',
description: 'My name is Joe Black, I am 32 years old, living in Sydney No. 1 Lake Park.',
},
];
return (
<div
className={styles.list}
style={{
display: 'flex',
flexDirection: 'column',
padding: 24,
gap: 12,
}}
>
{
myLlm.map((item: any) => {
return (<ProCard
key={item.llm_factory}
// title={<div>可折叠-图标自定义</div>}
collapsibleIconRender={({
collapsed: buildInCollapsed,
}: {
collapsed: boolean;
}) => {
return (<div>
<h3><RadarChartOutlined />{item.llm_factory}</h3>
<div>{item.tags.split(',').map((d: string) => {
return <Tag key={d}>{d}</Tag>
})}</div>
{
buildInCollapsed ? <span>显示{OpenAI.length}个模型</span> : <span>收起{OpenAI.length}个模型 </span>
}
</div>)
}}
extra={
<Button
size="small"
type='link'
onClick={(e) => {
e.stopPropagation();
dispatch({
type: 'settingModel/updateState',
payload: {
llm_factory: item.llm_factory,
isShowSAKModal: true
}
});
}}
>
设置
</Button>
}
style={{ marginBlockStart: 16 }}
headerBordered
collapsible
defaultCollapsed
>
{/* <ul>
{OpenAI.map(item => {
return <li key={item.llm_name}>
<span>{item.llm_name}</span>
<span className={styles[item.available ? 'statusAvailable' : 'statusDisaabled']}>
</span>
</li>
})}
</ul> */}
</ProCard>)
})
}
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
{
factoriesList.map((item: any) => {
return (<Col key={item.name} xs={24} sm={12} md={8} lg={6}>
<Card title={item.name} bordered={false} extra={
<Button
size="small"
type='link'
onClick={(e) => {
e.stopPropagation();
dispatch({
type: 'settingModel/updateState',
payload: {
llm_factory: item.name,
isShowSAKModal: true
}
});
}}
>
设置
</Button>
}>
<div>
{
item.tags.split(',').map((d: string) => {
return <Tag key={d}>{d}</Tag>
})
}
</div>
</Card>
</Col>)
})
}
</Row>
</div>
);
}
export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index);

+ 84
- 0
web/src/pages/setting/SAKModal.tsx Ver arquivo

@@ -0,0 +1,84 @@
import { connect, Dispatch } from 'umi';
import i18n from 'i18next';
import { FC } from 'react'
import { useTranslation, Trans } from 'react-i18next'
import { Input, Modal, Form } from 'antd'
import { rsaPsw } from '@/utils'
import styles from './index.less';
type FieldType = {
api_key?: string;
};
interface SAKModalProps {
dispatch: Dispatch;
settingModel: any
}
const Index: FC<SAKModalProps> = ({ settingModel, dispatch }) => {
const { isShowSAKModal, llm_factory } = settingModel
console.log(llm_factory)
const { t } = useTranslation()
const handleCancel = () => {
dispatch({
type: 'settingModel/updateState',
payload: {
isShowSAKModal: false
}
});
};
const [form] = Form.useForm()
const handleOk = async () => {
try {
const values = await form.validateFields();
dispatch({
type: 'settingModel/set_api_key',
payload: {
api_key: values.api_key,
llm_factory: llm_factory
},
callback: () => {
dispatch({
type: 'settingModel/updateState',
payload: {
isShowSAKModal: false
}
});
// dispatch({
// type: 'settingModel/getUserInfo',
// payload: {
// }
// });
}
});
} catch (errorInfo) {
console.log('Failed:', errorInfo);
}
};
return (
<Modal title="Basic Modal" open={isShowSAKModal} onOk={handleOk} onCancel={handleCancel}>
<Form
form={form}
name="validateOnly"
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
style={{ maxWidth: 600 }}
autoComplete="off"
>
<Form.Item<FieldType>
label="API Key"
name="api_key"
rules={[{ required: true, message: 'Please input ' }]}
>
<Input />
</Form.Item>
</Form>
</Modal >
);
}
export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index);

+ 153
- 0
web/src/pages/setting/SSModal.tsx Ver arquivo

@@ -0,0 +1,153 @@
import { connect, Dispatch } from 'umi';
import { FC } from 'react'
import i18n from 'i18next';
import { useTranslation, Trans } from 'react-i18next'
import { Input, Modal, Form, Select } from 'antd'
import { rsaPsw } from '@/utils'
import styles from './index.less';
type FieldType = {
embd_id?: string;
img2txt_id?: string;
llm_id?: string;
asr_id?: string
};
interface SSModalProps {
dispatch: Dispatch;
settingModel: any
}
const Index: FC<SSModalProps> = ({ settingModel, dispatch }) => {
const { isShowSSModal, llmInfo = {}, tenantIfo } = settingModel
const { t } = useTranslation()
const handleCancel = () => {
dispatch({
type: 'settingModel/updateState',
payload: {
isShowSSModal: false
}
});
};
const [form] = Form.useForm()
const handleOk = async () => {
try {
const values = await form.validateFields();
console.log(values)
dispatch({
type: 'settingModel/set_tenant_info',
payload: {
...values,
tenant_id: tenantIfo.tenant_id,
},
callback: () => {
dispatch({
type: 'settingModel/updateState',
payload: {
isShowSSModal: false
}
});
// dispatch({
// type: 'settingModel/getUserInfo',
// payload: {
// }
// });
}
});
} catch (errorInfo) {
console.log('Failed:', errorInfo);
}
};
const handleChange = () => {
}
return (
<Modal title="Basic Modal" open={isShowSSModal} onOk={handleOk} onCancel={handleCancel}>
<Form
form={form}
name="validateOnly"
// labelCol={{ span: 8 }}
// wrapperCol={{ span: 16 }}
style={{ maxWidth: 600 }}
autoComplete="off"
layout="vertical"
>
<Form.Item<FieldType>
label="embedding 模型"
name="embd_id"
rules={[{ required: true, message: 'Please input your password!' }]}
initialValue={tenantIfo.embd_id}
>
<Select
// style={{ width: 200 }}
onChange={handleChange}
// fieldNames={label:}
options={Object.keys(llmInfo).map(t => {
const options = llmInfo[t].filter((d: any) => d.model_type === 'embedding').map((d: any) => ({ label: d.llm_name, value: d.llm_name, }))
return { label: t, options }
})}
/>
</Form.Item>
<Form.Item<FieldType>
label="chat 模型"
name="llm_id"
rules={[{ required: true, message: 'Please input your password!' }]}
initialValue={tenantIfo.llm_id}
>
<Select
// style={{ width: 200 }}
onChange={handleChange}
// fieldNames={label:}
options={Object.keys(llmInfo).map(t => {
const options = llmInfo[t].filter((d: any) => d.model_type === 'chat').map((d: any) => ({ label: d.llm_name, value: d.llm_name, }))
return { label: t, options }
})}
/>
</Form.Item>
<Form.Item<FieldType>
label="image2text 模型"
name="img2txt_id"
rules={[{ required: true, message: 'Please input your password!' }]}
initialValue={tenantIfo.img2txt_id}
>
<Select
// style={{ width: 200 }}
onChange={handleChange}
// fieldNames={label:}
options={Object.keys(llmInfo).map(t => {
const options = llmInfo[t].filter((d: any) => d.model_type === 'image2text').map((d: any) => ({ label: d.llm_name, value: d.llm_name, }))
return { label: t, options }
})}
/>
</Form.Item>
<Form.Item<FieldType>
label="speech2text 模型"
name="asr_id"
rules={[{ required: true, message: 'Please input your password!' }]}
initialValue={tenantIfo.asr_id}
>
<Select
// style={{ width: 200 }}
onChange={handleChange}
// fieldNames={label:}
options={Object.keys(llmInfo).map(t => {
const options = llmInfo[t].filter((d: any) => d.model_type === 'speech2text').map((d: any) => ({ label: d.llm_name, value: d.llm_name, }))
return { label: t, options }
})}
/>
</Form.Item>
</Form>
</Modal >
);
}
export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index);

+ 58
- 0
web/src/pages/setting/TntModal.tsx Ver arquivo

@@ -0,0 +1,58 @@
import { connect, Dispatch } from 'umi';
import { FC } from 'react'
import i18n from 'i18next';
import { useTranslation, Trans } from 'react-i18next'
import { Modal, Table } from 'antd'
import styles from './index.less';
import type { ColumnsType } from 'antd/es/table';
interface DataType {
key: React.Key;
name: string;
role: string;
time: string;
}
interface TntodalProps {
dispatch: Dispatch;
settingModel: any
}
const Index: FC<TntodalProps> = ({ settingModel, dispatch }) => {
const { isShowTntModal, tenantIfo, loading, factoriesList } = settingModel
const { t } = useTranslation()
const handleCancel = () => {
dispatch({
type: 'settingModel/updateState',
payload: {
isShowTntModal: false
}
});
};
console.log(tenantIfo)
const handleOk = async () => {
dispatch({
type: 'settingModel/updateState',
payload: {
isShowTntModal: false
}
});
};
const columns: ColumnsType<DataType> = [
{ title: '姓名', dataIndex: 'name', key: 'name' },
{ title: '活动时间', dataIndex: 'update_date', key: 'update_date' },
{ title: '角色', dataIndex: 'role', key: 'age' },
];
return (
<Modal title="用户" open={isShowTntModal} onOk={handleOk} onCancel={handleCancel}>
<div className={styles.tenantIfo}>
{tenantIfo.name}
</div>
<Table rowKey='name' loading={loading} columns={columns} dataSource={factoriesList} />
</Modal >
);
}
export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index);

+ 49
- 0
web/src/pages/setting/index.less Ver arquivo

@@ -0,0 +1,49 @@
.settingPage {
padding: 10px;
}
.avatar {
display: flex;
justify-content: center;
}
.tenantIfo {
height: 50px;
background-color: #f4dfdf;
margin-bottom: 10px;
padding: 5px;
box-sizing: border-box;
display: flex;
align-items: center;
}
.list {
:global {
.ant-pro-card-header {
height: 150px;
background-color: rgb(229, 231, 235);
}
}
}
ul {
li {
display: flex;
justify-content: space-between;
margin-bottom: 5px;
.statusDisaabled {
width: 10px;
height: 10px;
border-radius: 40%;
background: rgba(0, 0, 0, 0.4);
}
.statusAvailable {
width: 10px;
height: 10px;
border-radius: 50%;
background: green;
}
}
}

+ 90
- 0
web/src/pages/setting/index.tsx Ver arquivo

@@ -0,0 +1,90 @@
import { connect, Dispatch } from 'umi';
import i18n from 'i18next';
import { useTranslation, Trans } from 'react-i18next'
import { Button, Input, Modal, Form, FloatButton, Table } from 'antd'
import styles from './index.less';
import CPwModal from './CPwModal'
import SAKModal from './SAKModal'
import TntModal from './TntModal'
import SSModal from './SSModal'
import List from './List'
import { useEffect, useState, FC } from 'react';
interface CPwModalProps {
dispatch: Dispatch;
settingModel: any
}
const Index: FC<CPwModalProps> = ({ settingModel, dispatch }) => {
// const [llm_factory, set_llm_factory] = useState('')
const { t } = useTranslation()
const userInfo = JSON.parse(localStorage.getItem('userInfo') || '')
const changeLang = (val: string) => { // 改变状态里的 语言 进行切换
i18n.changeLanguage(val);
}
useEffect(() => {
dispatch({
type: 'settingModel/getTenantInfo',
payload: {
}
});
}, [])
const showCPwModal = () => {
dispatch({
type: 'settingModel/updateState',
payload: {
isShowPSwModal: true
}
});
};
const showTntModal = () => {
dispatch({
type: 'settingModel/updateState',
payload: {
isShowTntModal: true
}
});
};
const showSSModal = () => {
dispatch({
type: 'settingModel/updateState',
payload: {
isShowSSModal: true
}
});
// dispatch({
// type: 'settingModel/getTenantInfo',
// payload: {
// }
// });
};
return (
<div className={styles.settingPage}>
<div className={styles.avatar}>
<img style={{ width: 50, marginRight: 5 }} src="https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png" alt="" />
<div>
<div>账号:{userInfo.name}</div>
<div><span>密码:******</span><Button type='link' onClick={showCPwModal}>修改密码</Button></div>
</div>
</div >
<div>
<Button type="link" onClick={showTntModal}>
租户
</Button>
<Button type="link" onClick={showSSModal}>
系统模型设置
</Button>
<List />
</div>
<CPwModal />
<SAKModal />
<SSModal />
<TntModal />
<FloatButton shape='square' description={t('setting.btn')} onClick={() => i18n.changeLanguage(i18n.language == 'en' ? 'zh' : 'en')} type="default" style={{ right: 94, fontSize: 14 }} />
</div >
);
}
export default connect(({ settingModel, loading }) => ({ settingModel, loading }))(Index);

+ 181
- 0
web/src/pages/setting/model.ts Ver arquivo

@@ -0,0 +1,181 @@
import { Effect, Reducer, Subscription } from 'umi';
import { message } from 'antd';
import { addParam } from '@/utils';
import userService from '@/services/userService';
import { rearg } from 'lodash';
export interface settingModelState {
isShowPSwModal: boolean;
isShowTntModal: boolean;
isShowSAKModal: boolean;
isShowSSModal: boolean;
llm_factory: string;
loading: boolean;
tenantIfo: any,
llmInfo: any,
myLlm: any[],
factoriesList: any[]
}
export interface settingModelType {
namespace: 'settingModel';
state: settingModelState;
effects: {
setting: Effect;
getUserInfo: Effect;
getTenantInfo: Effect;
set_tenant_info: Effect;
factories_list: Effect;
llm_list: Effect;
my_llm: Effect;
set_api_key: Effect;
};
reducers: {
updateState: Reducer<settingModelState>;
};
subscriptions: { setup: Subscription };
}
const Model: settingModelType = {
namespace: 'settingModel',
state: {
isShowPSwModal: false,
isShowTntModal: false,
isShowSAKModal: false,
isShowSSModal: false,
llm_factory: '',
loading: false,
tenantIfo: {},
llmInfo: {},
myLlm: [],
factoriesList: []
},
subscriptions: {
setup({ dispatch, history }) {
history.listen(location => {
});
}
},
effects: {
*setting({ payload = {}, callback }, { call, put }) {
const { data, response } = yield call(userService.setting, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
message.success('密码修改成功!');
callback && callback()
}
},
*getUserInfo({ payload = {} }, { call, put }) {
const { data, response } = yield call(userService.user_info, payload);
const { retcode, data: res, retmsg } = data
const userInfo = {
avatar: res.avatar,
name: res.nickname,
email: res.email
};
localStorage.setItem('userInfo', JSON.stringify(userInfo))
if (retcode === 0) {
// localStorage.setItem('userInfo',res.)
}
},
*getTenantInfo({ payload = {} }, { call, put }) {
yield put({
type: 'updateState',
payload: {
loading: true
}
});
const { data, response } = yield call(userService.get_tenant_info, payload);
const { retcode, data: res, retmsg } = data
// llm_id 对应chat_id
// asr_id 对应speech2txt
yield put({
type: 'updateState',
payload: {
loading: false
}
});
if (retcode === 0) {
res.chat_id = res.llm_id
res.speech2text_id = res.asr_id
yield put({
type: 'updateState',
payload: {
tenantIfo: res
}
});
}
},
*set_tenant_info({ payload = {} }, { call, put }) {
const { data, response } = yield call(userService.set_tenant_info, payload);
const { retcode, data: res, retmsg } = data
// llm_id 对应chat_id
// asr_id 对应speech2txt
if (retcode === 0) {
yield put({
type: 'updateState',
payload: {
isShowSSModal: false
}
});
yield put({
type: 'getTenantInfo'
})
}
},
*factories_list({ payload = {} }, { call, put }) {
const { data, response } = yield call(userService.factories_list, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
yield put({
type: 'updateState',
payload: {
factoriesList: res
}
});
}
},
*llm_list({ payload = {} }, { call, put }) {
const { data, response } = yield call(userService.llm_list, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
yield put({
type: 'updateState',
payload: {
llmInfo: res
}
});
}
},
*my_llm({ payload = {} }, { call, put }) {
const { data, response } = yield call(userService.my_llm, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
yield put({
type: 'updateState',
payload: {
myLlm: res
}
});
}
},
*set_api_key({ payload = {}, callback }, { call, put }) {
const { data, response } = yield call(userService.set_api_key, payload);
const { retcode, data: res, retmsg } = data
if (retcode === 0) {
message.success('设置API KEY成功!');
callback && callback()
}
},
},
reducers: {
updateState(state, { payload }) {
return {
...state,
...payload
};
}
}
};
export default Model;

+ 70
- 0
web/src/services/kbService.ts Ver arquivo

@@ -0,0 +1,70 @@
import api from '@/utils/api';
import registerServer from '@/utils/registerServer';
import request from '@/utils/request';
const {
create_kb,
update_kb,
rm_kb,
get_kb_detail,
kb_list, get_document_list, document_change_status, document_rm, document_create, document_change_parser } = api;
interface kbService {
createKb: () => void;
updateKb: () => void;
rmKb: () => void;
get_kb_detail: () => void;
getList: () => void;
get_document_list: () => void;
document_change_status: () => void;
document_rm: () => void;
document_create: () => void;
document_change_parser: () => void;
}
const kbService: kbService = registerServer(
{
createKb: {
url: create_kb,
method: 'post'
},
updateKb: {
url: update_kb,
method: 'post'
},
rmKb: {
url: rm_kb,
method: 'post'
},
get_kb_detail: {
url: get_kb_detail,
method: 'get'
},
getList: {
url: kb_list,
method: 'get'
},
get_document_list: {
url: get_document_list,
method: 'get'
},
document_change_status: {
url: document_change_status,
method: 'post'
},
document_rm: {
url: document_rm,
method: 'post'
},
document_create: {
url: document_create,
method: 'post'
},
document_change_parser: {
url: document_change_parser,
method: 'post'
},
},
request
);
export default kbService;

+ 21
- 0
web/src/services/uploadService.ts Ver arquivo

@@ -0,0 +1,21 @@
import request from '@/utils/request';
import api from '@/utils/api';
const { upload } = api;
const uploadService = {
uploadFile: function (file, kb_id) {
const formData = new FormData();
formData.append('file', file);
formData.append('kb_id', kb_id);
const options = {
method: 'post',
data: formData
};
return request(upload, options);
}
};
export default uploadService;

+ 57
- 0
web/src/services/userService.ts Ver arquivo

@@ -0,0 +1,57 @@
import api from '@/utils/api';
import registerServer from '@/utils/registerServer';
import request from '@/utils/request';
const {
login, register, setting, user_info, tenant_info, factories_list, llm_list, my_llm, set_api_key, set_tenant_info } = api;
interface userServiceType {
login: (params: any) => void
}
const userService = registerServer(
{
login: {
url: login,
method: 'post',
},
register: {
url: register,
method: 'post'
},
setting: {
url: setting,
method: 'post'
},
user_info: {
url: user_info,
method: 'get'
},
get_tenant_info: {
url: tenant_info,
method: 'get'
},
set_tenant_info: {
url: set_tenant_info,
method: 'post'
},
factories_list: {
url: factories_list,
method: 'get'
},
llm_list: {
url: llm_list,
method: 'get'
},
my_llm: {
url: my_llm,
method: 'get'
},
set_api_key: {
url: set_api_key,
method: 'post'
},
},
request
);
export default userService;

+ 11
- 0
web/src/theme/theme.ts Ver arquivo

@@ -0,0 +1,11 @@
module.exports = {
'primary-color': '#338AFF', // '#338AFF',
'border-radius-base': '4px',
// 'menu-dark-color': '',
// 'menu-dark-danger-color': '',
'menu-dark-bg': '#092140',
'menu-dark-item-active-bg': '#092140'
// 'menu-dark-arrow-color': '',
// 'menu-dark-inline-submenu-bg': '',
};

+ 9
- 0
web/src/theme/vars.less Ver arquivo

@@ -0,0 +1,9 @@
@header-height: 64px;
@menu-width: 200px;
@menu-small-width: 83px;
@layout-bg: #f2f3f6;
@logo-font-size: 22px;
@border-color: #d9d9d9;
@dashboard-desc-color: #9d9fa2;
@primary-color: #338aff;
@primary-color-light: rgba(21, 65, 255, 0.5);

+ 42
- 0
web/src/utils/api.ts Ver arquivo

@@ -0,0 +1,42 @@
let api_host = `/v1`;
export { api_host };
export default {
// 用户
login: `${api_host}/user/login`,
register: `${api_host}/user/register`,
setting: `${api_host}/user/setting`,
user_info: `${api_host}/user/info`,
tenant_info: `${api_host}/user/tenant_info`,
set_tenant_info: `${api_host}/user/set_tenant_info`,
// 模型管理
factories_list: `${api_host}/llm/factories`,
llm_list: `${api_host}/llm/list`,
my_llm: `${api_host}/llm/my_llms`,
set_api_key: `${api_host}/llm/set_api_key`,
//知识库管理
kb_list: `${api_host}/kb/list`,
create_kb: `${api_host}/kb/create`,
update_kb: `${api_host}/kb/update`,
rm_kb: `${api_host}/kb/rm`,
get_kb_detail: `${api_host}/kb/detail`,
// 上传
upload: `${api_host}/document/upload`,
get_document_list: `${api_host}/document/list`,
document_change_status: `${api_host}/document/change_status`,
document_rm: `${api_host}/document/rm`,
document_create: `${api_host}/document/create`,
document_change_parser: `${api_host}/document/change_parser`,
};

+ 20
- 0
web/src/utils/date.ts Ver arquivo

@@ -0,0 +1,20 @@
import moment from 'moment';
export function today() {
return formatDate(moment());
}
export function lastDay() {
return formatDate(moment().subtract(1, 'days'));
}
export function lastWeek() {
return formatDate(moment().subtract(1, 'weeks'));
}
export function formatDate(date) {
if (!date) {
return '';
}
return moment(date).format('YYYY-MM-DD');
}

+ 14
- 0
web/src/utils/hooks.ts Ver arquivo

@@ -0,0 +1,14 @@
import { useState } from 'react';
export const usePagination = function (defaultPage: number, defaultPageSize: number, total: number) {
const [page = 1, setPage] = useState(defaultPage);
const [pageSize = 10, setPageSize] = useState(defaultPageSize);
return {
page,
pageSize,
count: total,
setPage,
setPageSize,
nextPage: () => setPage(page + 1)
};
};

+ 26
- 0
web/src/utils/index.ts Ver arquivo

@@ -0,0 +1,26 @@
/**
* @param {String} url
* @param {Boolean} isNoCaseSensitive 是否区分大小写
* @return {Object}
*/
// import numeral from 'numeral';
import JSEncrypt from 'jsencrypt';
import { Base64 } from 'js-base64';
export const getWidth = () => {
return { width: window.innerWidth };
};
export const rsaPsw = (password: string) => {
const pub = "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArq9XTUSeYr2+N1h3Afl/z8Dse/2yD0ZGrKwx+EEEcdsBLca9Ynmx3nIB5obmLlSfmskLpBo0UACBmB5rEjBp2Q2f3AG3Hjd4B+gNCG6BDaawuDlgANIhGnaTLrIqWrrcm4EMzJOnAOI1fgzJRsOOUEfaS318Eq9OVO3apEyCCt0lOQK6PuksduOjVxtltDav+guVAA068NrPYmRNabVKRNLJpL8w4D44sfth5RvZ3q9t+6RTArpEtc5sh5ChzvqPOzKGMXW83C95TxmXqpbK6olN4RevSfVjEAgCydH6HN6OhtOQEcnrU97r9H0iZOWwbw3pVrZiUkuRD1R56Wzs2wIDAQAB-----END PUBLIC KEY-----"
const encryptor = new JSEncrypt()
encryptor.setPublicKey(pub)
return encryptor.encrypt(Base64.encode(password))
}
export default {
getWidth,
rsaPsw
};

+ 22
- 0
web/src/utils/registerServer.ts Ver arquivo

@@ -0,0 +1,22 @@
const registerServer = (opt: any, request: any): any => {
let server = {};
for (let key in opt) {
server[key] = (params: any) => {
if (opt[key].method === 'post' || opt[key].method === 'POST') {
return request(opt[key].url, {
method: opt[key].method,
data: params
});
}
if (opt[key].method === 'get' || opt[key].method === 'GET') {
return request.get(opt[key].url, {
params
});
}
};
}
return server;
};
export default registerServer;

+ 116
- 0
web/src/utils/request.ts Ver arquivo

@@ -0,0 +1,116 @@
import { extend } from 'umi-request';
import { notification, message } from 'antd';
import _ from 'lodash';
import api from '@/utils/api';
const { login } = api;
const ABORT_REQUEST_ERR_MESSAGE = 'The user aborted a request.'; // 手动中断请求。errorHandler 抛出的error message
const retcodeMessage = {
200: '服务器成功返回请求的数据。',
201: '新建或修改数据成功。',
202: '一个请求已经进入后台排队(异步任务)。',
204: '删除数据成功。',
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
401: '用户没有权限(令牌、用户名、密码错误)。',
403: '用户得到授权,但是访问是被禁止的。',
404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
406: '请求的格式不可得。',
410: '请求的资源被永久删除,且不会再得到的。',
422: '当创建一个对象时,发生一个验证错误。',
500: '服务器发生错误,请检查服务器。',
502: '网关错误。',
503: '服务不可用,服务器暂时过载或维护。',
504: '网关超时。'
};
/**
* 异常处理程序
*/
const errorHandler = (error: any) => {
const { response } = error;
// 手动中断请求 abort
if (error.message === ABORT_REQUEST_ERR_MESSAGE) {
console.log('user abort request');
} else {
if (response && response.status) {
const errorText = retcodeMessage[response.status] || response.statusText;
const { status, url } = response;
notification.error({
message: `请求错误 ${status}: ${url}`,
description: errorText,
});
} else if (!response) {
notification.error({
description: '您的网络发生异常,无法连接服务器',
message: '网络异常',
});
}
}
return response;
};
/**
* 配置request请求时的默认参数
*/
const request = extend({
errorHandler, // 默认错误处理
// credentials: 'include', // 默认请求是否带上cookie
timeout: 3000000,
getResponse: true
});
request.interceptors.request.use((url, options) => {
let prefix = '';
console.log(url)
const Authorization = localStorage.getItem('Authorization')
return {
url,
options: {
...options,
headers: {
...(options.skipToken ? undefined : { Authorization }),
...options.headers
},
interceptors: true
}
};
});
/*
* 请求response拦截器
* */
request.interceptors.response.use(async (response, request) => {
console.log(response, request)
const data = await response.clone().json();
// response 拦截
if (data.retcode === 401 || data.retcode === 401) {
notification.error({
message: data.retmsg,
description: data.retmsg,
duration: 3,
});
} else if (data.retcode !== 0) {
if (data.retcode === 100) {
message.error(data.retmsg);
} else {
notification.error({
message: `提示 : ${data.retcode}`,
description: data.retmsg,
duration: 3,
});
}
return response;
} else {
return response;
}
});
export default request;

+ 12
- 0
web/src/wrappers/auth.tsx Ver arquivo

@@ -0,0 +1,12 @@
import { Navigate, Outlet } from 'umi'
export default (props) => {
// const { isLogin } = useAuth();
console.log(props)
const isLogin = false
if (isLogin) {
return <Outlet />;
} else {
return <Navigate to="/login" />;
}
}

+ 6
- 0
web/tsconfig.json Ver arquivo

@@ -0,0 +1,6 @@
{
"extends": "./src/.umi/tsconfig.json",
"@@/*": [
"src/.umi/*"
]
}

+ 2
- 0
web/typings.d.ts Ver arquivo

@@ -0,0 +1,2 @@
import 'umi/typings';
declare module 'lodash'

Carregando…
Cancelar
Salvar