Skip to content

Commit ac2c79c

Browse files
authored
Merge pull request #1923 from DevCloudFE/zp/dev
Update Dev
2 parents 9d1133d + b8710c9 commit ac2c79c

File tree

14 files changed

+524
-293
lines changed

14 files changed

+524
-293
lines changed

packages/devui-vue/devui/code-review/src/code-review-types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@ export interface CommentPosition {
1010
left: number;
1111
right: number;
1212
}
13+
export type ILineNumberTdMap = Record<number, HTMLElement[]>;
14+
export interface IExpandLineNumberInfo {
15+
nextL: string;
16+
nextR: string;
17+
prevL: string;
18+
prevR: string;
19+
}
20+
export interface ICheckedLineDetails {
21+
lefts: number[];
22+
rights: number[];
23+
codes: Record<string, string[]> | string[];
24+
}
1325
export interface CodeReviewMethods {
1426
toggleFold: (status?: boolean) => void;
1527
insertComment: (lineNumber: number, lineSide: LineSide, commentDom: HTMLElement) => void;

packages/devui-vue/devui/code-review/src/code-review.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* @jsxImportSource vue */
2-
import { defineComponent, onMounted, provide, toRefs } from 'vue';
2+
import { defineComponent, onMounted, provide, toRefs, ref } from 'vue';
33
import type { SetupContext } from 'vue';
44
import CodeReviewHeader from './components/code-review-header';
55
import { CommentIcon } from './components/code-review-icons';
@@ -18,8 +18,7 @@ export default defineComponent({
1818
setup(props: CodeReviewProps, ctx: SetupContext) {
1919
const ns = useNamespace('code-review');
2020
const { diffType } = toRefs(props);
21-
const { renderHtml, reviewContentRef, diffFile, onContentClick } = useCodeReview(props, ctx);
22-
const { isFold, toggleFold } = useCodeReviewFold(props, ctx);
21+
const reviewContentRef = ref();
2322
const {
2423
commentLeft,
2524
commentTop,
@@ -28,16 +27,18 @@ export default defineComponent({
2827
onCommentIconClick,
2928
insertComment,
3029
removeComment,
31-
updateCheckedLineClass,
3230
clearCheckedLines,
31+
updateLineNumberMap,
32+
updateCheckedLine,
3333
} = useCodeReviewComment(reviewContentRef, props, ctx);
34+
const { renderHtml, diffFile, onContentClick } = useCodeReview(props, ctx, reviewContentRef, updateLineNumberMap, updateCheckedLine);
35+
const { isFold, toggleFold } = useCodeReviewFold(props, ctx);
3436

3537
onMounted(() => {
3638
ctx.emit('afterViewInit', {
3739
toggleFold,
3840
insertComment,
3941
removeComment,
40-
updateCheckedLineClass,
4142
clearCheckedLines,
4243
});
4344
});
Lines changed: 30 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { ref, toRefs, onUnmounted, watch } from 'vue';
1+
import { ref, toRefs, onUnmounted } from 'vue';
22
import type { SetupContext, Ref } from 'vue';
33
import { useCodeReviewLineSelection } from './use-code-review-line-selection';
4-
import type { LineSide, CodeReviewProps } from '../code-review-types';
4+
import type { LineSide, CodeReviewProps, ICheckedLineDetails } from '../code-review-types';
55
import { useNamespace } from '../../../shared/hooks/use-namespace';
66
import {
77
notEmptyNode,
@@ -14,28 +14,18 @@ import {
1414
export function useCodeReviewComment(reviewContentRef: Ref<HTMLElement>, props: CodeReviewProps, ctx: SetupContext) {
1515
const { outputFormat, allowComment, allowChecked } = toRefs(props);
1616
const ns = useNamespace('code-review');
17-
const { onMousedown } = useCodeReviewLineSelection(reviewContentRef, props, updateLineNumbers, afterCheckLines);
17+
const { onMousedown, updateLineNumberMap, getCheckedLineDetails, clearCommentClass, updateCheckedLine } = useCodeReviewLineSelection(
18+
reviewContentRef,
19+
props,
20+
afterMouseup
21+
);
1822
const commentLeft = ref(-100);
1923
const commentTop = ref(-100);
2024
let currentLeftLineNumber = -1;
2125
let currentRightLineNumber = -1;
26+
let currentPosition: 'left' | 'right';
2227
let lastLineNumberContainer: HTMLElement | null;
23-
let checkedLineNumberContainer: Array<Element> = [];
24-
let currentLeftLineNumbers: Array<number> = [];
25-
let currentRightLineNumbers: Array<number> = [];
26-
let checkedLineCodeString: Array<string> | Record<string, Array<string>> = {};
27-
let allTrNodes: NodeListOf<Element> = [];
28-
let afterCheckLinesEmitData: Record<string, any>;
29-
watch(
30-
() => outputFormat.value,
31-
() => {
32-
// 如果出现单栏双栏切换则需要重置选中
33-
checkedLineNumberContainer = [];
34-
currentLeftLineNumbers = [];
35-
currentRightLineNumbers = [];
36-
checkedLineCodeString = [];
37-
}
38-
);
28+
3929
const resetLeftTop = () => {
4030
commentLeft.value = -100;
4131
commentTop.value = -100;
@@ -85,6 +75,8 @@ export function useCodeReviewComment(reviewContentRef: Ref<HTMLElement>, props:
8575
commentLeft.value = left;
8676
commentTop.value = top;
8777
currentLeftLineNumber = parseInt(leftLineNumberContainer.innerText);
78+
currentRightLineNumber = parseInt(rightLineNumberContainer.innerText || '-1');
79+
currentPosition = 'left';
8880
} else {
8981
resetLeftTop();
9082
}
@@ -98,7 +90,9 @@ export function useCodeReviewComment(reviewContentRef: Ref<HTMLElement>, props:
9890
const { top, left } = rightLineNumberContainer.getBoundingClientRect();
9991
commentLeft.value = left;
10092
commentTop.value = top;
93+
currentLeftLineNumber = parseInt(leftLineNumberContainer.innerText || '-1');
10194
currentRightLineNumber = parseInt(rightLineNumberContainer.innerText);
95+
currentPosition = 'right';
10296
} else {
10397
resetLeftTop();
10498
}
@@ -117,168 +111,27 @@ export function useCodeReviewComment(reviewContentRef: Ref<HTMLElement>, props:
117111
resetLeftTop();
118112
}
119113
};
120-
// 获代码行 取值方法
121-
const getLineNumbers = (currentNumber: number, currentNumbers: Array<number>, moveDirection: 'up' | 'down') => {
122-
if (currentNumber === -1) {
123-
// 当前行没数据不代表之前选中的没数据,此时返回原来的
124-
return currentNumbers;
125-
}
126-
if (currentNumbers.length === 0) {
127-
return [currentNumber];
128-
}
129-
const numbers = [...currentNumbers];
130-
let max = Math.max(...numbers);
131-
let min = Math.min(...numbers);
132-
if (moveDirection === 'down') {
133-
max = currentNumber;
134-
}
135-
if (moveDirection === 'up') {
136-
min = currentNumber;
137-
}
138-
return Array.from({ length: max - min + 1 }, (_, i) => i + min);
139-
};
140-
// 获取一些公共类和判断
141-
const getCommonClassAndJudge = () => {
142-
const checkedLine = [currentLeftLineNumbers, currentRightLineNumbers];
143-
return {
144-
linenumberDom: allTrNodes,
145-
checkedLine,
146-
};
147-
};
148-
// 之前每次都先移出所有选中的方法过于浪费性能,增加具体dom节点选中方法(防重复添加)
149-
const addCommentCheckedClass = (Dom: Element) => {
150-
!Dom.classList.contains('comment-checked') && Dom.classList.add('comment-checked');
151-
};
152-
// 单栏
153-
function getSingleCheckedLineCode(shouldRenderClass: boolean) {
154-
const { linenumberDom, checkedLine } = getCommonClassAndJudge();
155-
const checkedCodeContent = [];
156-
for (let i = 0; i < linenumberDom.length; i++) {
157-
const lineNumberDomLeft = linenumberDom[i].children[0];
158-
const lineNumberDomRight = linenumberDom[i].children[1];
159-
if (lineNumberDomLeft || lineNumberDomRight) {
160-
const codeLineNumberLeft = parseInt((lineNumberDomLeft as HTMLElement)?.innerText);
161-
const codeLineNumberRight = parseInt((lineNumberDomRight as HTMLElement)?.innerText);
162-
// 因为存在左边或者右边为空的num所以两边都要循环,但是同一个dom已经过就不需要再赋予
163-
if (checkedLine[0].includes(codeLineNumberLeft) || checkedLine[1].includes(codeLineNumberRight)) {
164-
checkedLineNumberContainer.push(linenumberDom[i]);
165-
// 两个节点之间可能间隔文本节点
166-
const codeNode = linenumberDom[i].nextElementSibling as HTMLElement;
167-
checkedCodeContent.push(codeNode?.innerText);
168-
if (shouldRenderClass) {
169-
addCommentCheckedClass(linenumberDom[i]);
170-
addCommentCheckedClass(codeNode);
171-
}
172-
}
173-
}
174-
}
175-
checkedLineCodeString = checkedCodeContent;
176-
}
177-
// 双栏
178-
function getDoubleCheckedLineCode(shouldRenderClass: boolean) {
179-
const { linenumberDom, checkedLine } = getCommonClassAndJudge();
180-
const checkedCodeContentLeft = [];
181-
const checkedCodeContentRight = [];
182114

183-
function checkedFunc(Dom: Element) {
184-
checkedLineNumberContainer.push(Dom);
185-
const codeNode = Dom.nextElementSibling as HTMLElement;
186-
if (shouldRenderClass) {
187-
addCommentCheckedClass(Dom);
188-
addCommentCheckedClass(codeNode);
189-
}
190-
return codeNode?.innerText;
191-
}
192-
193-
for (let i = 0; i < linenumberDom.length; i++) {
194-
// 左右双栏一起遍历
195-
const codeLineNumber = parseInt(linenumberDom[i]?.innerHTML);
196-
if (linenumberDom[i].classList.contains('d-code-left') && checkedLine[0].includes(codeLineNumber)) {
197-
const lineNumText = checkedFunc(linenumberDom[i]);
198-
checkedCodeContentLeft.push(lineNumText);
199-
continue;
200-
}
201-
if (linenumberDom[i].classList.contains('d-code-right') && checkedLine[1].includes(codeLineNumber)) {
202-
const lineNumText = checkedFunc(linenumberDom[i]);
203-
checkedCodeContentRight.push(lineNumText);
204-
}
205-
}
206-
checkedLineCodeString = { leftCode: checkedCodeContentLeft, rightCode: checkedCodeContentRight };
207-
}
208-
function getCheckedLineCode(shouldRenderClass: boolean) {
209-
if (props.outputFormat === 'line-by-line') {
210-
return getSingleCheckedLineCode(shouldRenderClass);
211-
}
212-
getDoubleCheckedLineCode(shouldRenderClass);
213-
}
214-
function updateLineNumbers(moveDirection: 'up' | 'down') {
215-
currentLeftLineNumbers =
216-
currentLeftLineNumber === -1 ? currentLeftLineNumbers : getLineNumbers(currentLeftLineNumber, currentLeftLineNumbers, moveDirection);
217-
currentRightLineNumbers =
218-
currentRightLineNumber === -1
219-
? currentRightLineNumbers
220-
: getLineNumbers(currentRightLineNumber, currentRightLineNumbers, moveDirection);
221-
getCheckedLineCode(false);
222-
afterCheckLinesEmitData = {
223-
left: currentLeftLineNumber,
224-
right: currentRightLineNumber,
225-
details: {
226-
lefts: currentLeftLineNumbers,
227-
rights: currentRightLineNumbers,
228-
codes: checkedLineCodeString,
229-
},
230-
};
231-
}
232-
const updateCheckedLineClass = () => {
233-
getCheckedLineCode(true);
234-
};
235-
// 还原样式
236-
const resetCommentClass = () => {
237-
for (let i = 0; i < checkedLineNumberContainer.length; i++) {
238-
checkedLineNumberContainer[i].classList.remove('comment-checked');
239-
const codeNode = checkedLineNumberContainer[i].nextElementSibling;
240-
(codeNode as HTMLElement)?.classList.remove('comment-checked');
241-
}
242-
checkedLineNumberContainer = [];
243-
};
244115
// 点击
245116
const commentClick = () => {
246-
interface recordType {
247-
left: number;
248-
right: number;
249-
details?: {
250-
lefts: Array<number>;
251-
rights: Array<number>;
252-
codes: Record<string, Array<string>> | Record<string, Array<number>>;
253-
};
254-
}
255-
let obj: recordType = { left: currentLeftLineNumber, right: currentRightLineNumber };
256-
if ((currentLeftLineNumbers.length >= 1 || currentRightLineNumbers.length >= 1) && allowChecked.value) {
257-
// 选中模式
258-
const maxCurrentLeftLineNumber = currentLeftLineNumbers[currentLeftLineNumbers.length - 1];
259-
const maxCurrentRightLineNumber = currentRightLineNumbers[currentRightLineNumbers.length - 1];
260-
if (maxCurrentLeftLineNumber === currentLeftLineNumber || maxCurrentRightLineNumber === currentRightLineNumber) {
261-
// 点击添加评论图标触发的事件
262-
obj = {
263-
left: currentLeftLineNumber,
264-
right: currentRightLineNumber,
265-
details: {
266-
lefts: currentLeftLineNumbers,
267-
rights: currentRightLineNumbers,
268-
codes: checkedLineCodeString,
269-
},
270-
};
117+
let obj = { left: currentLeftLineNumber, right: currentRightLineNumber, position: currentPosition };
118+
const checkedLineDetails = getCheckedLineDetails();
119+
// 多行选中
120+
if (checkedLineDetails && allowChecked.value) {
121+
const { lefts, rights } = checkedLineDetails;
122+
const maxCheckedLeftLineNumber = lefts[lefts.length - 1];
123+
const maxCheckedRightLineNumber = rights[rights.length - 1];
124+
if (maxCheckedLeftLineNumber === currentLeftLineNumber || maxCheckedRightLineNumber === currentRightLineNumber) {
125+
obj.details = checkedLineDetails;
271126
} else {
272-
currentLeftLineNumbers = [];
273-
currentRightLineNumbers = [];
274-
resetCommentClass();
127+
clearCommentClass();
275128
}
276129
}
277130
// 点击添加评论图标触发的事件
278131
ctx.emit('addComment', obj);
279132
};
280-
function afterCheckLines() {
281-
ctx.emit('afterCheckLines', afterCheckLinesEmitData);
133+
function afterMouseup(details: ICheckedLineDetails) {
134+
ctx.emit('afterCheckLines', { left: currentLeftLineNumber, right: currentRightLineNumber, position: currentPosition, details });
282135
}
283136
// 图标或者单行的点击
284137
const onCommentIconClick = (e: Event) => {
@@ -335,16 +188,7 @@ export function useCodeReviewComment(reviewContentRef: Ref<HTMLElement>, props:
335188
};
336189

337190
const clearCheckedLines = () => {
338-
currentLeftLineNumbers = [];
339-
currentRightLineNumbers = [];
340-
checkedLineCodeString = [];
341-
resetCommentClass();
342-
};
343-
344-
const handleMouseDown = (e: MouseEvent) => {
345-
const lineClassName = props.outputFormat === 'line-by-line' ? '.d2h-code-linenumber' : '.d2h-code-side-linenumber';
346-
allTrNodes = reviewContentRef.value.querySelectorAll(lineClassName);
347-
onMousedown(e);
191+
clearCommentClass();
348192
};
349193

350194
const mouseEvent: Record<string, (e: MouseEvent) => void> = {};
@@ -353,7 +197,7 @@ export function useCodeReviewComment(reviewContentRef: Ref<HTMLElement>, props:
353197
mouseEvent.onMouseleave = onMouseleave;
354198
}
355199
if (props.allowChecked) {
356-
mouseEvent.onMousedown = handleMouseDown;
200+
mouseEvent.onMousedown = onMousedown;
357201
}
358202

359203
window.addEventListener('scroll', resetLeftTop);
@@ -366,11 +210,12 @@ export function useCodeReviewComment(reviewContentRef: Ref<HTMLElement>, props:
366210
commentLeft,
367211
commentTop,
368212
mouseEvent,
369-
updateCheckedLineClass,
370213
clearCheckedLines,
371214
onCommentMouseLeave,
372215
onCommentIconClick,
373216
insertComment,
374217
removeComment,
218+
updateLineNumberMap,
219+
updateCheckedLine,
375220
};
376-
}
221+
}

packages/devui-vue/devui/code-review/src/composables/use-code-review-expand.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { toRefs } from 'vue';
22
import type { Ref } from 'vue';
3-
import type { CodeReviewProps, ExpandDirection } from '../code-review-types';
3+
import type { CodeReviewProps, ExpandDirection, IExpandLineNumberInfo } from '../code-review-types';
44
import { ExpandLineReg, FirstLineReg } from '../const';
55
import {
66
attachExpandUpDownButton,
@@ -14,7 +14,12 @@ import {
1414
ifRemoveExpandLineForDoubleColumn,
1515
} from '../utils';
1616

17-
export function useCodeReviewExpand(reviewContentRef: Ref<HTMLElement>, props: CodeReviewProps) {
17+
export function useCodeReviewExpand(
18+
reviewContentRef: Ref<HTMLElement>,
19+
props: CodeReviewProps,
20+
updateLineNumberMap: (expandLineNumberInfo: IExpandLineNumberInfo, newCode: string, direction: 'up' | 'down') => void,
21+
updateCheckedLine: (expandLineNumberInfo: IExpandLineNumberInfo, direction: 'up' | 'down') => void
22+
) {
1823
const { outputFormat, expandThreshold, expandLoader } = toRefs(props);
1924

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

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

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

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

0 commit comments

Comments
 (0)