whx пре 4 дана
родитељ
комит
7c3e2fed73

Разлика између датотеке није приказан због своје велике величине
+ 1312 - 2321
virgo.wzfrontend/aiChat/package-lock.json


+ 4 - 2
virgo.wzfrontend/aiChat/package.json

@@ -1,7 +1,7 @@
 {
 	"name": "aichat",
 	"private": true,
-	"version": "0.0.0",
+	"version": "1.0.0",
 	"type": "module",
 	"scripts": {
 		"dev": "vite",
@@ -11,6 +11,8 @@
 	"dependencies": {
 		"axios": "^1.11.0",
 		"element-plus": "^2.10.4",
+		"highlight.js": "^11.11.1",
+		"marked": "^16.1.1",
 		"pinia": "^3.0.3",
 		"vue": "^3.5.17",
 		"vue-router": "^4.5.1"
@@ -21,4 +23,4 @@
 		"sass-loader": "^12.6.0",
 		"vite": "^7.0.4"
 	}
-}
+}

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

@@ -0,0 +1,221 @@
+import request from '@/utils/request'
+/* 
+ * 获取dify文本数据
+ * 
+ * 
+ */
+export function getAIData(simpleUUID) {
+	return request({
+		url: `/api/ai/completion/${simpleUUID}`,
+		method: 'get',
+	})
+}
+/* 
+ * 生成dify文本数据
+ * 
+ * 
+ */
+export function createAIData(difyTypeId, data) {
+	return request({
+		url: `/api/ai/completion/run/${difyTypeId}`,
+		method: 'post',
+		data: data
+	})
+}
+/* 
+ * 获取dify文本数据状态
+ * 
+ * 
+ */
+export function getAIDataStatus(simpleUUID) {
+	return request({
+		url: `/api/ai/completion/${simpleUUID}`,
+		method: 'get'
+	})
+}
+/* 
+ * 获取dify文本数据列表
+ * 
+ * 
+ */
+export function getAIDataList(data) {
+	return request({
+		url: `/api/ai/completion`,
+		method: 'post',
+		data: data
+	})
+}
+/* 
+ * 保存html代码
+ * 
+ * 
+ */
+export function saveHtmlData(data) {
+	return request({
+		url: `/api/ai/htmlCode`,
+		method: 'post',
+		data: data
+	})
+}
+/* 
+ * 获取保存html代码
+ * 
+ * 
+ */
+export function getHtmlData(data) {
+	return request({
+		url: `/api/ai/htmlCode/query`,
+		method: 'post',
+		data: data
+	})
+}
+/* 
+ * 更新html代码
+ * 
+ * 
+ */
+export function updateHtmlData(data) {
+	return request({
+		url: `/api/ai/htmlCode/update`,
+		method: 'put',
+		data: data
+	})
+}
+/* 
+ * 获取dify工作流数据列表
+ * 
+ * 
+ */
+export function getAIFlowDataList(data) {
+	return request({
+		url: `/api/ai/workflow`,
+		method: 'post',
+		data: data
+	})
+}
+/* 
+ * 生成dify工作流数据
+ * 
+ * 
+ */
+export function createAIFlowData(difyTypeId, data) {
+	return request({
+		url: `/api/ai/workflow/run/${difyTypeId}`,
+		method: 'post',
+		data: data
+	})
+}
+/* 
+ * 获取dify工作流数据状态
+ * 
+ * 
+ */
+export function getAIFlowDataStatus(simpleUUID) {
+	return request({
+		url: `/api/ai/workflow/${simpleUUID}`,
+		method: 'get'
+	})
+}
+/* 
+ * 获取层级
+ * 
+ * 
+ */
+export function getAITree() {
+	return request({
+		url: `/api/treeData`,
+		method: 'get'
+	})
+}
+/* 
+ * 获取通过id设备层级
+ * 
+ * 
+ */
+export function getAITreeById(id) {
+	return request({
+		url: `/api/treeData/${id}`,
+		method: 'get'
+	})
+}
+/* 
+ * 新增设备层级
+ * 
+ * 
+ */
+export function insertAITree(data) {
+	return request({
+		url: `/api/treeData`,
+		method: 'post',
+		data: data
+	})
+}
+/* 
+ * 编辑设备层级
+ * 
+ * 
+ */
+export function updateAITree(data) {
+	return request({
+		url: `/api/treeData`,
+		method: 'put',
+		data: data
+	})
+}
+/* 
+ * 删除设备层级
+ * 
+ * 
+ */
+export function deleteAITree(id) {
+	return request({
+		url: `/api/treeData/${id}`,
+		method: 'delete'
+	})
+}
+/* 
+ * 更新html文件
+ * 
+ * 
+ */
+export function updateHtml(data) {
+	return request({
+		url: `/file/enterprise`,
+		method: 'post',
+		data: data
+	})
+}
+/* 
+ * 执行对话型Chat
+ * 
+ * 
+ */
+export function createChat(difyTypeId, data) {
+	return request({
+		url: `/api/ai/chat/run/${difyTypeId}`,
+		method: 'post',
+		data: data
+	})
+}
+/* 
+ * 获取执行对话型Chat列表
+ * 
+ * 
+ */
+export function getChatList(difyTypeId) {
+	return request({
+		url: `/api/ai/chat/conversations/${difyTypeId}`,
+		method: 'get'
+	})
+}
+/* 
+ * 获取执行对话型Chat列表
+ * 
+ * 
+ */
+export function getHistoryChatList(conversationId) {
+	return request({
+		url: `/api/ai/chat/message/${conversationId}`,
+		method: 'get'
+	})
+}

+ 1 - 1
virgo.wzfrontend/aiChat/src/api/index.js

@@ -1,4 +1,4 @@
-import request from '../utils/request'
+import request from '@/utils/request'
 
 export const getPosts = () => {
 	return request({

+ 1 - 1
virgo.wzfrontend/aiChat/src/api/login.js

@@ -1,4 +1,4 @@
-import request from '../utils/request'
+import request from '@/utils/request'
 
 /* 
  * 获取图片验证码

+ 30 - 1
virgo.wzfrontend/aiChat/src/assets/scss/variables.scss

@@ -9,4 +9,33 @@
 
 // If you just import on demand, you can ignore the following content.
 // 如果你想导入所有样式:
-@use "element-plus/theme-chalk/src/index.scss" as *;
+@use "element-plus/theme-chalk/src/index.scss" as *;
+
+.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;
+	}
+}

+ 307 - 0
virgo.wzfrontend/aiChat/src/components/AIFlowChat.vue

@@ -0,0 +1,307 @@
+<script setup>
+	import {
+		onMounted,
+		ref,
+		toRefs,
+		reactive
+	} from 'vue';
+	import {
+		getChatList,
+		createChat,
+		getHistoryChatList
+	} from '@/api/ai'
+	import {
+		Top
+	} from '@element-plus/icons-vue'
+	import {
+		useUserStore
+	} from '@/store'
+	import {
+		marked
+	} from 'marked';
+	import hljs from 'highlight.js/lib/common';
+	// 引入 github 代码主题
+	import 'highlight.js/styles/github.css';
+
+	const state = reactive({
+		renderedMarkdown: ''
+	});
+	const {
+		renderedMarkdown
+	} = toRefs(state);
+	const user = ref(useUserStore().userData);
+	const messageList = ref([]);
+	const loading = ref(false);
+	const messageValue = ref('')
+	const formatTime = () => {
+		return ''
+	}
+	const init = async () => {
+		let chatData = await getChatList(8);
+		if (chatData.state) {
+			let data = chatData.data.data;
+			if (data.length > 0) initChatList(data[0].id);
+		}
+	}
+	onMounted(() => {
+		init();
+	})
+	const initChatList = async (id) => {
+		let flowData = await getHistoryChatList(id);
+		if (flowData.state) {
+			messageList.value = flowData.data.data.map(node => {
+				node['AIoutputs'] = renderMarkdown(node.answer);
+				return node
+			});
+			hljs.highlightAll()
+		}
+	}
+	const sendMessage = async () => {
+		let chatData = await createChat(8, {
+			query: messageValue.value
+		})
+	}
+	const returnUserInputs = (data) => {
+		if (!data) return '';
+		return JSON.parse(data).query;
+	}
+	/**
+	 * 使用 marked 解析 Markdown
+	 * @param markdown 解析的文本
+	 */
+	const renderMarkdown = markdown => {
+		const renderer = new marked.Renderer();
+		renderer.code = ({
+			text,
+			lang,
+			escaped
+		}) => {
+			const language = hljs.getLanguage(lang) ? lang : 'plaintext';
+			const highlighted = hljs.highlight(text, {
+				language
+			}).value;
+			return `<pre><code class="hljs language-${language}">${highlighted}</code></pre>`;
+		};
+		return marked(markdown, {
+			renderer
+		});
+	};
+</script>
+<template>
+	<div class="ai-chat-container">
+		<div class="chat-body" ref="chatBody">
+			<div v-for="(message, index) in messageList" :key="index">
+				<div class="message user-message">
+					<div class="message-content" v-if="message.query" v-html="message.query"></div>
+				</div>
+				<div class="message ai-message" v-if="!loading || message.status !== 'running'"
+					style="margin-top: 15px;">
+					<div class="message-header">
+						<el-avatar :size="30"
+							src="https://file-node.oss-cn-shanghai.aliyuncs.com/youji/f9617c7f80da485cb3cc72b6accc62ed">
+						</el-avatar>
+						<div class="message-header-label">AI助手</div>
+					</div>
+					<div class="message-content">
+						<div v-if="message.status === 'failed'">
+							<p>服务器繁忙,请稍后重试</p>
+							<el-button size="small" @click="reload(message)"
+								:disabled="index !== messageList.length - 1" style="margin-top: 10px;">
+								点击重试
+							</el-button>
+						</div>
+						<div class="ai-website-boxs" v-else v-html="message.AIoutputs"></div>
+					</div>
+				</div>
+			</div>
+			<div v-if="loading" class="typing-indicator">
+				<div class="typing-dot"></div>
+				<div class="typing-dot"></div>
+				<div class="typing-dot"></div>
+				<span style="margin-left: 10px;">思考中...</span>
+			</div>
+		</div>
+		<div class="input-container">
+			<div class="input-box">
+				<el-input type="textarea" v-model="messageValue" placeholder="给AI发送消息" resize="none" :rows="4"
+					:autosize="{ minRows: 2, maxRows: 6 }">
+				</el-input>
+				<div class="input-button">
+					<el-button circle type="primary" @click="sendMessage" :disabled="!messageValue.trim() || loading"
+						:icon="Top">
+					</el-button>
+				</div>
+			</div>
+		</div>
+	</div>
+</template>
+
+
+<style>
+	.message-image {
+		width: 30px;
+	}
+</style>
+<style scoped lang="scss">
+	.hljs{
+		.language-html{
+			background: #fafafa;
+		}
+	}
+	.ai-chat-container {
+		width: 100%;
+		height: 100%;
+		background: white;
+		border-radius: 16px;
+		box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
+		overflow: hidden;
+		display: flex;
+		flex-direction: column;
+	}
+
+	/* 聊天内容区域 */
+	.chat-body {
+		flex: 1;
+		padding: 20px;
+		overflow-y: auto;
+		background: #f8fafc;
+		display: flex;
+		flex-direction: column;
+		gap: 15px;
+		overflow-x: hidden;
+	}
+
+	.message {
+		padding: 12px 16px;
+		border-radius: 18px;
+		position: relative;
+		animation: fadeIn 0.3s ease;
+		line-height: 1.5;
+	}
+
+	.user-message {
+		background: #7a72cf;
+		color: white;
+		margin-left: auto;
+		border-bottom-right-radius: 4px;
+	}
+
+	.ai-message {
+		background: #ffffff;
+		border: 1px solid #e9ecef;
+		margin-right: auto;
+		border-bottom-left-radius: 4px;
+	}
+
+	.message-header {
+		display: flex;
+		align-items: center;
+		margin-bottom: 5px;
+		font-weight: 500;
+	}
+
+	.message-header-label {
+		flex: 1;
+		width: 0;
+		overflow: hidden;
+		margin-left: 5px;
+		font-weight: bold;
+	}
+
+	.message-time {
+		font-size: 0.7rem;
+		opacity: 0.7;
+		margin-top: 5px;
+		text-align: right;
+	}
+
+	/* 加载指示器 */
+	.typing-indicator {
+		display: flex;
+		align-items: center;
+		padding: 12px 16px;
+		background: white;
+		border: 1px solid #e9ecef;
+		border-radius: 18px;
+		width: fit-content;
+		margin-bottom: 15px;
+		border-bottom-left-radius: 4px;
+	}
+
+	.typing-dot {
+		width: 8px;
+		height: 8px;
+		background: #6c757d;
+		border-radius: 50%;
+		margin: 0 3px;
+		animation: typing 1.4s infinite;
+	}
+
+	.typing-dot:nth-child(1) {
+		animation-delay: 0s;
+	}
+
+	.typing-dot:nth-child(2) {
+		animation-delay: 0.2s;
+	}
+
+	.typing-dot:nth-child(3) {
+		animation-delay: 0.4s;
+	}
+
+	/* 输入区域 */
+	.input-container {
+		padding: 10px;
+		box-sizing: border-box;
+		background: #f8fafc;
+
+		.input-box {
+			background: #ffffff;
+			padding: 5px 0;
+			border: 1px solid var(--el-border-color);
+			border-radius: 10px;
+		}
+
+		:deep(.el-textarea__inner) {
+			border: none;
+			background: transparent;
+			box-shadow: none;
+
+			&:hover {
+				box-shadow: none;
+			}
+		}
+	}
+
+	.input-button {
+		margin-top: 10px;
+		text-align: right;
+		padding: 5px 10px;
+	}
+
+	/* 动画 */
+	@keyframes fadeIn {
+		from {
+			opacity: 0;
+			transform: translateY(10px);
+		}
+
+		to {
+			opacity: 1;
+			transform: translateY(0);
+		}
+	}
+
+	@keyframes typing {
+
+		0%,
+		60%,
+		100% {
+			transform: translateY(0);
+		}
+
+		30% {
+			transform: translateY(-5px);
+		}
+	}
+</style>

+ 54 - 0
virgo.wzfrontend/aiChat/src/components/HideUpload.vue

@@ -0,0 +1,54 @@
+<script setup>
+	import {
+		ref
+	} from 'vue'
+	import config from '@/config';
+	import {
+		useUserStore
+	} from '@/store'
+	import {
+		ElMessage
+	} from 'element-plus'
+	const userStore = useUserStore()
+	const action = ref(config.baseURL + '/file/filenode/-1');
+	const headers = ref({
+		token: userStore.token
+	})
+	const emits = defineEmits(['uploadImage']);
+	const uploadRef = ref(null);
+	const fileList = ref([])
+	const successFile = (res) => {
+		if (res.code != 200) return errorUpload();
+		let data = res.data;
+		ElMessage({
+			message: '上传成功',
+			type: 'success',
+		});
+		emits('uploadImage', data.node.url);
+	}
+	const errorUpload = () => {
+		ElMessage({
+			message: '上传失败',
+			type: 'error',
+		})
+	}
+	const progress = (res) => {
+		console.log(res);
+	}
+	const handleUpload = () => {
+		uploadRef.value.$el.querySelector('input').click();
+	}
+	defineExpose({
+		handleUpload
+	})
+</script>
+<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">
+		</el-upload>
+	</div>
+</template>
+<style lang="scss">
+	.datacenter-upload {}
+</style>

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

@@ -142,8 +142,7 @@
 		};
 		let loginData = await login(postData);
 		if (loginData.state) {
-			userStore.setToken(loginData.data.token);
-			console.log(userStore.token);
+			userStore.setToken(loginData.data.token);
 			let userData = await getUserInfo();
 			if (userData.state) {
 				let user = userData.data;

+ 4 - 0
virgo.wzfrontend/aiChat/src/router/index.js

@@ -7,6 +7,10 @@ const routes = [{
 	path: '/',
 	name: 'Home',
 	component: () => import('../views/Home.vue')
+},{
+	path: '/ai-chat',
+	name: 'AIChat',
+	component: () => import('../views/AIChat.vue')
 }]
 
 const router = createRouter({

+ 0 - 1
virgo.wzfrontend/aiChat/src/store/plugins/registerPlugin.js

@@ -7,7 +7,6 @@ export default function(context) {
 
 	//注册页面卸载和刷新行为事件
 	window.addEventListener("beforeunload", function() {
-		alert(JSON.stringify(store.$state));
 		sessionStorage.setItem(KEY_PREFIX + store.$id, JSON.stringify(store.$state));
 	});
 	// 读取数据

+ 2 - 1
virgo.wzfrontend/aiChat/src/utils/request.js

@@ -51,7 +51,8 @@ service.interceptors.response.use(
 			msg: res.code == '200' ? 'success' : 'error'
 		}
 	},
-	error => { //请求返回错误
+	error => { //请求返回错误
+	console.log(error);
 		return {
 			state: false
 		}

+ 190 - 0
virgo.wzfrontend/aiChat/src/views/AIChat.vue

@@ -0,0 +1,190 @@
+<script setup>
+	import {
+		ref
+	} from 'vue'
+	import AIFlowChat from '@/components/AIFlowChat.vue';
+	import {
+		useUserStore
+	} from '@/store'
+	const user = ref(useUserStore().userData);
+	const websiteUrl = ref('');
+	const loading = ref(false);
+	const onloadIframe = () => {
+
+	}
+</script>
+<template>
+	<div class="ai-website">
+		<header class="ai-website-header">
+			<div class="home-nav-left">
+				<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="ai-website-content">
+			<div class="website-form ai-website-box">
+				<div class="website-form-title">AI聊天</div>
+				<div class="hui-flex-box">
+					<AIFlowChat></AIFlowChat>
+				</div>
+			</div>
+			<div class="website-show ai-website-box">
+				<div class="website-form-title">网页展示</div>
+				<div class="hui-flex-box">
+					<div class="no-empty" v-if="!websiteUrl">
+						<el-empty description="请先预览网站"></el-empty>
+					</div>
+					<div class="html-box" v-else v-loading="loading">
+						<iframe ref="iframeDom" :src="websiteUrl" width="100%" height="100%" frameborder="0"
+							@load="onloadIframe">
+						</iframe>
+					</div>
+				</div>
+				<div class="hui-drawer-submit">
+
+				</div>
+			</div>
+		</div>
+	</div>
+</template>
+
+
+<style lang="scss">
+	.ai-website {
+		width: 100%;
+		height: 100%;
+		display: flex;
+		background: #fcfbf8;
+		flex-direction: column;
+
+		.ai-website-header {
+			height: 44px;
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			padding: 0 15px;
+
+			.home-nav-left {
+				display: flex;
+				align-items: center;
+			}
+
+			.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;
+					}
+				}
+			}
+		}
+
+		.ai-website-content {
+			display: flex;
+			width: 100%;
+			height: 0;
+			flex: 1;
+			padding: 0 10px 10px 10px;
+		}
+
+		.ai-website-box {
+			background: #fff;
+			border: 1px solid var(--el-border-color);
+			border-radius: 10px;
+			display: flex;
+			flex-direction: column;
+		}
+
+		.html-box {
+			width: 100%;
+			overflow: hidden;
+			height: 100%;
+		}
+
+		.iframe-class {
+			width: 100%;
+			height: 100%;
+			border: none;
+			overflow: hidden;
+		}
+
+		.website-form-title {
+			height: 44px;
+			line-height: 44px;
+			border-bottom: 1px solid var(--el-border-color);
+			padding: 0 10px;
+			font-weight: bold;
+		}
+
+		.website-form {
+			width: 400px;
+			border-right: 1px solid var(--el-border-color);
+			margin-right: 10px;
+		}
+
+		.no-empty {
+			width: 100%;
+			height: 100%;
+			display: flex;
+			flex-direction: column;
+			justify-content: center;
+		}
+
+		.website-show {
+			flex: 1;
+			width: 0;
+		}
+
+		.hui-flex-box {
+			height: 0;
+			flex: 1;
+		}
+
+		.website-form-content {
+			padding: 10px;
+
+			.el-form {
+				display: block;
+
+				.el-form-item {
+					width: 100%;
+					padding: 0 !important;
+					margin-bottom: 15px;
+				}
+			}
+		}
+	}
+</style>

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

@@ -20,8 +20,12 @@
 		useUserStore
 	} from '@/store'
 	import Login from '@/components/Login.vue'
+	import HideUpload from '@/components/HideUpload.vue'
+	import { useRouter } from 'vue-router';
+	const router = useRouter();
 	const userStore = useUserStore()
 	const message = ref('');
+	const hideUploadRef = ref(null);
 	const typeList = ref([{
 		id: 1,
 		name: '网站'
@@ -57,7 +61,16 @@
 	const loading = ref(false);
 	const websiteURL = ref('');
 	const commandFunction = (command) => {
+		if (!userStore.token) {
+			ElMessage({
+				message: '请先登录',
+				type: 'warning',
+			})
+			loginVisible.value = true;
+			return;
+		}
 		if (command === 'url') openUrl();
+		if (command === 'image') hideUploadRef.value.handleUpload();
 	}
 	const openUrl = () => {
 		ElMessageBox.prompt('请输入参考网站网址', 'WorkArk.AI提示', {
@@ -72,10 +85,10 @@
 			websiteURL.value = value;
 		}).catch(() => {});
 	}
-	const imageList = ref([{
-		id: 1,
-		url: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'
-	}])
+	const imageList = ref([])
+	const uploadImage = url => {
+		imageList.value.push(url);
+	}
 	const removeImage = (index) => {
 		ElMessageBox.confirm('是否删除该图片?', 'WorkArk.AI提示', {
 			confirmButtonText: '确认',
@@ -93,8 +106,10 @@
 	const user = ref({});
 	const init = () => {
 		user.value = userStore.userData;
-		console.log(JSON.stringify(user.value));
 	}
+	const selectVisible = ref(false);
+	const selectData = ref({});
+
 	onMounted(() => {
 		init();
 	})
@@ -129,6 +144,7 @@
 				<el-input type="textarea" v-model="message" placeholder="生成一个信息科技企业官网" resize="none" :rows="5"
 					:autosize="{ minRows: 3, maxRows: 7 }">
 				</el-input>
+				<HideUpload ref="hideUploadRef" v-show="false" @uploadImage="uploadImage"></HideUpload>
 				<div class="form-submit">
 					<div class="form-operation">
 						<el-dropdown @command="commandFunction">
@@ -140,9 +156,13 @@
 								</el-dropdown-menu>
 							</template>
 						</el-dropdown>
-						<el-button style="margin-left: 10px;" size="default" :icon="Plus" circle></el-button>
+						<el-button style="margin-left: 10px;" size="default" :icon="Plus" circle
+							@click="selectVisible = true">
+						</el-button>
 					</div>
-					<el-button type="primary" size="large" :icon="Top" circle :loading="loading"></el-button>
+					<el-button type="primary" size="large" :icon="Top" circle :loading="loading"
+						style="font-size: 18px;" @click="router.push('/ai-chat')">
+					</el-button>
 				</div>
 				<div class="operation-file" v-if="websiteURL || imageList.length > 0">
 					<div class="operation-url" v-if="websiteURL">
@@ -151,8 +171,8 @@
 						</el-tag>
 					</div>
 					<div class="operation-image" v-if="imageList.length > 0">
-						<div class="image-item" v-for="(image,index) in imageList" :key="image.id">
-							<el-image style="width: 60px; height: 60px" :src="image.url" fit="cover" />
+						<div class="image-item" v-for="(image,index) in imageList" :key="index">
+							<el-image style="width: 60px; height: 60px" :src="image" fit="cover" />
 							<el-icon class="image-icon" @click="removeImage(index)">
 								<CircleCloseFilled />
 							</el-icon>
@@ -164,9 +184,43 @@
 		<el-dialog v-model="loginVisible" title="登录" width="440px">
 			<login v-if="loginVisible" @callback="callback"></login>
 		</el-dialog>
+		<el-dialog v-model="selectVisible" title="选项" width="800px" class="ai-dialog select-dialog">
+			<div class="select-item">
+				<div class="select-item-title">生成类型</div>
+				<el-row :gutter="20">
+					<el-col :span="6" v-for="(item,index) in typeList" :key="index">
+						<el-button :type="typeValue === item.id ? 'primary' : ''" style="width: 100%;"
+							@click="typeValue = item.id">
+							{{item.name}}
+						</el-button>
+					</el-col>
+				</el-row>
+			</div>
+			<div class="select-item">
+				<div class="select-item-title">类型</div>
+				<el-row :gutter="20">
+					<el-col :span="6" v-for="(item,index) in generateList" :key="-index">
+						<el-button :type="generateValue === item.id ? 'primary':''" style="width: 100%;"
+							@click="generateValue = item.id">
+							{{item.name}}
+						</el-button>
+					</el-col>
+				</el-row>
+			</div>
+		</el-dialog>
 	</div>
 </template>
 <style lang="scss">
+	.select-dialog {
+		.select-item {
+			margin-bottom: 20px;
+		}
+
+		.select-item-title {
+			margin: 20px 0;
+		}
+	}
+
 	.home-container {
 		width: 100%;
 		height: 100%;
@@ -327,6 +381,7 @@
 
 			.image-item {
 				position: relative;
+				margin-right: 10px;
 			}
 
 			.image-icon {

+ 9 - 1
virgo.wzfrontend/aiChat/vite.config.js

@@ -14,13 +14,21 @@ export default defineConfig({
 		}
 	},
 	server: {
+		port: '8080',
 		proxy: {
-			'/apiV1': { // 配置需要代理的路径 --> 这里的意思是代理http://localhost:80/api/后的所有路由
+			'/apiV1': { // 配置需要代理的路径
 				target: 'https://www.workark.com', // 目标地址 --> 服务器地址
 				changeOrigin: true, // 允许跨域
 				ws: true, // 允许websocket代理
 				// 重写路径 --> 作用与vue配置pathRewrite作用相同
 				rewrite: (path) => path.replace(/^\/apiV1/, "")
+			},
+			'/difyApi': { // 配置需要代理的路径
+				target: 'http://203.110.233.149/v1', // 目标地址 --> 服务器地址
+				changeOrigin: true, // 允许跨域
+				ws: true, // 允许websocket代理
+				// 重写路径 --> 作用与vue配置pathRewrite作用相同
+				rewrite: (path) => path.replace(/^\/difyApi/, "")
 			}
 		},
 	}