Merge pull request #8167 from dataease/pr@dev-v2@feat_xpack_appearance

feat(X-Pack): 外观配置
This commit is contained in:
fit2cloud-chenyw 2024-02-26 18:36:22 +08:00 committed by GitHub
commit 72484e69fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 84 additions and 31 deletions

View File

@ -11,3 +11,5 @@ export const platformLoginApi = origin => request.post({ url: '/login/platformLo
export const logoutApi = () => request.get({ url: '/logout' })
export const refreshApi = () => request.get({ url: '/login/refresh' })
export const uiLoadApi = () => request.get({ url: '/appearance/query' })

View File

@ -75,6 +75,9 @@ const toolboxMenu = computed(() => route.path.includes('toolbox'))
.with-sider {
padding: 10px 24px 24px 24px;
}
.with-sider:has(.appearance-foot) {
padding: 10px 24px 0px 24px !important;
}
}
}
</style>

View File

@ -2210,5 +2210,9 @@ export default {
reset: '重置',
preview: '预览',
save: '保存'
},
appearance: {
give_up: '放弃更新',
save_apply: '保存并应用'
}
}

View File

@ -3,7 +3,7 @@ import { ref, reactive, onMounted, computed, nextTick } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import { FormRules, FormInstance } from 'element-plus-secondary'
import { Icon } from '@/components/icon-custom'
import { loginApi, queryDekey } from '@/api/login'
import { loginApi, queryDekey, uiLoadApi } from '@/api/login'
import { useCache } from '@/hooks/web/useCache'
import { useAppStoreWithOut } from '@/store/modules/app'
import { CustomPassword } from '@/components/custom-password'
@ -16,18 +16,20 @@ import { logoutHandler } from '@/utils/logout'
import DeImage from '@/assets/login-desc-de.png'
import elementResizeDetectorMaker from 'element-resize-detector'
import { isLarkPlatform } from '@/utils/utils'
const basePath = import.meta.env.VITE_API_BASEPATH
const { wsCache } = useCache()
const appStore = useAppStoreWithOut()
const userStore = useUserStoreWithOut()
const { t } = useI18n()
const contentShow = ref(true)
const loading = ref(false)
const axiosFinished = ref(true)
const axiosFinished = ref(false)
const showFoot = ref(false)
const loginLogoUrl = ref(null)
const msg = ref(null)
const loginImageUrl = ref(null)
const slogan = ref(null)
const footContent = ref(null)
const loginErrorMsg = ref('')
const xpackLoginHandler = ref()
@ -170,7 +172,26 @@ const showLoginErrorMsg = () => {
}
ElMessage.error(loginErrorMsg.value)
}
const loadArrearance = () => {
const imgUrlPrefix = basePath + '/appearance/image/'
uiLoadApi().then(res => {
axiosFinished.value = true
const items = res.data
items.forEach(item => {
const pkey = item.pkey
const pval = item.pval
if (pkey === 'bg') {
loginImageUrl.value = imgUrlPrefix + pval
} else if (pkey === 'login') {
loginLogoUrl.value = imgUrlPrefix + pval
} else if (pkey === 'slogan') {
slogan.value = pval
}
})
})
}
onMounted(() => {
loadArrearance()
checkPlatform()
if (localStorage.getItem('DE-GATEWAY-FLAG')) {
const msg = localStorage.getItem('DE-GATEWAY-FLAG')
@ -206,18 +227,10 @@ onMounted(() => {
<div class="login-container" ref="loginContainer">
<div class="login-image-content" v-loading="!axiosFinished" v-if="showLoginImage">
<el-image
v-if="!loginImageUrl && axiosFinished"
v-if="axiosFinished"
class="login-image"
fit="cover"
:src="DeImage"
/>
<div
v-if="loginImageUrl && axiosFinished"
class="login-image-de"
:style="{
background: 'url(' + loginImageUrl + ') no-repeat',
backgroundSize: 'contain'
}"
:src="loginImageUrl || DeImage"
/>
</div>
<div class="login-form-content" v-loading="loading">
@ -231,24 +244,8 @@ onMounted(() => {
></Icon>
<img v-if="loginLogoUrl && axiosFinished" :src="loginLogoUrl" alt="" />
</div>
<div
v-if="
state.uiInfo &&
state.uiInfo['ui.loginTitle'] &&
state.uiInfo['ui.loginTitle'].paramValue
"
class="login-welcome"
>
{{ state.uiInfo['ui.loginTitle'].paramValue }}
</div>
<div v-else class="login-welcome">
{{
t('login.welcome') +
((state.uiInfo &&
state.uiInfo['ui.title'] &&
state.uiInfo['ui.title'].paramValue) ||
' DataEase 数据可视化分析平台')
}}
<div class="login-welcome">
{{ slogan || '欢迎使用 DataEase 数据可视化分析平台' }}
</div>
<div class="login-form">
<el-tabs v-model="activeName" @tab-click="handleClick" class="default-login-tabs">

@ -1 +1 @@
Subproject commit 0d32a09e80a1a62aa4be141ce94309c0e8bb3d73
Subproject commit 7614b60f695b438e28bed0e2c7a987aef7aa8f3f

View File

@ -0,0 +1,24 @@
package io.dataease.api.xpack.appearance.api;
import io.dataease.api.xpack.appearance.vo.AppearanceItemVO;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
public interface XpackAppearanceApi {
@PostMapping(value = "/save", consumes = {"multipart/form-data"})
void save(@RequestPart("request") List<AppearanceItemVO> items, @RequestPart(value = "files", required = false) List<MultipartFile> files);
@GetMapping("/query")
List<AppearanceItemVO> query();
@GetMapping(value = "/image/{imageId}", produces = {MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE})
ResponseEntity<byte[]> image(@PathVariable("imageId") String imageId);
}

View File

@ -0,0 +1,20 @@
package io.dataease.api.xpack.appearance.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
@Schema(description = "外观设置参数项")
@Data
public class AppearanceItemVO implements Serializable {
@Schema(description = "", requiredMode = Schema.RequiredMode.REQUIRED)
private String pkey;
@Schema(description = "", requiredMode = Schema.RequiredMode.REQUIRED)
private String pval;
@Schema(description = "类型", requiredMode = Schema.RequiredMode.REQUIRED)
private String type;
@Schema(description = "顺序", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer sort;
}

View File

@ -17,6 +17,7 @@ public class StaticResourceConstants {
public static String MAP_DIR = ensureSuffix(USER_HOME, FILE_SEPARATOR) + "map";
public static String CUSTOM_MAP_DIR = ensureSuffix(USER_HOME, FILE_SEPARATOR) + "geo";
public static String APPEARANCE_DIR = ensureSuffix(USER_HOME, FILE_SEPARATOR) + "appearance";
public static String MAP_URL = "/map";
public static String GEO_URL = "/geo";

View File

@ -39,6 +39,7 @@ public class WhitelistUtils {
"/wecom/token",
"/sysParameter/requestTimeOut",
"/setting/authentication/status",
"/appearance/query",
"/");
public static boolean match(String requestURI) {
@ -53,6 +54,7 @@ public class WhitelistUtils {
|| StringUtils.startsWithAny(requestURI, "data:image")
|| StringUtils.startsWithAny(requestURI, "/login/platformLogin/")
|| StringUtils.startsWithAny(requestURI, "/static-resource/")
|| StringUtils.startsWithAny(requestURI, "/appearance/image/")
|| StringUtils.startsWithAny(requestURI, "/share/proxyInfo")
|| StringUtils.startsWithAny(requestURI, "/xpackComponent/content/")
|| StringUtils.startsWithAny(requestURI, "/geo/")