Compare commits

...

3 Commits

Author SHA1 Message Date
hejl 4cc8379d97 Merge branch 'master' of http://47.98.153.252:3000/hejl/manta 1 week ago
hejl cceb30aaba 修复前后台和swagger 1 week ago
hejl a3fc5c4d4f 修复前台错误 1 week ago
  1. 2
      gofaster/app/dist/renderer/js/index.js
  2. 419
      gofaster/app/src/main/index.js
  3. 548
      gofaster/app/src/renderer/modules/role-management/views/RoleApiTest.vue
  4. 1
      gofaster/backend/tmp/build-errors.log
  5. BIN
      gofaster/backend/tmp/main.exe

2
gofaster/app/dist/renderer/js/index.js vendored

@ -14510,7 +14510,7 @@ __webpack_require__.r(__webpack_exports__); @@ -14510,7 +14510,7 @@ __webpack_require__.r(__webpack_exports__);
/******/
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
/******/ __webpack_require__.h = () => ("fd7db7612102d9d9")
/******/ __webpack_require__.h = () => ("a30697658a725fba")
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */

419
gofaster/app/src/main/index.js

@ -65,7 +65,13 @@ let isDev = null @@ -65,7 +65,13 @@ let isDev = null
function getIsDev() {
if (isDev === null) {
try {
isDev = process.env.NODE_ENV === 'development' || !app.isPackaged
// 确保app对象可用
if (app && typeof app.isPackaged === 'boolean') {
isDev = process.env.NODE_ENV === 'development' || !app.isPackaged
} else {
// 如果app对象还没有准备好,默认使用开发环境
isDev = process.env.NODE_ENV === 'development' || true
}
} catch (error) {
// 如果app对象还没有准备好,默认使用开发环境
isDev = process.env.NODE_ENV === 'development' || true
@ -77,6 +83,12 @@ function getIsDev() { @@ -77,6 +83,12 @@ function getIsDev() {
// 初始化日志系统
function initLogging() {
try {
// 确保app对象可用
if (!app || typeof app.getPath !== 'function') {
console.warn('app对象不可用,跳过日志系统初始化');
return;
}
// 创建日志目录
const logDir = path.join(app.getPath('userData'), 'logs')
if (!fs.existsSync(logDir)) {
@ -155,6 +167,7 @@ if (getIsDev() && !process.argv.includes('--watch')) { @@ -155,6 +167,7 @@ if (getIsDev() && !process.argv.includes('--watch')) {
/\.git|[\/\\]\./
]
});
console.log('热重载已启用');
} catch (error) {
console.log('Hot reload failed:', error.message);
}
@ -348,12 +361,9 @@ function createWindow() { @@ -348,12 +361,9 @@ function createWindow() {
setTimeout(() => {
try {
const { spawn } = require('child_process');
// 在 Windows 环境下使用 npm.cmd
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
const buildProcess = spawn(npmCommand, ['run', 'build:vue'], {
const buildProcess = spawn('npm', ['run', 'build:vue'], {
cwd: appRoot,
stdio: 'pipe',
shell: true
stdio: 'pipe'
});
buildProcess.on('close', (code) => {
@ -505,212 +515,225 @@ function createWindow() { @@ -505,212 +515,225 @@ function createWindow() {
}
}
app.whenReady().then(() => {
// 初始化窗口状态管理器
initWindowStateManager()
// 初始化日志系统
initLogging()
createWindow()
// 确保app对象可用后再调用whenReady
if (app && typeof app.whenReady === 'function') {
app.whenReady().then(() => {
// 初始化窗口状态管理器
initWindowStateManager()
// 初始化日志系统
initLogging()
createWindow()
// 修复IPC通信问题
ipcMain.on('request-status', (event) => {
try {
const statusData = {
status: 'running',
timestamp: Date.now()
// 修复IPC通信问题
ipcMain.on('request-status', (event) => {
try {
const statusData = {
status: 'running',
timestamp: Date.now()
}
event.sender.send('status-update', statusData)
} catch (error) {
console.error('IPC communication error:', error);
}
event.sender.send('status-update', statusData)
} catch (error) {
console.error('IPC communication error:', error);
}
})
})
// 添加获取进程内存信息的API
ipcMain.handle('get-process-memory-info', async (event) => {
try {
// 使用 process.memoryUsage 获取内存信息
const memoryUsage = process.memoryUsage();
// 获取更详细的系统内存信息
let systemMemoryInfo = {};
// 添加获取进程内存信息的API
ipcMain.handle('get-process-memory-info', async (event) => {
try {
// 尝试使用 require('os') 获取系统内存信息
const os = require('os');
systemMemoryInfo = {
totalMemory: os.totalmem(),
freeMemory: os.freemem(),
usedMemory: os.totalmem() - os.freemem()
// 使用 process.memoryUsage 获取内存信息
const memoryUsage = process.memoryUsage();
// 获取更详细的系统内存信息
let systemMemoryInfo = {};
try {
// 尝试使用 require('os') 获取系统内存信息
const os = require('os');
systemMemoryInfo = {
totalMemory: os.totalmem(),
freeMemory: os.freemem(),
usedMemory: os.totalmem() - os.freemem()
};
} catch (osError) {
console.warn('Cannot get system memory info:', osError.message);
}
return {
// 进程内存使用情况
privateBytes: memoryUsage.rss, // Resident Set Size - 进程占用的物理内存
sharedBytes: memoryUsage.external, // 外部内存使用
heapUsed: memoryUsage.heapUsed, // JavaScript堆内存使用
heapTotal: memoryUsage.heapTotal, // JavaScript堆内存总量
// 系统内存信息
systemTotal: systemMemoryInfo.totalMemory || 0,
systemFree: systemMemoryInfo.freeMemory || 0,
systemUsed: systemMemoryInfo.usedMemory || 0
};
} catch (error) {
console.error('Failed to get memory info:', error);
// 返回默认值
return {
privateBytes: 0,
sharedBytes: 0,
heapUsed: 0,
heapTotal: 0,
systemTotal: 0,
systemFree: 0,
systemUsed: 0
};
} catch (osError) {
console.warn('Cannot get system memory info:', osError.message);
}
return {
// 进程内存使用情况
privateBytes: memoryUsage.rss, // Resident Set Size - 进程占用的物理内存
sharedBytes: memoryUsage.external, // 外部内存使用
heapUsed: memoryUsage.heapUsed, // JavaScript堆内存使用
heapTotal: memoryUsage.heapTotal, // JavaScript堆内存总量
// 系统内存信息
systemTotal: systemMemoryInfo.totalMemory || 0,
systemFree: systemMemoryInfo.freeMemory || 0,
systemUsed: systemMemoryInfo.usedMemory || 0
};
} catch (error) {
console.error('Failed to get memory info:', error);
// 返回默认值
return {
privateBytes: 0,
sharedBytes: 0,
heapUsed: 0,
heapTotal: 0,
systemTotal: 0,
systemFree: 0,
systemUsed: 0
};
}
});
// 添加更新窗口标题的API
ipcMain.handle('update-window-title', async (event, newTitle) => {
try {
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.setTitle(newTitle);
return { success: true, message: '窗口标题更新成功' };
} else {
return { success: false, message: '主窗口不存在或已销毁' };
}
} catch (error) {
console.error('更新窗口标题失败:', error);
return { success: false, message: '更新窗口标题失败: ' + error.message };
}
});
// 获取错误日志计数
ipcMain.handle('get-error-log-count', async () => {
return { count: errorLogCount }
});
// 获取日志文件路径
ipcMain.handle('get-log-file-path', async () => {
return { path: logFilePath }
});
});
// 添加更新窗口标题的API
ipcMain.handle('update-window-title', async (event, newTitle) => {
try {
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.setTitle(newTitle);
return { success: true, message: '窗口标题更新成功' };
} else {
return { success: false, message: '主窗口不存在或已销毁' };
}
} catch (error) {
console.error('更新窗口标题失败:', error);
return { success: false, message: '更新窗口标题失败: ' + error.message };
}
});
// 打开日志文件所在文件夹
ipcMain.handle('open-log-folder', async () => {
try {
const path = require('path');
const logDir = path.dirname(logFilePath);
require('electron').shell.openPath(logDir);
return { success: true, message: '日志文件夹已打开' };
} catch (error) {
console.error('打开日志文件夹失败:', error);
return { success: false, message: '打开日志文件夹失败: ' + error.message };
}
});
// 获取错误日志计数
ipcMain.handle('get-error-log-count', async () => {
return { count: errorLogCount }
});
// 获取本地IP地址
ipcMain.handle('get-local-ip', async () => {
try {
const ipInfo = getLocalIPAddresses();
if (ipInfo) {
return {
success: true,
ip: ipInfo.address,
interface: ipInfo.name,
netmask: ipInfo.netmask
};
} else {
return {
success: false,
message: '无法获取本地IP地址',
fallback: '127.0.0.1'
};
}
} catch (error) {
console.error('获取本地IP地址失败:', error);
return {
success: false,
message: '获取本地IP地址失败: ' + error.message,
fallback: '127.0.0.1'
};
}
});
// 获取日志文件路径
ipcMain.handle('get-log-file-path', async () => {
return { path: logFilePath }
});
// 窗口状态管理相关的IPC处理器
ipcMain.handle('reset-window-state', async () => {
try {
if (!windowStateManager) {
return {
success: false,
message: '窗口状态管理器未初始化'
// 打开日志文件所在文件夹
ipcMain.handle('open-log-folder', async () => {
try {
if (logFilePath) {
const logDir = path.dirname(logFilePath)
require('electron').shell.openPath(logDir)
return { success: true, message: '日志文件夹已打开' }
} else {
return { success: false, message: '日志文件路径未设置' }
}
} catch (error) {
console.error('打开日志文件夹失败:', error)
return { success: false, message: '打开日志文件夹失败: ' + error.message }
}
}
const result = windowStateManager.resetState()
return {
success: result,
message: result ? '窗口状态已重置' : '没有找到保存的窗口状态'
}
} catch (error) {
console.error('重置窗口状态失败:', error)
return {
success: false,
message: '重置窗口状态失败: ' + error.message
}
}
})
});
ipcMain.handle('get-window-state-info', async () => {
try {
if (!windowStateManager) {
return {
success: false,
message: '窗口状态管理器未初始化'
// 获取本地IP地址
ipcMain.handle('get-local-ip', async () => {
try {
const ipInfo = getLocalIPAddresses()
if (ipInfo) {
return {
success: true,
address: ipInfo.address,
name: ipInfo.name,
netmask: ipInfo.netmask,
family: ipInfo.family
}
} else {
return {
success: false,
message: '无法获取本地IP地址',
fallback: '127.0.0.1'
}
}
} catch (error) {
console.error('获取本地IP地址失败:', error)
return {
success: false,
message: '获取本地IP地址失败: ' + error.message,
fallback: '127.0.0.1'
};
}
}
const hasState = windowStateManager.hasSavedState()
const statePath = windowStateManager.getStatePath()
let currentState = null
if (hasState) {
});
// 窗口状态管理相关的IPC处理器
ipcMain.handle('reset-window-state', async () => {
try {
const stateData = fs.readFileSync(statePath, 'utf8')
currentState = JSON.parse(stateData)
if (!windowStateManager) {
return {
success: false,
message: '窗口状态管理器未初始化'
}
}
const result = windowStateManager.resetState()
return {
success: result,
message: result ? '窗口状态已重置' : '没有找到保存的窗口状态'
}
} catch (error) {
console.error('读取当前窗口状态失败:', error)
console.error('重置窗口状态失败:', error)
return {
success: false,
message: '重置窗口状态失败: ' + error.message
}
}
}
return {
hasSavedState: hasState,
statePath: statePath,
currentState: currentState
}
} catch (error) {
console.error('获取窗口状态信息失败:', error)
return {
success: false,
message: '获取窗口状态信息失败: ' + error.message
}
}
})
})
}); // 闭合 app.whenReady().then() 的回调函数
ipcMain.handle('get-window-state-info', async () => {
try {
if (!windowStateManager) {
return {
success: false,
message: '窗口状态管理器未初始化'
}
}
const hasState = windowStateManager.hasSavedState()
const statePath = windowStateManager.getStatePath()
let currentState = null
if (hasState) {
try {
const stateData = fs.readFileSync(statePath, 'utf8')
currentState = JSON.parse(stateData)
} catch (error) {
console.error('读取当前窗口状态失败:', error)
}
}
return {
hasSavedState: hasState,
statePath: statePath,
currentState: currentState
}
} catch (error) {
console.error('获取窗口状态信息失败:', error)
return {
success: false,
message: '获取窗口状态信息失败: ' + error.message
}
}
})
app.on('window-all-closed', () => {
// 由于已经在窗口 close 事件中处理了退出登录,这里直接退出
if (process.platform !== 'darwin') {
app.quit()
}
})
}); // 闭合 app.whenReady().then() 的回调函数
} else {
console.error('app对象不可用或whenReady方法不存在');
}
// 确保app对象可用后再注册事件监听器
if (app && typeof app.on === 'function') {
app.on('window-all-closed', () => {
// 由于已经在窗口 close 事件中处理了退出登录,这里直接退出
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (mainWindow === null) createWindow()
})
app.on('activate', () => {
if (mainWindow === null) createWindow()
})
} else {
console.error('app对象不可用,无法注册事件监听器');
}
// 添加错误处理
process.on('uncaughtException', (error) => {
@ -721,3 +744,13 @@ process.on('unhandledRejection', (reason, promise) => { @@ -721,3 +744,13 @@ process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled promise rejection:', reason)
})
// 测试日志系统 - 在开发环境下生成一些测试错误
if (getIsDev()) {
setTimeout(() => {
console.error('测试错误日志 1: 这是一个模拟的错误信息')
}, 5000)
setTimeout(() => {
console.error('测试错误日志 2: 另一个模拟的错误信息')
}, 10000)
}

548
gofaster/app/src/renderer/modules/role-management/views/RoleApiTest.vue

@ -0,0 +1,548 @@ @@ -0,0 +1,548 @@
<template>
<div class="role-api-test">
<div class="page-header">
<h2>角色管理API测试</h2>
<div class="header-actions">
<button
class="btn btn-secondary"
@click="toggleTestMode"
:title="testMode ? '当前为测试模式(无需认证)' : '当前为正式模式(需要认证)'"
>
<i class="fas fa-flask"></i>
{{ testMode ? '测试模式' : '正式模式' }}
</button>
<button class="btn btn-primary" @click="runAllTests">
<i class="fas fa-play"></i> 运行所有测试
</button>
</div>
</div>
<div class="test-content">
<!-- API配置信息 -->
<div class="test-section">
<h3>API配置信息</h3>
<div class="config-info">
<div class="config-item">
<label>API基础地址:</label>
<span>{{ apiBaseUrl }}</span>
</div>
<div class="config-item">
<label>当前模式:</label>
<span :class="testMode ? 'test-mode' : 'prod-mode'">
{{ testMode ? '测试模式' : '正式模式' }}
</span>
</div>
<div class="config-item">
<label>API路径:</label>
<span>{{ currentApiPath }}</span>
</div>
</div>
</div>
<!-- 测试结果 -->
<div class="test-section">
<h3>测试结果</h3>
<div class="test-results">
<div
v-for="(result, index) in testResults"
:key="index"
class="test-result-item"
:class="result.status"
>
<div class="test-header">
<span class="test-name">{{ result.name }}</span>
<span class="test-status">{{ getStatusText(result.status) }}</span>
</div>
<div v-if="result.message" class="test-message">
{{ result.message }}
</div>
<div v-if="result.data" class="test-data">
<pre>{{ JSON.stringify(result.data, null, 2) }}</pre>
</div>
</div>
</div>
</div>
<!-- 手动测试 -->
<div class="test-section">
<h3>手动测试</h3>
<div class="manual-tests">
<div class="test-group">
<h4>获取角色列表</h4>
<button @click="testGetRoles" :disabled="testing">
{{ testing ? '测试中...' : '测试获取角色列表' }}
</button>
</div>
<div class="test-group">
<h4>创建角色</h4>
<div class="form-group">
<label>角色名称:</label>
<input v-model="testRole.name" type="text" placeholder="测试角色" />
</div>
<div class="form-group">
<label>角色代码:</label>
<input v-model="testRole.code" type="text" placeholder="TEST_ROLE" />
</div>
<div class="form-group">
<label>描述:</label>
<input v-model="testRole.description" type="text" placeholder="测试角色描述" />
</div>
<button @click="testCreateRole" :disabled="testing">
{{ testing ? '测试中...' : '测试创建角色' }}
</button>
</div>
<div class="test-group">
<h4>更新角色</h4>
<div class="form-group">
<label>角色ID:</label>
<input v-model="updateRoleId" type="number" placeholder="输入角色ID" />
</div>
<button @click="testUpdateRole" :disabled="testing || !updateRoleId">
{{ testing ? '测试中...' : '测试更新角色' }}
</button>
</div>
<div class="test-group">
<h4>删除角色</h4>
<div class="form-group">
<label>角色ID:</label>
<input v-model="deleteRoleId" type="number" placeholder="输入角色ID" />
</div>
<button @click="testDeleteRole" :disabled="testing || !deleteRoleId">
{{ testing ? '测试中...' : '测试删除角色' }}
</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { ref, reactive, computed, onMounted } from 'vue'
import { roleService } from '../services/roleService.js'
import { getFinalConfig } from '../../../../config/app.config.js'
export default {
name: 'RoleApiTest',
setup() {
const testing = ref(false)
const testMode = ref(false)
const testResults = ref([])
const updateRoleId = ref('')
const deleteRoleId = ref('')
const testRole = reactive({
name: '测试角色',
code: 'TEST_ROLE',
description: '这是一个测试角色'
})
const apiBaseUrl = computed(() => getFinalConfig().apiBaseUrl)
const currentApiPath = computed(() => testMode.value ? '/auth/roles/test' : '/auth/roles')
//
const toggleTestMode = () => {
testMode.value = roleService.toggleTestMode()
addTestResult('模式切换', 'success', `已切换到${testMode.value ? '测试' : '正式'}模式`)
}
//
const addTestResult = (name, status, message, data = null) => {
testResults.value.unshift({
name,
status,
message,
data,
timestamp: new Date().toLocaleString()
})
}
//
const getStatusText = (status) => {
const statusMap = {
'success': '成功',
'error': '失败',
'warning': '警告'
}
return statusMap[status] || status
}
//
const testGetRoles = async () => {
testing.value = true
try {
const response = await roleService.getRoles(1, 10)
if (response.code === 200) {
addTestResult('获取角色列表', 'success', '获取角色列表成功', response.data)
} else {
addTestResult('获取角色列表', 'error', `获取失败: ${response.message}`, response)
}
} catch (error) {
addTestResult('获取角色列表', 'error', `请求失败: ${error.message || error.error}`, error)
} finally {
testing.value = false
}
}
//
const testCreateRole = async () => {
testing.value = true
try {
const response = await roleService.createRole(testRole)
if (response.code === 200) {
addTestResult('创建角色', 'success', '创建角色成功', response.data)
} else {
addTestResult('创建角色', 'error', `创建失败: ${response.message}`, response)
}
} catch (error) {
addTestResult('创建角色', 'error', `请求失败: ${error.message || error.error}`, error)
} finally {
testing.value = false
}
}
//
const testUpdateRole = async () => {
if (!updateRoleId.value) {
addTestResult('更新角色', 'warning', '请输入角色ID')
return
}
testing.value = true
try {
const updateData = {
name: `${testRole.name}_更新`,
code: `${testRole.code}_UPDATED`,
description: `${testRole.description}_更新`
}
const response = await roleService.updateRole(updateRoleId.value, updateData)
if (response.code === 200) {
addTestResult('更新角色', 'success', '更新角色成功', response.data)
} else {
addTestResult('更新角色', 'error', `更新失败: ${response.message}`, response)
}
} catch (error) {
addTestResult('更新角色', 'error', `请求失败: ${error.message || error.error}`, error)
} finally {
testing.value = false
}
}
//
const testDeleteRole = async () => {
if (!deleteRoleId.value) {
addTestResult('删除角色', 'warning', '请输入角色ID')
return
}
testing.value = true
try {
const response = await roleService.deleteRole(deleteRoleId.value)
if (response.code === 200) {
addTestResult('删除角色', 'success', '删除角色成功', response.data)
} else {
addTestResult('删除角色', 'error', `删除失败: ${response.message}`, response)
}
} catch (error) {
addTestResult('删除角色', 'error', `请求失败: ${error.message || error.error}`, error)
} finally {
testing.value = false
}
}
//
const runAllTests = async () => {
addTestResult('测试开始', 'success', '开始运行所有API测试')
await testGetRoles()
await new Promise(resolve => setTimeout(resolve, 1000)) // 1
await testCreateRole()
await new Promise(resolve => setTimeout(resolve, 1000)) // 1
addTestResult('测试完成', 'success', '所有API测试已完成')
}
onMounted(() => {
testMode.value = roleService.getTestModeStatus()
addTestResult('页面加载', 'success', '角色管理API测试页面已加载')
})
return {
testing,
testMode,
testResults,
updateRoleId,
deleteRoleId,
testRole,
apiBaseUrl,
currentApiPath,
toggleTestMode,
testGetRoles,
testCreateRole,
testUpdateRole,
testDeleteRole,
runAllTests,
getStatusText
}
}
}
</script>
<style scoped>
.role-api-test {
padding: 20px;
height: 100%;
overflow-y: auto;
}
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.page-header h2 {
margin: 0;
color: var(--text-primary);
}
.header-actions {
display: flex;
gap: 12px;
align-items: center;
}
.test-content {
max-width: 1200px;
}
.test-section {
background: var(--card-bg);
border-radius: 8px;
padding: 24px;
margin-bottom: 24px;
box-shadow: 0 2px 8px var(--shadow-color);
}
.test-section h3 {
margin: 0 0 20px 0;
color: var(--text-primary);
font-size: 18px;
border-bottom: 2px solid var(--border-color);
padding-bottom: 8px;
}
.config-info {
display: grid;
gap: 12px;
}
.config-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px;
background: var(--bg-secondary);
border-radius: 4px;
}
.config-item label {
font-weight: 500;
color: var(--text-primary);
}
.config-item span {
color: var(--text-secondary);
font-family: monospace;
}
.test-mode {
color: #ff9800 !important;
font-weight: bold;
}
.prod-mode {
color: #4caf50 !important;
font-weight: bold;
}
.test-results {
max-height: 400px;
overflow-y: auto;
}
.test-result-item {
margin-bottom: 16px;
padding: 16px;
border-radius: 6px;
border-left: 4px solid;
}
.test-result-item.success {
background: rgba(76, 175, 80, 0.1);
border-left-color: #4caf50;
}
.test-result-item.error {
background: rgba(244, 67, 54, 0.1);
border-left-color: #f44336;
}
.test-result-item.warning {
background: rgba(255, 152, 0, 0.1);
border-left-color: #ff9800;
}
.test-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.test-name {
font-weight: 500;
color: var(--text-primary);
}
.test-status {
font-size: 12px;
padding: 4px 8px;
border-radius: 4px;
font-weight: 500;
}
.test-result-item.success .test-status {
background: #4caf50;
color: white;
}
.test-result-item.error .test-status {
background: #f44336;
color: white;
}
.test-result-item.warning .test-status {
background: #ff9800;
color: white;
}
.test-message {
color: var(--text-secondary);
margin-bottom: 8px;
}
.test-data {
background: var(--bg-secondary);
padding: 12px;
border-radius: 4px;
overflow-x: auto;
}
.test-data pre {
margin: 0;
font-size: 12px;
color: var(--text-secondary);
}
.manual-tests {
display: grid;
gap: 24px;
}
.test-group {
padding: 16px;
background: var(--bg-secondary);
border-radius: 6px;
}
.test-group h4 {
margin: 0 0 16px 0;
color: var(--text-primary);
}
.form-group {
margin-bottom: 12px;
}
.form-group label {
display: block;
margin-bottom: 4px;
font-weight: 500;
color: var(--text-primary);
}
.form-group input {
width: 100%;
padding: 8px 12px;
border: 1px solid var(--border-color);
border-radius: 4px;
background: var(--input-bg);
color: var(--input-text);
box-sizing: border-box;
}
.btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
display: inline-flex;
align-items: center;
gap: 6px;
transition: all 0.2s;
}
.btn-primary {
background: var(--accent-color);
color: white;
}
.btn-primary:hover {
background: var(--accent-hover);
}
.btn-secondary {
background: #757575;
color: white;
}
.btn-secondary:hover {
background: #616161;
}
.btn:hover {
opacity: 0.9;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
button {
background: var(--accent-color);
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: all 0.2s;
}
button:hover:not(:disabled) {
background: var(--accent-hover);
}
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
</style>

1
gofaster/backend/tmp/build-errors.log

@ -1 +0,0 @@ @@ -1 +0,0 @@
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1

BIN
gofaster/backend/tmp/main.exe

Binary file not shown.
Loading…
Cancel
Save