性能优化和样式更新

This commit is contained in:
2026-06-23 10:08:39 +08:00
parent c3739b18eb
commit 58260797b2
4 changed files with 163 additions and 47 deletions
+38 -5
View File
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { ref, computed, nextTick } from 'vue';
import { splitTokens, parseDetailedToken, constructToken } from '../../stores/promptStore';
import { splitTokens, parseDetailedToken, constructToken, normalizeSymbols } from '../../stores/promptStore';
import PromptQuickAdd from '../PromptQuickAdd.vue';
const props = defineProps<{
@@ -26,6 +26,7 @@ const emit = defineEmits<{
'add-tag': [tag: string];
'drag-tag-start': [tag: string];
'drag-tag-end': [];
'locate-token': [index: number];
}>();
const inputEl = ref<HTMLTextAreaElement | null>(null);
@@ -154,9 +155,41 @@ async function applySuggestion(s: string) {
emit('update-suggestions');
}
function updateSuggestions() {
// 通知父组件更新建议
// 计算与 splitTokens 对齐的非空 token 区间(用于光标定位)
function computeTokenRanges(txt: string): { start: number; end: number }[] {
const ranges: { start: number; end: number }[] = [];
let depth = 0;
let segStart = 0;
for (let i = 0; i < txt.length; i++) {
const c = txt[i]!;
if (c === '(' || c === '[' || c === '{' || c === '<') depth++;
else if (c === ')' || c === ']' || c === '}' || c === '>') depth = Math.max(0, depth - 1);
if ((c === ',' || c === '\n') && depth === 0) {
ranges.push({ start: segStart, end: i });
segStart = i + 1;
}
}
ranges.push({ start: segStart, end: txt.length });
return ranges.filter(r => txt.slice(r.start, r.end).trim().length > 0);
}
// 根据光标位置定位对应的 token 序号,通知父组件高亮右侧映射
function emitLocate() {
const el = inputEl.value;
if (!el) return;
const norm = normalizeSymbols(props.text);
const pos = el.selectionStart ?? norm.length;
const ranges = computeTokenRanges(norm);
if (!ranges.length) { emit('locate-token', -1); return; }
let idx = ranges.findIndex(r => pos >= r.start && pos <= r.end);
if (idx === -1) idx = ranges.findIndex(r => pos <= r.end);
if (idx === -1) idx = ranges.length - 1;
emit('locate-token', idx);
}
function onCursorActivity() {
emit('update-suggestions');
emitLocate();
}
defineExpose({
@@ -172,8 +205,8 @@ defineExpose({
class="pe-input"
v-model="localText"
@keydown="onKeyDown"
@click="updateSuggestions"
@keyup="updateSuggestions"
@click="onCursorActivity"
@keyup="onCursorActivity"
placeholder="例如:1girl, aaa, bbb, ccc"
></textarea>
<div class="pe-input-actions">