feat: 添加设置页面,采用玻璃拟态设计并支持分配规则管理
This commit is contained in:
@@ -37,6 +37,7 @@ export const AllocationRuleForm: React.FC<AllocationRuleFormProps> = ({
|
||||
triggerType: 'income',
|
||||
sourceAccountId: undefined,
|
||||
isActive: true,
|
||||
autoExecute: true,
|
||||
targets: [],
|
||||
});
|
||||
|
||||
@@ -50,6 +51,7 @@ export const AllocationRuleForm: React.FC<AllocationRuleFormProps> = ({
|
||||
triggerType: allocationRule.triggerType as 'income' | 'manual',
|
||||
sourceAccountId: allocationRule.sourceAccountId,
|
||||
isActive: allocationRule.isActive,
|
||||
autoExecute: allocationRule.autoExecute,
|
||||
targets: allocationRule.targets.map((target) => ({
|
||||
targetType: target.targetType,
|
||||
targetId: target.targetId,
|
||||
@@ -309,6 +311,27 @@ export const AllocationRuleForm: React.FC<AllocationRuleFormProps> = ({
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{/* Auto Execute */}
|
||||
<div className="allocation-rule-form__field allocation-rule-form__field--checkbox">
|
||||
<label className="allocation-rule-form__checkbox-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="autoExecute"
|
||||
checked={formData.autoExecute !== false}
|
||||
onChange={(e) => {
|
||||
const checked = e.target.checked;
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
autoExecute: checked,
|
||||
}));
|
||||
}}
|
||||
className="allocation-rule-form__checkbox"
|
||||
disabled={isLoading}
|
||||
/>
|
||||
<span>自动执行(无需确认,并发送短信通知)</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{/* Allocation Targets */}
|
||||
<div className="allocation-rule-form__section">
|
||||
<div className="allocation-rule-form__section-header">
|
||||
|
||||
@@ -705,4 +705,27 @@
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3));
|
||||
}
|
||||
|
||||
.settings-input-container {
|
||||
min-width: 200px;
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.settings-text-input {
|
||||
width: 100%;
|
||||
padding: var(--spacing-md);
|
||||
border: 1px solid var(--glass-border);
|
||||
border-radius: var(--radius-lg);
|
||||
background: var(--glass-bg);
|
||||
color: var(--color-text);
|
||||
font-size: var(--font-base);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.settings-text-input:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-primary);
|
||||
box-shadow: 0 0 0 3px var(--color-primary-lighter);
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
@@ -439,6 +439,22 @@ function Settings() {
|
||||
<span className="settings-toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="settings-item">
|
||||
<div className="settings-item-info">
|
||||
<label className="settings-item__label">手机号码</label>
|
||||
<p className="settings-item__description">用于接收短信通知(自动记账等)</p>
|
||||
</div>
|
||||
<div className="settings-input-container">
|
||||
<input
|
||||
type="tel"
|
||||
className="settings-text-input"
|
||||
placeholder="请输入手机号"
|
||||
value={userSettings?.phone || ''}
|
||||
onChange={(e) => handleUserSettingChange('phone', e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -17,6 +17,7 @@ function transformAllocationRule(data: Record<string, unknown>): AllocationRule
|
||||
sourceAccountId: (data.source_account_id ?? data.sourceAccountId) as number | undefined,
|
||||
sourceAccount: data.source_account ? transformSourceAccount(data.source_account as Record<string, unknown>) : undefined,
|
||||
isActive: (data.is_active ?? data.isActive) as boolean,
|
||||
autoExecute: (data.auto_execute ?? data.autoExecute) as boolean | undefined,
|
||||
targets: ((data.targets as Record<string, unknown>[]) || []).map(transformAllocationTarget),
|
||||
createdAt: (data.created_at ?? data.createdAt) as string,
|
||||
};
|
||||
@@ -58,6 +59,7 @@ export interface AllocationRuleFormInput {
|
||||
triggerType: 'income' | 'manual';
|
||||
sourceAccountId?: number;
|
||||
isActive: boolean;
|
||||
autoExecute?: boolean;
|
||||
targets: AllocationTargetInput[];
|
||||
}
|
||||
|
||||
@@ -143,6 +145,7 @@ export const createAllocationRule = async (
|
||||
trigger_type: data.triggerType,
|
||||
source_account_id: data.sourceAccountId,
|
||||
is_active: data.isActive,
|
||||
auto_execute: data.autoExecute,
|
||||
targets: data.targets.map(t => ({
|
||||
target_type: t.targetType,
|
||||
target_id: t.targetId,
|
||||
@@ -170,6 +173,7 @@ export const updateAllocationRule = async (
|
||||
trigger_type: data.triggerType,
|
||||
source_account_id: data.sourceAccountId,
|
||||
is_active: data.isActive,
|
||||
auto_execute: data.autoExecute,
|
||||
targets: data.targets.map(t => ({
|
||||
target_type: t.targetType,
|
||||
target_id: t.targetId,
|
||||
|
||||
@@ -76,7 +76,9 @@ export interface UserSettings {
|
||||
defaultExpenseAccountId?: number | null;
|
||||
defaultIncomeAccountId?: number | null;
|
||||
defaultExpenseAccount?: Account | null;
|
||||
defaultExpenseAccount?: Account | null;
|
||||
defaultIncomeAccount?: Account | null;
|
||||
phone?: string;
|
||||
}
|
||||
|
||||
// Tag Interface
|
||||
@@ -222,6 +224,7 @@ export interface AllocationRule {
|
||||
sourceAccountId?: number;
|
||||
sourceAccount?: Account;
|
||||
isActive: boolean;
|
||||
autoExecute?: boolean;
|
||||
targets: AllocationTarget[];
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user