feat: 尝试删除索引的时候删除整个段落

This commit is contained in:
liuweiqing 2024-02-02 22:59:21 +08:00
parent d56f427484
commit 732dd738c9
6 changed files with 203 additions and 16 deletions

View File

@ -0,0 +1,44 @@
import { faL } from "@fortawesome/free-solid-svg-icons";
import React from "react";
import Swal from "sweetalert2";
// 定义Props类型
interface SweetAlertComponentProps {
index: number;
removeReferenceUpdateIndex: (index: number, rmPg: boolean) => void;
}
const ParagraphDeleteButton: React.FC<SweetAlertComponentProps> = ({
index,
removeReferenceUpdateIndex,
}) => {
const showAlert = async () => {
const result = await Swal.fire({
title: "需要同时删除与文献相关的整个段落吗?",
text: "根据周围的换行符来判断是否是同一个段落",
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
confirmButtonText: "Yes, delete it!",
});
if (result.isConfirmed) {
removeReferenceUpdateIndex(index, true);
// Swal.fire("Deleted!", "Your file has been deleted.", "success");
} else {
removeReferenceUpdateIndex(index, false);
// Swal.fire("Cancelled", "Your imaginary file is safe :)", "error");
}
};
return (
<button
className="text-red-500 hover:text-red-700 ml-4"
onClick={showAlert} // 直接使用showAlert而不传递参数
>
X
</button>
);
};
export default ParagraphDeleteButton;

View File

@ -56,7 +56,7 @@ const QEditor = () => {
const upsreamUrl = useAppSelector((state: any) => state.auth.upsreamUrl);
const [quill, setQuill] = useState(null);
//询问ai用户输入
const [userInput, setUserInput] = useState("");
const [userInput, setUserInput] = useState("robot");
//quill编辑器鼠标位置
const [cursorPosition, setCursorPosition] = useState(null);

View File

@ -7,6 +7,9 @@ import {
formatAllReferencesForCopy,
delteIndexUpdateBracketNumbersInDeltaKeepSelection,
} from "@/utils/others/quillutils";
//删除文献按钮
import ParagraphDeleteButton from "@/components/ParagraphDeleteInterface";
//redux
import { useAppDispatch, useAppSelector } from "@/app/store";
import {
@ -51,10 +54,9 @@ function ReferenceList({ editor }: ReferenceListProps) {
dispatch(swapReferencesRedux({ indexA: index, indexB: index + 1 }));
}
function removeReferenceUpdateIndex(index: number) {
// removeReference(index);
function removeReferenceUpdateIndex(index: number, rmPg = false) {
handleRemoveReference(index);
delteIndexUpdateBracketNumbersInDeltaKeepSelection(editor, index);
delteIndexUpdateBracketNumbersInDeltaKeepSelection(editor, index, rmPg);
}
const handleAddReference = (newReference: Reference) => {
@ -205,12 +207,16 @@ function ReferenceList({ editor }: ReferenceListProps) {
>
</button>
<button
{/* <button
className="text-red-500 hover:text-red-700 ml-4"
onClick={() => removeReferenceUpdateIndex(index)}
>
X
</button>
</button> */}
<ParagraphDeleteButton
index={index}
removeReferenceUpdateIndex={removeReferenceUpdateIndex}
></ParagraphDeleteButton>
</li>
)
)}

15
package-lock.json generated
View File

@ -39,6 +39,7 @@
"slate-history": "^0.100.0",
"slate-hyperscript": "^0.100.0",
"slate-react": "^0.101.5",
"sweetalert2": "^11.10.4",
"tailwindcss": "3.3.3",
"typescript": "5.1.3",
"xml2js": "^0.6.2"
@ -3045,6 +3046,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/sweetalert2": {
"version": "11.10.4",
"resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.10.4.tgz",
"integrity": "sha512-MOVRuEW/yQsyzgkaiHqAJcYKxW3vhtE5o3Skp6vZdyJejCOWo4FOicbjRfvqHAXTyTMuwDHA+0lYbO6BiHl1Gw==",
"funding": {
"type": "individual",
"url": "https://github.com/sponsors/limonte"
}
},
"node_modules/tailwindcss": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz",
@ -5530,6 +5540,11 @@
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
},
"sweetalert2": {
"version": "11.10.4",
"resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.10.4.tgz",
"integrity": "sha512-MOVRuEW/yQsyzgkaiHqAJcYKxW3vhtE5o3Skp6vZdyJejCOWo4FOicbjRfvqHAXTyTMuwDHA+0lYbO6BiHl1Gw=="
},
"tailwindcss": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz",

View File

@ -38,6 +38,7 @@
"slate-history": "^0.100.0",
"slate-hyperscript": "^0.100.0",
"slate-react": "^0.101.5",
"sweetalert2": "^11.10.4",
"tailwindcss": "3.3.3",
"typescript": "5.1.3",
"xml2js": "^0.6.2"

View File

@ -46,23 +46,138 @@ function updateBracketNumbersInDelta(delta) {
return { ops: updatedOps };
}
function deleteUpdateBracketNumbers(delta, indexToRemove: number, quill) {
const updatedOps = delta.ops.map((op) => {
function deleteReferenceNumberOrParagraph(
delta,
indexToRemove: number,
quill,
deleteParagraph: boolean
) {
const indexStr = `[${indexToRemove + 1}]`;
const updatedOps = delta.ops.flatMap((op, i) => {
if (typeof op.insert === "string") {
// 如果文本包含要删除的索引,删除它
const indexStr = `[${indexToRemove + 1}]`;
const indexPos = op.insert.indexOf(indexStr);
if (indexPos !== -1) {
const before = op.insert.slice(0, indexPos);
const after = op.insert.slice(indexPos + indexStr.length);
op.insert = before + after;
if (deleteParagraph) {
// // 检查是否包含要删除的索引并找到段落的起止位置
// let startPos = op.insert.lastIndexOf("\n", indexPos) + 1;
// let endPos = op.insert.indexOf("\n", indexPos);
// console.log("startPos", startPos);
// console.log("endPos", endPos);
// // 如果没有找到首部的换行符,说明是文档的第一个段落或索引紧跟在段落开头
// if (startPos === 0 && indexPos > 0) {
// // 直接从文档开始删除到段落末尾
// startPos = 0; // 从文档开头开始
// }
// // 如果没有找到末尾的换行符,说明索引在文档或段落的末尾
// endPos = endPos === -1 ? op.insert.length : endPos;
// // 删除整个段落
// console.log("startPos2", startPos);
// console.log("endPos2", endPos);
// const before = op.insert.slice(0, startPos);
// const after = op.insert.slice(endPos);
// op.insert = before + after;
// // 如果处理后的insert为空字符串我们返回一个空数组来避免创建空操作
// console.log("删除整个段落");
// return op.insert ? [op] : [];
// 找到索引所在的op开始向前和向后搜索段落的边界
let startPos = findPrevParagraphEnd(delta.ops, i);
let endPos = findNextParagraphStart(delta.ops, i);
// 删除段落需要根据startPos和endPos来决定删除或修改哪些op
// 这可能包括从一个op中删除文本或者完全删除一个或多个op
deleteParagraphOps(delta.ops, startPos, endPos);
} else {
// 删除单个索引的逻辑
const before = op.insert.slice(0, indexPos);
const after = op.insert.slice(indexPos + indexStr.length);
op.insert = before + after;
console.log("删除索引");
}
}
}
return op;
// 对于不需要修改的op直接返回
return [op];
});
return { ops: updatedOps };
}
function findPrevParagraphEnd(ops, currentIndex) {
// 从当前索引向前搜索换行符
for (let i = currentIndex - 1; i >= 0; i--) {
const op = ops[i];
if (typeof op.insert === "string") {
const newlineIndex = op.insert.lastIndexOf("\n");
// 如果在当前op中找到了换行符返回这个位置和op的索引
if (newlineIndex !== -1) {
return { opIndex: i, charIndex: newlineIndex + 1 };
}
}
}
// 如果没有找到换行符,返回文档开头的位置
return { opIndex: -1, charIndex: 0 };
}
function findNextParagraphStart(ops, currentIndex) {
// 从当前索引向后搜索换行符
for (let i = currentIndex; i < ops.length; i++) {
const op = ops[i];
if (typeof op.insert === "string") {
const newlineIndex = op.insert.indexOf("\n");
// 如果在当前op中找到了换行符返回这个位置和op的索引
if (newlineIndex !== -1) {
return { opIndex: i, charIndex: newlineIndex + 1 };
}
}
}
// 如果没有找到换行符,返回文档末尾的位置
return {
opIndex: ops.length - 1,
charIndex: ops[ops.length - 1].insert.length,
};
}
function deleteParagraphOps(ops, startPos, endPos) {
// 如果段落在同一个op内
if (startPos.opIndex === endPos.opIndex && startPos.opIndex !== -1) {
const op = ops[startPos.opIndex];
const before = op.insert.substring(0, startPos.charIndex);
const after = op.insert.substring(endPos.charIndex);
op.insert = before + after;
if (op.insert === "") {
// 如果op为空则移除此op
ops.splice(startPos.opIndex, 1);
}
} else {
// 处理跨越多个op的段落删除
// 1. 修改或删除起始op
if (startPos.opIndex !== -1) {
const startOp = ops[startPos.opIndex];
startOp.insert = startOp.insert.substring(0, startPos.charIndex);
if (startOp.insert === "") {
// 如果起始op为空删除之
ops.splice(startPos.opIndex, 1);
// 调整结束位置索引,因为数组长度减少了
endPos.opIndex--;
}
}
// 2. 删除起始位置和结束位置之间的所有op
const deleteCount = endPos.opIndex - startPos.opIndex - 1;
if (deleteCount > 0) {
ops.splice(startPos.opIndex + 1, deleteCount);
}
// 3. 修改或删除结束op
if (endPos.opIndex !== -1 && endPos.opIndex < ops.length) {
const endOp = ops[endPos.opIndex];
endOp.insert = endOp.insert.substring(endPos.charIndex);
if (endOp.insert === "" && deleteCount >= 0) {
// 如果结束op为空删除之
ops.splice(endPos.opIndex, 1);
}
}
}
}
// function deleteUpdateBracketNumbers(delta, indexToRemove:number, quill) {
// let currentNumber = 1;
@ -100,11 +215,17 @@ function updateBracketNumbersInDeltaKeepSelection(quill) {
export function delteIndexUpdateBracketNumbersInDeltaKeepSelection(
quill,
index: number
index: number,
rmPg: boolean
) {
const selection = quill.getSelection();
const delta = quill.getContents();
let updatedDelta = deleteUpdateBracketNumbers(delta, index, quill);
let updatedDelta = deleteReferenceNumberOrParagraph(
delta,
index,
quill,
rmPg
);
updatedDelta = updateBracketNumbersInDelta(updatedDelta);
quill.setContents(updatedDelta);
if (selection) {