feat: add support for dynamic slider range configuration in UI and settings
This commit is contained in:
+98
-48
@@ -336,14 +336,14 @@
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<!-- 進階係數關聯調整 (X = a1 - a2) -->
|
||||
<!-- 進階 a1/a2 微調 -->
|
||||
<div class="mt-4">
|
||||
<button v-if="!showAdvancedAdjustment" @click="enableAdvancedAdjustment"
|
||||
class="w-full py-3 border-2 border-dashed border-slate-200 dark:border-gray-800 rounded-xl text-slate-400 dark:text-gray-500 text-xs font-bold hover:bg-slate-50 dark:hover:bg-gray-800/50 hover:border-indigo-300 dark:hover:border-indigo-900 transition-all flex items-center justify-center gap-2">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4"></path>
|
||||
</svg>
|
||||
開啟進階係數關聯調整 (a1, a2)
|
||||
開啟 a1/a2 步階微調
|
||||
</button>
|
||||
|
||||
<div v-if="showAdvancedAdjustment" class="p-4 bg-slate-50 dark:bg-gray-900 border border-slate-200 dark:border-gray-800 rounded-xl shadow-inner">
|
||||
@@ -351,47 +351,77 @@
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
|
||||
</svg>
|
||||
進階係數關聯調整
|
||||
a1/a2 步階微調
|
||||
</h3>
|
||||
|
||||
<!-- 差距調整 (X) -->
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="text-[11px] font-semibold text-slate-400 dark:text-gray-500 flex justify-between mb-2">
|
||||
<span>差距 (a1 - a2)</span>
|
||||
<span class="text-indigo-600 dark:text-indigo-400 font-mono bg-indigo-50 dark:bg-indigo-900/30 px-2 py-0.5 rounded">{{ a1a2Diff.toFixed(3) }}</span>
|
||||
</label>
|
||||
<input type="range" v-model.number="a1a2Diff" min="-4" max="4" step="0.001"
|
||||
@input="updateA1A2FromRelationship"
|
||||
class="w-full accent-indigo-500 h-1.5 bg-slate-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer">
|
||||
<div class="text-[11px] font-semibold text-slate-400 dark:text-gray-500 mb-2">
|
||||
{{ isTouchInput ? '觸控拖曳微調' : '直接輸入 / 滾動微調' }}
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<label v-if="!isTouchInput" class="block">
|
||||
<span class="text-[9px] text-slate-400 block uppercase font-bold mb-1">a1</span>
|
||||
<input type="number" :value="formatFineCoeff(currentA1)" step="0.001"
|
||||
@change="setAFineDirect(1, $event.target.value)" @keydown="onlyNumberKey"
|
||||
@wheel.prevent="handleAFineWheel(1, $event)"
|
||||
class="w-full bg-white dark:bg-gray-800 border border-slate-200 dark:border-gray-700 rounded-lg p-3 text-sm font-mono text-center text-indigo-700 dark:text-indigo-300">
|
||||
</label>
|
||||
<button v-else type="button" @pointerdown.prevent="startAFineDrag(1, $event)"
|
||||
class="touch-none select-none w-28 mx-auto bg-white dark:bg-gray-800 border border-slate-200 dark:border-gray-700 rounded-lg p-3 text-center active:border-indigo-400 active:ring-2 active:ring-indigo-400/20">
|
||||
<span class="text-[9px] text-slate-400 block uppercase font-bold mb-1">a1</span>
|
||||
<span class="text-lg font-mono font-bold text-indigo-700 dark:text-indigo-300">{{ formatFineCoeff(currentA1) }}</span>
|
||||
</button>
|
||||
<label v-if="!isTouchInput" class="block">
|
||||
<span class="text-[9px] text-slate-400 block uppercase font-bold mb-1">a2</span>
|
||||
<input type="number" :value="formatFineCoeff(currentA2)" step="0.001"
|
||||
@change="setAFineDirect(2, $event.target.value)" @keydown="onlyNumberKey"
|
||||
@wheel.prevent="handleAFineWheel(2, $event)"
|
||||
class="w-full bg-white dark:bg-gray-800 border border-slate-200 dark:border-gray-700 rounded-lg p-3 text-sm font-mono text-center text-emerald-700 dark:text-emerald-300">
|
||||
</label>
|
||||
<button v-else type="button" @pointerdown.prevent="startAFineDrag(2, $event)"
|
||||
class="touch-none select-none w-28 mx-auto bg-white dark:bg-gray-800 border border-slate-200 dark:border-gray-700 rounded-lg p-3 text-center active:border-emerald-400 active:ring-2 active:ring-emerald-400/20">
|
||||
<span class="text-[9px] text-slate-400 block uppercase font-bold mb-1">a2</span>
|
||||
<span class="text-lg font-mono font-bold text-emerald-700 dark:text-emerald-300">{{ formatFineCoeff(currentA2) }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 平移調整 (S) -->
|
||||
<div class="mb-4">
|
||||
<label class="text-[11px] font-semibold text-slate-400 dark:text-gray-500 flex justify-between mb-2">
|
||||
<span>平移 (a1 + a2)</span>
|
||||
<span class="text-emerald-600 dark:text-emerald-400 font-mono bg-emerald-50 dark:bg-emerald-900/30 px-2 py-0.5 rounded">{{ a1a2Sum.toFixed(3) }}</span>
|
||||
</label>
|
||||
<input type="range" v-model.number="a1a2Sum" min="-4" max="4" step="0.001"
|
||||
@input="updateA1A2FromRelationship"
|
||||
class="w-full accent-emerald-500 h-1.5 bg-slate-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer">
|
||||
<div class="grid grid-cols-2 gap-2 mb-4">
|
||||
<div class="bg-white dark:bg-gray-800 border border-slate-100 dark:border-gray-700 rounded-lg p-2 text-center shadow-sm">
|
||||
<span class="text-[9px] text-slate-400 block uppercase font-bold mb-1">目前 a1</span>
|
||||
<span class="text-sm font-mono font-bold text-indigo-600 dark:text-indigo-400">{{ formatFineCoeff(currentA1) }}</span>
|
||||
</div>
|
||||
<div class="bg-white dark:bg-gray-800 border border-slate-100 dark:border-gray-700 rounded-lg p-2 text-center shadow-sm">
|
||||
<span class="text-[9px] text-slate-400 block uppercase font-bold mb-1">目前 a2</span>
|
||||
<span class="text-sm font-mono font-bold text-emerald-600 dark:text-emerald-400">{{ formatFineCoeff(currentA2) }}</span>
|
||||
</div>
|
||||
<div class="bg-white dark:bg-gray-800 border border-slate-100 dark:border-gray-700 rounded-lg p-2 text-center shadow-sm">
|
||||
<span class="text-[9px] text-slate-400 block uppercase font-bold mb-1">差值 a1-a2</span>
|
||||
<span class="text-xs font-mono text-slate-600 dark:text-gray-300">{{ formatFineCoeff(currentA1A2Diff) }}</span>
|
||||
</div>
|
||||
<div class="bg-white dark:bg-gray-800 border border-slate-100 dark:border-gray-700 rounded-lg p-2 text-center shadow-sm">
|
||||
<span class="text-[9px] text-slate-400 block uppercase font-bold mb-1">總和 a1+a2</span>
|
||||
<span class="text-xs font-mono text-slate-600 dark:text-gray-300">{{ formatFineCoeff(currentA1A2Sum) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 預覽結果 -->
|
||||
<div class="flex gap-2 mb-4">
|
||||
<div class="flex-1 bg-white dark:bg-gray-800 border border-slate-100 dark:border-gray-700 rounded-lg p-2 text-center shadow-sm">
|
||||
<span class="text-[9px] text-slate-400 block uppercase font-bold mb-1">a1 變化預覽</span>
|
||||
<div class="flex items-center justify-center gap-1.5">
|
||||
<span class="text-[10px] font-mono text-slate-400">{{ currentA1.toFixed(3) }}</span>
|
||||
<svg class="w-2.5 h-2.5 text-slate-300" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
|
||||
<span class="text-xs font-mono font-bold text-indigo-600 dark:text-indigo-400">{{ previewA1.toFixed(3) }}</span>
|
||||
<div class="space-y-3 mb-4">
|
||||
<div>
|
||||
<div class="text-[11px] font-semibold text-slate-400 dark:text-gray-500 mb-1">共同平移</div>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<button @pointerdown.prevent="startA1A2Repeat('common', -1)" @pointerup="stopA1A2Repeat" @pointerleave="stopA1A2Repeat" @pointercancel="stopA1A2Repeat"
|
||||
class="rounded-lg bg-slate-200 dark:bg-gray-800 hover:bg-slate-300 dark:hover:bg-gray-700 text-slate-700 dark:text-gray-300 py-2 text-xs font-bold transition-colors">a1 - 0.001, a2 - 0.001</button>
|
||||
<button @pointerdown.prevent="startA1A2Repeat('common', 1)" @pointerup="stopA1A2Repeat" @pointerleave="stopA1A2Repeat" @pointercancel="stopA1A2Repeat"
|
||||
class="rounded-lg bg-slate-200 dark:bg-gray-800 hover:bg-slate-300 dark:hover:bg-gray-700 text-slate-700 dark:text-gray-300 py-2 text-xs font-bold transition-colors">a1 + 0.001, a2 + 0.001</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1 bg-white dark:bg-gray-800 border border-slate-100 dark:border-gray-700 rounded-lg p-2 text-center shadow-sm">
|
||||
<span class="text-[9px] text-slate-400 block uppercase font-bold mb-1">a2 變化預覽</span>
|
||||
<div class="flex items-center justify-center gap-1.5">
|
||||
<span class="text-[10px] font-mono text-slate-400">{{ currentA2.toFixed(3) }}</span>
|
||||
<svg class="w-2.5 h-2.5 text-slate-300" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
|
||||
<span class="text-xs font-mono font-bold text-emerald-600 dark:text-emerald-400">{{ previewA2.toFixed(3) }}</span>
|
||||
<div>
|
||||
<div class="text-[11px] font-semibold text-slate-400 dark:text-gray-500 mb-1">差值調整</div>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<button @pointerdown.prevent="startA1A2Repeat('spread', 1)" @pointerup="stopA1A2Repeat" @pointerleave="stopA1A2Repeat" @pointercancel="stopA1A2Repeat"
|
||||
class="rounded-lg bg-indigo-100 dark:bg-indigo-900/30 hover:bg-indigo-200 dark:hover:bg-indigo-900/50 text-indigo-700 dark:text-indigo-300 py-2 text-xs font-bold transition-colors">展開差值</button>
|
||||
<button @pointerdown.prevent="startA1A2Repeat('converge', 1)" @pointerup="stopA1A2Repeat" @pointerleave="stopA1A2Repeat" @pointercancel="stopA1A2Repeat"
|
||||
class="rounded-lg bg-emerald-100 dark:bg-emerald-900/30 hover:bg-emerald-200 dark:hover:bg-emerald-900/50 text-emerald-700 dark:text-emerald-300 py-2 text-xs font-bold transition-colors">收斂差值</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -399,7 +429,7 @@
|
||||
<div class="bg-amber-50 dark:bg-amber-900/20 border border-amber-100 dark:border-amber-800/30 rounded-lg p-3">
|
||||
<p class="text-[10px] text-amber-700 dark:text-amber-400 leading-relaxed">
|
||||
<span class="font-bold">運算說明:</span><br>
|
||||
調整時,系統會先將現有係數四捨五入至三位小數再計算基準值。調整結果會自動將 a1, a2 存回為三位小數精度。
|
||||
係數固定對齊到小數點後第三位。微調後請按「套用」更新圖表;觸控時按住數值面板上下拖曳。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -415,8 +445,11 @@
|
||||
<div class="flex items-center gap-2">
|
||||
<span>定點數係數轉換</span>
|
||||
<span
|
||||
class="text-xs bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 px-2 py-1 rounded">Q{{
|
||||
shiftBits }}</span>
|
||||
class="text-xs bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 px-2 py-1 rounded">b Q{{
|
||||
shiftBitsB }}</span>
|
||||
<span
|
||||
class="text-xs bg-orange-100 dark:bg-orange-900/30 text-orange-700 dark:text-orange-300 px-2 py-1 rounded">a Q{{
|
||||
shiftBitsA }}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<button
|
||||
@@ -428,16 +461,33 @@
|
||||
</div>
|
||||
</h2>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="text-sm text-slate-500 dark:text-gray-400 mb-1 block">左移位元數 (Shift Bits:
|
||||
0~14)</label>
|
||||
<div class="flex items-center gap-2">
|
||||
<input type="number" v-model.number="shiftBits" min="0" max="14"
|
||||
@change="clearFixedOverrides" @keydown="onlyNumberKey"
|
||||
<div class="mb-4 grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="text-sm text-slate-500 dark:text-gray-400 mb-1 block">b 左移位元數 (Shift Bits)</label>
|
||||
<input v-if="!isTouchInput" type="number" :value="shiftBitsB" min="0"
|
||||
@change="setShiftBits('b', $event.target.value)" @keydown="onlyNumberKey"
|
||||
@wheel.prevent="handleShiftBitWheel('b', $event)"
|
||||
class="w-full bg-white dark:bg-gray-800 border border-slate-200 dark:border-gray-700 rounded-lg p-3 text-base focus:border-blue-500 outline-none transition-all text-slate-900 dark:text-gray-100">
|
||||
<button v-else type="button" @pointerdown.prevent="startShiftBitDrag('b', $event)"
|
||||
class="touch-none select-none block w-24 mx-auto bg-white dark:bg-gray-800 border border-slate-200 dark:border-gray-700 rounded-lg p-3 text-center active:border-blue-400 active:ring-2 active:ring-blue-400/20">
|
||||
<span class="text-lg font-mono font-bold text-blue-700 dark:text-blue-300">{{ shiftBitsB }}</span>
|
||||
</button>
|
||||
<p class="text-[10px] text-slate-400 mt-1">b scaling: 2^{{ shiftBitsB }} ({{
|
||||
Math.pow(2, shiftBitsB) }})</p>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-sm text-slate-500 dark:text-gray-400 mb-1 block">a 左移位元數 (Shift Bits)</label>
|
||||
<input v-if="!isTouchInput" type="number" :value="shiftBitsA" min="0"
|
||||
@change="setShiftBits('a', $event.target.value)" @keydown="onlyNumberKey"
|
||||
@wheel.prevent="handleShiftBitWheel('a', $event)"
|
||||
class="w-full bg-white dark:bg-gray-800 border border-slate-200 dark:border-gray-700 rounded-lg p-3 text-base focus:border-blue-500 outline-none transition-all text-slate-900 dark:text-gray-100">
|
||||
<button v-else type="button" @pointerdown.prevent="startShiftBitDrag('a', $event)"
|
||||
class="touch-none select-none block w-24 mx-auto bg-white dark:bg-gray-800 border border-slate-200 dark:border-gray-700 rounded-lg p-3 text-center active:border-orange-400 active:ring-2 active:ring-orange-400/20">
|
||||
<span class="text-lg font-mono font-bold text-orange-700 dark:text-orange-300">{{ shiftBitsA }}</span>
|
||||
</button>
|
||||
<p class="text-[10px] text-slate-400 mt-1">a scaling: 2^{{ shiftBitsA }} ({{
|
||||
Math.pow(2, shiftBitsA) }})</p>
|
||||
</div>
|
||||
<p class="text-[10px] text-slate-400 mt-1">Scaling: 2^{{ shiftBits }} ({{ Math.pow(2, shiftBits)
|
||||
}})</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
@@ -472,8 +522,8 @@
|
||||
class="w-full bg-slate-50 dark:bg-gray-900 border border-slate-200 dark:border-gray-700 rounded-lg p-3 text-sm focus:border-blue-500 outline-none font-mono resize-none leading-relaxed text-orange-700 dark:text-orange-300"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-[10px] text-slate-400 dark:text-gray-500 mt-3 italic">註:此數值為原始係數乘以 2^{{ shiftBits }}
|
||||
後四捨五入之結果,可用於定點數 DSP 實作。</p>
|
||||
<p class="text-[10px] text-slate-400 dark:text-gray-500 mt-3 italic">註:b 係數乘以 2^{{ shiftBitsB }},a
|
||||
係數乘以 2^{{ shiftBitsA }} 後四捨五入,可用於定點數 DSP 實作。</p>
|
||||
</section>
|
||||
|
||||
</aside>
|
||||
|
||||
Reference in New Issue
Block a user