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:
parent
8bf9d8700b
commit
6d6e4a27a1
@ -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>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user