theme-preview.tpl 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. <style lang="scss">
  2. .page-container.page-theme-preview {
  3. padding-top: 30px;
  4. .display {
  5. width: 75%;
  6. display: inline-block;
  7. vertical-align: top;
  8. h3 {
  9. font-size: 28px;
  10. margin: 30px 0 0 0;
  11. }
  12. }
  13. .side {
  14. display: inline-block;
  15. width: 25%;
  16. .editor {
  17. overflow: hidden;
  18. background: #f5f7fa;
  19. border: 1px solid #ebeef5;
  20. border-radius: 5px;
  21. margin-bottom: 20px;
  22. &.fixed {
  23. position: fixed;
  24. width: 285px;
  25. box-sizing: border-box;
  26. }
  27. }
  28. }
  29. }
  30. </style>
  31. <template>
  32. <div class="page-container page-theme-preview" ref="themePreview">
  33. <section class="display">
  34. <el-button type="text" icon="el-icon-back" @click="navBack">
  35. <%= 1 >
  36. </el-button>
  37. <h3>{{previewConfig.name}}</h3>
  38. <basic-tokens-preview>
  39. </basic-tokens-preview>
  40. <components-preview>
  41. </components-preview>
  42. </section>
  43. <aside class="side">
  44. <section class="editor" :style="{top: `${editorTop}px`, height: `${editorHeight}px`}" :class="{'fixed': isFixed}">
  45. <theme-configurator
  46. :isOfficial="isOfficial"
  47. :themeConfig="themeConfig"
  48. :onUserConfigUpdate="onUserConfigUpdate"
  49. >
  50. </theme-configurator>
  51. </section>
  52. </aside>
  53. </div>
  54. </template>
  55. <script>
  56. import bus from '../../bus.js';
  57. import ThemeConfigurator from '../../components/theme-configurator';
  58. import ComponentsPreview from '../../components/theme/components-preview';
  59. import BasicTokensPreview from '../../components/theme/basic-tokens-preview';
  60. import {
  61. loadPreviewFromLocal,
  62. loadUserThemeFromLocal,
  63. saveUserThemeToLocal
  64. } from '../../components/theme/localstorage';
  65. import {
  66. getThemeConfigObject
  67. } from '../../components/theme/utils';
  68. import {
  69. ACTION_APPLY_THEME
  70. } from '../../components/theme/constant.js';
  71. import throttle from 'throttle-debounce/throttle';
  72. import { getActionDisplayName } from '../../components/theme-configurator/utils/utils';
  73. const maxUserTheme = 8;
  74. export default {
  75. components: {
  76. ThemeConfigurator,
  77. BasicTokensPreview,
  78. ComponentsPreview
  79. },
  80. data() {
  81. return {
  82. previewConfig: {},
  83. themeConfig: {},
  84. userTheme: [],
  85. editorTop: 0,
  86. editorHeight: 1000,
  87. isFixed: false
  88. };
  89. },
  90. computed: {
  91. isOfficial() {
  92. return this.previewConfig.type === 'official';
  93. }
  94. },
  95. created() {
  96. this.throttledHandleScroll = throttle(10, true, index => {
  97. this.handleScroll(index);
  98. });
  99. },
  100. methods: {
  101. navBack() {
  102. this.$router.go(-1);
  103. this.$nextTick(() => {
  104. window.scrollTo(0, 0);
  105. });
  106. },
  107. getNewUserThemeName(originName) {
  108. let n = 1;
  109. let name;
  110. while (true) {
  111. name = `${originName}-${n}`;
  112. if (this.userTheme.filter(theme => (theme.name === name)).length === 0) {
  113. break;
  114. }
  115. n += 1;
  116. }
  117. return name;
  118. },
  119. onUserConfigUpdate(userConfig) {
  120. const themeConfig = JSON.stringify(userConfig);
  121. const { type, name } = this.previewConfig;
  122. if (this.isOfficial) {
  123. if (this.userTheme.length >= maxUserTheme) {
  124. this.$message.error(getActionDisplayName('max-user-theme'));
  125. return;
  126. }
  127. const autoUserName = this.getNewUserThemeName(name);
  128. this.previewConfig.name = autoUserName;
  129. this.previewConfig.type = 'user';
  130. this.userTheme.push({
  131. update: Date.now(),
  132. name: autoUserName,
  133. theme: themeConfig
  134. });
  135. saveUserThemeToLocal(this.userTheme);
  136. return;
  137. }
  138. if (type === 'user') {
  139. this.userTheme.forEach((config) => {
  140. if (config.name === name) {
  141. config.update = Date.now();
  142. config.theme = themeConfig;
  143. }
  144. });
  145. saveUserThemeToLocal(this.userTheme);
  146. }
  147. },
  148. handleScroll() {
  149. const rect = this.$refs.themePreview.getBoundingClientRect();
  150. let offsetTop = rect.top;
  151. let offsetBottom = rect.bottom;
  152. const calHeight = this.editorHeight + 30 + 20;
  153. if (offsetTop < 0) {
  154. this.isFixed = true;
  155. if (offsetBottom < calHeight) {
  156. this.editorTop = 30 - calHeight + offsetBottom;
  157. } else {
  158. this.editorTop = 30;
  159. }
  160. } else {
  161. this.isFixed = false;
  162. this.editorTop = 0;
  163. }
  164. }
  165. },
  166. beforeDestroy() {
  167. window.removeEventListener('scroll', this.throttledHandleScroll);
  168. },
  169. mounted() {
  170. this.editorHeight = window.innerHeight - 40 - 5;
  171. window.addEventListener('scroll', this.throttledHandleScroll);
  172. this.userTheme = loadUserThemeFromLocal();
  173. const previewConfig = loadPreviewFromLocal();
  174. const pageRefer = this.$route.params.refer;
  175. if (!previewConfig || !pageRefer) {
  176. this.$alert(getActionDisplayName('no-preview-config'), getActionDisplayName('notice'), {
  177. confirmButtonText: getActionDisplayName('confirm'),
  178. callback: action => {
  179. const newPath = this.$route.path.replace('/preview', '');
  180. this.$router.replace(newPath);
  181. }
  182. });
  183. return;
  184. }
  185. this.previewConfig = previewConfig;
  186. const themeConfig = getThemeConfigObject(previewConfig.theme);
  187. if (themeConfig) {
  188. this.themeConfig = themeConfig;
  189. bus.$emit(ACTION_APPLY_THEME, themeConfig);
  190. }
  191. }
  192. };
  193. </script>