feat: minder-editor脑图组件功能补齐&样式

This commit is contained in:
baiqi 2023-06-07 17:41:45 +08:00 committed by rubylliu
parent b8a3ed8ed6
commit d8d94a0c20
13 changed files with 214 additions and 185 deletions

View File

@ -5,11 +5,57 @@
// Read more: https://github.com/vuejs/core/pull/3399
import '@vue/runtime-core'
export {}
export {};
declare module '@vue/runtime-core' {
export interface GlobalComponents {
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
AAffix: typeof import('@arco-design/web-vue')['Affix'];
AAlert: typeof import('@arco-design/web-vue')['Alert'];
AAvatar: typeof import('@arco-design/web-vue')['Avatar'];
ABadge: typeof import('@arco-design/web-vue')['Badge'];
ABreadcrumb: typeof import('@arco-design/web-vue')['Breadcrumb'];
ABreadcrumbItem: typeof import('@arco-design/web-vue')['BreadcrumbItem'];
AButton: typeof import('@arco-design/web-vue')['Button'];
ACard: typeof import('@arco-design/web-vue')['Card'];
ACardMeta: typeof import('@arco-design/web-vue')['CardMeta'];
ACol: typeof import('@arco-design/web-vue')['Col'];
AConfigProvider: typeof import('@arco-design/web-vue')['ConfigProvider'];
ADivider: typeof import('@arco-design/web-vue')['Divider'];
ADoption: typeof import('@arco-design/web-vue')['Doption'];
ADrawer: typeof import('@arco-design/web-vue')['Drawer'];
ADropdown: typeof import('@arco-design/web-vue')['Dropdown'];
AInputNumber: typeof import('@arco-design/web-vue')['InputNumber'];
ALayout: typeof import('@arco-design/web-vue')['Layout'];
ALayoutContent: typeof import('@arco-design/web-vue')['LayoutContent'];
ALayoutFooter: typeof import('@arco-design/web-vue')['LayoutFooter'];
ALayoutSider: typeof import('@arco-design/web-vue')['LayoutSider'];
ALink: typeof import('@arco-design/web-vue')['Link'];
AList: typeof import('@arco-design/web-vue')['List'];
AListItem: typeof import('@arco-design/web-vue')['ListItem'];
AListItemMeta: typeof import('@arco-design/web-vue')['ListItemMeta'];
AMenu: typeof import('@arco-design/web-vue')['Menu'];
AMenuItem: typeof import('@arco-design/web-vue')['MenuItem'];
AModal: typeof import('@arco-design/web-vue')['Modal'];
AOption: typeof import('@arco-design/web-vue')['Option'];
APagination: typeof import('@arco-design/web-vue')['Pagination'];
APopover: typeof import('@arco-design/web-vue')['Popover'];
AResult: typeof import('@arco-design/web-vue')['Result'];
ARow: typeof import('@arco-design/web-vue')['Row'];
ASelect: typeof import('@arco-design/web-vue')['Select'];
ASkeleton: typeof import('@arco-design/web-vue')['Skeleton'];
ASkeletonLine: typeof import('@arco-design/web-vue')['SkeletonLine'];
ASkeletonShape: typeof import('@arco-design/web-vue')['SkeletonShape'];
ASpace: typeof import('@arco-design/web-vue')['Space'];
ASpin: typeof import('@arco-design/web-vue')['Spin'];
ASubMenu: typeof import('@arco-design/web-vue')['SubMenu'];
ASwitch: typeof import('@arco-design/web-vue')['Switch'];
ATabPane: typeof import('@arco-design/web-vue')['TabPane'];
ATabs: typeof import('@arco-design/web-vue')['Tabs'];
ATag: typeof import('@arco-design/web-vue')['Tag'];
ATooltip: typeof import('@arco-design/web-vue')['Tooltip'];
ATypographyParagraph: typeof import('@arco-design/web-vue')['TypographyParagraph'];
ATypographyText: typeof import('@arco-design/web-vue')['TypographyText'];
RouterLink: typeof import('vue-router')['RouterLink'];
RouterView: typeof import('vue-router')['RouterView'];
}
}

View File

@ -23,7 +23,16 @@
</a-tab-pane>
<a-tab-pane key="viewMenu" :title="t('minder.main.header.style')">
<div class="mind-tab-panel">
<view-menu :minder="minder" :default-mold="props.defaultMold" @mold-change="handleMoldChange" />
<view-menu
v-if="props.viewMenuEnable"
:minder="minder"
:default-mold="props.defaultMold"
:arrange-enable="props.arrangeEnable"
:mold-enable="props.moldEnable"
:font-enable="props.fontEnable"
:style-enable="props.styleEnable"
@mold-change="handleMoldChange"
/>
</div>
</a-tab-pane>
</a-tabs>
@ -35,7 +44,7 @@
import editMenu from '../menu/edit/editMenu.vue';
import viewMenu from '../menu/view/viewMenu.vue';
import { useI18n } from '@/hooks/useI18n';
import { editMenuProps, moleProps, priorityProps, tagProps, delProps } from '../props';
import { editMenuProps, moleProps, priorityProps, tagProps, delProps, viewMenuProps } from '../props';
const { t } = useI18n();
@ -45,6 +54,7 @@
...priorityProps,
...tagProps,
...delProps,
...viewMenuProps,
minder: null,
});
@ -59,10 +69,11 @@
</script>
<style lang="less">
@import '../style/header';
@import '../style/header.less';
.mind_tab-content {
.tab-icons {
@apply bg-[url('@/assets/images/minder/icons.png')] bg-no-repeat;
background-image: url('@/assets/images/minder/icons.png');
background-repeat: no-repeat;
}
}
</style>

View File

@ -131,7 +131,7 @@
<style lang="less">
@import '../style/editor.less';
.save-btn {
@apply absolute;
@apply !absolute;
}
.minder-container {
@apply relative;

View File

@ -36,3 +36,15 @@
const props = defineProps({ ...editMenuProps, ...priorityProps, ...tagProps, ...delProps });
</script>
<style lang="less" scoped>
.menu-container {
height: 60px;
i {
@apply inline-block;
width: 20px;
height: 20px;
}
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div :disabled="commandDisabled">
<a-button class="delete-btn mx-[4px] my-0 h-[23px] w-[23px] !p-[2px]" shape="circle" @click="execCommand()">
<a-button class="delete-btn !mx-[4px] !my-0 !h-[23px] !w-[23px] !p-[2px]" shape="circle" @click="execCommand()">
<template #icon>
<icon-delete />
</template>
@ -83,6 +83,8 @@
<style lang="less" scoped>
.delete-btn {
border-color: #909399;
background-color: #909399;
i {
width: 1em !important;
height: 1em !important;

View File

@ -57,7 +57,7 @@
<style lang="less">
.toggle {
.arco-dropdown-list {
@apply col-span-2 grid;
@apply grid grid-cols-2;
padding: 5px;
gap: 5px;

View File

@ -1,9 +1,9 @@
<template>
<div class="menu-container">
<mold :default-mold="props.defaultMold" @mold-change="handleMoldChange" />
<arrange />
<style-operation />
<font-operation />
<mold v-if="moldEnable" :default-mold="props.defaultMold" @mold-change="handleMoldChange" />
<arrange v-if="arrangeEnable" />
<style-operation v-if="styleEnable" />
<font-operation v-if="fontEnable" />
</div>
</template>
@ -12,9 +12,9 @@
import arrange from './arrange.vue';
import styleOperation from './styleOperation.vue';
import fontOperation from './fontOperation.vue';
import { moleProps } from '../../props';
import { moleProps, viewMenuProps } from '../../props';
const props = defineProps(moleProps);
const props = defineProps({ ...moleProps, ...viewMenuProps });
const emit = defineEmits<{
(e: 'moldChange', data: number): void;

View File

@ -15,6 +15,10 @@
:distinct-tags="props.distinctTags"
:default-mold="props.defaultMold"
:del-confirm="props.delConfirm"
:arrange-enable="props.arrangeEnable"
:mold-enable="props.moldEnable"
:font-enable="props.fontEnable"
:style-enable="props.styleEnable"
@mold-change="handleMoldChange"
/>
<main-editor
@ -42,7 +46,7 @@
import { onMounted } from 'vue';
import headerMenu from './main/header.vue';
import mainEditor from './main/mainEditor.vue';
import { editMenuProps, mainEditorProps, moleProps, priorityProps, tagProps, delProps } from './props';
import { editMenuProps, mainEditorProps, moleProps, priorityProps, tagProps, delProps, viewMenuProps } from './props';
const emit = defineEmits<{
(e: 'moldChange', data: number): void;
@ -57,6 +61,7 @@
...priorityProps,
...tagProps,
...delProps,
...viewMenuProps,
});
onMounted(async () => {

View File

@ -111,3 +111,26 @@ export const delProps = {
default: null,
},
};
export const viewMenuProps = {
viewMenuEnable: {
type: Boolean,
default: true,
},
moldEnable: {
type: Boolean,
default: true,
},
arrangeEnable: {
type: Boolean,
default: true,
},
styleEnable: {
type: Boolean,
default: true,
},
fontEnable: {
type: Boolean,
default: true,
},
};

View File

@ -1,4 +1,3 @@
@import 'mixin.less';
@import 'dropdown-list.less';
.mind-tab-panel {
@apply h-full w-full;
@ -14,11 +13,13 @@
}
}
.menu-btn {
@apply inline-flex cursor-pointer;
@include flexcenter;
@apply flex cursor-pointer items-center justify-center;
}
.menu-btn:not([disabled='true']):hover {
background-color: @btn-hover-color;
background-color: var(--color-fill-2);
}
.menu-btn[disabled='true'] {
opacity: 0.7;
}
.tab-icons {
@apply inline-flex;
@ -27,15 +28,14 @@
height: 20px;
}
.do-group {
@apply h-full w-[40px];
@apply h-full;
padding: 0 5px;
width: 40px;
p {
@apply m-0;
@apply m-0 flex items-center justify-center;
height: 50%;
@include flexcenter;
}
.undo i {
background-position: 0 -1240px;
@ -47,7 +47,7 @@
.insert-group {
width: 110px;
& > div {
margin: 5px 0;
margin: 0 5px;
}
.insert-sibling-box {
i {
@ -62,8 +62,9 @@
}
.edit-del-group,
.move-group {
@apply flex items-center justify-center;
width: 70px;
@include flexcenter;
}
.move-group {
.move-up {
@ -90,28 +91,26 @@
}
}
.attachment-group {
@apply flex items-center justify-center;
width: 185px;
@include flexcenter;
button {
@apply bg-no-repeat p-0;
@apply flex items-center justify-center border-none bg-transparent bg-no-repeat p-0 outline-none;
width: 45px;
height: 20px;
background-position: right;
@include button;
@include flexcenter;
span {
margin-left: 15px;
}
}
button:hover {
background-color: @btn-hover-color;
background-color: var(--color-fill-2);
}
& > div {
@apply h-full flex-wrap;
@apply flex h-full flex-wrap items-center justify-center;
width: 60px;
@include flexcenter;
}
.insert {
@apply bg-no-repeat;
@ -136,8 +135,9 @@
}
.progress-group,
.sequence-group {
@apply flex items-center justify-center;
width: 135px;
@include flexcenter;
ul {
@apply m-0 list-none p-0;
@ -172,8 +172,7 @@
.arrange-group {
width: 65px;
.arrange {
@apply flex-wrap;
@include flexcenter;
@apply flex flex-wrap items-center justify-center;
}
.tab-icons {
@apply m-0 inline-block bg-no-repeat;
@ -184,10 +183,11 @@
}
}
.style-group {
@apply w-[150px];
width: 150px;
.clear-style-btn {
@apply w-[65px] flex-wrap;
@include flexcenter;
@apply flex flex-wrap items-center justify-center;
width: 65px;
.tab-icons {
@apply m-0 inline-block bg-no-repeat;
@ -197,7 +197,7 @@
}
}
.copy-paste-panel {
@apply w-[70px];
width: 70px;
.tab-icons {
@apply inline-block;
@ -245,12 +245,13 @@
}
.expand-group,
.selection-group {
@apply flex items-center justify-center;
margin: 0 5px;
width: 60px;
button {
@apply border-none outline-none;
}
@include flexcenter;
span {
font-size: 12px;
}

View File

@ -1,16 +0,0 @@
@btn-hover-color: #eee;
*[disabled='true'] {
@apply opacity-50;
}
.block() {
@apply h-full w-full;
}
.button() {
@apply border-none bg-transparent outline-none;
}
.flexcenter() {
@apply flex items-center justify-center;
}

View File

@ -175,10 +175,10 @@
};
onMounted(() => {
const _theme = getLocalStorage<ThemeData>('vue-custom-theme', true) as ThemeData;
if (_theme) {
useTheme(_theme, false);
}
// const _theme = getLocalStorage<ThemeData>('vue-custom-theme', true) as ThemeData;
// if (_theme) {
// useTheme(_theme, false);
// }
});
const fetchThemeList = async (current: number, search: string) => {

View File

@ -1,5 +1,5 @@
<template>
<!-- <minder-editor
<minder-editor
class="minder-container"
:import-json="importJson"
:progress-enable="false"
@ -7,136 +7,81 @@
:tags="tags"
:default-mold="defaultMode"
:del-confirm="delConfirm"
:style-enable="true"
:arrange-enable="true"
:mold-enable="true"
:font-enable="true"
@save="save"
/> -->
/>
<!-- <JsonPicker /> -->
<div class="bg-white">
<a-tabs>
<a-tab-pane key="1">
<template #title> <icon-calendar /> Tab 1 </template>
Content of Tab Panel 1
</a-tab-pane>
<a-tab-pane key="2">
<template #title> <icon-clock-circle /> Tab 2 </template>
Content of Tab Panel 2
</a-tab-pane>
<a-tab-pane key="3">
<template #title> <icon-user /> Tab 3 </template>
Content of Tab Panel 3
</a-tab-pane>
</a-tabs>
<a-tabs class="w-[500px]" :editable="true" show-add-button auto-switch @add="handleAdd" @delete="handleDelete">
<a-tab-pane v-for="(item, index) of data" :key="item.key" :title="item.title" :closable="index !== 2">
{{ item?.content }}
</a-tab-pane>
</a-tabs>
</div>
</template>
<script setup lang="ts" name="minderIndex">
import { ref } from 'vue';
let count = 5;
const data = ref([
{
key: '1',
title: 'Tab 1',
content: 'Content of Tab Panel 1',
},
{
key: '2',
title: 'Tab 2',
content: 'Content of Tab Panel 2',
},
{
key: '3',
title: 'Tab 3',
content: 'Content of Tab Panel 3',
},
{
key: '4',
title: 'Tab 4',
content: 'Content of Tab Panel 4',
},
]);
const handleAdd = () => {
const number = count++;
data.value = data.value.concat({
key: `${number}`,
title: `New Tab ${number}`,
content: `Content of New Tab Panel ${number}`,
});
};
const handleDelete = (key: string | number) => {
data.value = data.value.filter((item) => item.key !== key);
};
// import MinderEditor from '@/components/minder-editor/minderEditor.vue';
import MinderEditor from '@/components/minder-editor/minderEditor.vue';
// import JsonPicker from '@/components/jsonpath-picker/index.vue';
// const importJson = {
// root: {
// data: {
// //
// text: 'vue3-minder-editor',
// //
// resource: ['1'],
// //
// // disable: true,
// // collapse
// // expandState: 'collapse',
// // disable true
// // tagEnable: true,
// // disable true
// // allowDelete: true,
// // disable true tagEnable
// // allowDisabledTag: true,
// },
// //
// children: [
// {
// data: {
// text: 'child1',
// // disable: true,
// expandState: 'collapse',
// resource: ['2'],
// },
// children: [
// {
// data: {
// text: 'axxaaaa',
// disable: true,
// allowDelete: true,
// // tagEnable: true,
// allowDisabledTag: true,
// resource: ['12'],
// priority: 3,
// loaded: true,
// },
// },
// ],
// },
// {
// data: {
// text: 'child2',
// },
// },
// ],
// },
// template: 'default',
// };
// const height = 500;
// const defaultMode = 3;
// const tags = ['1', '', '', '', '', ''];
const importJson = {
root: {
data: {
//
text: 'vue3-minder-editor',
//
resource: ['模块1'],
//
// disable: true,
// collapse
// expandState: 'collapse',
// disable true
// tagEnable: true,
// disable true
// allowDelete: true,
// disable true tagEnable
// allowDisabledTag: true,
},
//
children: [
{
data: {
text: 'child1',
// disable: true,
expandState: 'collapse',
resource: ['模块2'],
},
children: [
{
data: {
text: '地图axxaaaa',
disable: true,
allowDelete: true,
// tagEnable: true,
allowDisabledTag: true,
resource: ['模块12'],
priority: 3,
loaded: true,
},
},
],
},
{
data: {
text: 'child2',
},
},
],
},
template: 'default',
};
const height = 500;
const defaultMode = 3;
const tags = ['模块1', '用例', '前置条件', '测试步骤', '预期结果', '备注'];
// function save(data: any) {
// // eslint-disable-next-line no-console
// console.log(data);
// }
function save(data: any) {
// eslint-disable-next-line no-console
console.log(data);
}
// function delConfirm() {
// // eslint-disable-next-line no-console
// console.log('-=-=-=-=-=-=-==');
// }
function delConfirm() {
// eslint-disable-next-line no-console
console.log('-=-=-=-=-=-=-==');
}
</script>