diff --git a/apps/application/flow/common.py b/apps/application/flow/common.py index 10f612300..98f706fde 100644 --- a/apps/application/flow/common.py +++ b/apps/application/flow/common.py @@ -175,8 +175,7 @@ class Workflow: return Workflow(nodes, edges) def get_start_node(self): - start_node_list = [node for node in self.nodes if node.id == 'start-node'] - return start_node_list[0] + return self.get_node('start-node') def get_search_node(self): return [node for node in self.nodes if node.type == 'search-dataset-node'] diff --git a/ui/chat.html b/ui/chat.html new file mode 100644 index 000000000..5ab118316 --- /dev/null +++ b/ui/chat.html @@ -0,0 +1,14 @@ + + + + + + + + %VITE_APP_TITLE% + + +
+ + + diff --git a/ui/env/.env b/ui/env/.env index 87cd57582..3fadebde2 100644 --- a/ui/env/.env +++ b/ui/env/.env @@ -1,4 +1,5 @@ VITE_APP_NAME=ui VITE_BASE_PATH=/ui/ VITE_APP_PORT=3000 -VITE_APP_TITLE = 'MaxKB' \ No newline at end of file +VITE_APP_TITLE = 'MaxKB' +VITE_INPUT="index.html" \ No newline at end of file diff --git a/ui/env/.env.chat b/ui/env/.env.chat new file mode 100644 index 000000000..5aef14a8b --- /dev/null +++ b/ui/env/.env.chat @@ -0,0 +1,5 @@ +VITE_APP_NAME=chat +VITE_BASE_PATH=/chat/ +VITE_APP_PORT=3000 +VITE_APP_TITLE = 'MaxKB' +VITE_INPUT="chat.html" \ No newline at end of file diff --git a/ui/package.json b/ui/package.json index 272bc79d9..465a8cf9f 100644 --- a/ui/package.json +++ b/ui/package.json @@ -5,9 +5,12 @@ "type": "module", "scripts": { "dev": "vite", + "chat": "vite --mode chat", "build": "run-p type-check \"build-only {@}\" --", + "build-chat": "run-p type-check \"build-only-chat {@}\" --", "preview": "vite preview", "build-only": "vite build", + "build-only-chat": "vite build --mode chat", "type-check": "vue-tsc --build", "lint": "eslint . --fix", "format": "prettier --write src/" @@ -39,6 +42,7 @@ "screenfull": "^6.0.2", "sortablejs": "^1.15.6", "use-element-plus-theme": "^0.0.5", + "vite-plugin-html": "^3.2.2", "vue": "^3.5.13", "vue-clipboard3": "^2.0.0", "vue-codemirror": "^6.1.1", diff --git a/ui/src/chat.ts b/ui/src/chat.ts new file mode 100644 index 000000000..75032559b --- /dev/null +++ b/ui/src/chat.ts @@ -0,0 +1,65 @@ +import '@/styles/index.scss' +import ElementPlus from 'element-plus' +import * as ElementPlusIcons from '@element-plus/icons-vue' +import zhCn from 'element-plus/es/locale/lang/zh-cn' +import enUs from 'element-plus/es/locale/lang/en' +import zhTW from 'element-plus/es/locale/lang/zh-tw' +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' +import router from '@/router/chat' +import i18n from '@/locales' +import Components from '@/components' +import directives from '@/directives' + +import { config } from 'md-editor-v3' +import screenfull from 'screenfull' + +import katex from 'katex' +import 'katex/dist/katex.min.css' + +import Cropper from 'cropperjs' + +import mermaid from 'mermaid' + +import highlight from 'highlight.js' +import 'highlight.js/styles/atom-one-dark.css' + +config({ + editorExtensions: { + highlight: { + instance: highlight, + }, + screenfull: { + instance: screenfull, + }, + katex: { + instance: katex, + }, + cropper: { + instance: Cropper, + }, + mermaid: { + instance: mermaid, + }, + }, +}) +const app = createApp(App) +app.use(createPinia()) +for (const [key, component] of Object.entries(ElementPlusIcons)) { + app.component(key, component) +} +const locale_map: any = { + 'zh-CN': zhCn, + 'zh-Hant': zhTW, + 'en-US': enUs, +} +app.use(ElementPlus, { + locale: locale_map[localStorage.getItem('MaxKB-locale') || navigator.language || 'en-US'], +}) +app.use(directives) +app.use(router) +app.use(i18n) +app.use(Components) +app.mount('#app') +export { app } diff --git a/ui/src/router/chat/index.ts b/ui/src/router/chat/index.ts new file mode 100644 index 000000000..b759efeff --- /dev/null +++ b/ui/src/router/chat/index.ts @@ -0,0 +1,82 @@ +import { hasPermission } from '@/utils/permission/index' +import NProgress from 'nprogress' +import { + createRouter, + createWebHistory, + type NavigationGuardNext, + type RouteLocationNormalized, + type RouteRecordRaw, + type RouteRecordName, +} from 'vue-router' +import useStore from '@/stores' +import { routes } from '@/router/chat/routes' +NProgress.configure({ showSpinner: false, speed: 500, minimum: 0.3 }) +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: routes, +}) + +// 路由前置拦截器 +router.beforeEach( + async (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => { + NProgress.start() + if (to.name === '404') { + next() + return + } + const { user, login } = useStore() + + const notAuthRouteNameList = ['login', 'ForgotPassword', 'ResetPassword', 'Chat', 'UserLogin'] + if (!notAuthRouteNameList.includes(to.name ? to.name.toString() : '')) { + if (to.query && to.query.token) { + localStorage.setItem('token', to.query.token.toString()) + } + const token = login.getToken() + if (!token) { + next({ + path: '/login', + }) + return + } + if (!user.userInfo) { + await user.profile() + } + } + // 判断是否有菜单权限 + if (to.meta.permission ? hasPermission(to.meta.permission as any, 'OR') : true) { + next() + } else { + // 如果没有权限则直接取404页面 + next('404') + } + }, +) +router.afterEach(() => { + NProgress.done() +}) + +export const getChildRouteListByPathAndName = (path: any, name?: RouteRecordName | any) => { + return getChildRouteList(routes, path, name) +} + +export const getChildRouteList: ( + routeList: Array, + path: string, + name?: RouteRecordName | null | undefined, +) => Array = (routeList, path, name) => { + for (let index = 0; index < routeList.length; index++) { + const route = routeList[index] + if (name === route.name && path === route.path) { + return route.children || [] + } + if (route.children && route.children.length > 0) { + const result = getChildRouteList(route.children, path, name) + if (result && result?.length > 0) { + return result + } + } + } + return [] +} + +export default router diff --git a/ui/src/router/chat/routes.ts b/ui/src/router/chat/routes.ts new file mode 100644 index 000000000..744c54dac --- /dev/null +++ b/ui/src/router/chat/routes.ts @@ -0,0 +1,10 @@ +import type { RouteRecordRaw } from 'vue-router' + +export const routes: Array = [ + // 对话 + { + path: '/chat/:accessToken', + name: 'Chat', + component: () => import('@/views/chat/index.vue'), + }, +] diff --git a/ui/vite.config.ts b/ui/vite.config.ts index cb0a3d5bf..ee3d9215c 100644 --- a/ui/vite.config.ts +++ b/ui/vite.config.ts @@ -4,40 +4,44 @@ import { defineConfig, loadEnv } from 'vite' import vue from '@vitejs/plugin-vue' import vueJsx from '@vitejs/plugin-vue-jsx' import DefineOptions from 'unplugin-vue-define-options/vite' +import path from 'path' +import { createHtmlPlugin } from 'vite-plugin-html' + // import vueDevTools from 'vite-plugin-vue-devtools' const envDir = './env' // https://vite.dev/config/ export default defineConfig(({ mode }) => { + console.log('ssss') const ENV = loadEnv(mode, envDir) const prefix = process.env.VITE_DYNAMIC_PREFIX || ENV.VITE_BASE_PATH const proxyConf: Record = {} proxyConf['/api'] = { target: 'http://127.0.0.1:8080', changeOrigin: true, - rewrite: (path) => path.replace(ENV.VITE_BASE_PATH, '/'), + rewrite: (path: string) => path.replace(ENV.VITE_BASE_PATH, '/'), } - proxyConf['/oss'] = { + proxyConf['/oss'] = { target: 'http://127.0.0.1:8080', changeOrigin: true, - rewrite: (path) => path.replace(ENV.VITE_BASE_PATH, '/'), + rewrite: (path: string) => path.replace(ENV.VITE_BASE_PATH, '/'), } proxyConf['/doc'] = { target: 'http://127.0.0.1:8080', changeOrigin: true, - rewrite: (path) => path.replace(ENV.VITE_BASE_PATH, '/'), + rewrite: (path: string) => path.replace(ENV.VITE_BASE_PATH, '/'), } proxyConf['/static'] = { target: 'http://127.0.0.1:8080', changeOrigin: true, - rewrite: (path) => path.replace(ENV.VITE_BASE_PATH, '/'), + rewrite: (path: string) => path.replace(ENV.VITE_BASE_PATH, '/'), } return { preflight: false, lintOnSave: false, base: prefix, envDir: envDir, - plugins: [vue(), vueJsx(), DefineOptions()], + plugins: [vue(), vueJsx(), DefineOptions(), createHtmlPlugin({ template: ENV.VITE_INPUT })], server: { cors: true, host: '0.0.0.0', @@ -46,7 +50,10 @@ export default defineConfig(({ mode }) => { proxy: proxyConf, }, build: { - outDir: 'dist/ui', + outDir: `dist${ENV.VITE_BASE_PATH}`, + rollupOptions: { + input: path.resolve(__dirname, ENV.VITE_INPUT), + }, }, resolve: { alias: {