gaoluyang
2026-06-24 712aa51536236d43e87273e4ce45ac5691dffad8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
<script setup lang="ts">
import type {
  CustomPreferencesField,
  CustomPreferencesRecord,
} from '..\..\..\..\..\..\..\preferences\src';
 
import { computed } from 'vue';
 
import { $t } from '..\..\..\..\..\..\..\locales\src';
 
import InputItem from '../input-item.vue';
import NumberFieldItem from '../number-field-item.vue';
import SelectItem from '../select-item.vue';
import SwitchItem from '../switch-item.vue';
 
defineOptions({
  name: 'PreferenceCustomFields',
});
 
const props = defineProps<{
  fields: Array<CustomPreferencesField>;
  values: CustomPreferencesRecord;
}>();
 
const emit = defineEmits<{
  update: [updates: CustomPreferencesRecord];
}>();
 
function handleUpdate(key: string, value: boolean | number | string) {
  emit('update', { [key]: value });
}
 
function handleBooleanUpdate(key: string, value: boolean | undefined) {
  handleUpdate(key, value ?? false);
}
 
function resolveNumberValue(value: unknown) {
  return typeof value === 'number' && Number.isFinite(value)
    ? value
    : undefined;
}
 
function handleNumberUpdate(key: string, value: number | undefined) {
  const resolvedValue = resolveNumberValue(value);
 
  if (resolvedValue !== undefined) {
    handleUpdate(key, resolvedValue);
  }
}
 
function handleStringUpdate(key: string, value: string | undefined) {
  handleUpdate(key, value ?? '');
}
 
const resolvedFields = computed(() => {
  return props.fields.map((field) => {
    return {
      ...field,
      label: $t(field.label),
      options:
        field.component === 'select'
          ? field.options.map((option) => ({
              ...option,
              label: $t(option.label),
            }))
          : undefined,
      placeholder: field.placeholder ? $t(field.placeholder) : '',
      tip: field.tip ? $t(field.tip) : '',
    };
  });
});
</script>
 
<template>
  <template v-for="field in resolvedFields" :key="field.key">
    <SwitchItem
      v-if="field.component === 'switch'"
      :disabled="field.disabled"
      :model-value="Boolean(values[field.key])"
      :tip="field.tip"
      v-bind="field.componentProps"
      @update:model-value="handleBooleanUpdate(field.key, $event)"
    >
      {{ field.label }}
    </SwitchItem>
    <NumberFieldItem
      v-else-if="field.component === 'number'"
      :disabled="field.disabled"
      :model-value="resolveNumberValue(values[field.key])"
      :placeholder="field.placeholder"
      :tip="field.tip"
      v-bind="field.componentProps"
      @update:model-value="handleNumberUpdate(field.key, $event)"
    >
      {{ field.label }}
    </NumberFieldItem>
    <SelectItem
      v-else-if="field.component === 'select'"
      :disabled="field.disabled"
      :items="field.options"
      :model-value="String(values[field.key] ?? '')"
      :placeholder="field.placeholder"
      :tip="field.tip"
      v-bind="field.componentProps"
      @update:model-value="handleStringUpdate(field.key, $event)"
    >
      {{ field.label }}
    </SelectItem>
    <InputItem
      v-else
      :disabled="field.disabled"
      :model-value="String(values[field.key] ?? '')"
      :placeholder="field.placeholder"
      :tip="field.tip"
      v-bind="field.componentProps"
      @update:model-value="handleStringUpdate(field.key, $event)"
    >
      {{ field.label }}
    </InputItem>
  </template>
</template>