|
@@ -18,6 +18,7 @@
|
|
|
<el-button type="primary" @click="onAddAdvice" :disabled="props.disabled">添加到常用意见</el-button>
|
|
|
</span>
|
|
|
</div>
|
|
|
+ <pre v-if="highlightedText" v-html="highlightedText" class="highlighted-text"></pre>
|
|
|
<el-drawer v-model="state.showDrawer" :size="props.drawerWidth" :show-close="false" :modal="props.modal">
|
|
|
<template #header="{ close }">
|
|
|
<div class="comments-header">
|
|
@@ -109,17 +110,15 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-drawer>
|
|
|
- <div v-if="wrongText" class="wrong-text">
|
|
|
- <span class="wrong-label">错别字:</span><span class="color-danger wrong-content">{{ wrongText }}</span>
|
|
|
- </div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts" name="commonAdvice">
|
|
|
-import { reactive, ref, computed } from 'vue';
|
|
|
+import { reactive, ref, computed, watch } from 'vue';
|
|
|
import { ElMessage, ElMessageBox, FormInstance } from 'element-plus';
|
|
|
import { commonList, addCommon, deleteCommon } from '@/api/auxiliary/advice';
|
|
|
import { commonEnum } from '@/utils/constants';
|
|
|
+import { jthsErrorWord } from '@/api/todo/voiceAssistant';
|
|
|
const emit = defineEmits(['chooseAdvice', 'update:modelValue']);
|
|
|
const props = defineProps({
|
|
|
modal: {
|
|
@@ -191,7 +190,6 @@ const state = reactive<any>({
|
|
|
loading: false, // 是否显示loading
|
|
|
commonType: '', // 类型
|
|
|
});
|
|
|
-
|
|
|
// 打开常用意见管理
|
|
|
const showAdvice = () => {
|
|
|
openDialog();
|
|
@@ -321,9 +319,51 @@ const chooseAdvice = (item: any) => {
|
|
|
const closeDialog = () => {
|
|
|
state.showDrawer = false;
|
|
|
};
|
|
|
+// 字节位置转换为字符位置的函数
|
|
|
+const byteToCharIndex=(text:string, byteIndex:number)=> {
|
|
|
+ let charIndex = 0;
|
|
|
+ let byteCount = 0;
|
|
|
+
|
|
|
+ while (byteCount < byteIndex && charIndex < text.length) {
|
|
|
+ const char = text[charIndex];
|
|
|
+ byteCount += new Blob([char]).size;
|
|
|
+ if (byteCount <= byteIndex) {
|
|
|
+ charIndex++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return charIndex;
|
|
|
+}
|
|
|
+// 计算属性,生成高亮文本
|
|
|
+const highlightedFn= (text:string, errors:any[]) => {
|
|
|
+ let highlighted = text;
|
|
|
+ const errorPositions = errors.map(error => {
|
|
|
+ const startCharPos = byteToCharIndex(value.value, error.begPos);
|
|
|
+ const endCharPos = byteToCharIndex(value.value, error.begPos + error.length);
|
|
|
+ return { startCharPos, endCharPos };
|
|
|
+ });
|
|
|
+
|
|
|
+ // 逆序处理,以避免更改已经处理的部分
|
|
|
+ errorPositions.reverse().forEach(({ startCharPos, endCharPos }) => {
|
|
|
+ const before = highlighted.slice(0, startCharPos);
|
|
|
+ const errorText = highlighted.slice(startCharPos, endCharPos);
|
|
|
+ const after = highlighted.slice(endCharPos);
|
|
|
+ highlighted = `${before}<b class="color-danger">${errorText}</b>${after}`;
|
|
|
+ });
|
|
|
+
|
|
|
+ return highlighted;
|
|
|
+}
|
|
|
// 文件检查
|
|
|
-const wrongText = ref('');
|
|
|
+const highlightedText = ref('');
|
|
|
+const errorWordsArray = ref([]);
|
|
|
const textCheck = () => {
|
|
|
+ if(!value.value) {
|
|
|
+ ElMessage.warning({
|
|
|
+ message:props.placeholder,
|
|
|
+ grouping:true
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
ElMessageBox.confirm(`确认要检查文本内容?`, '提示', {
|
|
|
confirmButtonText: '确认',
|
|
|
cancelButtonText: '取消',
|
|
@@ -335,22 +375,41 @@ const textCheck = () => {
|
|
|
if (action === 'confirm') {
|
|
|
instance.confirmButtonLoading = true;
|
|
|
instance.confirmButtonText = '检查中,请稍后';
|
|
|
- setTimeout(() => {
|
|
|
- done();
|
|
|
- instance.confirmButtonLoading = false;
|
|
|
- }, 700);
|
|
|
+ const request = {
|
|
|
+ text: value.value,
|
|
|
+ resource: {
|
|
|
+ property: '',
|
|
|
+ },
|
|
|
+ };
|
|
|
+ jthsErrorWord(request)
|
|
|
+ .then((res: any) => {
|
|
|
+ ElMessage.success('检查完成');
|
|
|
+ highlightedText.value = '';
|
|
|
+ errorWordsArray.value = res?.result ?? [];
|
|
|
+ highlightedText.value = highlightedFn(value.value, errorWordsArray.value);
|
|
|
+ done();
|
|
|
+ instance.confirmButtonLoading = false;
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ console.log(err);
|
|
|
+ done();
|
|
|
+ ElMessage.error(err.response.data.msg);
|
|
|
+ });
|
|
|
} else {
|
|
|
done();
|
|
|
}
|
|
|
},
|
|
|
})
|
|
|
.then(async () => {
|
|
|
- ElMessage.success('检查成功');
|
|
|
+ /*ElMessage.success('检查成功');
|
|
|
wrongText.value = '';
|
|
|
- closeDialog();
|
|
|
+ closeDialog();*/
|
|
|
})
|
|
|
.catch(() => {});
|
|
|
};
|
|
|
+watch(()=>value.value,(val)=>{
|
|
|
+ if(!val) highlightedText.value = '';
|
|
|
+})
|
|
|
// 暴露变量
|
|
|
defineExpose({
|
|
|
openDialog,
|
|
@@ -368,12 +427,33 @@ defineExpose({
|
|
|
}
|
|
|
.buttons {
|
|
|
position: absolute;
|
|
|
- right: 80px;
|
|
|
+ right: 100px;
|
|
|
bottom: 10px;
|
|
|
}
|
|
|
:deep(.el-textarea__inner) {
|
|
|
padding-bottom: 40px;
|
|
|
}
|
|
|
+ .highlighted-text {
|
|
|
+ margin-top:10px;
|
|
|
+ background-color: var(--el-input-bg-color, var(--el-fill-color-blank));
|
|
|
+ background-image: none;
|
|
|
+ border: none;
|
|
|
+ border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
|
|
|
+ box-shadow: 0 0 0 1px var(--el-input-border-color, var(--el-border-color)) inset;
|
|
|
+ box-sizing: border-box;
|
|
|
+ color: var(--el-input-text-color, var(--el-text-color-regular));
|
|
|
+ display: block;
|
|
|
+ font-family: inherit;
|
|
|
+ font-size: inherit;
|
|
|
+ line-height: 1.5;
|
|
|
+ padding: 5px 11px;
|
|
|
+ position: relative;
|
|
|
+ resize: vertical;
|
|
|
+ transition: var(--el-transition-box-shadow);
|
|
|
+ width: 100%;
|
|
|
+ text-wrap: wrap;
|
|
|
+ word-wrap: break-word;
|
|
|
+ }
|
|
|
}
|
|
|
.comments-container {
|
|
|
.comments-box {
|
|
@@ -400,20 +480,6 @@ defineExpose({
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-.wrong-text{
|
|
|
- line-height: 24px;
|
|
|
- display: flex;
|
|
|
- margin-top: 5px;
|
|
|
- .wrong-label{
|
|
|
- flex: 0 0 auto;
|
|
|
- }
|
|
|
- .wrong-content{
|
|
|
- align-items: center;
|
|
|
- flex:1;
|
|
|
- min-width: 0;
|
|
|
- word-break: break-all;
|
|
|
- }
|
|
|
-}
|
|
|
.comments-header {
|
|
|
.active {
|
|
|
color: var(--el-color-primary);
|