Phase 007: migrate every remaining view from naive-ui to Arco Design Vue
The project now has exactly one UI library. Every naive-ui component in
packages/client/src is replaced by its Arco equivalent across 24 views and
roughly 80 components, and naive-ui is dropped from package.json along with
its transitive vueuc / @css-render / vdirs / seemly dependencies.
The migration is rendering-layer only. No store logic, no API contract, and
no /chat-run payload was touched.
Three classes of leftover were invisible to `grep naive-ui` and are now
covered by tests/client/no-naive-ui.test.ts, which asserts all three:
- dead .n-* class names in style blocks
- dead --n-* custom properties
- naive-ui in package.json
Notable behavioural traps handled along the way, recorded in
docs/arco-migration-rules.md:
- a-input-password defaults to masked; passing default-visibility="false"
would have exposed API keys in clear text
- a-upload fires a real XHR unless auto-upload is false
- nested Trigger components fight over the first element child, so the
group-chat settings dropdown was flattened
- Arco renders tooltip default-slot text inline, which was silently
collapsing the chat and group-chat toolbars
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { NButton } from 'naive-ui'
|
||||
import { useMessage } from '@/composables/useMessage'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import MarkdownRenderer from '@/components/hermes/chat/MarkdownRenderer.vue'
|
||||
@@ -82,7 +81,7 @@ const displaySoul = computed(() => (data.value?.soul || '').replace(/§/g, '\n\n
|
||||
<div class="memory-view">
|
||||
<header class="page-header">
|
||||
<h2 class="header-title">{{ t('memory.title') }}</h2>
|
||||
<NButton size="small" quaternary @click="loadMemory">
|
||||
<a-button size="small" type="text" @click="loadMemory">
|
||||
<template #icon>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="23 4 23 10 17 10" />
|
||||
@@ -90,7 +89,7 @@ const displaySoul = computed(() => (data.value?.soul || '').replace(/§/g, '\n\n
|
||||
</svg>
|
||||
</template>
|
||||
{{ t('memory.refresh') }}
|
||||
</NButton>
|
||||
</a-button>
|
||||
</header>
|
||||
|
||||
<div class="memory-content">
|
||||
@@ -111,7 +110,7 @@ const displaySoul = computed(() => (data.value?.soul || '').replace(/§/g, '\n\n
|
||||
<span class="section-title">{{ t('memory.myNotes') }}</span>
|
||||
<span v-if="data?.memory_mtime" class="section-mtime">{{ formatTime(data.memory_mtime) }}</span>
|
||||
</div>
|
||||
<NButton v-if="editingSection !== 'memory'" size="tiny" quaternary @click="startEdit('memory')">
|
||||
<a-button v-if="editingSection !== 'memory'" size="mini" type="text" @click="startEdit('memory')">
|
||||
<template #icon>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
|
||||
@@ -119,7 +118,7 @@ const displaySoul = computed(() => (data.value?.soul || '').replace(/§/g, '\n\n
|
||||
</svg>
|
||||
</template>
|
||||
{{ t('common.edit') }}
|
||||
</NButton>
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<!-- View mode -->
|
||||
@@ -137,8 +136,8 @@ const displaySoul = computed(() => (data.value?.soul || '').replace(/§/g, '\n\n
|
||||
spellcheck="false"
|
||||
></textarea>
|
||||
<div class="edit-actions">
|
||||
<NButton size="small" @click="cancelEdit">{{ t('common.cancel') }}</NButton>
|
||||
<NButton size="small" type="primary" :loading="saving" @click="handleSave">{{ t('common.save') }}</NButton>
|
||||
<a-button size="small" @click="cancelEdit">{{ t('common.cancel') }}</a-button>
|
||||
<a-button size="small" type="primary" :loading="saving" @click="handleSave">{{ t('common.save') }}</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -156,7 +155,7 @@ const displaySoul = computed(() => (data.value?.soul || '').replace(/§/g, '\n\n
|
||||
<span class="section-title">{{ t('memory.userProfile') }}</span>
|
||||
<span v-if="data?.user_mtime" class="section-mtime">{{ formatTime(data.user_mtime) }}</span>
|
||||
</div>
|
||||
<NButton v-if="editingSection !== 'user'" size="tiny" quaternary @click="startEdit('user')">
|
||||
<a-button v-if="editingSection !== 'user'" size="mini" type="text" @click="startEdit('user')">
|
||||
<template #icon>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
|
||||
@@ -164,7 +163,7 @@ const displaySoul = computed(() => (data.value?.soul || '').replace(/§/g, '\n\n
|
||||
</svg>
|
||||
</template>
|
||||
{{ t('common.edit') }}
|
||||
</NButton>
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<!-- View mode -->
|
||||
@@ -182,8 +181,8 @@ const displaySoul = computed(() => (data.value?.soul || '').replace(/§/g, '\n\n
|
||||
spellcheck="false"
|
||||
></textarea>
|
||||
<div class="edit-actions">
|
||||
<NButton size="small" @click="cancelEdit">{{ t('common.cancel') }}</NButton>
|
||||
<NButton size="small" type="primary" :loading="saving" @click="handleSave">{{ t('common.save') }}</NButton>
|
||||
<a-button size="small" @click="cancelEdit">{{ t('common.cancel') }}</a-button>
|
||||
<a-button size="small" type="primary" :loading="saving" @click="handleSave">{{ t('common.save') }}</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -203,7 +202,7 @@ const displaySoul = computed(() => (data.value?.soul || '').replace(/§/g, '\n\n
|
||||
<span class="section-title">{{ t('memory.soul') }}</span>
|
||||
<span v-if="data?.soul_mtime" class="section-mtime">{{ formatTime(data.soul_mtime) }}</span>
|
||||
</div>
|
||||
<NButton v-if="editingSection !== 'soul'" size="tiny" quaternary @click="startEdit('soul')">
|
||||
<a-button v-if="editingSection !== 'soul'" size="mini" type="text" @click="startEdit('soul')">
|
||||
<template #icon>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
|
||||
@@ -211,7 +210,7 @@ const displaySoul = computed(() => (data.value?.soul || '').replace(/§/g, '\n\n
|
||||
</svg>
|
||||
</template>
|
||||
{{ t('common.edit') }}
|
||||
</NButton>
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<!-- View mode -->
|
||||
@@ -229,8 +228,8 @@ const displaySoul = computed(() => (data.value?.soul || '').replace(/§/g, '\n\n
|
||||
spellcheck="false"
|
||||
></textarea>
|
||||
<div class="edit-actions">
|
||||
<NButton size="small" @click="cancelEdit">{{ t('common.cancel') }}</NButton>
|
||||
<NButton size="small" type="primary" :loading="saving" @click="handleSave">{{ t('common.save') }}</NButton>
|
||||
<a-button size="small" @click="cancelEdit">{{ t('common.cancel') }}</a-button>
|
||||
<a-button size="small" type="primary" :loading="saving" @click="handleSave">{{ t('common.save') }}</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user