更新builder的css

This commit is contained in:
NanGua_QWQ
2026-03-14 21:45:23 +08:00
parent c4d1e6f760
commit 528d01d035
7 changed files with 223 additions and 691 deletions
+1 -2
View File
@@ -16,8 +16,7 @@ export {
ThemeServiceToken,
WindowManagerToken,
TrayServiceToken,
AutoScoreServiceToken,
FileSystemServiceToken
AutoScoreServiceToken
} from './tokens'
export type {
appRuntimeContext,
-1
View File
@@ -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')
+1 -8
View File
@@ -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)
+2 -121
View File
@@ -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<number, NodeJS.Timeout> = new Map()
@@ -130,83 +112,7 @@ export class AutoScoreService extends Service {
}
private async loadRulesFromFile(): Promise<void> {
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<AutoScoreRulesFile>(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<void> {
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() {
-281
View File
@@ -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<void> | 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<void> {
await this.ensureDirectories()
}
private async ensureDirectories(): Promise<void> {
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<T = any>(
relativePath: string,
folder: 'automatic' | 'script' = 'automatic'
): Promise<T | null> {
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<boolean> {
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<string | null> {
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<boolean> {
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<boolean> {
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<ConfigFileInfo[]> {
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<boolean> {
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 }
}
)
}
}
@@ -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;
}
+1 -2
View File
@@ -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,