refactor(admin): unify sortable/draggable/repeater list UI
- Add shared sortable-list.css, SORTABLE_LIST_ATTRS and AksSortHandle - Migrate schema sortable, selected order, inline/modal repeater, sorter, floating buttons, footer tabbar and ticket prereply lists to the shared design - Split AksField.vue (1885 -> 969 lines) into focused components/helpers - Remove dead AksArrayTable/AksRepeaterField and move-up/down helpers - Replace hardcoded colors and --n-* vars with --aksrt-color-* tokens Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
135fb4eaa4
commit
8843ae4261
20 files changed
+1442
-1796
No files matched your search
@@ -1,23 +1,29 @@
|
||||
<template>
|
||||
<div class="float-btn-panel">
|
||||
<div class="float-btn-panel__head" @click="expanded = !expanded">
|
||||
<button type="button" class="float-btn-panel__handle" aria-label="拖拽排序" @click.stop>
|
||||
<i class="fa fas fa-arrows-alt-v" />
|
||||
</button>
|
||||
<strong class="float-btn-panel__title">{{ meta.title }}</strong>
|
||||
<template v-if="modelValue.type !== 'more'">
|
||||
<n-tag v-if="modelValue.pc_s" size="small" type="info" :bordered="false">PC</n-tag>
|
||||
<n-tag v-if="modelValue.m_s" size="small" type="warning" :bordered="false">移动</n-tag>
|
||||
<n-tag v-if="!modelValue.pc_s && !modelValue.m_s" size="small" :bordered="false">未显示</n-tag>
|
||||
</template>
|
||||
<n-tag v-else size="small" :bordered="false">{{ modelValue.buttons.length }} 个</n-tag>
|
||||
<span v-if="meta.warn" class="float-btn-panel__warn">
|
||||
<i class="fa fas fa-info-circle" /> {{ meta.warn }}
|
||||
</span>
|
||||
<i class="fa fas float-btn-panel__arrow" :class="expanded ? 'fa-angle-up' : 'fa-angle-down'" />
|
||||
<div class="aksrt-sortable__head is-clickable" @click="expanded = !expanded">
|
||||
<AksSortHandle @click.stop />
|
||||
<div class="aksrt-sortable__main">
|
||||
<div class="aksrt-sortable__title-row">
|
||||
<span class="aksrt-sortable__title">{{ meta.title }}</span>
|
||||
<template v-if="modelValue.type !== 'more'">
|
||||
<n-tag v-if="modelValue.pc_s" size="small" type="info" :bordered="false">PC</n-tag>
|
||||
<n-tag v-if="modelValue.m_s" size="small" type="warning" :bordered="false">移动</n-tag>
|
||||
<n-tag v-if="!modelValue.pc_s && !modelValue.m_s" size="small" :bordered="false">未显示</n-tag>
|
||||
</template>
|
||||
<n-tag v-else size="small" :bordered="false">{{ modelValue.buttons.length }} 个</n-tag>
|
||||
</div>
|
||||
<span v-if="meta.warn" class="aksrt-sortable__desc float-btn-panel__warn">
|
||||
<i class="fa fas fa-info-circle" aria-hidden="true" /> {{ meta.warn }}
|
||||
</span>
|
||||
</div>
|
||||
<i
|
||||
class="fa fas aksrt-sortable__toggle"
|
||||
:class="expanded ? 'fa-chevron-down' : 'fa-chevron-right'"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-show="expanded" class="float-btn-panel__body">
|
||||
<div v-show="expanded" class="aksrt-sortable__body">
|
||||
<div class="float-btn-panel__subtitle">{{ meta.panel }}</div>
|
||||
|
||||
<FloatMoreButtonsEditor
|
||||
@@ -56,9 +62,11 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
/** 悬浮按钮排序列表中的单个卡片;外层 .aksrt-sortable__item 由 FloatingButtonsSettings 提供。 */
|
||||
import { computed, ref } from 'vue'
|
||||
import FaIconPicker from '@/components/form/FaIconPicker.vue'
|
||||
import AksMediaField from '@/components/form/AksMediaField.vue'
|
||||
import AksSortHandle from '@/components/form/AksSortHandle.vue'
|
||||
import FloatBtnCommonFields from './FloatBtnCommonFields.vue'
|
||||
import FloatMoreButtonsEditor from './FloatMoreButtonsEditor.vue'
|
||||
import { FLOAT_BTN_META } from './floating-defaults.js'
|
||||
@@ -82,76 +90,18 @@ function patch(partial) {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.float-btn-panel {
|
||||
border: 1px solid var(--n-border-color, rgba(0, 0, 0, 0.09));
|
||||
border-radius: 8px;
|
||||
background: var(--n-card-color, #fff);
|
||||
}
|
||||
|
||||
.float-btn-panel__head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 10px 14px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.float-btn-panel__handle {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: var(--n-text-color-3, #999);
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.float-btn-panel__handle:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.float-btn-panel__title {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.float-btn-panel__arrow {
|
||||
margin-left: auto;
|
||||
color: var(--n-text-color-3, #999);
|
||||
}
|
||||
|
||||
.float-btn-panel__warn {
|
||||
font-size: 12px;
|
||||
color: #f0a020;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.float-btn-panel__body {
|
||||
padding: 12px 16px 16px;
|
||||
border-top: 1px solid var(--n-border-color, rgba(0, 0, 0, 0.09));
|
||||
color: var(--aksrt-color-warning, #D97706);
|
||||
}
|
||||
|
||||
.float-btn-panel__subtitle {
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
margin-bottom: 12px;
|
||||
color: var(--aksrt-color-text);
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.float-btn-panel__extra {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.float-btn-panel__block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.float-btn-panel__desc {
|
||||
font-size: 12px;
|
||||
color: var(--n-text-color-3, #999);
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user