Skip to content

Commit

Permalink
feat: add global header and fotter script support. (#685)
Browse files Browse the repository at this point in the history
* feat: console支持加载全局头片断和尾部片断代码。

* feat: add SettingService for get setting vo.

* docs: update changelog md
  • Loading branch information
chivehao authored Oct 11, 2024
1 parent 0c96c29 commit a8afdba
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 42 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

# 0.15.11

## 新特性

- Console支持管理和加载全局header和footer配置

## 插件支持

- 添加`MetaOperate`以支持插件调用三方元数据插件条目查寻
Expand Down
11 changes: 11 additions & 0 deletions api/src/main/java/run/ikaros/api/core/setting/vo/BasicSetting.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package run.ikaros.api.core.setting.vo;

import lombok.Data;

@Data
public class BasicSetting {
private String siteTitle;
private String siteSubhead;
private String logo;
private String favicon;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package run.ikaros.api.core.setting.vo;

import lombok.Data;

@Data
public class GlobalSetting {
private String header;
private String footer;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package run.ikaros.api.core.setting.vo;


public enum MailProtocol {
SMTP
}
15 changes: 15 additions & 0 deletions api/src/main/java/run/ikaros/api/core/setting/vo/MailSetting.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package run.ikaros.api.core.setting.vo;

import lombok.Data;

@Data
public class MailSetting {
private Boolean enable;
private MailProtocol protocol;
private String smtpHost;
private String smtpPort;
private String smtpAccount;
private String smtpPassword;
private String smtpAccountAlias;
private String smtpReceiveAddress;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package run.ikaros.api.core.setting.vo;

import lombok.Data;

@Data
public class UserSetting {
private Boolean allowRegister;
private String defaultRole;
}
95 changes: 91 additions & 4 deletions console/src/layouts/BasicLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
import Aside from './Aside.vue';
import Header from './Header.vue';
import variables from '@/styles/variables.module.scss';
import { useLayoutStore } from '@/stores/layout';
import {useLayoutStore} from '@/stores/layout';
import GlobalSearchDialog from '@/components/global-search/GlobalSearchDialog.vue';
import { computed, onMounted, onUnmounted, ref } from 'vue';
import { ElContainer, ElAside, ElHeader, ElMain, ElCard } from 'element-plus';
import { RouterView } from 'vue-router';
import {computed, onMounted, onUnmounted, ref} from 'vue';
import {ElAside, ElCard, ElContainer, ElHeader, ElMain} from 'element-plus';
import {RouterView} from 'vue-router';
import {useSettingStore} from '@/stores/setting';
const layoutStore = useLayoutStore();
const settingStore = useSettingStore();
const asideWidth = computed(() => {
return layoutStore.asideIsExtend
Expand All @@ -28,8 +30,87 @@ const handleGlobalSearchKeybinding = (e: KeyboardEvent) => {
}
};
const headerDom = ref();
const footerDom = ref();
const loadGlobalHeader = ()=>{
if (settingStore.globalHeader) {
var headerDiv = document.createElement("div");
headerDiv.innerHTML = settingStore.globalHeader;
headerDom.value.appendChild(headerDiv);
// 获取所有的 <script> 标签
const scriptElements = headerDiv.querySelectorAll<HTMLScriptElement>('script');
// 提取并加载每个 script 的 src
scriptElements.forEach(script => {
const src = script.getAttribute('src');
// 如果存在 src 属性
if (src) {
// 创建一个新的 script 标签
const newScript = document.createElement('script');
newScript.src = src;
newScript.async = true; // 异步加载
// 动态设置属性
if (script instanceof HTMLScriptElement) {
const attributes = script.attributes;
for (let i = 0; i < attributes.length; i++) {
const attr = attributes[i];
console.debug(`Attribute Name: ${attr.name}, Attribute Value: ${attr.value}`);
newScript.setAttribute(attr.name, attr.value);
}
}
// 将新的 script 标签添加到 <head> 中,开始加载
document.head.appendChild(newScript);
}
});
}
}
const loadGolbalFooter = ()=>{
if (settingStore.globalFooter) {
var fotterDiv = document.createElement("div");
fotterDiv.innerHTML = settingStore.globalFooter;
footerDom.value.appendChild(fotterDiv);
// 获取所有的 <script> 标签
const scriptElements = fotterDiv.querySelectorAll<HTMLScriptElement>('script');
// 提取并加载每个 script 的 src
scriptElements.forEach(script => {
console.debug('script', script);
const src = script.getAttribute('src');
// 如果存在 src 属性
if (src) {
// 创建一个新的 script 标签
const newScript = document.createElement('script');
newScript.src = src;
newScript.async = true; // 异步加载
// 动态设置属性
if (script instanceof HTMLScriptElement) {
const attributes = script.attributes;
for (let i = 0; i < attributes.length; i++) {
const attr = attributes[i];
console.debug(`Attribute Name: ${attr.name}, Attribute Value: ${attr.value}`);
newScript.setAttribute(attr.name, attr.value);
}
}
// 将新的 script 标签添加到 <head> 中,开始加载
footerDom.value.appendChild(newScript);
}
});
}
}
onMounted(() => {
document.addEventListener('keydown', handleGlobalSearchKeybinding);
loadGlobalHeader();
loadGolbalFooter();
});
onUnmounted(() => {
Expand All @@ -38,6 +119,9 @@ onUnmounted(() => {
</script>

<template>
<div v-if="settingStore.globalHeader">
<div ref="headerDom"></div>
</div>
<el-container class="app-wrapper">
<el-aside :width="asideWidth" class="sidebar-container">
<Aside />
Expand All @@ -55,6 +139,9 @@ onUnmounted(() => {
</el-container>
</el-container>
<GlobalSearchDialog v-model:visible="globalSearchDialogVisible" />
<div v-if="settingStore.globalFooter">
<div ref="footerDom"></div>
</div>
</template>

<style lang="scss" scoped>
Expand Down
57 changes: 19 additions & 38 deletions console/src/modules/system/setting/Setting.vue
Original file line number Diff line number Diff line change
Expand Up @@ -260,41 +260,6 @@ onMounted(getSettingFromServer);
</el-button>
</el-form-item>
</el-tab-pane>
<!-- <el-tab-pane label="远端配置">
<el-alert
title="此功能尚不稳定,不建议开启。"
type="warning"
show-icon
/>
<el-form-item label="启用远端">
<el-switch
v-model="setting.REMOTE_ENABLE"
inline-prompt
size="large"
active-text="启用"
inactive-text="禁用"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="updateSetting">保存</el-button>
</el-form-item>
</el-tab-pane>
<el-tab-pane label="用户设置">
<el-form-item label="开放注册">
<el-switch
v-model="setting.ALLOW_REGISTER"
inline-prompt
size="large"
active-text="开启"
inactive-text="关闭"
disabled
@click="onDisableClick"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="updateSetting">保存</el-button>
</el-form-item>
</el-tab-pane>
<el-tab-pane label="代码注入">
<el-form-item label="全局Header">
<el-input
Expand All @@ -305,7 +270,6 @@ onMounted(getSettingFromServer);
rows="10"
show-word-limit
type="textarea"
disabled
/>
</el-form-item>
<el-form-item label="全局Footer">
Expand All @@ -317,14 +281,31 @@ onMounted(getSettingFromServer);
rows="10"
show-word-limit
type="textarea"
disabled
/>
</el-form-item>

<el-form-item>
<el-button type="primary" @click="updateSetting">保存</el-button>
</el-form-item>
</el-tab-pane> -->
</el-tab-pane>
<!--
<el-tab-pane label="用户设置">
<el-form-item label="开放注册">
<el-switch
v-model="setting.ALLOW_REGISTER"
inline-prompt
size="large"
active-text="开启"
inactive-text="关闭"
disabled
@click="onDisableClick"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="updateSetting">保存</el-button>
</el-form-item>
</el-tab-pane>
-->
</el-tabs>
</el-form>
</template>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package run.ikaros.server.core.setting;

import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import run.ikaros.api.core.setting.ConfigMap;
import run.ikaros.api.core.setting.vo.GlobalSetting;
import run.ikaros.api.custom.ReactiveCustomClient;

@Slf4j
@Service
public class DefaultSettingService implements SettingService {

private final ReactiveCustomClient reactiveCustomClient;
private static final String configMapName = "setting.server.ikaros.run";

public DefaultSettingService(ReactiveCustomClient reactiveCustomClient) {
this.reactiveCustomClient = reactiveCustomClient;
}

@Override
public Mono<GlobalSetting> getGlobalSetting() {
return reactiveCustomClient.findOne(ConfigMap.class, configMapName)
.map(configMap -> {
Map<String, String> data = configMap.getData();
GlobalSetting globalSetting = new GlobalSetting();
globalSetting.setHeader(data.get("GLOBAL_HEADER"));
globalSetting.setFooter(data.get("GLOBAL_FOOTER"));
return globalSetting;
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package run.ikaros.server.core.setting;

import reactor.core.publisher.Mono;
import run.ikaros.api.core.setting.vo.GlobalSetting;

public interface SettingService {
Mono<GlobalSetting> getGlobalSetting();
}

0 comments on commit a8afdba

Please sign in to comment.