feat(editor): editor使用tmagic-design

#401
This commit is contained in:
roymondchen 2022-10-11 20:25:10 +08:00 committed by jia000
parent 6d432ba1da
commit 63c61caccc
39 changed files with 558 additions and 138 deletions

View File

@ -15,6 +15,8 @@ import { getConfig } from './config';
const props = defineProps<{
bodyStyle?: Record<string, any>;
shadow?: string;
header?: string;
}>();
const uiComponent = getConfig('components').card;

View File

@ -0,0 +1,30 @@
<template>
<component :is="uiComponent.component" v-bind="uiProps" @update:modelValue="updateModelValue" @change="changeHandler">
<slot></slot>
</component>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { getConfig } from './config';
const props = defineProps<{
modelValue?: string | string[];
accordion?: boolean;
}>();
const uiComponent = getConfig('components').collapse;
const uiProps = computed(() => uiComponent.props(props));
const emit = defineEmits(['change', 'update:modelValue']);
const changeHandler = (v: any) => {
emit('change', v);
};
const updateModelValue = (v: any) => {
emit('update:modelValue', v);
};
</script>

View File

@ -0,0 +1,34 @@
<template>
<component :is="uiComponent.component" v-bind="uiProps" @update:modelValue="updateModelValue" @change="changeHandler">
<slot></slot>
<template #title>
<slot name="title"></slot>
</template>
</component>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { getConfig } from './config';
const props = defineProps<{
name?: string | number;
title?: string;
disabled?: boolean;
}>();
const uiComponent = getConfig('components').collapseItem;
const uiProps = computed(() => uiComponent.props(props));
const emit = defineEmits(['change', 'update:modelValue']);
const changeHandler = (v: any) => {
emit('change', v);
};
const updateModelValue = (v: any) => {
emit('update:modelValue', v);
};
</script>

View File

@ -16,6 +16,7 @@ import { getConfig } from './config';
const props = defineProps<{
modelValue?: boolean;
appendToBody?: boolean;
beforeClose?: any;
title?: string;
width?: string | number;
fullscreen?: boolean;

View File

@ -0,0 +1,21 @@
<template>
<component :is="uiComponent.component" v-bind="uiProps">
<slot></slot>
</component>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { getConfig } from './config';
const props = defineProps<{
direction?: string;
borderStyle?: string;
contentPosition?: string;
}>();
const uiComponent = getConfig('components').divider;
const uiProps = computed(() => uiComponent.props(props));
</script>

View File

@ -0,0 +1,41 @@
<template>
<component :is="uiComponent.component" v-bind="uiProps" @command="commandHandler">
<slot></slot>
<template #dropdown>
<slot name="dropdown"></slot>
</template>
</component>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { getConfig } from './config';
const props = defineProps<{
type?: string;
size?: string;
maxHeight?: string | number;
splitButton?: boolean;
disable?: boolean;
placement?: string;
trigger?: string;
hideOnClick?: boolean;
showTimeout?: number;
role?: string;
tabindex?: number;
popperClass?: string;
popperOptions?: any;
}>();
const uiComponent = getConfig('components').dropdown;
const uiProps = computed(() => uiComponent.props(props));
const emit = defineEmits(['command']);
const commandHandler = (...args: any[]) => {
emit('command', ...args);
};
</script>

View File

@ -0,0 +1,22 @@
<template>
<component :is="uiComponent.component" v-bind="uiProps">
<slot></slot>
</component>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { getConfig } from './config';
const props = defineProps<{
command?: any;
disabled?: boolean;
divided?: boolean;
icon?: any;
}>();
const uiComponent = getConfig('components').dropdownItem;
const uiProps = computed(() => uiComponent.props(props));
</script>

View File

@ -0,0 +1,17 @@
<template>
<component :is="uiComponent.component" v-bind="uiProps">
<slot></slot>
</component>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { getConfig } from './config';
const props = defineProps();
const uiComponent = getConfig('components').dropdownMenu;
const uiProps = computed(() => uiComponent.props(props));
</script>

View File

@ -25,11 +25,11 @@ const uiProps = computed(() => uiComponent.props(props));
defineExpose({
validate() {
form.value?.validate();
return form.value?.validate();
},
resetFields() {
form.value?.resetFields();
return form.value?.resetFields();
},
});
</script>

View File

@ -5,7 +5,7 @@
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { computed, ref } from 'vue';
import { getConfig } from './config';
@ -19,8 +19,4 @@ const uiComponent = getConfig('components').optionGroup;
const uiProps = computed(() => uiComponent.props(props));
const optionGroup = ref<any>();
onMounted(() => {
optionGroup.value.visible = true;
});
</script>

View File

@ -15,8 +15,13 @@ import { getConfig } from './config';
const props = defineProps<{
placement?: string;
width?: string;
width?: string | number;
title?: string;
trigger?: string;
effect?: string;
content?: string;
disabled?: boolean;
popperClass?: string;
}>();
const uiComponent = getConfig('components').popover;

View File

@ -0,0 +1,17 @@
<template>
<component :is="uiComponent.component" v-bind="uiProps">
<slot></slot>
</component>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { getConfig } from './config';
const props = defineProps();
const uiComponent = getConfig('components').scrollbar;
const uiProps = computed(() => uiComponent.props(props));
</script>

View File

@ -77,7 +77,7 @@ defineExpose({
setSelected() {
if (!select.value) return;
select.value.setSelected();
return select.value.setSelected();
},
});
</script>

View File

@ -3,6 +3,10 @@
<template #default>
<slot></slot>
</template>
<template #label v-if="$slots.label">
<slot name="label"></slot>
</template>
</component>
</template>

View File

@ -47,15 +47,15 @@ defineExpose({
$el: table.value?.$el,
clearSelection(...args: any[]) {
table.value?.clearSelection(...args);
return table.value?.clearSelection(...args);
},
toggleRowSelection(...args: any[]) {
table.value?.toggleRowSelection(...args);
return table.value?.toggleRowSelection(...args);
},
toggleRowExpansion(...args: any[]) {
table.value?.toggleRowExpansion(...args);
return table.value?.toggleRowExpansion(...args);
},
});
</script>

View File

@ -16,6 +16,9 @@ const props = defineProps<{
placement?: string;
disabled?: boolean;
content?: string;
effect?: string;
transition?: string;
offset?: number;
}>();
const uiComponent = getConfig('components').tooltip;

View File

@ -0,0 +1,127 @@
<template>
<component
ref="tree"
:is="uiComponent.component"
v-bind="uiProps"
@node-click="nodeClickHandler"
@node-contextmenu="contextmenu"
@node-drag-end="handleDragEnd"
@node-collapse="handleCollapse"
@node-expand="handleExpand"
@check="checkHandler"
@mousedown="mousedownHandler"
@mouseup="mouseupHandler"
>
<template #default="{ data, node }">
<slot :data="data" :node="node"></slot>
</template>
</component>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
import { getConfig } from './config';
const props = defineProps<{
data?: any[];
emptyText?: string;
nodeKey?: string;
props?: any;
renderAfterExpand?: boolean;
load?: any;
renderContent?: any;
highlightCurrent?: boolean;
defaultExpandAll?: boolean;
checkOnClickNode?: boolean;
autoExpandParent?: boolean;
defaultExpandedKeys?: any[];
showCheckbox?: boolean;
checkStrictly?: boolean;
defaultCheckedKeys?: any[];
currentNodeKey?: string | number;
filterNodeMethod?: (value: any, data: any, node: any) => void;
accordion?: boolean;
indent?: number;
icon?: any;
lazy?: boolean;
draggable?: boolean;
allowDrag?: (node: any) => boolean;
allowDrop?: any;
}>();
const uiComponent = getConfig('components').tree;
const uiProps = computed(() => uiComponent.props(props));
const emit = defineEmits([
'node-click',
'node-contextmenu',
'node-drag-end',
'node-collapse',
'node-expand',
'check',
'mousedown',
'mouseup',
]);
const nodeClickHandler = (...args: any[]) => {
emit('node-click', ...args);
};
const contextmenu = (...args: any[]) => {
emit('node-contextmenu', ...args);
};
const handleDragEnd = (...args: any[]) => {
emit('node-drag-end', ...args);
};
const handleCollapse = (...args: any[]) => {
emit('node-collapse', ...args);
};
const handleExpand = (...args: any[]) => {
emit('node-expand', ...args);
};
const checkHandler = (...args: any[]) => {
emit('check', ...args);
};
const mousedownHandler = (...args: any[]) => {
emit('mousedown', ...args);
};
const mouseupHandler = (...args: any[]) => {
emit('mouseup', ...args);
};
const tree = ref<any>();
defineExpose({
getData() {
return tree.value?.data;
},
getStore() {
return tree.value?.store;
},
filter(...args: any[]) {
return tree.value?.filter(...args);
},
getNode(...args: any[]) {
return tree.value?.getNode(...args);
},
setCheckedKeys(...args: any[]) {
return tree.value?.setCheckedKeys(...args);
},
setCurrentKey(...args: any[]) {
return tree.value?.setCurrentKey(...args);
},
});
</script>

View File

@ -25,7 +25,7 @@ const upload = ref<any>();
defineExpose({
clearFiles(...args: any[]) {
upload.value?.clearFiles(...args);
return upload.value?.clearFiles(...args);
},
});
</script>

View File

@ -1,6 +1,6 @@
import { App } from 'vue';
import { getConfig, setConfig } from './config';
import { setConfig } from './config';
import { PluginOptions, TMagicMessage, TMagicMessageBox } from './type';
export * from './type';
@ -13,9 +13,15 @@ export { default as TMagicCascader } from './Cascader.vue';
export { default as TMagicCheckbox } from './Checkbox.vue';
export { default as TMagicCheckboxGroup } from './CheckboxGroup.vue';
export { default as TMagicCol } from './Col.vue';
export { default as TMagicCollapse } from './Collapse.vue';
export { default as TMagicCollapseItem } from './CollapseItem.vue';
export { default as TMagicColorPicker } from './ColorPicker.vue';
export { default as TMagicDatePicker } from './DatePicker.vue';
export { default as TMagicDialog } from './Dialog.vue';
export { default as TMagicDivider } from './Divider.vue';
export { default as TMagicDropdown } from './Dropdown.vue';
export { default as TMagicDropdownItem } from './DropdownItem.vue';
export { default as TMagicDropdownMenu } from './DropdownMenu.vue';
export { default as TMagicForm } from './Form.vue';
export { default as TMagicFormItem } from './FormItem.vue';
export { default as TMagicIcon } from './Icon.vue';
@ -28,6 +34,7 @@ export { default as TMagicPopover } from './Popover.vue';
export { default as TMagicRadio } from './Radio.vue';
export { default as TMagicRadioGroup } from './RadioGroup.vue';
export { default as TMagicRow } from './Row.vue';
export { default as TMagicScrollbar } from './Scrollbar.vue';
export { default as TMagicSelect } from './Select.vue';
export { default as TMagicStep } from './Step.vue';
export { default as TMagicSteps } from './Steps.vue';
@ -39,13 +46,28 @@ export { default as TMagicTabs } from './Tabs.vue';
export { default as TMagicTag } from './Tag.vue';
export { default as TMagicTimePicker } from './TimePicker.vue';
export { default as TMagicTooltip } from './Tooltip.vue';
export { default as TMagicTree } from './Tree.vue';
export { default as TMagicUpload } from './Upload.vue';
export const tMagicMessage: TMagicMessage = getConfig('message') as TMagicMessage;
export const tMagicMessageBox: TMagicMessageBox = getConfig('messageBox') as TMagicMessageBox;
export const tMagicMessage = {} as unknown as TMagicMessage;
export const tMagicMessageBox = {} as unknown as TMagicMessageBox;
export default {
install(app: App, options: PluginOptions) {
if (options.message) {
tMagicMessage.error = options.message?.error;
tMagicMessage.success = options.message?.success;
tMagicMessage.warning = options.message?.warning;
tMagicMessage.info = options.message?.info;
tMagicMessage.closeAll = options.message?.closeAll;
}
if (options.messageBox) {
tMagicMessageBox.alert = options.messageBox?.alert;
tMagicMessageBox.confirm = options.messageBox?.confirm;
tMagicMessageBox.prompt = options.messageBox?.prompt;
tMagicMessageBox.close = options.messageBox?.close;
}
app.config.globalProperties.$MAGIC_DESIGN = options;
setConfig(options);
},

View File

@ -12,6 +12,7 @@ export interface TMagicMessage {
warning: (msg: string) => void;
info: (msg: string) => void;
error: (msg: string) => void;
closeAll: () => void;
}
export type ElMessageBoxShortcutMethod = ((

View File

@ -46,13 +46,13 @@
"@babel/core": "^7.18.0",
"@element-plus/icons-vue": "^2.0.9",
"@tmagic/core": "1.2.0-beta.2",
"@tmagic/design": "1.2.0-beta.2",
"@tmagic/form": "1.2.0-beta.2",
"@tmagic/schema": "1.2.0-beta.2",
"@tmagic/stage": "1.2.0-beta.2",
"@tmagic/utils": "1.2.0-beta.2",
"buffer": "^6.0.3",
"color": "^3.1.3",
"element-plus": "^2.2.17",
"events": "^3.3.0",
"gesto": "^1.7.0",
"keycon": "^1.1.2",
@ -62,8 +62,8 @@
"vue": "^3.2.37"
},
"peerDependencies": {
"@tmagic/design": "1.2.0-beta.2",
"@tmagic/form": "1.2.0-beta.2",
"element-plus": "^2.2.17",
"monaco-editor": "^0.34.0",
"vue": "^3.2.37"
},

View File

@ -1,14 +1,14 @@
<template>
<div v-if="menuData.length && visible" class="magic-editor-content-menu" ref="menu" :style="menuStyle">
<div>
<tool-button
<ToolButton
v-for="(item, index) in menuData"
event-type="mouseup"
:data="item"
:key="index"
@mouseup="hide"
@mouseenter="showSubMenu(item)"
></tool-button>
></ToolButton>
</div>
<teleport to="body">
<content-menu

View File

@ -1,16 +1,18 @@
<template>
<el-icon v-if="!icon" class="magic-editor-icon"><Edit></Edit></el-icon>
<el-icon v-else-if="typeof icon === 'string' && icon.startsWith('http')" class="magic-editor-icon"
<TMagicIcon v-if="!icon" class="magic-editor-icon"><Edit></Edit></TMagicIcon>
<TMagicIcon v-else-if="typeof icon === 'string' && icon.startsWith('http')" class="magic-editor-icon"
><img :src="icon"
/></el-icon>
/></TMagicIcon>
<i v-else-if="typeof icon === 'string'" class="magic-editor-icon" :class="icon"></i>
<el-icon v-else class="magic-editor-icon"><component :is="toRaw(icon)"></component></el-icon>
<TMagicIcon v-else class="magic-editor-icon"><component :is="toRaw(icon)"></component></TMagicIcon>
</template>
<script lang="ts" setup>
import { toRaw } from 'vue';
import { Edit } from '@element-plus/icons-vue';
import { TMagicIcon } from '@tmagic/design';
defineProps<{
icon?: any;
}>();

View File

@ -7,32 +7,37 @@
@mousedown="mousedownHandler(data, $event)"
@mouseup="mouseupHandler(data, $event)"
>
<el-divider v-if="data.type === 'divider'" :direction="data.direction || 'vertical'"></el-divider>
<TMagicDivider v-if="data.type === 'divider'" :direction="data.direction || 'vertical'"></TMagicDivider>
<div v-else-if="data.type === 'text'" class="menu-item-text">{{ data.text }}</div>
<template v-else-if="data.type === 'button'">
<el-tooltip v-if="data.tooltip" effect="dark" placement="bottom-start" :content="data.tooltip">
<el-button size="small" text :disabled="disabled"
><MIcon v-if="data.icon" :icon="data.icon"></MIcon><span>{{ data.text }}</span></el-button
<TMagicTooltip v-if="data.tooltip" effect="dark" placement="bottom-start" :content="data.tooltip">
<TMagicButton size="small" text :disabled="disabled"
><MIcon v-if="data.icon" :icon="data.icon"></MIcon><span>{{ data.text }}</span></TMagicButton
>
</el-tooltip>
<el-button v-else size="small" text :disabled="disabled"
><MIcon v-if="data.icon" :icon="data.icon"></MIcon><span>{{ data.text }}</span></el-button
</TMagicTooltip>
<TMagicButton v-else size="small" text :disabled="disabled"
><MIcon v-if="data.icon" :icon="data.icon"></MIcon><span>{{ data.text }}</span></TMagicButton
>
</template>
<el-dropdown v-else-if="data.type === 'dropdown'" trigger="click" :disabled="disabled" @command="dropdownHandler">
<TMagicDropdown
v-else-if="data.type === 'dropdown'"
trigger="click"
:disabled="disabled"
@command="dropdownHandler"
>
<span class="el-dropdown-link menubar-menu-button">
{{ data.text }}<el-icon class="el-icon--right"><ArrowDown></ArrowDown></el-icon>
{{ data.text }}<TMagicIcon class="el-icon--right"><ArrowDown></ArrowDown></TMagicIcon>
</span>
<template #dropdown>
<el-dropdown-menu v-if="data.items && data.items.length">
<el-dropdown-item v-for="(subItem, index) in data.items" :key="index" :command="{ data, subItem }">{{
<TMagicDropdownMenu v-if="data.items && data.items.length">
<TMagicDropdownItem v-for="(subItem, index) in data.items" :key="index" :command="{ data, subItem }">{{
subItem.text
}}</el-dropdown-item>
</el-dropdown-menu>
}}</TMagicDropdownItem>
</TMagicDropdownMenu>
</template>
</el-dropdown>
</TMagicDropdown>
<component v-else-if="data.type === 'component'" v-bind="data.props || {}" :is="data.component"></component>
</div>
@ -42,6 +47,16 @@
import { computed, inject } from 'vue';
import { ArrowDown } from '@element-plus/icons-vue';
import {
TMagicButton,
TMagicDivider,
TMagicDropdown,
TMagicDropdownItem,
TMagicDropdownMenu,
TMagicIcon,
TMagicTooltip,
} from '@tmagic/design';
import MIcon from '../components/Icon.vue';
import type { MenuButton, MenuComponent, Services } from '../type';

View File

@ -1,6 +1,6 @@
<template>
<div class="m-fields-code-select" :key="fieldKey">
<el-card shadow="never">
<TMagicCard shadow="never">
<template #header>
<m-fields-select
:config="selectConfig"
@ -12,7 +12,7 @@
></m-fields-select>
</template>
<div class="tool-bar">
<el-tooltip class="tool-item" effect="dark" content="查看代码块" placement="top">
<TMagicTooltip class="tool-item" effect="dark" content="查看代码块" placement="top">
<svg
@click="viewHandler"
preserveAspectRatio="xMidYMid meet"
@ -26,17 +26,17 @@
d="m23 12l-7.071 7.071l-1.414-1.414L20.172 12l-5.657-5.657l1.414-1.414L23 12zM3.828 12l5.657 5.657l-1.414 1.414L1 12l7.071-7.071l1.414 1.414L3.828 12z"
></path>
</svg>
</el-tooltip>
</TMagicTooltip>
</div>
</el-card>
</TMagicCard>
</div>
</template>
<script lang="ts" setup>
import { computed, defineEmits, defineProps, inject, ref, watchEffect } from 'vue';
import { ElMessage } from 'element-plus';
import { cloneDeep, map, xor } from 'lodash-es';
import { TMagicCard, tMagicMessage, TMagicTooltip } from '@tmagic/design';
import { SelectConfig } from '@tmagic/form';
import type { Services } from '../type';
@ -128,7 +128,7 @@ const setCombineIds = async (codeIds: string[]) => {
const viewHandler = async () => {
if (props.model[props.name].length === 0) {
ElMessage.error('请先绑定代码块');
tMagicMessage.error('请先绑定代码块');
return;
}
//

View File

@ -1,14 +1,14 @@
<template>
<div class="m-fields-ui-select" v-if="uiSelectMode" @click="cancelHandler">
<el-button type="danger" :icon="Delete" text style="padding: 0">取消</el-button>
<TMagicButton type="danger" :icon="Delete" text style="padding: 0">取消</TMagicButton>
</div>
<div class="m-fields-ui-select" v-else @click="startSelect" style="display: flex">
<el-tooltip v-if="val" content="清除">
<el-button style="padding: 0" type="danger" :icon="Close" text @click.stop="deleteHandler"></el-button>
</el-tooltip>
<el-tooltip :content="val ? toName + '_' + val : '点击此处选择'">
<el-button text style="padding: 0; margin: 0">{{ val ? toName + '_' + val : '点击此处选择' }}</el-button>
</el-tooltip>
<TMagicTooltip v-if="val" content="清除">
<TMagicButton style="padding: 0" type="danger" :icon="Close" text @click.stop="deleteHandler"></TMagicButton>
</TMagicTooltip>
<TMagicTooltip :content="val ? toName + '_' + val : '点击此处选择'">
<TMagicButton text style="padding: 0; margin: 0">{{ val ? toName + '_' + val : '点击此处选择' }}</TMagicButton>
</TMagicTooltip>
</div>
</template>
@ -16,6 +16,7 @@
import { computed, inject, ref } from 'vue';
import { Close, Delete } from '@element-plus/icons-vue';
import { TMagicButton, TMagicTooltip } from '@tmagic/design';
import { FormState } from '@tmagic/form';
import { Services } from '../type';

View File

@ -3,7 +3,7 @@
<div class="m-editor-empty-content">
<div class="m-editor-empty-button" @click="clickHandler">
<div>
<el-icon><plus /></el-icon>
<MIcon :icon="Plus"></MIcon>
</div>
<p>新增页面</p>
</div>
@ -17,6 +17,7 @@ import { Plus } from '@element-plus/icons-vue';
import { NodeType } from '@tmagic/schema';
import MIcon from '../components/Icon.vue';
import type { Services } from '../type';
import { generatePageNameByApp } from '../utils';

View File

@ -34,9 +34,9 @@
</template>
<template v-if="pageLength > 0" #right>
<el-scrollbar>
<TMagicScrollbar>
<slot name="props-panel"></slot>
</el-scrollbar>
</TMagicScrollbar>
</template>
</layout>
</div>
@ -45,6 +45,7 @@
<script lang="ts" setup>
import { computed, inject, ref, watchEffect } from 'vue';
import { TMagicScrollbar } from '@tmagic/design';
import type { MApp } from '@tmagic/schema';
import { GetColumnWidth, Services } from '../type';

View File

@ -15,8 +15,8 @@
<script lang="ts" setup>
import { computed, getCurrentInstance, inject, onMounted, ref, watchEffect } from 'vue';
import { ElMessage } from 'element-plus';
import { tMagicMessage } from '@tmagic/design';
import type { FormValue, MForm } from '@tmagic/form';
import type { MNode } from '@tmagic/schema';
import type StageCore from '@tmagic/stage';
@ -65,13 +65,8 @@ const submit = async () => {
services?.editorService.update(values);
} catch (e: any) {
console.error(e);
ElMessage.closeAll();
ElMessage.error({
duration: 10000,
showClose: true,
message: e.message,
dangerouslyUseHTMLString: true,
});
tMagicMessage.closeAll();
tMagicMessage.error(e.message);
}
};

View File

@ -1,9 +1,9 @@
<template>
<el-scrollbar>
<TMagicScrollbar>
<slot name="component-list-panel-header"></slot>
<el-collapse class="ui-component-panel" :model-value="collapseValue">
<el-input
<TMagicCollapse class="ui-component-panel" :model-value="collapseValue">
<TMagicInput
prefix-icon="el-icon-search"
placeholder="输入关键字进行过滤"
class="search-input"
@ -12,8 +12,8 @@
v-model="searchText"
/>
<template v-for="(group, index) in list">
<el-collapse-item v-if="group.items && group.items.length" :key="index" :name="index">
<template #title><i class="el-icon-s-grid"></i>{{ group.title }}</template>
<TMagicCollapseItem v-if="group.items && group.items.length" :key="index" :name="`${index}`">
<template #title><MIcon :icon="Grid"></MIcon>{{ group.title }}</template>
<div
v-for="item in group.items"
class="component-item"
@ -27,21 +27,23 @@
<slot name="component-list-item" :component="item">
<MIcon :icon="item.icon"></MIcon>
<el-tooltip effect="dark" placement="bottom" :content="item.text">
<TMagicTooltip effect="dark" placement="bottom" :content="item.text">
<span>{{ item.text }}</span>
</el-tooltip>
</TMagicTooltip>
</slot>
</div>
</el-collapse-item>
</TMagicCollapseItem>
</template>
</el-collapse>
</el-scrollbar>
</TMagicCollapse>
</TMagicScrollbar>
</template>
<script lang="ts" setup>
import { computed, inject, ref } from 'vue';
import { Grid } from '@element-plus/icons-vue';
import serialize from 'serialize-javascript';
import { TMagicCollapse, TMagicCollapseItem, TMagicInput, TMagicScrollbar, TMagicTooltip } from '@tmagic/design';
import type StageCore from '@tmagic/stage';
import { removeClassNameByClassName } from '@tmagic/utils';
@ -62,7 +64,7 @@ const list = computed(() =>
const collapseValue = computed(() =>
Array(list.value?.length)
.fill(1)
.map((x, i) => i),
.map((x, i) => `${i}`),
);
let timeout: NodeJS.Timeout | undefined;

View File

@ -1,21 +1,21 @@
<template>
<el-scrollbar
<TMagicScrollbar
class="magic-editor-layer-panel"
@mouseenter="addSelectModeListener"
@mouseleave="removeSelectModeListener"
>
<slot name="layer-panel-header"></slot>
<el-input
<TMagicInput
class="filterInput"
size="small"
placeholder="输入关键字进行过滤"
clearable
v-model="filterText"
@change="filterTextChangeHandler"
></el-input>
></TMagicInput>
<el-tree
<TMagicTree
v-if="values.length"
ref="tree"
node-key="id"
@ -55,20 +55,20 @@
</slot>
</div>
</template>
</el-tree>
</TMagicTree>
<teleport to="body">
<layer-menu ref="menu"></layer-menu>
</teleport>
</el-scrollbar>
</TMagicScrollbar>
</template>
<script lang="ts" setup>
import { computed, inject, ref, watch } from 'vue';
import type { ElTree } from 'element-plus';
import KeyController from 'keycon';
import { throttle } from 'lodash-es';
import { TMagicInput, TMagicScrollbar, TMagicTree } from '@tmagic/design';
import type { Id, MNode, MPage } from '@tmagic/schema';
import { MContainer, NodeType } from '@tmagic/schema';
import StageCore from '@tmagic/stage';
@ -80,7 +80,7 @@ import LayerMenu from './LayerMenu.vue';
const throttleTime = 150;
const services = inject<Services>('services');
const tree = ref<InstanceType<typeof ElTree>>();
const tree = ref<InstanceType<typeof TMagicTree>>();
const menu = ref<InstanceType<typeof LayerMenu>>();
const editorService = services?.editorService;
const page = computed(() => editorService?.get('page'));
@ -157,7 +157,7 @@ const handleDragEnd = async (e: any) => {
node.style.top = 0;
node.style.left = 0;
}
const { data } = tree.value;
const data = tree.value.getData();
const [page] = data as [MPage];
editorService?.update(page);
};
@ -228,7 +228,7 @@ watch(
setTimeout(() => {
tree.value &&
Object.entries(tree.value.store.nodesMap).forEach(([id, node]) => {
Object.entries(tree.value.getStore().nodesMap).forEach(([id, node]: [string, any]) => {
if (node.expanded && node.data.items) {
expandedKeys.set(id, id);
}

View File

@ -1,5 +1,5 @@
<template>
<el-tabs
<TMagicTabs
v-if="data.type === 'tabs' && data.items.length"
class="m-editor-sidebar"
v-model="activeTabName"
@ -35,12 +35,14 @@
<slot name="code-block-edit-panel-header" :id="id"></slot>
</template>
</tab-pane>
</el-tabs>
</TMagicTabs>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue';
import { TMagicTabs } from '@tmagic/design';
import { SideBarData } from '../../type';
import TabPane from './TabPane.vue';

View File

@ -1,5 +1,5 @@
<template>
<el-tab-pane v-if="config" :name="config.text">
<TMagicTabPane v-if="config" :name="config.text">
<template #label>
<div :key="config.text">
<m-icon v-if="config.icon" :icon="config.icon"></m-icon>
@ -61,13 +61,15 @@
/>
</template>
</component>
</el-tab-pane>
</TMagicTabPane>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { Coin, EditPen, Files } from '@element-plus/icons-vue';
import { TMagicTabPane } from '@tmagic/design';
import MIcon from '../../components/Icon.vue';
import { SideComponent, SideItem } from '../../type';

View File

@ -1,5 +1,5 @@
<template>
<el-dialog
<TMagicDialog
v-model="isShowCodeBlockEditor"
class="code-editor-dialog"
:title="currentTitle"
@ -10,16 +10,15 @@
<layout v-model:left="left" :min-left="45" class="code-editor-layout">
<!-- 左侧列表 -->
<template #left v-if="mode === CodeEditorMode.LIST">
<el-tree
<TMagicTree
v-if="!isEmpty(state.codeList)"
ref="tree"
class="side-tree"
node-key="id"
empty-text="暂无代码块"
:data="state.codeList"
:highlight-current="true"
@node-click="selectHandler"
:current-node-key="state.codeList[0].id"
class="side-tree"
@node-click="selectHandler"
>
<template #default="{ data }">
<div :id="data.id" class="list-container">
@ -28,7 +27,7 @@
</div>
</div>
</template>
</el-tree>
</TMagicTree>
</template>
<!-- 右侧区域 -->
<template #center>
@ -41,11 +40,16 @@
]"
>
<slot name="code-block-edit-panel-header" :id="id"></slot>
<el-card shadow="never">
<TMagicCard shadow="never">
<template #header>
<div class="code-name-wrapper">
<div class="code-name-label">代码块名称</div>
<el-input v-if="codeConfig" class="code-name-input" v-model="codeConfig.name" :disabled="!editable" />
<TMagicInput
v-if="codeConfig"
class="code-name-input"
v-model="codeConfig.name"
:disabled="!editable"
/>
</div>
</template>
<div class="m-editor-wrapper">
@ -63,26 +67,27 @@
}"
></magic-code-editor>
<div class="m-editor-content-bottom" v-if="editable">
<el-button type="primary" class="button" @click="saveCode">保存</el-button>
<el-button type="primary" class="button" @click="saveAndClose">关闭</el-button>
<TMagicButton type="primary" class="button" @click="saveCode">保存</TMagicButton>
<TMagicButton type="primary" class="button" @click="saveAndClose">关闭</TMagicButton>
</div>
<div class="m-editor-content-bottom" v-else>
<el-button type="primary" class="button" @click="saveAndClose">关闭</el-button>
<TMagicButton type="primary" class="button" @click="saveAndClose">关闭</TMagicButton>
</div>
</div>
</el-card>
</TMagicCard>
</div>
</template>
</layout>
</el-dialog>
</TMagicDialog>
</template>
<script lang="ts" setup>
import { computed, inject, reactive, ref, watchEffect } from 'vue';
import { ElMessage } from 'element-plus';
import { forIn, isEmpty } from 'lodash-es';
import type * as monaco from 'monaco-editor';
import { TMagicButton, TMagicCard, TMagicDialog, TMagicInput, tMagicMessage, TMagicTree } from '@tmagic/design';
import type { CodeBlockContent, CodeDslList, ListState, Services } from '../../../type';
import { CodeEditorMode } from '../../../type';
import MagicCodeEditor from '../../CodeEditor.vue';
@ -137,7 +142,7 @@ const saveCode = async (): Promise<boolean> => {
/* eslint no-eval: "off" */
codeConfig.value.content = eval(codeContent);
} catch (e: any) {
ElMessage.error(e.stack);
tMagicMessage.error(e.stack);
return false;
}
// dsl
@ -145,7 +150,7 @@ const saveCode = async (): Promise<boolean> => {
name: codeConfig.value.name,
content: codeConfig.value.content,
});
ElMessage.success('代码保存成功');
tMagicMessage.success('代码保存成功');
return true;
};

View File

@ -2,22 +2,22 @@
<div class="m-editor-code-block-list">
<slot name="code-block-panel-header">
<div class="code-header-wrapper">
<el-input
<TMagicInput
:class="[editable ? 'code-filter-input' : 'code-filter-input-no-btn']"
size="small"
placeholder="输入关键字进行过滤"
clearable
v-model="filterText"
@input="filterTextChangeHandler"
></el-input>
<el-button class="create-code-button" type="primary" size="small" @click="createCodeBlock" v-if="editable"
>新增</el-button
></TMagicInput>
<TMagicButton class="create-code-button" type="primary" size="small" @click="createCodeBlock" v-if="editable"
>新增</TMagicButton
>
</div>
</slot>
<!-- 代码块列表 -->
<el-tree
<TMagicTree
v-if="!isEmpty(state.codeList)"
ref="tree"
node-key="id"
@ -33,20 +33,20 @@
<div class="code-name">{{ data.name }}{{ data.id }}</div>
<!-- 右侧工具栏 -->
<div class="right-tool">
<el-tooltip effect="dark" :content="editable ? '编辑' : '查看'" placement="bottom">
<TMagicTooltip effect="dark" :content="editable ? '编辑' : '查看'" placement="bottom">
<Icon :icon="editable ? Edit : View" class="edit-icon" @click.stop="editCode(`${data.id}`)"></Icon>
</el-tooltip>
<el-tooltip
</TMagicTooltip>
<TMagicTooltip
effect="dark"
content="查看绑定关系"
placement="bottom"
v-if="state.bindComps[data.id] && state.bindComps[data.id].length > 0"
>
<Icon :icon="Link" class="edit-icon" @click.stop="toggleCombineRelation(data)"></Icon>
</el-tooltip>
<el-tooltip effect="dark" content="删除" placement="bottom" v-if="editable">
</TMagicTooltip>
<TMagicTooltip effect="dark" content="删除" placement="bottom" v-if="editable">
<Icon :icon="Close" class="edit-icon" @click.stop="deleteCode(`${data.id}`)"></Icon>
</el-tooltip>
</TMagicTooltip>
<slot name="code-block-panel-tool" :id="data.id" :data="data.codeBlockContent"></slot>
</div>
</div>
@ -62,27 +62,27 @@
></path>
</svg>
<!-- todo 功能暂时隐藏 -->
<!-- <el-button
<!-- <TMagicButton
v-for="(comp, index) in state.bindComps[data.id]"
:key="index"
class="code-comp"
size="small"
:plain="true"
>{{ comp.name }}<Icon :icon="Close" class="comp-delete-icon" @click.stop="unbind(comp.id, data.id)"></Icon
></el-button> -->
<el-button
></TMagicButton> -->
<TMagicButton
v-for="(comp, index) in state.bindComps[data.id]"
:key="index"
class="code-comp"
size="small"
:plain="true"
@click.stop="selectComp(comp.id)"
>{{ comp.name }}</el-button
>{{ comp.name }}</TMagicButton
>
</div>
</div>
</template>
</el-tree>
</TMagicTree>
<!-- 代码块编辑区 -->
<code-block-editor>
@ -96,9 +96,9 @@
<script lang="ts" setup>
import { computed, inject, reactive, ref, watch } from 'vue';
import { Close, Edit, Link, View } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { forIn, isEmpty } from 'lodash-es';
import { TMagicButton, TMagicInput, tMagicMessage, TMagicTooltip, TMagicTree } from '@tmagic/design';
import { Id } from '@tmagic/schema';
import StageCore from '@tmagic/stage';
@ -184,7 +184,7 @@ watch(
const createCodeBlock = async () => {
const { codeBlockService } = services || {};
if (!codeBlockService) {
ElMessage.error('新增代码块失败');
tMagicMessage.error('新增代码块失败');
return;
}
const codeConfig: CodeBlockContent = {
@ -214,7 +214,7 @@ const deleteCode = (key: string) => {
if (typeof props.customError === 'function') {
props.customError(key, existBinds ? CodeDeleteErrorType.BIND : CodeDeleteErrorType.UNDELETEABLE);
} else {
ElMessage.error('代码块删除失败');
tMagicMessage.error('代码块删除失败');
}
}
};

View File

@ -9,39 +9,39 @@
>
<div class="m-editor-page-bar-title">
<slot name="page-bar-title" :page="item">
<el-tooltip effect="dark" placement="top-start" :content="item.name">
<TMagicTooltip effect="dark" placement="top-start" :content="item.name">
<span>{{ item.name || item.id }}</span>
</el-tooltip>
</TMagicTooltip>
</slot>
</div>
<el-popover popper-class="page-bar-popover" placement="top" :width="160" trigger="hover">
<TMagicPopover popper-class="page-bar-popover" placement="top" :width="160" trigger="hover">
<div>
<slot name="page-bar-popover" :page="item">
<tool-button
<ToolButton
:data="{
type: 'button',
text: '复制',
icon: DocumentCopy,
handler: () => copy(item),
}"
></tool-button>
<tool-button
></ToolButton>
<ToolButton
:data="{
type: 'button',
text: '删除',
icon: Delete,
handler: () => remove(item),
}"
></tool-button>
></ToolButton>
</slot>
</div>
<template #reference>
<el-icon class="m-editor-page-bar-menu-icon">
<TMagicIcon class="m-editor-page-bar-menu-icon">
<CaretBottom></CaretBottom>
</el-icon>
</TMagicIcon>
</template>
</el-popover>
</TMagicPopover>
</div>
</PageBarScrollContainer>
</template>
@ -50,6 +50,7 @@
import { computed, inject } from 'vue';
import { CaretBottom, Delete, DocumentCopy } from '@element-plus/icons-vue';
import { TMagicIcon, TMagicPopover, TMagicTooltip } from '@tmagic/design';
import type { MApp, MPage } from '@tmagic/schema';
import ToolButton from '../../components/ToolButton.vue';

View File

@ -5,9 +5,15 @@ import {
ElCheckbox,
ElCheckboxGroup,
ElCol,
ElCollapse,
ElCollapseItem,
ElColorPicker,
ElDatePicker,
ElDialog,
ElDivider,
ElDropdown,
ElDropdownItem,
ElDropdownMenu,
ElForm,
ElFormItem,
ElIcon,
@ -18,9 +24,11 @@ import {
ElOption,
ElOptionGroup,
ElPagination,
ElPopover,
ElRadio,
ElRadioGroup,
ElRow,
ElScrollbar,
ElSelect,
ElStep,
ElSteps,
@ -31,6 +39,7 @@ import {
ElTabs,
ElTimePicker,
ElTooltip,
ElTree,
ElUpload,
} from 'element-plus';
@ -68,6 +77,16 @@ const adapter: any = {
props: (props: any) => props,
},
collapse: {
component: ElCollapse,
props: (props: any) => props,
},
collapseItem: {
component: ElCollapseItem,
props: (props: any) => props,
},
colorPicker: {
component: ElColorPicker,
props: (props: any) => props,
@ -83,6 +102,26 @@ const adapter: any = {
props: (props: any) => props,
},
divider: {
component: ElDivider,
props: (props: any) => props,
},
dropdown: {
component: ElDropdown,
props: (props: any) => props,
},
dropdownItem: {
component: ElDropdownItem,
props: (props: any) => props,
},
dropdownMenu: {
component: ElDropdownMenu,
props: (props: any) => props,
},
form: {
component: ElForm,
props: (props: any) => props,
@ -123,6 +162,11 @@ const adapter: any = {
props: (props: any) => props,
},
popover: {
component: ElPopover,
props: (props: any) => props,
},
radio: {
component: ElRadio,
props: (props: any) => props,
@ -138,6 +182,11 @@ const adapter: any = {
props: (props: any) => props,
},
scrollbar: {
component: ElScrollbar,
props: (props: any) => props,
},
select: {
component: ElSelect,
props: (props: any) => props,
@ -193,6 +242,11 @@ const adapter: any = {
props: (props: any) => props,
},
tree: {
component: ElTree,
props: (props: any) => props,
},
upload: {
component: ElUpload,
props: (props: any) => props,

View File

@ -35,13 +35,11 @@
"@tmagic/design": "1.2.0-beta.2",
"@tmagic/form": "1.2.0-beta.2",
"@tmagic/utils": "1.2.0-beta.2",
"element-plus": "^2.2.17",
"lodash-es": "^4.17.21",
"vue": "^3.2.37"
},
"peerDependencies": {
"@tmagic/form": "1.2.0-beta.2",
"element-plus": "^2.2.17",
"vue": "^3.2.37"
},
"devDependencies": {

6
pnpm-lock.yaml generated
View File

@ -189,6 +189,7 @@ importers:
'@babel/core': ^7.18.0
'@element-plus/icons-vue': ^2.0.9
'@tmagic/core': 1.2.0-beta.2
'@tmagic/design': 1.2.0-beta.2
'@tmagic/form': 1.2.0-beta.2
'@tmagic/schema': 1.2.0-beta.2
'@tmagic/stage': 1.2.0-beta.2
@ -202,7 +203,6 @@ importers:
'@vue/test-utils': ^2.0.0
buffer: ^6.0.3
color: ^3.1.3
element-plus: ^2.2.17
events: ^3.3.0
gesto: ^1.7.0
keycon: ^1.1.2
@ -219,13 +219,13 @@ importers:
'@babel/core': 7.18.2
'@element-plus/icons-vue': 2.0.9_vue@3.2.37
'@tmagic/core': link:../core
'@tmagic/design': link:../design
'@tmagic/form': link:../form
'@tmagic/schema': link:../schema
'@tmagic/stage': link:../stage
'@tmagic/utils': link:../utils
buffer: 6.0.3
color: 3.2.1
element-plus: 2.2.17_vue@3.2.37
events: 3.3.0
gesto: 1.8.1
keycon: 1.1.2
@ -365,7 +365,6 @@ importers:
'@vitejs/plugin-vue': ^3.1.0
'@vue/compiler-sfc': ^3.2.37
'@vue/test-utils': ^2.0.0
element-plus: ^2.2.17
lodash-es: ^4.17.21
rimraf: ^3.0.2
sass: ^1.35.1
@ -377,7 +376,6 @@ importers:
'@tmagic/design': link:../design
'@tmagic/form': link:../form
'@tmagic/utils': link:../utils
element-plus: 2.2.17_vue@3.2.37
lodash-es: 4.17.21
vue: 3.2.37
devDependencies: