吉安感知网项目-前端
罗广辉
2026-01-06 457ec00abf3dbc49fca614a4e0a2ea122f7fad3f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
 
const fs = require('fs');
const path = require('path');
 
const targetDir = path.resolve('e:\\AllWorkProject\\drone_project\\ztzf-drone-web\\applications\\command-center-dashboard\\src\\views\\newRoutePlan');
 
function getAllFiles(dirPath, arrayOfFiles) {
  const files = fs.readdirSync(dirPath);
  arrayOfFiles = arrayOfFiles || [];
 
  files.forEach(function(file) {
    if (fs.statSync(dirPath + "/" + file).isDirectory()) {
      arrayOfFiles = getAllFiles(dirPath + "/" + file, arrayOfFiles);
    } else {
      if (file.endsWith('.vue') || file.endsWith('.js')) {
        arrayOfFiles.push(path.join(dirPath, "/", file));
      }
    }
  });
 
  return arrayOfFiles;
}
 
function extractFunctions(content, filePath) {
  const functions = [];
  // Regex is not perfect, but good enough for finding standard definitions
  // 1. function name(...) {
  // 2. const name = (...) => {
  // 3. const name = function(...) {
 
  // We will iterate through the file to find function starts, then balance braces.
  
  // Simple tokenizer-like approach
  let index = 0;
  const len = content.length;
 
  while (index < len) {
    // Find 'function' or 'const/let/var'
    const sub = content.substring(index);
    
    // Match function definition: function name (...)
    const funcMatch = sub.match(/^(async\s+)?function\s+([a-zA-Z0-9_$]+)\s*\(/);
    
    // Match arrow/expression: (const|let|var) name = ...
    const varMatch = sub.match(/^(const|let|var)\s+([a-zA-Z0-9_$]+)\s*=\s*/);
 
    if (funcMatch) {
      const name = funcMatch[2];
      const startBody = content.indexOf('{', index + funcMatch[0].length);
      if (startBody !== -1) {
        const body = extractBody(content, startBody);
        if (body) {
          functions.push({ name, body, filePath });
          index = startBody + body.length;
          continue;
        }
      }
    } else if (varMatch) {
      const name = varMatch[2];
      // Check if it's a function assignment
      const afterVar = index + varMatch[0].length;
      const subAfter = content.substring(afterVar);
      
      // Look for function(...) or (...) => or async ...
      // This is tricky with regex. 
      // Let's simplified: if we see 'function' or '=>' closely after.
      
      // Heuristic: Check next 100 chars for 'function' or '=>'
      const checkLimit = Math.min(subAfter.length, 200);
      const checkChunk = subAfter.substring(0, checkLimit);
      
      let isFunc = false;
      let bodyStartSearchIndex = afterVar;
      
      if (checkChunk.match(/^\s*(async\s+)?function/)) {
        isFunc = true;
      } else if (checkChunk.match(/^\s*(async\s+)?\(.*?\)\s*=>/)) {
        isFunc = true;
      } else if (checkChunk.match(/^\s*[a-zA-Z0-9_$]+\s*=>/)) { // single arg arrow
         isFunc = true;
      }
 
      if (isFunc) {
        const startBody = content.indexOf('{', afterVar);
        // Ensure the { is part of the function (not perfect but heuristic)
        if (startBody !== -1 && startBody - afterVar < 200) {
           const body = extractBody(content, startBody);
           if (body) {
             functions.push({ name, body, filePath });
             index = startBody + body.length;
             continue;
           }
        }
      }
    }
 
    index++;
  }
  return functions;
}
 
function extractBody(content, startIndex) {
  let braceCount = 0;
  let inString = false;
  let stringChar = '';
  let inComment = false; // Simplified, doesn't handle block comments perfectly
  
  for (let i = startIndex; i < content.length; i++) {
    const char = content[i];
    
    if (char === '{') {
      if (!inString) braceCount++;
    } else if (char === '}') {
      if (!inString) {
        braceCount--;
        if (braceCount === 0) {
          return content.substring(startIndex, i + 1);
        }
      }
    }
    // Handle strings/comments loosely to avoid breaking on braces inside them
    // This is a basic parser, might fail on edge cases
  }
  return null;
}
 
const files = getAllFiles(targetDir);
const allFunctions = [];
 
files.forEach(file => {
  const content = fs.readFileSync(file, 'utf8');
  const funcs = extractFunctions(content, file);
  allFunctions.push(...funcs);
});
 
// Find duplicates
// Key: name + normalized_body
const map = new Map();
 
allFunctions.forEach(f => {
  // Normalize body: remove all whitespace
  const normBody = f.body.replace(/\s/g, '');
  const key = f.name + '|||' + normBody;
  
  if (!map.has(key)) {
    map.set(key, []);
  }
  map.get(key).push(f.filePath);
});
 
console.log("Checking for duplicates...");
let found = false;
map.forEach((paths, key) => {
  if (paths.length > 1) {
    // Check if paths are actually different (ignore same file if scanned twice? No, unique files)
    // Actually user wants "identical name, identical body".
    // Check if the file paths are distinct
    const uniquePaths = [...new Set(paths)];
    
    if (uniquePaths.length > 1) {
        const name = key.split('|||')[0];
        if (name && name !== 'setup' && name !== 'data') { // Ignore common Vue boilerplate if any
             console.log(`\nDuplicate Function: ${name}`);
             uniquePaths.forEach(p => console.log(`  - ${p}`));
             found = true;
        }
    }
  }
});
 
if (!found) {
    console.log("No duplicates found.");
}