长城汽车软件包管理平台
whychdw
2025-05-06 4a867727d81b9513e675ad396903368c6a293dca
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<template>
  <el-drawer v-model="drawerVisible" size="300" title="项目配置" :before-close="handleCloseDrawer">
    <!-- 主题设置 -->
    <section class="config-section">
      <el-divider>主题</el-divider>
 
      <div class="flex-center config-item">
        <el-switch
          v-model="isDarkTheme"
          active-icon="Moon"
          inactive-icon="Sunny"
          @change="handleThemeChange"
        />
      </div>
    </section>
 
    <!-- 界面设置 -->
    <section class="config-section">
      <el-divider>界面设置</el-divider>
 
      <div class="config-item flex-x-between">
        <span class="text-xs">主题颜色</span>
 
        <el-color-picker
          v-model="selectedThemeColor"
          :predefine="colorPresets"
          popper-class="theme-picker-dropdown"
        />
      </div>
 
      <div class="config-item flex-x-between">
        <span class="text-xs">开启 Tags-View</span>
        <el-switch v-model="settingsStore.tagsView" />
      </div>
 
      <div class="config-item flex-x-between">
        <span class="text-xs">侧边栏 LOGO</span>
        <el-switch v-model="settingsStore.sidebarLogo" />
      </div>
    </section>
 
    <!-- 布局设置 -->
    <section class="config-section">
      <el-divider>导航栏设置</el-divider>
      <LayoutSelect v-model="settingsStore.layout" @update:model-value="handleLayoutChange" />
    </section>
  </el-drawer>
</template>
 
<script setup lang="ts">
import { LayoutMode } from "@/enums/settings/layout.enum";
import { ThemeMode } from "@/enums/settings/theme.enum";
import { useSettingsStore, usePermissionStore, useAppStore } from "@/store";
 
// 颜色预设
const colorPresets = [
  "#4080FF",
  "#ff4500",
  "#ff8c00",
  "#90ee90",
  "#00ced1",
  "#1e90ff",
  "#c71585",
  "rgb(255, 120, 0)",
  "hsva(120, 40, 94)",
];
 
const route = useRoute();
const appStore = useAppStore();
const settingsStore = useSettingsStore();
const permissionStore = usePermissionStore();
 
const isDarkTheme = ref<boolean>(settingsStore.theme === ThemeMode.DARK);
 
const selectedThemeColor = computed({
  get: () => settingsStore.themeColor,
  set: (value) => settingsStore.changeThemeColor(value),
});
 
const drawerVisible = computed({
  get: () => settingsStore.settingsVisible,
  set: (value) => (settingsStore.settingsVisible = value),
});
 
/**
 * 处理主题切换
 *
 * @param isDark 是否启用暗黑模式
 */
const handleThemeChange = (isDark: string | number | boolean) => {
  settingsStore.changeTheme(isDark ? ThemeMode.DARK : ThemeMode.LIGHT);
};
 
/**
 * 处理布局切换
 * @param layout - 新布局模式
 */
const handleLayoutChange = (layout: LayoutMode) => {
  settingsStore.changeLayout(layout);
  if (layout === LayoutMode.MIX && route.name) {
    const topLevelRoute = findTopLevelRoute(permissionStore.routes, route.name as string);
    if (appStore.activeTopMenuPath !== topLevelRoute.path) {
      appStore.activeTopMenu(topLevelRoute.path);
    }
  }
};
 
/**
 * 查找路由的顶层父路由
 *
 * @param tree 树形数据
 * @param findName 查找的名称
 */
function findTopLevelRoute(tree: any[], findName: string) {
  let parentMap: any = {};
 
  function buildParentMap(node: any, parent: any) {
    parentMap[node.name] = parent;
 
    if (node.children) {
      for (let i = 0; i < node.children.length; i++) {
        buildParentMap(node.children[i], node);
      }
    }
  }
 
  for (let i = 0; i < tree.length; i++) {
    buildParentMap(tree[i], null);
  }
 
  let currentNode = parentMap[findName];
  while (currentNode) {
    if (!parentMap[currentNode.name]) {
      return currentNode;
    }
    currentNode = parentMap[currentNode.name];
  }
  return null;
}
 
/**
 * 关闭抽屉前的回调
 */
const handleCloseDrawer = () => {
  settingsStore.settingsVisible = false;
};
</script>
 
<style lang="scss" scoped>
.config-section {
  margin-bottom: 24px;
 
  .config-item {
    padding: 12px 0;
    border-bottom: 1px solid var(--el-border-color-light);
 
    &:last-child {
      border-bottom: none;
    }
  }
}
</style>