mirror of
https://github.com/hpd840321/starRiverProperty.git
synced 2026-06-09 16:30:29 +08:00
7b2bd307f1
- backend/: 13 Maven modules (cw-elevator-application, cloudwalk-cloud, intelligent-cwoscomponent, ninca-crk, etc.) - frontend/: 4 Vue projects (elevator-front, cwos-portal, alarm-front, front_acs) + decompiled + scripts - scripts/: build, test-env, tools (Docker Compose, service templates, API parity) - docs/: AGENTS.md, superpowers specs, architecture docs - .gitignore: standard Java/Maven exclusions Moved from legacy maven-*/ root layout to backend/ organized structure.
1350 lines
37 KiB
Markdown
1350 lines
37 KiB
Markdown
# Frontend-Source 反编译与重建实施计划
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
||
**Goal:** 创建 `frontend-source/` 目录,将 28 个 Vue 2 + Element UI dist 产物反编译为可读源码(阶段 1),并重建 4 个核心应用为可构建工程(阶段 2)。
|
||
|
||
**Architecture:** 四步工具链(解包→格式化→AST分析→组织),先跑通 cwos-portal 验证流程,再批量处理其余 27 个。核心 4 个应用用 Vue 2 + Element UI 脚手架重建。
|
||
|
||
**Tech Stack:** Node.js 18+, `@babel/parser`, `js-beautify`, `prettier`, `webpack-bundle-analyzer`, Vue 2.6 + Element UI 2.15 + Vue CLI 4.5
|
||
|
||
**关联 Spec:** `docs/superpowers/specs/2026-04-29-frontend-source-design.md`
|
||
|
||
---
|
||
|
||
## 前置准备
|
||
|
||
### Task 0: 环境准备与目录初始化
|
||
|
||
- [ ] **Step 1: 创建目录结构**
|
||
|
||
```bash
|
||
mkdir -p frontend-source/decompiled
|
||
mkdir -p frontend-source/projects
|
||
mkdir -p frontend-source/scripts
|
||
```
|
||
|
||
- [ ] **Step 2: 创建 .gitignore**
|
||
|
||
写入 `frontend-source/.gitignore`:
|
||
```
|
||
**/node_modules/
|
||
**/dist/
|
||
**/.cache/
|
||
```
|
||
|
||
- [ ] **Step 3: 初始化脚本 package.json**
|
||
|
||
写入 `frontend-source/scripts/package.json`:
|
||
```json
|
||
{
|
||
"name": "frontend-source-tools",
|
||
"private": true,
|
||
"scripts": {
|
||
"unpack": "node unpack-webpack.js",
|
||
"extract-api": "node extract-api-calls.js",
|
||
"extract-router": "node extract-router.js",
|
||
"beautify": "bash beautify-all.sh",
|
||
"compare": "bash compare-output.sh"
|
||
},
|
||
"dependencies": {
|
||
"@babel/parser": "^7.24.0",
|
||
"@babel/traverse": "^7.24.0",
|
||
"@babel/types": "^7.24.0",
|
||
"js-beautify": "^1.15.0",
|
||
"prettier": "^3.2.0"
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 4: 安装依赖**
|
||
|
||
```bash
|
||
cd frontend-source/scripts && npm install
|
||
```
|
||
|
||
- [ ] **Step 5: 将 frontend-source/ 加入根 .gitignore 白名单**
|
||
|
||
在 `/media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/.gitignore` 末尾添加:
|
||
```
|
||
!/frontend-source/
|
||
!/frontend-source/**
|
||
```
|
||
|
||
- [ ] **Step 6: Commit**
|
||
|
||
```bash
|
||
git add frontend-source/ .gitignore
|
||
git commit -m "chore: init frontend-source directory with tooling scaffold"
|
||
```
|
||
|
||
---
|
||
|
||
## 阶段 1:工具脚本开发
|
||
|
||
### Task 1: webpack bundle 解包脚本
|
||
|
||
**Files:**
|
||
- Create: `frontend-source/scripts/unpack-webpack.js`
|
||
|
||
- [ ] **Step 1: 编写解包脚本**
|
||
|
||
```javascript
|
||
#!/usr/bin/env node
|
||
/**
|
||
* webpack bundle 解包器
|
||
* 识别 __webpack_modules__ 结构,按模块 ID 拆分为独立文件
|
||
*
|
||
* 用法: node unpack-webpack.js <bundle.js> <output-dir>
|
||
*/
|
||
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
function unpackWebpackBundle(bundlePath, outputDir) {
|
||
const code = fs.readFileSync(bundlePath, 'utf-8');
|
||
|
||
// 检测 webpack 版本并提取模块对象
|
||
let modules = null;
|
||
|
||
// 模式1: __webpack_modules__ = { 123: function(module, exports, __webpack_require__) {...}, ... }
|
||
const modulesAssignMatch = code.match(/__webpack_modules__\s*=\s*(\{[\s\S]*?\});/);
|
||
// 模式2: (function(modules) { ... })({ 123: function(...) {...}, ... })
|
||
const iifeMatch = code.match(/\(function\(\s*\w+\s*\)\s*\{[\s\S]*?\}\s*\)\s*\(\s*(\{[\s\S]*?\})\s*\)\s*;/);
|
||
|
||
if (modulesAssignMatch) {
|
||
modules = eval('(' + modulesAssignMatch[1] + ')');
|
||
} else if (iifeMatch) {
|
||
modules = eval('(' + iifeMatch[1] + ')');
|
||
} else {
|
||
console.error('未识别到 webpack 模块结构,尝试按 function(module, exports, __webpack_require__) 正则提取');
|
||
modules = extractByRegex(code);
|
||
}
|
||
|
||
if (!modules || Object.keys(modules).length === 0) {
|
||
console.error('未能提取任何模块');
|
||
process.exit(1);
|
||
}
|
||
|
||
fs.mkdirSync(outputDir, { recursive: true });
|
||
|
||
let count = 0;
|
||
for (const [id, factory] of Object.entries(modules)) {
|
||
const moduleCode = typeof factory === 'function'
|
||
? factory.toString()
|
||
: JSON.stringify(factory, null, 2);
|
||
|
||
const safeId = String(id).replace(/[^a-zA-Z0-9_-]/g, '_');
|
||
fs.writeFileSync(path.join(outputDir, `module_${safeId}.js`), moduleCode);
|
||
count++;
|
||
}
|
||
|
||
console.log(`拆解完成: ${count} 个模块 → ${outputDir}`);
|
||
return count;
|
||
}
|
||
|
||
function extractByRegex(code) {
|
||
const modules = {};
|
||
// 匹配 function(e,t,n){...} 模式 (压缩后的 webpack 模块)
|
||
const re = /(\d+):\s*function\s*\(\s*\w+\s*,\s*\w+\s*,\s*\w+\s*\)\s*\{/g;
|
||
const idRe = /(\d+):\s*function\s*\(\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\)\s*\{/;
|
||
|
||
let match;
|
||
let lastIndex = 0;
|
||
const matches = [];
|
||
|
||
while ((match = re.exec(code)) !== null) {
|
||
matches.push({ id: match[1], start: match.index });
|
||
}
|
||
|
||
for (let i = 0; i < matches.length; i++) {
|
||
const current = matches[i];
|
||
const next = matches[i + 1];
|
||
const startIdx = current.start;
|
||
const endIdx = next ? next.start : code.length;
|
||
|
||
// 找到匹配的闭合大括号
|
||
let depth = 1;
|
||
let pos = startIdx + current[0].length;
|
||
while (depth > 0 && pos < endIdx) {
|
||
if (code[pos] === '{') depth++;
|
||
if (code[pos] === '}') depth--;
|
||
pos++;
|
||
}
|
||
|
||
const funcBody = code.substring(startIdx, pos);
|
||
modules[current.id] = funcBody;
|
||
}
|
||
|
||
return modules;
|
||
}
|
||
|
||
// CLI
|
||
const args = process.argv.slice(2);
|
||
if (args.length < 2) {
|
||
console.log('用法: node unpack-webpack.js <bundle.js> <output-dir>');
|
||
process.exit(1);
|
||
}
|
||
|
||
unpackWebpackBundle(args[0], args[1]);
|
||
```
|
||
|
||
- [ ] **Step 2: 对 cwos-portal 进行解包测试**
|
||
|
||
```bash
|
||
cd frontend-source/scripts
|
||
node unpack-webpack.js ../frontend/cwos-portal/static/js/app.32c5fb6ab7ff973ea14d.js /tmp/cwos-portal-unpack-test
|
||
```
|
||
|
||
- [ ] **Step 3: 验证输出**
|
||
|
||
```bash
|
||
ls /tmp/cwos-portal-unpack-test/ | wc -l
|
||
# 预期: > 10 个模块文件
|
||
head -5 /tmp/cwos-portal-unpack-test/module_*.js
|
||
```
|
||
|
||
- [ ] **Step 4: Commit**
|
||
|
||
```bash
|
||
git add frontend-source/scripts/unpack-webpack.js
|
||
git commit -m "feat: add webpack bundle unpacker script"
|
||
```
|
||
|
||
### Task 2: 批量格式化脚本
|
||
|
||
**Files:**
|
||
- Create: `frontend-source/scripts/beautify-all.sh`
|
||
|
||
- [ ] **Step 1: 编写格式化脚本**
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
# 用法: bash beautify-all.sh <input-dir> <output-dir>
|
||
|
||
INPUT_DIR="${1:-.}"
|
||
OUTPUT_DIR="${2:-./formatted}"
|
||
|
||
mkdir -p "$OUTPUT_DIR"
|
||
|
||
count=0
|
||
for file in "$INPUT_DIR"/*.js; do
|
||
base=$(basename "$file")
|
||
output="$OUTPUT_DIR/${base%.js}.formatted.js"
|
||
|
||
# 先用 js-beautify 还原缩进和换行
|
||
npx js-beautify "$file" \
|
||
--indent-size 2 \
|
||
--brace-style collapse \
|
||
--wrap-line-length 120 \
|
||
> "$output.tmp" 2>/dev/null
|
||
|
||
# 再用 prettier 统一风格
|
||
npx prettier --write "$output.tmp" \
|
||
--parser babel \
|
||
--print-width 120 \
|
||
--tab-width 2 \
|
||
--single-quote true \
|
||
--trailing-comma es5 \
|
||
2>/dev/null
|
||
|
||
mv "$output.tmp" "$output"
|
||
count=$((count + 1))
|
||
echo "格式化: $base → $(basename "$output")"
|
||
done
|
||
|
||
echo "完成: $count 个文件已格式化"
|
||
```
|
||
|
||
- [ ] **Step 2: 测试格式化**
|
||
|
||
```bash
|
||
cd frontend-source/scripts
|
||
bash beautify-all.sh /tmp/cwos-portal-unpack-test /tmp/cwos-portal-formatted-test
|
||
head -30 /tmp/cwos-portal-formatted-test/module_*.formatted.js | head -30
|
||
```
|
||
|
||
- [ ] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add frontend-source/scripts/beautify-all.sh
|
||
git commit -m "feat: add batch beautifier script"
|
||
```
|
||
|
||
### Task 3: API 调用提取器
|
||
|
||
**Files:**
|
||
- Create: `frontend-source/scripts/extract-api-calls.js`
|
||
|
||
- [ ] **Step 1: 编写提取脚本**
|
||
|
||
```javascript
|
||
#!/usr/bin/env node
|
||
/**
|
||
* API 调用提取器
|
||
* 从格式化后的 JS 中提取 HTTP 请求模式,输出 API 清单 JSON
|
||
*
|
||
* 用法: node extract-api-calls.js <formatted-dir> <output.json>
|
||
*/
|
||
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const parser = require('@babel/parser');
|
||
const traverse = require('@babel/traverse').default;
|
||
|
||
function extractApiCalls(inputDir, outputFile) {
|
||
const apiCalls = [];
|
||
const files = fs.readdirSync(inputDir).filter(f => f.endsWith('.formatted.js'));
|
||
|
||
for (const file of files) {
|
||
const code = fs.readFileSync(path.join(inputDir, file), 'utf-8');
|
||
|
||
try {
|
||
const ast = parser.parse(code, {
|
||
sourceType: 'script',
|
||
plugins: ['jsx', 'typescript', 'classProperties', 'dynamicImport'],
|
||
errorRecovery: true,
|
||
});
|
||
|
||
traverse(ast, {
|
||
// 匹配: axios.get('/api/xxx')
|
||
// 匹配: axios.post('/api/xxx', data)
|
||
// 匹配: this.$http.get('/api/xxx')
|
||
CallExpression(nodePath) {
|
||
const node = nodePath.node;
|
||
const callee = node.callee;
|
||
|
||
// axios.get|post|put|delete|patch
|
||
if (
|
||
callee.type === 'MemberExpression' &&
|
||
callee.object.type === 'Identifier' &&
|
||
(callee.object.name === 'axios' || callee.object.name === 'http')
|
||
) {
|
||
const method = callee.property.name;
|
||
if (['get', 'post', 'put', 'delete', 'patch'].includes(method)) {
|
||
const url = node.arguments[0];
|
||
if (url && url.type === 'StringLiteral') {
|
||
apiCalls.push({
|
||
file: file,
|
||
method: method.toUpperCase(),
|
||
url: url.value,
|
||
hasBody: method !== 'get' && node.arguments.length > 1,
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
// this.$http.get|post
|
||
if (
|
||
callee.type === 'MemberExpression' &&
|
||
callee.object.type === 'MemberExpression' &&
|
||
callee.object.property.name === '$http'
|
||
) {
|
||
const method = callee.property.name;
|
||
const url = node.arguments[0];
|
||
if (url && url.type === 'StringLiteral') {
|
||
apiCalls.push({
|
||
file: file,
|
||
method: method.toUpperCase(),
|
||
url: url.value,
|
||
via: '$http',
|
||
});
|
||
}
|
||
}
|
||
},
|
||
|
||
// 匹配字符串常量中的 API 路径
|
||
StringLiteral(nodePath) {
|
||
const value = nodePath.node.value;
|
||
if (typeof value === 'string' && value.startsWith('/api/') && value.length > 5) {
|
||
// 避免重复捕获(CallExpression 已处理)
|
||
const parent = nodePath.parent;
|
||
if (parent.type === 'CallExpression') return;
|
||
|
||
apiCalls.push({
|
||
file: file,
|
||
method: 'REFERENCE',
|
||
url: value,
|
||
});
|
||
}
|
||
},
|
||
});
|
||
} catch (e) {
|
||
console.error(`解析失败: ${file} — ${e.message}`);
|
||
}
|
||
}
|
||
|
||
// 去重 + 排序
|
||
const unique = {};
|
||
apiCalls.forEach(call => {
|
||
const key = `${call.method} ${call.url}`;
|
||
if (!unique[key]) {
|
||
unique[key] = call;
|
||
}
|
||
});
|
||
|
||
const result = Object.values(unique).sort((a, b) => a.url.localeCompare(b.url));
|
||
|
||
fs.writeFileSync(outputFile, JSON.stringify(result, null, 2));
|
||
console.log(`提取完成: ${result.length} 个 API 端点 → ${outputFile}`);
|
||
|
||
// 同时生成 Markdown 清单
|
||
const mdPath = outputFile.replace('.json', '.md');
|
||
let md = '# API 端点清单\n\n';
|
||
md += `| Method | URL | 来源文件 |\n`;
|
||
md += `|--------|-----|----------|\n`;
|
||
result.forEach(call => {
|
||
md += `| ${call.method} | \`${call.url}\` | ${call.file} |\n`;
|
||
});
|
||
fs.writeFileSync(mdPath, md);
|
||
console.log(`Markdown 清单: ${mdPath}`);
|
||
}
|
||
|
||
const args = process.argv.slice(2);
|
||
if (args.length < 2) {
|
||
console.log('用法: node extract-api-calls.js <formatted-dir> <output.json>');
|
||
process.exit(1);
|
||
}
|
||
|
||
extractApiCalls(args[0], args[1]);
|
||
```
|
||
|
||
- [ ] **Step 2: 测试 API 提取**
|
||
|
||
```bash
|
||
cd frontend-source/scripts
|
||
node extract-api-calls.js /tmp/cwos-portal-formatted-test /tmp/cwos-portal-api.json
|
||
cat /tmp/cwos-portal-api.md | head -30
|
||
```
|
||
|
||
- [ ] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add frontend-source/scripts/extract-api-calls.js
|
||
git commit -m "feat: add API call extractor script"
|
||
```
|
||
|
||
### Task 4: 路由表提取器
|
||
|
||
**Files:**
|
||
- Create: `frontend-source/scripts/extract-router.js`
|
||
|
||
- [ ] **Step 1: 编写提取脚本**
|
||
|
||
```javascript
|
||
#!/usr/bin/env node
|
||
/**
|
||
* 路由表提取器
|
||
* 从格式化后的 JS 中提取 vue-router 的 routes 定义
|
||
*
|
||
* 用法: node extract-router.js <formatted-dir> <output.json>
|
||
*/
|
||
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const parser = require('@babel/parser');
|
||
const traverse = require('@babel/traverse').default;
|
||
|
||
function extractRouter(inputDir, outputFile) {
|
||
const files = fs.readdirSync(inputDir).filter(f => f.endsWith('.formatted.js'));
|
||
const routes = [];
|
||
|
||
for (const file of files) {
|
||
const code = fs.readFileSync(path.join(inputDir, file), 'utf-8');
|
||
|
||
try {
|
||
const ast = parser.parse(code, {
|
||
sourceType: 'script',
|
||
plugins: ['jsx', 'typescript', 'classProperties', 'dynamicImport'],
|
||
errorRecovery: true,
|
||
});
|
||
|
||
traverse(ast, {
|
||
// 匹配 routes: [...] 数组
|
||
ArrayExpression(nodePath) {
|
||
const node = nodePath.node;
|
||
const parent = nodePath.parent;
|
||
|
||
// 检查是否是路由数组 (包含 path 和 component 属性的对象)
|
||
const hasRoutes = node.elements.some(el =>
|
||
el.type === 'ObjectExpression' &&
|
||
el.properties.some(prop => prop.key.name === 'path')
|
||
);
|
||
|
||
if (hasRoutes) {
|
||
node.elements.forEach(el => {
|
||
if (el.type === 'ObjectExpression') {
|
||
const routeDef = {};
|
||
el.properties.forEach(prop => {
|
||
if (prop.key.type === 'Identifier') {
|
||
if (prop.key.name === 'path' && prop.value.type === 'StringLiteral') {
|
||
routeDef.path = prop.value.value;
|
||
}
|
||
if (prop.key.name === 'name' && prop.value.type === 'StringLiteral') {
|
||
routeDef.name = prop.value.value;
|
||
}
|
||
if (prop.key.name === 'meta' && prop.value.type === 'ObjectExpression') {
|
||
routeDef.meta = {};
|
||
prop.value.properties.forEach(mp => {
|
||
if (mp.key.type === 'Identifier') {
|
||
routeDef.meta[mp.key.name] = mp.value.type === 'StringLiteral' ? mp.value.value : true;
|
||
}
|
||
});
|
||
}
|
||
if (prop.key.name === 'component') {
|
||
routeDef.component = prop.value.type === 'ArrowFunctionExpression'
|
||
? 'lazyImport'
|
||
: (prop.value.type === 'Identifier' ? prop.value.name : 'inline');
|
||
}
|
||
}
|
||
});
|
||
|
||
if (routeDef.path && !routes.find(r => r.path === routeDef.path)) {
|
||
routes.push(routeDef);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
},
|
||
|
||
// 匹配字符串中的路径模式 /xxx/xxx
|
||
StringLiteral(nodePath) {
|
||
const value = nodePath.node.value;
|
||
if (typeof value === 'string' && /^\/[a-z][a-z0-9_/-]*$/i.test(value) && value.length > 2) {
|
||
const parent = nodePath.parent;
|
||
if (parent.type === 'ObjectProperty' && parent.key.name === 'path') {
|
||
return; // 已被上面处理
|
||
}
|
||
if (!routes.find(r => r.path === value)) {
|
||
routes.push({ path: value, source: 'stringLiteral', file: file });
|
||
}
|
||
}
|
||
},
|
||
});
|
||
} catch (e) {
|
||
// 跳过解析错误的文件
|
||
}
|
||
}
|
||
|
||
const result = routes.sort((a, b) => (a.path || '').localeCompare(b.path || ''));
|
||
|
||
fs.writeFileSync(outputFile, JSON.stringify(result, null, 2));
|
||
console.log(`提取完成: ${result.length} 条路由 → ${outputFile}`);
|
||
|
||
// 生成 Markdown 路由树
|
||
const mdPath = outputFile.replace('.json', '.md');
|
||
let md = '# 路由表\n\n';
|
||
md += `| Path | Name | Component | Meta |\n`;
|
||
md += `|------|------|-----------|------|\n`;
|
||
result.forEach(r => {
|
||
md += `| \`${r.path || '-'}\` | ${r.name || '-'} | ${r.component || '-'} | ${r.meta ? JSON.stringify(r.meta) : '-'} |\n`;
|
||
});
|
||
fs.writeFileSync(mdPath, md);
|
||
console.log(`路由表 Markdown: ${mdPath}`);
|
||
}
|
||
|
||
const args = process.argv.slice(2);
|
||
if (args.length < 2) {
|
||
console.log('用法: node extract-router.js <formatted-dir> <output.json>');
|
||
process.exit(1);
|
||
}
|
||
|
||
extractRouter(args[0], args[1]);
|
||
```
|
||
|
||
- [ ] **Step 2: 测试路由提取**
|
||
|
||
```bash
|
||
cd frontend-source/scripts
|
||
node extract-router.js /tmp/cwos-portal-formatted-test /tmp/cwos-portal-router.json
|
||
cat /tmp/cwos-portal-router.md
|
||
```
|
||
|
||
- [ ] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add frontend-source/scripts/extract-router.js
|
||
git commit -m "feat: add router table extractor script"
|
||
```
|
||
|
||
---
|
||
|
||
## 阶段 2-A:P0 — cwos-portal 反编译验证
|
||
|
||
### Task 5: cwos-portal 解包与格式化
|
||
|
||
**Files:**
|
||
- Create: `frontend-source/decompiled/cwos-portal/`
|
||
|
||
- [ ] **Step 1: 定位 cwos-portal 的 JS bundle**
|
||
|
||
```bash
|
||
ls -la frontend/cwos-portal/static/js/app.*.js
|
||
ls -la frontend/cwos-portal/static/js/vendor.*.js
|
||
ls -la frontend/cwos-portal/static/js/manifest.*.js
|
||
```
|
||
|
||
- [ ] **Step 2: 解包所有 bundle**
|
||
|
||
```bash
|
||
cd frontend-source/scripts
|
||
mkdir -p /tmp/cwos-portal-raw
|
||
|
||
for js in ../../frontend/cwos-portal/static/js/app.*.js; do
|
||
node unpack-webpack.js "$js" /tmp/cwos-portal-raw
|
||
done
|
||
|
||
for js in ../../frontend/cwos-portal/static/js/vendor.*.js; do
|
||
node unpack-webpack.js "$js" /tmp/cwos-portal-raw
|
||
done
|
||
|
||
ls /tmp/cwos-portal-raw/ | wc -l
|
||
```
|
||
|
||
- [ ] **Step 3: 格式化所有模块**
|
||
|
||
```bash
|
||
cd frontend-source/scripts
|
||
mkdir -p /tmp/cwos-portal-formatted
|
||
bash beautify-all.sh /tmp/cwos-portal-raw /tmp/cwos-portal-formatted
|
||
ls /tmp/cwos-portal-formatted/ | wc -l
|
||
```
|
||
|
||
- [ ] **Step 4: 提取 API 清单**
|
||
|
||
```bash
|
||
cd frontend-source/scripts
|
||
node extract-api-calls.js /tmp/cwos-portal-formatted ../decompiled/cwos-portal/api-calls.json
|
||
```
|
||
|
||
- [ ] **Step 5: 提取路由表**
|
||
|
||
```bash
|
||
cd frontend-source/scripts
|
||
node extract-router.js /tmp/cwos-portal-formatted ../decompiled/cwos-portal/router-tree.json
|
||
```
|
||
|
||
- [ ] **Step 6: 组装到 frontend-source/decompiled/cwos-portal/**
|
||
|
||
```bash
|
||
mkdir -p frontend-source/decompiled/cwos-portal/src/{views,components,api,router}
|
||
mkdir -p frontend-source/decompiled/cwos-portal/static
|
||
|
||
# 复制格式化后的模块
|
||
cp /tmp/cwos-portal-formatted/*.formatted.js frontend-source/decompiled/cwos-portal/src/
|
||
|
||
# 复制原始 static 文件
|
||
cp -r frontend/cwos-portal/static/* frontend-source/decompiled/cwos-portal/static/
|
||
cp frontend/cwos-portal/index.html frontend-source/decompiled/cwos-portal/
|
||
cp frontend/cwos-portal/favicon.ico frontend-source/decompiled/cwos-portal/
|
||
cp frontend/cwos-portal/projectInfo.json frontend-source/decompiled/cwos-portal/
|
||
|
||
# API 和路由已在步骤 4-5 中直接写入
|
||
ls frontend-source/decompiled/cwos-portal/
|
||
```
|
||
|
||
- [ ] **Step 7: 编写 README.md**
|
||
|
||
写入 `frontend-source/decompiled/cwos-portal/README.md`:
|
||
```markdown
|
||
# cwos-portal — 物业管理门户
|
||
|
||
## 来源
|
||
- 原始 dist: `frontend/cwos-portal/`
|
||
- 构建日期: 2022-01-12
|
||
- 技术栈: Vue 2 + Element UI + webpack
|
||
|
||
## API 端点
|
||
详见 [api-calls.md](api-calls.md)
|
||
|
||
## 路由表
|
||
详见 [router-tree.md](router-tree.md)
|
||
|
||
## 目录结构
|
||
- `src/` — 格式化的 JS 模块
|
||
- `static/` — CSS/img/font 原始文件
|
||
- `index.html` — 原始入口
|
||
- `projectInfo.json` — 项目配置
|
||
```
|
||
|
||
- [ ] **Step 8: Commit**
|
||
|
||
```bash
|
||
git add frontend-source/decompiled/cwos-portal/
|
||
git commit -m "feat: add cwos-portal decompiled source (P0 verification)"
|
||
```
|
||
|
||
---
|
||
|
||
## 阶段 2-B:P1 核心应用反编译
|
||
|
||
### Task 6: elevator-front 反编译
|
||
|
||
**Files:**
|
||
- Create: `frontend-source/decompiled/elevator-front/`
|
||
|
||
- [ ] **Step 1: 解包 elevator-front**
|
||
|
||
```bash
|
||
cd frontend-source/scripts
|
||
mkdir -p /tmp/elevator-front-raw /tmp/elevator-front-formatted
|
||
|
||
for js in ../../frontend/elevator-front/js/*.js; do
|
||
node unpack-webpack.js "$js" /tmp/elevator-front-raw
|
||
done
|
||
|
||
bash beautify-all.sh /tmp/elevator-front-raw /tmp/elevator-front-formatted
|
||
node extract-api-calls.js /tmp/elevator-front-formatted ../decompiled/elevator-front/api-calls.json
|
||
node extract-router.js /tmp/elevator-front-formatted ../decompiled/elevator-front/router-tree.json
|
||
```
|
||
|
||
- [ ] **Step 2: 组织文件并复制静态资源**
|
||
|
||
```bash
|
||
mkdir -p frontend-source/decompiled/elevator-front/src
|
||
mkdir -p frontend-source/decompiled/elevator-front/static
|
||
|
||
cp /tmp/elevator-front-formatted/*.formatted.js frontend-source/decompiled/elevator-front/src/
|
||
cp -r frontend/elevator-front/css frontend-source/decompiled/elevator-front/static/
|
||
cp -r frontend/elevator-front/img frontend-source/decompiled/elevator-front/static/
|
||
cp -r frontend/elevator-front/fonts frontend-source/decompiled/elevator-front/static/ 2>/dev/null
|
||
cp frontend/elevator-front/index.html frontend-source/decompiled/elevator-front/
|
||
cp frontend/elevator-front/favicon.ico frontend-source/decompiled/elevator-front/ 2>/dev/null
|
||
```
|
||
|
||
- [ ] **Step 3: 编写 README.md**
|
||
|
||
写入 `frontend-source/decompiled/elevator-front/README.md`:
|
||
```markdown
|
||
# elevator-front — 电梯管理前端
|
||
|
||
## 来源
|
||
- 原始 dist: `frontend/elevator-front/`
|
||
- 构建日期: 2023-10-19
|
||
- 技术栈: Vue 2 + Element UI + webpack
|
||
|
||
详见 [api-calls.md](api-calls.md) 和 [router-tree.md](router-tree.md)
|
||
```
|
||
|
||
- [ ] **Step 4: Commit**
|
||
|
||
```bash
|
||
git add frontend-source/decompiled/elevator-front/
|
||
git commit -m "feat: add elevator-front decompiled source"
|
||
```
|
||
|
||
### Task 7: alarm-front 反编译
|
||
|
||
**Files:**
|
||
- Create: `frontend-source/decompiled/alarm-front/`
|
||
|
||
- [ ] **Step 1: 解包 alarm-front**
|
||
|
||
```bash
|
||
cd frontend-source/scripts
|
||
mkdir -p /tmp/alarm-front-raw /tmp/alarm-front-formatted
|
||
|
||
for js in ../../frontend/alarm-front/js/*.js; do
|
||
node unpack-webpack.js "$js" /tmp/alarm-front-raw
|
||
done
|
||
|
||
bash beautify-all.sh /tmp/alarm-front-raw /tmp/alarm-front-formatted
|
||
node extract-api-calls.js /tmp/alarm-front-formatted ../decompiled/alarm-front/api-calls.json
|
||
node extract-router.js /tmp/alarm-front-formatted ../decompiled/alarm-front/router-tree.json
|
||
```
|
||
|
||
- [ ] **Step 2: 组织文件**
|
||
|
||
```bash
|
||
mkdir -p frontend-source/decompiled/alarm-front/src
|
||
mkdir -p frontend-source/decompiled/alarm-front/static
|
||
|
||
cp /tmp/alarm-front-formatted/*.formatted.js frontend-source/decompiled/alarm-front/src/
|
||
cp -r frontend/alarm-front/css frontend-source/decompiled/alarm-front/static/
|
||
cp -r frontend/alarm-front/img frontend-source/decompiled/alarm-front/static/
|
||
cp -r frontend/alarm-front/fonts frontend-source/decompiled/alarm-front/static/ 2>/dev/null
|
||
cp -r frontend/alarm-front/media frontend-source/decompiled/alarm-front/static/ 2>/dev/null
|
||
cp frontend/alarm-front/index.html frontend-source/decompiled/alarm-front/
|
||
cp frontend/alarm-front/favicon.ico frontend-source/decompiled/alarm-front/ 2>/dev/null
|
||
```
|
||
|
||
- [ ] **Step 3: 编写 README.md**
|
||
|
||
写入 `frontend-source/decompiled/alarm-front/README.md`:
|
||
```markdown
|
||
# alarm-front — 报警管理前端
|
||
|
||
## 来源
|
||
- 原始 dist: `frontend/alarm-front/`
|
||
- 构建日期: 2023-11-09
|
||
- 技术栈: Vue 2 + Element UI + webpack
|
||
|
||
详见 [api-calls.md](api-calls.md) 和 [router-tree.md](router-tree.md)
|
||
```
|
||
|
||
- [ ] **Step 4: Commit**
|
||
|
||
```bash
|
||
git add frontend-source/decompiled/alarm-front/
|
||
git commit -m "feat: add alarm-front decompiled source"
|
||
```
|
||
|
||
### Task 8: front_acs 反编译
|
||
|
||
**Files:**
|
||
- Create: `frontend-source/decompiled/front_acs/`
|
||
|
||
- [ ] **Step 1: 解包 front_acs**
|
||
|
||
```bash
|
||
cd frontend-source/scripts
|
||
mkdir -p /tmp/front-acs-raw /tmp/front-acs-formatted
|
||
|
||
for js in ../../frontend/front_acs/static/js/*.js; do
|
||
node unpack-webpack.js "$js" /tmp/front-acs-raw
|
||
done
|
||
|
||
bash beautify-all.sh /tmp/front-acs-raw /tmp/front-acs-formatted
|
||
node extract-api-calls.js /tmp/front-acs-formatted ../decompiled/front_acs/api-calls.json
|
||
node extract-router.js /tmp/front-acs-formatted ../decompiled/front_acs/router-tree.json
|
||
```
|
||
|
||
- [ ] **Step 2: 组织文件**
|
||
|
||
```bash
|
||
mkdir -p frontend-source/decompiled/front_acs/src
|
||
mkdir -p frontend-source/decompiled/front_acs/static
|
||
|
||
cp /tmp/front-acs-formatted/*.formatted.js frontend-source/decompiled/front_acs/src/
|
||
cp -r frontend/front_acs/static/* frontend-source/decompiled/front_acs/static/
|
||
cp frontend/front_acs/index.html frontend-source/decompiled/front_acs/
|
||
cp frontend/front_acs/favicon.ico frontend-source/decompiled/front_acs/
|
||
cp frontend/front_acs/projectInfo.json frontend-source/decompiled/front_acs/ 2>/dev/null
|
||
```
|
||
|
||
- [ ] **Step 3: 编写 README.md**
|
||
|
||
写入 `frontend-source/decompiled/front_acs/README.md`:
|
||
```markdown
|
||
# front_acs — 门禁管理前端
|
||
|
||
## 来源
|
||
- 原始 dist: `frontend/front_acs/`
|
||
- 构建日期: 2023-12-22
|
||
- 技术栈: Vue 2 + Element UI + webpack
|
||
|
||
详见 [api-calls.md](api-calls.md) 和 [router-tree.md](router-tree.md)
|
||
```
|
||
|
||
- [ ] **Step 4: Commit**
|
||
|
||
```bash
|
||
git add frontend-source/decompiled/front_acs/
|
||
git commit -m "feat: add front_acs decompiled source"
|
||
```
|
||
|
||
---
|
||
|
||
## 阶段 2-C:P2-P3 批量反编译
|
||
|
||
### Task 9: Canoe 系列批量反编译
|
||
|
||
**Files:**
|
||
- Create: `frontend-source/decompiled/canoe-{account,car,device,person,person-h5}/`
|
||
|
||
- [ ] **Step 1: 批量解包脚本**
|
||
|
||
```bash
|
||
cd frontend-source/scripts
|
||
|
||
APPS="canoe-account canoe-car canoe-device canoe-person canoe-person-h5"
|
||
|
||
for app in $APPS; do
|
||
echo "=== 处理: $app ==="
|
||
mkdir -p /tmp/${app}-raw /tmp/${app}-formatted
|
||
|
||
JS_DIR="../../frontend/${app}/js"
|
||
if [ -d "$JS_DIR" ]; then
|
||
for js in "$JS_DIR"/*.js; do
|
||
node unpack-webpack.js "$js" /tmp/${app}-raw
|
||
done
|
||
fi
|
||
|
||
# 部分应用 js 在 static/js/
|
||
STATIC_JS="../../frontend/${app}/static/js"
|
||
if [ -d "$STATIC_JS" ]; then
|
||
for js in "$STATIC_JS"/*.js; do
|
||
node unpack-webpack.js "$js" /tmp/${app}-raw
|
||
done
|
||
fi
|
||
|
||
bash beautify-all.sh /tmp/${app}-raw /tmp/${app}-formatted
|
||
node extract-api-calls.js /tmp/${app}-formatted ../decompiled/${app}/api-calls.json 2>/dev/null
|
||
node extract-router.js /tmp/${app}-formatted ../decompiled/${app}/router-tree.json 2>/dev/null
|
||
|
||
mkdir -p ../decompiled/${app}/src ../decompiled/${app}/static
|
||
cp /tmp/${app}-formatted/*.formatted.js ../decompiled/${app}/src/ 2>/dev/null
|
||
cp -r ../../frontend/${app}/css ../decompiled/${app}/static/ 2>/dev/null
|
||
cp -r ../../frontend/${app}/js ../decompiled/${app}/static/ 2>/dev/null
|
||
cp -r ../../frontend/${app}/img ../decompiled/${app}/static/ 2>/dev/null
|
||
cp -r ../../frontend/${app}/static ../decompiled/${app}/ 2>/dev/null
|
||
cp ../../frontend/${app}/index.html ../decompiled/${app}/ 2>/dev/null
|
||
cp ../../frontend/${app}/favicon.ico ../decompiled/${app}/ 2>/dev/null
|
||
|
||
echo "README: $app" > ../decompiled/${app}/README.md
|
||
echo "" >> ../decompiled/${app}/README.md
|
||
echo "来源: frontend/${app}/" >> ../decompiled/${app}/README.md
|
||
done
|
||
|
||
echo "批量处理完成"
|
||
```
|
||
|
||
- [ ] **Step 2: Commit**
|
||
|
||
```bash
|
||
git add frontend-source/decompiled/canoe-account/ \
|
||
frontend-source/decompiled/canoe-car/ \
|
||
frontend-source/decompiled/canoe-device/ \
|
||
frontend-source/decompiled/canoe-person/ \
|
||
frontend-source/decompiled/canoe-person-h5/
|
||
git commit -m "feat: add Canoe series decompiled sources"
|
||
```
|
||
|
||
### Task 10: 其余 20 个应用批量反编译
|
||
|
||
**Files:**
|
||
- Create: `frontend-source/decompiled/{dashboard-front,homepage,...}/`(20个)
|
||
|
||
- [ ] **Step 1: 批量处理脚本**
|
||
|
||
```bash
|
||
cd frontend-source/scripts
|
||
|
||
# 门禁/电梯辅助应用
|
||
APPS_P2="area-front personFile monitor-front snap-front heat-analysis-portal"
|
||
|
||
# 访客/考勤/会议
|
||
APPS_P2="$APPS_P2 visitorpc visitorh5 conferencepc attendancepc"
|
||
|
||
# 系统辅助
|
||
APPS_P2="$APPS_P2 front_message sysetting-front ninca-engine-service"
|
||
|
||
# Canoe 辅助
|
||
APPS_P2="$APPS_P2 canoe-account canoe-car canoe-device canoe-person"
|
||
|
||
# 其他
|
||
APPS_P2="$APPS_P2 cwos_manager_frontend"
|
||
|
||
for app in $APPS_P2; do
|
||
[ ! -d "../../frontend/${app}" ] && continue
|
||
echo "=== 处理: $app ==="
|
||
|
||
mkdir -p /tmp/${app}-raw /tmp/${app}-formatted
|
||
|
||
for js_dir in "js" "static/js"; do
|
||
if [ -d "../../frontend/${app}/${js_dir}" ]; then
|
||
for js in ../../frontend/${app}/${js_dir}/*.js; do
|
||
node unpack-webpack.js "$js" /tmp/${app}-raw 2>/dev/null
|
||
done
|
||
fi
|
||
done
|
||
|
||
bash beautify-all.sh /tmp/${app}-raw /tmp/${app}-formatted 2>/dev/null
|
||
|
||
mkdir -p ../decompiled/${app}/src ../decompiled/${app}/static
|
||
cp /tmp/${app}-formatted/*.formatted.js ../decompiled/${app}/src/ 2>/dev/null
|
||
cp -r ../../frontend/${app}/static ../decompiled/${app}/ 2>/dev/null
|
||
cp ../../frontend/${app}/index.html ../decompiled/${app}/ 2>/dev/null
|
||
cp ../../frontend/${app}/favicon.ico ../decompiled/${app}/ 2>/dev/null
|
||
|
||
echo "# $app" > ../decompiled/${app}/README.md
|
||
echo "来源: frontend/${app}/" >> ../decompiled/${app}/README.md
|
||
|
||
echo " ✓ $app"
|
||
done
|
||
|
||
echo "全部批量处理完成"
|
||
```
|
||
|
||
- [ ] **Step 2: Commit**
|
||
|
||
```bash
|
||
git add frontend-source/decompiled/
|
||
git commit -m "feat: add remaining 20 apps decompiled sources (bulk)"
|
||
```
|
||
|
||
---
|
||
|
||
## 阶段 3:核心应用 C 级重建
|
||
|
||
### Task 11: cwos-portal 项目脚手架
|
||
|
||
**Files:**
|
||
- Create: `frontend-source/projects/cwos-portal/`
|
||
|
||
- [ ] **Step 1: 手动搭建 Vue 2 项目(不用 vue create)**
|
||
|
||
写入 `frontend-source/projects/cwos-portal/package.json`:
|
||
```json
|
||
{
|
||
"name": "cwos-portal",
|
||
"version": "1.0.0",
|
||
"private": true,
|
||
"scripts": {
|
||
"dev": "vue-cli-service serve",
|
||
"build": "vue-cli-service build",
|
||
"lint": "vue-cli-service lint"
|
||
},
|
||
"dependencies": {
|
||
"axios": "^0.21.4",
|
||
"element-ui": "^2.15.14",
|
||
"vue": "^2.6.14",
|
||
"vue-router": "^3.5.3",
|
||
"vuex": "^3.6.2"
|
||
},
|
||
"devDependencies": {
|
||
"@vue/cli-plugin-babel": "^4.5.19",
|
||
"@vue/cli-plugin-router": "^4.5.19",
|
||
"@vue/cli-plugin-vuex": "^4.5.19",
|
||
"@vue/cli-service": "^4.5.19",
|
||
"vue-template-compiler": "^2.6.14"
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: 创建 vue.config.js**
|
||
|
||
写入 `frontend-source/projects/cwos-portal/vue.config.js`:
|
||
```javascript
|
||
module.exports = {
|
||
publicPath: './',
|
||
outputDir: 'dist',
|
||
assetsDir: 'static',
|
||
productionSourceMap: false,
|
||
devServer: {
|
||
port: 8080,
|
||
proxy: {
|
||
'/api': {
|
||
target: 'http://localhost:8090',
|
||
changeOrigin: true,
|
||
},
|
||
},
|
||
},
|
||
};
|
||
```
|
||
|
||
- [ ] **Step 3: 创建 babel.config.js**
|
||
|
||
写入 `frontend-source/projects/cwos-portal/babel.config.js`:
|
||
```javascript
|
||
module.exports = {
|
||
presets: ['@vue/cli-plugin-babel/preset'],
|
||
};
|
||
```
|
||
|
||
- [ ] **Step 4: 创建入口文件**
|
||
|
||
写入 `frontend-source/projects/cwos-portal/public/index.html`:
|
||
```html
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||
<meta name="renderer" content="webkit">
|
||
<link rel="shortcut icon" href="./favicon.ico">
|
||
<title>物业管理门户</title>
|
||
</head>
|
||
<body>
|
||
<div id="app"></div>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
- [ ] **Step 5: 创建 main.js 和 App.vue**
|
||
|
||
写入 `frontend-source/projects/cwos-portal/src/main.js`:
|
||
```javascript
|
||
import Vue from 'vue';
|
||
import ElementUI from 'element-ui';
|
||
import 'element-ui/lib/theme-chalk/index.css';
|
||
import App from './App.vue';
|
||
import router from './router';
|
||
import store from './store';
|
||
import axios from 'axios';
|
||
|
||
Vue.use(ElementUI);
|
||
Vue.prototype.$http = axios;
|
||
|
||
Vue.config.productionTip = false;
|
||
|
||
new Vue({
|
||
router,
|
||
store,
|
||
render: (h) => h(App),
|
||
}).$mount('#app');
|
||
```
|
||
|
||
写入 `frontend-source/projects/cwos-portal/src/App.vue`:
|
||
```vue
|
||
<template>
|
||
<div id="app">
|
||
<router-view />
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: 'App',
|
||
};
|
||
</script>
|
||
|
||
<style>
|
||
#app {
|
||
height: 100%;
|
||
}
|
||
</style>
|
||
```
|
||
|
||
- [ ] **Step 6: 创建路由和 store 骨架**
|
||
|
||
写入 `frontend-source/projects/cwos-portal/src/router/index.js`:
|
||
```javascript
|
||
import Vue from 'vue';
|
||
import VueRouter from 'vue-router';
|
||
|
||
Vue.use(VueRouter);
|
||
|
||
// 路由从 decompiled/cwos-portal/router-tree.md 提取后填入
|
||
// 参考 router-tree.md 中的路径列表,逐个转换为 route 对象
|
||
// 示例格式:
|
||
// { path: '/dashboard', name: 'Dashboard', component: () => import('@/views/Dashboard.vue') }
|
||
const routes = [];
|
||
|
||
const router = new VueRouter({
|
||
mode: 'hash',
|
||
routes,
|
||
});
|
||
|
||
export default router;
|
||
```
|
||
|
||
写入 `frontend-source/projects/cwos-portal/src/store/index.js`:
|
||
```javascript
|
||
import Vue from 'vue';
|
||
import Vuex from 'vuex';
|
||
|
||
Vue.use(Vuex);
|
||
|
||
export default new Vuex.Store({
|
||
state: {},
|
||
mutations: {},
|
||
actions: {},
|
||
modules: {},
|
||
});
|
||
```
|
||
|
||
- [ ] **Step 7: 创建 API 层骨架**
|
||
|
||
写入 `frontend-source/projects/cwos-portal/src/api/index.js`:
|
||
```javascript
|
||
import axios from 'axios';
|
||
|
||
const api = axios.create({
|
||
baseURL: '/api',
|
||
timeout: 30000,
|
||
});
|
||
|
||
// 请求拦截器
|
||
api.interceptors.request.use((config) => {
|
||
// token 注入(参考原 config.js)
|
||
return config;
|
||
});
|
||
|
||
// 响应拦截器
|
||
api.interceptors.response.use(
|
||
(response) => response.data,
|
||
(error) => Promise.reject(error)
|
||
);
|
||
|
||
export default api;
|
||
```
|
||
|
||
- [ ] **Step 8: 安装依赖并验证构建**
|
||
|
||
```bash
|
||
cd frontend-source/projects/cwos-portal && npm install
|
||
npm run build
|
||
```
|
||
|
||
- [ ] **Step 9: Commit**
|
||
|
||
```bash
|
||
git add frontend-source/projects/cwos-portal/
|
||
git commit -m "feat: scaffold cwos-portal Vue 2 project (skeleton)"
|
||
```
|
||
|
||
### Task 12: 其他 3 个核心应用脚手架
|
||
|
||
**Files:**
|
||
- Create: `frontend-source/projects/{elevator-front,alarm-front,front_acs}/`
|
||
|
||
- [ ] **Step 1: 批量创建脚手架**(结构与 Task 11 一致,调整应用名)
|
||
|
||
```bash
|
||
cd frontend-source/projects
|
||
|
||
for app in elevator-front alarm-front front_acs; do
|
||
mkdir -p $app/public $app/src/{views,components,api,router,store}
|
||
|
||
# package.json (相同的依赖,只改 name)
|
||
cat > $app/package.json << EOF
|
||
{
|
||
"name": "$app",
|
||
"version": "1.0.0",
|
||
"private": true,
|
||
"scripts": {
|
||
"dev": "vue-cli-service serve",
|
||
"build": "vue-cli-service build"
|
||
},
|
||
"dependencies": {
|
||
"axios": "^0.21.4",
|
||
"element-ui": "^2.15.14",
|
||
"vue": "^2.6.14",
|
||
"vue-router": "^3.5.3",
|
||
"vuex": "^3.6.2"
|
||
},
|
||
"devDependencies": {
|
||
"@vue/cli-plugin-babel": "^4.5.19",
|
||
"@vue/cli-plugin-router": "^4.5.19",
|
||
"@vue/cli-plugin-vuex": "^4.5.19",
|
||
"@vue/cli-service": "^4.5.19",
|
||
"vue-template-compiler": "^2.6.14"
|
||
}
|
||
}
|
||
EOF
|
||
|
||
# vue.config.js, babel.config.js, public/index.html, src/main.js, src/App.vue,
|
||
# src/router/index.js, src/store/index.js, src/api/index.js
|
||
# (复制项目模板,使用前面 Task 11 的相同内容,修改标题即可)
|
||
|
||
cd $app && npm install && npm run build && cd ..
|
||
done
|
||
```
|
||
|
||
- [ ] **Step 2: Commit**
|
||
|
||
```bash
|
||
git add frontend-source/projects/elevator-front/ \
|
||
frontend-source/projects/alarm-front/ \
|
||
frontend-source/projects/front_acs/
|
||
git commit -m "feat: scaffold 3 core app Vue 2 projects (skeletons)"
|
||
```
|
||
|
||
---
|
||
|
||
## 阶段 4:文档与最终校验
|
||
|
||
### Task 13: frontend-source/AGENTS.md
|
||
|
||
**Files:**
|
||
- Create: `frontend-source/AGENTS.md`
|
||
|
||
- [ ] **Step 1: 编写目录说明**
|
||
|
||
写入 `frontend-source/AGENTS.md`:
|
||
```markdown
|
||
# frontend-source/ — 前端源码目录
|
||
|
||
## OVERVIEW
|
||
从 `frontend/` dist 产物反编译还原的前端源码。分为两类:
|
||
- `decompiled/` — B 级反编译(全部 28 个应用,可读参考)
|
||
- `projects/` — C 级重建(4 个核心应用,可构建部署)
|
||
|
||
## WHERE TO LOOK
|
||
|
||
| 任务 | 目录 | 说明 |
|
||
|------|------|------|
|
||
| 查看任意应用源码 | `decompiled/<app>/src/` | 格式化后的 JS 模块 |
|
||
| 查看 API 清单 | `decompiled/<app>/api-calls.md` | HTTP 端点列表 |
|
||
| 查看路由表 | `decompiled/<app>/router-tree.md` | 页面路由树 |
|
||
| 开发核心应用 | `projects/<app>/` | 可构建的 Vue 2 工程 |
|
||
| 反编译工具 | `scripts/` | unpack-webpack 等 |
|
||
|
||
## CONVENTIONS
|
||
|
||
- `decompiled/` 下文件**不可用于构建**,仅供阅读参考
|
||
- `projects/` 下工程可正常 `npm run dev` / `npm run build`
|
||
- 技术栈: Vue 2.6 + Element UI 2.15 + axios + vue-router 3 + vuex 3
|
||
- 构建使用 Vue CLI 4.5
|
||
|
||
## ANTI-PATTERNS
|
||
|
||
- 不要修改 `decompiled/` 下的源码后试图构建 — 这些是反编译参考
|
||
- 不要混用 Vue 3 / Element Plus — 阶段 2 必须用 Vue 2 + Element UI
|
||
- 不要删除 `frontend/` 原 dist 目录 — 它是唯一定稿的参考来源
|
||
|
||
## NOTES
|
||
|
||
- 反编译工具在 `scripts/` 下,Node.js 18+
|
||
- 阶段 2 重建的重点包含 `projects/` 下 4 个应用的逐页面重写
|
||
- 原始源码完全丢失,JS bundle 反编译无法恢复原始变量名
|
||
```
|
||
|
||
- [ ] **Step 2: Commit**
|
||
|
||
```bash
|
||
git add frontend-source/AGENTS.md
|
||
git commit -m "docs: add frontend-source AGENTS.md"
|
||
```
|
||
|
||
### Task 14: 最终校验
|
||
|
||
- [ ] **Step 1: 校验目录完整性**
|
||
|
||
```bash
|
||
echo "=== decompiled/ 应用数 ==="
|
||
ls frontend-source/decompiled/ | wc -l
|
||
echo "预期: 28"
|
||
|
||
echo "=== projects/ 应用数 ==="
|
||
ls frontend-source/projects/ | wc -l
|
||
echo "预期: 4"
|
||
|
||
echo "=== 脚本文件数 ==="
|
||
ls frontend-source/scripts/*.js frontend-source/scripts/*.sh 2>/dev/null | wc -l
|
||
echo "预期: 5 (3 js + 2 sh)"
|
||
```
|
||
|
||
- [ ] **Step 2: 校验 4 个核心项目可构建**
|
||
|
||
```bash
|
||
for app in cwos-portal elevator-front alarm-front front_acs; do
|
||
echo "=== 构建: $app ==="
|
||
cd frontend-source/projects/$app && npm run build 2>&1 | tail -3 || echo "构建失败"
|
||
cd ../../..
|
||
done
|
||
```
|
||
|
||
- [ ] **Step 3: Commit**
|
||
|
||
```bash
|
||
git add frontend-source/
|
||
git commit -m "chore: final verification of frontend-source directory"
|
||
```
|
||
|
||
---
|
||
|
||
## 计划总结
|
||
|
||
| 阶段 | 任务数 | 预计时间 |
|
||
|------|--------|----------|
|
||
| 前置准备 | Task 0 | 0.5h |
|
||
| 工具开发 | Task 1-4 | 2h |
|
||
| P0 验证 | Task 5 | 1h |
|
||
| P1 核心 | Task 6-8 | 1.5h |
|
||
| P2-P3 批量 | Task 9-10 | 1h |
|
||
| C 级重建 | Task 11-12 | 2h |
|
||
| 文档校验 | Task 13-14 | 0.5h |
|
||
| **合计** | **14 Tasks** | **~8.5h** |
|