Skip to content

Commit

Permalink
Merge pull request #1923 from DevCloudFE/zp/dev
Browse files Browse the repository at this point in the history
Update Dev
  • Loading branch information
GreatZPP authored Dec 10, 2024
2 parents 9d1133d + b8710c9 commit ac2c79c
Show file tree
Hide file tree
Showing 14 changed files with 524 additions and 293 deletions.
12 changes: 12 additions & 0 deletions packages/devui-vue/devui/code-review/src/code-review-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ export interface CommentPosition {
left: number;
right: number;
}
export type ILineNumberTdMap = Record<number, HTMLElement[]>;
export interface IExpandLineNumberInfo {
nextL: string;
nextR: string;
prevL: string;
prevR: string;
}
export interface ICheckedLineDetails {
lefts: number[];
rights: number[];
codes: Record<string, string[]> | string[];
}
export interface CodeReviewMethods {
toggleFold: (status?: boolean) => void;
insertComment: (lineNumber: number, lineSide: LineSide, commentDom: HTMLElement) => void;
Expand Down
11 changes: 6 additions & 5 deletions packages/devui-vue/devui/code-review/src/code-review.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* @jsxImportSource vue */
import { defineComponent, onMounted, provide, toRefs } from 'vue';
import { defineComponent, onMounted, provide, toRefs, ref } from 'vue';
import type { SetupContext } from 'vue';
import CodeReviewHeader from './components/code-review-header';
import { CommentIcon } from './components/code-review-icons';
Expand All @@ -18,8 +18,7 @@ export default defineComponent({
setup(props: CodeReviewProps, ctx: SetupContext) {
const ns = useNamespace('code-review');
const { diffType } = toRefs(props);
const { renderHtml, reviewContentRef, diffFile, onContentClick } = useCodeReview(props, ctx);
const { isFold, toggleFold } = useCodeReviewFold(props, ctx);
const reviewContentRef = ref();
const {
commentLeft,
commentTop,
Expand All @@ -28,16 +27,18 @@ export default defineComponent({
onCommentIconClick,
insertComment,
removeComment,
updateCheckedLineClass,
clearCheckedLines,
updateLineNumberMap,
updateCheckedLine,
} = useCodeReviewComment(reviewContentRef, props, ctx);
const { renderHtml, diffFile, onContentClick } = useCodeReview(props, ctx, reviewContentRef, updateLineNumberMap, updateCheckedLine);
const { isFold, toggleFold } = useCodeReviewFold(props, ctx);

onMounted(() => {
ctx.emit('afterViewInit', {
toggleFold,
insertComment,
removeComment,
updateCheckedLineClass,
clearCheckedLines,
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ref, toRefs, onUnmounted, watch } from 'vue';
import { ref, toRefs, onUnmounted } from 'vue';
import type { SetupContext, Ref } from 'vue';
import { useCodeReviewLineSelection } from './use-code-review-line-selection';
import type { LineSide, CodeReviewProps } from '../code-review-types';
import type { LineSide, CodeReviewProps, ICheckedLineDetails } from '../code-review-types';
import { useNamespace } from '../../../shared/hooks/use-namespace';
import {
notEmptyNode,
Expand All @@ -14,28 +14,18 @@ import {
export function useCodeReviewComment(reviewContentRef: Ref<HTMLElement>, props: CodeReviewProps, ctx: SetupContext) {
const { outputFormat, allowComment, allowChecked } = toRefs(props);
const ns = useNamespace('code-review');
const { onMousedown } = useCodeReviewLineSelection(reviewContentRef, props, updateLineNumbers, afterCheckLines);
const { onMousedown, updateLineNumberMap, getCheckedLineDetails, clearCommentClass, updateCheckedLine } = useCodeReviewLineSelection(
reviewContentRef,
props,
afterMouseup
);
const commentLeft = ref(-100);
const commentTop = ref(-100);
let currentLeftLineNumber = -1;
let currentRightLineNumber = -1;
let currentPosition: 'left' | 'right';
let lastLineNumberContainer: HTMLElement | null;
let checkedLineNumberContainer: Array<Element> = [];
let currentLeftLineNumbers: Array<number> = [];
let currentRightLineNumbers: Array<number> = [];
let checkedLineCodeString: Array<string> | Record<string, Array<string>> = {};
let allTrNodes: NodeListOf<Element> = [];
let afterCheckLinesEmitData: Record<string, any>;
watch(
() => outputFormat.value,
() => {
// 如果出现单栏双栏切换则需要重置选中
checkedLineNumberContainer = [];
currentLeftLineNumbers = [];
currentRightLineNumbers = [];
checkedLineCodeString = [];
}
);

const resetLeftTop = () => {
commentLeft.value = -100;
commentTop.value = -100;
Expand Down Expand Up @@ -85,6 +75,8 @@ export function useCodeReviewComment(reviewContentRef: Ref<HTMLElement>, props:
commentLeft.value = left;
commentTop.value = top;
currentLeftLineNumber = parseInt(leftLineNumberContainer.innerText);
currentRightLineNumber = parseInt(rightLineNumberContainer.innerText || '-1');
currentPosition = 'left';
} else {
resetLeftTop();
}
Expand All @@ -98,7 +90,9 @@ export function useCodeReviewComment(reviewContentRef: Ref<HTMLElement>, props:
const { top, left } = rightLineNumberContainer.getBoundingClientRect();
commentLeft.value = left;
commentTop.value = top;
currentLeftLineNumber = parseInt(leftLineNumberContainer.innerText || '-1');
currentRightLineNumber = parseInt(rightLineNumberContainer.innerText);
currentPosition = 'right';
} else {
resetLeftTop();
}
Expand All @@ -117,168 +111,27 @@ export function useCodeReviewComment(reviewContentRef: Ref<HTMLElement>, props:
resetLeftTop();
}
};
// 获代码行 取值方法
const getLineNumbers = (currentNumber: number, currentNumbers: Array<number>, moveDirection: 'up' | 'down') => {
if (currentNumber === -1) {
// 当前行没数据不代表之前选中的没数据,此时返回原来的
return currentNumbers;
}
if (currentNumbers.length === 0) {
return [currentNumber];
}
const numbers = [...currentNumbers];
let max = Math.max(...numbers);
let min = Math.min(...numbers);
if (moveDirection === 'down') {
max = currentNumber;
}
if (moveDirection === 'up') {
min = currentNumber;
}
return Array.from({ length: max - min + 1 }, (_, i) => i + min);
};
// 获取一些公共类和判断
const getCommonClassAndJudge = () => {
const checkedLine = [currentLeftLineNumbers, currentRightLineNumbers];
return {
linenumberDom: allTrNodes,
checkedLine,
};
};
// 之前每次都先移出所有选中的方法过于浪费性能,增加具体dom节点选中方法(防重复添加)
const addCommentCheckedClass = (Dom: Element) => {
!Dom.classList.contains('comment-checked') && Dom.classList.add('comment-checked');
};
// 单栏
function getSingleCheckedLineCode(shouldRenderClass: boolean) {
const { linenumberDom, checkedLine } = getCommonClassAndJudge();
const checkedCodeContent = [];
for (let i = 0; i < linenumberDom.length; i++) {
const lineNumberDomLeft = linenumberDom[i].children[0];
const lineNumberDomRight = linenumberDom[i].children[1];
if (lineNumberDomLeft || lineNumberDomRight) {
const codeLineNumberLeft = parseInt((lineNumberDomLeft as HTMLElement)?.innerText);
const codeLineNumberRight = parseInt((lineNumberDomRight as HTMLElement)?.innerText);
// 因为存在左边或者右边为空的num所以两边都要循环,但是同一个dom已经过就不需要再赋予
if (checkedLine[0].includes(codeLineNumberLeft) || checkedLine[1].includes(codeLineNumberRight)) {
checkedLineNumberContainer.push(linenumberDom[i]);
// 两个节点之间可能间隔文本节点
const codeNode = linenumberDom[i].nextElementSibling as HTMLElement;
checkedCodeContent.push(codeNode?.innerText);
if (shouldRenderClass) {
addCommentCheckedClass(linenumberDom[i]);
addCommentCheckedClass(codeNode);
}
}
}
}
checkedLineCodeString = checkedCodeContent;
}
// 双栏
function getDoubleCheckedLineCode(shouldRenderClass: boolean) {
const { linenumberDom, checkedLine } = getCommonClassAndJudge();
const checkedCodeContentLeft = [];
const checkedCodeContentRight = [];

function checkedFunc(Dom: Element) {
checkedLineNumberContainer.push(Dom);
const codeNode = Dom.nextElementSibling as HTMLElement;
if (shouldRenderClass) {
addCommentCheckedClass(Dom);
addCommentCheckedClass(codeNode);
}
return codeNode?.innerText;
}

for (let i = 0; i < linenumberDom.length; i++) {
// 左右双栏一起遍历
const codeLineNumber = parseInt(linenumberDom[i]?.innerHTML);
if (linenumberDom[i].classList.contains('d-code-left') && checkedLine[0].includes(codeLineNumber)) {
const lineNumText = checkedFunc(linenumberDom[i]);
checkedCodeContentLeft.push(lineNumText);
continue;
}
if (linenumberDom[i].classList.contains('d-code-right') && checkedLine[1].includes(codeLineNumber)) {
const lineNumText = checkedFunc(linenumberDom[i]);
checkedCodeContentRight.push(lineNumText);
}
}
checkedLineCodeString = { leftCode: checkedCodeContentLeft, rightCode: checkedCodeContentRight };
}
function getCheckedLineCode(shouldRenderClass: boolean) {
if (props.outputFormat === 'line-by-line') {
return getSingleCheckedLineCode(shouldRenderClass);
}
getDoubleCheckedLineCode(shouldRenderClass);
}
function updateLineNumbers(moveDirection: 'up' | 'down') {
currentLeftLineNumbers =
currentLeftLineNumber === -1 ? currentLeftLineNumbers : getLineNumbers(currentLeftLineNumber, currentLeftLineNumbers, moveDirection);
currentRightLineNumbers =
currentRightLineNumber === -1
? currentRightLineNumbers
: getLineNumbers(currentRightLineNumber, currentRightLineNumbers, moveDirection);
getCheckedLineCode(false);
afterCheckLinesEmitData = {
left: currentLeftLineNumber,
right: currentRightLineNumber,
details: {
lefts: currentLeftLineNumbers,
rights: currentRightLineNumbers,
codes: checkedLineCodeString,
},
};
}
const updateCheckedLineClass = () => {
getCheckedLineCode(true);
};
// 还原样式
const resetCommentClass = () => {
for (let i = 0; i < checkedLineNumberContainer.length; i++) {
checkedLineNumberContainer[i].classList.remove('comment-checked');
const codeNode = checkedLineNumberContainer[i].nextElementSibling;
(codeNode as HTMLElement)?.classList.remove('comment-checked');
}
checkedLineNumberContainer = [];
};
// 点击
const commentClick = () => {
interface recordType {
left: number;
right: number;
details?: {
lefts: Array<number>;
rights: Array<number>;
codes: Record<string, Array<string>> | Record<string, Array<number>>;
};
}
let obj: recordType = { left: currentLeftLineNumber, right: currentRightLineNumber };
if ((currentLeftLineNumbers.length >= 1 || currentRightLineNumbers.length >= 1) && allowChecked.value) {
// 选中模式
const maxCurrentLeftLineNumber = currentLeftLineNumbers[currentLeftLineNumbers.length - 1];
const maxCurrentRightLineNumber = currentRightLineNumbers[currentRightLineNumbers.length - 1];
if (maxCurrentLeftLineNumber === currentLeftLineNumber || maxCurrentRightLineNumber === currentRightLineNumber) {
// 点击添加评论图标触发的事件
obj = {
left: currentLeftLineNumber,
right: currentRightLineNumber,
details: {
lefts: currentLeftLineNumbers,
rights: currentRightLineNumbers,
codes: checkedLineCodeString,
},
};
let obj = { left: currentLeftLineNumber, right: currentRightLineNumber, position: currentPosition };
const checkedLineDetails = getCheckedLineDetails();
// 多行选中
if (checkedLineDetails && allowChecked.value) {
const { lefts, rights } = checkedLineDetails;
const maxCheckedLeftLineNumber = lefts[lefts.length - 1];
const maxCheckedRightLineNumber = rights[rights.length - 1];
if (maxCheckedLeftLineNumber === currentLeftLineNumber || maxCheckedRightLineNumber === currentRightLineNumber) {
obj.details = checkedLineDetails;
} else {
currentLeftLineNumbers = [];
currentRightLineNumbers = [];
resetCommentClass();
clearCommentClass();
}
}
// 点击添加评论图标触发的事件
ctx.emit('addComment', obj);
};
function afterCheckLines() {
ctx.emit('afterCheckLines', afterCheckLinesEmitData);
function afterMouseup(details: ICheckedLineDetails) {
ctx.emit('afterCheckLines', { left: currentLeftLineNumber, right: currentRightLineNumber, position: currentPosition, details });
}
// 图标或者单行的点击
const onCommentIconClick = (e: Event) => {
Expand Down Expand Up @@ -335,16 +188,7 @@ export function useCodeReviewComment(reviewContentRef: Ref<HTMLElement>, props:
};

const clearCheckedLines = () => {
currentLeftLineNumbers = [];
currentRightLineNumbers = [];
checkedLineCodeString = [];
resetCommentClass();
};

const handleMouseDown = (e: MouseEvent) => {
const lineClassName = props.outputFormat === 'line-by-line' ? '.d2h-code-linenumber' : '.d2h-code-side-linenumber';
allTrNodes = reviewContentRef.value.querySelectorAll(lineClassName);
onMousedown(e);
clearCommentClass();
};

const mouseEvent: Record<string, (e: MouseEvent) => void> = {};
Expand All @@ -353,7 +197,7 @@ export function useCodeReviewComment(reviewContentRef: Ref<HTMLElement>, props:
mouseEvent.onMouseleave = onMouseleave;
}
if (props.allowChecked) {
mouseEvent.onMousedown = handleMouseDown;
mouseEvent.onMousedown = onMousedown;
}

window.addEventListener('scroll', resetLeftTop);
Expand All @@ -366,11 +210,12 @@ export function useCodeReviewComment(reviewContentRef: Ref<HTMLElement>, props:
commentLeft,
commentTop,
mouseEvent,
updateCheckedLineClass,
clearCheckedLines,
onCommentMouseLeave,
onCommentIconClick,
insertComment,
removeComment,
updateLineNumberMap,
updateCheckedLine,
};
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { toRefs } from 'vue';
import type { Ref } from 'vue';
import type { CodeReviewProps, ExpandDirection } from '../code-review-types';
import type { CodeReviewProps, ExpandDirection, IExpandLineNumberInfo } from '../code-review-types';
import { ExpandLineReg, FirstLineReg } from '../const';
import {
attachExpandUpDownButton,
Expand All @@ -14,7 +14,12 @@ import {
ifRemoveExpandLineForDoubleColumn,
} from '../utils';

export function useCodeReviewExpand(reviewContentRef: Ref<HTMLElement>, props: CodeReviewProps) {
export function useCodeReviewExpand(
reviewContentRef: Ref<HTMLElement>,
props: CodeReviewProps,
updateLineNumberMap: (expandLineNumberInfo: IExpandLineNumberInfo, newCode: string, direction: 'up' | 'down') => void,
updateCheckedLine: (expandLineNumberInfo: IExpandLineNumberInfo, direction: 'up' | 'down') => void
) {
const { outputFormat, expandThreshold, expandLoader } = toRefs(props);

const processSideBySide = () => {
Expand Down Expand Up @@ -85,8 +90,12 @@ export function useCodeReviewExpand(reviewContentRef: Ref<HTMLElement>, props: C

// 过滤有效行
const trNodesToBeInserted = trNodes.filter((element) => element !== expandLine);
/* 更新左右行号映射关系 */
updateLineNumberMap(referenceDom.dataset as unknown as IExpandLineNumberInfo, prefix + code, direction);
// 将有效代码行插入页面
insertIncrementLineToPage(referenceDom, trNodesToBeInserted, direction);
/* 若新增行在选中区间,则将新增行高亮 */
updateCheckedLine(referenceDom.dataset as unknown as IExpandLineNumberInfo, direction);

// 判断是否需要移除展开行,代码若已全部展开,不再需要展开行
const removedExpandLine = ifRemoveExpandLineForDoubleColumn(referenceDom, expandLine, direction);
Expand Down Expand Up @@ -192,6 +201,8 @@ export function useCodeReviewExpand(reviewContentRef: Ref<HTMLElement>, props: C
const trNodesToBeInserted = trNodes.filter((element) => element.children[0].children.length === 2);
// 将有效代码行插入页面
insertIncrementLineToPage(referenceDom, trNodesToBeInserted, direction);
/* 若新增行在选中区间,则将新增行高亮 */
updateCheckedLine(referenceDom.dataset as unknown as IExpandLineNumberInfo, direction);

// 判断是否需要移除展开行,代码若已全部展开,不再需要展开行
const removedExpandLine = ifRemoveExpandLine(referenceDom, expandLine, direction);
Expand Down
Loading

0 comments on commit ac2c79c

Please sign in to comment.