element-ui/examples/pages/template/theme-preview.tpl
2021-06-07 11:56:04 +08:00

197 lines
5.3 KiB
Smarty

<style lang="scss">
.page-container.page-theme-preview {
padding-top: 30px;
.display {
width: 75%;
display: inline-block;
vertical-align: top;
h3 {
font-size: 28px;
margin: 30px 0 0 0;
}
}
.side {
display: inline-block;
width: 25%;
.editor {
overflow: hidden;
background: #f5f7fa;
border: 1px solid #ebeef5;
border-radius: 5px;
margin-bottom: 20px;
&.fixed {
position: fixed;
width: 285px;
box-sizing: border-box;
}
}
}
}
</style>
<template>
<div class="page-container page-theme-preview" ref="themePreview">
<section class="display">
<el-button type="text" icon="el-icon-back" @click="navBack">
<%= 1 >
</el-button>
<h3>{{previewConfig.name}}</h3>
<basic-tokens-preview>
</basic-tokens-preview>
<components-preview>
</components-preview>
</section>
<aside class="side">
<section class="editor" :style="{top: `${editorTop}px`, height: `${editorHeight}px`}" :class="{'fixed': isFixed}">
<theme-configurator
:isOfficial="isOfficial"
:themeConfig="themeConfig"
:previewConfig="previewConfig"
:onUserConfigUpdate="onUserConfigUpdate"
>
</theme-configurator>
</section>
</aside>
</div>
</template>
<script>
import bus from '../../bus.js';
import ThemeConfigurator from '../../components/theme-configurator';
import ComponentsPreview from '../../components/theme/components-preview';
import BasicTokensPreview from '../../components/theme/basic-tokens-preview';
import {
loadPreviewFromLocal,
loadUserThemeFromLocal,
saveUserThemeToLocal
} from '../../components/theme/localstorage';
import {
getThemeConfigObject
} from '../../components/theme/utils';
import {
ACTION_APPLY_THEME
} from '../../components/theme/constant.js';
import throttle from 'throttle-debounce/throttle';
import { getActionDisplayName } from '../../components/theme-configurator/utils/utils';
const maxUserTheme = 8;
export default {
components: {
ThemeConfigurator,
BasicTokensPreview,
ComponentsPreview
},
data() {
return {
previewConfig: {},
themeConfig: {},
userTheme: [],
editorTop: 0,
editorHeight: 1000,
isFixed: false
};
},
computed: {
isOfficial() {
return this.previewConfig.type === 'official';
}
},
created() {
this.throttledHandleScroll = throttle(10, true, index => {
this.handleScroll(index);
});
},
methods: {
navBack() {
this.$router.go(-1);
this.$nextTick(() => {
window.scrollTo(0, 0);
});
},
getNewUserThemeName(originName) {
let n = 1;
let name;
while (true) {
name = `${originName}-${n}`;
if (this.userTheme.filter(theme => (theme.name === name)).length === 0) {
break;
}
n += 1;
}
return name;
},
onUserConfigUpdate(userConfig) {
const themeConfig = JSON.stringify(userConfig);
const { type, name } = this.previewConfig;
if (this.isOfficial) {
if (this.userTheme.length >= maxUserTheme) {
this.$message.error(getActionDisplayName('max-user-theme'));
return;
}
const autoUserName = this.getNewUserThemeName(name);
this.previewConfig.name = autoUserName;
this.previewConfig.type = 'user';
this.userTheme.push({
update: Date.now(),
name: autoUserName,
theme: themeConfig
});
saveUserThemeToLocal(this.userTheme);
return;
}
if (type === 'user') {
this.userTheme.forEach((config) => {
if (config.name === name) {
config.update = Date.now();
config.theme = themeConfig;
}
});
saveUserThemeToLocal(this.userTheme);
}
},
handleScroll() {
const rect = this.$refs.themePreview.getBoundingClientRect();
let offsetTop = rect.top;
let offsetBottom = rect.bottom;
const calHeight = this.editorHeight + 30 + 20;
if (offsetTop < 0) {
this.isFixed = true;
if (offsetBottom < calHeight) {
this.editorTop = 30 - calHeight + offsetBottom;
} else {
this.editorTop = 30;
}
} else {
this.isFixed = false;
this.editorTop = 0;
}
}
},
beforeDestroy() {
window.removeEventListener('scroll', this.throttledHandleScroll);
},
mounted() {
this.editorHeight = window.innerHeight - 40 - 5;
window.addEventListener('scroll', this.throttledHandleScroll);
this.userTheme = loadUserThemeFromLocal();
const previewConfig = loadPreviewFromLocal();
const pageRefer = this.$route.params.refer;
if (!previewConfig || !pageRefer) {
this.$alert(getActionDisplayName('no-preview-config'), getActionDisplayName('notice'), {
confirmButtonText: getActionDisplayName('confirm'),
callback: action => {
const newPath = this.$route.path.replace('/preview', '');
this.$router.replace(newPath);
}
});
return;
}
this.previewConfig = previewConfig;
const themeConfig = getThemeConfigObject(previewConfig.theme);
if (themeConfig) {
this.themeConfig = themeConfig;
bus.$emit(ACTION_APPLY_THEME, themeConfig);
}
}
};
</script>