feat: 创建多智能体展示分支
- 包含会展策划智能体配置文件 - 包含项目文档和配置更新 - 准备多智能体协作功能展示
This commit is contained in:
548
data/智能开发/Agent/assets/javascript/index.js
Executable file
548
data/智能开发/Agent/assets/javascript/index.js
Executable file
@@ -0,0 +1,548 @@
|
||||
|
||||
const { createApp } = Vue;
|
||||
|
||||
|
||||
const treeNode = {
|
||||
name: 'tree-node',
|
||||
props: {
|
||||
node: {
|
||||
type: Object,
|
||||
default: []
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="w-full pb-[4px]">
|
||||
<div class="node" @click.stop="toggle(node)">
|
||||
<div v-if="node.folderFlag" @click.stop="toggle(node)" :style="{backgroundColor:selectId === node.uuid?'#E4EFFF':''}" class="h-32px flex items-center cursor-pointer rounded-[6px] hover:bg-[#E4EFFF]">
|
||||
<i v-if="isExpanded" style="margin-left:4px" class="mr-10px fas fa-caret-down arrow"></i>
|
||||
<i v-else style="margin-left:4px" class="mr-10px fas fa-caret-right arrow"></i>
|
||||
<svg class="text-[12px] mr-10px" width="1em" height="1em" fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1091 1024">
|
||||
<path d="M0 932.552719V91.461901Q0 53.489228 27.290422 26.588669 54.190982 0 92.241628 0H412.475241a38.986318 38.986318 0 0 1 29.785547 13.801156l121.715283 143.859513h435.399196q38.050646 0 65.029178 26.588668 27.290422 26.900559 27.290422 64.951206v683.274203q0 38.128619-27.290422 64.951205-26.978532 26.588669-65.029178 26.588669H92.3196q-38.050646 0-65.10715-26.510696Q0 970.525392 0 932.396773z m77.972635 0q0 13.489266 14.346965 13.489266h906.977694q14.346965 0 14.346965-13.567239V249.200543q0-13.567239-14.346965-13.567239H545.808447a38.986318 38.986318 0 0 1-29.785546-13.801156L394.38559 77.972635H92.3196Q77.972635 77.972635 77.972635 91.539874V932.552719z" fill="#333333"></path>
|
||||
<path d="M38.986318 420.506422h1013.644259v77.972636H38.986318v-77.972636z" fill="#333333"></path>
|
||||
<path d="M0 301.754099a38.986318 38.986318 0 0 1 77.972635 0v315.39931a38.986318 38.986318 0 1 1-77.972635 0V301.754099z" fill="#333333"></path>
|
||||
</svg>
|
||||
<span class="text-[12px]">{{ node.pageName }}</span>
|
||||
</div>
|
||||
<div v-else class="children pl-4 rounded-[6px] hover:bg-[#E4EFFF]" @click.stop="selectPage(node)" :style="{backgroundColor:selectId === node.uuid?'#E4EFFF':''}">
|
||||
<div class="">
|
||||
<div class="h-32px ml-10px flex items-center cursor-pointer">
|
||||
<img
|
||||
v-if="node.pageScene === 'web'"
|
||||
src="./assets/img/pagelist-web-page.png"
|
||||
type="icon-yemian"
|
||||
class="mr-10px"
|
||||
/>
|
||||
<img
|
||||
v-else-if="node.pageScene === 'app'"
|
||||
src="./assets/img/pagelist-app-page.png"
|
||||
type="icon-yemian"
|
||||
class="mr-10px"
|
||||
/>
|
||||
<img v-else class="mr-10px" src="./public/assets/preview/page.png" alt="">
|
||||
<span class="text-[12px]">{{ node.pageName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul v-show="isExpanded && node.folderFlag">
|
||||
<li v-for="child in node.childrenList" :key="child.id">
|
||||
<tree-node :node="child" :selectId="selectId" @node-click="(event) => $emit('node-click', event)"></tree-node>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
isExpanded: true
|
||||
}
|
||||
},
|
||||
inject: ['getSelectId'],
|
||||
computed: {
|
||||
selectId () {
|
||||
return this.getSelectId()
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
toggle(node) {
|
||||
this.isExpanded = !this.isExpanded
|
||||
this.$emit('node-click', node)
|
||||
},
|
||||
selectPage(node){
|
||||
this.$emit('node-click', node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const app = createApp({
|
||||
provide () {
|
||||
return {
|
||||
getSelectId: () => this.pageUuid
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
message: 'Hello Vue!',
|
||||
treeData: [],
|
||||
appVersion: '',
|
||||
pageUuid: '',
|
||||
pageType:'',
|
||||
pageName: '',
|
||||
previewSizeOptions: [],
|
||||
previewSizeW: 1920,
|
||||
previewSizeH: 1080,
|
||||
previewSize: '1920x1080',
|
||||
cleanup: null,
|
||||
currentIndex: 0,
|
||||
pageList: [],
|
||||
isPreview: false,
|
||||
isShowTip: false,
|
||||
appName: projectName,
|
||||
resizeObserver: null,
|
||||
setTimeout1: null,
|
||||
isHtml: true,
|
||||
url: '',
|
||||
childUrl: '',
|
||||
iframeMessage: null,
|
||||
childIframe: null, // 导航页内嵌子页面添加键盘事件
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
pageType:{
|
||||
handler(value){
|
||||
this.$nextTick(()=>{
|
||||
if (!this.appName) return
|
||||
this.changePageType(value)
|
||||
let iframeDoc = null
|
||||
let iframeAppDoc = null
|
||||
const iframeKeydownHandler=(e) => {
|
||||
this.keyboardEvents(e)
|
||||
}
|
||||
if (value === 'app') {
|
||||
if (iframeDoc) {
|
||||
iframeDoc.removeEventListener('keydown', iframeKeydownHandler);
|
||||
}
|
||||
const iframeId = this.isHtml ? '#iframeApp' : '#vueIframeApp'
|
||||
const iframeApp = document.querySelector(iframeId);
|
||||
// 聚焦到iframe时,键盘左右切换不生效
|
||||
// iframeApp.addEventListener('load', () => {
|
||||
// iframeAppDoc = iframeApp.contentDocument || iframeApp.contentWindow.document;
|
||||
// iframeAppDoc.addEventListener('keydown', iframeKeydownHandler);
|
||||
// if (!this.isHtml) {
|
||||
// const tag = iframeAppDoc.querySelector('.ai-tag')
|
||||
// tag && (tag.style && (tag.style.visibility = 'hidden') || tag.style.setAtrrbute('visibility','hidden'))
|
||||
// }
|
||||
// });
|
||||
if (this.resizeObserver) {
|
||||
this.resizeObserver.disconnect()
|
||||
this.resizeObserver = null
|
||||
}
|
||||
} else {
|
||||
// 监听web类型iframe父元素大小变化
|
||||
const element = document.querySelector('.preview-web')
|
||||
this.resizeObserver = new ResizeObserver(entries => {
|
||||
for (let entry of entries) {
|
||||
const { width, height } = entry.contentRect
|
||||
if (this.previewSize == 'auto') {
|
||||
this.previewSizeW = parseInt(width)
|
||||
this.previewSizeH = parseInt(height)
|
||||
}
|
||||
this.changeResolution()
|
||||
}
|
||||
})
|
||||
this.resizeObserver.observe(element)
|
||||
|
||||
if (iframeAppDoc) {
|
||||
iframeAppDoc.removeEventListener('keydown', iframeKeydownHandler);
|
||||
}
|
||||
// 聚焦到iframe时,键盘左右切换不生效
|
||||
const iframeWeb = this.isHtml ? document.getElementById('iframe') : document.getElementById('vueIframeWeb')
|
||||
iframeWeb.addEventListener('load', () => {
|
||||
iframeDoc = iframeWeb.contentDocument || iframeWeb.contentWindow.document;
|
||||
iframeDoc.addEventListener('keydown', iframeKeydownHandler);
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
isHtml(value){
|
||||
this.$nextTick(()=>{
|
||||
if (!this.appName) return
|
||||
let iframeDoc = null
|
||||
let iframeAppDoc = null
|
||||
const iframeKeydownHandler=(e) => {
|
||||
this.keyboardEvents(e)
|
||||
}
|
||||
if (value === 'app') {
|
||||
if (iframeDoc) {
|
||||
iframeDoc.removeEventListener('keydown', iframeKeydownHandler);
|
||||
}
|
||||
const iframeId = this.isHtml ? '#iframeApp' : '#vueIframeApp'
|
||||
const iframeApp = document.querySelector(iframeId);
|
||||
// 聚焦到iframe时,键盘左右切换不生效
|
||||
// iframeApp.addEventListener('load', () => {
|
||||
// iframeAppDoc = iframeApp.contentDocument || iframeApp.contentWindow.document;
|
||||
// iframeAppDoc.addEventListener('keydown', iframeKeydownHandler);
|
||||
// if (!this.isHtml) {
|
||||
// this.$nextTick(() => {
|
||||
// const tag = iframeAppDoc.querySelector('.ai-tag')
|
||||
// tag && (tag.style && (tag.style.visibility = 'hidden') || tag.style.setAtrrbute('visibility','hidden'))
|
||||
// })
|
||||
// }
|
||||
// });
|
||||
if (this.resizeObserver) {
|
||||
this.resizeObserver.disconnect()
|
||||
this.resizeObserver = null
|
||||
}
|
||||
} else {
|
||||
// 监听web类型iframe父元素大小变化
|
||||
const element = document.querySelector('.preview-web')
|
||||
this.resizeObserver = new ResizeObserver(entries => {
|
||||
for (let entry of entries) {
|
||||
const { width, height } = entry.contentRect
|
||||
if (this.previewSize == 'auto') {
|
||||
this.previewSizeW = parseInt(width)
|
||||
this.previewSizeH = parseInt(height)
|
||||
}
|
||||
this.changeResolution()
|
||||
}
|
||||
})
|
||||
this.resizeObserver.observe(element)
|
||||
|
||||
if (iframeAppDoc) {
|
||||
iframeAppDoc.removeEventListener('keydown', iframeKeydownHandler);
|
||||
}
|
||||
// 聚焦到iframe时,键盘左右切换不生效
|
||||
const iframeWeb = this.isHtml ? document.getElementById('iframe') : document.getElementById('vueIframeWeb')
|
||||
iframeWeb.addEventListener('load', () => {
|
||||
iframeDoc = iframeWeb.contentDocument || iframeWeb.contentWindow.document;
|
||||
iframeDoc.addEventListener('keydown', iframeKeydownHandler);
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
previewSize(val) {
|
||||
const option = this.previewSizeOptions.find(item => item.value === val)
|
||||
this.previewSizeW = option.w
|
||||
this.previewSizeH= option.h
|
||||
this.changeResolution()
|
||||
},
|
||||
previewSizeW(val) {
|
||||
if (!this.appName) return
|
||||
this.changeResolution()
|
||||
},
|
||||
previewSizeH(val) {
|
||||
if (!this.appName) return
|
||||
this.changeResolution()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
document.querySelector('#app').style.display = 'block'
|
||||
this.getPageList()
|
||||
this.communicationFun()
|
||||
},
|
||||
methods: {
|
||||
communicationFun () {
|
||||
this.iframeMessage = useEventListener(window, 'message', async (event) => {
|
||||
// 处理消息 判断data值是页面id时处理切换页面
|
||||
if (event.source != window) {
|
||||
const currentPage = this.pageList.find(item => item.pageUuid == event.data)
|
||||
this.pageUuid = currentPage.pageUuid
|
||||
this.pageName = currentPage.pageName
|
||||
this.pageType = currentPage.pageScene
|
||||
this.isHtml = currentPage.codeType === 'html'
|
||||
this.getAppPageVersion(currentPage)
|
||||
this.currentIndex = this.pageList.findIndex(item=>item.pageUuid == this.pageUuid) || 0;
|
||||
}
|
||||
}, true)
|
||||
},
|
||||
// 修改页面类型
|
||||
changePageType(value) {
|
||||
const autoSize = {
|
||||
label: "自定义",
|
||||
value: "auto",
|
||||
w: 375,
|
||||
h: 812
|
||||
}
|
||||
if (value === 'app') {
|
||||
this.previewSizeOptions = [autoSize, ...resolutionInfo.app]
|
||||
this.previewSizeW = 393
|
||||
this.previewSizeH= 852
|
||||
this.previewSize = '393x852-16'
|
||||
} else {
|
||||
let iframe = document.querySelector('.preview-web')
|
||||
autoSize.w = parseInt(iframe.clientWidth)
|
||||
autoSize.h = parseInt(iframe.clientHeight)
|
||||
this.previewSizeOptions = [autoSize, ...resolutionInfo.web]
|
||||
this.previewSizeW = autoSize.w
|
||||
this.previewSizeH= autoSize.h
|
||||
this.previewSize = 'auto'
|
||||
}
|
||||
this.changeResolution()
|
||||
},
|
||||
// 找第一个页面
|
||||
findFirstPage(treeData) {
|
||||
const queue = [...treeData];
|
||||
while (queue.length > 0) {
|
||||
const item = queue.shift();
|
||||
|
||||
// 如果是有效页面,直接返回
|
||||
if (item.folderFlag === false && item.uuid) {
|
||||
return item;
|
||||
}
|
||||
|
||||
// 如果是文件夹且有子节点,将子节点加入队列前端(优先处理)
|
||||
if (item.folderFlag === true && item.childrenList?.length) {
|
||||
queue.unshift(...item.childrenList);
|
||||
}
|
||||
|
||||
// 如果是空文件夹,自动跳过(继续循环)
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
// 页面列表
|
||||
getPageList() {
|
||||
this.treeData = filterByHasVersion(treeArr)
|
||||
// const currentPage = this.treeData.find(item => item.default) || this.treeData[0]
|
||||
const currentPage = this.findFirstPage(this.treeData)
|
||||
console.log(this.treeData, this.pageList);
|
||||
|
||||
this.pageUuid = currentPage.pageUuid
|
||||
this.pageName = currentPage.pageName
|
||||
this.pageType = currentPage.pageScene
|
||||
this.isHtml = currentPage.codeType === 'html'
|
||||
this.$nextTick(()=>{
|
||||
this.getAppPageVersion(currentPage)
|
||||
})
|
||||
collectItems(this.treeData, this.pageList);
|
||||
this.currentIndex = this.pageList.findIndex(item=>item.pageUuid == this.pageUuid) || 0;
|
||||
this.cleanup = this.createKeyboardNavigation();
|
||||
},
|
||||
// 获取应用中页面内容
|
||||
async getAppPageVersion(info) {
|
||||
const isApp = this.pageType == 'app'
|
||||
let iframe = this.isHtml ? document.getElementById('iframe') : document.getElementById('vueIframeWeb')
|
||||
|
||||
if (isApp) {
|
||||
iframe = document.getElementById('iframeApp')
|
||||
}
|
||||
if (info.parentUrl) {
|
||||
iframe.src = info.parentUrl
|
||||
this.childUrl = info.url
|
||||
} else {
|
||||
iframe.src = info.url;
|
||||
}
|
||||
},
|
||||
loadHtmlIframe() {
|
||||
if (this.childIframe) {
|
||||
this.childIframe()
|
||||
this.childIframe = null
|
||||
}
|
||||
const isApp = this.pageType == 'app'
|
||||
// let template = handleCode(this.pageHtml, !isApp);
|
||||
let iframe = document.getElementById('iframe')
|
||||
if (isApp) {
|
||||
iframe = document.getElementById('iframeApp')
|
||||
}
|
||||
const htmlIframe = iframe.contentDocument || iframe.contentWindow.document;
|
||||
if (htmlIframe) {
|
||||
const navIframe = htmlIframe.getElementById('navigation') || htmlIframe.getElementById('contentFrame')
|
||||
this.$nextTick(() => {
|
||||
const top = this.checkIframePositionSimple(htmlIframe)
|
||||
if (navIframe) {
|
||||
if (top) {
|
||||
navIframe.style.height = `calc(100vh - ${top}px)`; // 减去导航高度
|
||||
}
|
||||
// navIframe.srcdoc = handleCode(this.childUrl, !isApp);
|
||||
navIframe.src = this.childUrl
|
||||
const iframeKeydownHandler=(e) => {
|
||||
this.keyboardEvents(e)
|
||||
}
|
||||
navIframe.addEventListener('load', () => {
|
||||
const navIframeDoc = navIframe.contentDocument || navIframe.contentWindow.document;
|
||||
this.childIframe = useEventListener(navIframeDoc, 'keydown', iframeKeydownHandler)
|
||||
});
|
||||
}
|
||||
var homeMenu = htmlIframe.querySelector(`[data-uuid="${this.pageUuid}"]`)
|
||||
let currentMenu = htmlIframe.querySelector('.active-menu')
|
||||
if (homeMenu) {
|
||||
currentMenu?.classList.remove('active-menu')
|
||||
homeMenu.classList.add('active-menu');
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
// 获取子页面位置信息
|
||||
checkIframePositionSimple(htmlIframe) {
|
||||
const iframe = htmlIframe.getElementById('navigation');
|
||||
if (iframe) {
|
||||
const iframeRect = iframe.getBoundingClientRect();
|
||||
return iframeRect.top
|
||||
}
|
||||
return
|
||||
},
|
||||
renderIframe(pageHtml) {
|
||||
// const isApp = this.pageType == 'app'
|
||||
// let template = handleCode(pageHtml, !isApp);
|
||||
// let iframe = document.getElementById('iframe')
|
||||
// if (isApp) {
|
||||
// iframe = document.getElementById('iframeApp')
|
||||
// }
|
||||
// if(isIOSWechat()) {
|
||||
// const parser = new DOMParser();
|
||||
// const doc = parser.parseFromString(template, 'text/html');
|
||||
// const updatedHtmlString = new XMLSerializer().serializeToString(doc);
|
||||
// const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
|
||||
// iframeDocument.write(updatedHtmlString);
|
||||
// return
|
||||
// }
|
||||
// if(!this.isHtml) {
|
||||
// return
|
||||
// }
|
||||
// iframe.srcdoc = template
|
||||
},
|
||||
// 点击目录切换页面
|
||||
handleChangePage(node) {
|
||||
if (!node.folderFlag) {
|
||||
this.pageName = node.pageName
|
||||
this.pageType = node.pageScene
|
||||
this.$nextTick(()=>{
|
||||
this.getAppPageVersion(node)
|
||||
})
|
||||
}
|
||||
this.currentIndex = this.pageList.findIndex(item=>item.pageUuid == node.uuid) || 0;
|
||||
this.pageUuid = node.uuid
|
||||
},
|
||||
changeResolution() {
|
||||
if (this.pageType === 'app') {
|
||||
const contentApp = document.querySelector('.preview-suitable-content-app')
|
||||
// contentApp.style.aspectRatio = Number(this.previewSizeW)/Number(this.previewSizeH)
|
||||
const borderDom = document.querySelector('.app-border')
|
||||
const scale = Math.min(contentApp.offsetWidth/Number(this.previewSizeW), contentApp.offsetHeight/Number(this.previewSizeH))
|
||||
borderDom.style.transform = `scale(${scale})`
|
||||
} else {
|
||||
if (this.appName) {
|
||||
const contentApp = document.querySelector('.page-content')
|
||||
let borderDom = this.isHtml ? document.getElementById('iframe') : document.getElementById('vueIframeWeb')
|
||||
const scale = Math.min(contentApp.offsetWidth/Number(this.previewSizeW), contentApp.offsetHeight/Number(this.previewSizeH))
|
||||
borderDom.style.transform = `scale(${scale})`
|
||||
}
|
||||
}
|
||||
},
|
||||
changeCurrentIndex(num) {
|
||||
if (num == -1) {
|
||||
if (this.currentIndex > 0) {
|
||||
this.currentIndex--
|
||||
}
|
||||
} else {
|
||||
if (this.currentIndex < this.pageList.length - 1) {
|
||||
this.currentIndex++
|
||||
}
|
||||
}
|
||||
this.handleChangePage(this.pageList[this.currentIndex])
|
||||
},
|
||||
// 键盘事件
|
||||
keyboardEvents(event) {
|
||||
if (event.key === 'ArrowLeft') {
|
||||
// 向左键:移动到前一个项目,如果已经是第一个则不处理
|
||||
event.preventDefault();
|
||||
this.changeCurrentIndex(-1)
|
||||
} else if (event.key === 'ArrowRight') {
|
||||
// 向右键:移动到下一个项目,如果已经是最后一个则不处理
|
||||
event.preventDefault();
|
||||
this.changeCurrentIndex(1)
|
||||
} else if (event.key === 'Escape') {
|
||||
this.isPreview = false
|
||||
this.isShowTip = false
|
||||
clearTimeout(this.setTimeout1)
|
||||
this.setTimeout1 = null
|
||||
}
|
||||
},
|
||||
createKeyboardNavigation() {
|
||||
// 处理键盘事件
|
||||
const handleKeyDown = (event) => {
|
||||
if (this.pageList.length === 0) return;
|
||||
this.keyboardEvents(event)
|
||||
};
|
||||
// 添加事件监听
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
|
||||
// 返回一个移除事件监听的函数
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
},
|
||||
toPreview() {
|
||||
this.isPreview = true
|
||||
this.isShowTip = true
|
||||
this.setTimeout1 = setTimeout(()=>{
|
||||
this.isShowTip = false
|
||||
}, 5000)
|
||||
},
|
||||
vueIfameloaded() {
|
||||
this.$nextTick(() => {
|
||||
const iframeId = this.pageType === 'app' ? '#vueIframeApp' : '#vueIframeWeb'
|
||||
const iframeApp = document.querySelector(iframeId);
|
||||
// const iframeAppDoc = iframeApp.contentDocument || iframeApp.contentWindow.document;
|
||||
// const tag = iframeAppDoc.querySelector('.ai-tag')
|
||||
// tag && (tag.style && (tag.style.visibility = 'hidden') || tag.style.setAtrrbute('visibility','hidden'))
|
||||
})
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.cleanup()
|
||||
if (this.resizeObserver) {
|
||||
this.resizeObserver.disconnect()
|
||||
}
|
||||
if (this.iframeMessage) {
|
||||
this.iframeMessage()
|
||||
this.iframeMessage = null
|
||||
}
|
||||
if (this.childIframe) {
|
||||
this.childIframe()
|
||||
this.childIframe = null
|
||||
}
|
||||
}
|
||||
})
|
||||
app.component('treeNode', treeNode);
|
||||
app.mount('#app')
|
||||
|
||||
// 过滤用户没有生成的页面
|
||||
function filterByHasVersion(data) {
|
||||
// 如果不是数组,直接返回
|
||||
if (!Array.isArray(data)) return data;
|
||||
|
||||
// 使用 filter 移除 hasVersion === 1 的对象
|
||||
return data.filter(item => {
|
||||
if (item.hasVersion === '1') {
|
||||
return false; // 移除该对象
|
||||
}
|
||||
|
||||
// 递归处理 children
|
||||
if (item.children && Array.isArray(item.children)) {
|
||||
item.children = filterByHasVersion(item.children);
|
||||
}
|
||||
|
||||
return true; // 保留该对象
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于遍历嵌套数组中 folderFlag 为 false 的对象
|
||||
* @param {Array} items - 要遍历的嵌套数组
|
||||
*/
|
||||
function collectItems(nodes, flatItems) {
|
||||
nodes.forEach((node) => {
|
||||
|
||||
if (node.folderFlag === false) {
|
||||
flatItems.push({
|
||||
...node,
|
||||
});
|
||||
}
|
||||
|
||||
if (node.childrenList && node.childrenList.length > 0) {
|
||||
collectItems(node.childrenList, flatItems);
|
||||
}
|
||||
});
|
||||
}
|
||||
214
data/智能开发/Agent/assets/javascript/initData.js
Executable file
214
data/智能开发/Agent/assets/javascript/initData.js
Executable file
@@ -0,0 +1,214 @@
|
||||
const resolutionInfo = {
|
||||
"web": [
|
||||
{
|
||||
"label": "网页 1920",
|
||||
"value": "1920x1080",
|
||||
"w": 1920,
|
||||
"h": 1080
|
||||
},
|
||||
{
|
||||
"label": "网页 1440",
|
||||
"value": "1440x1024",
|
||||
"w": 1440,
|
||||
"h": 1024
|
||||
},
|
||||
{
|
||||
"label": "MacBook Pro 16\"",
|
||||
"value": "1728x1117",
|
||||
"w": 1728,
|
||||
"h": 1117
|
||||
},
|
||||
{
|
||||
"label": "MacBook Pro 14\"",
|
||||
"value": "1512x982",
|
||||
"w": 1512,
|
||||
"h": 982
|
||||
},
|
||||
{
|
||||
"label": "MacBook Pro",
|
||||
"value": "1440x900",
|
||||
"w": 1440,
|
||||
"h": 900
|
||||
},
|
||||
{
|
||||
"label": "MacBook Air 13",
|
||||
"value": "1280x832",
|
||||
"w": 1280,
|
||||
"h": 832
|
||||
},
|
||||
{
|
||||
"label": "iMac",
|
||||
"value": "2240x1260",
|
||||
"w": 2240,
|
||||
"h": 1260
|
||||
},
|
||||
{
|
||||
"label": "华为 MateBook 16s",
|
||||
"value": "1260x840",
|
||||
"w": 1260,
|
||||
"h": 840
|
||||
},
|
||||
{
|
||||
"label": "华为 MateBook 14s",
|
||||
"value": "1260x840-14",
|
||||
"w": 1260,
|
||||
"h": 840
|
||||
}
|
||||
],
|
||||
"app": [
|
||||
{
|
||||
"label": "iPhone 16 Pro Max",
|
||||
"value": "440x956-16pm",
|
||||
"w": 440,
|
||||
"h": 956
|
||||
},
|
||||
{
|
||||
"label": "iPhone 16 Pro",
|
||||
"value": "402x874-16p",
|
||||
"w": 402,
|
||||
"h": 874
|
||||
},
|
||||
{
|
||||
"label": "iPhone 16 Plus",
|
||||
"value": "430x932-16+",
|
||||
"w": 430,
|
||||
"h": 932
|
||||
},
|
||||
{
|
||||
"label": "iPhone 16",
|
||||
"value": "393x852-16",
|
||||
"w": 393,
|
||||
"h": 852
|
||||
},
|
||||
{
|
||||
"label": "iPhone 15 Pro Max",
|
||||
"value": "430x932-15pm",
|
||||
"w": 430,
|
||||
"h": 932
|
||||
},
|
||||
{
|
||||
"label": "iPhone 15 Pro",
|
||||
"value": "393x852-15p",
|
||||
"w": 393,
|
||||
"h": 852
|
||||
},
|
||||
{
|
||||
"label": "iPhone 15 Plus",
|
||||
"value": "430x932-15+",
|
||||
"w": 430,
|
||||
"h": 932
|
||||
},
|
||||
{
|
||||
"label": "iPhone 15",
|
||||
"value": "393x852-15",
|
||||
"w": 393,
|
||||
"h": 852
|
||||
},
|
||||
{
|
||||
"label": "iPhone 14 Plus",
|
||||
"value": "428x926-14+",
|
||||
"w": 428,
|
||||
"h": 926
|
||||
},
|
||||
{
|
||||
"label": "iPhone 14",
|
||||
"value": "390x844-14",
|
||||
"w": 390,
|
||||
"h": 844
|
||||
},
|
||||
{
|
||||
"label": "iPhone 13 mini",
|
||||
"value": "375x812-13m",
|
||||
"w": 375,
|
||||
"h": 812
|
||||
},
|
||||
{
|
||||
"label": "iPhone 11",
|
||||
"value": "414x896-11",
|
||||
"w": 414,
|
||||
"h": 896
|
||||
},
|
||||
{
|
||||
"label": "iPhone SE",
|
||||
"value": "320x568-se",
|
||||
"w": 320,
|
||||
"h": 568
|
||||
},
|
||||
{
|
||||
"label": "Mate 70",
|
||||
"value": "405x896-m70",
|
||||
"w": 405,
|
||||
"h": 896
|
||||
},
|
||||
{
|
||||
"label": "Mate 70 Pro",
|
||||
"value": "438x944-m70p",
|
||||
"w": 438,
|
||||
"h": 944
|
||||
},
|
||||
{
|
||||
"label": "Mate 70 Pro+",
|
||||
"value": "438x944-m70p+",
|
||||
"w": 438,
|
||||
"h": 944
|
||||
},
|
||||
{
|
||||
"label": "Mate 60",
|
||||
"value": "405x896-m60",
|
||||
"w": 405,
|
||||
"h": 896
|
||||
},
|
||||
{
|
||||
"label": "Mate 60 Pro",
|
||||
"value": "420x907-m60p",
|
||||
"w": 420,
|
||||
"h": 907
|
||||
},
|
||||
{
|
||||
"label": "Mate XT-单屏",
|
||||
"value": "336x744-mxt-s",
|
||||
"w": 336,
|
||||
"h": 744
|
||||
},
|
||||
{
|
||||
"label": "Mate XT-双屏",
|
||||
"value": "682x744-mxt-d",
|
||||
"w": 682,
|
||||
"h": 744
|
||||
},
|
||||
{
|
||||
"label": "Mate XT-三屏",
|
||||
"value": "1061x744-mxt-t",
|
||||
"w": 1061,
|
||||
"h": 744
|
||||
},
|
||||
{
|
||||
"label": "Mate X5-展开",
|
||||
"value": "741x832-mx5-u",
|
||||
"w": 741,
|
||||
"h": 832
|
||||
},
|
||||
{
|
||||
"label": "Mate X5-折叠",
|
||||
"value": "360x835-mx5-f",
|
||||
"w": 360,
|
||||
"h": 835
|
||||
},
|
||||
{
|
||||
"label": "小米 15",
|
||||
"value": "400x890-mi15",
|
||||
"w": 400,
|
||||
"h": 890
|
||||
},
|
||||
{
|
||||
"label": "Samsung Galaxy S23",
|
||||
"value": "360x7-s23",
|
||||
"w": 360,
|
||||
"h": 780
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const treeArr = [{"appuuid":"1970803702419685376","buildType":1,"codeType":"html_module","configurationInformation":"{\"freelayoutType\":\"custom\",\"minWidth\":\"\",\"maxWidth\":\"\",\"customWidth\":\"adaptive\",\"customHeight\":\"adaptive\",\"minHeight\":\"\",\"maxHeight\":\"\",\"backgroundType\":\"color\",\"background\":\"#fff\",\"grid\":\"1\",\"height\":\"\",\"width\":\"\"}","createTime":"2025-09-24 19:14:09","createUser":"WX20250924SL0K","default":false,"folderFlag":false,"id":270773,"name":"UI页面起草","pageName":"UI页面起草","pageScene":"web","pageType":"0","pageUuid":"1970808971233067008","sort":3,"status":"0","updateTime":"2025-09-24 20:25:37","updateUser":"WX20250924SL0K","url":"./assets/page/1970808971233067008.html","uuid":"1970808971233067008"}]
|
||||
|
||||
const projectName = '未命名'
|
||||
152
data/智能开发/Agent/assets/javascript/reload.js
Executable file
152
data/智能开发/Agent/assets/javascript/reload.js
Executable file
@@ -0,0 +1,152 @@
|
||||
// 保存原生方法
|
||||
const nativeElementQuerySelector = Element.prototype.querySelector;
|
||||
const nativeDocumentQuerySelector = Document.prototype.querySelector;
|
||||
function ytCustomQuerySelector(selector) {
|
||||
// 第二步:尝试用选择器获取DOM元素
|
||||
// 执行原生选择器查询
|
||||
const foundElement = this === document ?
|
||||
nativeDocumentQuerySelector.call(this, selector) :
|
||||
nativeElementQuerySelector.call(this, selector);
|
||||
|
||||
if (foundElement) {
|
||||
// 设置属性
|
||||
if (!foundElement.hasAttribute('data-selectorname')) {
|
||||
foundElement.setAttribute('data-selectorname', selector);
|
||||
}
|
||||
// 第三步:直接返回找到的元素
|
||||
return foundElement;
|
||||
}
|
||||
|
||||
// 如果通过选择器没找到,尝试通过data-selectorName属性查找
|
||||
const allElements = document.querySelectorAll('[data-selectorname]');
|
||||
for (let i = 0; i < allElements.length; i++) {
|
||||
if (allElements[i].getAttribute('data-selectorname') === selector) {
|
||||
return allElements[i];
|
||||
}
|
||||
}
|
||||
|
||||
// 如果都没找到,返回null
|
||||
return null;
|
||||
}
|
||||
|
||||
// 如果需要也重写querySelectorAll,可以类似实现
|
||||
// 重写原生的querySelector
|
||||
Document.prototype.querySelector = ytCustomQuerySelector
|
||||
Element.prototype.querySelector = ytCustomQuerySelector
|
||||
|
||||
const nativeElementInsertBefore = Element.prototype.insertBefore;
|
||||
|
||||
function ytCustomInsertBefore(newNode, referenceNode) {
|
||||
// 当前元素作为默认父元素
|
||||
const defaultParentNode = this;
|
||||
|
||||
// 检查参考节点是否存在
|
||||
if (!referenceNode) {
|
||||
// 如果没有提供参考节点,直接添加到末尾
|
||||
return nativeElementInsertBefore.call(defaultParentNode, newNode, null);
|
||||
}
|
||||
|
||||
// 检查参考节点是否仍然是父节点的直接子节点
|
||||
if (referenceNode.parentNode === defaultParentNode) {
|
||||
// 正常情况:参考节点仍在父节点下,直接插入
|
||||
return nativeElementInsertBefore.call(defaultParentNode, newNode, referenceNode);
|
||||
}
|
||||
|
||||
// 检查参考节点是否有 data-ytparentvalue 属性(被移动出去的节点)
|
||||
const referenceParentValue = referenceNode.getAttribute('data-ytparentvalue');
|
||||
|
||||
if (referenceParentValue) {
|
||||
// 查找具有匹配 data-ytextravalue 的父元素
|
||||
const actualParentNode = document.querySelector('[data-ytextravalue="' + referenceParentValue + '"]');
|
||||
|
||||
if (actualParentNode) {
|
||||
// 获取参考节点原来的索引位置
|
||||
const originalIndex = referenceNode.getAttribute('data-ytoriginindex');
|
||||
|
||||
if (originalIndex !== null && !isNaN(originalIndex)) {
|
||||
// 获取实际父节点当前的所有子节点
|
||||
const children = Array.from(actualParentNode.children);
|
||||
|
||||
// 查找应该插入的位置
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const child = children[i];
|
||||
const childOriginalIndex = child.getAttribute('data-ytoriginindex');
|
||||
|
||||
// 如果子节点有原始索引,并且比参考节点的原始索引大
|
||||
if (childOriginalIndex !== null && !isNaN(childOriginalIndex)) {
|
||||
if (parseInt(childOriginalIndex) > parseInt(originalIndex)) {
|
||||
// 找到第一个索引更大的节点,插入到它前面
|
||||
return nativeElementInsertBefore.call(actualParentNode, newNode, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有找到更大的索引,插入到最后
|
||||
return nativeElementInsertBefore.call(actualParentNode, newNode, null);
|
||||
}
|
||||
|
||||
// 没有原始索引信息,插入到实际父元素的最后
|
||||
return nativeElementInsertBefore.call(actualParentNode, newNode, null);
|
||||
}
|
||||
}
|
||||
|
||||
// 默认情况:插入到当前父元素的最后
|
||||
return nativeElementInsertBefore.call(defaultParentNode, newNode, null);
|
||||
}
|
||||
|
||||
// 重写原生 insertBefore 方法
|
||||
Element.prototype.insertBefore = ytCustomInsertBefore;
|
||||
|
||||
// 需要给新添加的a标签跳转链接加入一些必要的样式 保证加入后不影响原来的布局
|
||||
function addUniqueStyle(cssText, id = 'custom-style') {
|
||||
const targetDom = document.getElementById(id)
|
||||
if (targetDom && targetDom.tagName === 'STYLE') return; // 已存在则跳过
|
||||
|
||||
const style = document.createElement('style');
|
||||
style.id = id;
|
||||
style.innerHTML = cssText;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
addUniqueStyle('.yt-a-defalut-link[custom-a="true"] > * { margin:0;flex:1; }')
|
||||
|
||||
// 定义要劫持的属性
|
||||
const ytCustomProperties = ['textContent', 'innerText'];
|
||||
|
||||
ytCustomProperties.forEach(prop => {
|
||||
let descriptor = Object.getOwnPropertyDescriptor(Element.prototype, prop) ||
|
||||
Object.getOwnPropertyDescriptor(Node.prototype, prop);
|
||||
if (descriptor && descriptor.set && descriptor.get) {
|
||||
const originalGet = descriptor.get; // 保存原生 getter
|
||||
const originalSet = descriptor.set;
|
||||
Object.defineProperty(Element.prototype, prop, {
|
||||
get: function () {
|
||||
return originalGet.call(this); // 保持原生 getter 逻辑
|
||||
},
|
||||
set: function (value) {
|
||||
// 优先取 data-yteditvalue,否则用传入的 value
|
||||
const finalValue = this.dataset.yteditvalue ?? value;
|
||||
originalSet.call(this, finalValue);
|
||||
},
|
||||
configurable: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function ytCustomLinkNavigation () {
|
||||
const parseWithURLSearchParams = (queryString) => {
|
||||
const params = queryString.split('&')
|
||||
const result = {}
|
||||
params.forEach(param => {
|
||||
const key = param.split('=')[0]
|
||||
const value = param.split('=')[1]
|
||||
result[key] = value
|
||||
})
|
||||
return result
|
||||
}
|
||||
const topWin = window.top
|
||||
const href = window.event.currentTarget.getAttribute('custom-href')
|
||||
if (href) {
|
||||
const newParams = parseWithURLSearchParams(href)
|
||||
topWin.postMessage(newParams.uuid, '*');
|
||||
}
|
||||
}
|
||||
36
data/智能开发/Agent/assets/javascript/tool.js
Executable file
36
data/智能开发/Agent/assets/javascript/tool.js
Executable file
@@ -0,0 +1,36 @@
|
||||
|
||||
function handleCode (code, isWeb) {
|
||||
if (isWeb) {
|
||||
return code;
|
||||
}
|
||||
// 要插入的滚动条样式
|
||||
const scrollbarStyle = `
|
||||
<style>
|
||||
::-webkit-scrollbar {
|
||||
width: 0px;
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
|
||||
// 将样式插入到 <head> 标签内(如果存在 <head>)
|
||||
let modifiedHtml = code;
|
||||
if (/\s*<\/head\s*>/i.test(modifiedHtml)) {
|
||||
modifiedHtml = modifiedHtml.replace(/(\s*<\/head\s*>)/i, `${scrollbarStyle}$1`);
|
||||
} else {
|
||||
// 如果没有 <head>,直接插入到 <html> 之后
|
||||
modifiedHtml = modifiedHtml.replace('<html>', `<html>${scrollbarStyle}`);
|
||||
}
|
||||
return modifiedHtml
|
||||
}
|
||||
|
||||
|
||||
const useEventListener = (element, eventType, callback, useCapture = false) => {
|
||||
if (!element || !callback) return null;
|
||||
|
||||
const handler = (event) => callback(event);
|
||||
element.addEventListener(eventType, handler, useCapture);
|
||||
|
||||
return () => {
|
||||
element.removeEventListener(eventType, handler, useCapture);
|
||||
};
|
||||
};
|
||||
18193
data/智能开发/Agent/assets/javascript/vue.global.js
Executable file
18193
data/智能开发/Agent/assets/javascript/vue.global.js
Executable file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user