feat: 支持导入swagger2.0版本的JSON

pull/15/head
bqy_fe 3 years ago
parent eeb9c839f9
commit 249179ce44
  1. 3
      components.d.ts
  2. 4
      src/main.ts
  3. 4
      src/packages/base-widgets/button/index.tsx
  4. 13
      src/plugins/element-plus.ts
  5. 2
      src/plugins/vant.ts
  6. 41
      src/visual-editor/components/left-aside/components/data-source/data-fetch.vue
  7. 46
      src/visual-editor/components/left-aside/components/data-source/data-model.vue
  8. 6
      src/visual-editor/components/left-aside/components/data-source/index.vue
  9. 113
      src/visual-editor/components/left-aside/components/data-source/utils.tsx
  10. 24
      src/visual-editor/components/left-aside/index.vue
  11. 68
      src/visual-editor/hooks/useVisualData.ts
  12. 10
      src/visual-editor/index.vue

3
components.d.ts vendored

@ -23,9 +23,10 @@ declare module 'vue' {
ElInput: typeof import('element-plus/es/el-input')['default'] ElInput: typeof import('element-plus/es/el-input')['default']
ElFormItem: typeof import('element-plus/es/el-form-item')['default'] ElFormItem: typeof import('element-plus/es/el-form-item')['default']
ElForm: typeof import('element-plus/es/el-form')['default'] ElForm: typeof import('element-plus/es/el-form')['default']
ElPopconfirm: typeof import('element-plus/es/el-popconfirm')['default']
ElCollapseItem: typeof import('element-plus/es/el-collapse-item')['default'] ElCollapseItem: typeof import('element-plus/es/el-collapse-item')['default']
ElCollapse: typeof import('element-plus/es/el-collapse')['default'] ElCollapse: typeof import('element-plus/es/el-collapse')['default']
ElPopconfirm: typeof import('element-plus/es/el-popconfirm')['default'] ElInfiniteScroll: typeof import('element-plus/es/el-infinite-scroll')['default']
} }
} }

@ -1,7 +1,7 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import App from './App.vue' import App from './App.vue'
import './plugins/element-plus' import { setupElementPlus } from './plugins/element-plus'
import { setupVant } from './plugins/vant' import { setupVant } from './plugins/vant'
import 'normalize.css' import 'normalize.css'
@ -14,6 +14,8 @@ import store from './store/'
const app = createApp(App) const app = createApp(App)
// 使用element-plus插件
setupElementPlus(app)
// 使用vant插件 // 使用vant插件
setupVant(app) setupVant(app)

@ -87,6 +87,10 @@ export default {
{ {
label: '表单提交按钮', label: '表单提交按钮',
value: 'submit' value: 'submit'
},
{
label: '表单重置按钮',
value: 'reset'
} }
], ],
defaultValue: 'button' defaultValue: 'button'

@ -1,3 +1,16 @@
/*
* @Author:
* @Date: 2021-04-22 02:10:31
* @LastEditTime: 2021-06-27 14:58:03
* @LastEditors:
* @Description: element-plus
* @FilePath: \vite-vue3-lowcode\src\plugins\element-plus.ts
*/
import 'element-plus/packages/theme-chalk/src/base.scss' import 'element-plus/packages/theme-chalk/src/base.scss'
// import 'element-plus/lib/theme-chalk/index.css' // import 'element-plus/lib/theme-chalk/index.css'
// import 'element-plus/lib/theme-chalk/el-popper.css' // import 'element-plus/lib/theme-chalk/el-popper.css'
import type { App } from 'vue'
import { ElInfiniteScroll } from 'element-plus'
export const setupElementPlus = (app: App) => {
app.use(ElInfiniteScroll)
}

@ -1,4 +1,4 @@
import { App } from 'vue' import type { App } from 'vue'
import '@vant/touch-emulator' import '@vant/touch-emulator'
import 'vant/lib/index.css' import 'vant/lib/index.css'

@ -1,7 +1,7 @@
<!-- <!--
* @Author: 卜启缘 * @Author: 卜启缘
* @Date: 2021-06-24 18:36:03 * @Date: 2021-06-24 18:36:03
* @LastEditTime: 2021-06-26 21:34:53 * @LastEditTime: 2021-06-27 14:59:24
* @LastEditors: 卜启缘 * @LastEditors: 卜启缘
* @Description: 接口请求 * @Description: 接口请求
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\components\data-source\data-fetch.vue * @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\components\data-source\data-fetch.vue
@ -12,13 +12,25 @@
<el-button type="warning" size="small" @click="showImportSwaggerJsonModal" <el-button type="warning" size="small" @click="showImportSwaggerJsonModal"
>导入swagger</el-button >导入swagger</el-button
> >
<el-popconfirm
confirm-button-text="确定"
cancel-button-text="取消"
icon="el-icon-info"
icon-color="red"
title="确定要删除全部接口吗?"
@confirm="updateFetchApi([], true)"
>
<template #reference>
<el-button type="danger" size="small">清空</el-button>
</template>
</el-popconfirm>
</div> </div>
<el-collapse v-model="state.activeNames"> <el-collapse v-model="state.activeNames" v-infinite-scroll="() => {}">
<template v-for="item in apis" :key="item.key"> <template v-for="item in apis" :key="item.key">
<el-collapse-item :title="item.name" :name="item.key"> <el-collapse-item :title="item.name" :name="item.key">
<template #title> <template #title>
<div class="model-item-title"> <div class="model-item-title">
<span>{{ item.name }}</span> <span class="truncate w-160px">{{ item.name }}</span>
<div class="model-actions"> <div class="model-actions">
<i class="el-icon-edit" @click="editApiItem(item)"></i> <i class="el-icon-edit" @click="editApiItem(item)"></i>
<el-popconfirm <el-popconfirm
@ -56,12 +68,13 @@ import {
ElMessage, ElMessage,
ElCascader ElCascader
} from 'element-plus' } from 'element-plus'
import { useVisualData, fieldTypes } from '@/visual-editor/hooks/useVisualData' import { useVisualData } from '@/visual-editor/hooks/useVisualData'
import type { FetchApiItem, VisualEditorModel } from '@/visual-editor/visual-editor.utils' import type { FetchApiItem, VisualEditorModel } from '@/visual-editor/visual-editor.utils'
import { useModal } from '@/visual-editor/hooks/useModal' import { useModal } from '@/visual-editor/hooks/useModal'
import { cloneDeep } from 'lodash' import { cloneDeep } from 'lodash'
import { generateUUID } from '@/visual-editor/utils/' import { generateUUID } from '@/visual-editor/utils/'
import { RequestEnum, ContentTypeEnum } from '@/enums/httpEnum' import { RequestEnum, ContentTypeEnum } from '@/enums/httpEnum'
import { useImportSwaggerJsonModal } from './utils'
interface IState { interface IState {
activeNames: string[] activeNames: string[]
@ -70,7 +83,7 @@ interface IState {
} }
const { jsonData, incrementFetchApi, updateFetchApi, deleteFetchApi } = useVisualData() const { jsonData, incrementFetchApi, updateFetchApi, deleteFetchApi } = useVisualData()
const { showImportSwaggerJsonModal } = useImportSwaggerJsonModal()
/** /**
* @description 接口集合 * @description 接口集合
*/ */
@ -123,8 +136,9 @@ const handleBindChange = (e: VisualEditorModel[]) => {
* @description 显示添加接口弹窗 * @description 显示添加接口弹窗
*/ */
const showModelMoal = () => { const showModelMoal = () => {
const operateType = isEdit.value ? '编辑' : '新增'
useModal({ useModal({
title: `${isEdit.value ? '编辑' : '新增'}接口`, title: `${operateType}接口`,
props: { props: {
width: 600 width: 600
}, },
@ -187,7 +201,7 @@ const showModelMoal = () => {
} else { } else {
incrementFetchApi(cloneDeep(state.ruleForm)) incrementFetchApi(cloneDeep(state.ruleForm))
} }
ElMessage.success(`${isEdit.value ? '修改' : '新增'}接口成功!`) ElMessage.success(`${operateType}接口成功!`)
state.ruleForm = createEmptyApiItem() state.ruleForm = createEmptyApiItem()
resolve('submit!') resolve('submit!')
} else { } else {
@ -210,20 +224,17 @@ const editApiItem = (apiItem: FetchApiItem) => {
state.ruleForm = cloneDeep(apiItem) state.ruleForm = cloneDeep(apiItem)
showModelMoal() showModelMoal()
} }
/**
* @description 显示导入swagger JSON模态框
*/
const showImportSwaggerJsonModal = () => {
ElMessage.info('敬请期待!')
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.code { .low-model-item {
overflow: auto;
.code {
padding: 4px 10px; padding: 4px 10px;
font-size: 12px; font-size: 12px;
line-height: 1.4; line-height: 1.4;
}
} }
.model-item-title { .model-item-title {

@ -1,7 +1,7 @@
<!-- <!--
* @Author: 卜启缘 * @Author: 卜启缘
* @Date: 2021-06-24 18:36:03 * @Date: 2021-06-24 18:36:03
* @LastEditTime: 2021-06-26 21:35:13 * @LastEditTime: 2021-06-27 14:48:53
* @LastEditors: 卜启缘 * @LastEditors: 卜启缘
* @Description: 数据模型管理 * @Description: 数据模型管理
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\components\data-source\data-model.vue * @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\components\data-source\data-model.vue
@ -12,13 +12,25 @@
<el-button type="warning" size="small" @click="showImportSwaggerJsonModal" <el-button type="warning" size="small" @click="showImportSwaggerJsonModal"
>导入swagger</el-button >导入swagger</el-button
> >
<el-popconfirm
confirm-button-text="确定"
cancel-button-text="取消"
icon="el-icon-info"
icon-color="red"
title="确定要删除全部模型吗?"
@confirm="updateModel([], true)"
>
<template #reference>
<el-button type="danger" size="small">清空</el-button>
</template>
</el-popconfirm>
</div> </div>
<el-collapse v-model="state.activeNames"> <el-collapse v-model="state.activeNames" v-infinite-scroll="() => {}">
<template v-for="item in models" :key="item.key"> <template v-for="item in models" :key="item.key">
<el-collapse-item :title="item.name" :name="item.key"> <el-collapse-item :title="item.name" :name="item.key">
<template #title> <template #title>
<div class="model-item-title"> <div class="model-item-title">
<span>{{ item.name }}</span> <span class="truncate w-160px">{{ item.name }}</span>
<div class="model-actions"> <div class="model-actions">
<i class="el-icon-edit" @click="editModel(item)"></i> <i class="el-icon-edit" @click="editModel(item)"></i>
<el-popconfirm <el-popconfirm
@ -63,6 +75,7 @@ import type { VisualEditorModel } from '@/visual-editor/visual-editor.utils'
import { useModal } from '@/visual-editor/hooks/useModal' import { useModal } from '@/visual-editor/hooks/useModal'
import { cloneDeep } from 'lodash' import { cloneDeep } from 'lodash'
import { generateUUID } from '@/visual-editor/utils/' import { generateUUID } from '@/visual-editor/utils/'
import { useImportSwaggerJsonModal } from './utils'
interface IState { interface IState {
activeNames: string[] activeNames: string[]
@ -71,6 +84,8 @@ interface IState {
} }
const { jsonData, incrementModel, updateModel, deleteModel } = useVisualData() const { jsonData, incrementModel, updateModel, deleteModel } = useVisualData()
const { showImportSwaggerJsonModal } = useImportSwaggerJsonModal()
/** /**
* @description 模型集合 * @description 模型集合
*/ */
@ -79,7 +94,7 @@ const models = computed(() => cloneDeep(jsonData.models))
/** /**
* @description 是否处于编辑状态 * @description 是否处于编辑状态
*/ */
const isEdit = computed(() => models.value.some((item) => item.key == state.ruleForm.key)) const isEdit = computed(() => models.value.some((item) => item.key === state.ruleForm.key))
/** /**
* @description 创建空的实体对象 * @description 创建空的实体对象
@ -120,8 +135,9 @@ const addEntityItem = () => {
* @description 显示添加接口弹窗 * @description 显示添加接口弹窗
*/ */
const showModelMoal = () => { const showModelMoal = () => {
const operateType = isEdit.value ? '修改' : '新增'
useModal({ useModal({
title: `${isEdit.value ? '编辑' : '新增'}数据源`, title: `${operateType}数据源`,
props: { props: {
width: 600 width: 600
}, },
@ -213,11 +229,11 @@ const showModelMoal = () => {
state.ruleFormRef.validate((valid) => { state.ruleFormRef.validate((valid) => {
if (valid) { if (valid) {
if (isEdit.value) { if (isEdit.value) {
updateModel(cloneDeep(state.ruleForm)) updateModel(state.ruleForm)
} else { } else {
incrementModel(cloneDeep(state.ruleForm)) incrementModel(state.ruleForm)
} }
ElMessage.success(`${isEdit.value ? '修改' : '新增'}模型成功!`) ElMessage.success(`${operateType}模型成功!`)
state.ruleForm = createEmptyModel() state.ruleForm = createEmptyModel()
resolve('submit!') resolve('submit!')
} else { } else {
@ -231,7 +247,6 @@ const showModelMoal = () => {
onCancel: () => (state.ruleForm = createEmptyModel()) onCancel: () => (state.ruleForm = createEmptyModel())
}) })
} }
/** /**
* @description 编辑模型 * @description 编辑模型
*/ */
@ -240,20 +255,17 @@ const editModel = (model: VisualEditorModel) => {
state.ruleForm = cloneDeep(model) state.ruleForm = cloneDeep(model)
showModelMoal() showModelMoal()
} }
/**
* @description 显示导入swagger JSON模态框
*/
const showImportSwaggerJsonModal = () => {
ElMessage.info('敬请期待!')
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.code { .low-model-item {
overflow: auto;
.code {
padding: 4px 10px; padding: 4px 10px;
font-size: 12px; font-size: 12px;
line-height: 1.4; line-height: 1.4;
}
} }
.model-item-title { .model-item-title {

@ -1,17 +1,17 @@
<!-- <!--
* @Author: 卜启缘 * @Author: 卜启缘
* @Date: 2021-06-24 18:36:03 * @Date: 2021-06-24 18:36:03
* @LastEditTime: 2021-06-26 14:15:33 * @LastEditTime: 2021-06-27 14:45:03
* @LastEditors: 卜启缘 * @LastEditors: 卜启缘
* @Description: 数据源管理 * @Description: 数据源管理
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\components\data-source\index.vue * @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\components\data-source\index.vue
--> -->
<template> <template>
<el-tabs type="border-card" stretch> <el-tabs type="border-card" stretch>
<el-tab-pane label="数据模型"> <el-tab-pane label="数据模型" lazy>
<data-model /> <data-model />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="数据接口"> <el-tab-pane label="数据接口" lazy>
<data-fetch /> <data-fetch />
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>

@ -0,0 +1,113 @@
/*
* @Author:
* @Date: 2021-06-27 13:15:19
* @LastEditTime: 2021-06-27 14:17:31
* @LastEditors:
* @Description:
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\components\data-source\utils.tsx
*/
import { generateUUID } from '@/visual-editor/utils'
import type { FetchApiItem } from '@/visual-editor/visual-editor.utils'
import { RequestEnum } from '@/enums/httpEnum'
import MonacoEditor from '@/visual-editor/components/common/monaco-editor/MonacoEditor'
import { useVisualData } from '@/visual-editor/hooks/useVisualData'
import type { VisualEditorModel } from '@/visual-editor/visual-editor.utils'
import { useModal } from '@/visual-editor/hooks/useModal'
import { ElMessage } from 'element-plus'
/**
* @description
* @param {object} swagger JSON字符串
* @returns { apis, models }
*/
export const importSwaggerJson = (swagger: any) => {
swagger = typeof swagger == 'string' ? JSON.parse(swagger) : swagger
const models: VisualEditorModel[] = []
Object.keys(swagger.definitions).forEach((model) => {
const properties = swagger.definitions[model].properties
const modelItem: VisualEditorModel = {
name: model,
key: generateUUID(),
entitys: []
}
Object.keys(properties).forEach((field) => {
modelItem.entitys.push({
key: field,
name: properties[field].description || field,
type: properties[field].type,
value: ''
})
})
models.push(modelItem)
})
const apis: FetchApiItem[] = []
Object.keys(swagger.paths).forEach((url) => {
Object.keys(swagger.paths[url]).forEach((method) => {
const apiUrlObj = swagger.paths[url][method]
const model = apiUrlObj.parameters?.[0]?.schema?.$ref?.split('/').pop()
const bindTarget = model ? models.find((item) => item.name == model) : undefined
typeof bindTarget == 'object' && (bindTarget.name = apiUrlObj.summary)
const api: FetchApiItem = {
key: generateUUID(),
name: apiUrlObj.summary,
options: {
url: url, // 请求的url
method: method.toLocaleUpperCase() as RequestEnum, // 请求的方法
contentType: apiUrlObj.produces[0] || apiUrlObj.consumes[0] // 请求的内容类型
},
data: {
bind: bindTarget?.key || '', // 请求绑定对应的某个实体
recv: '' // 响应的结果绑定到某个实体上
}
}
apis.push(api)
})
})
return { apis, models }
}
/**
* @description swagger JSON模态框
*/
export const useImportSwaggerJsonModal = () => {
const { updateModel, updateFetchApi } = useVisualData()
const shema = {}
const handleSchemaChange = (val) => {
try {
const newObj = JSON.parse(val)
Object.assign(shema, newObj)
} catch (e) {
console.log('JSON格式有误:', e)
}
}
return {
showImportSwaggerJsonModal: () =>
useModal({
title: '导入swagger JSON (导入swagger: 2.0)',
props: {
width: 760
},
content: () => (
<MonacoEditor
code={''}
layout={{ width: 700, height: 600 }}
vid={-1}
onChange={handleSchemaChange}
title=""
/>
),
onConfirm: () => {
try {
const { models, apis } = importSwaggerJson(shema)
updateModel(models, true)
updateFetchApi(apis, true)
ElMessage.success('导入成功!')
console.log({ models, apis }, '导入的swagger')
} catch (e) {
ElMessage.success('导入失败!请检查swagger JSON是否有误!')
}
}
})
}
}

@ -1,7 +1,7 @@
<!-- <!--
* @Author: 卜启缘 * @Author: 卜启缘
* @Date: 2021-06-24 00:35:17 * @Date: 2021-06-24 00:35:17
* @LastEditTime: 2021-06-26 00:24:40 * @LastEditTime: 2021-06-27 14:44:35
* @LastEditors: 卜启缘 * @LastEditors: 卜启缘
* @Description: 左侧边栏 * @Description: 左侧边栏
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\index.vue * @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\index.vue
@ -9,7 +9,7 @@
<template> <template>
<el-tabs v-model="activeName" tab-position="left" class="left-aside"> <el-tabs v-model="activeName" tab-position="left" class="left-aside">
<template v-for="tabItem in tabs" :key="tabItem.componentName"> <template v-for="tabItem in tabs" :key="tabItem.componentName">
<el-tab-pane :name="tabItem.componentName"> <el-tab-pane :name="tabItem.componentName" lazy>
<template #label> <template #label>
<div :ref="(el) => el && (tabItemRef[tabItem.componentName] = el)" class="tab-item"> <div :ref="(el) => el && (tabItemRef[tabItem.componentName] = el)" class="tab-item">
<i :class="tabItem.icon"></i> <i :class="tabItem.icon"></i>
@ -23,7 +23,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, reactive, toRefs, onMounted, ComponentInternalInstance } from 'vue' import { defineComponent, reactive, toRefs, ComponentInternalInstance } from 'vue'
import { tabs } from './tabs' import { tabs } from './tabs'
import components from './components' import components from './components'
@ -39,16 +39,6 @@ export default defineComponent({
tabItemRef: {} as { [prop: string]: ComponentInternalInstance | Element } tabItemRef: {} as { [prop: string]: ComponentInternalInstance | Element }
}) })
onMounted(() => {
setTimeout(() => {
tabs.forEach((item) => {
;(state.tabItemRef[item.componentName] as HTMLDivElement)
?.closest('.el-tabs__item')
?.setAttribute('data-custom-css', '')
})
})
})
return { return {
...toRefs(state), ...toRefs(state),
tabs tabs
@ -61,11 +51,10 @@ export default defineComponent({
.left-aside { .left-aside {
height: 100%; height: 100%;
::v-deep(.el-tabs__header.is-left) { > ::v-deep(.el-tabs__header) {
margin-right: 0; margin-right: 0;
}
::v-deep(.el-tabs__item[data-custom-css]) { .el-tabs__item {
height: 80px; height: 80px;
padding: 20px 16px; padding: 20px 16px;
@ -77,8 +66,9 @@ export default defineComponent({
} }
} }
} }
}
::v-deep(.el-tabs__content) { > ::v-deep(.el-tabs__content) {
height: 100%; height: 100%;
overflow-y: auto; overflow-y: auto;
} }

@ -5,22 +5,12 @@
* @descriptionuseVisualData * @descriptionuseVisualData
* @update: 2021/5/6 11:59 * @update: 2021/5/6 11:59
*/ */
import { import { reactive, inject, readonly, computed, watch, InjectionKey } from 'vue'
reactive,
inject,
readonly,
computed,
watch,
ComputedRef,
InjectionKey,
DeepReadonly
} from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import type { import type {
VisualEditorModelValue, VisualEditorModelValue,
VisualEditorBlockData, VisualEditorBlockData,
VisualEditorPage, VisualEditorPage,
VisualEditorConfig,
FetchApiItem, FetchApiItem,
VisualEditorModel VisualEditorModel
} from '@/visual-editor/visual-editor.utils' } from '@/visual-editor/visual-editor.utils'
@ -40,26 +30,6 @@ interface IState {
jsonData: VisualEditorModelValue // 整棵JSON树 jsonData: VisualEditorModelValue // 整棵JSON树
} }
export interface VisualData {
jsonData: DeepReadonly<VisualEditorModelValue> // 保护JSONData避免直接修改
currentPage: ComputedRef<VisualEditorPage> // 当前正在操作的页面
currentBlock: ComputedRef<VisualEditorBlockData> // 当前正在操作的组件
visualConfig: VisualEditorConfig // 组件配置
overrideProject: (jsonData: VisualEditorModelValue) => void // 使用JSON覆盖整个项目
updatePage: (data: { newPath?: string; oldPath: string; page: Partial<VisualEditorPage> }) => void // 更新某个页面
incrementPage: (path: string, page: Omit<VisualEditorPage, 'path'>) => void // 新增页面
deletePage: (path: string, redirect?: string) => void // 删除页面
updatePageBlock: (path: string, blocks: VisualEditorBlockData[]) => void // 更新某页面下的所有组件
setCurrentPage: (path: string) => void // 设置当前正在操作的页面
setCurrentBlock: (block: VisualEditorBlockData) => void // 设置当前正在操作的组件
incrementFetchApi: (api: FetchApiItem) => void // 新增api接口
deleteFetchApi: (key: string) => void // 删除某个api接口
updateFetchApi: (newApi: FetchApiItem) => void // 更新某个api接口
incrementModel: (api: VisualEditorModel) => void // 新增模型
deleteModel: (key: string) => void // 删除某个模型
updateModel: (newApi: VisualEditorModel) => void // 更新某个模型
}
/** /**
* @description * @description
*/ */
@ -92,7 +62,7 @@ const defaultValue: VisualEditorModelValue = {
} }
} }
export const initVisualData = (): VisualData => { export const initVisualData = () => {
const localData = JSON.parse(sessionStorage.getItem(localKey) as string) const localData = JSON.parse(sessionStorage.getItem(localKey) as string)
const jsonData: VisualEditorModelValue = Object.keys(localData?.pages || {}).length const jsonData: VisualEditorModelValue = Object.keys(localData?.pages || {}).length
? localData ? localData
@ -189,11 +159,21 @@ export const initVisualData = (): VisualData => {
} }
/** /**
* @description API接口 * @description
* @param {FetchApiItem | FetchApiItem[]} api
* @param {boolean} isCover
*/ */
const updateFetchApi = (api: FetchApiItem) => { const updateFetchApi = (api: FetchApiItem | FetchApiItem[], isCover = false) => {
const target = state.jsonData.actions.fetch.apis.find((item) => item.key == api.key) const fetch = state.jsonData.actions.fetch
const apis = Array.isArray(api) ? api : [api]
if (isCover) {
fetch.apis = apis
} else {
apis.forEach((apiItem) => {
const target = fetch.apis.find((item) => item.key == apiItem.key)
Object.assign(target, api) Object.assign(target, api)
})
}
} }
/** /**
@ -214,12 +194,22 @@ export const initVisualData = (): VisualData => {
} }
/** /**
* @param { VisualEditorModel | VisualEditorModel[]} model
* @param {boolean} isCover
* @description * @description
*/ */
const updateModel = (model: VisualEditorModel) => { const updateModel = (model: VisualEditorModel | VisualEditorModel[], isCover = false) => {
const index = state.jsonData.models.findIndex((item) => item.key == model.key) const jsonData = state.jsonData
const models = Array.isArray(model) ? model : [model]
if (isCover) {
jsonData.models = models
} else {
models.forEach((modelItem) => {
const index = jsonData.models.findIndex((item) => item.key == modelItem.key)
if (index !== -1) { if (index !== -1) {
state.jsonData.models.splice(index, 1, model) state.jsonData.models.splice(index, 1, modelItem)
}
})
} }
} }
@ -249,7 +239,7 @@ export const initVisualData = (): VisualData => {
} }
} }
export const useVisualData = () => inject<VisualData>(injectKey)! export const useVisualData = () => inject<ReturnType<typeof useVisualData>>(injectKey)!
/** /**
* *

@ -1,3 +1,11 @@
<!--
* @Author: 卜启缘
* @Date: 2021-06-24 00:35:17
* @LastEditTime: 2021-06-27 14:31:28
* @LastEditors: 卜启缘
* @Description: 可视化编辑器
* @FilePath: \vite-vue3-lowcode\src\visual-editor\index.vue
-->
<template> <template>
<el-container> <el-container>
<el-header height="80px" class="flex items-center shadow-md"> <el-header height="80px" class="flex items-center shadow-md">
@ -6,7 +14,7 @@
<!-- 顶部end --> <!-- 顶部end -->
</el-header> </el-header>
<el-container class="layout-container"> <el-container class="layout-container">
<el-aside class="shadow-sm" width="350px"> <el-aside class="shadow-sm" width="380px">
<!-- 左侧组件start --> <!-- 左侧组件start -->
<left-aside /> <left-aside />
<!-- 左侧组件end --> <!-- 左侧组件end -->

Loading…
Cancel
Save