whx 1 天之前
父节点
当前提交
c1f42a76fc
共有 33 个文件被更改,包括 653 次插入219 次删除
  1. 1 1
      virgo.wzfrontend/src/main/resources/static/workark/index.html
  2. 0 3
      virgo.wzfrontend/src/main/resources/static/workark/reset.css
  3. 0 0
      virgo.wzfrontend/src/main/resources/static/workark/static/css/2934.c5171ae5.css
  4. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/css/3156.1d2ca438.css
  5. 0 0
      virgo.wzfrontend/src/main/resources/static/workark/static/css/645.d2932744.css
  6. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/css/7769.80eefdb8.css
  7. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/css/8725.168c7384.css
  8. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/css/app.7e4b15dc.css
  9. 0 1
      virgo.wzfrontend/src/main/resources/static/workark/static/css/app.854e01a8.css
  10. 1 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/1291.b93112d3.js
  11. 1 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/1409.9c2fa07e.js
  12. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/2678.ce12f61b.js
  13. 0 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/2891.f3d361cf.js
  14. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/2934.6047978e.js
  15. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/3156.1c0e6349.js
  16. 1 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/348.8599411c.js
  17. 0 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/3838.99c2adc7.js
  18. 1 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/5996.36560e37.js
  19. 1 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/6072.a589d66c.js
  20. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/645.3ef99233.js
  21. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/8725.853c590e.js
  22. 0 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/9381.ab5a24f8.js
  23. 2 2
      virgo.wzfrontend/src/main/resources/static/workark/static/js/app.48c8537a.js
  24. 14 2
      virgo.wzfrontend/workark/src/api/ai.js
  25. 66 135
      virgo.wzfrontend/workark/src/components/work/common/aiFlowChat.vue
  26. 235 34
      virgo.wzfrontend/workark/src/components/work/common/aiFlowPage.vue
  27. 85 0
      virgo.wzfrontend/workark/src/components/work/common/renderItem.vue
  28. 116 0
      virgo.wzfrontend/workark/src/components/work/common/renderItems.vue
  29. 2 2
      virgo.wzfrontend/workark/src/layout/workLayout.vue
  30. 7 0
      virgo.wzfrontend/workark/src/router/modules/work/oa.js
  31. 1 1
      virgo.wzfrontend/workark/src/router/permission.js
  32. 58 30
      virgo.wzfrontend/workark/src/views/work/oa/ai/app.vue
  33. 52 0
      virgo.wzfrontend/workark/src/views/work/oa/ai/editWebsite.vue

文件差异内容过多而无法显示
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/workark/index.html


+ 0 - 3
virgo.wzfrontend/src/main/resources/static/workark/reset.css

@@ -50,9 +50,6 @@ section {
 
 /* 图片自适应 */
 img {
-	/*max-width: 100%;*/
-	height: auto;
-	width: auto\9;
 	/* ie8 */
 	-ms-interpolation-mode: bicubic;
 	/*为了照顾ie图片缩放失真*/

virgo.wzfrontend/src/main/resources/static/workark/static/css/2891.c5171ae5.css → virgo.wzfrontend/src/main/resources/static/workark/static/css/2934.c5171ae5.css


文件差异内容过多而无法显示
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/css/3156.1d2ca438.css


virgo.wzfrontend/src/main/resources/static/workark/static/css/3838.2ca6bd97.css → virgo.wzfrontend/src/main/resources/static/workark/static/css/645.d2932744.css


文件差异内容过多而无法显示
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/css/7769.80eefdb8.css


文件差异内容过多而无法显示
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/css/8725.168c7384.css


文件差异内容过多而无法显示
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/css/app.7e4b15dc.css


文件差异内容过多而无法显示
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/css/app.854e01a8.css


文件差异内容过多而无法显示
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/1291.b93112d3.js


文件差异内容过多而无法显示
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/1409.9c2fa07e.js


文件差异内容过多而无法显示
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/2678.ce12f61b.js


文件差异内容过多而无法显示
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/2891.f3d361cf.js


文件差异内容过多而无法显示
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/2934.6047978e.js


文件差异内容过多而无法显示
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/3156.1c0e6349.js


文件差异内容过多而无法显示
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/348.8599411c.js


文件差异内容过多而无法显示
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/3838.99c2adc7.js


文件差异内容过多而无法显示
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/5996.36560e37.js


文件差异内容过多而无法显示
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/6072.a589d66c.js


文件差异内容过多而无法显示
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/645.3ef99233.js


文件差异内容过多而无法显示
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/8725.853c590e.js


文件差异内容过多而无法显示
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/9381.ab5a24f8.js


文件差异内容过多而无法显示
+ 2 - 2
virgo.wzfrontend/src/main/resources/static/workark/static/js/app.48c8537a.js


+ 14 - 2
virgo.wzfrontend/workark/src/api/ai.js

@@ -104,7 +104,7 @@ export function createAIFlowData(difyTypeId, data) {
 		method: 'post',
 		data: data
 	})
-}
+}
 /* 
  * 获取dify工作流数据状态
  * 
@@ -115,7 +115,7 @@ export function getAIFlowDataStatus(simpleUUID) {
 		url: `/api/ai/workflow/${simpleUUID}`,
 		method: 'get'
 	})
-}
+}
 /* 
  * 获取层级
  * 
@@ -172,4 +172,16 @@ export function deleteAITree(id) {
 		url: `/api/treeData/${id}`,
 		method: 'delete'
 	})
+}
+/* 
+ * 更新html文件
+ * 
+ * 
+ */
+export function updateHtml(data) {
+	return request({
+		url: `/file/enterprise`,
+		method: 'post',
+		data: data
+	})
 }

+ 66 - 135
virgo.wzfrontend/workark/src/components/work/common/aiFlowChat.vue

@@ -11,10 +11,7 @@
 					<div class="message-header-label">AI网站生成助手</div>
 				</div>
 				<div class="message-content">
-					<p>您好!我是AI网站生成助手,请点击按钮生成网站。</p>
-					<el-button size="mini" @click="visible = true" style="margin-top: 10px;">
-						点击生成网站
-					</el-button>
+					<p>您好!我是AI网站生成助手,请输入任务让我修改展示的网站。</p>
 				</div>
 				<div class="message-time">
 					{{ formatTime(messageList.length === 0? new Date():messageList[0].date) }}
@@ -54,10 +51,9 @@
 						<div class="ai-website-boxs" v-else>
 							<div class="ai-website-box" v-html="message.AIInput"></div>
 							<div class="ai-website-mask">
-								<el-button size="mini" type="primary"
-									@click="$emit('previewWebSite', message.AIInput,message.simpleUUID)">
-									预览
-								</el-button>
+								<el-button size="mini"
+									@click="previewHtml(message.AIInput,message.simpleUUID)">预览</el-button>
+								<el-button size="mini" type="primary" @click="update(message.AIInput)">替换</el-button>
 							</div>
 						</div>
 					</div>
@@ -74,83 +70,38 @@
 			</div>
 		</div>
 		<div class="input-container">
-			<el-input type="textarea" v-model="newMessage" placeholder="给AI发送消息" resize="none" rows="2"
-				:autosize="{ minRows: 2, maxRows: 6 }" :disabled="!htmlCode">
+			<el-input type="textarea" v-model="messageValue" placeholder="给AI发送消息" resize="none" rows="2"
+				:autosize="{ minRows: 2, maxRows: 6 }">
 			</el-input>
 			<div class="input-button">
-				<el-button size="mini" @click="visible = true">
-					生成网站
-				</el-button>
-				<el-button size="mini" @click="selectProduct" :disabled="loading || !htmlCode">
-					添加商品
-				</el-button>
-				<el-button type="primary" size="mini" @click="sendMessage"
-					:disabled="!newMessage.trim() || loading || !htmlCode">
+				<el-button type="primary" size="mini" @click="sendMessage" :disabled="!messageValue.trim() || loading">
 					发送
 				</el-button>
 			</div>
 		</div>
-		<el-dialog :close-on-click-modal="false" title="生成网站" :visible.sync="visible" width="900px"
-			:append-to-body="true">
-			<website-form v-if="visible" @callback="callback"></website-form>
-		</el-dialog>
-		<el-dialog :close-on-click-modal="false" title="选择商品" :visible.sync="visibles" width="900px"
-			:append-to-body="true">
-			<div class="hui-flex hui-content hui-dialog">
-				<select-product ref="selectProduct" v-if="visibles"></select-product>
-				<div class="hui-dialog-submit">
-					<el-button size="small" @click="visibles = false">取 消</el-button>
-					<el-button size="small" type="primary" @click="sureProduct" :loading="productLoading">
-						确定
-					</el-button>
-				</div>
-			</div>
-		</el-dialog>
 	</div>
 </template>
 
 <script>
-	import websiteForm from '@/components/work/common/websiteForm.vue'
-	const selectProduct = () => import('@/components/work/common/selectProduct');
 	import {
 		getAIFlowDataStatus,
 		getAIFlowDataList,
-		createAIFlowData
+		createAIFlowData,
+		getHtmlData,
+		saveHtmlData,
+		updateHtml
 	} from '@/api/ai'
-	import Crypto from '@/uitls/crypto'
+	import config from '@/config'
 	export default {
-		components: {
-			websiteForm,
-			selectProduct
-		},
+		props: ['htmlData', 'htmlCode'],
 		data() {
 			return {
+				user: {},
 				messageList: [],
-				newMessage: '',
+				messageValue: '',
 				loading: false,
-				darkMode: false,
-				visible: false,
 				timer: null,
-				formData: {
-					company_name: '企业名称',
-					logo_url: '企业logo',
-					company_sub_name: '企业简称',
-					business_scope: '核心业务',
-					key_features: '核心优势',
-					contact_info: '联系方式',
-					industry_sector: '行业领域',
-					create_time: '成立时间',
-					create_place: '成立地点',
-					all_style: '整体风格',
-					model: '主要模块',
-					color_scheme: '主色调',
-					websites_url: '参考网站'
-				},
-				user: {},
-				htmlCode: '',
-				simpleUUID: '',
-				visibles: false,
-				productLoading: false
+				formData: {}
 			}
 		},
 		mounted() {
@@ -174,22 +125,21 @@
 		methods: {
 			init(data) {
 				getAIFlowDataList({
-					userId: this.$store.getters.user.userId
+					userId: this.$store.getters.user.userId,
+					organizationId: this.$store.getters.organization.id,
+					type: 1,
+					insertType: 2,
+					fileId: this.htmlData.id
 				}).then(res => {
 					if (res.state) {
 						this.messageList = res.data.map(node => {
 							node['userInput'] = this.returnUserInputs(node.inputs);
-							let AIInput = ''
-							if (node.outputs) AIInput = this.extractContentBetween(JSON.parse(node.outputs)
-								.text, node.simpleUUID)
-							node['AIInput'] = AIInput;
+							node['AIInput'] = this.extractContentBetween(node.outputs);
 							return node;
 						});
 						if (this.messageList.length > 0) {
 							let data = this.messageList[this.messageList.length - 1];
 							if (data.status === 'running') this.initStaus(data.simpleUUID);
-							if (data.status === 'succeeded') this.$emit('previewWebSite', this.htmlCode, this
-								.simpleUUID);
 						}
 					}
 				})
@@ -207,13 +157,11 @@
 								this.$forceUpdate();
 							}
 							if (data.status === 'succeeded' || data.status === 'failed') {
+								if (data.status === 'succeeded') data['AIInput'] = this
+									.extractContentBetween(data.outputs);
 								this.clearTimer();
 								this.loading = false;
-								if (data.outputs) data['AIInput'] = this.extractContentBetween(JSON.parse(
-									data.outputs).text, data.simpleUUID);
 								this.messageList[this.messageList.length - 1] = data;
-								if (data.status === 'succeeded') this.$emit('previewWebSite', this
-									.htmlCode, this.simpleUUID);
 							}
 						} else {
 							this.clearTimer();
@@ -221,26 +169,14 @@
 					})
 				}, 20000)
 			},
+			extractContentBetween(html) {
+				if (!html) return '';
+				let htmlCode = JSON.parse(html).text;
+				return htmlCode.split('```html')[1];
+			},
 			returnUserInputs(data) {
 				if (!data) return '';
-				let html = '';
-				let objs = JSON.parse(data);
-				if (objs.insertType === 1) {
-					let query = JSON.parse(objs.query)
-					for (let key in query) {
-						if (query[key].indexOf('https://file-node.oss-cn-shanghai.aliyuncs.com/youji/') > -1) {
-							html += this.formData[key] + ':<img class="message-image" src="' + query[key] +
-								'" alt="aa"/><br />';
-						} else if (this.formData[key]) {
-							html += this.formData[key] + ':' + query[key] + "<br />";
-						}
-					}
-				} else if (objs.insertType === 2 || objs.insertType === 4) {
-					html = objs.query;
-				} else if (objs.insertType === 3) {
-					html = objs.query;
-				}
-				return html;
+				return JSON.parse(data).query;
 			},
 			clearTimer() {
 				if (!this.timer) return;
@@ -259,16 +195,14 @@
 					container.scrollTop = container.scrollHeight;
 				}
 			},
-			callback(type) {
-				this.visible = false;
-				if (type === 'init') this.init();
-			},
 			sendMessage() {
 				createAIFlowData(5, {
 					type: 1,
 					insertType: 2,
-					query: this.newMessage,
-					html_code: this.htmlCode
+					query: this.messageValue,
+					html_code: this.htmlCode,
+					organizationId: this.$store.getters.organization.id,
+					fileId: this.htmlData.id
 				}).then(this.successFunc);
 			},
 			reload(message) {
@@ -278,52 +212,49 @@
 					query: data.query,
 					html_code: data.html_code,
 					insertType: data.insertType,
+					organizationId: this.$store.getters.organization.id
 				}).then(this.successFunc);
 			},
 			successFunc(res) {
 				if (res.state) {
 					this.visibles = false;
-					this.newMessage = '';
+					this.messageValue = '';
 					this.$message.success('操作成功');
 					this.init();
 				}
 			},
-			extractContentBetween(html, simpleUUID) {
-				if (!html) return '';
-				// 使用正则表达式匹配 ```html 和 ``` 之间的内容
-				let regex = /```html([\s\S]*?)```/;
-				let match = html.match(regex);
-				let htmls = match && match[1] ? match[1].trim() : '';
-				this.htmlCode = htmls;
-				this.simpleUUID = simpleUUID;
-				return htmls;
-			},
-			selectProduct() {
-				this.visibles = true;
-			},
-			sureProduct() {
-				let form = this.$refs.selectProduct.form;
-				let currentRow = this.$refs.selectProduct.currentRow.map(node => {
-					let id = Crypto.AES.encrypt(String(node.id), 'bosshand');
-					return {
-						id: encodeURIComponent(id),
-						name: node.name,
-						subtitme: node.subtitle,
-						img: this.imageUrl(node.listDisplayImage),
-						unit: '次'
-					}
-				});
-				if (currentRow.length === 0) return this.$message.warning('请至少选择一个商品');
-				createAIData(4, {
-					detailed_html: this.htmlCode,
-					model_name: form.modelName,
-					json_data: JSON.stringify(currentRow)
-				}).then(this.successFunc);
+			async previewHtml(html, simpleUUID) {
+				let url = await this.previewWebSite(html, simpleUUID);
+				window.open(url, '_blank');
 			},
-			imageUrl(data) {
-				if (data && JSON.parse(data)[0]) return JSON.parse(data)[0].url;
-				return 'https://assets.api.uizard.io/api/cdn/stream/c05650d2-192b-4a56-ae97-05638f53804c.png';
+			async previewWebSite(html, simpleUUID) {
+				let htmlData = await getHtmlData({
+					simpleUUID: simpleUUID
+				})
+				if (!htmlData.state) return '';
+				if (htmlData.data.length > 0) return `${config.baseURL}/api/enterprise/${simpleUUID}`
+				let saveData = await saveHtmlData({
+					data: html,
+					simpleUUID: simpleUUID
+				})
+				if (!saveData.state) return '';
+				return `${config.baseURL}/api/enterprise/${simpleUUID}`
 			},
+			update(html) {
+				this.$confirm(`是否替换${this.htmlData.name}代码?替换后将不能再恢复。`, () => {
+					this.$loading();
+					updateHtml({
+						html: html,
+						id: this.htmlData.id
+					}).then(res => {
+						if (res.state) {
+							this.$message.success('操作成功');
+							this.$emit('reloadIframe');
+						}
+						this.$loading.close();
+					})
+				})
+			}
 		}
 	}
 </script>

+ 235 - 34
virgo.wzfrontend/workark/src/components/work/common/aiFlowPage.vue

@@ -1,7 +1,53 @@
 <template>
-	<div class="ai-flow-page" element-loading-text="网站生成中,需15-30分钟" element-loading-spinner="el-icon-loading"
-		v-loading="loading">
-
+	<div class="ai-flow-page">
+		<div class="render-list hui-flex">
+			<div class="render-list-title">
+				网站信息
+			</div>
+			<div class="hui-flex-box">
+				<render-item v-for="(item,index) in fileList" :key="item.id" :item="item"
+					@previewWebSite="previewWebSite">
+				</render-item>
+			</div>
+		</div>
+		<div class="website-show hui-flex">
+			<div class="render-list-title">
+				<span>网站展示</span>
+				<website-upload ref="upload" v-show="false" @reload="successFunc">
+				</website-upload>
+			</div>
+			<div class="hui-flex-box render-ai-box">
+				<div ref="aiBox" class="render-ai-show">
+					<div class="no-empty" v-if="!websiteUrl">
+						<el-empty description="请先预览网站"></el-empty>
+					</div>
+					<div class="html-box" v-else v-loading="frameLoading">
+						<iframe class="iframe-class" ref="iframeDom" :src="websiteUrl" frameborder="0"
+							@load="onloadIframe">
+						</iframe>
+					</div>
+				</div>
+				<div class="render-ai" v-if="isAIEdit">
+					<ai-flow-chat :htmlData="htmlData" :htmlCode="htmlCode" @reloadIframe="reloadIframe"></ai-flow-chat>
+				</div>
+			</div>
+			<div class="hui-drawer-submit">
+				<el-button size="mini" :disabled="!websiteUrl" @click="cancelIframe" v-if="iframeEdit || isAIEdit">
+					取消
+				</el-button>
+				<el-button type="primary" size="mini" :disabled="!websiteUrl" @click="saveIframe" v-if="iframeEdit">
+					保存
+				</el-button>
+				<el-button type="primary" size="mini" :disabled="!websiteUrl" @click="editIframe"
+					v-if="!iframeEdit && !isAIEdit">
+					自定义编辑
+				</el-button>
+				<el-button type="primary" size="mini" :disabled="!websiteUrl" @click="submit"
+					v-if="!iframeEdit && !isAIEdit">
+					AI编辑
+				</el-button>
+			</div>
+		</div>
 	</div>
 </template>
 
@@ -9,53 +55,140 @@
 	import {
 		getAIFlowDataList,
 		createAIFlowData,
-		getAIFlowDataStatus
+		getAIFlowDataStatus,
+		updateHtml
 	} from '@/api/ai'
+	import {
+		getDirList
+	} from '@/api/datacenter'
+	import renderItem from './renderItem.vue'
+	import websiteUpload from './websiteUpload.vue'
+	import aiFlowChat from './aiFlowChat.vue'
+	import config from '@/config'
 	export default {
-		props: ['messageList'],
+		props: ['nowData'],
 		data() {
 			return {
-				nowData: {},
 				loading: false,
-				timer: null
+				fileList: [],
+				websiteUrl: '',
+				iframeEdit: false,
+				imageELement: null,
+				frameLoading: false,
+				htmlData: {},
+				isAIEdit: false,
+				htmlCode: ''
 			}
 		},
 		mounted() {
-			this.init();
+			if (this.nowData.outputs) this.init();
 		},
-		beforeDestroy() {
-			this.clearTimer();
+		components: {
+			renderItem,
+			websiteUpload,
+			aiFlowChat
 		},
 		methods: {
 			init() {
-				this.nowData = this.messageList[this.messageList.length - 1];
-				if (this.nowData.status === 'running') this.initStaus(this.nowData.simpleUUID);
-				if (this.nowData.status === 'success') this.initRender(this.nowData);
+				let outputs = JSON.parse(this.nowData.outputs);
+				if (outputs.text) {
+					getDirList(outputs.text).then(res => {
+						if (res.state) this.fileList = res.data;
+					})
+				}
+			},
+			previewWebSite(item) {
+				this.htmlData = item;
+				this.websiteUrl = `${config.baseURL}/file/enterprise/${item.parentId}/${item.name}`;
+				this.frameLoading = true;
+			},
+			onloadIframe() {
+				this.frameLoading = false;
+				this.initFrame();
+			},
+			initFrame() {
+				const iframe = this.$refs.iframeDom;
+				if (iframe.contentDocument) {
+					const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
+					this.htmlCode = iframeDoc.documentElement.outerHTML;
+					//编辑时a标签不要跳转
+					const a = iframeDoc.querySelectorAll('a');
+					a.forEach(element => {
+						element.oldHref = element.href;
+						element.href = 'javascript:void(0);'
+					});
+				}
+			},
+			reloadIframe() {
+				const iframe = this.$refs.iframeDom;
+				iframe.contentWindow.location.reload();
+			},
+			cancelIframe() {
+				this.reloadIframe();
+				this.iframeEdit = false;
+				this.isAIEdit = false;
+			},
+			getHtml() {
+				const iframe = this.$refs.iframeDom;
+				const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
+				const a = iframeDoc.querySelectorAll('a');
+				a.forEach(element => {
+					element.href = element.oldHref;
+					element.removeAttribute('oldHref');
+				});
+				const allElements = iframeDoc.querySelectorAll('*');
+				allElements.forEach(element => {
+					element.removeAttribute('contentEditable');
+				});
+				const img = iframeDoc.querySelectorAll('img');
+				img.forEach(element => {
+					element.style.cursor = 'pointer';
+					element.onclick = null;
+				});
+				const iframeDocs = iframe.contentDocument || iframe.contentWindow.document;
+				return iframeDocs.documentElement.outerHTML;
 			},
-			initStaus(simpleUUlD) {
-				this.loading = true;
-				this.timer = setInterval(() => {
-					getAIFlowDataStatus(simpleUUlD).then(res => {
-						if (res.state) {
-							let data = res.data;
-							if (!data) return;
-							if (data.status === 'succeeded' || data.status === 'failed') {
-								this.clearTimer();
-								this.loading = false;
-							}
-						} else {
-							this.clearTimer();
+			saveIframe() {
+				updateHtml({
+					html: this.getHtml(),
+					id: this.htmlData.id
+				}).then(res => {
+					if (res.state) {
+						this.$message.success('操作成功');
+						this.iframeEdit = false;
+						this.isAIEdit = false;
+					}
+				})
+			},
+			editIframe() {
+				let _self = this;
+				const iframe = _self.$refs.iframeDom;
+				if (iframe.contentDocument) {
+					const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
+					// 获取页面所有元素
+					const allElements = iframeDoc.querySelectorAll('*');
+					// 为每个元素设置contenteditable=true
+					allElements.forEach(element => {
+						if (element.nodeName !== 'IMG') element.contentEditable = 'true';
+					});
+					// 获取页面所有元素
+					const img = iframeDoc.querySelectorAll('img');
+					// 为每个元素设置contenteditable=true
+					img.forEach(element => {
+						element.style.cursor = 'pointer';
+						element.onclick = function() {
+							_self.imageELement = this;
+							_self.$refs.upload.reloadUpload();
 						}
-					})
-				}, 20000)
+					});
+					_self.iframeEdit = true;
+				}
 			},
-			clearTimer() {
-				if (!this.timer) return;
-				clearInterval(this.timer);
-				this.timer = null;
+			successFunc(url) {
+				if (this.imageELement) this.imageELement.src = url;
 			},
-			initRender() {
-
+			submit() {
+				this.isAIEdit = true;
 			}
 		}
 	}
@@ -65,5 +198,73 @@
 	.ai-flow-page {
 		width: 100%;
 		height: 100%;
+		display: flex;
+
+		.render-ai-box {
+			display: flex;
+		}
+
+		.render-ai-show {
+			flex: 1;
+			width: 0;
+			overflow: hidden;
+		}
+
+		.render-ai {
+			width: 300px;
+		}
+
+		.render-list-title {
+			height: 44px;
+			line-height: 44px;
+			border-bottom: 1px solid $--border-color-light;
+			padding: 0 10px;
+			font-weight: bold;
+		}
+
+		.render-list {
+			width: 220px;
+			border-right: 1px solid $--border-color-light;
+		}
+
+		.website-show {
+			flex: 1;
+			width: 0;
+		}
+
+		.html-box {
+			width: 100%;
+			overflow: hidden;
+			height: 100%;
+		}
+
+		.iframe-class {
+			width: 100%;
+			height: 100%;
+			border: none;
+			overflow: hidden;
+		}
+
+		.no-empty {
+			width: 100%;
+			height: 100%;
+			display: flex;
+			flex-direction: column;
+			justify-content: center;
+		}
+
+		.website-form-content {
+			padding: 10px;
+
+			.el-form {
+				display: block;
+
+				.el-form-item {
+					width: 100%;
+					padding: 0 !important;
+					margin-bottom: 15px;
+				}
+			}
+		}
 	}
 </style>

+ 85 - 0
virgo.wzfrontend/workark/src/components/work/common/renderItem.vue

@@ -0,0 +1,85 @@
+<template>
+	<div class="render-item">
+		<div class="render-item-title">{{item.name}}</div>
+		<div class="render-item-iframe" v-loading="loading">
+			<iframe ref="iframeDom" class="item-iframe"
+				:src="`${baseURL}/file/enterprise/${item.parentId}/${item.name}`" frameborder="0" width="100%"
+				height="100%" @load="onloadIframe" scrolling="no">
+			</iframe>
+			<div class="ai-website-mask">
+				<el-button size="mini" type="primary" @click="$emit('previewWebSite',item)">
+					编辑
+				</el-button>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script>
+	import config from '@/config'
+	export default {
+		props: ['item'],
+		data() {
+			return {
+				baseURL: '',
+				loading: false,
+			}
+		},
+		mounted() {
+			this.baseURL = config.baseURL;
+			this.loading = true;
+		},
+		methods: {
+			onloadIframe() {
+				this.loading = false;
+			}
+		},
+	}
+</script>
+
+<style lang="scss">
+	.render-item {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+	}
+
+	.render-item-title {
+		width: 185px;
+		line-height: 36px;
+		font-size: 16px;
+		font-weight: bold;
+	}
+
+	.render-item-iframe {
+		width: 185px;
+		height: 108px;
+		overflow: hidden;
+		cursor: pointer;
+		position: relative;
+
+		&:hover .ai-website-mask {
+			display: flex;
+		}
+
+		.ai-website-mask {
+			background: rgba(0, 0, 0, 0.4);
+			position: absolute;
+			top: 0;
+			left: 0;
+			right: 0;
+			bottom: 0;
+			display: none;
+			justify-content: center;
+			align-items: center;
+		}
+
+		.item-iframe {
+			width: 1850px;
+			height: 1080px;
+			overflow: hidden;
+			transform: scale(0.1);
+			transform-origin: 0 0;
+		}
+	}
+</style>

+ 116 - 0
virgo.wzfrontend/workark/src/components/work/common/renderItems.vue

@@ -0,0 +1,116 @@
+<template>
+	<div class="render-items">
+		<div class="running-item" v-if="item.status === 'running'">
+			<i class="el-icon-loading"></i> <span>网站生成中,需15-30分钟...</span>
+		</div>
+		<div class="render-items-iframe" v-else-if="item.status === 'succeeded' && file.id" v-loading="loading">
+			<iframe ref="iframeDom" class="item-iframe"
+				:src="`${baseURL}/file/enterprise/${file.parentId}/${file.name}`" frameborder="0" width="100%"
+				height="100%" @load="onloadIframe" scrolling="no">
+			</iframe>
+			<div class="ai-website-mask">
+				<el-button size="mini" @click="$router.push('/work/oa/editWebsite?simpleUUID='+item.simpleUUID)">
+					编辑
+				</el-button>
+				<el-button size="mini" type="primary"
+					@click="preview(`${baseURL}/file/enterprise/${file.parentId}/${file.name}`)">
+					预览
+				</el-button>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script>
+	import config from '@/config'
+	import {
+		getDirList
+	} from '@/api/datacenter'
+	export default {
+		props: ['item'],
+		data() {
+			return {
+				baseURL: '',
+				loading: false,
+				file: {}
+			}
+		},
+		mounted() {
+			this.baseURL = config.baseURL;
+			if (this.item.status === 'succeeded') {
+				this.loading = true;
+				this.init();
+			}
+		},
+		methods: {
+			init() {
+				let outputs = JSON.parse(this.item.outputs);
+				if (outputs.text) {
+					getDirList(outputs.text).then(res => {
+						if (res.state) this.file = res.data[0];
+					})
+				}
+			},
+			onloadIframe() {
+				this.loading = false;
+			},
+			preview(url) {
+				window.open(url, '_blank')
+			}
+		},
+	}
+</script>
+
+<style lang="scss">
+	.render-items {
+		width: 100%;
+		height: 100%;
+		overflow: hidden;
+
+		.running-item {
+			width: 100%;
+			height: 100%;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			background: rgba(0, 0, 0, 0.2);
+			color: $--color-primary;
+
+			span {
+				font-size: 12px;
+			}
+		}
+
+		.render-items-iframe {
+			width: 244px;
+			height: 137px;
+			overflow: hidden;
+			cursor: pointer;
+			position: relative;
+
+			&:hover .ai-website-mask {
+				display: flex;
+			}
+
+			.ai-website-mask {
+				background: rgba(0, 0, 0, 0.4);
+				position: absolute;
+				top: 0;
+				left: 0;
+				right: 0;
+				bottom: 0;
+				display: none;
+				justify-content: center;
+				align-items: center;
+			}
+
+			.item-iframe {
+				width: 1850px;
+				height: 1080px;
+				overflow: hidden;
+				transform: scale(0.132);
+				transform-origin: 0 0;
+			}
+		}
+	}
+</style>

+ 2 - 2
virgo.wzfrontend/workark/src/layout/workLayout.vue

@@ -261,7 +261,7 @@
 
 		.chat-box {
 			position: fixed;
-			bottom: 60px;
+			top: 60px;
 			right: 20px;
 			font-size: 26px;
 			cursor: pointer;
@@ -279,7 +279,7 @@
 			}
 
 			&.customer-serve {
-				bottom: 120px;
+				top: 120px;
 
 				.huifont-kefu {
 					font-size: 26px;

+ 7 - 0
virgo.wzfrontend/workark/src/router/modules/work/oa.js

@@ -33,5 +33,12 @@ const oa = [{
 	meta: {
 		title: 'AI软件'
 	}
+}, {
+	path: 'oa/editWebsite',
+	component: () => import('@/views/work/oa/ai/editWebsite'),
+	name: '编辑网站',
+	meta: {
+		title: '编辑网站'
+	}
 }]
 export default oa;

+ 1 - 1
virgo.wzfrontend/workark/src/router/permission.js

@@ -16,7 +16,7 @@ NProgress.configure({
 	showSpinner: false
 })
 
-const baseUrl = ['/work', '/work/message', '/work/notice', '/work/discount/userCoupon'];
+const baseUrl = ['/work', '/work/message', '/work/notice', '/work/discount/userCoupon','/work/oa/editWebsite'];
 const noTokenUrl = ['/', '/401', '/404', '/loginRegister/login', '/website/serveDetail', '/website/serveList'];
 
 const testBaseUrl = path => { //判断公共路由

+ 58 - 30
virgo.wzfrontend/workark/src/views/work/oa/ai/app.vue

@@ -1,22 +1,27 @@
 <template>
-	<div class="hui-flex border-box">
-		<div class="no-website-box" v-if="messageList.length === 0">
-			<div class="no-website">
-				<div class="no-title">我是AI网站生成助手</div>
-				<div class="no-sub-title">我可以帮你网站建设,请把你的任务交给我吧~</div>
-				<div class="no-input">
-					<el-input type="textarea" v-model="message" placeholder="生成一个信息科技企业官网" resize="none" rows="5"
-						:autosize="{ minRows: 5, maxRows: 7 }">
-					</el-input>
-					<el-button class="send-btn" type="primary" size="mini" @click="sendMessage"
-						:disabled="!message && !loading">
-						发送
-					</el-button>
-				</div>
+	<div class="border-box no-website-box">
+		<div class="no-website">
+			<div class="no-title">我是AI网站生成助手</div>
+			<div class="no-sub-title">我可以帮你网站建设,请把你的任务交给我吧~</div>
+			<div class="no-input">
+				<el-input type="textarea" v-model="message" placeholder="生成一个信息科技企业官网" resize="none" rows="5"
+					:autosize="{ minRows: 5, maxRows: 7 }">
+				</el-input>
+				<el-button class="send-btn" type="primary" size="mini" @click="sendMessage"
+					:disabled="!message && !loading">
+					点击生成({{3-messageList.length}}次)
+				</el-button>
 			</div>
 		</div>
-		<div class="ai-website" v-else>
-			<ai-flow-page :messageList="messageList"></ai-flow-page>
+		<div class="ai-website-list">
+			<div class="ai-website-item" v-for="(item,index) in messageList" :key="item.id">
+				<div class="item-box">
+					<div class="ai-item-title">网站{{index+1}}</div>
+					<div class="ai-item-content">
+						<render-items :item="item"></render-items>
+					</div>
+				</div>
+			</div>
 		</div>
 	</div>
 </template>
@@ -26,7 +31,7 @@
 		getAIFlowDataList,
 		createAIFlowData
 	} from '@/api/ai'
-	import aiFlowPage from '@/components/work/common/aiFlowPage.vue'
+	import renderItems from '@/components/work/common/renderItems.vue'
 	export default {
 		data() {
 			return {
@@ -36,7 +41,7 @@
 			}
 		},
 		components: {
-			aiFlowPage
+			renderItems
 		},
 		mounted() {
 			this.init();
@@ -44,20 +49,22 @@
 		methods: {
 			init() {
 				getAIFlowDataList({
-					userId: this.$store.getters.user.userId
+					userId: this.$store.getters.user.userId,
+					organizationId: this.$store.getters.organization.id,
+					type: 1,
+					insertType: 5
 				}).then(res => {
 					this.loading = true;
-					if (res.state) {
-						this.messageList = res.data.filter(node => node.status === 'success' || node.status ===
-							'running');
-					}
+					if (res.state) this.messageList = res.data;
 				})
 			},
 			sendMessage() {
+				if (3 - messageList.length <= 0) this.$message.warning('请联系平台增加生成次数');
 				createAIFlowData(5, {
 					type: 1,
 					insertType: 5,
-					query: this.message
+					query: this.message,
+					organizationId: this.$store.getters.organization.id
 				}).then(this.successFunc);
 			},
 			successFunc(res) {
@@ -92,8 +99,9 @@
 		}
 
 		.no-website {
-			width: 100%;
-			max-width: 800px;
+			width: 800px;
+			padding: 10px;
+			box-sizing: border-box;
 		}
 
 		.no-input {
@@ -105,10 +113,30 @@
 				right: 10px;
 			}
 		}
-	}
 
-	.ai-website {
-		width: 100%;
-		height: 100%;
+		.ai-website-list {
+			display: flex;
+			width: 800px;
+		}
+
+		.ai-website-item {
+			width: 33.33%;
+			padding: 10px;
+			box-sizing: border-box;
+
+			.item-box {
+				border: 1px solid $--border-color-light;
+			}
+
+			.ai-item-title {
+				line-height: 36px;
+				padding-left: 10px;
+				border-bottom: 1px solid $--border-color-light;
+			}
+
+			.ai-item-content {
+				height: 137px;
+			}
+		}
 	}
 </style>

+ 52 - 0
virgo.wzfrontend/workark/src/views/work/oa/ai/editWebsite.vue

@@ -0,0 +1,52 @@
+<template>
+	<div class="edit-website border-box">
+		<div class="no-empty" v-if="!aiData.id">
+			<el-empty description="暂无该网站"></el-empty>
+		</div>
+		<ai-flow-page :nowData="aiData" v-else></ai-flow-page>
+	</div>
+</template>
+
+<script>
+	import {
+		getAIFlowDataStatus
+	} from '@/api/ai'
+	import aiFlowPage from '@/components/work/common/aiFlowPage'
+	export default {
+		components: {
+			aiFlowPage
+		},
+		data() {
+			return {
+				aiData: {},
+				simpleUUID: ''
+			}
+		},
+		mounted() {
+			this.simpleUUID = this.$route.query.simpleUUID
+			if (this.simpleUUID) this.init();
+		},
+		methods: {
+			init() {
+				getAIFlowDataStatus(this.simpleUUID).then(res => {
+					if (res.state) this.aiData = res.data;
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.edit-website {
+		width: 100%;
+		height: 100%;
+
+		.no-empty {
+			width: 100%;
+			height: 100%;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+		}
+	}
+</style>