diff --git a/packages/plugins/theme-editor/src/client/components/ThemeCard.tsx b/packages/plugins/theme-editor/src/client/components/ThemeCard.tsx
index ade153ea9..ba0eaad63 100644
--- a/packages/plugins/theme-editor/src/client/components/ThemeCard.tsx
+++ b/packages/plugins/theme-editor/src/client/components/ThemeCard.tsx
@@ -71,8 +71,15 @@ const ThemeCard = (props: Props) => {
const [loading, setLoading] = React.useState(false);
const currentThemeId = useCurrentThemeId();
const { t } = useTranslation();
+ const { token } = useToken();
+
+ const isDefault = item.id === systemSettings?.data?.data?.options?.themeId;
const handleDelete = useCallback(() => {
+ if (isDefault) {
+ return;
+ }
+
modal.confirm({
title: t('Delete theme'),
content: t('Deletion is unrecoverable. Confirm deletion?'),
@@ -94,6 +101,7 @@ const ThemeCard = (props: Props) => {
}, [
api,
currentUser?.data?.data?.systemSettings?.themeId,
+ isDefault,
item,
modal,
onChange,
@@ -197,6 +205,7 @@ const ThemeCard = (props: Props) => {
>
{t('User selectable')}
{
>
{t('Default theme')}
{
},
],
};
- }, [
- handleSwitchDefault,
- handleSwitchOptional,
- item.id,
- item.optional,
- loading,
- systemSettings?.data?.data?.options?.themeId,
- t,
- ]);
+ }, [handleSwitchDefault, handleSwitchOptional, isDefault, item.optional, loading, t]);
const actions = useMemo(() => {
return [
,
- ,
+ ,
,
];
- }, [handleDelete, handleEdit, menu]);
+ }, [handleDelete, handleEdit, isDefault, menu, token.colorTextDisabled]);
const extra = useMemo(() => {
if (item.id !== systemSettings?.data?.data?.options?.themeId && !item.optional) {
@@ -294,7 +308,7 @@ const ThemeCard = (props: Props) => {
{
return data
@@ -34,7 +36,7 @@ function Label() {
value: item.id,
};
});
- }, [data]);
+ }, [data, t]);
useEffect(() => {
if (!data) {
@@ -42,6 +44,25 @@ function Label() {
}
}, []);
+ useEffect(() => {
+ const init = async () => {
+ // 当 themeId 为空时表示插件是第一次被启用
+ if (themeId == null && data) {
+ const firstTheme = data[0];
+
+ try {
+ // 避免并发请求,在本地存储中容易出问题
+ await updateSystemThemeSettings(firstTheme.id);
+ await updateUserThemeSettings(firstTheme.id);
+ } catch (err) {
+ error(err);
+ }
+ }
+ };
+
+ init();
+ }, [themeId, updateSystemThemeSettings, updateUserThemeSettings, data, api, refresh]);
+
if (err) {
error(err);
return null;
diff --git a/packages/plugins/theme-editor/src/client/locale/zh-CN.ts b/packages/plugins/theme-editor/src/client/locale/zh-CN.ts
index f6993d83e..51fb1f33e 100644
--- a/packages/plugins/theme-editor/src/client/locale/zh-CN.ts
+++ b/packages/plugins/theme-editor/src/client/locale/zh-CN.ts
@@ -16,6 +16,12 @@ const locale = {
'Edit based on current theme': '基于当前主题进行编辑',
'Create a brand new theme': '创建一个全新的主题',
+ // 内置主题的名字
+ 'Default theme of antd': 'antd 默认主题',
+ Dark: '暗黑',
+ Compact: '紧凑',
+ 'Compact dark': '紧凑暗黑',
+
// 主题编辑器
'Theme Editor': '主题编辑器',
Save: '保存',
diff --git a/packages/plugins/theme-editor/src/server/builtinThemes.ts b/packages/plugins/theme-editor/src/server/builtinThemes.ts
new file mode 100644
index 000000000..2deb6e79d
--- /dev/null
+++ b/packages/plugins/theme-editor/src/server/builtinThemes.ts
@@ -0,0 +1,41 @@
+import { ThemeItem } from '../types';
+
+/** antd 默认主题 */
+export const antd: Omit = {
+ config: {
+ name: 'Default theme of antd',
+ },
+ optional: true,
+ isBuiltIn: true,
+};
+
+export const dark: Omit = {
+ config: {
+ name: 'Dark',
+ // @ts-ignore
+ algorithm: 'darkAlgorithm',
+ },
+ optional: true,
+ isBuiltIn: true,
+};
+
+export const compact: Omit = {
+ config: {
+ name: 'Compact',
+ // @ts-ignore
+ algorithm: 'compactAlgorithm',
+ },
+ optional: true,
+ isBuiltIn: true,
+};
+
+/** 同时包含 `紧凑` 和 `暗黑` 两种模式 */
+export const compactDark: Omit = {
+ config: {
+ name: 'Compact dark',
+ // @ts-ignore
+ algorithm: ['compactAlgorithm', 'darkAlgorithm'],
+ },
+ optional: true,
+ isBuiltIn: true,
+};
diff --git a/packages/plugins/theme-editor/src/server/plugin.ts b/packages/plugins/theme-editor/src/server/plugin.ts
index 2ed0d2a19..d5945a3c9 100644
--- a/packages/plugins/theme-editor/src/server/plugin.ts
+++ b/packages/plugins/theme-editor/src/server/plugin.ts
@@ -1,12 +1,16 @@
+import { Collection } from '@nocobase/database';
import { InstallOptions, Plugin } from '@nocobase/server';
+import { antd, compact, compactDark, dark } from './builtinThemes';
export class ThemeEditorPlugin extends Plugin {
+ theme: Collection;
+
afterAdd() {}
beforeLoad() {}
async load() {
- this.db.collection({
+ this.theme = this.db.collection({
name: 'themeConfig',
fields: [
// 主题配置内容,一个 JSON 字符串
@@ -27,7 +31,13 @@ export class ThemeEditorPlugin extends Plugin {
});
}
- async install(options?: InstallOptions) {}
+ async install(options?: InstallOptions) {
+ if ((await this.theme.repository.count()) === 0) {
+ await this.theme.repository.create({
+ values: [antd, dark, compact, compactDark],
+ });
+ }
+ }
async afterEnable() {}