@yorha2b-lab/autodev 2.1.2 → 2.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/main.yml +56 -61
- package/bin/autodev.js +1 -1
- package/example/example.json +4 -4
- package/package.json +1 -1
- package/src/commands/handlers/page-handler.js +2 -2
- package/src/core/react-compiler.js +10 -6
- package/src/prompts/react/watch-page.js +7 -6
- package/src/prompts/react/watch-part.js +2 -0
- package/templates/react/handlebars/handleBlock.hbs +8 -2
|
@@ -1,86 +1,81 @@
|
|
|
1
|
-
name:
|
|
1
|
+
name: Bunker Native Stats
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
schedule:
|
|
5
|
-
- cron: '45 19 * * *'
|
|
5
|
+
- cron: '45 19 * * *' # 北京时间凌晨 03:45
|
|
6
6
|
workflow_dispatch:
|
|
7
7
|
|
|
8
|
+
# 💡 补丁 1:强制开启 Node.js 24,消灭那个烦人的黄色警告
|
|
8
9
|
env:
|
|
9
10
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
|
10
11
|
|
|
11
12
|
jobs:
|
|
12
|
-
|
|
13
|
+
update-ledger:
|
|
13
14
|
runs-on: ubuntu-latest
|
|
14
15
|
permissions:
|
|
15
16
|
contents: write
|
|
16
17
|
steps:
|
|
17
|
-
|
|
18
|
+
# 1. 检出数据分支
|
|
19
|
+
- name: Checkout Data Branch
|
|
18
20
|
uses: actions/checkout@v4
|
|
19
|
-
|
|
20
|
-
- name: run-ghrs
|
|
21
|
-
uses: jgehrcke/github-repo-stats@v1.4.1
|
|
22
21
|
with:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
ref: github-repo-stats
|
|
23
|
+
token: ${{ secrets.STATS_TOKEN }}
|
|
24
|
+
fetch-depth: 0 # 获取完整历史,确保物理对账无误
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
# 2. 物理装配与合并
|
|
27
|
+
- name: Fetch and Smart Merge
|
|
28
28
|
run: |
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if [ -d "$DATA_DIR" ]; then sudo cp -r $DATA_DIR /tmp/bunker_assets/; fi
|
|
36
|
-
if [ -d "$REPORT_DIR" ]; then sudo cp -r $REPORT_DIR /tmp/bunker_assets/; fi
|
|
37
|
-
if [ -d "$PLOT_DIR" ]; then sudo cp -r $PLOT_DIR /tmp/bunker_assets/; fi
|
|
38
|
-
|
|
39
|
-
# 2. 切换并净化分支
|
|
40
|
-
git fetch origin github-repo-stats
|
|
41
|
-
git checkout github-repo-stats
|
|
42
|
-
sudo chown -R runner:docker .
|
|
43
|
-
git rm -rf . 2>/dev/null || true
|
|
44
|
-
sudo rm -rf *
|
|
29
|
+
echo "🤖 Pod 042: 启动‘全链路数据闭环协议’..."
|
|
30
|
+
|
|
31
|
+
# A. 抓取数据(增加 -s 隐藏进度,-f 报错即停止)
|
|
32
|
+
curl -sf -H "Authorization: token ${{ secrets.STATS_TOKEN }}" \
|
|
33
|
+
-H "Accept: application/vnd.github.v3+json" \
|
|
34
|
+
https://api.github.com/repos/${{ github.repository }}/traffic/clones > raw.json
|
|
45
35
|
|
|
46
|
-
#
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if [ -f "report.md" ]; then sudo mv report.md README.md; fi
|
|
36
|
+
# B. 格式化新数据
|
|
37
|
+
mkdir -p ghrs-data
|
|
38
|
+
echo "date,clones,uniques" > /tmp/new_data.csv
|
|
39
|
+
jq -r '.clones[] | "\(.timestamp[0:10]),\(.count),\(.uniques)"' raw.json >> /tmp/new_data.csv
|
|
51
40
|
|
|
52
|
-
#
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if [ ! -f "$TARGET_FILE" ]; then TARGET_FILE="report.md"; fi
|
|
57
|
-
|
|
58
|
-
if [ -f "$TARGET_FILE" ]; then
|
|
59
|
-
# 💡 精准定位逻辑:
|
|
60
|
-
# 1. 寻找包含 "Total clones" 的行
|
|
61
|
-
# 2. 锁定该行之后的第一个 "Cumulative" 关键字
|
|
62
|
-
# 3. 提取其中的数字
|
|
63
|
-
TOTAL_CLONES=$(awk '/Total clones/{flag=1; next} flag && /Cumulative/{print $0; flag=0}' "$TARGET_FILE" | grep -oE "[0-9]+" | head -n 1 || echo "")
|
|
64
|
-
|
|
65
|
-
if [ ! -z "$TOTAL_CLONES" ] && [ "$TOTAL_CLONES" -gt 0 ]; then
|
|
66
|
-
echo "{\"total_clones\": $TOTAL_CLONES}" > bunker-stats.json
|
|
67
|
-
echo "✅ 成功:已精准定位克隆总数:$TOTAL_CLONES"
|
|
68
|
-
else
|
|
69
|
-
echo "⚠️ 警告:精准提取失败,正在启动 CSV 账本回溯..."
|
|
70
|
-
# 最后的兜底:计算 CSV 的总和
|
|
71
|
-
CSV_FILE="ghrs-data/views_clones_aggregate.csv"
|
|
72
|
-
TOTAL_CLONES=$(awk -F',' 'NR>1 {sum+=$2} END {print sum}' "$CSV_FILE" || echo "0")
|
|
73
|
-
echo "{\"total_clones\": $TOTAL_CLONES}" > bunker-stats.json
|
|
74
|
-
fi
|
|
41
|
+
# C. 🧬 执行物理合并逻辑
|
|
42
|
+
LEDGER="ghrs-data/clones_ledger.csv"
|
|
43
|
+
if [ ! -f "$LEDGER" ]; then
|
|
44
|
+
cp /tmp/new_data.csv "$LEDGER"
|
|
75
45
|
else
|
|
76
|
-
echo "
|
|
77
|
-
|
|
46
|
+
echo "📡 正在将手动补全的数据与 API 信号进行物理焊接..."
|
|
47
|
+
(head -n 1 "$LEDGER"; tail -n +2 "$LEDGER"; tail -n +2 /tmp/new_data.csv) | \
|
|
48
|
+
sed 's/\//-/g' | \
|
|
49
|
+
awk -F',' 'NR>1 {
|
|
50
|
+
split($1, a, "-");
|
|
51
|
+
if(length(a[2])==1) a[2]="0"a[2];
|
|
52
|
+
if(length(a[3])==1) a[3]="0"a[3];
|
|
53
|
+
printf "%s-%s-%s,%s,%s\n", a[1], a[2], a[3], $2, $3
|
|
54
|
+
}' | awk -F',' '!a[$1]++' | sort -r > /tmp/final_ledger.csv
|
|
55
|
+
|
|
56
|
+
echo "date,clones,uniques" > "$LEDGER"
|
|
57
|
+
cat /tmp/final_ledger.csv >> "$LEDGER"
|
|
78
58
|
fi
|
|
79
|
-
|
|
80
|
-
#
|
|
81
|
-
|
|
59
|
+
|
|
60
|
+
# D. 🔥 核心:产出 [bunker-stats.json]
|
|
61
|
+
# 确保 awk 逻辑百分之百执行
|
|
62
|
+
TOTAL_CLONES=$(awk -F',' 'NR>1 {sum+=$2} END {print sum}' "$LEDGER")
|
|
63
|
+
echo "{\"total_clones\": $TOTAL_CLONES}" > bunker-stats.json
|
|
64
|
+
echo "✅ 物理总数结算达成: $TOTAL_CLONES"
|
|
65
|
+
|
|
66
|
+
# E. 重构 README
|
|
67
|
+
echo "# 🛰️ 地堡运行报告 (Sovereign Report)" > README.md
|
|
68
|
+
echo "### 📊 累计物理克隆总数: **$TOTAL_CLONES**" >> README.md
|
|
69
|
+
echo "数据已根据 AGPL-3.0 协议物理封存。愿人类荣光永存。" >> README.md
|
|
70
|
+
echo "" >> README.md
|
|
71
|
+
echo "> 📡 信号状态:全频道在线 | 战绩自动核算中..." >> README.md
|
|
72
|
+
|
|
73
|
+
# 3. 封存并强力同步
|
|
74
|
+
- name: Commit and Push
|
|
75
|
+
run: |
|
|
82
76
|
git config user.name github-actions
|
|
83
77
|
git config user.email github-actions@github.com
|
|
84
78
|
git add -A
|
|
85
|
-
|
|
79
|
+
TOTAL=$(grep -oE "[0-9]+" bunker-stats.json | head -n 1)
|
|
80
|
+
git commit -m "chore: ledger & badge update - total $TOTAL" || echo "no changes"
|
|
86
81
|
git push origin github-repo-stats --force
|
package/bin/autodev.js
CHANGED
|
@@ -58,7 +58,7 @@ program
|
|
|
58
58
|
console.log('\n')
|
|
59
59
|
console.log(chalk.gray('--------------------------------------------------'))
|
|
60
60
|
console.log(chalk.white(' [System] ') + chalk.yellow(language('正在断开神经云链接,执行数据物理封存...', 'Disconnecting Neural Link, Executing Physical Assembly...')))
|
|
61
|
-
matrixEffect(
|
|
61
|
+
matrixEffect(500)
|
|
62
62
|
})
|
|
63
63
|
})
|
|
64
64
|
|
package/example/example.json
CHANGED
|
@@ -17,14 +17,14 @@
|
|
|
17
17
|
"key": "mage"
|
|
18
18
|
}
|
|
19
19
|
],
|
|
20
|
+
"staticInfo": {
|
|
21
|
+
"has": false,
|
|
22
|
+
"text": ""
|
|
23
|
+
},
|
|
20
24
|
"table": {
|
|
21
25
|
"pagination": true,
|
|
22
26
|
"expandable": true,
|
|
23
27
|
"rowSelection": true,
|
|
24
|
-
"staticInfo": {
|
|
25
|
-
"has": false,
|
|
26
|
-
"text": ""
|
|
27
|
-
},
|
|
28
28
|
"operation": [
|
|
29
29
|
{
|
|
30
30
|
"label": "查看",
|
package/package.json
CHANGED
|
@@ -19,8 +19,8 @@ module.exports = async (filePath, context) => {
|
|
|
19
19
|
|
|
20
20
|
const spinner = ora({
|
|
21
21
|
text: chalk.cyan(language(
|
|
22
|
-
`[System] 视觉传感器捕捉完成: [${fileName}]
|
|
23
|
-
`[System] Visual sensor captured: [${fileName}]. Allocating Bunker resources for physical construction
|
|
22
|
+
`[System] 视觉传感器捕捉完成: [${fileName}]。正在调配地堡资源进行物理构筑...\n`,
|
|
23
|
+
`[System] Visual sensor captured: [${fileName}]. Allocating Bunker resources for physical construction...\n`
|
|
24
24
|
)),
|
|
25
25
|
color: 'cyan'
|
|
26
26
|
}).start()
|
|
@@ -46,6 +46,8 @@ const index = ({ config, fileName, indexTpl, pageConfig }) => {
|
|
|
46
46
|
const hasTabs = pageConfig.tabs?.length > 0
|
|
47
47
|
const hasFormItems = pageConfig.formItems?.length > 0
|
|
48
48
|
const hasOperate = pageConfig.table.operation?.length > 0
|
|
49
|
+
const functionButtons = pageConfig.functionButton?.filter(item => !['查询', '重置'].includes(item.btn)) || []
|
|
50
|
+
const hasFunctionButtons = functionButtons.length > 0
|
|
49
51
|
|
|
50
52
|
let columnsValue = hasTabs ? 'columns[activeKey]' : 'columns'
|
|
51
53
|
if (hasOperate) {
|
|
@@ -58,17 +60,16 @@ const index = ({ config, fileName, indexTpl, pageConfig }) => {
|
|
|
58
60
|
hasOperate,
|
|
59
61
|
columnsValue,
|
|
60
62
|
hasFormItems,
|
|
63
|
+
functionButtons,
|
|
61
64
|
tabs: pageConfig.tabs,
|
|
62
|
-
pageStruct: pageConfig.pageStruct,
|
|
63
65
|
responseSuccess: config.responseSuccess,
|
|
66
|
+
hasStaticInfo: pageConfig.staticInfo?.has,
|
|
64
67
|
hasExpandable: pageConfig.table.expandable,
|
|
65
68
|
hasPagination: pageConfig.table.pagination,
|
|
66
69
|
operations: pageConfig.table.operation || [],
|
|
67
70
|
hasRowSelection: pageConfig.table.rowSelection,
|
|
68
|
-
hasStaticInfo: pageConfig.table.staticInfo?.has,
|
|
69
|
-
staticInfoText: pageConfig.table.staticInfo?.text,
|
|
70
71
|
formItems: hasTabs ? 'formItems[activeKey]' : 'formItems',
|
|
71
|
-
|
|
72
|
+
pageStruct: hasFunctionButtons ? pageConfig.pageStruct : pageConfig.pageStruct?.filter(item => item !== 'FunctionButtonsBlock'),
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
if (viewData.hasOperate) {
|
|
@@ -79,15 +80,18 @@ const index = ({ config, fileName, indexTpl, pageConfig }) => {
|
|
|
79
80
|
Handlebars.registerPartial('MySearchForm', `${fs.readFileSync(path.join(__dirname, '../../templates/react/handlebars/MySearchForm.hbs'), 'utf-8')}\n`)
|
|
80
81
|
}
|
|
81
82
|
|
|
83
|
+
if (hasFunctionButtons) {
|
|
84
|
+
Handlebars.registerPartial('FunctionButtonsBlock', `${fs.readFileSync(path.join(__dirname, '../../templates/react/handlebars/functionButtonsBlock.hbs'), 'utf-8')}\n`)
|
|
85
|
+
}
|
|
86
|
+
|
|
82
87
|
if (viewData.hasStaticInfo) {
|
|
83
|
-
Handlebars.registerPartial('AlertInfo', `{{{{raw}}}}<Alert showIcon title='${pageConfig.
|
|
88
|
+
Handlebars.registerPartial('AlertInfo', `{{{{raw}}}}<Alert showIcon title='${pageConfig.staticInfo?.text}' type='info' style={{ marginBottom: 16 }} />\n{{{{/raw}}}}`)
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
Handlebars.registerPartial('MyTable', `${fs.readFileSync(path.join(__dirname, '../../templates/react/handlebars/MyTable.hbs'), 'utf-8')}\n`)
|
|
87
92
|
Handlebars.registerPartial('hookBlock', `${fs.readFileSync(path.join(__dirname, '../../templates/react/handlebars/hookBlock.hbs'), 'utf-8')}\n`)
|
|
88
93
|
Handlebars.registerPartial('stateBlock', `${fs.readFileSync(path.join(__dirname, '../../templates/react/handlebars/stateBlock.hbs'), 'utf-8')}\n`)
|
|
89
94
|
Handlebars.registerPartial('handleBlock', `${fs.readFileSync(path.join(__dirname, '../../templates/react/handlebars/handleBlock.hbs'), 'utf-8')}\n`)
|
|
90
|
-
Handlebars.registerPartial('FunctionButtonsBlock', `${fs.readFileSync(path.join(__dirname, '../../templates/react/handlebars/functionButtonsBlock.hbs'), 'utf-8')}\n`)
|
|
91
95
|
|
|
92
96
|
const bodyCode = indexTpl(viewData)
|
|
93
97
|
const importsStr = generateSmartImports(bodyCode, hasTabs)
|
|
@@ -12,12 +12,13 @@ module.exports = `
|
|
|
12
12
|
⚠️⚠️⚠️注意:
|
|
13
13
|
如果是下拉框,请加入type:'select',options:_CODE_对应的英文名词Options_CODE_
|
|
14
14
|
如果是时间范围查询,请加入type:'daterange',name:'对应的英文名词start,对应的英文名词end'
|
|
15
|
-
4
|
|
15
|
+
4.统计条:
|
|
16
|
+
staticInfo:{has:true/false,text:'具体统计内容'},
|
|
17
|
+
5.表格:
|
|
16
18
|
{
|
|
17
19
|
pagination: true/false,
|
|
18
20
|
expandable: true/false,
|
|
19
21
|
rowSelection: true/false,
|
|
20
|
-
staticInfo:{has:true/false,text:''},
|
|
21
22
|
operation: [{label:'操作',action:'操作动词+ByRecord'}],
|
|
22
23
|
columns: [{ title: '普通列', dataIndex:'对应的英文名词' }],
|
|
23
24
|
}
|
|
@@ -28,17 +29,17 @@ module.exports = `
|
|
|
28
29
|
如果是序号列直接渲染为{ title: '序号',render: _CODE_(_, record, index) => index + 1_CODE_ }
|
|
29
30
|
如果是下拉框列(所对应的查询项明确是下拉框),请加入render:_CODE_text=>对应的options.find(item=>item.value===text)?.label_CODE_
|
|
30
31
|
如果列需要过滤请加上filters:[],onFilter: _CODE_(value, record) => record[对应的英文名词].includes(value)_CODE_
|
|
31
|
-
|
|
32
|
+
6.功能按钮
|
|
32
33
|
functionButton:[{btn:'btn',action:'操作动词+模块英文名词'}]
|
|
33
34
|
如果和表格行操作重复请在action加上BySelected前缀
|
|
34
35
|
如果是导出功能,对应的动词为export+对应的英文名词,没有名词则为exportData
|
|
35
|
-
|
|
36
|
+
7.下拉选项字典
|
|
36
37
|
optionDict:{_CODE_对应的英文名词Options_CODE_:[]]}
|
|
37
38
|
⚠️⚠️⚠️注意:数组值为对应列展示的内容组成的类似{label:'',value:''}的数组
|
|
38
|
-
|
|
39
|
+
8.pageStruct
|
|
39
40
|
从上至下的页面结构组成
|
|
40
41
|
⚠️⚠️⚠️注意:这里只能从AlertInfo,MySearchForm,FunctionButtonsBlock,MyTable中选择,并且只有真的存在才加入,绝对禁止加入其他组件
|
|
41
42
|
⚠️⚠️⚠️另外这里不要加入tabs组件
|
|
42
43
|
最后输出一个JSON对象,不要包含任何Markdown标签,格式如下
|
|
43
|
-
{ tabs: [], table: {}, formItems: [], optionDict: {}, functionButton: [],pageStruct:[]}
|
|
44
|
+
{ tabs: [], table: {}, formItems: [],staticInfo:{}, optionDict: {}, functionButton: [],pageStruct:[]}
|
|
44
45
|
`
|
|
@@ -47,6 +47,12 @@ const expandedRowRender = record => (<div>自定义渲染</div>)
|
|
|
47
47
|
{{/if}}
|
|
48
48
|
|
|
49
49
|
const modalSubmit = async values => {
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
let response
|
|
51
|
+
if(modal.type==='add'){
|
|
52
|
+
response = await request('/api')
|
|
53
|
+
}
|
|
54
|
+
if({{{responseSuccess}}}){
|
|
55
|
+
setModal({ visible: false })
|
|
56
|
+
refresh()
|
|
57
|
+
}
|
|
52
58
|
}
|