Skip to content

Commit a7f5147

Browse files
committed
feat chat ui
1 parent f7349d2 commit a7f5147

File tree

9 files changed

+197
-10
lines changed

9 files changed

+197
-10
lines changed

apps/application/flow/common.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,7 @@ def new_instance(flow_obj: Dict):
175175
return Workflow(nodes, edges)
176176

177177
def get_start_node(self):
178-
start_node_list = [node for node in self.nodes if node.id == 'start-node']
179-
return start_node_list[0]
178+
return self.get_node('start-node')
180179

181180
def get_search_node(self):
182181
return [node for node in self.nodes if node.type == 'search-dataset-node']

ui/chat.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!doctype html>
2+
<html lang="">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" href="/favicon.ico" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<base target="_blank" />
8+
<title>%VITE_APP_TITLE%</title>
9+
</head>
10+
<body>
11+
<div id="app"></div>
12+
<script type="module" src="/src/chat.ts"></script>
13+
</body>
14+
</html>

ui/env/.env

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
VITE_APP_NAME=ui
22
VITE_BASE_PATH=/ui/
33
VITE_APP_PORT=3000
4-
VITE_APP_TITLE = 'MaxKB'
4+
VITE_APP_TITLE = 'MaxKB'
5+
VITE_INPUT="index.html"

ui/env/.env.chat

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
VITE_APP_NAME=chat
2+
VITE_BASE_PATH=/chat/
3+
VITE_APP_PORT=3000
4+
VITE_APP_TITLE = 'MaxKB'
5+
VITE_INPUT="chat.html"

ui/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
"type": "module",
66
"scripts": {
77
"dev": "vite",
8+
"chat": "vite --mode chat",
89
"build": "run-p type-check \"build-only {@}\" --",
10+
"build-chat": "run-p type-check \"build-only-chat {@}\" --",
911
"preview": "vite preview",
1012
"build-only": "vite build",
13+
"build-only-chat": "vite build --mode chat",
1114
"type-check": "vue-tsc --build",
1215
"lint": "eslint . --fix",
1316
"format": "prettier --write src/"
@@ -39,6 +42,7 @@
3942
"screenfull": "^6.0.2",
4043
"sortablejs": "^1.15.6",
4144
"use-element-plus-theme": "^0.0.5",
45+
"vite-plugin-html": "^3.2.2",
4246
"vue": "^3.5.13",
4347
"vue-clipboard3": "^2.0.0",
4448
"vue-codemirror": "^6.1.1",

ui/src/chat.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import '@/styles/index.scss'
2+
import ElementPlus from 'element-plus'
3+
import * as ElementPlusIcons from '@element-plus/icons-vue'
4+
import zhCn from 'element-plus/es/locale/lang/zh-cn'
5+
import enUs from 'element-plus/es/locale/lang/en'
6+
import zhTW from 'element-plus/es/locale/lang/zh-tw'
7+
import { createApp } from 'vue'
8+
import { createPinia } from 'pinia'
9+
import App from './App.vue'
10+
import router from '@/router/chat'
11+
import i18n from '@/locales'
12+
import Components from '@/components'
13+
import directives from '@/directives'
14+
15+
import { config } from 'md-editor-v3'
16+
import screenfull from 'screenfull'
17+
18+
import katex from 'katex'
19+
import 'katex/dist/katex.min.css'
20+
21+
import Cropper from 'cropperjs'
22+
23+
import mermaid from 'mermaid'
24+
25+
import highlight from 'highlight.js'
26+
import 'highlight.js/styles/atom-one-dark.css'
27+
28+
config({
29+
editorExtensions: {
30+
highlight: {
31+
instance: highlight,
32+
},
33+
screenfull: {
34+
instance: screenfull,
35+
},
36+
katex: {
37+
instance: katex,
38+
},
39+
cropper: {
40+
instance: Cropper,
41+
},
42+
mermaid: {
43+
instance: mermaid,
44+
},
45+
},
46+
})
47+
const app = createApp(App)
48+
app.use(createPinia())
49+
for (const [key, component] of Object.entries(ElementPlusIcons)) {
50+
app.component(key, component)
51+
}
52+
const locale_map: any = {
53+
'zh-CN': zhCn,
54+
'zh-Hant': zhTW,
55+
'en-US': enUs,
56+
}
57+
app.use(ElementPlus, {
58+
locale: locale_map[localStorage.getItem('MaxKB-locale') || navigator.language || 'en-US'],
59+
})
60+
app.use(directives)
61+
app.use(router)
62+
app.use(i18n)
63+
app.use(Components)
64+
app.mount('#app')
65+
export { app }

ui/src/router/chat/index.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { hasPermission } from '@/utils/permission/index'
2+
import NProgress from 'nprogress'
3+
import {
4+
createRouter,
5+
createWebHistory,
6+
type NavigationGuardNext,
7+
type RouteLocationNormalized,
8+
type RouteRecordRaw,
9+
type RouteRecordName,
10+
} from 'vue-router'
11+
import useStore from '@/stores'
12+
import { routes } from '@/router/chat/routes'
13+
NProgress.configure({ showSpinner: false, speed: 500, minimum: 0.3 })
14+
const router = createRouter({
15+
history: createWebHistory(import.meta.env.BASE_URL),
16+
routes: routes,
17+
})
18+
19+
// 路由前置拦截器
20+
router.beforeEach(
21+
async (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
22+
NProgress.start()
23+
if (to.name === '404') {
24+
next()
25+
return
26+
}
27+
const { user, login } = useStore()
28+
29+
const notAuthRouteNameList = ['login', 'ForgotPassword', 'ResetPassword', 'Chat', 'UserLogin']
30+
if (!notAuthRouteNameList.includes(to.name ? to.name.toString() : '')) {
31+
if (to.query && to.query.token) {
32+
localStorage.setItem('token', to.query.token.toString())
33+
}
34+
const token = login.getToken()
35+
if (!token) {
36+
next({
37+
path: '/login',
38+
})
39+
return
40+
}
41+
if (!user.userInfo) {
42+
await user.profile()
43+
}
44+
}
45+
// 判断是否有菜单权限
46+
if (to.meta.permission ? hasPermission(to.meta.permission as any, 'OR') : true) {
47+
next()
48+
} else {
49+
// 如果没有权限则直接取404页面
50+
next('404')
51+
}
52+
},
53+
)
54+
router.afterEach(() => {
55+
NProgress.done()
56+
})
57+
58+
export const getChildRouteListByPathAndName = (path: any, name?: RouteRecordName | any) => {
59+
return getChildRouteList(routes, path, name)
60+
}
61+
62+
export const getChildRouteList: (
63+
routeList: Array<RouteRecordRaw>,
64+
path: string,
65+
name?: RouteRecordName | null | undefined,
66+
) => Array<RouteRecordRaw> = (routeList, path, name) => {
67+
for (let index = 0; index < routeList.length; index++) {
68+
const route = routeList[index]
69+
if (name === route.name && path === route.path) {
70+
return route.children || []
71+
}
72+
if (route.children && route.children.length > 0) {
73+
const result = getChildRouteList(route.children, path, name)
74+
if (result && result?.length > 0) {
75+
return result
76+
}
77+
}
78+
}
79+
return []
80+
}
81+
82+
export default router

ui/src/router/chat/routes.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { RouteRecordRaw } from 'vue-router'
2+
3+
export const routes: Array<RouteRecordRaw> = [
4+
// 对话
5+
{
6+
path: '/chat/:accessToken',
7+
name: 'Chat',
8+
component: () => import('@/views/chat/index.vue'),
9+
},
10+
]

ui/vite.config.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,44 @@ import { defineConfig, loadEnv } from 'vite'
44
import vue from '@vitejs/plugin-vue'
55
import vueJsx from '@vitejs/plugin-vue-jsx'
66
import DefineOptions from 'unplugin-vue-define-options/vite'
7+
import path from 'path'
8+
import { createHtmlPlugin } from 'vite-plugin-html'
9+
710
// import vueDevTools from 'vite-plugin-vue-devtools'
811
const envDir = './env'
912

1013
// https://vite.dev/config/
1114
export default defineConfig(({ mode }) => {
15+
console.log('ssss')
1216
const ENV = loadEnv(mode, envDir)
1317
const prefix = process.env.VITE_DYNAMIC_PREFIX || ENV.VITE_BASE_PATH
1418
const proxyConf: Record<string, string | ProxyOptions> = {}
1519
proxyConf['/api'] = {
1620
target: 'http://127.0.0.1:8080',
1721
changeOrigin: true,
18-
rewrite: (path) => path.replace(ENV.VITE_BASE_PATH, '/'),
22+
rewrite: (path: string) => path.replace(ENV.VITE_BASE_PATH, '/'),
1923
}
20-
proxyConf['/oss'] = {
24+
proxyConf['/oss'] = {
2125
target: 'http://127.0.0.1:8080',
2226
changeOrigin: true,
23-
rewrite: (path) => path.replace(ENV.VITE_BASE_PATH, '/'),
27+
rewrite: (path: string) => path.replace(ENV.VITE_BASE_PATH, '/'),
2428
}
2529
proxyConf['/doc'] = {
2630
target: 'http://127.0.0.1:8080',
2731
changeOrigin: true,
28-
rewrite: (path) => path.replace(ENV.VITE_BASE_PATH, '/'),
32+
rewrite: (path: string) => path.replace(ENV.VITE_BASE_PATH, '/'),
2933
}
3034
proxyConf['/static'] = {
3135
target: 'http://127.0.0.1:8080',
3236
changeOrigin: true,
33-
rewrite: (path) => path.replace(ENV.VITE_BASE_PATH, '/'),
37+
rewrite: (path: string) => path.replace(ENV.VITE_BASE_PATH, '/'),
3438
}
3539
return {
3640
preflight: false,
3741
lintOnSave: false,
3842
base: prefix,
3943
envDir: envDir,
40-
plugins: [vue(), vueJsx(), DefineOptions()],
44+
plugins: [vue(), vueJsx(), DefineOptions(), createHtmlPlugin({ template: ENV.VITE_INPUT })],
4145
server: {
4246
cors: true,
4347
host: '0.0.0.0',
@@ -46,7 +50,10 @@ export default defineConfig(({ mode }) => {
4650
proxy: proxyConf,
4751
},
4852
build: {
49-
outDir: 'dist/ui',
53+
outDir: `dist${ENV.VITE_BASE_PATH}`,
54+
rollupOptions: {
55+
input: path.resolve(__dirname, ENV.VITE_INPUT),
56+
},
5057
},
5158
resolve: {
5259
alias: {

0 commit comments

Comments
 (0)