gaoluyang
5 天以前 c7566bba45e6f90594d36ec4b80ac4ff89f577ee
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
// 扫描源码 src 下所有 .vue/.js 的三方 import,列出目标工程 package.json 里没有的包。
// 一次性用途:避免在阶段3逐模块移植时反复被“依赖没装”打断构建。
import { readdirSync, readFileSync, statSync } from 'node:fs'
import path from 'node:path'
 
const SRC = 'D:/beforeProject/lims/lims-ruoyi-before/src'
const TARGET_PKG = 'D:/beforeProject/lims/lims-vue3/package.json'
const SRC_PKG = 'D:/beforeProject/lims/lims-ruoyi-before/package.json'
 
const tgt = JSON.parse(readFileSync(TARGET_PKG, 'utf8'))
const src = JSON.parse(readFileSync(SRC_PKG, 'utf8'))
const tgtDeps = { ...tgt.dependencies, ...tgt.devDependencies }
const srcDeps = { ...src.dependencies, ...src.devDependencies }
 
function* walk(dir) {
  for (const name of readdirSync(dir)) {
    const p = path.join(dir, name)
    if (statSync(p).isDirectory()) yield* walk(p)
    else if (/\.(vue|js|mjs)$/.test(name)) yield p
  }
}
 
function pkgOf(spec) {
  if (!spec) return null
  if (spec.startsWith('.') || spec.startsWith('/') || spec.startsWith('@/') || spec.startsWith('~')) return null
  if (!/^[@a-zA-Z]/.test(spec)) return null
  const parts = spec.split('/')
  return spec.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0]
}
 
const RE = /(?:^|[^\w.])(?:import\s+(?:[\s\S]*?\sfrom\s+)?|export\s+[\s\S]*?\sfrom\s+|require\()\s*['"]([^'"]+)['"]/g
const use = new Map() // pkg -> Set(files)
 
for (const file of walk(SRC)) {
  const text = readFileSync(file, 'utf8')
  let m
  RE.lastIndex = 0
  while ((m = RE.exec(text))) {
    const pkg = pkgOf(m[1])
    if (!pkg) continue
    if (pkg === 'vue' || pkg === 'vue-router' || pkg === 'vuex' || pkg === 'pinia') continue
    if (!use.has(pkg)) use.set(pkg, new Set())
    use.get(pkg).add(path.relative(SRC, file).replace(/\\/g, '/'))
  }
}
 
const missing = []
const present = []
for (const [pkg, files] of [...use].sort()) {
  if (tgtDeps[pkg]) present.push([pkg, tgtDeps[pkg], srcDeps[pkg] || '-', files.size])
  else missing.push([pkg, srcDeps[pkg] || '未在源码 package.json 声明', files.size, [...files].slice(0, 3)])
}
 
console.log('=== 目标工程缺失的包(' + missing.length + ')===')
for (const [pkg, sv, n, sample] of missing) {
  console.log(`  ${pkg.padEnd(30)} src=${String(sv).padEnd(10)} 引用文件数=${n}  例:${sample.join(', ')}`)
}
console.log('\n=== 已有(' + present.length + ')===')
for (const [pkg, tv, sv, n] of present) {
  const flag = sv !== '-' && sv.replace(/[\^~]/g, '') !== String(tv).replace(/[\^~]/g, '') ? '  ← 版本不同' : ''
  console.log(`  ${pkg.padEnd(30)} tgt=${String(tv).padEnd(12)} src=${String(sv).padEnd(12)} 文件数=${n}${flag}`)
}