From 528d01d035cbd3293de758d992ca916115bc7f26 Mon Sep 17 00:00:00 2001 From: NanGua_QWQ Date: Sat, 14 Mar 2026 21:45:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0builder=E7=9A=84css?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/hosting/index.ts | 3 +- src/main/hosting/tokens.ts | 1 - src/main/index.ts | 9 +- src/main/services/AutoScoreService.ts | 123 +---- src/main/services/FileSystemService.ts | 281 ---------- .../autoScore/ruleBuilderOverride.css | 494 ++++++++---------- tsconfig.web.json | 3 +- 7 files changed, 223 insertions(+), 691 deletions(-) delete mode 100644 src/main/services/FileSystemService.ts diff --git a/src/main/hosting/index.ts b/src/main/hosting/index.ts index 9fc74c5..3f55de2 100644 --- a/src/main/hosting/index.ts +++ b/src/main/hosting/index.ts @@ -16,8 +16,7 @@ export { ThemeServiceToken, WindowManagerToken, TrayServiceToken, - AutoScoreServiceToken, - FileSystemServiceToken + AutoScoreServiceToken } from './tokens' export type { appRuntimeContext, diff --git a/src/main/hosting/tokens.ts b/src/main/hosting/tokens.ts index 4574e3e..918f43f 100644 --- a/src/main/hosting/tokens.ts +++ b/src/main/hosting/tokens.ts @@ -15,4 +15,3 @@ export const ThemeServiceToken = Symbol.for('secscore.themeService') export const WindowManagerToken = Symbol.for('secscore.windowManager') export const TrayServiceToken = Symbol.for('secscore.trayService') export const AutoScoreServiceToken = Symbol.for('secscore.autoScoreService') -export const FileSystemServiceToken = Symbol.for('secscore.fileSystemService') diff --git a/src/main/index.ts b/src/main/index.ts index ca825de..7a249f1 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -16,7 +16,6 @@ import { ThemeService } from './services/ThemeService' import { WindowManager, type windowManagerOptions } from './services/WindowManager' import { TrayService } from './services/TrayService' import { AutoScoreService } from './services/AutoScoreService' -import { FileSystemService } from './services/FileSystemService' import { DbConnectionService } from './services/DbConnectionService' import { StudentRepository } from './repos/StudentRepository' import { ReasonRepository } from './repos/ReasonRepository' @@ -39,8 +38,7 @@ import { ThemeServiceToken, WindowManagerToken, TrayServiceToken, - AutoScoreServiceToken, - FileSystemServiceToken + AutoScoreServiceToken } from './hosting' type mainAppConfig = { @@ -267,10 +265,6 @@ app.whenReady().then(async () => { TrayServiceToken, (p) => new TrayService(p.get(MainContext), config.window) ) - services.addSingleton( - FileSystemServiceToken, - (p) => new FileSystemService(p.get(MainContext), config.configDir) - ) services.addSingleton(AutoScoreServiceToken, (p) => new AutoScoreService(p.get(MainContext))) services.addSingleton(DbConnectionService, (p) => new DbConnectionService(p.get(MainContext))) }) @@ -320,7 +314,6 @@ app.whenReady().then(async () => { const tray = services.get(TrayServiceToken) as TrayService tray.initialize() } - services.get(FileSystemServiceToken) const autoScore = services.get(AutoScoreServiceToken) as AutoScoreService await autoScore.initialize?.() services.get(DbConnectionService) diff --git a/src/main/services/AutoScoreService.ts b/src/main/services/AutoScoreService.ts index cb11382..e26bc18 100644 --- a/src/main/services/AutoScoreService.ts +++ b/src/main/services/AutoScoreService.ts @@ -11,30 +11,12 @@ interface AutoScoreRule extends RuleConfig { lastExecuted?: Date } -interface AutoScoreRuleFileData { - id: number - enabled: boolean - name: string - studentNames: string[] - lastExecuted?: string - triggers?: Array<{ event: string; value?: string; relation?: 'AND' | 'OR' }> - actions?: Array<{ event: string; value?: string; reason?: string }> -} - -interface AutoScoreRulesFile { - version: number - rules: AutoScoreRuleFileData[] - updatedAt?: string -} - declare module '../../shared/kernel' { interface Context { autoScore: AutoScoreService } } -const RULES_FILE_NAME = 'auto-score-rules.json' - export class AutoScoreService extends Service { private rules: AutoScoreRule[] = [] private timers: Map = new Map() @@ -130,83 +112,7 @@ export class AutoScoreService extends Service { } private async loadRulesFromFile(): Promise { - try { - const fs = this.mainCtx.fileSystem - if (!fs) { - this.logger.warn('FileSystemService not available, falling back to settings') - await this.loadRulesFromSettings() - return - } - - const data = await fs.readJsonFile(RULES_FILE_NAME, 'automatic') - if (data && data.rules) { - this.rules = data.rules.map((rule: any) => { - const migratedRule = this.migrateRule(rule) - return { - ...migratedRule, - lastExecuted: migratedRule.lastExecuted - ? new Date(migratedRule.lastExecuted) - : undefined - } - }) - if ( - data.rules.some( - (rule: any) => rule.intervalMinutes !== undefined || rule.scoreValue !== undefined - ) - ) { - await this.saveRulesToFile() - } - } else { - await this.loadRulesFromSettings() - await this.saveRulesToFile() - } - } catch (error) { - this.logger.warn('Failed to load auto score rules from file, falling back to settings', { - error - }) - await this.loadRulesFromSettings() - } - } - - private migrateRule(rule: any): AutoScoreRule { - if (!rule.intervalMinutes && !rule.scoreValue) { - return rule - } - - const migratedRule: AutoScoreRule = { - id: rule.id, - enabled: rule.enabled, - name: rule.name, - studentNames: rule.studentNames || [], - lastExecuted: rule.lastExecuted, - triggers: rule.triggers || [], - actions: rule.actions || [] - } - - if ( - rule.intervalMinutes && - !migratedRule.triggers?.find((t) => t.event === 'interval_time_passed') - ) { - migratedRule.triggers = migratedRule.triggers || [] - migratedRule.triggers.push({ - event: 'interval_time_passed', - value: String(rule.intervalMinutes) - }) - } - - if ( - rule.scoreValue !== undefined && - !migratedRule.actions?.find((a) => a.event === 'add_score') - ) { - migratedRule.actions = migratedRule.actions || [] - migratedRule.actions.push({ - event: 'add_score', - value: String(rule.scoreValue), - reason: rule.reason - }) - } - - return migratedRule + await this.loadRulesFromSettings() } private async loadRulesFromSettings() { @@ -226,32 +132,7 @@ export class AutoScoreService extends Service { } private async saveRulesToFile(): Promise { - try { - const fs = this.mainCtx.fileSystem - if (!fs) { - this.logger.warn('FileSystemService not available, falling back to settings') - await this.saveRulesToSettings() - return - } - - const data: AutoScoreRulesFile = { - version: 1, - rules: this.rules.map(({ lastExecuted, ...rule }) => ({ - ...rule, - lastExecuted: lastExecuted?.toISOString() - })), - updatedAt: new Date().toISOString() - } - - const success = await fs.writeJsonFile(RULES_FILE_NAME, data, 'automatic') - if (!success) { - this.logger.warn('Failed to save rules to file, falling back to settings') - await this.saveRulesToSettings() - } - } catch (error) { - this.logger.error('Failed to save auto score rules to file:', { error }) - await this.saveRulesToSettings() - } + await this.saveRulesToSettings() } private async saveRulesToSettings() { diff --git a/src/main/services/FileSystemService.ts b/src/main/services/FileSystemService.ts deleted file mode 100644 index 276623f..0000000 --- a/src/main/services/FileSystemService.ts +++ /dev/null @@ -1,281 +0,0 @@ -import { Service } from '../../shared/kernel' -import { MainContext } from '../context' -import { join } from 'path' -import fs from 'fs/promises' - -declare module '../../shared/kernel' { - interface Context { - fileSystem: FileSystemService - } -} - -export interface ConfigFileInfo { - name: string - path: string - size: number - modified: Date -} - -export interface ConfigFolderStructure { - configRoot: string - automatic: string - script: string -} - -export class FileSystemService extends Service { - private configRoot: string - private automaticDir: string - private scriptDir: string - private initPromise: Promise | null = null - - constructor(ctx: MainContext, ConfigRoot: string) { - super(ctx, 'fileSystem') - this.configRoot = ConfigRoot - this.automaticDir = join(this.configRoot, 'automatic') - this.scriptDir = join(this.configRoot, 'script') - this.initPromise = this.initialize() - this.registerIpc() - } - - private async initialize(): Promise { - await this.ensureDirectories() - } - - private async ensureDirectories(): Promise { - try { - await fs.mkdir(this.configRoot, { recursive: true }) - await fs.mkdir(this.automaticDir, { recursive: true }) - await fs.mkdir(this.scriptDir, { recursive: true }) - } catch (error) { - this.ctx.logger.warn('FileSystemService: Failed to create config directories', { error }) - } - } - - getConfigStructure(): ConfigFolderStructure { - return { - configRoot: this.configRoot, - automatic: this.automaticDir, - script: this.scriptDir - } - } - - async readJsonFile( - relativePath: string, - folder: 'automatic' | 'script' = 'automatic' - ): Promise { - await this.initPromise - const baseDir = folder === 'automatic' ? this.automaticDir : this.scriptDir - const filePath = join(baseDir, relativePath) - - try { - const content = await fs.readFile(filePath, 'utf-8') - return JSON.parse(content) as T - } catch (error) { - if (error instanceof Error && 'code' in error && (error as any).code === 'ENOENT') { - return null - } - this.ctx.logger.warn('FileSystemService: Failed to read JSON file', { path: filePath, error }) - return null - } - } - - async writeJsonFile( - relativePath: string, - data: any, - folder: 'automatic' | 'script' = 'automatic' - ): Promise { - await this.initPromise - const baseDir = folder === 'automatic' ? this.automaticDir : this.scriptDir - const filePath = join(baseDir, relativePath) - - try { - const content = JSON.stringify(data, null, 2) - await fs.writeFile(filePath, content, 'utf-8') - return true - } catch (error) { - this.ctx.logger.warn('FileSystemService: Failed to write JSON file', { - path: filePath, - error - }) - return false - } - } - - async readTextFile( - relativePath: string, - folder: 'automatic' | 'script' = 'automatic' - ): Promise { - await this.initPromise - const baseDir = folder === 'automatic' ? this.automaticDir : this.scriptDir - const filePath = join(baseDir, relativePath) - - try { - return await fs.readFile(filePath, 'utf-8') - } catch (error) { - if (error instanceof Error && 'code' in error && (error as any).code === 'ENOENT') { - return null - } - this.ctx.logger.warn('FileSystemService: Failed to read text file', { path: filePath, error }) - return null - } - } - - async writeTextFile( - content: string, - relativePath: string, - folder: 'automatic' | 'script' = 'automatic' - ): Promise { - await this.initPromise - const baseDir = folder === 'automatic' ? this.automaticDir : this.scriptDir - const filePath = join(baseDir, relativePath) - - try { - await fs.writeFile(filePath, content, 'utf-8') - return true - } catch (error) { - this.ctx.logger.warn('FileSystemService: Failed to write text file', { - path: filePath, - error - }) - return false - } - } - - async deleteFile( - relativePath: string, - folder: 'automatic' | 'script' = 'automatic' - ): Promise { - await this.initPromise - const baseDir = folder === 'automatic' ? this.automaticDir : this.scriptDir - const filePath = join(baseDir, relativePath) - - try { - await fs.unlink(filePath) - return true - } catch (error) { - if (error instanceof Error && 'code' in error && (error as any).code === 'ENOENT') { - return false - } - this.ctx.logger.warn('FileSystemService: Failed to delete file', { path: filePath, error }) - return false - } - } - - async listFiles(folder: 'automatic' | 'script' = 'automatic'): Promise { - await this.initPromise - const baseDir = folder === 'automatic' ? this.automaticDir : this.scriptDir - - try { - const entries = await fs.readdir(baseDir, { withFileTypes: true }) - const files: ConfigFileInfo[] = [] - - for (const entry of entries) { - if (entry.isFile()) { - const filePath = join(baseDir, entry.name) - const stats = await fs.stat(filePath) - files.push({ - name: entry.name, - path: filePath, - size: stats.size, - modified: stats.mtime - }) - } - } - - return files - } catch (error) { - if (error instanceof Error && 'code' in error && (error as any).code === 'ENOENT') { - return [] - } - this.ctx.logger.warn('FileSystemService: Failed to list files', { path: baseDir, error }) - return [] - } - } - - async fileExists( - relativePath: string, - folder: 'automatic' | 'script' = 'automatic' - ): Promise { - await this.initPromise - const baseDir = folder === 'automatic' ? this.automaticDir : this.scriptDir - const filePath = join(baseDir, relativePath) - - try { - await fs.access(filePath) - return true - } catch { - return false - } - } - - private get mainCtx() { - return this.ctx as MainContext - } - - private registerIpc(): void { - this.mainCtx.handle('fs:getConfigStructure', async () => { - await this.initPromise - return { success: true, data: this.getConfigStructure() } - }) - - this.mainCtx.handle( - 'fs:readJson', - async (_event, relativePath: string, folder: 'automatic' | 'script') => { - await this.initPromise - const data = await this.readJsonFile(relativePath, folder) - return { success: true, data } - } - ) - - this.mainCtx.handle( - 'fs:writeJson', - async (_event, relativePath: string, data: any, folder: 'automatic' | 'script') => { - await this.initPromise - const success = await this.writeJsonFile(relativePath, data, folder) - return { success } - } - ) - - this.mainCtx.handle( - 'fs:readText', - async (_event, relativePath: string, folder: 'automatic' | 'script') => { - await this.initPromise - const content = await this.readTextFile(relativePath, folder) - return { success: true, data: content } - } - ) - - this.mainCtx.handle( - 'fs:writeText', - async (_event, content: string, relativePath: string, folder: 'automatic' | 'script') => { - await this.initPromise - const success = await this.writeTextFile(content, relativePath, folder) - return { success } - } - ) - - this.mainCtx.handle( - 'fs:deleteFile', - async (_event, relativePath: string, folder: 'automatic' | 'script') => { - await this.initPromise - const success = await this.deleteFile(relativePath, folder) - return { success } - } - ) - - this.mainCtx.handle('fs:listFiles', async (_event, folder: 'automatic' | 'script') => { - await this.initPromise - const files = await this.listFiles(folder) - return { success: true, data: files } - }) - - this.mainCtx.handle( - 'fs:fileExists', - async (_event, relativePath: string, folder: 'automatic' | 'script') => { - await this.initPromise - const exists = await this.fileExists(relativePath, folder) - return { success: true, data: exists } - } - ) - } -} diff --git a/src/renderer/src/components/autoScore/ruleBuilderOverride.css b/src/renderer/src/components/autoScore/ruleBuilderOverride.css index 5dde63b..624b224 100644 --- a/src/renderer/src/components/autoScore/ruleBuilderOverride.css +++ b/src/renderer/src/components/autoScore/ruleBuilderOverride.css @@ -1,309 +1,251 @@ -.queryBuilder { - --querybuilder-font-family: - -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', - sans-serif; - --querybuilder-background: var(--ss-card-bg, #ffffff); - --querybuilder-color: var(--ss-text-main, rgba(0, 0, 0, 0.85)); - --querybuilder-border-radius: 6px; - --querybuilder-border-color: #d9d9d9; - --querybuilder-disabled-color: rgba(0, 0, 0, 0.25); - font-family: var(--querybuilder-font-family); - font-size: 14px; - line-height: 1.5715; - color: var(--querybuilder-color); - background: var(--querybuilder-background); - padding: 0; - border-radius: var(--querybuilder-border-radius); +.ruleGroup { + background-color: var(--ss-card-bg, #fff); + border: 1px solid var(--ss-border-color, #d9d9d9); + border-radius: 8px; + padding: 16px; + margin-bottom: 12px; } -.queryBuilder .ruleGroup { - background: var(--querybuilder-background); - border: 1px solid var(--querybuilder-border-color); - border-radius: var(--querybuilder-border-radius); - padding: 8px; - margin: 0; -} - -.queryBuilder .ruleGroup-header { +.ruleGroup-header { display: flex; + align-items: center; + gap: 12px; + margin-bottom: 12px; flex-wrap: wrap; +} + +.ruleGroup-combinators, +.ruleGroup-addRule, +.ruleGroup-addGroup { + margin-right: 8px; +} + +.ruleGroup-body { + padding-left: 12px; + border-left: 2px solid var(--ss-primary-color, #1677ff); + margin-left: 4px; +} + +.rule { + display: flex; align-items: center; gap: 8px; + padding: 8px 12px; + background-color: var(--ss-item-bg, rgba(0, 0, 0, 0.02)); + border-radius: 6px; margin-bottom: 8px; -} - -.queryBuilder .ruleGroup-body { - padding-left: 20px; - border-left: 2px solid var(--querybuilder-border-color); - margin-left: 0; -} - -.queryBuilder .rule { - display: flex; flex-wrap: wrap; - align-items: center; - gap: 8px; - padding: 4px 8px; - margin: 0; - background: rgba(0, 0, 0, 0.02); - border-radius: 4px; - border: 1px solid transparent; - transition: all 0.3s; } -.queryBuilder .rule:hover { - background: rgba(0, 0, 0, 0.04); - border-color: var(--querybuilder-border-color); +.rule:hover { + background-color: var(--ss-item-hover, rgba(0, 0, 0, 0.04)); } -.queryBuilder select, -.queryBuilder .ruleGroup-combinators select { - appearance: none; - background: var(--querybuilder-background); - border: 1px solid var(--querybuilder-border-color); - border-radius: var(--querybuilder-border-radius); - padding: 4px 28px 4px 11px; - height: 32px; - font-size: 14px; - color: var(--querybuilder-color); - cursor: pointer; - transition: all 0.3s; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='rgba(0,0,0,0.25)' d='M6 8L1 3h10z'/%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: right 8px center; -} - -.queryBuilder select:hover, -.queryBuilder .ruleGroup-combinators select:hover { - border-color: #40a9ff; -} - -.queryBuilder select:focus, -.queryBuilder .ruleGroup-combinators select:focus { - outline: none; - border-color: #40a9ff; - box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); -} - -.queryBuilder input[type='text'], -.queryBuilder input[type='number'], -.queryBuilder input:not([type]) { - background: var(--querybuilder-background); - border: 1px solid var(--querybuilder-border-color); - border-radius: var(--querybuilder-border-radius); - padding: 4px 11px; - height: 32px; - font-size: 14px; - color: var(--querybuilder-color); - transition: all 0.3s; +.rule-fields, +.rule-operators, +.rule-value, +.rule-subfields { min-width: 120px; } -.queryBuilder input[type='text']:hover, -.queryBuilder input[type='number']:hover, -.queryBuilder input:not([type]):hover { - border-color: #40a9ff; +.rule-fields .ant-select-selector, +.rule-operators .ant-select-selector, +.rule-subfields .ant-select-selector { + background-color: var(--ss-input-bg, #fff) !important; + border-color: var(--ss-border-color, #d9d9d9) !important; + color: var(--ss-text-main, rgba(0, 0, 0, 0.88)) !important; } -.queryBuilder input[type='text']:focus, -.queryBuilder input[type='number']:focus, -.queryBuilder input:not([type]):focus { - outline: none; - border-color: #40a9ff; - box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); +.rule-fields .ant-select-selector:hover, +.rule-operators .ant-select-selector:hover, +.rule-subfields .ant-select-selector:hover { + border-color: var(--ss-primary-color, #1677ff) !important; } -.queryBuilder input::placeholder { - color: #bfbfbf; +.rule-fields .ant-select-focused .ant-select-selector, +.rule-operators .ant-select-focused .ant-select-selector, +.rule-subfields .ant-select-focused .ant-select-selector { + border-color: var(--ss-primary-color, #1677ff) !important; + box-shadow: 0 0 0 2px rgba(var(--ss-primary-rgb, 22, 119, 255), 0.1) !important; } -.queryBuilder button { - display: inline-flex; +.rule-value .ant-input, +.rule-value .ant-input-number, +.rule-value .ant-select-selector { + background-color: var(--ss-input-bg, #fff) !important; + border-color: var(--ss-border-color, #d9d9d9) !important; + color: var(--ss-text-main, rgba(0, 0, 0, 0.88)) !important; +} + +.rule-value .ant-input:hover, +.rule-value .ant-input-number:hover, +.rule-value .ant-select-selector:hover { + border-color: var(--ss-primary-color, #1677ff) !important; +} + +.rule-value .ant-input:focus, +.rule-value .ant-input-number-focused, +.rule-value .ant-select-focused .ant-select-selector { + border-color: var(--ss-primary-color, #1677ff) !important; + box-shadow: 0 0 0 2px rgba(var(--ss-primary-rgb, 22, 119, 255), 0.1) !important; +} + +.rule-value .ant-input-number-input { + color: var(--ss-text-main, rgba(0, 0, 0, 0.88)) !important; +} + +.rule-remove, +.ruleGroup-remove { + color: #fff !important; + background-color: var(--ant-color-error, #ff4d4f) !important; + border-color: var(--ant-color-error, #ff4d4f) !important; + transition: all 0.2s; +} + +.rule-remove:hover, +.ruleGroup-remove:hover { + color: #fff !important; + background-color: #ff7875 !important; + border-color: #ff7875 !important; +} + +.ruleGroup-addRule, +.ruleGroup-addGroup { + color: var(--ss-primary-color, #1677ff) !important; + border-color: var(--ss-primary-color, #1677ff) !important; + background-color: transparent !important; +} + +.ruleGroup-addRule:hover, +.ruleGroup-addGroup:hover { + color: #fff !important; + background-color: var(--ss-primary-color, #1677ff) !important; +} + +.betweenRules { + display: flex; align-items: center; justify-content: center; - font-weight: 400; - white-space: nowrap; - text-align: center; - background-image: none; - border: 1px solid transparent; - cursor: pointer; - transition: all 0.3s; - height: 32px; - padding: 4px 15px; - font-size: 14px; - border-radius: var(--querybuilder-border-radius); - color: var(--querybuilder-color); - background: var(--querybuilder-background); - border-color: var(--querybuilder-border-color); -} - -.queryBuilder button:hover { - color: #40a9ff; - border-color: #40a9ff; -} - -.queryBuilder button:focus { - outline: none; - color: #40a9ff; - border-color: #40a9ff; -} - -.queryBuilder button.ruleGroup-addRule, -.queryBuilder button.ruleGroup-addGroup { - color: #fff; - background: var(--ant-color-primary, #1677ff); - border-color: var(--ant-color-primary, #1677ff); - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12); - box-shadow: 0 2px 0 rgba(0, 0, 0, 0.045); -} - -.queryBuilder button.ruleGroup-addRule:hover, -.queryBuilder button.ruleGroup-addGroup:hover { - color: #fff; - background: var(--ant-color-primary-hover, #4096ff); - border-color: var(--ant-color-primary-hover, #4096ff); -} - -.queryBuilder button.ruleGroup-addRule:focus, -.queryBuilder button.ruleGroup-addGroup:focus { - color: #fff; - background: var(--ant-color-primary-hover, #4096ff); - border-color: var(--ant-color-primary-hover, #4096ff); -} - -.queryBuilder button.rule-remove, -.queryBuilder button.ruleGroup-remove { - color: #ff4d4f; - border-color: #ff4d4f; - background: transparent; -} - -.queryBuilder button.rule-remove:hover, -.queryBuilder button.ruleGroup-remove:hover { - color: #ff7875; - border-color: #ff7875; -} - -.queryBuilder button.rule-remove:focus, -.queryBuilder button.ruleGroup-remove:focus { - color: #ff7875; - border-color: #ff7875; -} - -.queryBuilder .ruleGroup-combinators { - display: inline-flex; - align-items: center; - gap: 8px; -} - -.queryBuilder .betweenRules { - display: inline-flex; - align-items: center; - gap: 4px; -} - -.queryBuilder .betweenRules .operator-joiner { - color: var(--querybuilder-color); - padding: 0 4px; -} - -.queryBuilder .ruleGroup-notToggle { - display: inline-flex; - align-items: center; - gap: 4px; - margin-left: 8px; - color: var(--querybuilder-color); -} - -.queryBuilder .ruleGroup-notToggle input[type='checkbox'] { - width: 16px; - height: 16px; - cursor: pointer; - accent-color: #1890ff; -} - -.queryBuilder .dragHandle { - cursor: move; - color: var(--querybuilder-disabled-color); - padding: 4px; -} - -.queryBuilder .dragHandle:hover { - color: var(--querybuilder-color); -} - -.queryBuilder .shiftActions { - display: inline-flex; - gap: 4px; - margin-left: 8px; -} - -.queryBuilder .shiftActions button { - padding: 4px 8px; - min-width: auto; -} - -.queryBuilder .valueEditor-caseSensitive, -.queryBuilder .valueEditor-caseSensitive input[type='checkbox'] { - cursor: pointer; -} - -.queryBuilder .valueEditor-caseSensitive input[type='checkbox'] { - width: 14px; - height: 14px; - accent-color: #1890ff; -} - -.queryBuilder .valueSource-dropdown { - min-width: 100px; -} - -.queryBuilder:disabled, -.queryBuilder .disabled { - opacity: 0.65; - cursor: not-allowed; - pointer-events: none; -} - -.queryBuilder .validation-error { - color: #ff4d4f; + margin: 8px 0; + color: var(--ss-text-secondary, rgba(0, 0, 0, 0.45)); font-size: 12px; - margin-top: 4px; } -.queryBuilder .rule-with-error { - border-color: #ff4d4f !important; +.betweenRules::before, +.betweenRules::after { + content: ''; + flex: 1; + height: 1px; + background-color: var(--ss-border-color, #d9d9d9); } -.queryBuilder .rule-with-error input, -.queryBuilder .rule-with-error select { - border-color: #ff4d4f !important; +.betweenRules::before { + margin-right: 12px; } -.queryBuilder .rule-with-error input:focus, -.queryBuilder .rule-with-error select:focus { - box-shadow: 0 0 0 2px rgba(255, 77, 79, 0.2) !important; +.betweenRules::after { + margin-left: 12px; } -@media (prefers-color-scheme: dark) { - .queryBuilder { - --querybuilder-border-color: #434343; - --querybuilder-disabled-color: rgba(255, 255, 255, 0.3); - } - - .queryBuilder .rule { - background: rgba(255, 255, 255, 0.04); - } - - .queryBuilder .rule:hover { - background: rgba(255, 255, 255, 0.08); - } - - .queryBuilder select { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='rgba(255,255,255,0.3)' d='M6 8L1 3h10z'/%3E%3C/svg%3E"); - } - - .queryBuilder input::placeholder { - color: rgba(255, 255, 255, 0.3); - } +.dragHandle { + cursor: grab; + color: var(--ss-text-secondary, rgba(0, 0, 0, 0.45)); + padding: 4px; + margin-right: 4px; +} + +.dragHandle:hover { + color: var(--ss-text-main, rgba(0, 0, 0, 0.88)); +} + +.queryBuilder .ant-select-dropdown { + background-color: var(--ss-card-bg, #fff); +} + +.queryBuilder .ant-select-item { + color: var(--ss-text-main, rgba(0, 0, 0, 0.88)); +} + +.queryBuilder .ant-select-item-option-active { + background-color: var(--ss-item-hover, rgba(0, 0, 0, 0.04)); +} + +.queryBuilder .ant-select-item-option-selected { + background-color: rgba(var(--ss-primary-rgb, 22, 119, 255), 0.1); + color: var(--ss-primary-color, #1677ff); +} + +.queryBuilder .ant-btn { + border-radius: 6px; +} + +.queryBuilder .ant-select-selector, +.queryBuilder .ant-input, +.queryBuilder .ant-input-number { + border-radius: 6px; +} + +[theme-mode='dark'] .ruleGroup { + background-color: var(--ss-card-bg, #1f1f1f); + border-color: var(--ss-border-color, #424242); +} + +[theme-mode='dark'] .rule { + background-color: var(--ss-item-bg, rgba(255, 255, 255, 0.04)); +} + +[theme-mode='dark'] .rule:hover { + background-color: var(--ss-item-hover, rgba(255, 255, 255, 0.08)); +} + +[theme-mode='dark'] .rule-fields .ant-select-selector, +[theme-mode='dark'] .rule-operators .ant-select-selector, +[theme-mode='dark'] .rule-subfields .ant-select-selector, +[theme-mode='dark'] .rule-value .ant-input, +[theme-mode='dark'] .rule-value .ant-input-number, +[theme-mode='dark'] .rule-value .ant-select-selector { + background-color: var(--ss-input-bg, #141414) !important; + border-color: var(--ss-border-color, #424242) !important; + color: var(--ss-text-main, rgba(255, 255, 255, 0.85)) !important; +} + +[theme-mode='dark'] .rule-value .ant-input-number-input { + color: var(--ss-text-main, rgba(255, 255, 255, 0.85)) !important; +} + +[theme-mode='dark'] .betweenRules { + color: var(--ss-text-secondary, rgba(255, 255, 255, 0.45)); +} + +[theme-mode='dark'] .betweenRules::before, +[theme-mode='dark'] .betweenRules::after { + background-color: var(--ss-border-color, #424242); +} + +[theme-mode='dark'] .dragHandle { + color: var(--ss-text-secondary, rgba(255, 255, 255, 0.45)); +} + +[theme-mode='dark'] .dragHandle:hover { + color: var(--ss-text-main, rgba(255, 255, 255, 0.85)); +} + +[theme-mode='dark'] .queryBuilder .ant-select-dropdown { + background-color: var(--ss-card-bg, #1f1f1f); +} + +[theme-mode='dark'] .queryBuilder .ant-select-item { + color: var(--ss-text-main, rgba(255, 255, 255, 0.85)); +} + +[theme-mode='dark'] .queryBuilder .ant-select-item-option-active { + background-color: var(--ss-item-hover, rgba(255, 255, 255, 0.08)); +} + +[theme-mode='dark'] .queryBuilder .ant-select-item-option-selected { + background-color: rgba(var(--ss-primary-rgb, 22, 119, 255), 0.2); +} + +.ruleGroup-header .ant-select-selector { + min-width: 80px; } diff --git a/tsconfig.web.json b/tsconfig.web.json index 5bb3f60..2e5b775 100644 --- a/tsconfig.web.json +++ b/tsconfig.web.json @@ -6,8 +6,7 @@ "src/renderer/src/**/*.tsx", "src/preload/*.d.ts", "src/preload/types.ts", - "src/shared/**/*", - "src/main/services/HttpService.ts" + "src/shared/**/*" ], "compilerOptions": { "composite": true,