Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 67 additions & 5 deletions packages/controller/src/useLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ const PLUGIN_POSITION = {
leftBottom: 'leftBottom',
independence: 'independence',
rightTop: 'rightTop',
rightBottom: 'rightBottom'
rightBottom: 'rightBottom',
fixed: 'fixed'
}

const pluginState = reactive({
Expand Down Expand Up @@ -184,11 +185,15 @@ export default () => {

//获取某个布局(左上/左下/右上)的插件名称列表
const getPluginsByLayout = (layout = 'all') => {
// 遍历对象并将 align 值分类到不同的数组中
const targetLayout = Object.keys(pluginStorageReactive.value).filter(
// 筛选出符合布局条件的插件名称
const pluginNames = Object.keys(pluginStorageReactive.value).filter(
(key) => pluginStorageReactive.value[key].align === layout || layout === 'all'
)
return targetLayout //这里返回的是只有名字的数组

// 根据 index 对插件名称进行排序
pluginNames.sort((a, b) => pluginStorageReactive.value[a].index - pluginStorageReactive.value[b].index)

return pluginNames // 返回排序后的插件名称数组
}

//修改某个插件的布局
Expand All @@ -198,6 +203,61 @@ export default () => {
}
}

//拖拽后改变插件位置
const dragPluginLayout = (from, to, oldIndex, newIndex) => {
if (from === to && oldIndex === newIndex) return

const items = Object.values(pluginStorageReactive.value)
// 记录拖拽项
const movedItem = items.find((item) => item.align === from && item.index === oldIndex)

// 同一列表中的拖拽
if (from === to) {
if (oldIndex < newIndex) {
//往后移动
items.forEach((item) => {
if (item !== movedItem && item.align === from && item.index > oldIndex && item.index <= newIndex) {
item.index -= 1
}
})
} else {
//往前移动
items.forEach((item) => {
if (item !== movedItem && item.align === from && item.index >= newIndex && item.index < oldIndex) {
item.index += 1
}
})
}
} else {
// 跨列表拖拽
items.forEach((item) => {
if (item !== movedItem && item.align === from && item.index > oldIndex) {
item.index -= 1
}
if (item !== movedItem && item.align === to && item.index >= newIndex) {
item.index += 1
}
})
}

// 更新拖拽项的位置
if (movedItem) {
movedItem.align = to
movedItem.index = newIndex
}
}

//判断是否在同一侧
const isSameSide = (from, to) => {
const leftSide = [PLUGIN_POSITION.leftTop, PLUGIN_POSITION.leftBottom]
const rightSide = [PLUGIN_POSITION.rightTop, PLUGIN_POSITION.rightBottom]

const isLeft = leftSide.includes(from) && leftSide.includes(to)
const isRight = rightSide.includes(from) && rightSide.includes(to)

return isLeft || isRight
}

return {
PLUGIN_NAME,
PLUGIN_POSITION,
Expand All @@ -222,6 +282,8 @@ export default () => {
changeRightFixedPanels,
getPluginsByLayout,
changePluginLayout,
getPluginByLayout
getPluginByLayout,
dragPluginLayout,
isSameSide
}
}
1 change: 1 addition & 0 deletions packages/design-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
"prettier": "2.7.1",
"sortablejs": "^1.14.0",
"vue": "3.4.23",
"vue-draggable-next": "2.1.0",
"vue-i18n": "^9.9.0"
},
"devDependencies": {
Expand Down
26 changes: 24 additions & 2 deletions packages/design-core/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,32 @@ export default {
jsClose: null
})

// Step 1: 收集插件的 align 信息
const alignGroups = {}
const pluginList = addons.plugins

pluginList.forEach((item) => {
if (item.id) {
const align = item.options?.align || 'leftTop'
if (!alignGroups[align]) {
alignGroups[align] = []
}
alignGroups[align].push(item.id)
}
})

// Step 2: 为每个插件分配 index 值
const plugin = {}
addons.plugins.forEach((item) => {
pluginList.forEach((item) => {
if (item.id) {
plugin[item.id] = { width: item.options?.width || 300, align: item.options?.align || 'rightTop' }
const align = item.options?.align || 'leftTop'
const index = alignGroups[align].indexOf(item.id)

plugin[item.id] = {
width: item.options?.width || 300,
align: align,
index: index
}
}
})
localStorage.setItem('plugin', JSON.stringify(plugin))
Expand Down
81 changes: 62 additions & 19 deletions packages/design-core/src/DesignPlugins.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@
<div>
<div id="tiny-engine-nav-panel" :style="{ 'pointer-events': pluginState.pluginEvent }">
<!-- 图标菜单上侧区域(主要icon) -->
<ul class="nav-panel-lists top">
<li
<vue-draggable-next
v-model="state.topNavLists"
filter="EditorHelp"
class="nav-panel-lists top"
id="leftTop"
group="plugins"
@end="onEnd"
>
<div
v-for="(item, index) in state.topNavLists"
:key="index"
:class="{
Expand All @@ -26,16 +33,38 @@
<component v-else :is="iconComponents[item.id]" class="panel-icon"></component>
</span>
</div>
</li>
</ul>
</div>
</vue-draggable-next>

<!-- 图标菜单下侧区域(附加icon) -->
<ul class="nav-panel-lists bottom">
<!-- 与上侧间隔 -->
<li style="flex: 1" class="list-item"></li>
<!-- 下侧具体icon插件菜单遍历渲染 -->
<li
v-for="(item, index) in state.bottomNavLists"
<div class="nav-panel-lists bottom">
<div style="flex: 1" class="list-item"></div>
<vue-draggable-next id="leftBottom" v-model="state.bottomNavLists" group="plugins" @end="onEnd">
<div
v-for="(item, index) in state.bottomNavLists"
:key="index"
:class="[
'list-item',
{ active: renderPanel === item.id, prev: state.prevIdex - 1 === index, 'first-item': index === 0 }
]"
:title="item.title"
@click="clickMenu({ item, index })"
>
<div :class="{ 'is-show': renderPanel }">
<span class="item-icon">
<public-icon
v-if="typeof iconComponents[item.id] === 'string'"
:name="iconComponents[item.id]"
class="panel-icon"
svgClass="panel-svg"
></public-icon>
<component v-else :is="iconComponents[item.id]" class="panel-icon"></component>
</span>
</div>
</div>
</vue-draggable-next>
<div
v-for="(item, index) in state.fixedNavLists"
:key="index"
:class="[
'list-item',
Expand All @@ -55,9 +84,8 @@
<component v-else :is="iconComponents[item.id]" class="panel-icon"></component>
</span>
</div>
</li>
<!-- 其他依赖插件菜单(比如AI机器人插件) -->
<li
</div>
<div
v-if="state.independence"
:key="state.bottomNavLists.length + 1"
:class="['list-item']"
Expand All @@ -69,8 +97,8 @@
<img class="chatgpt-icon" src="../assets/AI.png" />
</span>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>

Expand Down Expand Up @@ -111,11 +139,14 @@ import { Popover, Tooltip } from '@opentiny/vue'
import { useLayout, usePage } from '@opentiny/tiny-engine-controller'
import { PublicIcon } from '@opentiny/tiny-engine-common'
import { getPlugin } from '../config/plugin.js'
import { VueDraggableNext } from 'vue-draggable-next'

export default {
components: {
TinyPopover: Popover,
TinyTooltip: Tooltip,
PublicIcon
PublicIcon,
VueDraggableNext
},
props: {
renderPanel: {
Expand All @@ -138,7 +169,9 @@ export default {
changeLeftFixedPanels,
leftFixedPanelsStorage,
getPluginsByLayout,
PLUGIN_POSITION
PLUGIN_POSITION,
dragPluginLayout,
isSameSide
} = useLayout()

const plugins = getPluginsByLayout().map((pluginName) => getPlugin(pluginName))
Expand All @@ -158,7 +191,8 @@ export default {
prevIdex: -2,
topNavLists: getPluginsByLayout(PLUGIN_POSITION.leftTop).map((pluginName) => getPlugin(pluginName)),
bottomNavLists: getPluginsByLayout(PLUGIN_POSITION.leftBottom).map((pluginName) => getPlugin(pluginName)),
independence: getPluginsByLayout(PLUGIN_POSITION.independence).map((pluginName) => getPlugin(pluginName))
independence: getPluginsByLayout(PLUGIN_POSITION.independence).map((pluginName) => getPlugin(pluginName)),
fixedNavLists: getPluginsByLayout(PLUGIN_POSITION.fixed).map((pluginName) => getPlugin(pluginName))
})

const doCompleted = () => {
Expand Down Expand Up @@ -190,6 +224,7 @@ export default {
})
}
}

watch(isTemporaryPage, () => {
if (isTemporaryPage.saved) {
const pagePanel = state.topNavLists?.find((item) => item.id === 'AppManage') || null
Expand All @@ -204,6 +239,7 @@ export default {
robotComponent.value = components.Robot
robotVisible.value = !robotVisible.value
}

const close = () => {
state.prevIdex = -2
useLayout().closePlugin(true)
Expand All @@ -214,6 +250,12 @@ export default {
changeLeftFixedPanels(pluginName)
}

//监听拖拽结束事件
const onEnd = (e) => {
if (!isSameSide(e.from.id, e.to.id)) close()
dragPluginLayout(e.from.id, e.to.id, e.oldIndex, e.newIndex)
}

return {
state,
clickMenu,
Expand All @@ -228,7 +270,8 @@ export default {
completed,
doCompleted,
pluginState,
leftFixedPanelsStorage
leftFixedPanelsStorage,
onEnd
}
}
}
Expand Down
Loading