feat(引导功能): 添加可配置的引导功能开关

在设置中添加引导功能开关配置项,允许用户控制登录后是否显示引导
更新相关类型定义、存储设置和界面配置
优化部分表单样式和代码结构
This commit is contained in:
zhangtao
2025-10-10 23:26:27 +08:00
parent cbbcdfde4b
commit 105e9e7c1f
14 changed files with 1362 additions and 24 deletions
-3
View File
@@ -3,13 +3,10 @@ VITE_APP_ENV=development
# 项目名称
VITE_APP_TITLE=fastapiadmin
# 网络请求公用地址
VITE_API_BASE_URL=http://127.0.0.1:8001
# VITE_API_BASE_URL=https://service.fastapiadmin.com
# 代理前缀
VITE_APP_BASE_API=/api/v1
+2
View File
@@ -21,6 +21,7 @@ export const SHOW_FULLSCREEN_KEY = "showFullscreen";
export const SHOW_SIZE_SELECT_KEY = "showSizeSelect";
export const SHOW_LANG_SELECT_KEY = "showLangSelect";
export const SHOW_NOTIFICATION_KEY = "showNotification";
export const SHOW_GUIDE_KEY = "showGuide"; // 引导功能开关
export const LAYOUT_KEY = "layout";
export const SIDEBAR_COLOR_SCHEME_KEY = "sidebarColorScheme";
export const THEME_KEY = "theme";
@@ -53,6 +54,7 @@ export const SETTINGS_KEYS = {
SHOW_SIZE_SELECT: SHOW_SIZE_SELECT_KEY,
SHOW_LANG_SELECT: SHOW_LANG_SELECT_KEY,
SHOW_NOTIFICATION: SHOW_NOTIFICATION_KEY,
SHOW_GUIDE: SHOW_GUIDE_KEY,
SIDEBAR_COLOR_SCHEME: SIDEBAR_COLOR_SCHEME_KEY,
LAYOUT: LAYOUT_KEY,
THEME_COLOR: THEME_COLOR_KEY,
+1
View File
@@ -203,6 +203,7 @@ export default {
"Generate current settings code and copy to clipboard, then overwrite src/settings.ts file",
resetConfigDescription: "Restore all settings to system default values",
systemTheme: "System Theme",
showGuide: "Show Guide",
},
error: {
noPermission: `Sorry, you don't have permission to access this page.`,
+1
View File
@@ -205,6 +205,7 @@ export default {
copyConfigDescription: "生成当前设置的代码并复制到剪贴板,然后覆盖 src/settings.ts 文件",
resetConfigDescription: "恢复所有设置为系统默认值",
systemTheme: "系统主题",
showGuide: "启动引导",
},
error: {
noPermission: `抱歉,您无权访问此页面。`,
@@ -80,7 +80,7 @@
<div class="color-options">
<!-- 预设颜色选项 -->
<div
v-for="(color, index) in displayColorPresets"
v-for="(color) in displayColorPresets"
:key="color"
:class="[
'color-option',
@@ -172,6 +172,11 @@
<el-switch v-model="settingsStore.showNotification" />
</div>
<!-- 修改此部分为引导开关关闭以后登录以后不再启动引导 -->
<div class="flex-x-between">
<span class="text-xs">{{ t("settings.showGuide") }}</span>
<el-switch v-model="settingsStore.showGuide" />
</div>
</section>
</div>
@@ -216,7 +221,7 @@
</template>
<script setup lang="ts">
import { DocumentCopy, RefreshLeft, Check, Plus } from "@element-plus/icons-vue";
import { DocumentCopy, RefreshLeft, Check } from "@element-plus/icons-vue";
const { t } = useI18n();
import { LayoutMode, SidebarColor, ThemeMode } from "@/enums";
@@ -250,18 +255,12 @@ const layoutOptions: LayoutOption[] = [
];
// 使用统一的颜色预设配置
const colorPresets = themeColorPresets;
const settingsStore = useSettingsStore();
// 主题颜色选择器相关
const displayColorPresets = computed(() => themeColorPresets.slice(0, 7)); // 只显示前9个预设颜色
const allColorPresets = themeColorPresets; // 所有颜色预设,用于自定义颜色选择器
// 判断当前颜色是否为自定义颜色(不在前7个预设中)
const isCustomColor = computed(() => {
return !displayColorPresets.value.includes(selectedThemeColor.value);
});
const isDark = ref<boolean>(settingsStore.theme === ThemeMode.DARK);
const sidebarColor = ref(settingsStore.sidebarColorScheme);
+2
View File
@@ -42,6 +42,8 @@ export const defaultSettings: AppSettings = {
sidebarColorScheme: SidebarColor.CLASSIC_BLUE,
// 项目引导
guideVisible: false,
/** 是否启动引导 */
showGuide: true,
};
// 主题色预设 - 现代化配色方案
@@ -12,6 +12,7 @@ interface SettingsState {
showAppLogo: boolean;
showWatermark: boolean;
showSettings: boolean;
showGuide: boolean; // 引导功能开关
// 桌面端工具显示设置
showMenuSearch: boolean;
@@ -42,6 +43,7 @@ export const useSettingsStore = defineStore("setting", () => {
const showAppLogo = useStorage<boolean>(SETTINGS_KEYS.SHOW_APP_LOGO, defaultSettings.showAppLogo);
const showWatermark = useStorage<boolean>(SETTINGS_KEYS.SHOW_WATERMARK, defaultSettings.showWatermark);
const showSettings = useStorage<boolean>(SETTINGS_KEYS.SHOW_SETTINGS, defaultSettings.showSettings);
const showGuide = useStorage<boolean>(SETTINGS_KEYS.SHOW_GUIDE, defaultSettings.showGuide); // 引导功能开关
// 🎯 桌面端工具设置 - 持久化
const showMenuSearch = useStorage<boolean>(SETTINGS_KEYS.SHOW_MENU_SEARCH, defaultSettings.showMenuSearch);
@@ -62,6 +64,7 @@ export const useSettingsStore = defineStore("setting", () => {
showAppLogo,
showWatermark,
showSettings,
showGuide,
showMenuSearch,
showFullscreen,
showSizeSelect,
@@ -136,6 +139,7 @@ export const useSettingsStore = defineStore("setting", () => {
showAppLogo.value = defaultSettings.showAppLogo;
showWatermark.value = defaultSettings.showWatermark;
showSettings.value = defaultSettings.showSettings;
showGuide.value = defaultSettings.showGuide;
// 桌面端工具设置
showMenuSearch.value = defaultSettings.showMenuSearch;
@@ -160,6 +164,7 @@ export const useSettingsStore = defineStore("setting", () => {
showAppLogo,
showWatermark,
showSettings,
showGuide,
// 🎯 桌面端工具状态
showMenuSearch,
+2
View File
@@ -96,6 +96,8 @@ declare global {
sidebarColorScheme: "classic-blue" | "minimal-white";
/** 项目引导 */
guideVisible: boolean;
/** 是否启动引导 */
showGuide: boolean;
}
/**
+2 -1
View File
@@ -940,4 +940,5 @@ onMounted(async () => {
});
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
</style>
File diff suppressed because it is too large Load Diff
@@ -31,7 +31,7 @@
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-form-item class="search-buttons">
<el-button v-hasPerm="['generator:gencode:query']" type="primary" icon="search" @click="handleQuery">查询</el-button>
<el-button v-hasPerm="['generator:gencode:query']" icon="refresh" @click="handleRefresh">重置</el-button>
</el-form-item>
@@ -131,7 +131,7 @@
</template>
</el-table-column>
<el-table-column label="修改时间" prop="modified_time" min-width="180" sortable />
<el-table-column fixed="right" label="操作" align="center" min-width="200">
<el-table-column fixed="right" label="操作" align="center" min-width="200" class="search-buttons">
<template #default="{ row }">
<el-button
v-if="!row.is_dir"
@@ -105,12 +105,13 @@ import { LocationQuery, RouteLocationRaw, useRoute, useRouter } from "vue-router
import { useI18n } from "vue-i18n";
import { onActivated, onMounted, watch } from "vue";
import AuthAPI, {type LoginFormData, type CaptchaInfo } from "@/api/system/auth";
import { useAppStore, useUserStore } from "@/store";
import { useAppStore, useUserStore, useSettingsStore } from "@/store";
import CommonWrapper from "@/components/CommonWrapper/index.vue";
const { t } = useI18n();
const userStore = useUserStore();
const appStore = useAppStore();
const settingsStore = useSettingsStore();
const route = useRoute();
const router = useRouter();
@@ -225,7 +226,9 @@ async function handleLoginSubmit() {
// - 未选中"记住我": token存储在sessionStorage中,浏览器关闭后失效
// 登录成功后自动开启项目引导
if (settingsStore.showGuide) {
appStore.showGuide(true);
}
} catch (error: any) {
if (error) {
+7 -7
View File
@@ -212,11 +212,14 @@
</template>
<!-- 新增编辑表单 -->
<template v-else>
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-suffix=":" label-width="auto" label-position="right">
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-suffix=":" label-width="auto" label-position="right" :inline="true">
<el-form-item label="标题" prop="notice_title">
<el-input v-model="formData.notice_title" placeholder="请输入标题" :maxlength="50" />
</el-form-item>
<el-form-item label="类型" prop="notice_type">
<el-form-item label="描述" prop="description" >
<el-input v-model="formData.description" :rows="1" :maxlength="100" show-word-limit type="textarea" placeholder="请输入描述" />
</el-form-item>
<el-form-item label="类型" prop="notice_type" class="w-50">
<el-select v-model="formData.notice_type" placeholder="请选择类型" clearable>
<el-option
v-for="item in dictStore.getDictArray('sys_notice_type')"
@@ -238,11 +241,8 @@
</el-radio-group>
</el-form-item>
<el-form-item label="内容" prop="notice_content">
<!-- <WangEditor v-model="formData.notice_content" height="300px" /> -->
<el-input v-model="formData.notice_content" :rows="4" :maxlength="100" show-word-limit type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="描述" prop="description">
<el-input v-model="formData.description" :rows="4" :maxlength="100" show-word-limit type="textarea" placeholder="请输入描述" />
<WangEditor v-model="formData.notice_content" height="300px" />
<!-- <el-input v-model="formData.notice_content" :rows="4" :maxlength="100" show-word-limit type="textarea" placeholder="请输入内容" /> -->
</el-form-item>
</el-form>
</template>