预览提交

This commit is contained in:
jingna 2025-06-06 16:55:30 +08:00
parent ac50f51518
commit a6ccedc85b
17 changed files with 725 additions and 67 deletions

View File

@ -585,4 +585,30 @@ defineExpose({
.ed-select-group__wrap:not(:last-of-type)::after{
background: #434343 !important;
}
.ed-select .ed-input.is-focus .ed-input__wrapper{
box-shadow: none !important;
}
.ed-select:hover:not(.ed-select--disabled) .ed-input__wrapper{
box-shadow: none !important;
}
.ed-select .ed-input__wrapper.is-focus{
box-shadow: none !important;
}
.ed-dropdown-menu{
background-color: rgb(41, 41, 41);
}
.ed-dropdown-menu__item{
color: #fff;
}
.ed-dropdown-menu__item--divided{
border-top: 1px solid #5f5f5f;
}
.ed-dropdown-menu__item:not(.is-disabled):hover{
background-color: rgb(61, 61, 61);
}
.ed-dropdown__popper.ed-popper{
border: 1px solid #5f5f5f;
background:transparent;
}
</style>

View File

@ -228,11 +228,18 @@ export const routes: AppRouteRecordRaw[] = [
component: () => import('@/viewsnew/application/PreviewSystem.vue')
},
{
path: '/SfcEditor',
name: 'SfcEditor',
path: '/editNavbar',
name: 'editNavbar',
hidden: true,
meta: {},
component: () => import('@/viewsnew/application/SfcEditor/index.vue')
component: () => import('@/viewsnew/application/SfcEditor/NavbarEditor/editNavbar.vue')
},
{
path: '/editLogin',
name: 'editLogin',
hidden: true,
meta: {},
component: () => import('@/viewsnew/application/SfcEditor/LoginEditor/editlogin.vue')
},
{
path: '/SystemLogin',

View File

@ -1,7 +1,6 @@
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
// import Navbar from '@/viewsnew/application/SfcEditor/Navbar.vue'
import Navbar from '@/viewsnew/application/sfcEditor/previewNavSfc.vue'
import Navbar from '@/viewsnew/application/sfcEditor/NavbarEditor/previewNavSfc.vue'
import { useRoute, useRouter } from 'vue-router'
import { getMenuTree } from '@/api/permission/menu'
import { moduleList } from '@/api/application/module'

View File

@ -0,0 +1,353 @@
<template>
<div id="app">
<div class="sfc-header">
<div class="sfc-header-left">
<!-- <div class="return-box"><img src="@/assets/newimg/u594.png" alt=""></div> -->
<div class="sfc-header-icon"><img src="@/assets/newimg/logosmall.png" alt=""></div>
<div class="sfc-header-title">{{ hearderName }}</div>
</div>
</div>
<div class="sfc-content">
<el-tabs v-model="activeName" type="border-card" class="demo-tabs" @tab-change="handleClick"
style="height: calc(100vh - 100px);">
<el-tab-pane label="代码" name="代码">
<div style="height: calc(100vh - 215px);">
<textarea v-model="sfcCode"></textarea>
</div>
<div class="sfc-content-bottom">
<el-button type="primary" @click="importTemplate">导入模板</el-button>
<el-button type="primary" @click="saveClick">保存</el-button>
</div>
</el-tab-pane>
<el-tab-pane label="预览" name="预览" style="height: calc(100vh - 190px);">
<div ref="previewContainer" class="preview"></div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, reactive, nextTick } from 'vue'
import { ElMessage } from 'element-plus-secondary'
import { useRoute, useRouter } from 'vue-router'
import * as Vue from 'vue/dist/vue.esm-bundler.js'
import ElementPlus from 'element-plus'
import * as VueRouter from 'vue-router'
import { loadModule } from 'vue3-sfc-loader'
import less from 'less'
import defaultTemplate from '@/viewsnew/application/SfcEditor/LoginEditor/login.vue?raw'
import 'element-plus/dist/index.css'
import { i18n } from '@/plugins/vue-i18n'
import { moduleUpdate,moduleById } from '@/api/application/module'
const route = useRoute()
const router = useRouter()
const activeName: any = ref('代码')
const hearderName: any = ref('')
const sfcCode = ref('')
const previewContainer = ref(null)
let prevApp = null
const applicationId: any = ref('')
const menuList: any = ref([])
const appname: any = ref('')
const dvId: any = ref('')
// Base64
const convertToBase64 = async (imagePath) => {
try {
//
const resolvedPath = imagePath.replace('@/', '/src/')
const response = await fetch(resolvedPath)
if (!response.ok) throw new Error(`图片加载失败: ${response.status}`)
const blob = await response.blob()
return new Promise((resolve) => {
const reader = new FileReader()
reader.onloadend = () => resolve(reader.result)
reader.readAsDataURL(blob)
})
} catch (error) {
console.error('Base64转换失败:', error.message)
return ''
}
}
const runCode = async () => {
try {
if (prevApp) {
prevApp.unmount()
previewContainer.value.innerHTML = ''
}
const options = {
moduleCache: {
vue: Vue,
'element-plus': ElementPlus,
'vue/dist/vue.esm-bundler.js': Vue,
'vue-router': VueRouter
},
getFile: async (fileName) => {
if (fileName.startsWith('@/')) {
const resolvedPath = fileName.replace('@/', '/src/')
try {
const response = await fetch(resolvedPath)
return { content: await response.text() }
} catch (e) {
console.error(`文件加载失败: ${resolvedPath}`, e)
return { content: '<!-- 文件加载失败 -->' }
}
}
if (fileName === 'dynamic.vue') {
let code = sfcCode.value
// Lessscoped
const lessRegex = /<style\s+.*?lang="less".*?>(.*?)<\/style>/gis
let match
while ((match = lessRegex.exec(code)) !== null) {
const [full, content] = match
try {
const { css } = await less.render(content, {
paths: ['.'], //
filename: 'dynamic.less'
})
code = code.replace(full, `<style>${css}</style>`)
} catch (e) {
console.error('Less编译错误:', e.message)
code = code.replace(full, `<style>/* Less Error: ${e.message} */</style>`)
}
}
//
const imgRegex = /src=['"](.+?\.(png|jpg|jpeg))['"]/gi
let imgMatch
while ((imgMatch = imgRegex.exec(code)) !== null) {
const [full, path] = imgMatch
const base64 = await convertToBase64(path)
code = code.replace(full, `src="${base64}"`)
}
return code
.replace(/<\/script>/g, '<\\/script>')
.replace(/\\\//g, '/')
}
// Less
if (fileName.endsWith('.less')) {
const resolvedPath = fileName.replace('@/', '/src/')
try {
const response = await fetch(resolvedPath)
const content = await response.text()
const { css } = await less.render(content, { filename: fileName })
return { content: css, mediaType: 'text/css' }
} catch (e) {
return { content: `/* Less Error: ${e.message} */`, mediaType: 'text/css' }
}
}
return ''
},
addStyle: (css) => {
const style = document.createElement('style')
style.textContent = css
document.head.appendChild(style)
},
compiledCache: new Map(),
compileTemplate: true
}
const componentModule = await loadModule('dynamic.vue', options)
const component = componentModule.default || componentModule
const dynamicProps = ref({
id: route.query.dvId,
name: route.query.appname,
isExecuteEvent:true
})
// prevApp = Vue.createApp({
// render: () => Vue.h(component, dynamicProps.value)
// })
prevApp = Vue.createApp({
render: () => Vue.h(component, {
...dynamicProps.value,
router: router,
route: route
})
})
//
prevApp.use(router)
prevApp.use(ElementPlus)
prevApp.use(i18n)
prevApp.mount(previewContainer.value)
} catch (error) {
console.error('运行时错误:', error)
previewContainer.value.innerHTML = `
<div class="error">
<h3>错误</h3>
<pre>${error.message}</pre>
</div>
`
}
}
onMounted(() => {
hearderName.value = route.query.name
if (route.query.appId) {
applicationId.value = route.query.appId
appname.value = route.query.appname
dvId.value = route.query.dvId
getmenuinfo()
}
})
function importTemplate(){
sfcCode.value = defaultTemplate
}
function getmenuinfo() {
moduleById(dvId.value).then(res => {
if(res.data.data.canvas_style_data){
sfcCode.value = res.data.data.canvas_style_data
}
})
}
function goBack() {
router.push({
path: '/module',
query: {
id: route.query.appId
}
})
}
function handleClick() {
if (activeName.value == '预览') {
runCode()
}
}
function saveClick(){
const params = {
canvasStyleData:sfcCode.value,
componentData:'',
id:dvId.value
}
moduleUpdate(params).then(res => {
if(res.data.code == '0'){
ElMessage.success('保存成功')
}else{
ElMessage.error('保存失败')
}
})
}
</script>
<style scoped>
#app {
font-family: Arial, sans-serif;
margin: 0 auto;
width: 100%;
height: 100vh;
background: rgb(21, 21, 21);
}
.sfc-header {
width: 100%;
height: 60px;
background-color: #252626;
border-bottom: 1px solid #4f5052;
display: flex;
align-items: center;
color: #fff;
padding: 0px 20px;
}
.sfc-header-left {
display: flex;
align-items: center;
}
.sfc-header-icon {
display: flex;
justify-content: center;
align-items: center;
width: 36px;
height: 36px;
cursor: pointer;
}
.return-box {
display: flex;
justify-content: center;
align-items: center;
width: 36px;
height: 36px;
cursor: pointer;
}
.return-box:hover {
background-color: rgba(255, 255, 255, 0.1);
}
.sfc-header-title {
font-family: 'Arial Negreta', 'Arial Normal', 'Arial';
font-weight: 700;
font-style: normal;
font-size: 16px;
color: #F2F4F5;
padding-left: 14px;
}
.sfc-content {
height: calc(100vh -60px);
padding: 10px 20px;
color: #fff;
}
textarea {
flex: 1;
margin-bottom: 10px;
font-family: Monaco, monospace;
padding: 10px;
background: #252626;
width: 100%;
height: 100%;
color: #ffffff;
}
.sfc-content-bottom {
margin-top: 10px;
display: flex;
justify-content: flex-end;
}
.preview {
width: 100%;
height: 100%;
}
:deep(.ed-tabs__item) {
color: #fff !important;
padding-right: 0px;
}
:deep(.ed-tabs__header) {
border-bottom: 1px solid #4f5052;
}
:deep(.ed-tabs__item.is-active) {
color: #0089ff !important;
}
:deep(.ed-tabs__active-bar) {
background-color: #0089ff !important;
}
:deep(.ed-tabs--border-card) {
background: rgb(21, 21, 21);
border-color: #4f5052;
}
:deep(.ed-tabs--border-card>.ed-tabs__header) {
background: rgb(21, 21, 21);
}
:deep(.ed-tabs--border-card>.ed-tabs__header .ed-tabs__item.is-active) {
background: rgb(21, 21, 21);
border-color: #4f5052;
border-bottom: none;
}
:deep(.ed-button) {
background-color: #0089ff;
}
</style>

View File

@ -1,11 +1,13 @@
<script lang="ts" setup>
import { ref, watch, onMounted, onBeforeUnmount, shallowRef } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { useRouter } from 'vue-router'
import {useRoute, useRouter } from 'vue-router'
const router = useRouter()
const route = useRoute()
const props = defineProps({
id: String,
name: String
name: String,
isExecuteEvent: Boolean,
})
const form = ref({
username: '',
@ -22,6 +24,9 @@ const loginRules = ref({
const ruleFormRef = ref<FormInstance>()
const loginTitle: any = ref('')
const submitForm = async (formEl: FormInstance | undefined) => {
if(props.isExecuteEvent){
return
}
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
@ -74,7 +79,6 @@ onBeforeUnmount(() => {
</el-form-item>
<div class="login-button" @click="submitForm(ruleFormRef)">登录</div>
</el-form>
</div>
</div>
</div>

View File

@ -0,0 +1,192 @@
<template>
<div class="editor">
<div ref="previewContainer" class="preview"></div>
</div>
</template>
<script setup>
import { ref, onMounted,onUnmounted } from 'vue'
import { loadModule } from 'vue3-sfc-loader'
import * as Vue from 'vue/dist/vue.esm-bundler.js'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import less from 'less'
import { i18n } from '@/plugins/vue-i18n'
import * as VueRouter from 'vue-router'
import { useRoute, useRouter } from 'vue-router'
import { moduleUpdate,moduleById } from '@/api/application/module'
const route = useRoute()
const router = useRouter()
const props = defineProps({
name:String,
id:String,
isExecuteEvent: Boolean,
})
const sfcCode = ref('')
const previewContainer = ref(null)
let prevApp = null
// Base64
const convertToBase64 = async (imagePath) => {
try {
//
const resolvedPath = imagePath.replace('@/', '/src/')
const response = await fetch(resolvedPath)
if (!response.ok) throw new Error(`图片加载失败: ${response.status}`)
const blob = await response.blob()
return new Promise((resolve) => {
const reader = new FileReader()
reader.onloadend = () => resolve(reader.result)
reader.readAsDataURL(blob)
})
} catch (error) {
console.error('Base64转换失败:', error.message)
return ''
}
}
const runCode = async () => {
try {
if (prevApp) {
prevApp.unmount()
previewContainer.value.innerHTML = ''
}
const options = {
moduleCache: {
vue: Vue,
'element-plus': ElementPlus,
'vue/dist/vue.esm-bundler.js': Vue,
'vue-router': VueRouter
},
getFile: async (fileName) => {
if (fileName.startsWith('@/')) {
const resolvedPath = fileName.replace('@/', '/src/')
try {
const response = await fetch(resolvedPath)
return { content: await response.text() }
} catch (e) {
console.error(`文件加载失败: ${resolvedPath}`, e)
return { content: '<!-- 文件加载失败 -->' }
}
}
if (fileName === 'dynamic.vue') {
let code = sfcCode.value
// Lessscoped
const lessRegex = /<style\s+.*?lang="less".*?>(.*?)<\/style>/gis
let match
while ((match = lessRegex.exec(code)) !== null) {
const [full, content] = match
try {
const { css } = await less.render(content, {
paths: ['.'], //
filename: 'dynamic.less'
})
code = code.replace(full, `<style>${css}</style>`)
} catch (e) {
console.error('Less编译错误:', e.message)
code = code.replace(full, `<style>/* Less Error: ${e.message} */</style>`)
}
}
//
const imgRegex = /src=['"](.+?\.(png|jpg|jpeg))['"]/gi
let imgMatch
while ((imgMatch = imgRegex.exec(code)) !== null) {
const [full, path] = imgMatch
const base64 = await convertToBase64(path)
code = code.replace(full, `src="${base64}"`)
}
return code
.replace(/<\/script>/g, '<\\/script>')
.replace(/\\\//g, '/')
}
// Less
if (fileName.endsWith('.less')) {
const resolvedPath = fileName.replace('@/', '/src/')
try {
const response = await fetch(resolvedPath)
const content = await response.text()
const { css } = await less.render(content, { filename: fileName })
return { content: css, mediaType: 'text/css' }
} catch (e) {
return { content: `/* Less Error: ${e.message} */`, mediaType: 'text/css' }
}
}
return ''
},
addStyle: (css) => {
const style = document.createElement('style')
style.textContent = css
document.head.appendChild(style)
},
compiledCache: new Map(),
compileTemplate: true
}
const componentModule = await loadModule('dynamic.vue', options)
const component = componentModule.default || componentModule
const dynamicProps = ref({
id: props.id,
name: props.name,
isExecuteEvent:props.isExecuteEvent
})
prevApp = Vue.createApp({
render: () => Vue.h(component, {
...dynamicProps.value,
router: router,
route: route
})
})
//
prevApp.use(router)
prevApp.use(ElementPlus)
prevApp.use(i18n)
prevApp.mount(previewContainer.value)
} catch (error) {
console.error('运行时错误:', error)
previewContainer.value.innerHTML = `
<div class="error">
<h3>错误</h3>
<pre>${error.message}</pre>
</div>
`
}
}
onMounted(() => {
init()
})
function init(){
moduleById(props.id).then(res => {
if(res.data.data.canvas_style_data){
sfcCode.value = res.data.data.canvas_style_data
runCode()
}
})
}
</script>
<style>
/* 保留原有样式并补充 */
.editor {
display: flex;
flex-direction: column;
width: 100%;
height: 100vh;
overflow: hidden;
}
textarea {
flex: 1;
margin-bottom: 10px;
font-family: Monaco, monospace;
padding: 10px;
}
.preview {
width: 100%;
height: 100vh;
flex: 1;
overflow: hidden;
}
</style>

View File

@ -1,7 +1,8 @@
<script lang="ts" setup>
import { ref,watch, onMounted,onBeforeUnmount,shallowRef } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import Assocmodule from '@/viewsnew/application/SfcEditor/assocPage.vue'
import Assocmodule from '@/viewsnew/application/SfcEditor/NavbarEditor/assocPage.vue'
import PermissionSet from '@/viewsnew/application/permissionset/index.vue'
const props = defineProps({
menuList: {
type: Array, //
@ -19,12 +20,12 @@ const navmenulist:any = ref([
const checkindex = ref(null)
const showmodule = ref(false)
const currentMoudleId = ref('')
const showermission = ref(false)
watch(
() => props.menuList,
(newVal) => {
if (newVal) {
navmenulist.value = newVal
console.log(newVal)
}
},
{ immediate: true } //
@ -36,13 +37,14 @@ function menuclick(index:any) {
return
}
currentMoudleId.value = navmenulist.value[index].module_id
showmodule.value = true
}
}
function childmenuclick(item:any){
console.log(item,props.isExecuteEvent)
if(props.isExecuteEvent){
return
}
showermission.value = false
showmodule.value = false
if(item.module_id && item.module_id !== ''){
currentMoudleId.value = item.module_id
@ -98,6 +100,10 @@ onMounted(() => {
onBeforeUnmount(() => {
});
function permissionClick(){
showmodule.value = false
showermission.value = true
}
</script>
<template>
<div class="system-box">
@ -122,7 +128,7 @@ onBeforeUnmount(() => {
</div>
</div>
<div class="Navbar-box-right">
<div style="margin-right: 10px;"><img src="@/assets/img/nav1.png" alt=""></div>
<div style="margin-right: 10px;cursor: pointer;" @click="permissionClick"><img src="@/assets/img/nav1.png" alt=""></div>
<div style="margin-right: 15px;min-width: 45px;">admin</div>
<div style="margin-right: 15px;"><img src="@/assets/img/nav3.png" alt=""></div>
<div><img src="@/assets/img/nav4.png" alt=""></div>
@ -132,6 +138,7 @@ onBeforeUnmount(() => {
<div v-if="!props.isExecuteEvent" class="system-box-content" :style="{height:props.isFixed?'calc(100vh - 65px)':'calc(100vh - 125px)'}">
<Assocmodule v-if="showmodule" :applicationId="props.applicationId"
:moduleinfo="{module_id:currentMoudleId}" />
<!-- <PermissionSet v-if="showermission" /> -->
</div>
</div>
</template>

View File

@ -5,7 +5,7 @@ import FormCreate from '@/viewsnew/common/FormCreate.vue'
import { initCanvasData } from '@/utils/canvasUtils'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { moduleList } from '@/api/application/module'
import Navbar from '@/viewsnew/application/SfcEditor/assocPage.vue'
import Navbar from '@/viewsnew/application/SfcEditor/NavbarEditor/assocPage.vue'
const props = defineProps({
moduleinfo:Object,
applicationId:String
@ -89,16 +89,20 @@ function handleNodeClick(e){
if(e.type == '0301'){
busiFlag.value = 'dashboard'
loadCanvasData(e.id,9,0)
loading.value = false
}else if(e.type == '03'){
busiFlag.value = 'dataV'
loading.value = false
loadCanvasData(e.id,9,0)
}else if(e.type == '09'){
}else if(e.type == '04'||e.type == '05'||e.type == '06'){
moduleInfo.value = e
isFormCreate.value = true
loading.value = false
} else if(e.type == '02'){
isNavbar.value = true
}
loading.value = false
}
}
</script>
<template>

View File

@ -1,7 +1,5 @@
<template>
<div id="app">
<!-- <h1>Vue 3 SFC 在线编辑器</h1>
<SfcEditor /> -->
<div class="sfc-header">
<div class="sfc-header-left">
<!-- <div class="return-box"><img src="@/assets/newimg/u594.png" alt=""></div> -->
@ -17,7 +15,7 @@
<textarea v-model="sfcCode"></textarea>
</div>
<div class="sfc-content-bottom">
<el-button type="primary">导入模板</el-button>
<el-button type="primary" @click="importNav">导入模板</el-button>
<el-button type="primary" @click="saveClick">保存</el-button>
</div>
</el-tab-pane>
@ -37,7 +35,7 @@ import { loadModule } from 'vue3-sfc-loader'
import * as Vue from 'vue/dist/vue.esm-bundler.js'
import ElementPlus from 'element-plus'
import less from 'less'
import defaultTemplate from '@/viewsnew/application/SfcEditor/Navbar.vue?raw'
import defaultTemplate from '@/viewsnew/application/SfcEditor/NavbarEditor/Navbar.vue?raw'
import { getMenuTree } from '@/api/permission/menu'
import { moduleUpdate,moduleById } from '@/api/application/module'
import 'element-plus/dist/index.css'
@ -81,8 +79,8 @@ const runCode = async () => {
vue: Vue,
'element-plus': ElementPlus,
'vue/dist/vue.esm-bundler.js': Vue,
'@/viewsnew/application/SfcEditor/assocPage.vue': Vue.defineAsyncComponent(() =>
import('@/viewsnew/application/SfcEditor/assocPage.vue'))
'@/viewsnew/application/SfcEditor/NavbarEditor/assocPage.vue': Vue.defineAsyncComponent(() =>
import('@/viewsnew/application/SfcEditor/NavbarEditor/assocPage.vue'))
},
getFile: async (fileName) => {
if (fileName.startsWith('@/')) {
@ -198,7 +196,6 @@ function getmenuinfo() {
if(res.data.data.canvas_style_data){
sfcCode.value = res.data.data.canvas_style_data
}
})
}
function goBack() {
@ -216,7 +213,6 @@ function handleClick() {
}
}
function saveClick(){
// console.log(typeof(sfcCode.value))
const params = {
canvasStyleData:sfcCode.value,
componentData:'',
@ -230,6 +226,9 @@ function saveClick(){
}
})
}
function importNav(){
sfcCode.value = defaultTemplate
}
</script>
<style scoped>

View File

@ -4,15 +4,19 @@
</div>
</template>
<script setup>
import { ref, onMounted,onUnmounted } from 'vue'
import { ref, onMounted, onUnmounted } from 'vue'
import { loadModule } from 'vue3-sfc-loader'
import * as Vue from 'vue/dist/vue.esm-bundler.js'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import less from 'less'
import * as VueRouter from 'vue-router'
import { useRoute, useRouter } from 'vue-router'
import { i18n } from '@/plugins/vue-i18n'
import defaultTemplate from '@/viewsnew/application/SfcEditor/Navbar.vue?raw'
import { moduleUpdate,moduleById } from '@/api/application/module'
import defaultTemplate from '@/viewsnew/application/SfcEditor/NavbarEditor/Navbar.vue?raw'
import { moduleUpdate, moduleById } from '@/api/application/module'
const route = useRoute()
const router = useRouter()
const props = defineProps({
menuList: {
type: Array,
@ -62,9 +66,13 @@ const runCode = async () => {
vue: Vue,
'element-plus': ElementPlus,
'vue/dist/vue.esm-bundler.js': Vue,
'@/viewsnew/application/SfcEditor/assocPage.vue': Vue.defineAsyncComponent(() =>
import('@/viewsnew/application/SfcEditor/assocPage.vue')
'vue-router': VueRouter,
'@/viewsnew/application/SfcEditor/NavbarEditor/assocPage.vue': Vue.defineAsyncComponent(() =>
import('@/viewsnew/application/SfcEditor/NavbarEditor/assocPage.vue')
),
'@/viewsnew/application/permissionset/index.vue': Vue.defineAsyncComponent(() =>
import('@/viewsnew/application/permissionset/index.vue')
)
},
getFile: async (fileName) => {
if (fileName === 'dynamic.vue') {
@ -121,8 +129,15 @@ const runCode = async () => {
isExecuteEvent: props.isExecuteEvent
})
// createApp
// prevApp = Vue.createApp({
// render: () => Vue.h(component, dynamicProps)
// })
prevApp = Vue.createApp({
render: () => Vue.h(component, dynamicProps)
render: () => Vue.h(component, {
...dynamicProps,
router: router,
route: route
})
})
prevApp.use(i18n)
prevApp.use(ElementPlus)
@ -141,10 +156,11 @@ const runCode = async () => {
onMounted(() => {
init()
})
function init(){
function init() {
moduleById(props.projectId).then(res => {
if(res.data.data.canvas_style_data){
sfcCode.value = res.data.data.canvas_style_data
if (res.data.data.canvas_style_data) {
// sfcCode.value = res.data.data.canvas_style_data
sfcCode.value = defaultTemplate
runCode()
}
})

View File

@ -1,5 +1,5 @@
<script lang="ts" setup>
import { ref,watch, onMounted,onBeforeUnmount } from 'vue'
import { ref, watch, onMounted, onBeforeUnmount } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import * as VueRouter from 'vue-router'
@ -8,7 +8,8 @@ import * as Vue from 'vue/dist/vue.esm-bundler.js'
import { i18n } from '@/plugins/vue-i18n'
import ElementPlus from 'element-plus'
import less from 'less'
import defaultTemplate from '@/viewsnew/application/SfcEditor/login.vue?raw'
import defaultTemplate from '@/viewsnew/application/SfcEditor/LoginEditor/login.vue?raw'
import { moduleList, moduleById } from '@/api/application/module'
const route = useRoute()
const router = useRouter()
const sfcCode = ref(defaultTemplate)
@ -117,6 +118,7 @@ const runCode = async () => {
const dynamicProps = ref({
id: route.query.id,
name: route.query.name,
isExecuteEvent: false
})
// prevApp = Vue.createApp({
// render: () => Vue.h(component, dynamicProps.value)
@ -146,8 +148,31 @@ const runCode = async () => {
}
}
onMounted(() => {
runCode()
init()
})
function init() {
const paramss = { appId: route.query.id }
moduleList(paramss).then(ress => {
var arr = ress.data.data
let list: any = {}
arr.forEach((item: any) => {
if (item.type == '01' && item.node_type == '02') {
list = item
}
})
if (list.id) {
moduleById(list.id).then(res2 => {
if (res2.data.data.canvas_style_data) {
sfcCode.value = res2.data.data.canvas_style_data
runCode()
}
})
}else{
sfcCode.value = defaultTemplate
runCode()
}
})
}
onBeforeUnmount(() => {
});
@ -163,4 +188,14 @@ onBeforeUnmount(() => {
width: 100%;
height: 100vh;
}
.no-login{
width: 100%;
height: 100vh;
background-color: #151515;
color: #787878;
font-size: 20px;
line-height: 100vh;
text-align: center;
font-weight: 700;
}
</style>

View File

@ -231,6 +231,7 @@ function preview(row){
border-color: rgba(51, 51, 51, 1);
border-radius: 10px;
margin-right: 20px;
text-align: center;
}
.application_list_text{
font-family: 'Arial Normal', 'Arial';

View File

@ -9,7 +9,7 @@ import { ElTree,FormInstance } from 'element-plus'
import { publicTree } from '@/utils/validate';
import { setModuleId } from '@/api/permission/menu'
import { ElMessage, ElMessageBox } from 'element-plus'
import Navbar from '@/viewsnew/application/SfcEditor/previewNavSfc.vue'
import Navbar from '@/viewsnew/application/SfcEditor/NavbarEditor/previewNavSfc.vue'
import { getMenuTree } from '@/api/permission/menu'
const props = defineProps({
applicationId:String,
@ -93,7 +93,7 @@ const handleNodeClick = (e: any) => {
}else if(e.type == '03'){
busiFlag.value = 'dataV'
loadCanvasData(e.id,9,0)
}else if(e.type == '09'){
}else if(e.type == '04'||e.type == '05'||e.type == '06'){
moduleInfo.value = e
isFormCreate.value = true
} else if(e.type == '02'){

View File

@ -5,7 +5,7 @@ import FormCreate from '@/viewsnew/common/FormCreate.vue'
import { initCanvasData } from '@/utils/canvasUtils'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { moduleList } from '@/api/application/module'
import Navbar from '@/viewsnew/application/SfcEditor/assocPage.vue'
import Navbar from '@/viewsnew/application/SfcEditor/NavbarEditor/assocPage.vue'
const props = defineProps({
moduleinfo:Object,
applicationId:String

View File

@ -66,7 +66,6 @@ onMounted(()=>{
const canvas_style_data= {"width":1920,"height":1080,"refreshViewEnable":false,"refreshViewLoading":false,"refreshUnit":"minute","refreshTime":5,"scale":60,"scaleWidth":100,"scaleHeight":100,"backgroundColorSelect":false,"backgroundImageEnable":true,"backgroundType":"backgroundColor","background":"/static-resource/7127292608094670848.png","openCommonStyle":true,"opacity":1,"fontSize":14,"themeId":"10001","color":"#000000","backgroundColor":"rgba(245, 246, 247, 1)","dashboard":{"gap":"yes","gapSize":5,"resultMode":"all","resultCount":1000,"themeColor":"light","mobileSetting":{"customSetting":false,"imageUrl":null,"backgroundType":"image","color":"#000"}},"component":{"chartTitle":{"show":true,"fontSize":"18","hPosition":"left","vPosition":"top","isItalic":false,"isBolder":true,"remarkShow":false,"remark":"","fontFamily":"Microsoft YaHei","letterSpace":"0","fontShadow":false,"color":"#000000","remarkBackgroundColor":"#ffffff","modifyName":"color"},"chartColor":{"basicStyle":{"colorScheme":"default","colors":["#1E90FF","#90EE90","#00CED1","#E2BD84","#7A90E0","#3BA272","#2BE7FF","#0A8ADA","#FFD700"],"alpha":100,"gradient":true,"mapStyle":"normal","areaBaseColor":"#FFFFFF","areaBorderColor":"#303133","gaugeStyle":"default","tableBorderColor":"#E6E7E4","tableScrollBarColor":"#00000024"},"misc":{"mapLineGradient":false,"mapLineSourceColor":"#146C94","mapLineTargetColor":"#576CBC","nameFontColor":"#000000","valueFontColor":"#5470c6"},"tableHeader":{"tableHeaderBgColor":"#1E90FF","tableHeaderFontColor":"#000000"},"tableCell":{"tableItemBgColor":"#FFFFFF","tableFontColor":"#000000"},"modifyName":"gradient"},"chartCommonStyle":{"backgroundColorSelect":true,"backgroundImageEnable":false,"backgroundType":"innerImage","innerImage":"board/board_1.svg","outerImage":null,"innerPadding":12,"borderRadius":8,"backgroundColor":"rgba(255, 255, 255, 1)","innerImageColor":"rgba(16, 148, 229,1)"},"filterStyle":{"layout":"horizontal","titleLayout":"left","labelColor":"#1F2329","titleColor":"#1F2329","color":"#1f2329","borderColor":"#BBBFC4","text":"#1F2329","bgColor":"#FFFFFF"},"tabStyle":{"headPosition":"left","headFontColor":"#000000","headFontActiveColor":"#000000","headBorderColor":"#ffffff","headBorderActiveColor":"#ffffff"}}}
console.log(canvas_style_data)
projectInfo.value = props.projectInfo
})
@ -134,14 +133,19 @@ function editClic(data:any){
window.open('/#/formcreatedesigner?moduleId=' +data.id + '&appId='+projectInfo.value.id, '_blank');
} else if(data.type == '02'){
const route = router.resolve({
path: '/SfcEditor',
path: '/editNavbar',
query: { dvId: data.id,appId:projectInfo.value.id,name:data.name,appname:projectInfo.value.name }
});
window.open(route.href, '_blank');
} else if(data.type == '01'){
const route = router.resolve({
path: '/editLogin',
query: { dvId: data.id,appId:projectInfo.value.id,name:data.name,appname:projectInfo.value.name }
});
window.open(route.href, '_blank');
}
// window.open('/#/dvCanvas?dvId=' + "1097641013486424064", '_blank');
}
function addTreeChildNode(event:any,level:any,data:any){ // //
function addTreeChildNode(event:any,level:any,data:any){ //
let element = document.getElementById("drag_main_area")
if(element !=null){
const x = event.clientX; //

View File

@ -7,7 +7,8 @@ import { findApplicationById } from "@/api/application/application";
import { useRouter, useRoute } from 'vue-router'
import DvPreview from '@/viewsnew/data-visualization/DvPreview.vue'
import FormCreate from '@/viewsnew/common/FormCreate.vue'
import Navbar from '@/viewsnew/application/sfcEditor/previewNavSfc.vue'
import Navbar from '@/viewsnew/application/sfcEditor/NavbarEditor/previewNavSfc.vue'
import Login from '@/viewsnew/application/sfcEditor/LoginEditor/previewLogin.vue'
import DePreview from '@/components/data-visualization/canvas/DePreview.vue'
import { initCanvasData, initCanvasDataPrepare, onInitReady } from '@/utils/canvasUtils'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
@ -29,6 +30,7 @@ const downloadStatus = ref(false)
const dvPreviewRef = ref(null)
const showPosition = ref("preview")
const isNavbar = ref(false)
const isLogin = ref(false)
// const noClose = ref(false)
// const props = defineProps({
// showPosition: {
@ -105,7 +107,7 @@ const loadCanvasData = (dvId, weight?, ext?) => {
dvPreviewRef.value?.restore()
})
nextTick(() => {
onInitReloadCanvasDataady({ resourceId: dvId })
// onInitReloadCanvasDataady({ resourceId: dvId })
})
}
)
@ -116,6 +118,7 @@ function handleNodeClick(e){
isFormCreate.value = false
dataInitState.value = false
isNavbar.value = false
isLogin.value = false
if(e.type == '0301'){
busiFlag.value = 'dashboard'
loadCanvasData(e.id,9,0)
@ -137,6 +140,9 @@ function handleNodeClick(e){
menuList.value = res.data
isNavbar.value = true
})
}else if(e.type == '01'){
projectId.value = e.id
isLogin.value = true
}
}
@ -164,6 +170,7 @@ onBeforeMount(() => {
<form-create v-if="isFormCreate" :moduleInfo="moduleInfo"></form-create>
<Navbar class="navbarpreview" v-if="isNavbar" :isFixed="true" :applicationId="applicationId"
:menuList="menuList" :projectId="projectId" :projectName="projectInfo.name" :isExecuteEvent="isExecuteEvent"></Navbar>
<Login class="loginpreview" v-if="isLogin" :id="projectId" :name="projectInfo.name" :isExecuteEvent="true"></Login>
</div>
</div>
</template>
@ -190,6 +197,10 @@ onBeforeMount(() => {
height: calc(100vh - 60px);
// overflow: hidden;
}
.loginpreview{
width: calc(100% - 260px);
height: calc(100vh - 60px);
}
</style>
<style>
.ed-message-box{

View File

@ -30,7 +30,7 @@ function menuclick(name){
<template>
<div>
<Header :projectInfo="projectInfo"/>
<Header v-if="!route.query.name" :projectInfo="projectInfo"/>
<div class="permission-box">
<div class="permission-leftbox">
<div class="permission-leftbox-menu" :class="curmenu == '组织机构配置' ? 'permission-leftbox-menu-active' : ''" @click="menuclick('组织机构配置')">组织机构配置</div>