whx hace 15 horas
padre
commit
c8a1322a6c
Se han modificado 35 ficheros con 784 adiciones y 90 borrados
  1. 1 1
      virgo.wzfrontend/aiChat/src/App.vue
  2. 46 0
      virgo.wzfrontend/aiChat/src/api/ai.js
  3. 61 0
      virgo.wzfrontend/aiChat/src/assets/scss/common.scss
  4. 23 36
      virgo.wzfrontend/aiChat/src/assets/scss/variables.scss
  5. 13 3
      virgo.wzfrontend/aiChat/src/components/AIFlowChat.vue
  6. 63 0
      virgo.wzfrontend/aiChat/src/components/Admin/DataSetUpload.vue
  7. 130 0
      virgo.wzfrontend/aiChat/src/components/Admin/Layout.vue
  8. 47 0
      virgo.wzfrontend/aiChat/src/components/Admin/Menu.vue
  9. 148 0
      virgo.wzfrontend/aiChat/src/components/GlobalLoading/GlobalLoading.vue
  10. 51 0
      virgo.wzfrontend/aiChat/src/components/GlobalLoading/index.js
  11. 2 1
      virgo.wzfrontend/aiChat/src/components/HideUpload.vue
  12. 3 0
      virgo.wzfrontend/aiChat/src/main.js
  13. 10 1
      virgo.wzfrontend/aiChat/src/router/index.js
  14. 0 1
      virgo.wzfrontend/aiChat/src/style.css
  15. 3 3
      virgo.wzfrontend/aiChat/src/views/AIChat.vue
  16. 0 1
      virgo.wzfrontend/aiChat/src/views/Chats.vue
  17. 23 9
      virgo.wzfrontend/aiChat/src/views/Home.vue
  18. 115 0
      virgo.wzfrontend/aiChat/src/views/admin/Reading.vue
  19. 8 0
      virgo.wzfrontend/aiChat/src/views/admin/index.vue
  20. 1 1
      virgo.wzfrontend/src/main/resources/static/ai/assets/AIChat-BdmVgVKe.css
  21. 8 8
      virgo.wzfrontend/src/main/resources/static/ai/assets/AIChat-CbdVvAg4.js
  22. 1 1
      virgo.wzfrontend/src/main/resources/static/ai/assets/Chats-BIJscRVU.js
  23. 0 1
      virgo.wzfrontend/src/main/resources/static/ai/assets/Home-BRAMPYpx.js
  24. 1 1
      virgo.wzfrontend/src/main/resources/static/ai/assets/Home-CzWE_B2c.css
  25. 1 0
      virgo.wzfrontend/src/main/resources/static/ai/assets/Home-r0mnIQ-v.js
  26. 1 0
      virgo.wzfrontend/src/main/resources/static/ai/assets/Layout-49sykeTE.css
  27. 1 0
      virgo.wzfrontend/src/main/resources/static/ai/assets/Layout-DYL6SxtY.js
  28. 1 0
      virgo.wzfrontend/src/main/resources/static/ai/assets/Reading-B16EbW2H.js
  29. 1 0
      virgo.wzfrontend/src/main/resources/static/ai/assets/Reading-BuTxNn0F.css
  30. 0 1
      virgo.wzfrontend/src/main/resources/static/ai/assets/_plugin-vue_export-helper-DlAUqK2U.js
  31. 4 4
      virgo.wzfrontend/src/main/resources/static/ai/assets/ai-BVBwtq5f.js
  32. 1 0
      virgo.wzfrontend/src/main/resources/static/ai/assets/index-6QHqnDT6.css
  33. 0 1
      virgo.wzfrontend/src/main/resources/static/ai/assets/index-DkeKGeNw.css
  34. 14 14
      virgo.wzfrontend/src/main/resources/static/ai/assets/index-CkPFMXMA.js
  35. 2 2
      virgo.wzfrontend/src/main/resources/static/ai/index.html

+ 1 - 1
virgo.wzfrontend/aiChat/src/App.vue

@@ -9,5 +9,5 @@
 </template>
 
 <style lang="scss">
-
+	@use '@/assets/scss/common.scss'
 </style>

+ 46 - 0
virgo.wzfrontend/aiChat/src/api/ai.js

@@ -240,4 +240,50 @@ export function getDifyChatList(difyTypeId, lastId, limit) {
 		url: `/api/ai/chat/conversations/${difyTypeId}/${lastId}/${limit}`,
 		method: 'get'
 	})
+}
+/* 
+ * 获取知识库数据
+ * 
+ * 
+ */
+export function getDatasetList(data) {
+	return request({
+		url: `/api/ai/datasets/list`,
+		method: 'post',
+		data: data
+	})
+}
+/* 
+ * 创建知识库数据
+ * 
+ * 
+ */
+export function insertDataset(data) {
+	return request({
+		url: `/api/ai/dataset`,
+		method: 'post',
+		data: data
+	})
+}
+/* 
+ * 获取知识库文档列表
+ * 
+ * 
+ */
+export function getDatasetFileList(datasetId) {
+	return request({
+		url: `/api/ai/datasets/file/${datasetId}`,
+		method: 'get'
+	})
+}
+/* 
+ * 删除知识库文档列表
+ * 
+ * 
+ */
+export function deleteFileById(documentId) {
+	return request({
+		url: `/api/ai/datasets/file/${documentId}`,
+		method: 'delete'
+	})
 }

+ 61 - 0
virgo.wzfrontend/aiChat/src/assets/scss/common.scss

@@ -0,0 +1,61 @@
+
+.ai-dialog {
+	height: 70vh;
+	padding: 0;
+	display: flex;
+	flex-direction: column;
+
+	.el-dialog__header {
+		padding-top: 16px;
+		padding-left: 16px;
+		border-bottom: 1px solid var(--el-border-color);
+		box-sizing: border-box;
+
+		.el-dialog__headerbtn {
+			width: 55px;
+			height: 55px;
+			top: 3px;
+		}
+	}
+
+	.el-dialog__body {
+		flex: 1;
+		height: 0;
+		width: 100%;
+		overflow-y: auto;
+		overflow-x: hidden;
+		padding: 15px;
+	}
+}
+//testfont
+@font-face {
+	font-family: 'testfont';
+	src: url('../font/home.woff2') format("woff2");
+	font-display: swap
+}
+//flex-column 布局
+.wui-flex {
+	width: 100%;
+	height: 100%;
+	display: flex;
+	flex-direction: column;
+
+	.wui-flex-box {
+		flex: 1;
+		height: 0;
+		overflow-y: auto;
+	}
+}
+//wui-table
+.wui-table{
+	padding: 16px;
+	
+	.wui-table-operation{
+		text-align: right;
+	}
+	.wui-table-pagination{
+		padding-top: 16px;
+		display: flex;
+		justify-content: end;
+	}
+}

+ 23 - 36
virgo.wzfrontend/aiChat/src/assets/scss/variables.scss

@@ -7,44 +7,31 @@
 	'success': (
 	  'base': #0bbd87,
 	)
+  ),
+  $button:(
+	'font-weight':500
+  ),
+  $button-font-size:(
+	'default':13px
+  ),
+  $button-border-radius:(
+	'default':8px
+  ),
+  $menu:(
+	'base-level-padding':5px,
+	'bg-color':transparent,
+	'item-height': 40px,
+	'hover-bg-color': var(--el-color-primary-light-8),
+  ),
+  $text-color:(
+    'primary': #354052,
+    'regular': #3c485d,
+    'secondary': #676f83,
+    'placeholder': #a8abb2,
+    'disabled': #c0c4cc,
   )
 );
 
 // If you just import on demand, you can ignore the following content.
 // 如果你想导入所有样式:
-@use "element-plus/theme-chalk/src/index.scss" as *;
-
-@font-face {
-		font-family: 'testfont';
-		src: url('../font/home.woff2') format("woff2");
-		font-display: swap
-	}
-
-.ai-dialog {
-	height: 70vh;
-	padding: 0;
-	display: flex;
-	flex-direction: column;
-
-	.el-dialog__header {
-		padding-top: 16px;
-		padding-left: 16px;
-		border-bottom: 1px solid var(--el-border-color);
-		box-sizing: border-box;
-
-		.el-dialog__headerbtn {
-			width: 55px;
-			height: 55px;
-			top: 3px;
-		}
-	}
-
-	.el-dialog__body {
-		flex: 1;
-		height: 0;
-		width: 100%;
-		overflow-y: auto;
-		overflow-x: hidden;
-		padding: 15px;
-	}
-}
+@use "element-plus/theme-chalk/src/index.scss" as *;

+ 13 - 3
virgo.wzfrontend/aiChat/src/components/AIFlowChat.vue

@@ -33,7 +33,7 @@
 	import {
 		fetchEventSource
 	} from '@microsoft/fetch-event-source';
-	const emits = defineEmits(['updateURL']);
+	const emits = defineEmits(['updateURL', 'removeEdit']);
 	const user = ref(useUserStore().userData);
 	// 对话历史
 	const chatHistory = ref([]);
@@ -132,6 +132,8 @@
 				return {}
 			}
 		});
+		let urlList = newData.filter(node => node.type === 'url');
+		if (urlList.length > 0) previewUrl.value = urlList[urlList.length - 1].url;
 		return deduplicateByTypeAndId(newData);
 	}
 	const AIMessage = async (userMessage) => {
@@ -150,10 +152,17 @@
 			let setTime = null;
 			let dom = '';
 			if (domItem.value.name && domItem.value.parts) {
-				dom = JSON.stringify(domItem.value.parts.map(node => {
-					return `文件名为${domItem.value.file},line为${node.lineNumber}`
+				dom = JSON.stringify(domItem.value.parts.map(node => {
+					return {
+						fileName: domItem.value.file,
+						line: node.lineNumber,
+						componentName: domItem.value.name
+					}
 				}))
+				domItem.value = {};
+				emits('removeEdit');
 			}
+
 			fetchEventSource(`${config.baseURL}/api/ai/chat/run/7`, {
 				method: 'POST',
 				headers: {
@@ -186,6 +195,7 @@
 								clearTimeout(setTime);
 								loading.value = false;
 								setTime = null;
+								if (previewUrl.value) emits('updateURL', previewUrl.value);
 							}
 						}, 1000)
 					}

+ 63 - 0
virgo.wzfrontend/aiChat/src/components/Admin/DataSetUpload.vue

@@ -0,0 +1,63 @@
+<script setup>
+	import {
+		ref,
+		getCurrentInstance
+	} from 'vue'
+	import config from '@/config';
+	import {
+		useUserStore
+	} from '@/store'
+	import {
+		ElMessage
+	} from 'element-plus'
+	const props = defineProps(["accept", "action"])
+	const userStore = useUserStore()
+	const action = ref(config.baseURL + props.action);
+	const headers = ref({
+		token: userStore.token
+	})
+	const {
+		proxy
+	} = getCurrentInstance()
+	const emits = defineEmits(['uploadImage']);
+	const uploadRef = ref(null);
+	const fileList = ref([])
+	const successFile = (res) => {
+		if (res.code != 200) return errorUpload();
+		proxy.$hideLoading();
+		let data = res.data;
+		ElMessage.success('上传成功');
+		emits('uploadImage', data.node.url);
+	}
+	const errorUpload = () => {
+		proxy.$hideLoading();
+		ElMessage.error('上传失败')
+	}
+	const progress = (res) => {
+		// console.log(res);
+	}
+	const handleUpload = () => {
+		uploadRef.value.$el.querySelector('input').click();
+	}
+	const beforeUpload = (rawFile) => {
+		if (rawFile.size / 1024 / 1024 > 10) {
+			ElMessage.warning('文件不能超过10MB')
+			return false
+		}
+		proxy.$showLoading()
+	}
+	defineExpose({
+		handleUpload
+	})
+</script>
+<template>
+	<div class="hide-upload">
+		<el-upload :action="action" name="file" ref="uploadRef" :before-upload="beforeUpload" :headers="headers"
+			:on-success="successFile" :on-error="errorUpload" :show-file-list="false" :on-progress="progress"
+			:accept="props.accept">
+		</el-upload>
+	</div>
+</template>
+<style lang="scss">
+	.datacenter-upload {}
+</style>

+ 130 - 0
virgo.wzfrontend/aiChat/src/components/Admin/Layout.vue

@@ -0,0 +1,130 @@
+<script setup>
+	import {
+		ref
+	} from 'vue'
+	import {
+		RouterView,
+		useRouter
+	} from 'vue-router'
+	import {
+		useUserStore
+	} from '@/store'
+	import Menu from './Menu.vue'
+	const user = ref(useUserStore().userData);
+	const router = useRouter();
+</script>
+
+
+<template>
+	<div class="admin-layout">
+		<header class="admin-layout-header">
+			<div class="home-nav-left" @click="router.push('/')">
+				<img class="img"
+					src="https://file-node.oss-cn-shanghai.aliyuncs.com/youji/f9617c7f80da485cb3cc72b6accc62ed"
+					alt="logo.png" />
+				<span class="title">WorkArk.AI</span>
+			</div>
+			<div class="home-nav-right">
+				<div class="item no-token">
+					<el-avatar :size="26" :src="user.portrait"></el-avatar>
+				</div>
+			</div>
+		</header>
+		<div class="admin-layout-content">
+			<el-scrollbar class="main">
+				<Menu></Menu>
+			</el-scrollbar>
+			<div class="content">
+				<RouterView />
+			</div>
+		</div>
+	</div>
+</template>
+
+
+<style lang="scss">
+	.admin-layout {
+		background: #fafafa;
+		width: 100%;
+		height: 100%;
+		display: flex;
+		flex-direction: column;
+
+		.admin-layout-content {
+			display: flex;
+			flex: 1;
+			height: 0;
+			padding-right: 10px;
+			padding-bottom: 10px;
+
+			.main {
+				width: 240px;
+				padding-left: 10px;
+				padding-top: 10px;
+			}
+
+			.content {
+				flex: 1;
+				width: 0;
+				margin-left: 10px;
+				box-shadow: 0 2px 2px #0000000a, 0 8px 8px -8px #0000000a;
+				background: #fff;
+				border-style: solid;
+				border-width: 1px;
+				border-color: hsl(0deg 0% 0% / 5%);
+				background-clip: padding-box;
+				border-radius: 8px;
+				overflow: hidden;
+			}
+		}
+
+		.admin-layout-header {
+			height: 44px;
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			padding: 0 15px;
+
+			.home-nav-left {
+				display: flex;
+				align-items: center;
+				cursor: pointer;
+			}
+
+			.title {
+				font-weight: 600;
+				color: #000;
+				font-size: 18px;
+				margin-left: 10px;
+			}
+
+			.img {
+				width: 32px;
+				height: 32px;
+			}
+
+			.home-nav-right {
+				.item {
+					display: flex;
+					align-items: center;
+				}
+
+				.no-token {
+					cursor: pointer;
+				}
+
+				.name {
+					margin-left: 10px;
+				}
+
+				.el-avatar {
+					background: var(--el-color-primary);
+
+					img {
+						background: #fff;
+					}
+				}
+			}
+		}
+	}
+</style>

+ 47 - 0
virgo.wzfrontend/aiChat/src/components/Admin/Menu.vue

@@ -0,0 +1,47 @@
+<script setup>
+	import {
+		Reading,
+		Monitor
+	} from '@element-plus/icons-vue'
+</script>
+
+<template>
+	<el-menu class="wui-menu" default-active="/admin/reading" router>
+		<el-menu-item index="/admin/reading">
+			<el-icon>
+				<Reading />
+			</el-icon>
+			<span>知识库</span>
+		</el-menu-item>
+		<el-menu-item index="1">
+			<el-icon>
+				<Monitor />
+			</el-icon>
+			<span>网站管理</span>
+		</el-menu-item>
+	</el-menu>
+</template>
+
+
+<style lang="scss">
+	.wui-menu {
+		border-right: none;
+
+		.el-sub-menu__title {
+			border-radius: 6px;
+			padding-left: 10px;
+		}
+
+		.el-menu-item {
+			border-radius: 6px;
+
+			&.is-active {
+				background-color: var(--el-menu-hover-bg-color);
+			}
+		}
+
+		li {
+			margin-bottom: 4px;
+		}
+	}
+</style>

+ 148 - 0
virgo.wzfrontend/aiChat/src/components/GlobalLoading/GlobalLoading.vue

@@ -0,0 +1,148 @@
+<template>
+	<transition enter-active-class="animate__animated animate__fadeIn"
+		leave-active-class="animate__animated animate__fadeOut">
+		<div class="wui-loading-box" v-if="show">
+			<div class="spinner2">
+				<div class="rect1 rect"></div>
+				<div class="rect2 rect"></div>
+				<div class="rect3 rect"></div>
+				<div class="rect4 rect"></div>
+				<div class="rect5 rect"></div>
+				<div class="rect6 rect"></div>
+				<div class="rect7 rect"></div>
+				<!-- <div class="percent" v-if="percent">{{percent}}</div> -->
+			</div>
+		</div>
+	</transition>
+</template>
+
+<script setup>
+	import {
+		ref
+	} from 'vue'
+
+	let show = ref(false)
+
+	const showLoading = () => {
+		show.value = true
+	}
+	const hideLoading = (callback) => {
+		show.value = false
+		callback && setTimeout(() => callback(), 500)
+	}
+
+	defineExpose({
+		show,
+		showLoading,
+		hideLoading
+	})
+</script>
+
+<style scoped lang="scss">
+	.animate__animated.animate__fadeIn {
+		--animate-duration: 0.5s;
+	}
+
+	.animate__animated.animate__fadeOut {
+		--animate-duration: 0.5s;
+	}
+
+	.wui-loading-box {
+		position: fixed;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		background: rgba(255, 255, 255, 0.8);
+		z-index: 9999999999;
+
+		.spinner2 {
+			position: absolute;
+			top: 50%;
+			left: 50%;
+			transform: translate(-50%, -50%);
+			width: 200px;
+			height: 60px;
+			text-align: center;
+			font-size: 10px;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+
+			.percent {
+				font-size: 26px;
+				color: var(--el-color-primary);
+				margin-left: 10px;
+				width: 66px;
+				text-align: right
+			}
+		}
+
+		.spinner2 .rect {
+			background-color: var(--el-color-primary);
+			height: 100%;
+			width: 6px;
+			-webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out;
+			animation: sk-stretchdelay 1.2s infinite ease-in-out;
+			margin: 0 1px;
+		}
+
+		.spinner2 .rect2 {
+			-webkit-animation-delay: -1.1s;
+			animation-delay: -1.1s;
+		}
+
+		.spinner2 .rect3 {
+			-webkit-animation-delay: -1.0s;
+			animation-delay: -1.0s;
+		}
+
+		.spinner2 .rect4 {
+			-webkit-animation-delay: -0.9s;
+			animation-delay: -0.9s;
+		}
+
+		.spinner2 .rect5 {
+			-webkit-animation-delay: -0.8s;
+			animation-delay: -0.8s;
+		}
+
+		.spinner2 .rect6 {
+			-webkit-animation-delay: -0.7s;
+			animation-delay: -0.7s;
+		}
+
+		.spinner2 .rect7 {
+			-webkit-animation-delay: -0.6s;
+			animation-delay: -0.6s;
+		}
+
+		@-webkit-keyframes sk-stretchdelay {
+
+			0%,
+			40%,
+			100% {
+				-webkit-transform: scaleY(0.4)
+			}
+
+			20% {
+				-webkit-transform: scaleY(1.0)
+			}
+		}
+
+		@keyframes sk-stretchdelay {
+
+			0%,
+			40%,
+			100% {
+				transform: scaleY(0.4);
+				-webkit-transform: scaleY(0.4);
+			}
+
+			20% {
+				transform: scaleY(1.0);
+				-webkit-transform: scaleY(1.0);
+			}
+		}
+	}
+</style>

+ 51 - 0
virgo.wzfrontend/aiChat/src/components/GlobalLoading/index.js

@@ -0,0 +1,51 @@
+import {
+	createVNode,
+	render,
+	cloneVNode
+} from "vue"
+import GlobalLoading from "./GlobalLoading.vue"
+
+export default {
+	install(app) {
+		// 使用vue底层的createVNode方法将组件渲染为虚拟节点
+		const VNode = createVNode(GlobalLoading)
+		// 使用render函数将组件挂载到body中
+		render(VNode, document.body)
+		// 定义全局方法设置组件的显示和隐藏
+		app.config.globalProperties.$showLoading = VNode.component?.exposed.showLoading
+		app.config.globalProperties.$hideLoading = VNode.component?.exposed.hideLoading
+
+		const weakMap = new WeakMap()
+
+		// 自定义Loading指令
+		app.directive("zx-loading", {
+			mounted(el) {
+				if (weakMap.get(el)) return
+				//  记录当前绑定元素的position
+				weakMap.set(el, window.getComputedStyle(el).position)
+			},
+			updated(el, binding) {
+				const oldPosition = weakMap.get(el);
+				// 如果不是position: relative或者absolute,就设置为relative
+				// 这里的目的是确保loading组件正确覆盖当前绑定的元素
+				if (oldPosition !== 'absolute' && oldPosition !== 'relative') {
+					el.style.position = 'relative'
+				}
+				// 克隆一份loading元素,
+				// 作用是当页面上有多个zx-loading时,每个dom都维护一份属于自己的loading,不会冲突
+				const newVNode = cloneVNode(VNode)
+				// 挂载当前节点
+				render(newVNode, el)
+				// 判断绑定的值
+				if (binding.value) {
+					newVNode.component?.exposed.showLoading()
+				} else {
+					newVNode.component?.exposed.hideLoading(() => {
+						// 还原布局方式
+						el.style.position = oldPosition
+					})
+				}
+			}
+		})
+	}
+}

+ 2 - 1
virgo.wzfrontend/aiChat/src/components/HideUpload.vue

@@ -9,6 +9,7 @@
 	import {
 		ElMessage
 	} from 'element-plus'
+	const props = defineProps(["accept"])
 	const userStore = useUserStore()
 	const action = ref(config.baseURL + '/file/filenode/-1');
 	const headers = ref({
@@ -45,7 +46,7 @@
 <template>
 	<div class="hide-upload">
 		<el-upload :action="action" name="uploadFile" ref="uploadRef" :headers="headers" :on-success="successFile"
-			:on-error="errorUpload" :show-file-list="false" :on-progress="progress" accept=".png, .jpg, .jpeg">
+			:on-error="errorUpload" :show-file-list="false" :on-progress="progress" :accept="props.accept">
 		</el-upload>
 	</div>
 </template>

+ 3 - 0
virgo.wzfrontend/aiChat/src/main.js

@@ -9,9 +9,12 @@ import ElementPlus from 'element-plus'
 
 import pinia from './store'
 
+import GlobalLoading from "@/components/GlobalLoading";
+
 const app = createApp(App)
 app.use(pinia)
 app.use(router)
 app.use(ElementPlus)
+app.use(GlobalLoading)
 
 app.mount('#app')

+ 10 - 1
virgo.wzfrontend/aiChat/src/router/index.js

@@ -14,9 +14,18 @@ const routes = [{
 	name: 'AIChat',
 	component: () => import('../views/AIChat.vue')
 }, {
-	path: '/Chats',
+	path: '/chats',
 	name: 'Chats',
 	component: () => import('../views/Chats.vue')
+}, {
+	path: '/admin',
+	name: 'admin',
+	component: () => import('../components/admin/Layout.vue'),
+	children: [{
+		path: 'reading',
+		name: 'reading',
+		component: () => import('../views/admin/Reading.vue')
+	}]
 }]
 
 const router = createRouter({

+ 0 - 1
virgo.wzfrontend/aiChat/src/style.css

@@ -5,7 +5,6 @@
 	box-sizing: border-box;
 	outline: none;
 	font-family: LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, Helvetica Neue, Tahoma, PingFang SC, Microsoft Yahei, Arial, Hiragino Sans GB, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
-	font-weight: 400;
 	-webkit-font-smoothing: antialiased;
 	user-select: none;
 }

+ 3 - 3
virgo.wzfrontend/aiChat/src/views/AIChat.vue

@@ -56,6 +56,7 @@
 				type: "devtools_enable",
 				__v0_remote__: 1
 			}, '*')
+			isEdit.value = false;
 		}
 	}
 	const handleFunc = e => {
@@ -68,8 +69,7 @@
 			}
 			if (type === 'devtools_selected_state' && e.data.key) {
 				aiFlowChatRef.value.selectItem(e.data);
-			}
-			console.log(e.data);
+			}
 		}
 	}
 	onMounted(() => {
@@ -98,7 +98,7 @@
 			<div class="website-form ai-website-box">
 				<div class="website-form-title">AI聊天</div>
 				<div class="hui-flex-box">
-					<AIFlowChat ref="aiFlowChatRef" @updateURL="updateURL"></AIFlowChat>
+					<AIFlowChat ref="aiFlowChatRef" @updateURL="updateURL" @removeEdit="removeEdit"></AIFlowChat>
 				</div>
 			</div>
 			<div class="website-show ai-website-box">

+ 0 - 1
virgo.wzfrontend/aiChat/src/views/Chats.vue

@@ -56,7 +56,6 @@
 					</div>
 				</el-col>
 			</el-row>
-
 		</div>
 	</div>
 </template>

+ 23 - 9
virgo.wzfrontend/aiChat/src/views/Home.vue

@@ -4,7 +4,9 @@
 		Paperclip,
 		CircleCloseFilled,
 		Plus,
-		UserFilled
+		UserFilled,
+		Reading,
+		SwitchButton
 	} from '@element-plus/icons-vue'
 	import {
 		ElMessage,
@@ -78,6 +80,7 @@
 		if (command === 'url') openUrl();
 		if (command === 'image') hideUploadRef.value.handleUpload();
 		if (command === 'out') logOut();
+		if (command === 'reading') linkTo('/admin/reading')
 	}
 	const openUrl = () => {
 		ElMessageBox.prompt('请输入参考网站网址', 'WorkArk.AI提示', {
@@ -262,7 +265,7 @@
 			loginVisible.value = true;
 			return;
 		}
-		router.push('/Chats');
+		router.push(url);
 	}
 	onMounted(() => {
 		init();
@@ -283,7 +286,7 @@
 			},
 		}],
 	})
-	const linTo = (url) => {
+	const windowLinkTo = (url) => {
 		window.open(url)
 	}
 </script>
@@ -297,13 +300,16 @@
 					alt="logo.png" />
 				<span class="title">Workark.AI</span>
 				<ul class="header-ul">
-					<li class="header-li" @click="linTo('https://www.workark.com/workark/index.html')">Ark</li>
-					<li class="header-li">AI</li>
-					<li class="header-li" @click="linkTo()">定价</li>
-					<li class="header-li" @click="linkTo()">学习</li>
+					<li class="header-li" @click="windowLinkTo('https://www.workark.com/workark/index.html')">Ark</li>
+					<li class="header-li">AI建站</li>
+					<li class="header-li" @click="linkTo()">AI知识产权</li>
+					<li class="header-li" @click="linkTo()">AI财务</li>
+					<li class="header-li" @click="linkTo()">AI营销</li>
+					<li class="header-li" @click="linkTo()">AI任务</li>
 				</ul>
 			</div>
 			<div class="home-nav-right">
+				<div class="price">定价</div>
 				<el-button class="item no-token" v-if="!user.userId" size="default" @click="loginVisible = true">
 					登录
 				</el-button>
@@ -314,7 +320,8 @@
 					</div>
 					<template #dropdown>
 						<el-dropdown-menu>
-							<el-dropdown-item command="out">退出登录</el-dropdown-item>
+							<el-dropdown-item command="reading" :icon="Reading">知识库</el-dropdown-item>
+							<el-dropdown-item command="out" :icon="SwitchButton">退出登录</el-dropdown-item>
 						</el-dropdown-menu>
 					</template>
 				</el-dropdown>
@@ -329,7 +336,8 @@
 				<el-input type="textarea" v-model="message" :placeholder="`生成一个${placeholder}`" resize="none" :rows="5"
 					:autosize="{ minRows: 3, maxRows: 7 }">
 				</el-input>
-				<HideUpload ref="hideUploadRef" v-show="false" @uploadImage="uploadImage"></HideUpload>
+				<HideUpload ref="hideUploadRef" accept=".png, .jpg, .jpeg" v-show="false" @uploadImage="uploadImage">
+				</HideUpload>
 				<div class="form-submit">
 					<div class="form-operation">
 						<el-button size="default" :icon="Paperclip" circle @click="commandFunction('image')">
@@ -448,6 +456,12 @@
 				display: flex;
 				align-items: center;
 
+				.price {
+					opacity: 0.8;
+					padding: 0 15px;
+					cursor: pointer;
+				}
+
 				.item {
 					display: flex;
 					align-items: center;

+ 115 - 0
virgo.wzfrontend/aiChat/src/views/admin/Reading.vue

@@ -0,0 +1,115 @@
+<script setup>
+	import {
+		onMounted,
+		ref
+	} from 'vue'
+	import {
+		Plus
+	} from '@element-plus/icons-vue'
+	import {
+		getDatasetList,
+		insertDataset,
+		getDatasetFileList,
+		deleteFileById
+	} from '@/api/ai'
+
+	import {
+		useUserStore
+	} from '@/store'
+	import dayjs from 'dayjs'
+	import DataSetUpload from '@/components/Admin/DataSetUpload.vue'
+	const tableData = ref([]);
+	const userStore = useUserStore().userData;
+	const datasetId = ref('');
+	const dataSetUploadRef = ref(null);
+	const total = ref(0);
+	const init = async () => {
+		let list = await getDatasetList({
+			organizationId: userStore.organization.id
+		});
+		if (list.state) {
+			if (list.data.length === 0) return insertDatasetFunc();
+			datasetId.value = list.data[0].datasetId;
+			getFileData();
+		}
+	}
+	const insertDatasetFunc = async () => {
+		let insertData = await insertDataset({
+			description: userStore.organization.name,
+			name: String(userStore.organization.id),
+			organizationId: userStore.organization.id,
+			userId: userStore.userId
+		})
+		// if (insertData.state) init();
+	}
+	const getFileData = async () => {
+		let fileData = await getDatasetFileList(datasetId.value)
+		console.log(fileData);
+
+	}
+	const upload = () => {
+		dataSetUploadRef.value.handleUpload();
+	}
+	const uploadImage = () => {
+
+	}
+	const testWordCount = (num) => {
+		return num < 1000 ? num : parseFloat(num / 1000).toFixed(1) + 'K'
+	}
+
+	const formatTime = (time) => {
+		if (String(time).length === 10) time *= 1000;
+		let date = new Date(time)
+		return dayjs(date).format('YYYY-MM-DD HH:mm:ss')
+	}
+
+	onMounted(() => {
+		init();
+	})
+</script>
+
+<template>
+	<div class="wui-flex wui-table">
+		<div class="wui-table-operation">
+			<el-button type="primary" :icon="Plus" @click="upload">添加文件</el-button>
+			<DataSetUpload v-if="datasetId" :action="`/api/ai/dataset/file/${datasetId}`" ref="dataSetUploadRef"
+				accept=".TXT,.MARKDOWN,.MDX,.PDF,.HTML,.XLSX,.XLS,.DOCX,.CSV,.VTT,.PROPERTIES,.MD,.HTM" v-show="false"
+				@uploadImage="uploadImage">
+			</DataSetUpload>
+		</div>
+		<div class="wui-flex-box">
+			<el-table :data="tableData" height="100%">
+				<el-table-column label="序号" width="80">
+					<template #default="{ $index }">{{ $index + 1 }}</template>
+				</el-table-column>
+				<el-table-column prop="name" label="名称"></el-table-column>
+				<el-table-column label="字符数" width="180">
+					<template #default="scope">{{ testWordCount(scope.row.word_count)}}</template>
+				</el-table-column>
+				<el-table-column label="上传时间" width="180">
+					<template #default="scope">{{ formatTime(scope.row.created_at)}}</template>
+				</el-table-column>
+				<el-table-column label="操作" width="180">
+					<template #default="scope">
+						<div class="">
+							<el-button type="danger" size="small">删除</el-button>
+						</div>
+					</template>
+				</el-table-column>
+				<template #empty>
+					<el-empty description="暂无文档" />
+				</template>
+			</el-table>
+		</div>
+		<div class="wui-table-pagination">
+			<el-pagination background layout="prev, pager, next" :total="total"></el-pagination>
+		</div>
+	</div>
+</template>
+
+
+<style lang="scss">
+	.reading-box {
+		padding: 10px;
+	}
+</style>

+ 8 - 0
virgo.wzfrontend/aiChat/src/views/admin/index.vue

@@ -0,0 +1,8 @@
+<template>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/ai/assets/AIChat-BdmVgVKe.css


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 8 - 8
virgo.wzfrontend/src/main/resources/static/ai/assets/AIChat-CbdVvAg4.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/ai/assets/Chats-BIJscRVU.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/ai/assets/Home-BRAMPYpx.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/ai/assets/Home-CzWE_B2c.css


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/ai/assets/Home-r0mnIQ-v.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/ai/assets/Layout-49sykeTE.css


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/ai/assets/Layout-DYL6SxtY.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/ai/assets/Reading-B16EbW2H.js


+ 1 - 0
virgo.wzfrontend/src/main/resources/static/ai/assets/Reading-BuTxNn0F.css

@@ -0,0 +1 @@
+.reading-box{padding:10px}

+ 0 - 1
virgo.wzfrontend/src/main/resources/static/ai/assets/_plugin-vue_export-helper-DlAUqK2U.js

@@ -1 +0,0 @@
-const s=(t,r)=>{const o=t.__vccOpts||t;for(const[c,e]of r)o[c]=e;return o};export{s as _};

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 4 - 4
virgo.wzfrontend/src/main/resources/static/ai/assets/ai-BVBwtq5f.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/ai/assets/index-6QHqnDT6.css


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/ai/assets/index-DkeKGeNw.css


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 14 - 14
virgo.wzfrontend/src/main/resources/static/ai/assets/index-CkPFMXMA.js


+ 2 - 2
virgo.wzfrontend/src/main/resources/static/ai/index.html

@@ -5,8 +5,8 @@
 		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
 		<link rel="icon" href="https://file-node.oss-cn-shanghai.aliyuncs.com/youji/f9617c7f80da485cb3cc72b6accc62ed">
 		<title>WorkArk AI</title>

-		<script type="module" crossorigin src="./assets/index-CkPFMXMA.js"></script>
-		<link rel="stylesheet" crossorigin href="./assets/index-DkeKGeNw.css">
+		<script type="module" crossorigin src="./assets/index-DyOYl7hb.js"></script>
+		<link rel="stylesheet" crossorigin href="./assets/index-6QHqnDT6.css">
 	</head>
 	<body>
 		<div id="app"></div>