Skip to content

Commit 6c5f6fe

Browse files
committed
Merge branch 'dev'
2 parents 7d46f32 + 5d33ef1 commit 6c5f6fe

File tree

11 files changed

+563
-405
lines changed

11 files changed

+563
-405
lines changed

.eslintrc.yml

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,25 @@
11
env:
2-
commonjs: true
32
es2021: true
43
node: true
54
extends:
6-
- standard
5+
- 'eslint:recommended'
6+
- 'plugin:@typescript-eslint/recommended'
7+
parser: '@typescript-eslint/parser'
78
parserOptions:
8-
ecmaVersion: latest
9-
rules: {}
9+
ecmaVersion: 12
10+
sourceType: module
11+
plugins:
12+
- '@typescript-eslint'
13+
rules:
14+
indent:
15+
- error
16+
- 4
17+
linebreak-style:
18+
- error
19+
- unix
20+
quotes:
21+
- error
22+
- single
23+
semi:
24+
- error
25+
- always

index.js

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,44 @@
1-
import UtilArgs from './util/args.js'
2-
import UtilPath from './util/path.js'
3-
import UtilFs from './util/fs.js'
4-
import UtilCompare from './util/compare.js'
5-
import UtilQueue from './util/queue.js'
1+
import UtilArgs from './util/args.js';
2+
import UtilPath from './util/path.js';
3+
import UtilFs from './util/fs.js';
4+
import UtilCompare from './util/compare.js';
5+
import UtilQueue from './util/queue.js';
66

77
const argv = UtilArgs.getArgv();
88

99
(async function () {
10-
// get summary
11-
const lhsQueue = UtilQueue.createQueue({ concurrency: argv.n })
12-
const lhsFilePattern = UtilPath.resolve(argv.l, '**/*')
13-
const lhsFilePaths = await UtilPath.glob(lhsFilePattern)
14-
const lhsFileSummary = await UtilCompare.getFileSummary(argv.l, lhsFilePaths, lhsQueue)
15-
const rhsQueue = UtilQueue.createQueue({ concurrency: argv.m })
16-
const rhsFilePattern = UtilPath.resolve(argv.r, '**/*')
17-
const rhsFilePaths = await UtilPath.glob(rhsFilePattern)
18-
const rhsFileSummary = await UtilCompare.getFileSummary(argv.r, rhsFilePaths, rhsQueue)
19-
20-
// save file summary
21-
const lhsFileSummaryOutputPath = UtilPath.resolve(argv.o, './file-summary-lhs.json')
22-
UtilFs.writeJson(lhsFileSummaryOutputPath, lhsFileSummary)
23-
const rhsFileSummaryOutputPath = UtilPath.resolve(argv.o, './file-summary-rhs.json')
24-
UtilFs.writeJson(rhsFileSummaryOutputPath, rhsFileSummary)
25-
26-
// compare summary
27-
const compareSummary = UtilCompare.getCompareSummary(lhsFileSummary, rhsFileSummary)
28-
29-
// revalidate compare summary
30-
const compareRevalidateQueueLhs = UtilQueue.createQueue({ concurrency: argv.n })
31-
const compareRevalidateQueueRhs = UtilQueue.createQueue({ concurrency: argv.m })
32-
const compareRevalidateSummary = await UtilCompare.revalidateCompareSummary(compareSummary, compareRevalidateQueueLhs, compareRevalidateQueueRhs)
33-
34-
// save compare summary
35-
const compareSummaryOutputPath = UtilPath.resolve(argv.o, './compare-summary.json')
36-
UtilFs.writeJson(compareSummaryOutputPath, compareRevalidateSummary)
37-
38-
// compare report
39-
const compareReport = UtilCompare.getCompareReport(compareRevalidateSummary)
40-
41-
// save compare report
42-
const compareReportOutputPath = UtilPath.resolve(argv.o, './compare-report.html')
43-
UtilFs.writeFile(compareReportOutputPath, compareReport)
44-
})()
10+
// get summary
11+
const lhsQueue = UtilQueue.createQueue({ concurrency: argv.n });
12+
const lhsFilePattern = UtilPath.resolve(argv.l, '**/*');
13+
const lhsFilePaths = await UtilPath.glob(lhsFilePattern);
14+
const lhsFileSummary = await UtilCompare.getFileSummary(argv.l, lhsFilePaths, lhsQueue);
15+
const rhsQueue = UtilQueue.createQueue({ concurrency: argv.m });
16+
const rhsFilePattern = UtilPath.resolve(argv.r, '**/*');
17+
const rhsFilePaths = await UtilPath.glob(rhsFilePattern);
18+
const rhsFileSummary = await UtilCompare.getFileSummary(argv.r, rhsFilePaths, rhsQueue);
19+
20+
// save file summary
21+
const lhsFileSummaryOutputPath = UtilPath.resolve(argv.o, './file-summary-lhs.json');
22+
UtilFs.writeJson(lhsFileSummaryOutputPath, lhsFileSummary);
23+
const rhsFileSummaryOutputPath = UtilPath.resolve(argv.o, './file-summary-rhs.json');
24+
UtilFs.writeJson(rhsFileSummaryOutputPath, rhsFileSummary);
25+
26+
// compare summary
27+
const compareSummary = UtilCompare.getCompareSummary(lhsFileSummary, rhsFileSummary);
28+
29+
// revalidate compare summary
30+
const compareRevalidateQueueLhs = UtilQueue.createQueue({ concurrency: argv.n });
31+
const compareRevalidateQueueRhs = UtilQueue.createQueue({ concurrency: argv.m });
32+
const compareRevalidateSummary = await UtilCompare.revalidateCompareSummary(compareSummary, compareRevalidateQueueLhs, compareRevalidateQueueRhs);
33+
34+
// save compare summary
35+
const compareSummaryOutputPath = UtilPath.resolve(argv.o, './compare-summary.json');
36+
UtilFs.writeJson(compareSummaryOutputPath, compareRevalidateSummary);
37+
38+
// compare report
39+
const compareReport = UtilCompare.getCompareReport(compareRevalidateSummary);
40+
41+
// save compare report
42+
const compareReportOutputPath = UtilPath.resolve(argv.o, './compare-report.html');
43+
UtilFs.writeFile(compareReportOutputPath, compareReport);
44+
})();

package.json

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,20 @@
44
"main": "index.js",
55
"type": "module",
66
"license": "MIT",
7-
"private": true,
7+
"private": false,
88
"scripts": {
99
"commit": "cz",
1010
"compare": "node index.js",
11-
"lint": "eslint --ext .js .",
11+
"lint": "eslint --ext .js,.ts .",
1212
"release": "semantic-release"
1313
},
14+
"description": "Compare file differences between two directories and generate report",
15+
"keywords": [
16+
"backend",
17+
"cli",
18+
"kongying-cli-plugin",
19+
"kongying-cmd-compare"
20+
],
1421
"dependencies": {
1522
"fs-extra": "^10.0.1",
1623
"globby": "^13.1.1",
@@ -21,6 +28,8 @@
2128
"yargs": "^17.3.1"
2229
},
2330
"devDependencies": {
31+
"@typescript-eslint/eslint-plugin": "^5.27.1",
32+
"@typescript-eslint/parser": "^5.27.1",
2433
"commitizen": "^4.2.4",
2534
"cz-conventional-changelog": "3.3.0",
2635
"eslint": "^7.32.0",
@@ -44,5 +53,8 @@
4453
"@semantic-release/release-notes-generator",
4554
"@semantic-release/github"
4655
]
56+
},
57+
"publishConfig": {
58+
"access": "public"
4759
}
4860
}

template/compare.summary.vue

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>文件比对结果</title>
7+
<link rel="stylesheet" type="text/css" href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.6/theme-chalk/index.css">
8+
<style type="text/css">
9+
#app {
10+
display: flex;
11+
flex-direction: column;
12+
position: fixed;
13+
top: 0;
14+
bottom: 0;
15+
left: 0;
16+
right: 0;
17+
padding: .7rem;
18+
}
19+
.drawer-wrapper {
20+
padding: 0 1rem;
21+
}
22+
.form-component {
23+
width: 100%;
24+
}
25+
.action-wrapper {
26+
flex: none;
27+
margin-bottom: .7rem;
28+
}
29+
.table-wrapper {
30+
position: relative;
31+
flex: auto;
32+
}
33+
.table-component {
34+
position: absolute;
35+
top: 0;
36+
bottom: 0;
37+
left: 0;
38+
right: 0;
39+
}
40+
</style>
41+
</head>
42+
<body>
43+
<div id="app">
44+
<!-- Popups -->
45+
<el-drawer
46+
:visible.sync="state.filterDrawerVisible"
47+
title="过滤筛选"
48+
direction="rtl"
49+
size="40%"
50+
:wrapperClosable="false"
51+
append-to-body
52+
modal-append-to-body>
53+
<el-form
54+
class="drawer-wrapper"
55+
size="mini"
56+
label-position="left"
57+
label-width="100px">
58+
<el-form-item label="差异类型">
59+
<el-select
60+
v-model="state.filterTypes"
61+
class="form-component"
62+
multiple>
63+
<el-option
64+
v-for="(item, i) in plugins.typeOptions"
65+
:key="i"
66+
:label="item.label"
67+
:value="item.value">
68+
</el-option>
69+
</el-select>
70+
</el-form-item>
71+
</el-form>
72+
</el-drawer>
73+
74+
<div class="action-wrapper">
75+
<el-button
76+
size="mini"
77+
type="info"
78+
icon="el-icon-search"
79+
circle
80+
@click="popupFilterDrawer">
81+
</el-button>
82+
</div>
83+
84+
<div class="table-wrapper">
85+
<el-table
86+
class="table-component"
87+
:data="compareDataFiltered"
88+
size="mini"
89+
border
90+
height="auto">
91+
<el-empty slot="empty" description="暂无数据"></el-empty>
92+
93+
<el-table-column
94+
label="数字签名"
95+
sortable
96+
sort-by="hash">
97+
</el-table-column>
98+
<el-table-column
99+
label="左侧文件名"
100+
sortable
101+
sort-by="lhs.0.filename">
102+
<template slot-scope="scope">
103+
<template v-if="scope.row.lhs && scope.row.lhs.length > 0">
104+
<div v-for="(item, i) in scope.row.lhs" :key="i">
105+
{{item.filename}}
106+
</div>
107+
</template>
108+
</template>
109+
</el-table-column>
110+
<el-table-column
111+
width="100"
112+
align="center"
113+
sortable
114+
sort-by="type">
115+
<template slot-scope="scope">
116+
<el-button
117+
size="mini"
118+
:type="scope.row.typeOption.type"
119+
:icon="scope.row.typeOption.icon"
120+
circle>
121+
</el-button>
122+
</template>
123+
</el-table-column>
124+
<el-table-column
125+
label="右侧侧文件名"
126+
sortable
127+
sort-by="rhs.0.filename">
128+
<template slot-scope="scope">
129+
<template v-if="scope.row.rhs && scope.row.rhs.length > 0">
130+
<div v-for="(item, i) in scope.row.rhs" :key="i">
131+
{{item.filename}}
132+
</div>
133+
</template>
134+
</template>
135+
</el-table-column>
136+
</el-table>
137+
</div>
138+
</div>
139+
140+
<script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"></script>
141+
<script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.6/index.js"></script>
142+
<script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
143+
<script type="text/javascript">
144+
new Vue({
145+
el: '#app',
146+
data() {
147+
return {
148+
compareData: {{__ summary __}},
149+
state: {
150+
filterDrawerVisible: false,
151+
filterTypes: ['add', 'remove', 'same'],
152+
},
153+
plugins: {
154+
typeOptions: [
155+
{
156+
label: '新增',
157+
value: 'add',
158+
type: 'success',
159+
icon: 'el-icon-star-off'
160+
},
161+
{
162+
label: '删除',
163+
value: 'remove',
164+
type: 'danger',
165+
icon: 'el-icon-delete'
166+
},
167+
{
168+
label: '相同',
169+
value: 'same',
170+
type: 'info',
171+
icon: 'el-icon-more-outline'
172+
}
173+
]
174+
}
175+
}
176+
},
177+
computed: {
178+
compareDataFiltered() {
179+
let list = this.compareData || [];
180+
list = this.applyTypeMapper(list);
181+
list = this.applyTypeFilter(list);
182+
183+
return list;
184+
}
185+
},
186+
methods: {
187+
// popups / popdowns
188+
popupFilterDrawer() {
189+
this.state.filterDrawerVisible = true;
190+
},
191+
// Mappers
192+
applyTypeMapper(list = []) {
193+
let typeOptionMap = _.keyBy(this.plugins.typeOptions, 'value');
194+
let listMapped = _.map(list, v => {
195+
let typeKey = v.type || '';
196+
let typeOption = typeOptionMap[typeKey] || {};
197+
198+
v.typeOption = typeOption;
199+
200+
return v;
201+
});
202+
203+
return listMapped;
204+
},
205+
applyTypeFilter(list = []) {
206+
let listFiltered = _.filter(list, v => this.state.filterTypes.indexOf(v.type) !== -1);
207+
208+
return listFiltered;
209+
}
210+
}
211+
})
212+
</script>
213+
</body>
214+
</html>

0 commit comments

Comments
 (0)