Commit 8a629996 authored by 高如斌's avatar 高如斌

1

parent 8bcd41e5
...@@ -202,6 +202,9 @@ frontend/.env.development.local ...@@ -202,6 +202,9 @@ frontend/.env.development.local
frontend/.env.test.local frontend/.env.test.local
frontend/.env.production.local frontend/.env.production.local
# Kiro IDE files
.kiro/
# OS generated files # OS generated files
Thumbs.db Thumbs.db
.DS_Store .DS_Store
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
"highlight.js": "^11.9.0", "highlight.js": "^11.9.0",
"marked": "^17.0.1", "marked": "^17.0.1",
"pako": "^2.1.0", "pako": "^2.1.0",
"pangea-ui": "^0.14.2-beta.9",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"snabbdom": "^3.6.3", "snabbdom": "^3.6.3",
"vue": "^3.4.0", "vue": "^3.4.0",
...@@ -26,11 +27,13 @@ ...@@ -26,11 +27,13 @@
"vue-router": "^4.3.0" "vue-router": "^4.3.0"
}, },
"devDependencies": { "devDependencies": {
"@arco-design/web-vue": "^2.55.3",
"@types/dompurify": "^3.0.5", "@types/dompurify": "^3.0.5",
"@types/node": "^20.10.0", "@types/node": "^20.10.0",
"@vitejs/plugin-vue": "^5.0.0", "@vitejs/plugin-vue": "^5.0.0",
"eslint": "^8.55.0", "eslint": "^8.55.0",
"eslint-plugin-vue": "^9.19.0", "eslint-plugin-vue": "^9.19.0",
"less": "^4.2.0",
"terser": "^5.44.1", "terser": "^5.44.1",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"vite": "^5.0.0", "vite": "^5.0.0",
......
This diff is collapsed.
<template>
<hi-page-template
ref="templateRef"
:json="json"
:open-intl="false"
></hi-page-template>
<div class="button-wrap">
<a-button type="primary" @click="submit">提交</a-button>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import HiPageTemplate from "pangea-ui/hi-page-template";
const templateRef = ref();
const submit = () => {
templateRef.value?.ctx.validate(1, (res, data) => {
console.log(res, data);
});
};
const json = {
pages: [
{
key: 0,
type: "default",
name: "默认页",
code: "",
display: "",
props: {
margin: "16px",
padding: "12px",
backgroundColor: "white",
display: {},
},
bindProps: {},
coms: [
{
key: 1,
type: "node",
name: "表单容器",
code: "HiFormContainer",
display: "",
props: {
status: "default",
backgroundColor: "transparent",
layout: "horizontal",
size: "medium",
labelAlign: "right",
display: {},
borderRadius: {},
boxShadow: {},
loop: {
data: [],
},
},
bindProps: {},
coms: [
{
key: 1766473421208,
name: "输入框",
code: "HiInput",
props: {
title: "输入框",
status: "default",
placeholder: "请输入",
name: "INPUT_6CP8HIBK",
},
bindProps: {},
coms: [],
},
{
key: 1766476676439,
name: "日期",
code: "HiDatePicker",
props: {
title: "日期",
type: "date",
format: "YYYY-MM-DD",
status: "default",
name: "DATE_PA9TUPQQ",
},
bindProps: {},
},
],
},
],
},
],
params: [],
apis: [],
funcs: [],
pageTemplate: {},
};
</script>
<style scoped>
.button-wrap {
display: flex;
justify-content: center;
}
</style>
<template> <template>
<div class="work-area"> <div class="work-area">
<el-tabs v-model="activeTab" class="work-tabs"> <el-tabs v-model="activeTab" class="work-tabs">
<el-tab-pane label="表单" name="form">
<form-render ref="formRender" />
</el-tab-pane>
<el-tab-pane label="📋 时间轴" name="timeline"> <el-tab-pane label="📋 时间轴" name="timeline">
<timeline-container ref="timelineContainerRef" /> <timeline-container ref="timelineContainerRef" />
</el-tab-pane> </el-tab-pane>
...@@ -12,108 +15,121 @@ ...@@ -12,108 +15,121 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue' import { ref, onMounted, onUnmounted } from "vue";
import TimelineContainer from './TimelineContainer.vue' import FormRender from "./FormRender.vue";
import WebpageBrowser from './WebpageBrowser.vue' import TimelineContainer from "./TimelineContainer.vue";
import { TimelineService } from '../services/TimelineService' import WebpageBrowser from "./WebpageBrowser.vue";
import { TimelineService } from "../services/TimelineService";
const activeTab = ref('timeline')
const timelineContainerRef = ref<InstanceType<typeof TimelineContainer> | null>(null) const activeTab = ref("form");
const webBrowser = ref() const formRender = ref();
let timelineService: TimelineService | null = null const timelineContainerRef = ref<InstanceType<typeof TimelineContainer> | null>(
null
);
const webBrowser = ref();
let timelineService: TimelineService | null = null;
// 添加事件到时间轴 // 添加事件到时间轴
const addEvent = (event: any): void => { const addEvent = (event: any): void => {
timelineContainerRef.value?.addEvent(event) timelineContainerRef.value?.addEvent(event);
} };
// 初始化Timeline服务 // 初始化Timeline服务
const initTimelineService = () => { const initTimelineService = () => {
if (timelineContainerRef.value) { if (timelineContainerRef.value) {
timelineService = new TimelineService((event: any) => { timelineService = new TimelineService((event: any) => {
addEvent(event) addEvent(event);
}) });
timelineService.connectSSE() timelineService.connectSSE();
} }
} };
// 清除时间轴 // 清除时间轴
const clearTimeline = (): void => { const clearTimeline = (): void => {
timelineContainerRef.value?.clearTimeline() timelineContainerRef.value?.clearTimeline();
} };
// 定义embed事件的详细信息类型 // 定义embed事件的详细信息类型
interface EmbedEventDetail { interface EmbedEventDetail {
url: string url: string;
type: string type: string;
title: string title: string;
htmlContent?: string htmlContent?: string;
} }
// 监听embed事件 // 监听embed事件
const handleEmbedEvent = (e: Event) => { const handleEmbedEvent = (e: Event) => {
const customEvent = e as CustomEvent<EmbedEventDetail> const customEvent = e as CustomEvent<EmbedEventDetail>;
const { url, type, title, htmlContent } = customEvent.detail const { url, type, title, htmlContent } = customEvent.detail;
// 验证URL有效性 // 验证URL有效性
if (!url || typeof url !== 'string' || url.trim() === '') { if (!url || typeof url !== "string" || url.trim() === "") {
console.error('[WorkArea] embed事件URL验证失败:', { console.error("[WorkArea] embed事件URL验证失败:", {
url: url, url: url,
type: typeof url, type: typeof url,
isEmpty: url?.trim() === '', isEmpty: url?.trim() === "",
detail: customEvent.detail detail: customEvent.detail,
}) });
return return;
} }
// 自动切换到浏览器标签页 // 自动切换到浏览器标签页
activeTab.value = 'browser' activeTab.value = "browser";
// 调用WebpageBrowser的导航方法,传递完整信息 // 调用WebpageBrowser的导航方法,传递完整信息
if (webBrowser.value && typeof webBrowser.value.navigateToUrl === 'function') { if (
webBrowser.value &&
typeof webBrowser.value.navigateToUrl === "function"
) {
webBrowser.value.navigateToUrl(url, { webBrowser.value.navigateToUrl(url, {
htmlContent: htmlContent, htmlContent: htmlContent,
embedType: type, embedType: type,
embedTitle: title embedTitle: title,
}) });
} else { } else {
console.error('[WorkArea] webBrowser引用无效或navigateToUrl方法不存在', { console.error("[WorkArea] webBrowser引用无效或navigateToUrl方法不存在", {
hasWebBrowser: !!webBrowser.value, hasWebBrowser: !!webBrowser.value,
hasFn: webBrowser.value ? typeof webBrowser.value.navigateToUrl : 'undefined' hasFn: webBrowser.value
}) ? typeof webBrowser.value.navigateToUrl
: "undefined",
});
} }
} };
onMounted(() => { onMounted(() => {
// 监听embed事件 // 监听embed事件
window.addEventListener('embed-event', handleEmbedEvent as EventListener) window.addEventListener("embed-event", handleEmbedEvent as EventListener);
// 初始化Timeline服务 // 初始化Timeline服务
initTimelineService() initTimelineService();
}) });
onUnmounted(() => { onUnmounted(() => {
// 移除事件监听 // 移除事件监听
window.removeEventListener('embed-event', handleEmbedEvent as EventListener) window.removeEventListener("embed-event", handleEmbedEvent as EventListener);
// 清理Timeline服务 // 清理Timeline服务
if (timelineService) { if (timelineService) {
timelineService.cleanup() timelineService.cleanup();
} }
})// 暴露方法供父组件调用 }); // 暴露方法供父组件调用
defineExpose({ defineExpose({
formRender,
timelineContainerRef, timelineContainerRef,
webBrowser, webBrowser,
activeTab, activeTab,
// 提供切换tab的方法 // 提供切换tab的方法
switchToForm: () => {
activeTab.value = "form";
},
switchToTimeline: () => { switchToTimeline: () => {
activeTab.value = 'timeline' activeTab.value = "timeline";
}, },
switchToBrowser: () => { switchToBrowser: () => {
activeTab.value = 'browser' activeTab.value = "browser";
}, },
// 提供时间轴操作方法 // 提供时间轴操作方法
addEvent, addEvent,
clearTimeline clearTimeline,
}) });
</script> </script>
<style scoped> <style scoped>
......
...@@ -4,6 +4,9 @@ import router from './router' ...@@ -4,6 +4,9 @@ import router from './router'
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import ElementPlus from 'element-plus' import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css' import 'element-plus/dist/index.css'
import ArcoVue from "@arco-design/web-vue";
import ArcoVueIcon from "@arco-design/web-vue/es/icon";
import '@arco-design/web-vue/dist/arco.less';
import 'highlight.js/styles/atom-one-dark.css' import 'highlight.js/styles/atom-one-dark.css'
import './styles/variables.css' import './styles/variables.css'
import './styles/global.css' import './styles/global.css'
...@@ -17,6 +20,8 @@ const app = createApp(App) ...@@ -17,6 +20,8 @@ const app = createApp(App)
app.use(createPinia()) app.use(createPinia())
app.use(router) app.use(router)
app.use(ElementPlus) app.use(ElementPlus)
app.use(ArcoVue)
app.use(ArcoVueIcon)
// 全局注册所有Element Plus图标 // 全局注册所有Element Plus图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) { for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment