diff --git a/src/views/creative-generation-workshop/manuscript-writer/check/components/content-card/highlight-textarea.vue b/src/views/creative-generation-workshop/manuscript-writer/check/components/content-card/highlight-textarea.vue
index 9dce8c2..c02dbf5 100644
--- a/src/views/creative-generation-workshop/manuscript-writer/check/components/content-card/highlight-textarea.vue
+++ b/src/views/creative-generation-workshop/manuscript-writer/check/components/content-card/highlight-textarea.vue
@@ -1,24 +1,11 @@
-
(focus = true)"
- @blur="() => (focus = false)"
- />
+ (focus = true)" @blur="() => (focus = false)" />
-
+
@@ -47,9 +34,11 @@ const emit = defineEmits<{
(e: 'update:modelValue', value: string): void;
}>();
+// 内部状态管理
const inputValue = ref(props.modelValue || '');
-const scrollTop = ref(0);
const focus = ref(false);
+const textareaWrapRef = ref();
+let nativeTextarea: HTMLTextAreaElement | null = null;
const highlightedHtml = computed(() => generateHighlightedHtml());
// 监听外部modelValue变化
@@ -67,12 +56,6 @@ const handleInput = (value: string) => {
emit('update:modelValue', value);
};
-// 同步滚动位置
-const syncScroll = (e: Event) => {
- console.log('syncScroll');
- scrollTop.value = (e.target as HTMLTextAreaElement).scrollTop;
-};
-
const escapeHtml = (str: string): string => {
if (!isString(str)) return '';
return str
@@ -114,11 +97,24 @@ const generateHighlightedHtml = (): string => {
};
onMounted(() => {
- document.querySelector('.textarea-input .arco-textarea')?.addEventListener('scroll', handleTextareaScroll);
+ nativeTextarea = (textareaWrapRef.value?.$el || textareaWrapRef.value)?.querySelector?.('textarea.arco-textarea') ||
+ document.querySelector('.textarea-input .arco-textarea');
+
+ if (nativeTextarea) {
+ nativeTextarea.addEventListener('scroll', handleTextareaScroll);
+ nativeTextarea.addEventListener('compositionstart', handleCompositionUpdate);
+ nativeTextarea.addEventListener('compositionupdate', handleCompositionUpdate);
+ nativeTextarea.addEventListener('compositionend', handleCompositionUpdate);
+ }
});
onUnmounted(() => {
- document.querySelector('.textarea-input .arco-textarea')?.removeEventListener('scroll', handleTextareaScroll);
+ if (nativeTextarea) {
+ nativeTextarea.removeEventListener('scroll', handleTextareaScroll);
+ nativeTextarea.removeEventListener('compositionstart', handleCompositionUpdate);
+ nativeTextarea.removeEventListener('compositionupdate', handleCompositionUpdate);
+ nativeTextarea.removeEventListener('compositionend', handleCompositionUpdate);
+ }
});
const handleTextareaScroll = (e: Event) => {
@@ -129,6 +125,18 @@ const handleTextareaScroll = (e: Event) => {
highlightElement.scrollTop = _scrollTop;
}
};
+
+const handleCompositionUpdate = () => {
+ if (!nativeTextarea) return;
+ // 使用 rAF 等待浏览器把最新字符写入 textarea.value 再读取
+ requestAnimationFrame(() => {
+ if (!nativeTextarea) return;
+ const latest = nativeTextarea.value.slice(0, 1000);
+ if (latest !== inputValue.value) {
+ inputValue.value = latest;
+ }
+ });
+};
diff --git a/src/views/creative-generation-workshop/manuscript/check/components/content-card/highlight-textarea.vue b/src/views/creative-generation-workshop/manuscript/check/components/content-card/highlight-textarea.vue
index aceb257..3644d31 100644
--- a/src/views/creative-generation-workshop/manuscript/check/components/content-card/highlight-textarea.vue
+++ b/src/views/creative-generation-workshop/manuscript/check/components/content-card/highlight-textarea.vue
@@ -1,24 +1,11 @@
-
(focus = true)"
- @blur="() => (focus = false)"
- />
+ (focus = true)" @blur="() => (focus = false)" />
-
+
@@ -51,6 +38,8 @@ const emit = defineEmits<{
const inputValue = ref(props.modelValue || '');
const scrollTop = ref(0);
const focus = ref(false);
+const textareaWrapRef = ref();
+let nativeTextarea: HTMLTextAreaElement | null = null;
const highlightedHtml = computed(() => generateHighlightedHtml());
// 监听外部modelValue变化
@@ -68,12 +57,6 @@ const handleInput = (value: string) => {
emit('update:modelValue', value);
};
-// 同步滚动位置
-const syncScroll = (e: Event) => {
- console.log('syncScroll');
- scrollTop.value = (e.target as HTMLTextAreaElement).scrollTop;
-};
-
const escapeHtml = (str: string): string => {
if (!isString(str)) return '';
return str
@@ -115,11 +98,24 @@ const generateHighlightedHtml = (): string => {
};
onMounted(() => {
- document.querySelector('.textarea-input .arco-textarea')?.addEventListener('scroll', handleTextareaScroll);
+ nativeTextarea = (textareaWrapRef.value?.$el || textareaWrapRef.value)?.querySelector?.('textarea.arco-textarea') ||
+ document.querySelector('.textarea-input .arco-textarea');
+
+ if (nativeTextarea) {
+ nativeTextarea.addEventListener('scroll', handleTextareaScroll);
+ nativeTextarea.addEventListener('compositionstart', handleCompositionUpdate);
+ nativeTextarea.addEventListener('compositionupdate', handleCompositionUpdate);
+ nativeTextarea.addEventListener('compositionend', handleCompositionUpdate);
+ }
});
onUnmounted(() => {
- document.querySelector('.textarea-input .arco-textarea')?.removeEventListener('scroll', handleTextareaScroll);
+ if (nativeTextarea) {
+ nativeTextarea.removeEventListener('scroll', handleTextareaScroll);
+ nativeTextarea.removeEventListener('compositionstart', handleCompositionUpdate);
+ nativeTextarea.removeEventListener('compositionupdate', handleCompositionUpdate);
+ nativeTextarea.removeEventListener('compositionend', handleCompositionUpdate);
+ }
});
const handleTextareaScroll = (e: Event) => {
@@ -130,6 +126,18 @@ const handleTextareaScroll = (e: Event) => {
highlightElement.scrollTop = _scrollTop;
}
};
+
+const handleCompositionUpdate = () => {
+ if (!nativeTextarea) return;
+ // 使用 rAF 等待浏览器把最新字符写入 textarea.value 再读取
+ requestAnimationFrame(() => {
+ if (!nativeTextarea) return;
+ const latest = nativeTextarea.value.slice(0, 1000);
+ if (latest !== inputValue.value) {
+ inputValue.value = latest;
+ }
+ });
+};