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:
kate522andClaude Fable 5 committed 2026-10-28 13:41:26 +08:00
1 parent 135fb4eaa4
commit 8843ae4261
20 files changed
+1442 -1796

No files matched your search

@@ -19,20 +19,23 @@
<draggable
v-else
v-model="rows"
v-bind="SORTABLE_LIST_ATTRS"
item-key="id"
handle=".aksrt-ticket-prereply__handle"
:animation="160"
class="aksrt-ticket-prereply"
class="aksrt-sortable"
>
<template #item="{ element, index }">
<div class="aksrt-ticket-prereply__row">
<span class="aksrt-ticket-prereply__handle" title="拖动排序">⋮⋮</span>
<span class="aksrt-ticket-prereply__index">{{ index + 1 }}</span>
<span class="aksrt-ticket-prereply__content">{{ element.content }}</span>
<n-space size="small">
<n-button size="tiny" type="primary" quaternary @click="openEdit(element)">编辑</n-button>
<n-button size="tiny" type="error" quaternary @click="handleDelete(element)">删除</n-button>
</n-space>
<div class="aksrt-sortable__item">
<div class="aksrt-sortable__head">
<AksSortHandle />
<span class="aksrt-sortable__index">{{ index + 1 }}</span>
<div class="aksrt-sortable__main">
<span class="aksrt-ticket-prereply__content">{{ element.content }}</span>
</div>
<div class="aksrt-sortable__actions">
<n-button size="tiny" type="primary" quaternary @click="openEdit(element)">编辑</n-button>
<n-button size="tiny" type="error" quaternary @click="handleDelete(element)">删除</n-button>
</div>
</div>
</div>
</template>
</draggable>
@@ -71,6 +74,8 @@ import { computed, onMounted, ref } from 'vue'
import { NButton, NSpace, useDialog, useMessage } from 'naive-ui'
import draggable from 'vuedraggable'
import api from '@/api'
import AksSortHandle from '@/components/form/AksSortHandle.vue'
import { SORTABLE_LIST_ATTRS } from '@/components/form/sortable-options.js'
const message = useMessage()
const dialog = useDialog()
@@ -188,38 +193,11 @@ defineExpose({ reload: load })
</script>
<style scoped>
.aksrt-ticket-prereply {
display: grid;
gap: 8px;
}
.aksrt-ticket-prereply__row {
display: grid;
grid-template-columns: 20px 28px 1fr auto;
align-items: center;
gap: 10px;
padding: 10px 12px;
border: 1px var(--n-border-color, #efeff5) solid;
border-radius: 8px;
background: var(--n-color, #fff);
}
.aksrt-ticket-prereply__handle {
color: var(--aksrt-color-muted);
cursor: grab;
user-select: none;
}
.aksrt-ticket-prereply__index {
color: var(--aksrt-color-muted);
font-size: 12px;
font-variant-numeric: tabular-nums;
}
.aksrt-ticket-prereply__content {
white-space: pre-wrap;
word-break: break-word;
color: var(--aksrt-color-text, #1F2923);
font-size: 13px;
line-height: 1.6;
white-space: pre-wrap;
word-break: break-word;
}
</style>