Browse Source

逻辑已经OK,先提交

master
hejl 15 hours ago
parent
commit
5a1bdb7fc5
  1. 5
      gofaster/app/plugins/modules/api-collector.js
  2. 323
      gofaster/app/plugins/modules/call-chain-tracer.js
  3. 2
      gofaster/app/plugins/route-mapping-plugin.js
  4. 2
      gofaster/app/src/renderer/modules/role-management/components/PermissionManager.vue
  5. 8
      gofaster/app/src/renderer/modules/role-management/components/RolePermissionAssignment.vue
  6. 2
      gofaster/app/src/renderer/modules/role-management/components/UserRoleAssignment.vue
  7. 4
      gofaster/app/src/renderer/modules/role-management/views/RoleManagement.vue
  8. 138
      gofaster/app/src/renderer/modules/route-sync/direct-route-mappings.js
  9. 3
      gofaster/app/src/renderer/modules/user-management/components/PasswordChangeModal.vue
  10. 4
      gofaster/app/src/renderer/modules/user-management/views/UserManagement.vue

5
gofaster/app/plugins/modules/api-collector.js

@ -169,6 +169,11 @@ class ApiCollector { @@ -169,6 +169,11 @@ class ApiCollector {
// 只从@serverApiMethod注解中提取信息(强规则)
const annotationInfo = this.extractFromAnnotation(methodPath, servicePath)
if (annotationInfo) {
// 如果method是GET,跳过收集
if (annotationInfo.method === 'GET') {
return null
}
// 获取API基础URL
const apiBaseUrl = this.getApiBaseUrl()

323
gofaster/app/plugins/modules/call-chain-tracer.js

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
const { readFileSync, existsSync } = require('fs')
const { readFileSync, writeFileSync, existsSync } = require('fs')
const { resolve } = require('path')
const { parse } = require('@vue/compiler-sfc')
const parser = require('@babel/parser')
@ -11,6 +11,7 @@ const traverse = require('@babel/traverse').default @@ -11,6 +11,7 @@ const traverse = require('@babel/traverse').default
class CallChainTracer {
constructor() {
this.debugMode = process.env.ROUTE_MAPPING_DEBUG === 'true' || process.argv.includes('--debug')
this.processedFiles = new Set() // 跟踪已处理的文件,避免重复处理
}
/**
@ -29,37 +30,36 @@ class CallChainTracer { @@ -29,37 +30,36 @@ class CallChainTracer {
}
}
/**
* 清理已处理文件的记录
* 在每次新的处理周期开始时调用
*/
clearProcessedFiles() {
this.processedFiles.clear()
this.debugLog('已清理已处理文件记录')
}
/**
* 追溯所有method类型的触发源到可视控件
* @param {Array} apiMappings - API映射数组
* @returns {Array} 增强的API映射数组
*/
traceMethodTriggersToVisualComponents(apiMappings) {
this.debugLog('开始追溯method类型的触发源到可视控件')
this.debugLog('API映射数量', apiMappings.length)
const enhancedApiMappings = apiMappings.map(module => {
this.debugLog(`处理模块: ${module.module}`)
const enhancedApiMappings = module.apiMappings.map(api => {
if (!api.triggerSources || api.triggerSources.length === 0) {
this.debugLog(`API ${api.apiMethodName} 没有触发源,跳过`)
return api
}
this.debugLog(`处理API: ${api.apiMethodName},触发源数量: ${api.triggerSources.length}`)
// 只处理triggerType为method的触发源
const enhancedTriggerSources = api.triggerSources.map(trigger => {
if (trigger.triggerType === 'method') {
this.debugLog(`追溯method类型触发源: ${trigger.triggerName} in ${trigger.component}`)
const result = this.traceMethodToVisualComponent(
trigger,
module.module,
module.serviceName,
api.apiMethodName
)
this.debugLog(`追溯结果:`, result)
return result
}
return trigger
@ -77,7 +77,6 @@ class CallChainTracer { @@ -77,7 +77,6 @@ class CallChainTracer {
}
})
this.debugLog('追溯完成')
return enhancedApiMappings
}
@ -90,33 +89,25 @@ class CallChainTracer { @@ -90,33 +89,25 @@ class CallChainTracer {
* @returns {Object} 增强的触发源对象
*/
traceMethodToVisualComponent(trigger, moduleName, serviceName, apiMethodName) {
this.debugLog(`开始追溯method: ${trigger.triggerName} in ${trigger.component}`)
try {
// 查找组件文件
const componentPath = this.findComponentFile(trigger.component, moduleName)
this.debugLog(`查找组件文件: ${trigger.component} in ${moduleName}`, componentPath)
if (!componentPath) {
this.debugLog(`未找到组件文件: ${trigger.component}`)
return trigger
}
const content = readFileSync(componentPath, 'utf-8')
this.debugLog(`读取组件文件成功,内容长度: ${content.length}`)
// 解析Vue组件
const ast = this.parseVueComponent(content)
this.debugLog(`解析Vue组件结果:`, ast ? '成功' : '失败')
if (!ast) {
this.debugLog(`Vue组件解析失败`)
return trigger
}
// 建立函数调用关系映射
const functionCallMap = this.buildFunctionCallMap(ast)
this.debugLog(`建立函数调用关系映射,映射数量: ${functionCallMap.size}`)
// 追溯method到可视控件
const visualContext = this.traceToVisualComponent(
@ -126,22 +117,17 @@ class CallChainTracer { @@ -126,22 +117,17 @@ class CallChainTracer {
trigger.component
)
this.debugLog(`追溯可视控件结果:`, visualContext)
if (visualContext) {
const result = {
...trigger,
triggerName: visualContext.triggerName,
triggerType: visualContext.triggerType
}
this.debugLog(`追溯成功,返回结果:`, result)
return result
}
this.debugLog(`追溯失败,返回原始trigger`)
return trigger
} catch (error) {
this.debugLog(`追溯过程中发生错误:`, error.message)
return trigger
}
}
@ -153,28 +139,21 @@ class CallChainTracer { @@ -153,28 +139,21 @@ class CallChainTracer {
* @returns {string|null} 组件文件路径
*/
findComponentFile(componentName, moduleName) {
this.debugLog(`查找组件文件: ${componentName} in ${moduleName}`)
// 优先在指定模块中查找
if (moduleName) {
// 检查views目录
const viewPath = resolve(__dirname, `../../src/renderer/modules/${moduleName}/views/${componentName}.vue`)
this.debugLog(`检查views路径: ${viewPath}`, existsSync(viewPath))
if (existsSync(viewPath)) {
this.debugLog(`找到组件文件: ${viewPath}`)
return viewPath
}
// 检查components目录
const componentPath = resolve(__dirname, `../../src/renderer/modules/${moduleName}/components/${componentName}.vue`)
this.debugLog(`检查components路径: ${componentPath}`, existsSync(componentPath))
if (existsSync(componentPath)) {
this.debugLog(`找到组件文件: ${componentPath}`)
return componentPath
}
}
this.debugLog(`未找到组件文件: ${componentName}`)
return null
}
@ -187,15 +166,12 @@ class CallChainTracer { @@ -187,15 +166,12 @@ class CallChainTracer {
try {
// 提取script部分
const scriptMatch = content.match(/<script[^>]*>([\s\S]*?)<\/script>/)
this.debugLog(`提取script部分:`, scriptMatch ? '成功' : '失败')
if (!scriptMatch) {
this.debugLog(`未找到script标签`)
return null
}
const scriptContent = scriptMatch[1]
this.debugLog(`script内容长度: ${scriptContent.length}`)
// 使用Babel解析JavaScript
const ast = parser.parse(scriptContent, {
@ -203,10 +179,8 @@ class CallChainTracer { @@ -203,10 +179,8 @@ class CallChainTracer {
plugins: ['jsx', 'typescript']
})
this.debugLog(`Babel解析结果:`, ast ? '成功' : '失败')
return ast
} catch (error) {
this.debugLog(`解析Vue组件时发生错误:`, error.message)
return null
}
}
@ -280,31 +254,23 @@ class CallChainTracer { @@ -280,31 +254,23 @@ class CallChainTracer {
* @returns {Object|null} 可视控件上下文
*/
traceToVisualComponent(methodName, functionCallMap, filePath, componentName) {
this.debugLog(`追溯method到可视控件: ${methodName}`)
try {
// 读取组件文件内容
const content = readFileSync(filePath, 'utf-8')
// 分析模板中的事件绑定
this.debugLog(`分析模板中的事件绑定: ${methodName}`)
const visualContext = this.analyzeTemplateForMethod(content, methodName, componentName, filePath)
this.debugLog(`模板分析结果:`, visualContext)
if (visualContext) {
this.debugLog(`在模板中找到事件绑定`)
return visualContext
}
// 如果模板中没有找到,检查是否有其他方法调用了这个方法
this.debugLog(`模板中未找到,检查方法调用关系`)
const callerContext = this.findMethodCaller(methodName, functionCallMap)
this.debugLog(`找到调用者:`, callerContext)
if (callerContext) {
// 检查调用者是否是生命周期钩子
if (this.isLifecycleHook(callerContext)) {
this.debugLog(`调用者是生命周期钩子: ${callerContext}`)
return {
triggerName: '',
triggerType: 'page'
@ -312,13 +278,10 @@ class CallChainTracer { @@ -312,13 +278,10 @@ class CallChainTracer {
}
// 继续递归追溯
this.debugLog(`递归追溯调用者: ${callerContext}`)
return this.traceToVisualComponent(callerContext, functionCallMap, filePath, componentName)
}
this.debugLog(`未找到调用者,追溯失败`)
} catch (error) {
this.debugLog(`追溯可视控件时发生错误:`, error.message)
// 静默处理错误
}
return null
@ -333,36 +296,27 @@ class CallChainTracer { @@ -333,36 +296,27 @@ class CallChainTracer {
* @returns {Object|null} 可视控件上下文
*/
analyzeTemplateForMethod(content, methodName, componentName, filePath) {
this.debugLog(`分析模板中的方法调用: ${methodName}`)
try {
// 使用Vue编译器解析单文件组件
const { descriptor } = parse(content)
this.debugLog(`Vue编译器解析结果:`, descriptor ? '成功' : '失败')
if (!descriptor.template) {
this.debugLog(`未找到template部分`)
return null
}
// 解析模板AST
const templateAst = descriptor.template.ast
this.debugLog(`模板AST解析结果:`, templateAst ? '成功' : '失败')
if (!templateAst) {
this.debugLog(`模板AST解析失败`)
return null
}
// 遍历模板AST,查找事件绑定
this.debugLog(`开始遍历模板AST查找事件绑定`)
const result = this.findEventBindingInTemplate(templateAst, methodName, componentName, filePath)
this.debugLog(`模板AST遍历结果:`, result)
return result
} catch (error) {
this.debugLog(`分析模板时发生错误:`, error.message)
return null
}
}
@ -376,49 +330,33 @@ class CallChainTracer { @@ -376,49 +330,33 @@ class CallChainTracer {
* @returns {Object|null} 可视组件上下文
*/
findEventBindingInTemplate(node, methodName, componentName, filePath) {
this.debugLog(`查找事件绑定: ${methodName} in ${node.tag || 'root'}`)
if (!node) {
this.debugLog(`节点为空`)
return null
}
// 检查当前节点是否有事件绑定
if (node.props) {
this.debugLog(`检查节点属性,属性数量: ${node.props.length}`)
for (const prop of node.props) {
if (prop.type === 7) { // DIRECTIVE类型
const eventName = prop.name
this.debugLog(`检查指令: ${eventName}`)
if (eventName === 'on' && prop.arg) {
const eventType = prop.arg.content
this.debugLog(`检查事件类型: ${eventType}`)
if (['click', 'submit', 'change', 'input'].includes(eventType)) {
this.debugLog(`匹配事件类型: ${eventType}`)
// 检查事件处理函数
if (prop.exp && this.isMethodCall(prop.exp, methodName)) {
this.debugLog(`找到匹配的方法调用: ${methodName}`)
const context = this.createVisualContext(node, eventType, componentName, methodName, filePath)
this.debugLog(`创建可视上下文:`, context)
// 如果找到的是form,需要查找其中的submit按钮
if (context.triggerType === 'form') {
this.debugLog(`找到form,查找submit按钮`)
const submitButton = this.findSubmitButtonInForm(node, componentName, methodName, filePath)
if (submitButton) {
this.debugLog(`找到submit按钮:`, submitButton)
return submitButton
}
}
return context
} else {
this.debugLog(`事件处理函数不匹配: ${methodName}`)
}
}
}
@ -428,20 +366,16 @@ class CallChainTracer { @@ -428,20 +366,16 @@ class CallChainTracer {
// 递归检查子节点
if (node.children) {
this.debugLog(`递归检查子节点,子节点数量: ${node.children.length}`)
for (const child of node.children) {
if (child.type === 1) { // ELEMENT类型
const result = this.findEventBindingInTemplate(child, methodName, componentName, filePath)
if (result) {
this.debugLog(`在子节点中找到结果:`, result)
return result
}
}
}
}
this.debugLog(`未找到事件绑定`)
return null
}
@ -451,7 +385,7 @@ class CallChainTracer { @@ -451,7 +385,7 @@ class CallChainTracer {
* @param {string} componentName - 组件名称
* @param {string} methodName - 方法名称
* @param {string} filePath - 组件文件路径
* @returns {Object|null} submit按钮上下文
* @returns {Object|null} submit按钮节点和上下文
*/
findSubmitButtonInForm(formNode, componentName, methodName, filePath) {
if (!formNode || !formNode.children) return null
@ -476,6 +410,7 @@ class CallChainTracer { @@ -476,6 +410,7 @@ class CallChainTracer {
triggerName = `${componentName.toLowerCase()}-submit-${this.generateUniqueSuffix()}`
}
return {
node: child,
triggerName: triggerName,
triggerType: 'button'
}
@ -498,35 +433,26 @@ class CallChainTracer { @@ -498,35 +433,26 @@ class CallChainTracer {
* @returns {boolean} 是否是方法调用
*/
isMethodCall(exp, methodName) {
this.debugLog(`检查表达式是否是方法调用: ${methodName}`)
this.debugLog(`表达式类型: ${exp.type}`, exp)
if (!exp) {
this.debugLog(`表达式为空`)
return false
}
// 简单的方法调用:methodName
if (exp.type === 4 && exp.content === methodName) { // SIMPLE_EXPRESSION
this.debugLog(`匹配简单方法调用: ${methodName}`)
return true
}
// 带参数的方法调用:methodName(...) - 检查content是否以methodName开头
if (exp.type === 4 && exp.content && exp.content.startsWith(methodName + '(')) {
this.debugLog(`匹配带参数的方法调用: ${methodName}`)
return true
}
// 带参数的方法调用:methodName(...)
if (exp.type === 8) { // COMPOUND_EXPRESSION
this.debugLog(`检查复合表达式`)
const children = exp.children
if (children && children.length >= 1) {
const firstChild = children[0]
this.debugLog(`第一个子节点:`, firstChild)
if (firstChild.type === 4 && firstChild.content === methodName) {
this.debugLog(`匹配复合表达式中的方法调用: ${methodName}`)
return true
}
}
@ -534,13 +460,10 @@ class CallChainTracer { @@ -534,13 +460,10 @@ class CallChainTracer {
// 检查AST中的方法调用
if (exp.ast) {
this.debugLog(`检查AST中的方法调用`)
const result = this.checkAstMethodCall(exp.ast, methodName)
this.debugLog(`AST检查结果:`, result)
return result
}
this.debugLog(`未匹配任何方法调用模式`)
return false
}
@ -613,6 +536,24 @@ class CallChainTracer { @@ -613,6 +536,24 @@ class CallChainTracer {
triggerName = `${componentName.toLowerCase()}-${tag}-${this.generateUniqueSuffix()}`
}
// 先处理form追溯到button的逻辑
if (triggerType === 'form') {
const submitButton = this.findSubmitButtonInForm(node, componentName, methodName, filePath)
if (submitButton) {
// 如果找到submit按钮,为真正的button节点添加属性
this.modifyVueElementWithCompiler(filePath, submitButton.node, submitButton.triggerName, submitButton.triggerType)
return {
triggerName: submitButton.triggerName,
triggerType: submitButton.triggerType
}
}
}
// 为最终确定的控件添加name属性和权限控制
if (triggerType === 'button') {
this.modifyVueElementWithCompiler(filePath, node, triggerName, triggerType)
}
return {
triggerName: triggerName,
triggerType: triggerType
@ -657,6 +598,206 @@ class CallChainTracer { @@ -657,6 +598,206 @@ class CallChainTracer {
generateUniqueSuffix() {
return Math.random().toString(36).substr(2, 6)
}
/**
* 使用精确位置修改Vue文件中的元素
* @param {string} filePath - Vue文件路径
* @param {Object} node - AST节点
* @param {string} nameValue - name属性值
* @param {string} triggerType - 触发类型
*/
modifyVueElementWithCompiler(filePath, node, nameValue, triggerType) {
try {
// 检查文件是否已经被处理过,避免重复处理
const fileKey = `${filePath}-${nameValue}`
if (this.processedFiles.has(fileKey)) {
this.debugLog(`文件 ${filePath}${nameValue} 已被处理过,跳过`)
return
}
const content = readFileSync(filePath, 'utf-8')
this.debugLog(`开始修改Vue文件: ${filePath}`)
this.debugLog(`目标节点: ${node.tag}, name: ${nameValue}, type: ${triggerType}`)
// 获取节点的位置信息
const loc = node.loc
if (!loc) {
this.debugLog(`节点没有位置信息,无法修改Vue元素`)
return
}
const startLine = loc.start.line
const startColumn = loc.start.column
const endLine = loc.end.line
const endColumn = loc.end.column
this.debugLog(`节点位置: 第${startLine}行第${startColumn}列 到 第${endLine}行第${endColumn}`)
const lines = content.split('\n')
// 检查是否已经存在name属性或:visible属性,避免重复修改
const targetLine = lines[startLine - 1]
if (targetLine.includes(`name="`) || targetLine.includes(`name='`) ||
targetLine.includes(`:visible="false"`) || targetLine.includes(`:visible='false'`)) {
this.debugLog(`元素已包含name或:visible属性,跳过修改`)
return
}
// 处理单行元素
if (startLine === endLine) {
this.modifySingleLineElement(lines, startLine - 1, startColumn, endColumn, nameValue, triggerType)
} else {
// 处理多行元素
this.modifyMultiLineElement(lines, startLine - 1, startColumn, endLine - 1, endColumn, nameValue, triggerType)
}
// 写回文件
const newContent = lines.join('\n')
writeFileSync(filePath, newContent, 'utf-8')
// 标记文件为已处理
this.processedFiles.add(fileKey)
this.debugLog(`已成功修改Vue文件: ${filePath}`)
this.debugLog(`添加的属性: name="${nameValue}"${triggerType === 'button' ? ', :visible="false"' : ', :disabled="true"'}`)
} catch (error) {
this.debugLog(`修改Vue元素时出错:`, error.message)
this.debugLog(`错误堆栈:`, error.stack)
}
}
/**
* 修改单行元素
* @param {Array} lines - 文件行数组
* @param {number} lineIndex - 行索引
* @param {number} startCol - 开始列
* @param {number} endCol - 结束列
* @param {string} nameValue - name属性值
* @param {string} triggerType - 触发类型
*/
modifySingleLineElement(lines, lineIndex, startCol, endCol, nameValue, triggerType) {
const line = lines[lineIndex]
this.debugLog(`修改单行元素: ${line}`)
// 检查是否已经存在name属性或:visible属性,避免重复修改
if (line.includes(`name="`) || line.includes(`name='`) ||
line.includes(`:visible="false"`) || line.includes(`:visible='false'`)) {
this.debugLog(`单行元素已包含name或:visible属性,跳过修改`)
return
}
// 找到开始标签的结束位置
// AST列号从1开始,需要转换为从0开始的索引
const tagStart = line.indexOf('<', startCol - 1)
const tagEnd = line.indexOf('>', tagStart)
if (tagStart !== -1 && tagEnd !== -1) {
const beforeTag = line.substring(0, tagEnd)
const afterTag = line.substring(tagEnd)
// 构建新的属性
let newAttributes = ` name="${nameValue}"`
if (triggerType === 'button') {
newAttributes += ` :visible="false"`
} else {
newAttributes += ` :disabled="true"`
}
lines[lineIndex] = `${beforeTag}${newAttributes}${afterTag}`
this.debugLog(`单行元素修改完成: ${lines[lineIndex]}`)
}
}
/**
* 修改多行元素
* @param {Array} lines - 文件行数组
* @param {number} startLineIndex - 开始行索引
* @param {number} startCol - 开始列
* @param {number} endLineIndex - 结束行索引
* @param {number} endCol - 结束列
* @param {string} nameValue - name属性值
* @param {string} triggerType - 触发类型
*/
modifyMultiLineElement(lines, startLineIndex, startCol, endLineIndex, endCol, nameValue, triggerType) {
const startLine = lines[startLineIndex]
this.debugLog(`修改多行元素开始行: ${startLine}`)
// 检查整个多行元素是否已经存在name属性或:visible属性,避免重复修改
let hasExistingAttributes = false
for (let i = startLineIndex; i <= endLineIndex && i < lines.length; i++) {
const line = lines[i]
if (line.includes(`name="`) || line.includes(`name='`) ||
line.includes(`:visible="false"`) || line.includes(`:visible='false'`)) {
hasExistingAttributes = true
break
}
}
if (hasExistingAttributes) {
this.debugLog(`多行元素已包含name或:visible属性,跳过修改`)
return
}
// 找到开始标签的结束位置
// AST列号从1开始,需要转换为从0开始的索引
const tagStart = startLine.indexOf('<', startCol - 1)
let tagEnd = startLine.indexOf('>', tagStart)
let tagEndLineIndex = startLineIndex
// 如果当前行没有找到结束标签,查找后续行
if (tagStart !== -1 && tagEnd === -1) {
this.debugLog(`当前行没有找到结束标签,查找后续行`)
for (let i = startLineIndex; i <= endLineIndex && i < lines.length; i++) {
const line = lines[i]
const endPos = line.indexOf('>')
if (endPos !== -1) {
tagEnd = endPos
tagEndLineIndex = i
this.debugLog(`在第${i + 1}行找到结束标签,位置: ${endPos}`)
break
}
}
}
if (tagStart !== -1 && tagEnd !== -1) {
// 构建新的属性
let newAttributes = ` name="${nameValue}"`
if (triggerType === 'button') {
newAttributes += ` :visible="false"`
} else {
newAttributes += ` :disabled="true"`
}
// 在结束标签前添加属性
const endLine = lines[tagEndLineIndex]
const beforeEndTag = endLine.substring(0, tagEnd)
const afterEndTag = endLine.substring(tagEnd)
lines[tagEndLineIndex] = `${beforeEndTag}${newAttributes}${afterEndTag}`
this.debugLog(`多行元素修改完成: ${lines[tagEndLineIndex]}`)
} else {
this.debugLog(`未找到有效的标签位置: tagStart=${tagStart}, tagEnd=${tagEnd}`)
// 如果找不到结束标签,尝试在开始标签后直接添加
if (tagStart !== -1) {
this.debugLog(`尝试在开始标签后直接添加属性`)
const beforeTag = startLine.substring(0, tagStart + 1) // 包含 < 字符
const afterTag = startLine.substring(tagStart + 1)
let newAttributes = ` name="${nameValue}"`
if (triggerType === 'button') {
newAttributes += ` :visible="false"`
} else {
newAttributes += ` :disabled="true"`
}
lines[startLineIndex] = `${beforeTag}${newAttributes} ${afterTag}`
this.debugLog(`多行元素修改完成(备用方案): ${lines[startLineIndex]}`)
}
}
}
}
module.exports = CallChainTracer

2
gofaster/app/plugins/route-mapping-plugin.js

@ -144,6 +144,8 @@ function routeMappingPlugin() { @@ -144,6 +144,8 @@ function routeMappingPlugin() {
const enhancedApiMappings = this._triggerAnalyzer.findTriggerSourcesForApiMappings(apiMappings, routes)
// ========== 第二步半:调用链追溯 ==========
// 清理已处理文件的记录,开始新的处理周期
this._callChainTracer.clearProcessedFiles()
const tracedApiMappings = this._callChainTracer.traceMethodTriggersToVisualComponents(enhancedApiMappings)
// 生成包含triggerSources的文件

2
gofaster/app/src/renderer/modules/role-management/components/PermissionManager.vue

@ -55,7 +55,7 @@ @@ -55,7 +55,7 @@
<div class="modal-footer">
<button class="btn btn-secondary" @click="handleClose">取消</button>
<button class="btn btn-primary" @click="savePermissions" :disabled="saving">
<button class="btn btn-primary" @click="savePermissions" :disabled="saving" name="permissionmanager-button-k7wqyp" :visible="false">
{{ saving ? '保存中...' : '保存权限' }}
</button>
</div>

8
gofaster/app/src/renderer/modules/role-management/components/RolePermissionAssignment.vue

@ -63,7 +63,7 @@ @@ -63,7 +63,7 @@
<button
class="btn btn-sm btn-danger"
@click="removeSelectedPermissions"
:disabled="selectedAssignedPermissions.length === 0">
:disabled="selectedAssignedPermissions.length === 0" name="rolepermissionassignment-button-sj6qb7" :visible="false">
<i class="fas fa-minus"></i>
移除选中 ({{ selectedAssignedPermissions.length }})
</button>
@ -109,7 +109,7 @@ @@ -109,7 +109,7 @@
class="btn btn-sm btn-danger"
@click.stop="removePermission(permission.id)"
title="移除权限"
>
name="rolepermissionassignment-button-q86qi4" :visible="false">
<i class="fas fa-minus"></i>
</button>
</div>
@ -125,7 +125,7 @@ @@ -125,7 +125,7 @@
<button
class="btn btn-sm btn-primary"
@click="assignSelectedPermissions"
:disabled="selectedAvailablePermissions.length === 0">
:disabled="selectedAvailablePermissions.length === 0" name="rolepermissionassignment-button-a0nyh8" :visible="false">
<i class="fas fa-plus"></i>
分配选中 ({{ selectedAvailablePermissions.length }})
</button>
@ -171,7 +171,7 @@ @@ -171,7 +171,7 @@
class="btn btn-sm btn-primary"
@click.stop="assignPermission(permission.id)"
title="分配权限"
>
name="rolepermissionassignment-button-7uizm5" :visible="false">
<i class="fas fa-plus"></i>
</button>
</div>

2
gofaster/app/src/renderer/modules/role-management/components/UserRoleAssignment.vue

@ -82,7 +82,7 @@ @@ -82,7 +82,7 @@
<div class="modal-footer">
<button class="btn btn-secondary" @click="handleClose">取消</button>
<button class="btn btn-primary" @click="saveRoleAssignment" :disabled="saving">
<button class="btn btn-primary" @click="saveRoleAssignment" :disabled="saving" name="userroleassignment-button-3npmn8" :visible="false">
{{ saving ? '保存中...' : '保存分配' }}
</button>
</div>

4
gofaster/app/src/renderer/modules/role-management/views/RoleManagement.vue

@ -58,7 +58,7 @@ @@ -58,7 +58,7 @@
<button class="btn btn-sm btn-primary" @click="assignPermissions(role)" title="分配权限">
<i class="fas fa-shield-alt"></i>
</button>
<button class="btn btn-sm btn-danger" @click="deleteRole(role)" title="删除角色">
<button class="btn btn-sm btn-danger" @click="deleteRole(role)" title="删除角色" name="rolemanagement-button-0eqx80" :visible="false">
<i class="fas fa-trash"></i>
</button>
</div>
@ -177,7 +177,7 @@ @@ -177,7 +177,7 @@
<button type="button" class="btn btn-secondary" @click="showCreateDialog = false">
取消
</button>
<button type="submit" class="btn btn-primary" :disabled="saving">
<button type="submit" class="btn btn-primary" :disabled="saving" name="rolemanagement-submit-lhm6fs" :visible="false">
{{ saving ? '保存中...' : (editingRole ? '更新' : '创建') }}
</button>
</div>

138
gofaster/app/src/renderer/modules/route-sync/direct-route-mappings.js

@ -33,35 +33,6 @@ export default { @@ -33,35 +33,6 @@ export default {
"module": "role-management",
"serviceName": "roleService",
"apiMappings": [
{
"apiMethodName": "getRoles",
"method": "GET",
"path": "/api/auth/roles",
"triggerSources": [
{
"component": "RoleManagement",
"triggerName": "rolemanagement-submit-vkpa24",
"triggerType": "button"
},
{
"component": "UserRoleAssignment",
"triggerName": "",
"triggerType": "page"
}
]
},
{
"apiMethodName": "getRole",
"method": "GET",
"path": "/api/auth/roles/{id}",
"triggerSources": [
{
"component": "PermissionManager",
"triggerName": "",
"triggerType": "page"
}
]
},
{
"apiMethodName": "createRole",
"method": "POST",
@ -69,7 +40,7 @@ export default { @@ -69,7 +40,7 @@ export default {
"triggerSources": [
{
"component": "RoleManagement",
"triggerName": "rolemanagement-submit-t64ch2",
"triggerName": "rolemanagement-submit-lhm6fs",
"triggerType": "button"
}
]
@ -81,12 +52,12 @@ export default { @@ -81,12 +52,12 @@ export default {
"triggerSources": [
{
"component": "RoleManagement",
"triggerName": "rolemanagement-submit-5jkynw",
"triggerName": "rolemanagement-submit-lhm6fs",
"triggerType": "button"
},
{
"component": "PermissionManager",
"triggerName": "permissionmanager-button-aemgfa",
"triggerName": "permissionmanager-button-k7wqyp",
"triggerType": "button"
}
]
@ -98,28 +69,11 @@ export default { @@ -98,28 +69,11 @@ export default {
"triggerSources": [
{
"component": "RoleManagement",
"triggerName": "rolemanagement-button-u8kwcq",
"triggerName": "rolemanagement-button-0eqx80",
"triggerType": "button"
}
]
},
{
"apiMethodName": "getPermissions",
"method": "GET",
"path": "/api/auth/permissions",
"triggerSources": [
{
"component": "PermissionManager",
"triggerName": "",
"triggerType": "page"
},
{
"component": "RolePermissionAssignment",
"triggerName": "",
"triggerType": "page"
}
]
},
{
"apiMethodName": "assignRolesToUser",
"method": "POST",
@ -127,23 +81,11 @@ export default { @@ -127,23 +81,11 @@ export default {
"triggerSources": [
{
"component": "UserRoleAssignment",
"triggerName": "userroleassignment-button-ws5dcn",
"triggerName": "userroleassignment-button-3npmn8",
"triggerType": "button"
}
]
},
{
"apiMethodName": "getUserRoles",
"method": "GET",
"path": "/api/auth/roles/users/{userId}",
"triggerSources": [
{
"component": "UserRoleAssignment",
"triggerName": "",
"triggerType": "page"
}
]
},
{
"apiMethodName": "removeRolesFromUser",
"method": "DELETE",
@ -151,23 +93,11 @@ export default { @@ -151,23 +93,11 @@ export default {
"triggerSources": [
{
"component": "UserRoleAssignment",
"triggerName": "userroleassignment-button-dz2004",
"triggerName": "userroleassignment-button-3npmn8",
"triggerType": "button"
}
]
},
{
"apiMethodName": "getRolePermissions",
"method": "GET",
"path": "/api/auth/permissions/roles/{roleId}",
"triggerSources": [
{
"component": "RolePermissionAssignment",
"triggerName": "",
"triggerType": "page"
}
]
},
{
"apiMethodName": "assignPermissionsToRole",
"method": "POST",
@ -175,12 +105,12 @@ export default { @@ -175,12 +105,12 @@ export default {
"triggerSources": [
{
"component": "RolePermissionAssignment",
"triggerName": "rolepermissionassignment-button-m0nq2i",
"triggerName": "rolepermissionassignment-button-7uizm5",
"triggerType": "button"
},
{
"component": "RolePermissionAssignment",
"triggerName": "rolepermissionassignment-button-k2c65f",
"triggerName": "rolepermissionassignment-button-a0nyh8",
"triggerType": "button"
}
]
@ -192,12 +122,12 @@ export default { @@ -192,12 +122,12 @@ export default {
"triggerSources": [
{
"component": "RolePermissionAssignment",
"triggerName": "rolepermissionassignment-button-5fs10k",
"triggerName": "rolepermissionassignment-button-q86qi4",
"triggerType": "button"
},
{
"component": "RolePermissionAssignment",
"triggerName": "rolepermissionassignment-button-9ld5tc",
"triggerName": "rolepermissionassignment-button-sj6qb7",
"triggerType": "button"
}
]
@ -208,18 +138,6 @@ export default { @@ -208,18 +138,6 @@ export default {
"module": "user-management",
"serviceName": "userService",
"apiMappings": [
{
"apiMethodName": "getUsers",
"method": "GET",
"path": "/api/auth/admin/users",
"triggerSources": [
{
"component": "UserManagement",
"triggerName": "usermanagement-a-n900tn",
"triggerType": "element"
}
]
},
{
"apiMethodName": "createUser",
"method": "POST",
@ -227,7 +145,7 @@ export default { @@ -227,7 +145,7 @@ export default {
"triggerSources": [
{
"component": "UserManagement",
"triggerName": "usermanagement-submit-2t2744",
"triggerName": "usermanagement-submit-fksbqh",
"triggerType": "button"
}
]
@ -239,7 +157,7 @@ export default { @@ -239,7 +157,7 @@ export default {
"triggerSources": [
{
"component": "UserManagement",
"triggerName": "usermanagement-submit-goov4g",
"triggerName": "usermanagement-submit-fksbqh",
"triggerType": "button"
}
]
@ -251,7 +169,7 @@ export default { @@ -251,7 +169,7 @@ export default {
"triggerSources": [
{
"component": "UserManagement",
"triggerName": "usermanagement-button-a21wgq",
"triggerName": "usermanagement-button-tvncrr",
"triggerType": "button"
}
]
@ -263,23 +181,11 @@ export default { @@ -263,23 +181,11 @@ export default {
"triggerSources": [
{
"component": "PasswordChangeModal",
"triggerName": "passwordchangemodal-submit-y40w1v",
"triggerName": "passwordchangemodal-submit-2p704c",
"triggerType": "button"
}
]
},
{
"apiMethodName": "getPasswordPolicy",
"method": "GET",
"path": "/api/auth/password-policy",
"triggerSources": [
{
"component": "PasswordChangeModal",
"triggerName": "",
"triggerType": "page"
}
]
},
{
"apiMethodName": "validatePassword",
"method": "POST",
@ -287,23 +193,11 @@ export default { @@ -287,23 +193,11 @@ export default {
"triggerSources": [
{
"component": "PasswordChangeModal",
"triggerName": "passwordchangemodal-input-23dc8n",
"triggerName": "passwordchangemodal-input-b0ca4h",
"triggerType": "input"
}
]
},
{
"apiMethodName": "getCurrentUser",
"method": "GET",
"path": "/api/auth/me",
"triggerSources": [
{
"component": "UserProfile",
"triggerName": "userprofile-button-yfevhp",
"triggerType": "button"
}
]
},
{
"apiMethodName": "changePassword",
"method": "POST",
@ -311,7 +205,7 @@ export default { @@ -311,7 +205,7 @@ export default {
"triggerSources": [
{
"component": "PasswordChangeModal",
"triggerName": "passwordchangemodal-submit-m67po9",
"triggerName": "passwordchangemodal-submit-2p704c",
"triggerType": "button"
}
]

3
gofaster/app/src/renderer/modules/user-management/components/PasswordChangeModal.vue

@ -117,8 +117,7 @@ @@ -117,8 +117,7 @@
<button
type="submit"
class="btn btn-primary"
:disabled="loading || !isFormValid"
>
:disabled="loading || !isFormValid" name="passwordchangemodal-submit-2p704c" :visible="false">
<span v-if="loading" class="loading-spinner"></span>
{{ submitText }}
</button>

4
gofaster/app/src/renderer/modules/user-management/views/UserManagement.vue

@ -71,7 +71,7 @@ @@ -71,7 +71,7 @@
<button class="btn btn-sm btn-primary" @click="assignRoles(user)">
<i class="fas fa-user-shield"></i>
</button>
<button class="btn btn-sm btn-danger" @click="deleteUser(user.id)">
<button class="btn btn-sm btn-danger" @click="deleteUser(user.id)" name="usermanagement-button-tvncrr" :visible="false">
<i class="fas fa-trash"></i>
</button>
</div>
@ -200,7 +200,7 @@ @@ -200,7 +200,7 @@
<button type="button" class="btn btn-secondary" @click="closeModal">
取消
</button>
<button type="submit" class="btn btn-primary">
<button type="submit" class="btn btn-primary" name="usermanagement-submit-fksbqh" :visible="false">
{{ showEditUserModal ? '更新' : '创建' }}
</button>
</div>

Loading…
Cancel
Save