feat. 终端主题设置.
This commit is contained in:
@@ -151,7 +151,6 @@
|
|||||||
// 清空
|
// 清空
|
||||||
const handlerClear = () => {
|
const handlerClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -155,7 +155,6 @@
|
|||||||
// 清空
|
// 清空
|
||||||
const handlerClear = () => {
|
const handlerClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ export interface PreferenceUpdateRequest {
|
|||||||
/**
|
/**
|
||||||
* 用户偏好查询响应
|
* 用户偏好查询响应
|
||||||
*/
|
*/
|
||||||
export interface PreferenceQueryResponse {
|
export interface PreferenceQueryResponse<T> {
|
||||||
config: object;
|
config: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,7 +34,7 @@ export function updatePreferencePartial(request: PreferenceUpdateRequest) {
|
|||||||
/**
|
/**
|
||||||
* 查询用户偏好
|
* 查询用户偏好
|
||||||
*/
|
*/
|
||||||
export function getPreference(type: Preference) {
|
export function getPreference<T>(type: Preference) {
|
||||||
return axios.get<PreferenceQueryResponse>('/infra/preference/get', { params: { type } });
|
return axios.get<PreferenceQueryResponse<T>>('/infra/preference/get', { params: { type } });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -125,7 +125,6 @@
|
|||||||
// 清空
|
// 清空
|
||||||
const handlerClear = () => {
|
const handlerClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -86,8 +86,6 @@
|
|||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
// 加载主机秘钥
|
|
||||||
hostKeys.value = await cacheStore.loadHostKeys();
|
|
||||||
// 加载主机身份
|
// 加载主机身份
|
||||||
hostIdentities.value = await cacheStore.loadHostIdentities();
|
hostIdentities.value = await cacheStore.loadHostIdentities();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -96,6 +94,12 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 初始化数据
|
||||||
|
onMounted(async () => {
|
||||||
|
// 加载主机秘钥
|
||||||
|
hostKeys.value = await cacheStore.loadHostKeys();
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|||||||
@@ -176,7 +176,6 @@
|
|||||||
// 清空
|
// 清空
|
||||||
const handlerClear = () => {
|
const handlerClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -231,7 +231,6 @@
|
|||||||
// 清空
|
// 清空
|
||||||
const handlerClear = () => {
|
const handlerClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -28,4 +28,4 @@ export const AuthType = {
|
|||||||
export const authTypeKey = 'hostAuthTypeType';
|
export const authTypeKey = 'hostAuthTypeType';
|
||||||
|
|
||||||
// 加载的字典值
|
// 加载的字典值
|
||||||
export const dictKeys = ['hostAuthTypeType'];
|
export const dictKeys = [authTypeKey];
|
||||||
|
|||||||
@@ -183,7 +183,6 @@
|
|||||||
// 清空
|
// 清空
|
||||||
const handlerClear = () => {
|
const handlerClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
<template v-if="tab.type === TabType.SETTING">
|
<template v-if="tab.type === TabType.SETTING">
|
||||||
<!-- 主题设置 -->
|
<!-- 主题设置 -->
|
||||||
<terminal-theme-setting v-if="tab.key === InnerTabs.THEME_SETTING.key"
|
<terminal-theme-setting v-if="tab.key === InnerTabs.THEME_SETTING.key"
|
||||||
|
:preference="preference"
|
||||||
@emitter="dispatchEmitter" />
|
@emitter="dispatchEmitter" />
|
||||||
<span v-else>
|
<span v-else>
|
||||||
{{ tab.title }}
|
{{ tab.title }}
|
||||||
@@ -34,11 +35,11 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { PropType } from 'vue';
|
import type { PropType } from 'vue';
|
||||||
import type { TabItem } from '../../types/terminal.type';
|
import type { TabItem, TerminalPreference } from '../../types/terminal.type';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { TabType, InnerTabs } from '../../types/terminal.type';
|
import { TabType, InnerTabs } from '../../types/terminal.type';
|
||||||
import TerminalThemeSetting from '../terminal-theme-setting.vue';
|
|
||||||
import useEmitter from '@/hooks/emitter';
|
import useEmitter from '@/hooks/emitter';
|
||||||
|
import TerminalThemeSetting from '../terminal-theme-setting.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
@@ -48,7 +49,11 @@
|
|||||||
tabs: {
|
tabs: {
|
||||||
type: Array as PropType<Array<TabItem>>,
|
type: Array as PropType<Array<TabItem>>,
|
||||||
required: true
|
required: true
|
||||||
}
|
},
|
||||||
|
preference: {
|
||||||
|
type: Object as PropType<TerminalPreference>,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const emits = defineEmits(['changeDarkTheme']);
|
const emits = defineEmits(['changeDarkTheme']);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Terminal } from '@xterm/xterm';
|
import { Terminal } from '@xterm/xterm';
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, onUnmounted, ref } from 'vue';
|
||||||
import { TerminalTheme } from '../types/terminal.theme';
|
import { TerminalTheme } from '../types/terminal.theme';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -18,9 +18,10 @@
|
|||||||
}>();
|
}>();
|
||||||
|
|
||||||
const terminal = ref();
|
const terminal = ref();
|
||||||
|
const term = ref();
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const term = new Terminal({
|
term.value = new Terminal({
|
||||||
theme: props.theme,
|
theme: props.theme,
|
||||||
cols: 47,
|
cols: 47,
|
||||||
rows: 6,
|
rows: 6,
|
||||||
@@ -29,9 +30,9 @@
|
|||||||
cursorBlink: false,
|
cursorBlink: false,
|
||||||
cursorInactiveStyle: 'none'
|
cursorInactiveStyle: 'none'
|
||||||
});
|
});
|
||||||
term.open(terminal.value);
|
term.value.open(terminal.value);
|
||||||
|
|
||||||
term.write(
|
term.value.write(
|
||||||
'[94m[root[0m@[96mOrionServer usr]#[0m\n' +
|
'[94m[root[0m@[96mOrionServer usr]#[0m\n' +
|
||||||
'[92mdr-xr-xr-x.[0m 2 root root [96mbin[0m\n' +
|
'[92mdr-xr-xr-x.[0m 2 root root [96mbin[0m\n' +
|
||||||
'[92mdr-xr-xr-x.[0m 2 root root [96msbin[0m\n' +
|
'[92mdr-xr-xr-x.[0m 2 root root [96msbin[0m\n' +
|
||||||
@@ -41,6 +42,10 @@
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
term.value?.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|||||||
@@ -12,13 +12,11 @@
|
|||||||
<h3 class="terminal-setting-subtitle">
|
<h3 class="terminal-setting-subtitle">
|
||||||
主题选择
|
主题选择
|
||||||
</h3>
|
</h3>
|
||||||
<a-radio-group v-model="userDarkTheme"
|
<a-radio-group :default-value="preference.darkTheme"
|
||||||
size="mini"
|
size="mini"
|
||||||
type="button"
|
type="button"
|
||||||
@change="changeDarkTheme">
|
@change="changeDarkTheme"
|
||||||
<a-radio v-for="theme in DarkTheme" :key="theme.value" :value="theme.value">
|
:options="toOptions(darkThemeKey)">
|
||||||
{{ theme.label }}
|
|
||||||
</a-radio>
|
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
</div>
|
</div>
|
||||||
<!-- 内容区域 -->
|
<!-- 内容区域 -->
|
||||||
@@ -30,7 +28,7 @@
|
|||||||
:key="theme.name"
|
:key="theme.name"
|
||||||
class="terminal-theme-card simple-card"
|
class="terminal-theme-card simple-card"
|
||||||
:class="{
|
:class="{
|
||||||
'terminal-theme-card-check': theme.name === userTerminalTheme.name
|
'terminal-theme-card-check': theme.name === preference.terminalTheme.name
|
||||||
}"
|
}"
|
||||||
:title="theme.name"
|
:title="theme.name"
|
||||||
:style="{
|
:style="{
|
||||||
@@ -44,7 +42,7 @@
|
|||||||
<!-- 样例 -->
|
<!-- 样例 -->
|
||||||
<terminal-example :theme="theme" />
|
<terminal-example :theme="theme" />
|
||||||
<icon-check class="theme-check-icon" :style="{
|
<icon-check class="theme-check-icon" :style="{
|
||||||
display: theme.name === userTerminalTheme.name ? 'flex': 'none'
|
display: theme.name === preference.terminalTheme.name ? 'flex': 'none'
|
||||||
}" />
|
}" />
|
||||||
</a-card>
|
</a-card>
|
||||||
</div>
|
</div>
|
||||||
@@ -62,59 +60,60 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { TerminalTheme } from '../types/terminal.theme';
|
import type { TerminalTheme } from '../types/terminal.theme';
|
||||||
import { DarkTheme } from '../types/terminal.type';
|
import type { TerminalPreference } from '../types/terminal.type';
|
||||||
import ThemeSchema, { FRAPPE } from '../types/terminal.theme';
|
import { DarkTheme, darkThemeKey } from '../types/terminal.type';
|
||||||
|
import ThemeSchema from '../types/terminal.theme';
|
||||||
import useEmitter from '@/hooks/emitter';
|
import useEmitter from '@/hooks/emitter';
|
||||||
import { onBeforeMount, ref } from 'vue';
|
|
||||||
import TerminalExample from './terminal-example.vue';
|
|
||||||
import { useDebounceFn } from '@vueuse/core';
|
import { useDebounceFn } from '@vueuse/core';
|
||||||
|
import { useDictStore } from '@/store';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
import TerminalExample from './terminal-example.vue';
|
||||||
|
import { updatePreferencePartial } from '@/api/user/preference';
|
||||||
|
|
||||||
defineProps();
|
const props = defineProps<{
|
||||||
|
preference: TerminalPreference
|
||||||
|
}>();
|
||||||
|
|
||||||
const emits = defineEmits(['emitter']);
|
const emits = defineEmits(['emitter']);
|
||||||
|
|
||||||
const { bubblesEmitter } = useEmitter(emits);
|
const { bubblesEmitter } = useEmitter(emits);
|
||||||
|
const { toOptions } = useDictStore();
|
||||||
interface TerminalPreference {
|
|
||||||
darkTheme: string,
|
|
||||||
terminalTheme: TerminalTheme
|
|
||||||
}
|
|
||||||
|
|
||||||
const userDarkTheme = ref(DarkTheme.DARK.value);
|
|
||||||
const userTerminalTheme = ref<TerminalTheme>(FRAPPE);
|
|
||||||
|
|
||||||
// 修改暗色主题
|
// 修改暗色主题
|
||||||
const changeDarkTheme = (value: string) => {
|
const changeDarkTheme = (value: string) => {
|
||||||
if (value === DarkTheme.DARK.value) {
|
props.preference.darkTheme = value;
|
||||||
|
if (value === DarkTheme.DARK) {
|
||||||
// 暗色
|
// 暗色
|
||||||
bubblesEmitter('changeDarkTheme', true);
|
bubblesEmitter('changeDarkTheme', true);
|
||||||
} else if (value === DarkTheme.LIGHT.value) {
|
} else if (value === DarkTheme.LIGHT) {
|
||||||
// 亮色
|
// 亮色
|
||||||
bubblesEmitter('changeDarkTheme', false);
|
bubblesEmitter('changeDarkTheme', false);
|
||||||
} else if (value === DarkTheme.AUTO.value) {
|
} else if (value === DarkTheme.AUTO) {
|
||||||
// 自动配色
|
// 自动配色
|
||||||
bubblesEmitter('changeDarkTheme', userTerminalTheme.value.dark ? DarkTheme.DARK.value : DarkTheme.LIGHT.value);
|
bubblesEmitter('changeDarkTheme', props.preference.terminalTheme.dark);
|
||||||
}
|
}
|
||||||
|
// 同步用户偏好
|
||||||
sync();
|
sync();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 选择终端主题
|
// 选择终端主题
|
||||||
const checkTheme = (theme: TerminalTheme) => {
|
const checkTheme = (theme: TerminalTheme) => {
|
||||||
userTerminalTheme.value = theme;
|
props.preference.terminalTheme = theme;
|
||||||
// 切换主题配色
|
// 切换主题配色
|
||||||
if (userDarkTheme.value === DarkTheme.AUTO.value) {
|
if (props.preference.darkTheme === DarkTheme.AUTO) {
|
||||||
changeDarkTheme(theme.dark ? DarkTheme.DARK.value : DarkTheme.LIGHT.value);
|
bubblesEmitter('changeDarkTheme', theme.dark);
|
||||||
} else {
|
|
||||||
sync();
|
|
||||||
}
|
}
|
||||||
|
// 同步用户偏好
|
||||||
|
sync();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 同步用户偏好
|
// 同步用户偏好
|
||||||
const syncUserPreference = async () => {
|
const syncUserPreference = async () => {
|
||||||
try {
|
try {
|
||||||
// FIXME 同步用户配置
|
await updatePreferencePartial({
|
||||||
|
type: 'TERMINAL',
|
||||||
|
config: props.preference
|
||||||
|
});
|
||||||
Message.success('同步成功');
|
Message.success('同步成功');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Message.error('同步失败');
|
Message.error('同步失败');
|
||||||
@@ -123,10 +122,6 @@
|
|||||||
// 同步用户偏好防抖
|
// 同步用户偏好防抖
|
||||||
const sync = useDebounceFn(syncUserPreference, 1500);
|
const sync = useDebounceFn(syncUserPreference, 1500);
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
// FIXME 加载用户配置
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="host-layout">
|
<div class="host-layout" v-if="render">
|
||||||
<!-- 头部区域 -->
|
<!-- 头部区域 -->
|
||||||
<header class="host-layout-header">
|
<header class="host-layout-header">
|
||||||
<terminal-header v-model="activeKey"
|
<terminal-header v-model="activeKey"
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
<div class="host-layout-content">
|
<div class="host-layout-content">
|
||||||
<terminal-content v-model="activeKey"
|
<terminal-content v-model="activeKey"
|
||||||
:tabs="tabs"
|
:tabs="tabs"
|
||||||
|
:preference="preference as TerminalPreference"
|
||||||
@change-dark-theme="changeLayoutTheme" />
|
@change-dark-theme="changeLayoutTheme" />
|
||||||
</div>
|
</div>
|
||||||
<!-- 右侧操作栏 -->
|
<!-- 右侧操作栏 -->
|
||||||
@@ -34,30 +35,36 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { TabItem } from './types/terminal.type';
|
import type { TabItem, TerminalPreference } from './types/terminal.type';
|
||||||
import { ref } from 'vue';
|
import { ref, onBeforeMount } from 'vue';
|
||||||
import { useDark } from '@vueuse/core';
|
import { useDark } from '@vueuse/core';
|
||||||
import { TabType, InnerTabs, DarkTheme } from './types/terminal.type';
|
import { TabType, InnerTabs, DarkTheme, dictKeys } from './types/terminal.type';
|
||||||
|
import { DEFAULT_SCHEMA } from './types/terminal.theme';
|
||||||
|
import { useDictStore } from '@/store';
|
||||||
|
import { getPreference } from '@/api/user/preference';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
import TerminalHeader from './components/layout/terminal-header.vue';
|
import TerminalHeader from './components/layout/terminal-header.vue';
|
||||||
import TerminalLeftSidebar from './components/layout/terminal-left-sidebar.vue';
|
import TerminalLeftSidebar from './components/layout/terminal-left-sidebar.vue';
|
||||||
import TerminalRightSidebar from './components/layout/terminal-right-sidebar.vue';
|
import TerminalRightSidebar from './components/layout/terminal-right-sidebar.vue';
|
||||||
import TerminalContent from './components/layout/terminal-content.vue';
|
import TerminalContent from './components/layout/terminal-content.vue';
|
||||||
import './assets/styles/layout.less';
|
import './assets/styles/layout.less';
|
||||||
import '@xterm/xterm/css/xterm.css';
|
import '@xterm/xterm/css/xterm.css';
|
||||||
import { onBeforeMount } from 'vue/dist/vue';
|
|
||||||
|
|
||||||
// 系统主题
|
// 系统主题
|
||||||
const darkTheme = useDark({
|
const darkTheme = useDark({
|
||||||
selector: 'body',
|
selector: 'body',
|
||||||
attribute: 'terminal-theme',
|
attribute: 'terminal-theme',
|
||||||
valueDark: DarkTheme.DARK.value,
|
valueDark: DarkTheme.DARK,
|
||||||
valueLight: DarkTheme.LIGHT.value,
|
valueLight: DarkTheme.LIGHT,
|
||||||
initialValue: DarkTheme.DARK.value as any,
|
initialValue: DarkTheme.DARK as any,
|
||||||
storageKey: null
|
storageKey: null
|
||||||
});
|
});
|
||||||
|
const dictStore = useDictStore();
|
||||||
|
|
||||||
|
const render = ref(false);
|
||||||
const activeKey = ref(InnerTabs.THEME_SETTING.key);
|
const activeKey = ref(InnerTabs.THEME_SETTING.key);
|
||||||
const tabs = ref<Array<TabItem>>([InnerTabs.THEME_SETTING]);
|
const tabs = ref<Array<TabItem>>([InnerTabs.THEME_SETTING]);
|
||||||
|
const preference = ref<TerminalPreference>();
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
tabs.value.push({
|
tabs.value.push({
|
||||||
key: `host${i}`,
|
key: `host${i}`,
|
||||||
@@ -70,7 +77,6 @@
|
|||||||
const changeLayoutTheme = (dark: boolean) => {
|
const changeLayoutTheme = (dark: boolean) => {
|
||||||
darkTheme.value = dark;
|
darkTheme.value = dark;
|
||||||
};
|
};
|
||||||
changeLayoutTheme(false);
|
|
||||||
|
|
||||||
// 点击 tab
|
// 点击 tab
|
||||||
const clickTab = (key: string) => {
|
const clickTab = (key: string) => {
|
||||||
@@ -96,8 +102,31 @@
|
|||||||
activeKey.value = tab.key;
|
activeKey.value = tab.key;
|
||||||
};
|
};
|
||||||
|
|
||||||
onBeforeMount(() => {
|
// 加载用户终端偏好
|
||||||
// FIXME 加载用户配置
|
onBeforeMount(async () => {
|
||||||
|
try {
|
||||||
|
const { data } = await getPreference<TerminalPreference>('TERMINAL');
|
||||||
|
// 设置默认终端主题
|
||||||
|
if (!data.config.terminalTheme?.name) {
|
||||||
|
data.config.terminalTheme = DEFAULT_SCHEMA;
|
||||||
|
}
|
||||||
|
preference.value = data.config;
|
||||||
|
// 设置暗色主题
|
||||||
|
const userDarkTheme = data.config.darkTheme;
|
||||||
|
if (userDarkTheme === DarkTheme.AUTO) {
|
||||||
|
changeLayoutTheme(data.config.terminalTheme?.dark === true);
|
||||||
|
} else {
|
||||||
|
changeLayoutTheme(userDarkTheme === DarkTheme.DARK);
|
||||||
|
}
|
||||||
|
render.value = true;
|
||||||
|
} catch (e) {
|
||||||
|
Message.error('配置加载失败');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 加载字典值
|
||||||
|
onBeforeMount(async () => {
|
||||||
|
await dictStore.loadKeys([...dictKeys]);
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export interface TerminalTheme {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 默认配色
|
// 默认配色
|
||||||
export const FRAPPE = {
|
export const DEFAULT_SCHEMA = {
|
||||||
name: 'frappe',
|
name: 'frappe',
|
||||||
dark: true,
|
dark: true,
|
||||||
background: '#303446',
|
background: '#303446',
|
||||||
@@ -59,7 +59,7 @@ export const FRAPPE = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
FRAPPE,
|
DEFAULT_SCHEMA,
|
||||||
{
|
{
|
||||||
name: 'latte',
|
name: 'latte',
|
||||||
dark: false,
|
dark: false,
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
import type { CSSProperties } from 'vue';
|
import type { CSSProperties } from 'vue';
|
||||||
|
import type { TerminalTheme } from './terminal.theme';
|
||||||
|
|
||||||
// 暗色主题
|
// 暗色主题
|
||||||
export const DarkTheme = {
|
export const DarkTheme = {
|
||||||
DARK: {
|
DARK: 'dark',
|
||||||
value: 'dark',
|
LIGHT: 'light',
|
||||||
label: '暗色'
|
AUTO: 'auto'
|
||||||
},
|
|
||||||
LIGHT: {
|
|
||||||
value: 'light',
|
|
||||||
label: '亮色'
|
|
||||||
},
|
|
||||||
AUTO: {
|
|
||||||
value: 'auto',
|
|
||||||
label: '自动'
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 用户终端偏好
|
||||||
|
export interface TerminalPreference {
|
||||||
|
darkTheme: string,
|
||||||
|
terminalTheme: TerminalTheme
|
||||||
|
}
|
||||||
|
|
||||||
// sidebar 操作类型
|
// sidebar 操作类型
|
||||||
export interface SidebarAction {
|
export interface SidebarAction {
|
||||||
icon: string;
|
icon: string;
|
||||||
@@ -63,3 +61,9 @@ export interface TabItem {
|
|||||||
|
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 终端暗色模式 字典项
|
||||||
|
export const darkThemeKey = 'terminalDarkTheme';
|
||||||
|
|
||||||
|
// 加载的字典值
|
||||||
|
export const dictKeys = [darkThemeKey];
|
||||||
|
|||||||
@@ -245,7 +245,6 @@
|
|||||||
// 清空
|
// 清空
|
||||||
const handlerClear = () => {
|
const handlerClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -144,7 +144,7 @@
|
|||||||
import { usePagination } from '@/types/table';
|
import { usePagination } from '@/types/table';
|
||||||
import { dictValueTypeKey } from '../types/const';
|
import { dictValueTypeKey } from '../types/const';
|
||||||
import useCopy from '@/hooks/copy';
|
import useCopy from '@/hooks/copy';
|
||||||
import { useDictStore } from '@/store';
|
import { useCacheStore, useDictStore } from '@/store';
|
||||||
import { getDictValueList } from '@/api/system/dict-value';
|
import { getDictValueList } from '@/api/system/dict-value';
|
||||||
|
|
||||||
const tableRenderData = ref<DictKeyQueryResponse[]>([]);
|
const tableRenderData = ref<DictKeyQueryResponse[]>([]);
|
||||||
@@ -154,6 +154,7 @@
|
|||||||
const { copy } = useCopy();
|
const { copy } = useCopy();
|
||||||
const { loading, setLoading } = useLoading();
|
const { loading, setLoading } = useLoading();
|
||||||
const { toOptions, getDictValue } = useDictStore();
|
const { toOptions, getDictValue } = useDictStore();
|
||||||
|
const cacheStore = useCacheStore();
|
||||||
|
|
||||||
const formModel = reactive<DictKeyQueryRequest>({
|
const formModel = reactive<DictKeyQueryRequest>({
|
||||||
id: undefined,
|
id: undefined,
|
||||||
@@ -170,6 +171,7 @@
|
|||||||
// 调用删除接口
|
// 调用删除接口
|
||||||
await deleteDictKey(id);
|
await deleteDictKey(id);
|
||||||
Message.success('删除成功');
|
Message.success('删除成功');
|
||||||
|
cacheStore.reset('dictKeys');
|
||||||
// 重新加载数据
|
// 重新加载数据
|
||||||
fetchTableData();
|
fetchTableData();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -181,11 +183,13 @@
|
|||||||
// 添加后回调
|
// 添加后回调
|
||||||
const addedCallback = () => {
|
const addedCallback = () => {
|
||||||
fetchTableData();
|
fetchTableData();
|
||||||
|
cacheStore.reset('dictKeys');
|
||||||
};
|
};
|
||||||
|
|
||||||
// 更新后回调
|
// 更新后回调
|
||||||
const updatedCallback = () => {
|
const updatedCallback = () => {
|
||||||
fetchTableData();
|
fetchTableData();
|
||||||
|
cacheStore.reset('dictKeys');
|
||||||
};
|
};
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
|
|||||||
@@ -21,7 +21,9 @@
|
|||||||
:wrapper-col-props="{ span: 18 }"
|
:wrapper-col-props="{ span: 18 }"
|
||||||
:rules="formRules">
|
:rules="formRules">
|
||||||
<!-- 配置项 -->
|
<!-- 配置项 -->
|
||||||
<a-form-item field="keyId" label="配置项">
|
<a-form-item v-if="visible"
|
||||||
|
field="keyId"
|
||||||
|
label="配置项">
|
||||||
<dict-key-selector v-model="formModel.keyId" @change="changeKey" />
|
<dict-key-selector v-model="formModel.keyId" @change="changeKey" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 配置值 -->
|
<!-- 配置值 -->
|
||||||
@@ -123,18 +125,18 @@
|
|||||||
const emits = defineEmits(['added', 'updated']);
|
const emits = defineEmits(['added', 'updated']);
|
||||||
|
|
||||||
// 打开新增
|
// 打开新增
|
||||||
const openAdd = () => {
|
const openAdd = async () => {
|
||||||
title.value = '添加字典配置值';
|
title.value = '添加字典配置值';
|
||||||
isAddHandle.value = true;
|
isAddHandle.value = true;
|
||||||
renderForm({ ...defaultForm(), keyId: formModel.value.keyId, sort: (formModel.value.sort || 0) + sortStep });
|
await renderForm({ ...defaultForm(), keyId: formModel.value.keyId, sort: (formModel.value.sort || 0) + sortStep });
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 打开修改
|
// 打开修改
|
||||||
const openUpdate = (record: any) => {
|
const openUpdate = async (record: any) => {
|
||||||
title.value = '修改字典配置值';
|
title.value = '修改字典配置值';
|
||||||
isAddHandle.value = false;
|
isAddHandle.value = false;
|
||||||
renderForm({ ...defaultForm(), ...record });
|
await renderForm({ ...defaultForm(), ...record });
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -217,7 +219,6 @@
|
|||||||
// 清空
|
// 清空
|
||||||
const handlerClear = () => {
|
const handlerClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -255,7 +255,6 @@
|
|||||||
// 清空
|
// 清空
|
||||||
const handlerClear = () => {
|
const handlerClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
|
||||||
// 触发 watch 防止第二次加载变成根目录
|
// 触发 watch 防止第二次加载变成根目录
|
||||||
renderForm(defaultForm());
|
renderForm(defaultForm());
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -127,7 +127,6 @@
|
|||||||
// 清空
|
// 清空
|
||||||
const handlerClear = () => {
|
const handlerClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -115,7 +115,6 @@
|
|||||||
// 清空
|
// 清空
|
||||||
const handlerClear = () => {
|
const handlerClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -145,7 +145,6 @@
|
|||||||
// 清空
|
// 清空
|
||||||
const handlerClear = () => {
|
const handlerClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -112,7 +112,6 @@
|
|||||||
// 清空
|
// 清空
|
||||||
const handlerClear = () => {
|
const handlerClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -107,7 +107,6 @@
|
|||||||
// 清空
|
// 清空
|
||||||
const handlerClear = () => {
|
const handlerClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user