UnisKB/ui/src/views/theme/index.vue

269 lines
9.3 KiB
Vue
Raw Normal View History

2024-07-09 09:50:37 +00:00
<template>
2024-07-16 09:32:27 +00:00
<div class="theme-setting" v-loading="loading">
2024-07-12 09:13:11 +00:00
<h4 class="p-16-24">外观设置</h4>
2024-07-11 10:13:52 +00:00
<el-scrollbar>
2024-07-12 09:13:11 +00:00
<div class="p-24 pt-0">
<div class="app-card p-24">
<h5 class="mb-16">平台显示主题</h5>
<el-radio-group
v-model="themeForm.theme"
class="app-radio-button-group"
2024-07-16 09:32:27 +00:00
@change="changeThemeHandle"
2024-07-12 09:13:11 +00:00
>
<template v-for="(item, index) in themeList" :key="index">
<el-radio-button :label="item.label" :value="item.value" />
</template>
2024-07-11 10:13:52 +00:00
</el-radio-group>
</div>
2024-07-12 09:13:11 +00:00
<div class="app-card p-24 mt-16">
<h5 class="mb-16">平台登陆设置</h5>
<el-card shadow="never" class="layout-bg">
<div class="flex-between">
<h5 class="mb-16">页面预览</h5>
2024-07-16 09:32:27 +00:00
<el-button type="primary" link @click="resetForm"> </el-button>
2024-07-11 10:13:52 +00:00
</div>
2024-07-17 07:24:53 +00:00
<el-scrollbar>
<div class="theme-preview">
<el-row :gutter="8">
<el-col :span="16">
<LoginPreview :data="themeForm" />
</el-col>
<el-col :span="8">
<div class="theme-form">
<el-card shadow="never" class="mb-8">
<div class="flex-between mb-8">
<span class="lighter">网站 Logo</span>
<el-upload
ref="uploadRef"
action="#"
:auto-upload="false"
:show-file-list="false"
accept="image/*"
:on-change="
(file: any, fileList: any) => onChange(file, fileList, 'icon')
"
>
<el-button size="small"> 替换图片 </el-button>
</el-upload>
</div>
<el-text type="info" size="small"
>顶部网站显示的 Logo建议尺寸 48 x 48支持 JPGPNGSVG大小不超过
200KB</el-text
2024-07-16 09:32:27 +00:00
>
2024-07-17 07:24:53 +00:00
</el-card>
<el-card shadow="never" class="mb-8">
<div class="flex-between mb-8">
<span class="lighter">登录 Logo</span>
<el-upload
ref="uploadRef"
action="#"
:auto-upload="false"
:show-file-list="false"
accept="image/*"
:on-change="
(file: any, fileList: any) => onChange(file, fileList, 'loginLogo')
"
>
<el-button size="small"> 替换图片 </el-button>
</el-upload>
</div>
<el-text type="info" size="small"
>登录页面右侧 Logo建议尺寸 204*52支持 JPGPNGSVG大小不超过
200KB</el-text
2024-07-16 09:32:27 +00:00
>
2024-07-17 07:24:53 +00:00
</el-card>
<el-card shadow="never" class="mb-8">
<div class="flex-between mb-8">
<span class="lighter">登录背景图</span>
<el-upload
ref="uploadRef"
action="#"
:auto-upload="false"
:show-file-list="false"
accept="image/*"
:on-change="
(file: any, fileList: any) => onChange(file, fileList, 'loginImage')
"
>
<el-button size="small"> 替换图片 </el-button>
</el-upload>
</div>
<el-text type="info" size="small">
左侧背景图矢量图建议尺寸 576*900位图建议尺寸1152*1800支持
JPGPNGSVG大小不超过 5M
</el-text>
</el-card>
2024-07-11 10:13:52 +00:00
2024-07-17 07:24:53 +00:00
<el-form
ref="themeFormRef"
:model="themeForm"
label-position="top"
require-asterisk-position="right"
:rules="rules"
@submit.prevent
>
<el-form-item label="网站名称" prop="title">
<el-input v-model="themeForm.title" placeholder="请输入网站名称">
</el-input>
<el-text type="info"> 显示在网页 Tab 的平台名称 </el-text>
</el-form-item>
<el-form-item label="欢迎语" prop="slogan">
2024-07-24 03:00:19 +00:00
<el-input
v-model="themeForm.slogan"
placeholder="请输入欢迎语"
maxlength="64"
show-word-limit
>
2024-07-17 07:24:53 +00:00
</el-input>
<el-text type="info"> 产品 Logo 下的 欢迎语 </el-text>
</el-form-item>
</el-form>
</div></el-col
>
</el-row>
</div>
</el-scrollbar>
2024-07-12 09:13:11 +00:00
<div class="mt-16">
<el-text type="info">默认为 MaxKB 登录界面支持自定义设置</el-text>
2024-07-11 10:13:52 +00:00
</div>
2024-07-12 09:13:11 +00:00
</el-card>
2024-07-11 10:13:52 +00:00
</div>
</div>
</el-scrollbar>
2024-07-12 09:13:11 +00:00
<div class="theme-setting__operate w-full p-16-24">
2024-07-12 11:04:08 +00:00
<el-button @click="resetTheme"></el-button>
2024-07-16 09:32:27 +00:00
<el-button type="primary" @click="updataTheme(themeFormRef)"> </el-button>
2024-07-12 09:13:11 +00:00
</div>
2024-07-11 10:13:52 +00:00
</div>
2024-07-09 09:50:37 +00:00
</template>
2024-07-11 10:13:52 +00:00
<script lang="ts" setup>
2024-07-16 10:50:44 +00:00
import { ref, reactive, onMounted, computed, watch, nextTick } from 'vue'
2024-07-22 10:52:56 +00:00
import { useRouter, onBeforeRouteLeave } from 'vue-router'
2024-07-16 09:32:27 +00:00
import type { FormInstance, FormRules, UploadFiles } from 'element-plus'
import { cloneDeep } from 'lodash'
2024-07-12 09:13:11 +00:00
import LoginPreview from './LoginPreview.vue'
2024-07-16 10:26:26 +00:00
import { themeList, defaultSetting } from '@/utils/theme'
2024-07-16 09:32:27 +00:00
import ThemeApi from '@/api/theme'
import { MsgSuccess, MsgError } from '@/utils/message'
2024-07-15 06:09:01 +00:00
import useStore from '@/stores'
2024-07-16 09:32:27 +00:00
const { user } = useStore()
2024-07-22 10:52:56 +00:00
const router = useRouter()
2024-07-16 09:32:27 +00:00
onBeforeRouteLeave((to, from) => {
user.setTheme(cloneTheme.value)
})
const themeInfo = computed(() => user.themeInfo)
2024-07-12 09:13:11 +00:00
const themeFormRef = ref<FormInstance>()
2024-07-16 09:32:27 +00:00
const loading = ref(false)
const cloneTheme = ref(null)
const themeForm = ref<any>({
2024-07-24 03:19:30 +00:00
theme: '',
2024-07-12 09:13:11 +00:00
icon: '',
loginLogo: '',
loginImage: '',
title: 'MaxKB',
slogan: '欢迎使用 MaxKB 智能知识库'
2024-07-11 10:13:52 +00:00
})
2024-07-12 09:13:11 +00:00
const rules = reactive<FormRules>({
title: [{ required: true, message: '请输入网站标题', trigger: 'blur' }],
slogan: [{ required: true, message: '请输入欢迎语', trigger: 'blur' }]
2024-07-11 10:13:52 +00:00
})
2024-07-12 09:13:11 +00:00
2024-07-16 09:32:27 +00:00
const onChange = (file: any, fileList: UploadFiles, attr: string) => {
if (attr === 'loginImage') {
const isLimit = file?.size / 1024 / 1024 < 5
if (!isLimit) {
// @ts-ignore
MsgError(`文件大小超过 5M`)
return false
} else {
themeForm.value[attr] = file.raw
2024-07-16 09:32:27 +00:00
}
} else {
const isLimit = file?.size / 1024 < 200
if (!isLimit) {
// @ts-ignore
MsgError(`文件大小超过 200KB`)
return false
} else {
themeForm.value[attr] = file.raw
2024-07-16 09:32:27 +00:00
}
}
}
2024-07-15 10:08:02 +00:00
2024-07-16 09:32:27 +00:00
function changeThemeHandle(val: string) {
themeForm.value.theme = val
user.setTheme(themeForm.value)
}
2024-07-12 11:04:08 +00:00
function resetTheme() {
2024-07-16 09:32:27 +00:00
user.setTheme(cloneTheme.value)
themeForm.value = cloneDeep(themeInfo.value)
2024-07-12 11:04:08 +00:00
}
2024-07-16 09:32:27 +00:00
function resetForm() {
themeForm.value = {
theme: themeForm.value.theme,
2024-07-16 10:26:26 +00:00
...defaultSetting
2024-07-16 09:32:27 +00:00
}
user.setTheme(themeForm.value)
}
const updataTheme = async (formEl: FormInstance | undefined, test?: string) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
let fd = new FormData()
Object.keys(themeForm.value).map((item) => {
fd.append(item, themeForm.value[item])
})
ThemeApi.postThemeInfo(fd, loading).then((res) => {
user.theme()
cloneTheme.value = cloneDeep(themeForm.value)
MsgSuccess('外观设置成功')
})
2024-07-12 11:04:08 +00:00
}
2024-07-16 09:32:27 +00:00
})
}
onMounted(() => {
2024-07-22 10:52:56 +00:00
if (user.isExpire()) {
router.push({ path: `/application` })
}
2024-07-16 09:32:27 +00:00
if (themeInfo.value) {
themeForm.value = themeInfo.value
cloneTheme.value = cloneDeep(themeInfo.value)
2024-07-12 11:04:08 +00:00
}
2024-07-16 09:32:27 +00:00
})
2024-07-11 10:13:52 +00:00
</script>
2024-07-12 09:13:11 +00:00
<style lang="scss" scoped>
.theme-setting {
height: 100%;
display: flex;
flex-direction: column;
2024-07-11 10:13:52 +00:00
box-sizing: border-box;
2024-07-12 09:13:11 +00:00
position: relative;
padding-bottom: 64px;
&__operate {
position: absolute;
bottom: 0;
right: 0;
left: 0;
background: #ffffff;
text-align: right;
box-sizing: border-box;
box-shadow: 0px -2px 4px 0px rgba(31, 35, 41, 0.08);
}
.theme-preview {
min-width: 1000px;
2024-07-11 10:13:52 +00:00
}
}
</style>