feat(auth): 统一数据库运维菜单路由并添加装置单位及监测点限值配置功能
- 统一数据库监控菜单路径到 /system-ops/dbms 入口 - 添加 isDbmsMenu 函数处理多种数据库菜单路径匹配 - 在动态路由中增加多个数据库监控路径的重定向规则 - 添加设备单位配置功能包括新增 EquipmentUnitForm 接口定义 - 添加监测点限值配置功能包括新增 OverlimitDetail 接口定义 - 在装置表单中添加单位配置按钮并集成单位调试功能 - 在监测点表单中添加限值配置按钮并集成限值调试功能 - 添加电压等级变更时的默认容量和变比同步逻辑 - 配置监测点表单中的线路类型选择选项 - 添加装置表单中比率输入组的高度紧凑样式 - 新增数据库运维静态路由配置和别名支持
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const currentDir = path.dirname(fileURLToPath(import.meta.url))
|
||||
const pageDir = path.join(currentDir, '..')
|
||||
const dialogSource = fs.readFileSync(path.join(pageDir, 'components/DbmsConnectionDialog.vue'), 'utf8')
|
||||
const payloadSource = fs.readFileSync(path.join(pageDir, 'utils/taskPayload.ts'), 'utf8')
|
||||
|
||||
const checks = [
|
||||
['dialog uses compact Navicat-like width', /width="630px"/.test(dialogSource)],
|
||||
['dialog uses shared runtime size class', /class="dbms-connection-size-dialog"/.test(dialogSource)],
|
||||
['dialog renders connection flow header', /class="connection-flow"/.test(dialogSource)],
|
||||
['dialog keeps Basic connection type visible', /model-value="Basic"/.test(dialogSource)],
|
||||
[
|
||||
'dialog exposes service name and SID radio choices',
|
||||
/el-radio[\s\S]*SERVICE_NAME[\s\S]*el-radio[\s\S]*SID/.test(dialogSource)
|
||||
],
|
||||
[
|
||||
'dialog keeps only common connection fields in the visible form',
|
||||
!/label="Schema"|label="Directory"|label="目录路径"|label="扩展配置"|label="备注"/.test(dialogSource)
|
||||
],
|
||||
[
|
||||
'dialog keeps selected database type for payload',
|
||||
/buildConnectionPayload\(form,\s*selectedDbType\.value\)/.test(dialogSource)
|
||||
],
|
||||
[
|
||||
'dialog uses fixed viewport-relative height',
|
||||
/:global\(\.dbms-connection-size-dialog\.el-dialog\)[\s\S]*height:\s*calc\(100vh - 170px\)/.test(dialogSource)
|
||||
],
|
||||
['dialog constrains height to viewport', /max-height:\s*calc\(100vh - 170px\)/.test(dialogSource)],
|
||||
['dialog avoids large fixed bottom whitespace', !/margin:\s*0 auto 178px/.test(dialogSource)],
|
||||
[
|
||||
'new Oracle connection defaults service name to ORCL',
|
||||
/serviceName:\s*resolveText\(record\?\.serviceName\)\s*\|\|\s*'ORCL'/.test(payloadSource)
|
||||
]
|
||||
]
|
||||
|
||||
const failures = checks.filter(([, passed]) => !passed)
|
||||
|
||||
if (failures.length) {
|
||||
console.error('dbms connection dialog layout contract failed:')
|
||||
failures.forEach(([message]) => console.error(`- ${message}`))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log('dbms connection dialog layout contract passed')
|
||||
@@ -0,0 +1,87 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const currentDir = path.dirname(fileURLToPath(import.meta.url))
|
||||
const pageDir = path.join(currentDir, '..')
|
||||
const missingFiles = []
|
||||
const read = file => {
|
||||
const filePath = path.join(pageDir, file)
|
||||
if (!fs.existsSync(filePath)) {
|
||||
missingFiles.push(file)
|
||||
return ''
|
||||
}
|
||||
return fs.readFileSync(filePath, 'utf8')
|
||||
}
|
||||
|
||||
const files = {
|
||||
page: 'index.vue',
|
||||
selector: 'components/DbmsConnectionTypeDialog.vue',
|
||||
connectionDialog: 'components/DbmsConnectionDialog.vue',
|
||||
taskPayload: 'utils/taskPayload.ts',
|
||||
apiTypes: '../../../api/system/dbms/interface/index.ts'
|
||||
}
|
||||
|
||||
const checks = [
|
||||
[
|
||||
'page renders connection type dialog',
|
||||
/<DbmsConnectionTypeDialog[\s\S]*@next="handleSelectConnectionType"/.test(read(files.page))
|
||||
],
|
||||
[
|
||||
'connect command opens type selector',
|
||||
/\bconnect:\s*\(\)\s*=>\s*openConnectionTypeDialog\(\)/.test(read(files.page))
|
||||
],
|
||||
[
|
||||
'new connection command opens type selector',
|
||||
/\bnewConnection:\s*\(\)\s*=>\s*openConnectionTypeDialog\(\)/.test(read(files.page))
|
||||
],
|
||||
['selector defaults to Oracle', /selectedType\s*=\s*ref<Dbms\.DbType>\('ORACLE'\)/.test(read(files.selector))],
|
||||
['selector width matches connection form dialog', /width="630px"/.test(read(files.selector))],
|
||||
['selector uses shared runtime size class', /dbms-connection-size-dialog/.test(read(files.selector))],
|
||||
['selector uses own stretch class', /dbms-connection-type-size-dialog/.test(read(files.selector))],
|
||||
['selector height matches connection form dialog', /height:\s*calc\(100vh - 170px\)/.test(read(files.selector))],
|
||||
[
|
||||
'selector height constraint matches connection form dialog',
|
||||
/max-height:\s*calc\(100vh - 170px\)/.test(read(files.selector))
|
||||
],
|
||||
[
|
||||
'selector body stretches content area',
|
||||
/dbms-connection-type-size-dialog \.el-dialog__body\)[\s\S]*display:\s*flex/.test(read(files.selector))
|
||||
],
|
||||
['selector content fills dialog body', /connection-type-dialog[\s\S]*flex:\s*1/.test(read(files.selector))],
|
||||
['selector only exposes Oracle and MySQL', /type:\s*'ORACLE'[\s\S]*type:\s*'MYSQL'/.test(read(files.selector))],
|
||||
['selector keeps next action explicit', /emit\('next',\s*selectedType\.value\)/.test(read(files.selector))],
|
||||
[
|
||||
'page blocks MySQL until backend is available',
|
||||
/if\s*\(dbType\s*===\s*'MYSQL'\)[\s\S]*MySQL 连接配置暂未接入/.test(read(files.page))
|
||||
],
|
||||
['connection form displays selected database type', /selectedDbType/.test(read(files.connectionDialog))],
|
||||
[
|
||||
'connection form open accepts selected database type',
|
||||
/open = \(nextMode: 'add' \| 'edit', record\?: Dbms\.ConnectionRecord, dbType: Dbms\.DbType = 'ORACLE'\)/.test(
|
||||
read(files.connectionDialog)
|
||||
)
|
||||
],
|
||||
[
|
||||
'connection form payload uses selected database type',
|
||||
/buildConnectionPayload\(form,\s*selectedDbType\.value\)/.test(read(files.connectionDialog))
|
||||
],
|
||||
[
|
||||
'payload builder accepts database type',
|
||||
/buildConnectionPayload[\s\S]*dbType: Dbms\.DbType = 'ORACLE'/.test(read(files.taskPayload))
|
||||
],
|
||||
['api type allows MySQL selection', /export type DbType = 'ORACLE' \| 'MYSQL'/.test(read(files.apiTypes))]
|
||||
]
|
||||
|
||||
const failures = [
|
||||
...missingFiles.map(file => [`required file exists: ${file}`, false]),
|
||||
...checks.filter(([, passed]) => !passed)
|
||||
]
|
||||
|
||||
if (failures.length) {
|
||||
console.error('dbms connection type dialog contract failed:')
|
||||
failures.forEach(([message]) => console.error(`- ${message}`))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log('dbms connection type dialog contract passed')
|
||||
@@ -0,0 +1,29 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const currentDir = path.dirname(fileURLToPath(import.meta.url))
|
||||
const pageDir = path.join(currentDir, '..')
|
||||
const read = file => fs.readFileSync(path.join(pageDir, file), 'utf8')
|
||||
|
||||
const pageSource = read('index.vue')
|
||||
|
||||
const onMountedBlock = pageSource.match(/onMounted\(\(\)\s*=>\s*\{[\s\S]*?\n\}\)/)?.[0] ?? ''
|
||||
|
||||
const checks = [
|
||||
['page should not auto load dbms overview on menu open', !onMountedBlock.includes('loadOverview()')],
|
||||
['page should not auto load dbms connections on menu open', !onMountedBlock.includes('loadConnections()')],
|
||||
['page should not auto load dbms tasks on menu open', !onMountedBlock.includes('loadTasks()')],
|
||||
['page should not auto load dbms files on menu open', !onMountedBlock.includes('loadFiles()')],
|
||||
['connection tree keeps manual refresh entry', /<DbmsConnectionTree[\s\S]*@refresh="loadConnections"/.test(pageSource)]
|
||||
]
|
||||
|
||||
const failures = checks.filter(([, passed]) => !passed)
|
||||
|
||||
if (failures.length) {
|
||||
console.error('dbms initial api contract failed:')
|
||||
failures.forEach(([message]) => console.error(`- ${message}`))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log('dbms initial api contract passed')
|
||||
@@ -0,0 +1,38 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const currentDir = path.dirname(fileURLToPath(import.meta.url))
|
||||
const pageDir = path.join(currentDir, '..')
|
||||
const read = file => fs.readFileSync(path.join(pageDir, file), 'utf8')
|
||||
|
||||
const files = {
|
||||
page: 'index.vue',
|
||||
toolbar: 'components/DbmsToolbar.vue',
|
||||
tree: 'components/DbmsConnectionTree.vue',
|
||||
workspace: 'components/DbmsWorkspace.vue'
|
||||
}
|
||||
|
||||
const checks = [
|
||||
['page renders dbms workbench shell', /class="dbms-workbench"/, read(files.page)],
|
||||
['page uses top toolbar', /<DbmsToolbar[\s\S]*@command="handleToolbarCommand"/, read(files.page)],
|
||||
['page uses collapsible connection tree', /<DbmsConnectionTree[\s\S]*:collapsed="treeCollapsed"/, read(files.page)],
|
||||
['page uses right workspace', /<DbmsWorkspace[\s\S]*:active-section="activeSection"/, read(files.page)],
|
||||
['toolbar exposes Navicat-like commands', /command:\s*'connect'[\s\S]*command:\s*'backup'[\s\S]*command:\s*'bi'/, read(files.toolbar)],
|
||||
['connection tree supports collapse toggle', /emit\('toggle'\)/, read(files.tree)],
|
||||
['connection tree groups tables and views', /type:\s*'tableGroup'[\s\S]*type:\s*'viewGroup'/, read(files.tree)],
|
||||
['workspace shows table grid', /<el-table[\s\S]*:data="tables"/, read(files.workspace)],
|
||||
['workspace keeps view empty state explicit', /暂无视图接口/, read(files.workspace)],
|
||||
['workspace can open task panel', /<DbmsTaskPanel/, read(files.workspace)],
|
||||
['workspace can open task status card', /<DbmsTaskStatusCard/, read(files.workspace)]
|
||||
]
|
||||
|
||||
const failures = checks.filter(([, passed]) => !passed)
|
||||
|
||||
if (failures.length) {
|
||||
console.error('dbms workbench layout contract failed:')
|
||||
failures.forEach(([message]) => console.error(`- ${message}`))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log('dbms workbench layout contract passed')
|
||||
Reference in New Issue
Block a user