fix(ui): cap khanegi bottom nav at 4 slots with drag reorder
Merge all versions onto the shared nav sample so extra items cannot stay enabled. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+100
-4
@@ -2,12 +2,14 @@
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { message, Modal } from 'ant-design-vue'
|
||||
import { ArrowRightOutlined } from '@ant-design/icons-vue'
|
||||
import { ArrowRightOutlined, HolderOutlined } from '@ant-design/icons-vue'
|
||||
import api from '@/api/http'
|
||||
import VersionPageTabs from '@/components/VersionPageTabs.vue'
|
||||
import {
|
||||
applyKhanegiNavSample,
|
||||
cloneKhanegiAppSnapshot,
|
||||
createDefaultKhanegiUiConfig,
|
||||
MAX_BOTTOM_NAV_SLOTS,
|
||||
normalizeKhanegiUiConfigForClient,
|
||||
} from '@/config/defaultKhanegiUiConfig'
|
||||
import {
|
||||
@@ -37,6 +39,7 @@ const advancedJson = ref('')
|
||||
const jsonError = ref('')
|
||||
const selectedPreset = ref<KhanegiPresetId>('navy-gold')
|
||||
const previewMode = ref<'dark' | 'light'>('dark')
|
||||
const bottomDragFrom = ref<number | null>(null)
|
||||
|
||||
const config = reactive(createDefaultKhanegiUiConfig()) as ReturnType<
|
||||
typeof createDefaultKhanegiUiConfig
|
||||
@@ -44,6 +47,57 @@ const config = reactive(createDefaultKhanegiUiConfig()) as ReturnType<
|
||||
defaultSnapshot?: ReturnType<typeof cloneKhanegiAppSnapshot>
|
||||
}
|
||||
|
||||
function syncBottomNavOrder() {
|
||||
config.app.navigation.bottom.forEach((item, index) => {
|
||||
item.order = index + 1
|
||||
})
|
||||
}
|
||||
|
||||
function applySharedNavSample() {
|
||||
applyKhanegiNavSample(config.app)
|
||||
if (config.defaultSnapshot?.app) applyKhanegiNavSample(config.defaultSnapshot.app)
|
||||
syncBottomNavOrder()
|
||||
}
|
||||
|
||||
const visibleBottomCount = computed(
|
||||
() => config.app.navigation.bottom.filter((item) => item.visible).length,
|
||||
)
|
||||
|
||||
function onBottomVisibleChange(item: { visible: boolean }, checked: boolean) {
|
||||
if (checked && visibleBottomCount.value >= MAX_BOTTOM_NAV_SLOTS && !item.visible) {
|
||||
message.warning('منوی پایین فقط ۴ جایگاه دارد')
|
||||
return
|
||||
}
|
||||
item.visible = checked
|
||||
}
|
||||
|
||||
function onBottomDragStart(index: number, e: DragEvent) {
|
||||
bottomDragFrom.value = index
|
||||
e.dataTransfer?.setData('text/plain', String(index))
|
||||
if (e.dataTransfer) e.dataTransfer.effectAllowed = 'move'
|
||||
}
|
||||
|
||||
function onBottomDragOver(index: number, e: DragEvent) {
|
||||
e.preventDefault()
|
||||
const from = bottomDragFrom.value
|
||||
if (from == null || from === index) return
|
||||
const list = config.app.navigation.bottom
|
||||
const [moved] = list.splice(from, 1)
|
||||
list.splice(index, 0, moved)
|
||||
bottomDragFrom.value = index
|
||||
syncBottomNavOrder()
|
||||
}
|
||||
|
||||
function onBottomDrop() {
|
||||
bottomDragFrom.value = null
|
||||
syncBottomNavOrder()
|
||||
}
|
||||
|
||||
function onBottomDragEnd() {
|
||||
bottomDragFrom.value = null
|
||||
syncBottomNavOrder()
|
||||
}
|
||||
|
||||
const hasDefaultSnapshot = computed(() => Boolean(config.defaultSnapshot))
|
||||
const isCustom = computed(() => selectedPreset.value === 'custom')
|
||||
|
||||
@@ -129,6 +183,7 @@ function applyAdvancedJson() {
|
||||
if (keepSnapshot && !config.defaultSnapshot) {
|
||||
config.defaultSnapshot = keepSnapshot
|
||||
}
|
||||
applySharedNavSample()
|
||||
ensureSchemes()
|
||||
selectedPreset.value = resolvePresetId(config)
|
||||
jsonError.value = ''
|
||||
@@ -180,6 +235,7 @@ async function load() {
|
||||
Object.assign(config, createDefaultKhanegiUiConfig())
|
||||
}
|
||||
}
|
||||
applySharedNavSample()
|
||||
ensureSchemes()
|
||||
if (!config.defaultSnapshot) {
|
||||
config.defaultSnapshot = cloneKhanegiAppSnapshot(config)
|
||||
@@ -285,6 +341,7 @@ function resetToDefault() {
|
||||
const snap = config.defaultSnapshot!
|
||||
config.app = JSON.parse(JSON.stringify(snap.app))
|
||||
config.pages = JSON.parse(JSON.stringify(snap.pages || {}))
|
||||
applySharedNavSample()
|
||||
ensureSchemes()
|
||||
selectedPreset.value = resolvePresetId(config)
|
||||
previewMode.value = config.app.theme.mode === 'light' ? 'light' : 'dark'
|
||||
@@ -523,8 +580,30 @@ onMounted(load)
|
||||
</section>
|
||||
<section class="form-section">
|
||||
<h3>منوی پایین موبایل</h3>
|
||||
<div v-for="item in config.app.navigation.bottom" :key="item.id" class="nav-row">
|
||||
<a-switch v-model:checked="item.visible" />
|
||||
<p class="page-sub" style="margin-bottom: 12px">
|
||||
۴ جایگاه ثابت — بیشتر در نوار پایین جا نمیشود. با دستگیره، ترتیب را عوض کنید.
|
||||
</p>
|
||||
<div
|
||||
v-for="(item, index) in config.app.navigation.bottom"
|
||||
:key="item.id"
|
||||
class="nav-row"
|
||||
:class="{ 'is-dragging': bottomDragFrom === index }"
|
||||
@dragover.prevent="onBottomDragOver(index, $event)"
|
||||
@drop.prevent="onBottomDrop"
|
||||
>
|
||||
<span
|
||||
class="drag-handle"
|
||||
draggable="true"
|
||||
title="جابهجایی"
|
||||
@dragstart="onBottomDragStart(index, $event)"
|
||||
@dragend="onBottomDragEnd"
|
||||
>
|
||||
<HolderOutlined />
|
||||
</span>
|
||||
<a-switch
|
||||
:checked="item.visible"
|
||||
@change="(v: boolean) => onBottomVisibleChange(item, v)"
|
||||
/>
|
||||
<a-input v-model:value="item.label" />
|
||||
<span class="nav-route" dir="ltr">{{ item.route }}</span>
|
||||
</div>
|
||||
@@ -807,12 +886,29 @@ onMounted(load)
|
||||
|
||||
.nav-row {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
grid-template-columns: auto auto 1fr auto;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.nav-row.is-dragging {
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
.drag-handle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
cursor: grab;
|
||||
color: var(--ink-soft);
|
||||
padding: 4px;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
.drag-handle:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.nav-route {
|
||||
font-size: 12px;
|
||||
color: var(--ink-soft);
|
||||
|
||||
Reference in New Issue
Block a user