1
0
mirror of https://github.com/ZeroCatDev/Classworks.git synced 2025-07-02 09:19:23 +00:00

Refactor SettingItem.vue for improved readability and maintainability. Standardize template formatting, enhance indentation and spacing, and ensure consistent use of quotation marks. Update component properties and methods for better clarity and organization.

This commit is contained in:
SunWuyuan 2025-05-11 17:04:09 +08:00
parent 8bf9d8700b
commit 6d6e4a27a1
No known key found for this signature in database
GPG Key ID: A6A54CF66F56BB64

View File

@ -1,7 +1,7 @@
<template> <template>
<v-list-item class="setting-item" :disabled="disabled"> <v-list-item class="setting-item" :disabled="disabled">
<template #prepend> <template #prepend>
<v-icon :icon="settingIcon" /> <v-icon :icon="settingIcon" />
</template> </template>
<v-list-item-title class="text-wrap"> <v-list-item-title class="text-wrap">
@ -12,34 +12,79 @@
<span class="text-caption text-grey-darken-1">{{ settingKey }}</span> <span class="text-caption text-grey-darken-1">{{ settingKey }}</span>
</v-list-item-subtitle> </v-list-item-subtitle>
<template #append > <template #append>
<div class="d-flex flex-column flex-sm-row align-center"> <div class="d-flex flex-column flex-sm-row align-center">
<div v-if="type !== 'string' || hasOptions" class="me-2"> <div v-if="type !== 'string' || hasOptions" class="me-2">
<!-- 根据设置类型渲染不同的控件 --> <!-- 根据设置类型渲染不同的控件 -->
<v-switch v-if="type === 'boolean'" v-model="localValue" density="comfortable" hide-details :disabled="disabled" <v-switch
@update:model-value="updateSetting" /> v-if="type === 'boolean'"
v-model="localValue"
density="comfortable"
hide-details
:disabled="disabled"
@update:model-value="updateSetting"
/>
<v-select v-else-if="type === 'string' && hasOptions" v-model="localValue" :items="selectOptions" <v-select
density="compact" hide-details :disabled="disabled" class="setting-select" variant="outlined" bg-color="surface" v-else-if="type === 'string' && hasOptions"
@update:model-value="updateSetting" item-title="title" item-value="value" /> v-model="localValue"
:items="selectOptions"
density="compact"
hide-details
:disabled="disabled"
class="setting-select"
variant="outlined"
bg-color="surface"
@update:model-value="updateSetting"
item-title="title"
item-value="value"
/>
<div v-else-if="type === 'number'" class="d-flex align-center"> <div v-else-if="type === 'number'" class="d-flex align-center">
<v-btn icon="mdi-minus" size="small" variant="text" :disabled="disabled || localValue <= minValue" <v-btn
@click="adjustValue(-stepValue)" /> icon="mdi-minus"
size="small"
variant="text"
:disabled="disabled || localValue <= minValue"
@click="adjustValue(-stepValue)"
/>
<v-text-field v-model.number="localValue" type="number" density="compact" hide-details :min="minValue" <v-text-field
:max="maxValue" :step="stepValue" :disabled="disabled" class="mx-2 setting-number-field" style="width: 80px" v-model.number="localValue"
variant="outlined" bg-color="surface" @update:model-value="updateSetting" /> type="number"
density="compact"
hide-details
:min="minValue"
:max="maxValue"
:step="stepValue"
:disabled="disabled"
class="mx-2 setting-number-field"
style="width: 80px"
variant="outlined"
bg-color="surface"
@update:model-value="updateSetting"
/>
<v-btn icon="mdi-plus" size="small" variant="text" :disabled="disabled || localValue >= maxValue" <v-btn
@click="adjustValue(stepValue)" /> icon="mdi-plus"
size="small"
variant="text"
:disabled="disabled || localValue >= maxValue"
@click="adjustValue(stepValue)"
/>
</div> </div>
</div> </div>
<v-menu location="bottom"> <v-menu location="bottom">
<template v-slot:activator="{ props }"> <template v-slot:activator="{ props }">
<v-btn icon="mdi-dots-vertical" size="small" variant="text" v-bind="props" class="ml-2" <v-btn
:disabled="disabled" /> icon="mdi-dots-vertical"
size="small"
variant="text"
v-bind="props"
class="ml-2"
:disabled="disabled"
/>
</template> </template>
<v-list density="compact"> <v-list density="compact">
<v-list-item @click="copySettingId"> <v-list-item @click="copySettingId">
@ -72,21 +117,39 @@
<!-- 文本框显示在下方 --> <!-- 文本框显示在下方 -->
<div v-if="type === 'string' && !hasOptions" class="px-4 pb-2 pt-0"> <div v-if="type === 'string' && !hasOptions" class="px-4 pb-2 pt-0">
<v-text-field v-model="localValue" density="compact" hide-details :disabled="disabled" <v-text-field
class="setting-text-field mt-1" variant="outlined" bg-color="surface" @update:model-value="updateSetting" /> v-model="localValue"
density="compact"
hide-details
:disabled="disabled"
class="setting-text-field mt-1"
variant="outlined"
bg-color="surface"
@update:model-value="updateSetting"
/>
</div> </div>
<!-- 消息提示 --> <!-- 消息提示 -->
<v-snackbar v-model="showSnackbar" :timeout="2000" color="success" location="top"> <v-snackbar
v-model="showSnackbar"
:timeout="2000"
color="success"
location="top"
>
{{ snackbarText }} {{ snackbarText }}
</v-snackbar> </v-snackbar>
</template> </template>
<script> <script>
import { getSetting, setSetting, getSettingDefinition, resetSetting } from '@/utils/settings'; import {
getSetting,
setSetting,
getSettingDefinition,
resetSetting,
} from "@/utils/settings";
export default { export default {
name: 'SettingItem', name: "SettingItem",
props: { props: {
/** /**
@ -94,7 +157,7 @@ export default {
*/ */
settingKey: { settingKey: {
type: String, type: String,
required: true required: true,
}, },
/** /**
@ -102,7 +165,7 @@ export default {
*/ */
icon: { icon: {
type: String, type: String,
default: null default: null,
}, },
/** /**
@ -110,7 +173,7 @@ export default {
*/ */
disabled: { disabled: {
type: Boolean, type: Boolean,
default: false default: false,
}, },
/** /**
@ -118,7 +181,7 @@ export default {
*/ */
title: { title: {
type: String, type: String,
default: null default: null,
}, },
/** /**
@ -126,8 +189,8 @@ export default {
*/ */
description: { description: {
type: String, type: String,
default: null default: null,
} },
}, },
data() { data() {
@ -141,45 +204,45 @@ export default {
maxValue: 100, maxValue: 100,
stepValue: 1, stepValue: 1,
showSnackbar: false, showSnackbar: false,
snackbarText: '', snackbarText: "",
fontFamilies: [ fontFamilies: [
{ title: 'Arial', value: 'Arial, sans-serif' }, { title: "Arial", value: "Arial, sans-serif" },
{ title: 'Calibri', value: 'Calibri, sans-serif' }, { title: "Calibri", value: "Calibri, sans-serif" },
{ title: 'Cambria', value: 'Cambria, serif' }, { title: "Cambria", value: "Cambria, serif" },
{ title: 'Consolas', value: 'Consolas, monospace' }, { title: "Consolas", value: "Consolas, monospace" },
{ title: 'Courier New', value: 'Courier New, monospace' }, { title: "Courier New", value: "Courier New, monospace" },
{ title: 'Georgia', value: 'Georgia, serif' }, { title: "Georgia", value: "Georgia, serif" },
{ title: 'Helvetica', value: 'Helvetica, sans-serif' }, { title: "Helvetica", value: "Helvetica, sans-serif" },
{ title: 'Segoe UI', value: 'Segoe UI, sans-serif' }, { title: "Segoe UI", value: "Segoe UI, sans-serif" },
{ title: 'Times New Roman', value: 'Times New Roman, serif' }, { title: "Times New Roman", value: "Times New Roman, serif" },
{ title: 'Trebuchet MS', value: 'Trebuchet MS, sans-serif' }, { title: "Trebuchet MS", value: "Trebuchet MS, sans-serif" },
{ title: 'Verdana', value: 'Verdana, sans-serif' }, { title: "Verdana", value: "Verdana, sans-serif" },
{ title: 'Monospace', value: 'monospace' }, { title: "Monospace", value: "monospace" },
{ title: 'Sans-serif', value: 'sans-serif' }, { title: "Sans-serif", value: "sans-serif" },
{ title: 'Serif', value: 'serif' } { title: "Serif", value: "serif" },
], ],
// //
displayValueMappings: { displayValueMappings: {
'display.emptySubjectDisplay': { "display.emptySubjectDisplay": {
'card': '卡片', card: "卡片",
'button': '按钮' button: "按钮",
}, },
'theme.mode': { "theme.mode": {
'light': '浅色', light: "浅色",
'dark': '深色' dark: "深色",
},
"server.provider": {
classworkscloud: "Classworks云端存储",
"kv-local": "KV本地存储",
"kv-server": "KV远程服务器",
}, },
'server.provider': {
'kv-local': 'KV本地存储',
'kv-server': 'KV远程服务器',
'classworkscloud': 'Classworks云端存储'
}
}, },
// //
defaultIcons: { defaultIcons: {
'boolean': 'mdi-toggle-switch-outline', boolean: "mdi-toggle-switch-outline",
'number': 'mdi-numeric', number: "mdi-numeric",
'string': 'mdi-form-textbox' string: "mdi-form-textbox",
} },
}; };
}, },
@ -196,7 +259,7 @@ export default {
} }
// 使 // 使
const parts = this.settingKey.split('.'); const parts = this.settingKey.split(".");
return parts[parts.length - 1]; return parts[parts.length - 1];
}, },
@ -212,8 +275,10 @@ export default {
// //
isFontFamily() { isFontFamily() {
return this.settingKey.toLowerCase().includes('fontfamily') || return (
this.settingKey.toLowerCase().includes('font.family'); this.settingKey.toLowerCase().includes("fontfamily") ||
this.settingKey.toLowerCase().includes("font.family")
);
}, },
// //
@ -221,8 +286,11 @@ export default {
if (!this.definition) return true; if (!this.definition) return true;
// //
if (typeof this.localValue === 'object' && this.localValue !== null) { if (typeof this.localValue === "object" && this.localValue !== null) {
return JSON.stringify(this.localValue) === JSON.stringify(this.definition.default); return (
JSON.stringify(this.localValue) ===
JSON.stringify(this.definition.default)
);
} }
return this.localValue === this.definition.default; return this.localValue === this.definition.default;
@ -241,8 +309,8 @@ export default {
} }
// 使 // 使
return this.defaultIcons[this.type] || 'mdi-cog-outline'; return this.defaultIcons[this.type] || "mdi-cog-outline";
} },
}, },
created() { created() {
@ -266,7 +334,7 @@ export default {
this.localValue = getSetting(this.settingKey); this.localValue = getSetting(this.settingKey);
// //
if (this.type === 'string') { if (this.type === "string") {
// //
if (this.isFontFamily) { if (this.isFontFamily) {
this.selectOptions = this.fontFamilies; this.selectOptions = this.fontFamilies;
@ -275,10 +343,12 @@ export default {
// //
else if (this.settingKey in this.displayValueMappings) { else if (this.settingKey in this.displayValueMappings) {
const mapping = this.displayValueMappings[this.settingKey]; const mapping = this.displayValueMappings[this.settingKey];
this.selectOptions = Object.entries(mapping).map(([value, title]) => ({ this.selectOptions = Object.entries(mapping).map(
title, ([value, title]) => ({
value title,
})); value,
})
);
this.hasOptions = true; this.hasOptions = true;
} }
// //
@ -288,13 +358,13 @@ export default {
if (match) { if (match) {
const optionsStr = match[1]; const optionsStr = match[1];
const options = optionsStr.split(',').map(opt => { const options = optionsStr.split(",").map((opt) => {
const cleaned = opt.trim().replace(/['"]/g, ''); const cleaned = opt.trim().replace(/['"]/g, "");
// //
const displayValue = this.getDisplayValue(cleaned); const displayValue = this.getDisplayValue(cleaned);
return { return {
title: displayValue || cleaned, title: displayValue || cleaned,
value: cleaned value: cleaned,
}; };
}); });
@ -307,7 +377,7 @@ export default {
} }
// //
if (this.type === 'number' && this.definition.validate) { if (this.type === "number" && this.definition.validate) {
const validateStr = this.definition.validate.toString(); const validateStr = this.definition.validate.toString();
// //
@ -349,9 +419,9 @@ export default {
// //
let typedValue = value; let typedValue = value;
if (this.type === 'boolean') { if (this.type === "boolean") {
typedValue = Boolean(value); typedValue = Boolean(value);
} else if (this.type === 'number') { } else if (this.type === "number") {
typedValue = Number(value); typedValue = Number(value);
// //
@ -363,16 +433,16 @@ export default {
const success = setSetting(this.settingKey, typedValue); const success = setSetting(this.settingKey, typedValue);
if (success) { if (success) {
this.$emit('update', this.settingKey, typedValue); this.$emit("update", this.settingKey, typedValue);
} else { } else {
// //
this.localValue = getSetting(this.settingKey); this.localValue = getSetting(this.settingKey);
this.$emit('error', this.settingKey); this.$emit("error", this.settingKey);
} }
}, },
adjustValue(amount) { adjustValue(amount) {
if (this.type !== 'number') return; if (this.type !== "number") return;
const newValue = this.localValue + amount; const newValue = this.localValue + amount;
@ -384,31 +454,33 @@ export default {
// ID // ID
copySettingId() { copySettingId() {
navigator.clipboard.writeText(this.settingKey) navigator.clipboard
.writeText(this.settingKey)
.then(() => { .then(() => {
this.showSnackbarMessage('设置ID已复制到剪贴板'); this.showSnackbarMessage("设置ID已复制到剪贴板");
}) })
.catch(err => { .catch((err) => {
console.error('复制失败:', err); console.error("复制失败:", err);
}); });
}, },
// //
copySettingValue() { copySettingValue() {
let valueText = ''; let valueText = "";
if (typeof this.localValue === 'object' && this.localValue !== null) { if (typeof this.localValue === "object" && this.localValue !== null) {
valueText = JSON.stringify(this.localValue); valueText = JSON.stringify(this.localValue);
} else { } else {
valueText = String(this.localValue); valueText = String(this.localValue);
} }
navigator.clipboard.writeText(valueText) navigator.clipboard
.writeText(valueText)
.then(() => { .then(() => {
this.showSnackbarMessage('设置值已复制到剪贴板'); this.showSnackbarMessage("设置值已复制到剪贴板");
}) })
.catch(err => { .catch((err) => {
console.error('复制失败:', err); console.error("复制失败:", err);
}); });
}, },
@ -418,16 +490,16 @@ export default {
resetSetting(this.settingKey); resetSetting(this.settingKey);
this.localValue = getSetting(this.settingKey); this.localValue = getSetting(this.settingKey);
this.showSnackbarMessage('已重置为默认值'); this.showSnackbarMessage("已重置为默认值");
this.$emit('update', this.settingKey, this.localValue); this.$emit("update", this.settingKey, this.localValue);
}, },
// //
showSnackbarMessage(message) { showSnackbarMessage(message) {
this.snackbarText = message; this.snackbarText = message;
this.showSnackbar = true; this.showSnackbar = true;
} },
} },
}; };
</script> </script>