Browse Source

低代码平台一期工程(无工作流)完成

v1
超级管理员 2 years ago
parent
commit
5d3fe92669
  1. 8
      src/api/taskapi/management.ts
  2. 3
      src/components/DesignForm/formControlAttr.vue
  3. 7
      src/components/DesignForm/public/form/form.vue
  4. 14
      src/components/DesignForm/public/form/formItem.vue
  5. 187
      src/components/DesignForm/public/map/componentTest.vue
  6. 2
      src/main.ts
  7. 463
      src/views/system/menu/index.vue
  8. 2
      src/views/sysworkflow/codepage/createform.vue
  9. 4
      src/views/taskplatform/taskmanagement/edittaskcustomerform.vue
  10. 10
      src/views/taskplatform/taskmanagement/tasklist.vue

8
src/api/taskapi/management.ts

@ -56,3 +56,11 @@ export function haveCustomerFormVersion(data: customerFormLogo):AxiosPromise<cus
data: data data: data
}); });
} }
//获取自定义表单版本列表
export function delCustomerFormData(data: customerFormLogo) {
return request({
url: '/systemapi/task_management/del_customer_formdata',
method: 'post',
data: data
});
}

3
src/components/DesignForm/formControlAttr.vue

@ -799,6 +799,7 @@ const controlChange = (obj: any, val: any) => {
// value:type===inputSlot使v-model // value:type===inputSlot使v-model
break break
case 'labelNameVal': case 'labelNameVal':
if(val != ""){
chineseToPinyin({title:val,types:8,connector:""}) chineseToPinyin({title:val,types:8,connector:""})
.then((data:any)=>{ .then((data:any)=>{
if(data.code == 0){ if(data.code == 0){
@ -833,7 +834,7 @@ const controlChange = (obj: any, val: any) => {
} }
}) })
}
console.log("字段编辑--fileSignAry--》",fileSignAry) console.log("字段编辑--fileSignAry--》",fileSignAry)
break break

7
src/components/DesignForm/public/form/form.vue

@ -324,7 +324,8 @@ const getData = (params = {}) => {
requestUrl ="/systemapi/task_management/look_customer_formdata" requestUrl ="/systemapi/task_management/look_customer_formdata"
break; break;
case "saveFormContent": case "saveFormContent":
requestUrl ="/systemapi/task_management/customer_form_adddata" // requestUrl ="/systemapi/task_management/customer_form_adddata"
requestUrl ="/systemapi/task_management/add_form_data"
break; break;
case "editFormContent": case "editFormContent":
requestUrl ="/systemapi/task_management/customer_form_editdata" requestUrl ="/systemapi/task_management/customer_form_editdata"
@ -404,7 +405,9 @@ const submit = (params = {}) => {
apiUrl ="/systemapi/task_management/look_customer_formdata" apiUrl ="/systemapi/task_management/look_customer_formdata"
break; break;
case "saveFormContent": case "saveFormContent":
apiUrl ="/systemapi/task_management/customer_form_adddata" // apiUrl ="/systemapi/task_management/customer_form_adddata"
// apiUrl ="/systemapi/task_management/add_form_data"
apiUrl ="/systemapi/task_management/add_form_newdata"
break; break;
case "editFormContent": case "editFormContent":
apiUrl ="/systemapi/task_management/customer_form_editdata" apiUrl ="/systemapi/task_management/customer_form_editdata"

14
src/components/DesignForm/public/form/formItem.vue

@ -128,6 +128,13 @@ const currentComponent = computed(() => {
if (props.data.type === 'expand-user') { if (props.data.type === 'expand-user') {
return markRaw(ExpandUser) return markRaw(ExpandUser)
} }
if (props.data.type === 'datePicker') {
props.data.control.valueFormat="x"
}
// if (props.data.type === 'timePicker') {
// props.data.control.valueFormat="timestamp"
// }
// console.log("",props.data)
return `el-${props.data.type}` return `el-${props.data.type}`
}) })
// //
@ -305,6 +312,7 @@ const formatCustomRules = () => {
} }
// options // options
const setFormDict = (val: any) => { const setFormDict = (val: any) => {
// console.log("options",val)
if (val && config.value.optionsType === 2) { if (val && config.value.optionsType === 2) {
const opt = val[config.value.optionsFun] || val[props.data.name] // const opt = val[config.value.optionsFun] || val[props.data.name] //
if (opt !== undefined) { if (opt !== undefined) {
@ -327,6 +335,7 @@ const formOptions = inject(constSetFormOptions, {}) as any
watch( watch(
() => formOptions.value, () => formOptions.value,
(val: any) => { (val: any) => {
// console.log("",val)
const opt = val[props.data.name] const opt = val[props.data.name]
// //
if (val && opt !== undefined) { if (val && opt !== undefined) {
@ -556,7 +565,7 @@ const imgUploadApiUrl = import.meta.env.VITE_APP_BASE_API+"/api/upordown"
:options="options" :options="options"
v-model="value" v-model="value"
/> />
<el-time-picker v-if="data.type=='timePicker'" v-model="value" /> <el-time-picker v-if="data.type=='timePicker'" v-model="value" value-format="x" />
<component <component
v-if=" v-if="
[ [
@ -576,6 +585,9 @@ const imgUploadApiUrl = import.meta.env.VITE_APP_BASE_API+"/api/upordown"
:disabled="editDisabled" :disabled="editDisabled"
v-model="value" v-model="value"
/> />
<template v-if="data.type === 'tinymce'"> <template v-if="data.type === 'tinymce'">
<!-- 设计模式时拖动会出现异常设计模式暂用图片代替--> <!-- 设计模式时拖动会出现异常设计模式暂用图片代替-->
<tinymce-edit <tinymce-edit

187
src/components/DesignForm/public/map/componentTest.vue

@ -0,0 +1,187 @@
<template>
<el-row style="flex-wrap: nowrap">
<el-input v-model="value" :placeholder="placeholder" />
<el-button @click="visibleClick">选择</el-button>
</el-row>
<el-dialog v-model="state.visible" title="详细地址" width="800px">
<div class="map-container">
<el-input id="tipInput" v-model="state.tipInput" />
<div id="container" style="width: 100%; height: 400px"></div>
<div id="panel"></div>
</div>
<template #footer>
<el-button @click="selectClick" type="primary">确定</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { reactive, watch, ref, onMounted, nextTick } from 'vue'
import { loadScript } from '@/utils/DesignForm'
const props = withDefaults(
defineProps<{
modelValue?: string
disabled?: boolean
placeholder?: string
}>(),
{}
)
const emits = defineEmits<{
(e: 'update:modelValue', value: string): void
}>()
const value = ref(props.modelValue)
watch(
() => props.modelValue,
() => {
value.value = props.modelValue
}
)
const state = reactive({
visible: false,
tipInput: ''
})
const selectClick = () => {
state.visible = false
value.value = state.tipInput
emits('update:modelValue', value.value)
}
const visibleClick = () => {
state.visible = true
//
nextTick(() => {
const map = initMap()
mapSearch(map)
})
}
const center = ref([113.264499, 23.130061])
//
const initMap = () => {
const map = new AMap.Map('container', {
resizeEnable: true,
center: center.value,
zoom: 11,
viewMode: '3D' // 使3D
})
//
const marker = new AMap.Marker({
position: map.getCenter(),
//icon: '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png',
//
draggable: true,
cursor: 'move'
// content: 'markerContent',
})
const { lat, lng } = map.getCenter()
getDetailAddress(lng, lat, marker)
map.add(marker) //
map.on('click', (e: any) => {
const lnglat = e.lnglat
const lat = lnglat.lat
const lng = lnglat.lng
map.setCenter([lng, lat]) //
marker.setPosition([lng, lat]) //
getDetailAddress(lng, lat, marker)
})
return map
}
const mapSearch = (map: any) => {
AMap.plugin(['AMap.PlaceSearch', 'AMap.AutoComplete'], function () {
const auto = new AMap.AutoComplete({
input: 'tipInput'
})
const placeSearch = new AMap.PlaceSearch({
pageSize: 5, //
pageIndex: 1, //
city: '', //
citylimit: false, //
map: map, //
panel: 'panel', //
autoFitView: true // 使 Marker
})
auto.on('select', (evt: any) => {
placeSearch.setCity(evt.poi.adcode)
placeSearch.search(evt.poi.name) //
/*placeSearch.search(evt.poi.name, function (status, result) {
//
// resultPOI
console.log("搜索结果", result);
});*/
state.tipInput = evt.poi.name //
}) //
/*
// icon
placeSearch.on('markerClick',()=>{
console.log('placeSearch.onmarkerClick')
})*/
//
placeSearch.on('listElementClick', (evt: any) => {
state.tipInput = evt.data.name
})
})
}
const getDetailAddress = (lng: number, lat: number, marker: any) => {
//
AMap.plugin('AMap.Geocoder', () => {
const geocoder = new AMap.Geocoder()
geocoder.getAddress([lng, lat], (status: string, result: any) => {
if (status === 'complete' && result.info === 'OK') {
const detailAddress = result.regeocode.formattedAddress
state.tipInput = detailAddress
marker.setLabel({
direction: 'center',
offset: new AMap.Pixel(0, -25), //
content: `<div class='info'>${detailAddress}</div>` //
})
}
})
})
}
onMounted(() => {
console.log('onMountedonMounted')
loadScript(
'https://webapi.amap.com/maps?v=2.0&key=ljiKlTAsS7SNVqDM16IUwRVFFhrvbxiF&plugin=AMap.PlaceSearch'
).then(() => {})
})
</script>
<style lang="scss">
.map-container {
position: relative;
}
.amap-sug-result {
z-index: 2500;
}
#panel {
z-index: 2500;
position: absolute;
background-color: white;
max-height: 90%;
overflow-y: auto;
top: 10px;
right: 10px;
width: 280px;
.amap_lib_placeSearch {
border: 1px solid #ebedf0;
border-radius: 2px;
padding: 5px 10px 2px;
.poibox {
border-bottom: 1px solid #e8e8e8;
cursor: pointer;
padding: 10px 5px;
position: relative;
min-height: 35px;
}
.amap_lib_placeSearch_pic {
width: 46px;
height: 46px;
float: left;
margin: 4px 10px 0 0;
img {
width: 46px;
height: 46px;
}
}
}
}
</style>

2
src/main.ts

@ -36,6 +36,8 @@ for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component) app.component(key, component)
} }
app.use(router).use(i18n).use(ComComponents).use(ElementPlus, { app.use(router).use(i18n).use(ComComponents).use(ElementPlus, {
locale: zhCn locale: zhCn
}).use(AKDesign).mount('#app'); }).use(AKDesign).mount('#app');

463
src/views/system/menu/index.vue

@ -1,463 +0,0 @@
<script setup lang="ts">
defineOptions({
name: "cmenu",
inheritAttrs: false,
});
import { MenuQuery, MenuForm, MenuVO } from "@/api/menu/types";
import {
listMenus,
getMenuForm,
listMenuOptions,
addMenu,
deleteMenu,
updateMenu,
} from "@/api/menu";
import { MenuTypeEnum } from "@/enums/MenuTypeEnum";
import SvgIcon from "@/components/SvgIcon/index.vue";
import IconSelect from "@/components/IconSelect/index.vue";
const queryFormRef = ref(ElForm);
const menuFormRef = ref(ElForm);
const loading = ref(false);
const dialog = reactive<DialogOption>({
visible: false,
});
const queryParams = reactive<MenuQuery>({});
const menuList = ref<MenuVO[]>([]);
const menuOptions = ref<OptionType[]>([]);
const formData = reactive<MenuForm>({
parentId: 0,
visible: 1,
sort: 1,
type: MenuTypeEnum.MENU,
outside:1
});
const rules = reactive({
parentId: [{ required: true, message: "请选择顶级菜单", trigger: "blur" }],
name: [{ required: true, message: "请输入菜单名称", trigger: "blur" }],
type: [{ required: true, message: "请选择菜单类型", trigger: "blur" }],
path: [{ required: true, message: "请输入路由路径", trigger: "blur" }],
component: [
{ required: true, message: "请输入组件完整路径", trigger: "blur" },
],
});
// ID
const selectedRowMenuId = ref<number | undefined>();
const menuCacheData = reactive({
type: "",
path: "",
});
/**
* 查询
*/
function handleQuery() {
//
loading.value = true;
listMenus(queryParams)
.then(({ data }) => {
menuList.value = data;
})
.then(() => {
loading.value = false;
});
}
/**
* 查询重置
*/
function resetQuery() {
queryFormRef.value.resetFields();
handleQuery();
}
/**
* 行点击事件
*
* @param row
*/
function onRowClick(row: MenuVO) {
selectedRowMenuId.value = row.id;
}
/**
* 打开表单弹窗
*
* @param parentId 父菜单ID
* @param menuId 菜单ID
*/
function openDialog(parentId?: number, menuId?: number) {
listMenuOptions()
.then(({ data }) => {
menuOptions.value = [{ value: 0, label: "顶级菜单", children: data }];
})
.then(() => {
dialog.visible = true;
if (menuId) {
dialog.title = "编辑菜单";
getMenuForm({id:menuId.toString()}).then(({ data }) => {
Object.assign(formData, data);
menuCacheData.type = data.type;
menuCacheData.path = data.path ?? "";
});
} else {
dialog.title = "新增菜单";
formData.parentId = parentId;
}
});
}
/**
* 菜单类型 change
*/
function onMenuTypeChange() {
//
if (formData.type !== menuCacheData.type) {
formData.path = "";
} else {
formData.path = menuCacheData.path;
}
}
/**
* 菜单提交
*/
function submitForm() {
menuFormRef.value.validate((isValid: boolean) => {
if (isValid) {
const menuId = formData.id;
if (menuId) {
updateMenu(formData).then(() => {
ElMessage.success("修改成功");
closeDialog();
handleQuery();
});
} else {
addMenu(formData).then(() => {
ElMessage.success("新增成功");
closeDialog();
handleQuery();
});
}
}
});
}
/**
* 删除菜单
*/
function handleDelete(menuId: number) {
if (!menuId) {
ElMessage.warning("请勾选删除项");
return false;
}
ElMessageBox.confirm("确认删除已选中的数据项?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
deleteMenu({id:menuId.toString()}).then(() => {
ElMessage.success("删除成功");
handleQuery();
});
})
.catch(() => ElMessage.info("已取消删除"));
}
/**
* 关闭弹窗
*/
function closeDialog() {
dialog.visible = false;
resetForm();
}
/**
* 重置表单
*/
function resetForm() {
menuFormRef.value.resetFields();
menuFormRef.value.clearValidate();
formData.id = undefined;
formData.parentId = 0;
formData.visible = 1;
formData.sort = 1;
}
onMounted(() => {
handleQuery();
});
</script>
<template>
<div class="app-container">
<div class="search">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="关键字" prop="keywords">
<el-input
v-model="queryParams.keywords"
placeholder="菜单名称"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery"
><template #icon><i-ep-search /></template>搜索</el-button
>
<el-button @click="resetQuery">
<template #icon><i-ep-refresh /></template>
重置</el-button
>
</el-form-item>
</el-form>
</div>
<el-card shadow="never">
<template #header>
<el-button type="success" @click="openDialog(0)" v-hasPerm="['121646328009732096']">
<template #icon><i-ep-plus /></template>
新增</el-button
>
</template>
<el-table
v-loading="loading"
:data="menuList"
highlight-current-row
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
row-key="id"
default-expand-all
border
@row-click="onRowClick"
>
<el-table-column label="菜单名称" min-width="200">
<template #default="scope">
<svg-icon
:icon-class="
scope.row.type === MenuTypeEnum.BUTTON
? 'button'
: scope.row.icon
"
/>
{{ scope.row.name }}
</template>
</el-table-column>
<el-table-column label="菜单类型" align="center" width="100">
<template #default="scope">
<el-tag
v-if="scope.row.class === MenuTypeEnum.CATALOG"
type="warning"
>目录</el-tag
>
<el-tag v-if="scope.row.class === MenuTypeEnum.MENU" type="success"
>菜单</el-tag
>
<el-tag v-if="scope.row.class === MenuTypeEnum.BUTTON" type="danger"
>按钮</el-tag
>
<el-tag v-if="scope.row.class === MenuTypeEnum.EXTLINK" type="info"
>外链</el-tag
>
</template>
</el-table-column>
<el-table-column
label="权限标识"
align="center"
width="200"
prop="permcode"
/>
<el-table-column label="状态" align="center" width="100">
<template #default="scope">
<el-tag v-if="scope.row.visible === 1" type="success">显示</el-tag>
<el-tag v-else type="info">隐藏</el-tag>
</template>
</el-table-column>
<el-table-column label="排序" align="center" width="50" prop="sort" />
<el-table-column fixed="right" align="center" label="操作" width="220">
<template #default="scope">
<el-button
v-if="scope.row.class == 'CATALOG' || scope.row.class == 'MENU'"
v-hasPerm="['121646328009732096']"
type="primary"
link
size="small"
@click.stop="openDialog(scope.row.id)"
>
<i-ep-plus />新增
</el-button>
<el-button
v-hasPerm="['122274485305880576']"
type="primary"
link
size="small"
@click.stop="openDialog(undefined, scope.row.id)"
>
<i-ep-edit />编辑
</el-button>
<el-button
v-hasPerm="['122274565337395200']"
type="primary"
link
size="small"
@click.stop="handleDelete(scope.row.id)"
><i-ep-delete />
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog
v-model="dialog.visible"
:title="dialog.title"
destroy-on-close
append-to-body
width="750px"
@close="closeDialog"
>
<el-form
ref="menuFormRef"
:model="formData"
:rules="rules"
label-width="100px"
>
<el-form-item label="父级菜单" prop="parentId">
<el-tree-select
v-model="formData.parentId"
placeholder="选择上级菜单"
:data="menuOptions"
filterable
check-strictly
:render-after-expand="false"
/>
</el-form-item>
<el-form-item label="菜单名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入菜单名称" />
</el-form-item>
<el-form-item label="菜单类型" prop="type">
<el-radio-group v-model="formData.type" @change="onMenuTypeChange">
<el-radio label="CATALOG">目录</el-radio>
<el-radio label="MENU">菜单</el-radio>
<el-radio label="BUTTON">按钮</el-radio>
<el-radio label="EXTLINK">外链</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="formData.type == 'EXTLINK'"
label="外链地址"
prop="path"
>
<el-input v-model="formData.path" placeholder="请输入外链完整路径" />
</el-form-item>
<el-form-item
v-if="formData.type == 'CATALOG' || formData.type == 'MENU'"
label="路由路径"
prop="path"
>
<el-input
v-if="formData.type == 'CATALOG'"
v-model="formData.path"
placeholder="/system (目录以/开头)"
/>
<el-input v-else v-model="formData.path" placeholder="user" />
</el-form-item>
<!-- 组件页面完整路径 -->
<el-form-item
v-if="formData.type == MenuTypeEnum.MENU"
label="页面路径"
prop="component"
>
<el-input
v-model="formData.component"
placeholder="system/user/index"
style="width: 95%"
>
<template v-if="formData.parentId != 0" #prepend
>src/views/</template
>
<template v-if="formData.parentId != 0" #append>.vue</template>
</el-input>
</el-form-item>
<!-- 权限标识 -->
<!-- <el-form-item
v-if="formData.type == 'BUTTON'"
label="权限标识"
prop="perm"
>
<el-input v-model="formData.perm" placeholder="sys:user:add" />
</el-form-item> -->
<el-form-item
v-if="formData.type !== 'BUTTON'"
label="图标"
prop="icon"
>
<!-- 图标选择器 -->
<icon-select v-model="formData.icon" />
</el-form-item>
<el-form-item
v-if="formData.type == MenuTypeEnum.CATALOG"
label="跳转路由"
>
<el-input v-model="formData.redirect" placeholder="跳转路由" />
</el-form-item>
<el-form-item v-if="formData.type !== 'BUTTON'" label="状态">
<el-radio-group v-model="formData.visible">
<el-radio :label="1">显示</el-radio>
<el-radio :label="0">隐藏</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="可见范围">
<el-radio-group v-model="formData.outside">
<el-radio :label="1">内部使用</el-radio>
<el-radio :label="2">外部使用</el-radio>
<el-radio :label="3">内外使用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number
v-model="formData.sort"
style="width: 100px"
controls-position="right"
:min="0"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="closeDialog"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>

2
src/views/sysworkflow/codepage/createform.vue

@ -864,7 +864,7 @@ const editversionstaus = (id:string) =>{
/> />
<div class="main-body"> <div class="main-body">
<HeadTools :customerformid="props.formid" @click="headToolClick" /> <HeadTools v-loading="state.loading" :customerformid="props.formid" @click="headToolClick" />
<div v-loading="state.loading" class="main-form"> <div v-loading="state.loading" class="main-form">
<div v-if="state.formData.list.length === 0" class="empty-tips"> <div v-if="state.formData.list.length === 0" class="empty-tips">
从左侧拖拽来添加组件 从左侧拖拽来添加组件

4
src/views/taskplatform/taskmanagement/edittaskcustomerform.vue

@ -137,7 +137,7 @@ const formType = computed(() => {
return 1 return 1
} }
}) })
const emits = defineEmits(["update:iseditopen"]); const emits = defineEmits(["update:iseditopen","searchquery"]);
const isShow = computed({ const isShow = computed({
get: () => props.iseditopen, get: () => props.iseditopen,
set: (val) => { set: (val) => {
@ -188,7 +188,9 @@ const afterSubmit = (type: string) => {
if (type === 'success') { if (type === 'success') {
// router.go(-1) // router.go(-1)
console.log("表单提交成功") console.log("表单提交成功")
emits("searchquery");
closeAppSubmit(); closeAppSubmit();
} }
} }
const closeAppSubmit = () => { const closeAppSubmit = () => {

10
src/views/taskplatform/taskmanagement/tasklist.vue

@ -5,7 +5,7 @@
--> -->
<script lang='ts' setup> <script lang='ts' setup>
import { TaskLogQuery,taskLonCont } from '@/api/taskapi/types' import { TaskLogQuery,taskLonCont } from '@/api/taskapi/types'
import { appFormdataLog } from '@/api/taskapi/management' import { appFormdataLog,delCustomerFormData } from '@/api/taskapi/management'
// //
import TaskEntry from '@/views/taskplatform/taskmanagement/taskentry.vue' import TaskEntry from '@/views/taskplatform/taskmanagement/taskentry.vue'
@ -80,7 +80,11 @@ const editFormLogDialog = (val:any) =>{
} }
// //
const DeleteFormLog = (id:any) =>{ const DeleteFormLog = (id:any) =>{
loading.value = true;
delCustomerFormData({"id":id.toString()})
.then((data) =>{
searchQuery();
})
} }
// //
onMounted(() => { onMounted(() => {
@ -171,7 +175,7 @@ const openCustomerForm = (id:string,title:string) =>{
</el-card> </el-card>
<TaskEntry v-model:isshow="openTaskDialog" @opencustomerform="openCustomerForm" /> <TaskEntry v-model:isshow="openTaskDialog" @opencustomerform="openCustomerForm" />
<TaskCustomerForm v-model:isopen="openTaskDrawer" :versionid="versionId" :versiontitle="versionTitle" @searchquery="searchQuery" /> <TaskCustomerForm v-model:isopen="openTaskDrawer" :versionid="versionId" :versiontitle="versionTitle" @searchquery="searchQuery" />
<EditTaskCustomerForm v-model:iseditopen="openEditTaskDrawer" :versionid="versionId" :versiontitle="versionTitle" :masterskey="mastersKey" /> <EditTaskCustomerForm v-model:iseditopen="openEditTaskDrawer" :versionid="versionId" :versiontitle="versionTitle" :masterskey="mastersKey" infoid="2" @searchquery="searchQuery" />
</div> </div>
</template> </template>
<style lang='scss' scoped> <style lang='scss' scoped>

Loading…
Cancel
Save