feat(models): add shared searchable base model picker and overhaul bulk base model modal

- Extract a shared BaseModelPicker (search, keyboard navigation,
  filename-based suggestions, dynamic API models such as MiniMax H3
  under 'Other (API)') used by both the single-model metadata modal
  and the bulk base model modal
- Rework the bulk base model modal into a dedicated inline-list
  layout: fixed modal size, sticky-free footer with app-standard
  modal-actions/primary-btn/cancel-btn buttons, and an inline option
  list that scrolls itself instead of an overlay dropdown covering
  the footer
- Selecting an option in change mode now filters the list to the
  selection instead of resetting and scroll-jumping to it
- Restore opaque sticky section headers in the bulk modal so scrolled
  items no longer bleed through
This commit is contained in:
Will Miao
2026-08-27 18:07:28 +08:00
parent df34efafbc
commit 2bfb987312
9 changed files with 1228 additions and 382 deletions
@@ -1,5 +1,5 @@
<div id="bulkBaseModelModal" class="modal" style="display: none;">
<div class="modal-content modal-content">
<div class="modal-content">
<div class="modal-header">
<h2>{{ t('modals.bulkBaseModel.title') }}</h2>
<span class="close" onclick="modalManager.closeModal('bulkBaseModelModal')">&times;</span>
@@ -8,31 +8,18 @@
<div class="bulk-add-tags-info">
<p>{{ t('modals.bulkBaseModel.description') }} <span id="bulkBaseModelCount">0</span> {{ t('modals.bulkBaseModel.models') }}</p>
</div>
<div class="model-tags-container bulk-tags-container edit-mode">
<div class="metadata-edit-container" style="display: block;">
<div class="metadata-edit-content">
<div class="metadata-edit-header">
<label>{{ t('modals.bulkBaseModel.selectBaseModel') }}</label>
</div>
<div class="setting-control">
<div class="select-control">
<select id="bulkBaseModelSelect" class="bulk-base-model-select">
<!-- Options will be populated dynamically -->
</select>
</div>
</div>
<div class="metadata-edit-controls">
<button class="metadata-save-btn bulk-save-base-model-btn" onclick="bulkManager.saveBulkBaseModel()">
<i class="fas fa-save"></i> {{ t('modals.bulkBaseModel.save') }}
</button>
<button class="btn btn-secondary" onclick="modalManager.closeModal('bulkBaseModelModal')">
{{ t('modals.bulkBaseModel.cancel') }}
</button>
</div>
</div>
</div>
<label class="bulk-base-model-label">{{ t('modals.bulkBaseModel.selectBaseModel') }}</label>
<div id="bulkBaseModelPicker" class="bulk-base-model-picker">
<!-- Picker will be initialized dynamically -->
</div>
</div>
<div class="modal-actions bulk-base-model-footer">
<button class="cancel-btn" onclick="modalManager.closeModal('bulkBaseModelModal')">
{{ t('modals.bulkBaseModel.cancel') }}
</button>
<button class="primary-btn bulk-save-base-model-btn" onclick="bulkManager.saveBulkBaseModel()">
<i class="fas fa-save"></i> {{ t('modals.bulkBaseModel.save') }}
</button>
</div>
</div>
</div>