|
|
|
|
@ -1,7 +1,6 @@
|
|
|
|
|
<template>
|
|
|
|
|
<view v-if="visible" class="nav-menu-editor-mask" @click="handleClose">
|
|
|
|
|
<view class="nav-menu-editor" @click.stop @touchmove.stop.prevent="handleDragMove" @touchend.stop="handleDragEnd"
|
|
|
|
|
@touchcancel.stop="handleDragEnd">
|
|
|
|
|
<view v-if="renderVisible" class="nav-menu-editor-mask" :class="{ 'mask-hidden': !animVisible }" @click="handleClose">
|
|
|
|
|
<view class="nav-menu-editor" :class="{ 'panel-hidden': !animVisible }" @click.stop>
|
|
|
|
|
<view class="editor-header">
|
|
|
|
|
<text class="editor-title">{{ t('dashboard.editNavMenu') }}</text>
|
|
|
|
|
<view class="editor-close" @click="handleClose">
|
|
|
|
|
@ -12,19 +11,17 @@
|
|
|
|
|
<view class="editor-content">
|
|
|
|
|
<view class="nav-section">
|
|
|
|
|
<text class="nav-section-title">{{ t('dashboard.configuredNav') }}</text>
|
|
|
|
|
<view id="configured-zone" class="nav-grid" :class="{ 'nav-grid-target': isSectionDropTarget('configured') }">
|
|
|
|
|
<view v-for="item in configuredMenuList" :key="item.id" :id="`configured-item-${item.id}`" class="nav-item"
|
|
|
|
|
:class="{
|
|
|
|
|
'is-drop-target': isItemDropTarget('configured', item.id),
|
|
|
|
|
'is-dragging-source': draggingMenu?.id === item.id
|
|
|
|
|
}" @click="handleConfiguredClick(item)"
|
|
|
|
|
@longpress.stop.prevent="handleItemLongPress(item, 'configured', $event)">
|
|
|
|
|
<view class="nav-icon" :style="{ background: hexToRgba(item.accentColor, 0.1) }">
|
|
|
|
|
<uni-icons v-if="isUniIcon(item.icon)" :type="getUniIconName(item.icon)" size="24" :color="item.accentColor" />
|
|
|
|
|
<u-icon v-else-if="isUviewIcon(item.icon)" :name="getUviewIconName(item.icon)" size="24" :color="item.accentColor"></u-icon>
|
|
|
|
|
<view class="nav-grid">
|
|
|
|
|
<view v-for="item in configuredMenuList" :key="item.id" class="nav-item is-selected">
|
|
|
|
|
<view class="nav-icon" :style="{ background: '#e1e6eb' }">
|
|
|
|
|
<uni-icons v-if="isUniIcon(item.icon)" :type="getUniIconName(item.icon)" size="28" :color="item.accentColor" />
|
|
|
|
|
<u-icon v-else-if="isUviewIcon(item.icon)" :name="getUviewIconName(item.icon)" size="28" :color="item.accentColor"></u-icon>
|
|
|
|
|
<text v-else class="nav-icon-text">{{ item.symbol }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<text class="nav-text">{{ item.displayName }}</text>
|
|
|
|
|
<view class="check-badge" @click.stop="handleConfiguredClick(item)">
|
|
|
|
|
<u-icon name="minus-circle-fill" size="18" color="#de3730"></u-icon>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
@ -33,17 +30,12 @@
|
|
|
|
|
|
|
|
|
|
<view class="nav-section">
|
|
|
|
|
<text class="nav-section-title">{{ t('dashboard.unconfiguredNav') }}</text>
|
|
|
|
|
<view id="unconfigured-zone" class="nav-grid"
|
|
|
|
|
:class="{ 'nav-grid-target': isSectionDropTarget('unconfigured') }">
|
|
|
|
|
<view v-for="item in unconfiguredMenuList" :key="item.id" :id="`unconfigured-item-${item.id}`"
|
|
|
|
|
class="nav-item nav-item-disabled" :class="{
|
|
|
|
|
'is-drop-target': isItemDropTarget('unconfigured', item.id),
|
|
|
|
|
'is-dragging-source': draggingMenu?.id === item.id
|
|
|
|
|
}" @click="handleUnconfiguredClick(item)"
|
|
|
|
|
@longpress.stop.prevent="handleItemLongPress(item, 'unconfigured', $event)">
|
|
|
|
|
<view class="nav-icon nav-icon-disabled" :style="{ background: hexToRgba(item.accentColor, 0.1) }">
|
|
|
|
|
<uni-icons v-if="isUniIcon(item.icon)" :type="getUniIconName(item.icon)" size="24" :color="item.accentColor" />
|
|
|
|
|
<u-icon v-else-if="isUviewIcon(item.icon)" :name="getUviewIconName(item.icon)" size="24" :color="item.accentColor"></u-icon>
|
|
|
|
|
<view class="nav-grid">
|
|
|
|
|
<view v-for="item in unconfiguredMenuList" :key="item.id" class="nav-item"
|
|
|
|
|
@click="handleUnconfiguredClick(item)">
|
|
|
|
|
<view class="nav-icon nav-icon-disabled" :style="{ background: '#e1e6eb' }">
|
|
|
|
|
<uni-icons v-if="isUniIcon(item.icon)" :type="getUniIconName(item.icon)" size="28" :color="item.accentColor" />
|
|
|
|
|
<u-icon v-else-if="isUviewIcon(item.icon)" :name="getUviewIconName(item.icon)" size="28" :color="item.accentColor"></u-icon>
|
|
|
|
|
<text v-else class="nav-icon-text">{{ item.symbol }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<text class="nav-text nav-text-disabled">{{ item.displayName }}</text>
|
|
|
|
|
@ -51,8 +43,7 @@
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<text class="click-hint">{{ t('dashboard.dragHint') }}</text>
|
|
|
|
|
<text class="click-hint secondary-hint">{{ t('dashboard.clickHint') }}</text>
|
|
|
|
|
<text class="click-hint">{{ t('dashboard.clickHint') }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="editor-footer">
|
|
|
|
|
@ -63,21 +54,12 @@
|
|
|
|
|
<text>{{ t('common.complete') }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view v-if="draggingMenu" class="drag-ghost" :style="dragGhostStyle">
|
|
|
|
|
<view class="nav-icon" :style="{ background: hexToRgba(draggingMenu.accentColor, 0.1) }">
|
|
|
|
|
<uni-icons v-if="isUniIcon(draggingMenu.icon)" :type="getUniIconName(draggingMenu.icon)" size="24" :color="draggingMenu.accentColor" />
|
|
|
|
|
<u-icon v-else-if="isUviewIcon(draggingMenu.icon)" :name="getUviewIconName(draggingMenu.icon)" size="24" :color="draggingMenu.accentColor"></u-icon>
|
|
|
|
|
<text v-else class="nav-icon-text">{{ draggingMenu.symbol }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<text class="nav-text">{{ draggingMenu.displayName }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import { ref, computed, watch, nextTick, getCurrentInstance } from 'vue'
|
|
|
|
|
import { ref, computed, watch, nextTick } from 'vue'
|
|
|
|
|
import { useI18n } from 'vue-i18n'
|
|
|
|
|
import useUserStore from '@/store/modules/user'
|
|
|
|
|
import { getUserNavMenuList, updateUserNavMenuList } from '@/api/system/userNavMenu'
|
|
|
|
|
@ -86,18 +68,6 @@ import { buildNavMenuViewModels } from '@/utils/permissionMenu'
|
|
|
|
|
|
|
|
|
|
const { t } = useI18n()
|
|
|
|
|
const userStore = useUserStore()
|
|
|
|
|
const instance = getCurrentInstance()
|
|
|
|
|
|
|
|
|
|
function hexToRgba(hex, alpha) {
|
|
|
|
|
const value = String(hex || '').replace('#', '')
|
|
|
|
|
if (value.length !== 6) {
|
|
|
|
|
return `rgba(45, 90, 135, ${alpha})`
|
|
|
|
|
}
|
|
|
|
|
const red = parseInt(value.slice(0, 2), 16)
|
|
|
|
|
const green = parseInt(value.slice(2, 4), 16)
|
|
|
|
|
const blue = parseInt(value.slice(4, 6), 16)
|
|
|
|
|
return `rgba(${red}, ${green}, ${blue}, ${alpha})`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isUniIcon(icon) {
|
|
|
|
|
return String(icon || '').startsWith('uni-icons:')
|
|
|
|
|
@ -124,14 +94,25 @@ const props = defineProps({
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits(['close', 'update'])
|
|
|
|
|
|
|
|
|
|
const renderVisible = ref(false)
|
|
|
|
|
const animVisible = ref(false)
|
|
|
|
|
|
|
|
|
|
watch(() => props.visible, (val) => {
|
|
|
|
|
if (val) {
|
|
|
|
|
renderVisible.value = true
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
setTimeout(() => { animVisible.value = true }, 30)
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
animVisible.value = false
|
|
|
|
|
setTimeout(() => { renderVisible.value = false }, 300)
|
|
|
|
|
}
|
|
|
|
|
}, { immediate: true })
|
|
|
|
|
|
|
|
|
|
const userMenuList = ref([])
|
|
|
|
|
const configuredRecords = ref([])
|
|
|
|
|
const originConfIds = ref([])
|
|
|
|
|
const configuredIds = ref([])
|
|
|
|
|
const dragTargets = ref([])
|
|
|
|
|
const dropTarget = ref(null)
|
|
|
|
|
const draggingState = ref(null)
|
|
|
|
|
const lastDragEndAt = ref(0)
|
|
|
|
|
|
|
|
|
|
const menuMap = computed(() => {
|
|
|
|
|
const map = {}
|
|
|
|
|
@ -141,24 +122,6 @@ const menuMap = computed(() => {
|
|
|
|
|
return map
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const draggingMenu = computed(() => {
|
|
|
|
|
if (!draggingState.value) {
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
return menuMap.value[draggingState.value.id] || null
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const dragGhostStyle = computed(() => {
|
|
|
|
|
if (!draggingState.value) {
|
|
|
|
|
return {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
left: `${draggingState.value.x - 48}px`,
|
|
|
|
|
top: `${draggingState.value.y - 48}px`
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const configuredMenuList = computed(() => {
|
|
|
|
|
return configuredIds.value
|
|
|
|
|
.map(id => menuMap.value[id])
|
|
|
|
|
@ -183,24 +146,16 @@ async function loadData() {
|
|
|
|
|
.filter(menuId => !!menuMap.value[menuId])
|
|
|
|
|
|
|
|
|
|
originConfIds.value = [...configuredIds.value]
|
|
|
|
|
await nextTick()
|
|
|
|
|
collectDropTargets()
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('加载菜单数据失败:', error)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleConfiguredClick(item) {
|
|
|
|
|
if (shouldIgnoreClick()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
configuredIds.value = configuredIds.value.filter(id => id !== item.id)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleUnconfiguredClick(item) {
|
|
|
|
|
if (shouldIgnoreClick()) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (!configuredIds.value.includes(item.id)) {
|
|
|
|
|
configuredIds.value.push(item.id)
|
|
|
|
|
}
|
|
|
|
|
@ -232,217 +187,13 @@ async function handleConfirm() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleClose() {
|
|
|
|
|
resetDragState()
|
|
|
|
|
emit('close')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function shouldIgnoreClick() {
|
|
|
|
|
return Date.now() - lastDragEndAt.value < 300
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getTouchPoint(event) {
|
|
|
|
|
const touch = event?.changedTouches?.[0] || event?.touches?.[0]
|
|
|
|
|
if (touch) {
|
|
|
|
|
return {
|
|
|
|
|
x: touch.clientX ?? touch.pageX ?? 0,
|
|
|
|
|
y: touch.clientY ?? touch.pageY ?? 0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (typeof event?.detail?.x === 'number' && typeof event?.detail?.y === 'number') {
|
|
|
|
|
return {
|
|
|
|
|
x: event.detail.x,
|
|
|
|
|
y: event.detail.y
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function collectDropTargets() {
|
|
|
|
|
if (!instance?.proxy) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const selectors = [
|
|
|
|
|
{ selector: '#configured-zone', kind: 'section', section: 'configured' },
|
|
|
|
|
{ selector: '#unconfigured-zone', kind: 'section', section: 'unconfigured' }
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
configuredMenuList.value.forEach((item) => {
|
|
|
|
|
selectors.push({
|
|
|
|
|
selector: `#configured-item-${item.id}`,
|
|
|
|
|
kind: 'item',
|
|
|
|
|
section: 'configured',
|
|
|
|
|
id: item.id
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
unconfiguredMenuList.value.forEach((item) => {
|
|
|
|
|
selectors.push({
|
|
|
|
|
selector: `#unconfigured-item-${item.id}`,
|
|
|
|
|
kind: 'item',
|
|
|
|
|
section: 'unconfigured',
|
|
|
|
|
id: item.id
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const query = uni.createSelectorQuery().in(instance.proxy)
|
|
|
|
|
selectors.forEach((item) => {
|
|
|
|
|
query.select(item.selector).boundingClientRect()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
query.exec((rects = []) => {
|
|
|
|
|
dragTargets.value = rects
|
|
|
|
|
.map((rect, index) => {
|
|
|
|
|
if (!rect) {
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
...selectors[index],
|
|
|
|
|
...rect
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.filter(Boolean)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateDropTarget(point) {
|
|
|
|
|
const itemTarget = dragTargets.value.find((item) => {
|
|
|
|
|
return item.kind === 'item'
|
|
|
|
|
&& point.x >= item.left
|
|
|
|
|
&& point.x <= item.right
|
|
|
|
|
&& point.y >= item.top
|
|
|
|
|
&& point.y <= item.bottom
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if (itemTarget) {
|
|
|
|
|
dropTarget.value = {
|
|
|
|
|
section: itemTarget.section,
|
|
|
|
|
id: itemTarget.id,
|
|
|
|
|
position: point.y < itemTarget.top + itemTarget.height / 2 ? 'before' : 'after'
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const sectionTarget = dragTargets.value.find((item) => {
|
|
|
|
|
return item.kind === 'section'
|
|
|
|
|
&& point.x >= item.left
|
|
|
|
|
&& point.x <= item.right
|
|
|
|
|
&& point.y >= item.top
|
|
|
|
|
&& point.y <= item.bottom
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
dropTarget.value = sectionTarget
|
|
|
|
|
? { section: sectionTarget.section, id: null, position: 'end' }
|
|
|
|
|
: null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleItemLongPress(item, section, event) {
|
|
|
|
|
const point = getTouchPoint(event) || { x: 0, y: 0 }
|
|
|
|
|
draggingState.value = {
|
|
|
|
|
id: item.id,
|
|
|
|
|
section,
|
|
|
|
|
x: point.x,
|
|
|
|
|
y: point.y
|
|
|
|
|
}
|
|
|
|
|
dropTarget.value = {
|
|
|
|
|
section,
|
|
|
|
|
id: item.id,
|
|
|
|
|
position: 'after'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await nextTick()
|
|
|
|
|
collectDropTargets()
|
|
|
|
|
updateDropTarget(point)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleDragMove(event) {
|
|
|
|
|
if (!draggingState.value) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const point = getTouchPoint(event)
|
|
|
|
|
if (!point) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
draggingState.value = {
|
|
|
|
|
...draggingState.value,
|
|
|
|
|
x: point.x,
|
|
|
|
|
y: point.y
|
|
|
|
|
}
|
|
|
|
|
updateDropTarget(point)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function applyDrop() {
|
|
|
|
|
if (!draggingState.value || !dropTarget.value) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dropTarget.value.section === 'unconfigured') {
|
|
|
|
|
configuredIds.value = configuredIds.value.filter(id => id !== draggingState.value.id)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dropTarget.value.section !== 'configured') {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const nextIds = configuredIds.value.filter(id => id !== draggingState.value.id)
|
|
|
|
|
let insertIndex = nextIds.length
|
|
|
|
|
|
|
|
|
|
if (dropTarget.value.id != null) {
|
|
|
|
|
const targetIndex = nextIds.indexOf(dropTarget.value.id)
|
|
|
|
|
if (targetIndex !== -1) {
|
|
|
|
|
insertIndex = dropTarget.value.position === 'before' ? targetIndex : targetIndex + 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nextIds.splice(insertIndex, 0, draggingState.value.id)
|
|
|
|
|
configuredIds.value = nextIds
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleDragEnd() {
|
|
|
|
|
if (!draggingState.value) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyDrop()
|
|
|
|
|
lastDragEndAt.value = Date.now()
|
|
|
|
|
resetDragState()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function resetDragState() {
|
|
|
|
|
dropTarget.value = null
|
|
|
|
|
draggingState.value = null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isItemDropTarget(section, itemId) {
|
|
|
|
|
return dropTarget.value?.section === section && dropTarget.value?.id === itemId
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isSectionDropTarget(section) {
|
|
|
|
|
return dropTarget.value?.section === section && dropTarget.value?.id == null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
watch(() => props.visible, async (val) => {
|
|
|
|
|
if (val) {
|
|
|
|
|
await loadData()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resetDragState()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
watch([configuredMenuList, unconfiguredMenuList], async () => {
|
|
|
|
|
if (!props.visible) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await nextTick()
|
|
|
|
|
collectDropTargets()
|
|
|
|
|
})
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
@ -459,15 +210,25 @@ watch([configuredMenuList, unconfiguredMenuList], async () => {
|
|
|
|
|
align-items: flex-end;
|
|
|
|
|
padding-bottom: calc(100rpx + env(safe-area-inset-bottom));
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
transition: opacity 0.3s ease;
|
|
|
|
|
|
|
|
|
|
&.mask-hidden {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.nav-menu-editor {
|
|
|
|
|
width: 100%;
|
|
|
|
|
max-height: 66.6vh;
|
|
|
|
|
max-height: 75vh;
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
border-radius: 32rpx 32rpx 0 0;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
transition: transform 0.3s ease;
|
|
|
|
|
|
|
|
|
|
&.panel-hidden {
|
|
|
|
|
transform: translateY(100%);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.editor-header {
|
|
|
|
|
@ -516,11 +277,6 @@ watch([configuredMenuList, unconfiguredMenuList], async () => {
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
min-height: 120rpx;
|
|
|
|
|
border-radius: 24rpx;
|
|
|
|
|
transition: background-color 0.15s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.nav-grid-target {
|
|
|
|
|
background: rgba(34, 72, 110, 0.06);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.nav-item {
|
|
|
|
|
@ -531,23 +287,12 @@ watch([configuredMenuList, unconfiguredMenuList], async () => {
|
|
|
|
|
margin-bottom: 24rpx;
|
|
|
|
|
padding: 16rpx;
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
position: relative;
|
|
|
|
|
transition: all 0.15s;
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
opacity: 0.7;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&.nav-item-disabled {
|
|
|
|
|
opacity: 0.72;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.is-drop-target {
|
|
|
|
|
background: rgba(34, 72, 110, 0.08);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.is-dragging-source {
|
|
|
|
|
opacity: 0.25;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.nav-icon {
|
|
|
|
|
@ -559,12 +304,8 @@ watch([configuredMenuList, unconfiguredMenuList], async () => {
|
|
|
|
|
justify-content: center;
|
|
|
|
|
margin-bottom: 12rpx;
|
|
|
|
|
|
|
|
|
|
&.nav-icon-disabled {
|
|
|
|
|
opacity: 0.55;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.nav-icon-text {
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
color: #1a3a5c;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
}
|
|
|
|
|
@ -580,15 +321,24 @@ watch([configuredMenuList, unconfiguredMenuList], async () => {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.check-badge {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 8rpx;
|
|
|
|
|
right: 26rpx;
|
|
|
|
|
width: 32rpx;
|
|
|
|
|
height: 32rpx;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.click-hint {
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
color: #999;
|
|
|
|
|
text-align: center;
|
|
|
|
|
display: block;
|
|
|
|
|
margin-top: 16rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.secondary-hint {
|
|
|
|
|
padding-bottom: 24rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -620,15 +370,4 @@ watch([configuredMenuList, unconfiguredMenuList], async () => {
|
|
|
|
|
background: #22486e;
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.drag-ghost {
|
|
|
|
|
position: fixed;
|
|
|
|
|
z-index: 1002;
|
|
|
|
|
width: 96rpx;
|
|
|
|
|
margin-left: -8rpx;
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
</style>
|