feat: 尝试删除索引的时候删除整个段落
This commit is contained in:
parent
d56f427484
commit
732dd738c9
44
components/ParagraphDeleteInterface.tsx
Normal file
44
components/ParagraphDeleteInterface.tsx
Normal 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;
|
|
@ -56,7 +56,7 @@ const QEditor = () => {
|
||||||
const upsreamUrl = useAppSelector((state: any) => state.auth.upsreamUrl);
|
const upsreamUrl = useAppSelector((state: any) => state.auth.upsreamUrl);
|
||||||
const [quill, setQuill] = useState(null);
|
const [quill, setQuill] = useState(null);
|
||||||
//询问ai,用户输入
|
//询问ai,用户输入
|
||||||
const [userInput, setUserInput] = useState("");
|
const [userInput, setUserInput] = useState("robot");
|
||||||
//quill编辑器鼠标位置
|
//quill编辑器鼠标位置
|
||||||
const [cursorPosition, setCursorPosition] = useState(null);
|
const [cursorPosition, setCursorPosition] = useState(null);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,9 @@ import {
|
||||||
formatAllReferencesForCopy,
|
formatAllReferencesForCopy,
|
||||||
delteIndexUpdateBracketNumbersInDeltaKeepSelection,
|
delteIndexUpdateBracketNumbersInDeltaKeepSelection,
|
||||||
} from "@/utils/others/quillutils";
|
} from "@/utils/others/quillutils";
|
||||||
|
//删除文献按钮
|
||||||
|
import ParagraphDeleteButton from "@/components/ParagraphDeleteInterface";
|
||||||
|
|
||||||
//redux
|
//redux
|
||||||
import { useAppDispatch, useAppSelector } from "@/app/store";
|
import { useAppDispatch, useAppSelector } from "@/app/store";
|
||||||
import {
|
import {
|
||||||
|
@ -51,10 +54,9 @@ function ReferenceList({ editor }: ReferenceListProps) {
|
||||||
dispatch(swapReferencesRedux({ indexA: index, indexB: index + 1 }));
|
dispatch(swapReferencesRedux({ indexA: index, indexB: index + 1 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeReferenceUpdateIndex(index: number) {
|
function removeReferenceUpdateIndex(index: number, rmPg = false) {
|
||||||
// removeReference(index);
|
|
||||||
handleRemoveReference(index);
|
handleRemoveReference(index);
|
||||||
delteIndexUpdateBracketNumbersInDeltaKeepSelection(editor, index);
|
delteIndexUpdateBracketNumbersInDeltaKeepSelection(editor, index, rmPg);
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleAddReference = (newReference: Reference) => {
|
const handleAddReference = (newReference: Reference) => {
|
||||||
|
@ -205,12 +207,16 @@ function ReferenceList({ editor }: ReferenceListProps) {
|
||||||
>
|
>
|
||||||
复制
|
复制
|
||||||
</button>
|
</button>
|
||||||
<button
|
{/* <button
|
||||||
className="text-red-500 hover:text-red-700 ml-4"
|
className="text-red-500 hover:text-red-700 ml-4"
|
||||||
onClick={() => removeReferenceUpdateIndex(index)}
|
onClick={() => removeReferenceUpdateIndex(index)}
|
||||||
>
|
>
|
||||||
X
|
X
|
||||||
</button>
|
</button> */}
|
||||||
|
<ParagraphDeleteButton
|
||||||
|
index={index}
|
||||||
|
removeReferenceUpdateIndex={removeReferenceUpdateIndex}
|
||||||
|
></ParagraphDeleteButton>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
|
|
15
package-lock.json
generated
15
package-lock.json
generated
|
@ -39,6 +39,7 @@
|
||||||
"slate-history": "^0.100.0",
|
"slate-history": "^0.100.0",
|
||||||
"slate-hyperscript": "^0.100.0",
|
"slate-hyperscript": "^0.100.0",
|
||||||
"slate-react": "^0.101.5",
|
"slate-react": "^0.101.5",
|
||||||
|
"sweetalert2": "^11.10.4",
|
||||||
"tailwindcss": "3.3.3",
|
"tailwindcss": "3.3.3",
|
||||||
"typescript": "5.1.3",
|
"typescript": "5.1.3",
|
||||||
"xml2js": "^0.6.2"
|
"xml2js": "^0.6.2"
|
||||||
|
@ -3045,6 +3046,15 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"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": {
|
"node_modules/tailwindcss": {
|
||||||
"version": "3.3.3",
|
"version": "3.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||||
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
|
"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": {
|
"tailwindcss": {
|
||||||
"version": "3.3.3",
|
"version": "3.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz",
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
"slate-history": "^0.100.0",
|
"slate-history": "^0.100.0",
|
||||||
"slate-hyperscript": "^0.100.0",
|
"slate-hyperscript": "^0.100.0",
|
||||||
"slate-react": "^0.101.5",
|
"slate-react": "^0.101.5",
|
||||||
|
"sweetalert2": "^11.10.4",
|
||||||
"tailwindcss": "3.3.3",
|
"tailwindcss": "3.3.3",
|
||||||
"typescript": "5.1.3",
|
"typescript": "5.1.3",
|
||||||
"xml2js": "^0.6.2"
|
"xml2js": "^0.6.2"
|
||||||
|
|
|
@ -46,23 +46,138 @@ function updateBracketNumbersInDelta(delta) {
|
||||||
return { ops: updatedOps };
|
return { ops: updatedOps };
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteUpdateBracketNumbers(delta, indexToRemove: number, quill) {
|
function deleteReferenceNumberOrParagraph(
|
||||||
const updatedOps = delta.ops.map((op) => {
|
delta,
|
||||||
if (typeof op.insert === "string") {
|
indexToRemove: number,
|
||||||
// 如果文本包含要删除的索引,删除它
|
quill,
|
||||||
|
deleteParagraph: boolean
|
||||||
|
) {
|
||||||
const indexStr = `[${indexToRemove + 1}]`;
|
const indexStr = `[${indexToRemove + 1}]`;
|
||||||
|
const updatedOps = delta.ops.flatMap((op, i) => {
|
||||||
|
if (typeof op.insert === "string") {
|
||||||
const indexPos = op.insert.indexOf(indexStr);
|
const indexPos = op.insert.indexOf(indexStr);
|
||||||
if (indexPos !== -1) {
|
if (indexPos !== -1) {
|
||||||
|
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 before = op.insert.slice(0, indexPos);
|
||||||
const after = op.insert.slice(indexPos + indexStr.length);
|
const after = op.insert.slice(indexPos + indexStr.length);
|
||||||
op.insert = before + after;
|
op.insert = before + after;
|
||||||
|
console.log("删除索引");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return op;
|
}
|
||||||
|
// 对于不需要修改的op,直接返回
|
||||||
|
return [op];
|
||||||
});
|
});
|
||||||
|
|
||||||
return { ops: updatedOps };
|
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) {
|
// function deleteUpdateBracketNumbers(delta, indexToRemove:number, quill) {
|
||||||
// let currentNumber = 1;
|
// let currentNumber = 1;
|
||||||
|
|
||||||
|
@ -100,11 +215,17 @@ function updateBracketNumbersInDeltaKeepSelection(quill) {
|
||||||
|
|
||||||
export function delteIndexUpdateBracketNumbersInDeltaKeepSelection(
|
export function delteIndexUpdateBracketNumbersInDeltaKeepSelection(
|
||||||
quill,
|
quill,
|
||||||
index: number
|
index: number,
|
||||||
|
rmPg: boolean
|
||||||
) {
|
) {
|
||||||
const selection = quill.getSelection();
|
const selection = quill.getSelection();
|
||||||
const delta = quill.getContents();
|
const delta = quill.getContents();
|
||||||
let updatedDelta = deleteUpdateBracketNumbers(delta, index, quill);
|
let updatedDelta = deleteReferenceNumberOrParagraph(
|
||||||
|
delta,
|
||||||
|
index,
|
||||||
|
quill,
|
||||||
|
rmPg
|
||||||
|
);
|
||||||
updatedDelta = updateBracketNumbersInDelta(updatedDelta);
|
updatedDelta = updateBracketNumbersInDelta(updatedDelta);
|
||||||
quill.setContents(updatedDelta);
|
quill.setContents(updatedDelta);
|
||||||
if (selection) {
|
if (selection) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user