pwa,设置项,自动刷新
This commit is contained in:
@@ -144,7 +144,7 @@ export default {
|
||||
|
||||
async clearIndexedDB() {
|
||||
try {
|
||||
const DBName = "HomeworkDB";
|
||||
const DBName = "ClassworksDB";
|
||||
// 删除整个数据库
|
||||
await window.indexedDB.deleteDatabase(DBName);
|
||||
this.$message.success("清除成功", "数据库缓存已清除");
|
||||
@@ -156,7 +156,7 @@ export default {
|
||||
|
||||
async exportData() {
|
||||
try {
|
||||
const DBName = "HomeworkDB";
|
||||
const DBName = "ClassworksDB";
|
||||
const data = { indexedDB: {} };
|
||||
|
||||
// 打开数据库
|
||||
|
||||
@@ -1,260 +1,46 @@
|
||||
<template>
|
||||
<settings-card
|
||||
title="显示设置"
|
||||
icon="mdi-monitor"
|
||||
border
|
||||
>
|
||||
<v-form v-model="isValid" @submit.prevent="save">
|
||||
<settings-card title="显示设置" icon="mdi-monitor" border>
|
||||
<v-list>
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-card-outline" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>空科目显示方式</v-list-item-title>
|
||||
<v-list-item-subtitle>选择空科目的显示方式</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-select
|
||||
v-model="emptySubjectDisplay"
|
||||
:items="displayOptions"
|
||||
density="compact"
|
||||
hide-details
|
||||
variant="outlined"
|
||||
style="max-width: 150px"
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
<setting-item :setting-key="'display.emptySubjectDisplay'" />
|
||||
|
||||
|
||||
<v-divider class="my-2" />
|
||||
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-sort-variant" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>动态排序</v-list-item-title>
|
||||
<v-list-item-subtitle>优化卡片布局以提高显示效果</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="dynamicSort"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
<setting-item :setting-key="'display.dynamicSort'" />
|
||||
|
||||
<v-divider class="my-2" />
|
||||
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-dice-multiple" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>显示随机按钮</v-list-item-title>
|
||||
<v-list-item-subtitle>在主页显示随机点名按钮</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="showRandomButton"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
<setting-item :setting-key="'display.showRandomButton'" />
|
||||
|
||||
<v-divider class="my-2" />
|
||||
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-fullscreen" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>显示全屏按钮</v-list-item-title>
|
||||
<v-list-item-subtitle>在主页显示全屏切换按钮</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="showFullscreenButton"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
<setting-item :setting-key="'display.showFullscreenButton'" />
|
||||
|
||||
<v-divider class="my-2" />
|
||||
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-cards-outline" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>卡片悬浮效果</v-list-item-title>
|
||||
<v-list-item-subtitle>启用卡片悬停时的动画效果</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="cardHoverEffect"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
<setting-item :setting-key="'display.cardHoverEffect'" />
|
||||
|
||||
<v-divider class="my-2" />
|
||||
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-gesture-tap" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>增强触摸模式</v-list-item-title>
|
||||
<v-list-item-subtitle>优化触摸屏操作体验</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="enhancedTouchMode"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
<setting-item :setting-key="'display.enhancedTouchMode'" />
|
||||
|
||||
<v-divider class="my-2" />
|
||||
<setting-item :setting-key="'display.showAntiScreenBurnCard'" />
|
||||
|
||||
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-shield-check" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>显示防烧屏提示</v-list-item-title>
|
||||
<v-list-item-subtitle>显示防烧屏技术提示卡片</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="showAntiScreenBurnCard"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
|
||||
<div class="d-flex gap-2 mt-4">
|
||||
<v-btn
|
||||
color="primary"
|
||||
type="submit"
|
||||
:disabled="!hasChanges || !isValid"
|
||||
prepend-icon="mdi-content-save"
|
||||
>
|
||||
保存更改
|
||||
</v-btn>
|
||||
<v-btn
|
||||
variant="outlined"
|
||||
@click="reset"
|
||||
:disabled="!hasChanges"
|
||||
>
|
||||
重置
|
||||
</v-btn>
|
||||
</div>
|
||||
</v-list>
|
||||
</v-form>
|
||||
</settings-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SettingsCard from '@/components/SettingsCard.vue';
|
||||
import { getSetting, setSetting } from '@/utils/settings';
|
||||
|
||||
import SettingItem from '@/components/settings/SettingItem.vue';
|
||||
export default {
|
||||
name: 'DisplaySettingsCard',
|
||||
components: { SettingsCard },
|
||||
components: { SettingsCard, SettingItem },
|
||||
data() {
|
||||
const settings = {
|
||||
emptySubjectDisplay: getSetting('display.emptySubjectDisplay'),
|
||||
dynamicSort: getSetting('display.dynamicSort'),
|
||||
showRandomButton: getSetting('display.showRandomButton'),
|
||||
showFullscreenButton: getSetting('display.showFullscreenButton'),
|
||||
cardHoverEffect: getSetting('display.cardHoverEffect'),
|
||||
enhancedTouchMode: getSetting('display.enhancedTouchMode'),
|
||||
showAntiScreenBurnCard: getSetting('display.showAntiScreenBurnCard')
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
localSettings: { ...settings },
|
||||
originalSettings: settings,
|
||||
isValid: true,
|
||||
displayOptions: [
|
||||
{ title: '卡片', value: 'card' },
|
||||
{ title: '按钮', value: 'button' }
|
||||
]
|
||||
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasChanges() {
|
||||
return JSON.stringify(this.localSettings) !== JSON.stringify(this.originalSettings);
|
||||
},
|
||||
emptySubjectDisplay: {
|
||||
get() {
|
||||
return this.localSettings.emptySubjectDisplay;
|
||||
},
|
||||
set(value) {
|
||||
this.localSettings.emptySubjectDisplay = value;
|
||||
this.$emit('saved');
|
||||
}
|
||||
},
|
||||
dynamicSort: {
|
||||
get() {
|
||||
return this.localSettings.dynamicSort;
|
||||
},
|
||||
set(value) {
|
||||
this.localSettings.dynamicSort = value;
|
||||
this.$emit('saved');
|
||||
}
|
||||
},
|
||||
showRandomButton: {
|
||||
get() {
|
||||
return this.localSettings.showRandomButton;
|
||||
},
|
||||
set(value) {
|
||||
this.localSettings.showRandomButton = value;
|
||||
this.$emit('saved');
|
||||
}
|
||||
},
|
||||
showFullscreenButton: {
|
||||
get() {
|
||||
return this.localSettings.showFullscreenButton;
|
||||
},
|
||||
set(value) {
|
||||
this.localSettings.showFullscreenButton = value;
|
||||
this.$emit('saved');
|
||||
}
|
||||
},
|
||||
cardHoverEffect: {
|
||||
get() {
|
||||
return this.localSettings.cardHoverEffect;
|
||||
},
|
||||
set(value) {
|
||||
this.localSettings.cardHoverEffect = value;
|
||||
this.$emit('saved');
|
||||
}
|
||||
},
|
||||
enhancedTouchMode: {
|
||||
get() {
|
||||
return this.localSettings.enhancedTouchMode;
|
||||
},
|
||||
set(value) {
|
||||
this.localSettings.enhancedTouchMode = value;
|
||||
this.$emit('saved');
|
||||
}
|
||||
},
|
||||
showAntiScreenBurnCard: {
|
||||
get() {
|
||||
return this.localSettings.showAntiScreenBurnCard;
|
||||
},
|
||||
set(value) {
|
||||
this.localSettings.showAntiScreenBurnCard = value;
|
||||
this.$emit('saved');
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
save() {
|
||||
Object.entries(this.localSettings).forEach(([key, value]) => {
|
||||
setSetting(`display.${key}`, value);
|
||||
});
|
||||
this.originalSettings = { ...this.localSettings };
|
||||
this.$emit('saved');
|
||||
},
|
||||
reset() {
|
||||
this.localSettings = { ...this.originalSettings };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,135 +1,27 @@
|
||||
<template>
|
||||
<settings-card
|
||||
title="编辑设置"
|
||||
icon="mdi-pencil-cog"
|
||||
>
|
||||
<v-form v-model="isValid" @submit.prevent="save">
|
||||
<v-list>
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-content-save" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>自动保存</v-list-item-title>
|
||||
<v-list-item-subtitle>在编辑完成后自动保存到服务器</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="localSettings.autoSave"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
<settings-card title="编辑设置" icon="mdi-cog">
|
||||
<v-list>
|
||||
<setting-item :setting-key="'edit.autoSave'" />
|
||||
|
||||
<v-divider v-if="localSettings.autoSave" class="my-2" />
|
||||
|
||||
<v-list-item v-if="localSettings.autoSave">
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-calendar-lock" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>禁止自动保存非当天数据</v-list-item-title>
|
||||
<v-list-item-subtitle>仅允许自动保存当天的数据,避免误修改历史记录</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="localSettings.blockNonTodayAutoSave"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-divider class="my-2" />
|
||||
<setting-item :setting-key="'edit.blockNonTodayAutoSave'" />
|
||||
|
||||
<v-divider class="my-2" />
|
||||
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-calendar-alert" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>确认保存历史数据</v-list-item-title>
|
||||
<v-list-item-subtitle>保存非当天数据时显示确认对话框</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="localSettings.confirmNonTodaySave"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-divider class="my-2" />
|
||||
<setting-item :setting-key="'edit.confirmNonTodaySave'" />
|
||||
|
||||
<v-divider class="my-2" />
|
||||
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-refresh" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>编辑前刷新</v-list-item-title>
|
||||
<v-list-item-subtitle>在打开编辑框前从服务器获取最新数据</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="localSettings.refreshBeforeEdit"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
|
||||
<div class="d-flex gap-2 mt-4">
|
||||
<v-btn
|
||||
color="primary"
|
||||
type="submit"
|
||||
:disabled="!hasChanges || !isValid"
|
||||
prepend-icon="mdi-content-save"
|
||||
>
|
||||
保存更改
|
||||
</v-btn>
|
||||
<v-btn
|
||||
variant="outlined"
|
||||
@click="reset"
|
||||
:disabled="!hasChanges"
|
||||
>
|
||||
重置
|
||||
</v-btn>
|
||||
</div>
|
||||
</v-list>
|
||||
</v-form>
|
||||
<v-divider class="my-2" />
|
||||
<setting-item :setting-key="'edit.refreshBeforeEdit'" />
|
||||
|
||||
</v-list>
|
||||
</settings-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SettingsCard from '@/components/SettingsCard.vue';
|
||||
import { getSetting, setSetting } from '@/utils/settings';
|
||||
import SettingItem from '../SettingItem.vue';
|
||||
|
||||
export default {
|
||||
name: 'EditSettingsCard',
|
||||
components: { SettingsCard },
|
||||
data() {
|
||||
const settings = {
|
||||
autoSave: getSetting('edit.autoSave'),
|
||||
blockNonTodayAutoSave: getSetting('edit.blockNonTodayAutoSave'),
|
||||
confirmNonTodaySave: getSetting('edit.confirmNonTodaySave'),
|
||||
refreshBeforeEdit: getSetting('edit.refreshBeforeEdit')
|
||||
};
|
||||
|
||||
return {
|
||||
localSettings: { ...settings },
|
||||
originalSettings: settings,
|
||||
isValid: true
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasChanges() {
|
||||
return JSON.stringify(this.localSettings) !== JSON.stringify(this.originalSettings);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
save() {
|
||||
Object.entries(this.localSettings).forEach(([key, value]) => {
|
||||
setSetting(`edit.${key}`, value);
|
||||
});
|
||||
this.originalSettings = { ...this.localSettings };
|
||||
this.$emit('saved');
|
||||
},
|
||||
reset() {
|
||||
this.localSettings = { ...this.originalSettings };
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<v-card border class="mb-4">
|
||||
<v-card-title class="d-flex align-center">
|
||||
<v-icon icon="mdi-account-question" class="mr-2" />
|
||||
随机点名设置
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<v-switch
|
||||
v-model="randomPickerEnabled"
|
||||
label="启用随机点名功能"
|
||||
color="primary"
|
||||
hide-details
|
||||
class="mb-4"
|
||||
/>
|
||||
|
||||
<v-switch
|
||||
v-model="randomPickerAnimation"
|
||||
label="启用随机点名动画效果"
|
||||
color="primary"
|
||||
hide-details
|
||||
class="mb-4"
|
||||
:disabled="!randomPickerEnabled"
|
||||
/>
|
||||
|
||||
<v-slider
|
||||
v-model="defaultCount"
|
||||
label="默认抽取人数"
|
||||
min="1"
|
||||
max="10"
|
||||
step="1"
|
||||
thumb-label
|
||||
:disabled="!randomPickerEnabled"
|
||||
class="mb-4"
|
||||
/>
|
||||
|
||||
<v-divider class="my-4" />
|
||||
|
||||
<div class="text-subtitle-1 mb-2">学生过滤设置</div>
|
||||
|
||||
<v-switch
|
||||
v-model="excludeAbsent"
|
||||
label="排除请假学生"
|
||||
color="primary"
|
||||
hide-details
|
||||
class="mb-2"
|
||||
:disabled="!randomPickerEnabled"
|
||||
/>
|
||||
|
||||
<v-switch
|
||||
v-model="excludeLate"
|
||||
label="排除迟到学生"
|
||||
color="primary"
|
||||
hide-details
|
||||
class="mb-2"
|
||||
:disabled="!randomPickerEnabled"
|
||||
/>
|
||||
|
||||
<v-switch
|
||||
v-model="excludeExcluded"
|
||||
label="排除不参与学生"
|
||||
color="primary"
|
||||
hide-details
|
||||
class="mb-2"
|
||||
:disabled="!randomPickerEnabled"
|
||||
/>
|
||||
|
||||
<v-alert
|
||||
v-if="randomPickerEnabled"
|
||||
type="info"
|
||||
variant="tonal"
|
||||
class="mt-4"
|
||||
density="compact"
|
||||
>
|
||||
随机点名功能将在主页显示一个按钮,点击后可以随机抽取学生。
|
||||
</v-alert>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSetting, setSetting } from '@/utils/settings';
|
||||
|
||||
export default {
|
||||
name: 'RandomPickerSettingsCard',
|
||||
data() {
|
||||
return {
|
||||
randomPickerEnabled: getSetting('randomPicker.enabled'),
|
||||
randomPickerAnimation: getSetting('randomPicker.animation'),
|
||||
defaultCount: getSetting('randomPicker.defaultCount'),
|
||||
excludeAbsent: getSetting('randomPicker.excludeAbsent'),
|
||||
excludeLate: getSetting('randomPicker.excludeLate'),
|
||||
excludeExcluded: getSetting('randomPicker.excludeExcluded')
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
randomPickerEnabled(newValue) {
|
||||
setSetting('randomPicker.enabled', newValue);
|
||||
},
|
||||
randomPickerAnimation(newValue) {
|
||||
setSetting('randomPicker.animation', newValue);
|
||||
},
|
||||
defaultCount(newValue) {
|
||||
setSetting('randomPicker.defaultCount', newValue);
|
||||
},
|
||||
excludeAbsent(newValue) {
|
||||
setSetting('randomPicker.excludeAbsent', newValue);
|
||||
},
|
||||
excludeLate(newValue) {
|
||||
setSetting('randomPicker.excludeLate', newValue);
|
||||
},
|
||||
excludeExcluded(newValue) {
|
||||
setSetting('randomPicker.excludeExcluded', newValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,102 +1,28 @@
|
||||
<template>
|
||||
<settings-card
|
||||
title="刷新设置"
|
||||
icon="mdi-refresh-circle"
|
||||
>
|
||||
<v-form v-model="isValid" @submit.prevent="save">
|
||||
<settings-card title="刷新设置" icon="mdi-refresh-circle">
|
||||
<v-form>
|
||||
<v-list>
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-refresh" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>自动刷新</v-list-item-title>
|
||||
<v-list-item-subtitle>在后台自动刷新数据</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="localSettings.auto"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
<setting-item setting-key="refresh.auto" title="自动刷新" /> <v-divider class="my-2" />
|
||||
|
||||
<v-divider class="my-2" />
|
||||
|
||||
<v-list-item>
|
||||
<template #prepend>
|
||||
<v-icon icon="mdi-timer" class="mr-3" />
|
||||
</template>
|
||||
<v-list-item-title>刷新间隔</v-list-item-title>
|
||||
<v-list-item-subtitle>设置自动刷新的时间间隔(分钟)</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-text-field
|
||||
v-model="localSettings.interval"
|
||||
type="number"
|
||||
min="1"
|
||||
max="60"
|
||||
density="comfortable"
|
||||
hide-details
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
|
||||
<div class="d-flex gap-2 mt-4">
|
||||
<v-btn
|
||||
color="primary"
|
||||
type="submit"
|
||||
:disabled="!hasChanges || !isValid"
|
||||
prepend-icon="mdi-content-save"
|
||||
>
|
||||
保存更改
|
||||
</v-btn>
|
||||
<v-btn
|
||||
variant="outlined"
|
||||
@click="reset"
|
||||
:disabled="!hasChanges"
|
||||
>
|
||||
重置
|
||||
</v-btn>
|
||||
</div>
|
||||
<setting-item setting-key="refresh.interval" title="刷新间隔" />
|
||||
</v-list>
|
||||
|
||||
</v-form>
|
||||
</settings-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SettingsCard from '@/components/SettingsCard.vue';
|
||||
import { getSetting, setSetting } from '@/utils/settings';
|
||||
|
||||
import SettingItem from '@/components/settings/SettingItem.vue';
|
||||
export default {
|
||||
name: 'RefreshSettingsCard',
|
||||
components: { SettingsCard },
|
||||
data() {
|
||||
const settings = {
|
||||
auto: getSetting('refresh.auto'),
|
||||
interval: getSetting('refresh.interval')
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
localSettings: { ...settings },
|
||||
originalSettings: settings,
|
||||
isValid: true
|
||||
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasChanges() {
|
||||
return JSON.stringify(this.localSettings) !== JSON.stringify(this.originalSettings);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
save() {
|
||||
Object.entries(this.localSettings).forEach(([key, value]) => {
|
||||
setSetting(`refresh.${key}`, value);
|
||||
});
|
||||
this.originalSettings = { ...this.localSettings };
|
||||
this.$emit('saved');
|
||||
},
|
||||
reset() {
|
||||
this.localSettings = { ...this.originalSettings };
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,52 +1,19 @@
|
||||
<template>
|
||||
<settings-card title="数据源设置" icon="mdi-database" :loading="loading">
|
||||
<v-form v-model="isValid" @submit.prevent="save">
|
||||
<v-select
|
||||
v-model="localSettings.provider"
|
||||
:items="dataProviders"
|
||||
label="数据提供者"
|
||||
class="mb-4"
|
||||
/>
|
||||
<v-expand-transition>
|
||||
<div v-if="localSettings.provider === 'server'">
|
||||
<v-text-field
|
||||
v-model="localSettings.domain"
|
||||
label="服务器域名"
|
||||
placeholder="例如: http://example.com"
|
||||
prepend-inner-icon="mdi-web"
|
||||
/>
|
||||
</div>
|
||||
</v-expand-transition>
|
||||
<v-form>
|
||||
<setting-item setting-key="server.provider" title="数据提供者" />
|
||||
<v-divider class="my-2" />
|
||||
<setting-item setting-key="server.domain" title="服务器域名" /> <v-divider class="my-2" />
|
||||
|
||||
<v-text-field
|
||||
v-model="localSettings.classNumber"
|
||||
label="班号"
|
||||
placeholder="例如: 1 或 A"
|
||||
prepend-inner-icon="mdi-account-group"
|
||||
persistent-hint
|
||||
/>
|
||||
|
||||
<div class="d-flex gap-2 mt-4">
|
||||
<v-btn
|
||||
color="primary"
|
||||
type="submit"
|
||||
:disabled="!hasChanges || !isValid"
|
||||
prepend-icon="mdi-content-save"
|
||||
>
|
||||
保存更改
|
||||
</v-btn>
|
||||
<v-btn variant="outlined" @click="reset" :disabled="!hasChanges">
|
||||
重置
|
||||
</v-btn>
|
||||
</div>
|
||||
<setting-item setting-key="server.classNumber" title="班号" />
|
||||
|
||||
</v-form>
|
||||
</settings-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SettingsCard from "@/components/SettingsCard.vue";
|
||||
import { getSetting, setSetting } from "@/utils/settings";
|
||||
|
||||
import SettingItem from "@/components/settings/SettingItem.vue";
|
||||
export default {
|
||||
name: "ServerSettingsCard",
|
||||
components: { SettingsCard },
|
||||
@@ -54,68 +21,12 @@ export default {
|
||||
loading: Boolean,
|
||||
},
|
||||
data() {
|
||||
const settings = {
|
||||
provider: getSetting("server.provider"),
|
||||
domain: getSetting("server.domain"),
|
||||
classNumber: getSetting("server.classNumber"),
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
localSettings: { ...settings },
|
||||
originalSettings: settings,
|
||||
isValid: true,
|
||||
dataProviders: [
|
||||
{ title: "服务器", value: "server" },
|
||||
{ title: "本地数据库", value: "indexedDB" },
|
||||
],
|
||||
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasChanges() {
|
||||
return (
|
||||
JSON.stringify(this.localSettings) !==
|
||||
JSON.stringify(this.originalSettings)
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async save() {
|
||||
try {
|
||||
// 先保存设置
|
||||
Object.entries(this.localSettings).forEach(([key, value]) => {
|
||||
const success = setSetting(`server.${key}`, value);
|
||||
if (!success) {
|
||||
throw new Error(`保存设置 ${key} 失败`);
|
||||
}
|
||||
});
|
||||
|
||||
// 如果切换到服务器模式,验证服务器连接
|
||||
if (this.localSettings.provider === 'server' && this.localSettings.domain) {
|
||||
const testUrl = `${this.localSettings.domain.replace(/\/$/, '')}/api/test`;
|
||||
try {
|
||||
const response = await fetch(testUrl);
|
||||
if (!response.ok) {
|
||||
throw new Error('服务器连接测试失败');
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error('无法连接到服务器,请检查域名设置');
|
||||
}
|
||||
}
|
||||
|
||||
this.originalSettings = { ...this.localSettings };
|
||||
this.$emit('saved');
|
||||
|
||||
// 延迟刷新页面,让用户看到保存成功的提示
|
||||
setTimeout(() => {
|
||||
//window.location.reload();
|
||||
}, 1000);
|
||||
} catch (error) {
|
||||
this.$message?.error('保存失败', error.message);
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
this.localSettings = { ...this.originalSettings };
|
||||
},
|
||||
},
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user