feat: 迁移日汇总任务并修复商务菜单图标
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
"""通过真实菜单接口检查商务图标映射,不进行页面交互。"""
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--base-url', default='http://127.0.0.1:18000')
|
||||
parser.add_argument('--token-file', required=True, type=Path)
|
||||
parser.add_argument('--output', required=True, type=Path)
|
||||
args = parser.parse_args()
|
||||
token = args.token_file.read_text(encoding='utf-8').strip()
|
||||
icons = dict(re.findall(r'"(sw_[^"]+)":\s*"([^"]+)"', Path('internal/data/business/menu_icons.go').read_text(encoding='utf-8')))
|
||||
req = urllib.request.Request(args.base_url + '/menu/getMenu', data=b'{}', headers={'x-token': token, 'Content-Type': 'application/json'})
|
||||
with urllib.request.urlopen(req, timeout=30) as response:
|
||||
data = json.load(response)
|
||||
assert data['code'] == 0, data.get('msg')
|
||||
rows = []
|
||||
def walk(value):
|
||||
if isinstance(value, dict):
|
||||
name = value.get('name')
|
||||
if name in icons and 'component' in value:
|
||||
actual = value.get('meta', {}).get('icon')
|
||||
rows.append({'name': name, 'icon': actual, 'expected': icons[name], 'passed': actual == icons[name]})
|
||||
for item in value.values():
|
||||
walk(item)
|
||||
elif isinstance(value, list):
|
||||
for item in value:
|
||||
walk(item)
|
||||
walk(data)
|
||||
report = {'baseURL': args.base_url, 'menuCount': len(rows), 'checks': rows, 'passed': len(rows) == len(icons) and all(row['passed'] for row in rows)}
|
||||
args.output.write_text(json.dumps(report, ensure_ascii=False, indent=2) + '\n', encoding='utf-8')
|
||||
print(json.dumps(report, ensure_ascii=False))
|
||||
if not report['passed']:
|
||||
raise SystemExit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,32 @@
|
||||
// 核验实际安装的图标组件及 SVG 输出,不启动浏览器、不检查页面交互。
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
const assert = require('node:assert/strict')
|
||||
const { createRequire } = require('node:module')
|
||||
const root = path.resolve(__dirname, '..')
|
||||
const localRequire = createRequire(path.join(root, 'web', 'package.json'))
|
||||
const icons = localRequire('@element-plus/icons-vue')
|
||||
const { createSSRApp, h } = localRequire('vue')
|
||||
const { renderToString } = localRequire('@vue/server-renderer')
|
||||
|
||||
;(async () => {
|
||||
const source = fs.readFileSync(path.join(root, 'internal/data/business/menu_icons.go'), 'utf8')
|
||||
const entries = [...source.matchAll(/"(sw_[^"]+)":\s*"([^"]+)"/g)].map(match => ({ name: match[1], icon: match[2] }))
|
||||
assert.equal(entries.length, 14)
|
||||
const sql = fs.readFileSync(path.join(root, 'docs/sw6-to-kra/sw_to_kra_migrate.sql'), 'utf8')
|
||||
const moduleSource = fs.readFileSync(path.join(root, 'internal/modules/business/definition.go'), 'utf8')
|
||||
for (const row of entries) {
|
||||
assert.ok(icons[row.icon], `${row.icon} 未注册`)
|
||||
assert.ok(sql.includes(`WHEN '${row.name}' THEN '${row.icon}'`), `${row.name} 缺少重复执行修复`)
|
||||
assert.ok(sql.includes(`WHEN '${row.name.slice(3)}' THEN '${row.icon}'`), `${row.name} 缺少首次迁移映射`)
|
||||
assert.ok(moduleSource.includes(`Icon: databusiness.MenuIcon("${row.name}")`))
|
||||
const rendered = await renderToString(createSSRApp({ render: () => h(icons[row.icon]) }))
|
||||
assert.match(rendered, /<svg[\s>]/)
|
||||
assert.match(rendered, /<(path|circle|rect|polygon|line)[\s>]/)
|
||||
row.svgRendered = true
|
||||
}
|
||||
assert.ok(icons.Menu, 'SQL 默认图标必须已注册')
|
||||
const result = { method: '本地已安装组件的 SSR SVG 验证,包含首次/重复迁移 SQL 与模块定义一致性检查', icons: entries, passed: true }
|
||||
fs.writeFileSync(path.join(root, 'docs/sw6-to-kra/menu-icons-components-2026-11-04.json'), JSON.stringify(result, null, 2) + '\n')
|
||||
console.log(JSON.stringify(result))
|
||||
})().catch(error => { console.error(error); process.exitCode = 1 })
|
||||
@@ -0,0 +1,34 @@
|
||||
"""只读核验汇总任务方法已注册、导入计划保持禁用,不触发实际数据重建。"""
|
||||
import argparse
|
||||
import json
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--base-url', default='http://127.0.0.1:18000')
|
||||
parser.add_argument('--token-file', required=True, type=Path)
|
||||
parser.add_argument('--output', required=True, type=Path)
|
||||
args = parser.parse_args()
|
||||
token = args.token_file.read_text(encoding='utf-8').strip()
|
||||
def get(path):
|
||||
req = urllib.request.Request(args.base_url + path, headers={'x-token': token})
|
||||
with urllib.request.urlopen(req, timeout=30) as response:
|
||||
data = json.load(response)
|
||||
assert data['code'] == 0, data.get('msg')
|
||||
return data['data']
|
||||
methods = get('/timedTask/getRegisteredMethods')['methods']
|
||||
names = {row['name'] for row in methods}
|
||||
expected = {f'swReport{kind}{period}Task' for kind in ['Day', 'ServerDay'] for period in ['Today', 'Yesterday', 'Backfill']}
|
||||
tasks = get('/timedTask/getTimedTaskList?page=1&pageSize=1000')
|
||||
imported = [row for row in tasks['list'] if row.get('name', '').startswith('SW/')]
|
||||
report = {'scope': '真实 sw7 会话,只读任务接口;正向创建和触发通过隔离数据库原生任务 HTTP 测试。', 'registeredMethods': sorted(names & expected), 'importedTasks': len(imported), 'enabledImportedTasks': sum(bool(row['enabled']) for row in imported), 'passed': expected <= names and not any(row['enabled'] for row in imported)}
|
||||
args.output.write_text(json.dumps(report, ensure_ascii=False, indent=2) + '\n', encoding='utf-8')
|
||||
print(json.dumps(report, ensure_ascii=False))
|
||||
if not report['passed']:
|
||||
raise SystemExit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user